/classes/Cart.php
PHP | 3733 lines | 2758 code | 495 blank | 480 comment | 543 complexity | 9635aa388fa21639e831544f0b18d24c MD5 | raw file
Possible License(s): LGPL-3.0, CC-BY-SA-3.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- <?php
- /*
- * 2007-2014 PrestaShop
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 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/osl-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 <contact@prestashop.com>
- * @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 CartCore extends ObjectModel
- {
- public $id;
- public $id_shop_group;
- public $id_shop;
- /** @var integer Customer delivery address ID */
- public $id_address_delivery;
- /** @var integer Customer invoicing address ID */
- public $id_address_invoice;
- /** @var integer Customer currency ID */
- public $id_currency;
- /** @var integer Customer ID */
- public $id_customer;
- /** @var integer Guest ID */
- public $id_guest;
- /** @var integer Language ID */
- public $id_lang;
- /** @var boolean True if the customer wants a recycled package */
- public $recyclable = 0;
- /** @var boolean True if the customer wants a gift wrapping */
- public $gift = 0;
- /** @var string Gift message if specified */
- public $gift_message;
- /** @var boolean Mobile Theme */
- public $mobile_theme;
- /** @var string Object creation date */
- public $date_add;
- /** @var string secure_key */
- public $secure_key;
- /** @var integer Carrier ID */
- public $id_carrier = 0;
- /** @var string Object last modification date */
- public $date_upd;
- public $checkedTos = false;
- public $pictures;
- public $textFields;
- public $delivery_option;
- /** @var boolean 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 $_products = null;
- protected static $_totalWeight = array();
- protected $_taxCalculationMethod = PS_TAX_EXC;
- protected static $_carriers = null;
- protected static $_taxes_rate = null;
- protected static $_attributesLists = array();
- /**
- * @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' => 'isDateFormat'),
- 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'),
- ),
- );
- 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;
- 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 ($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->secure_key || $this->secure_key == '-1') && $customer->secure_key)
- {
- $this->secure_key = $customer->secure_key;
- $this->save();
- }
- }
- $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;
-
- $return = parent::add($autodate);
- Hook::exec('actionCartSave');
- return $return;
- }
- 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]);
- $this->_products = null;
- $return = parent::update();
- Hook::exec('actionCartSave');
- 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();
-
- $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);
- $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);
- }
- public function delete()
- {
- if ($this->OrderExists()) //NOT delete a cart which is associated with an order
- return false;
- $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']);
- }
- 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('
- 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;
- return parent::delete();
- }
- 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;
- $products = $cart->getProducts();
- $total_products_moy = 0;
- $ratio_tax = 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;
-
- $total_products_moy += $product['total_wt'];
- $ratio_tax += $product['total_wt'] * Tax::getProductTaxRate(
- (int)$product['id_product'],
- (int)$address_id
- );
- }
- if ($total_products_moy > 0)
- return $ratio_tax / $total_products_moy;
- return 0;
- }
- /**
- * @deprecated 1.5.0, use Cart->getCartRules()
- */
- public function getDiscounts($lite = false, $refresh = false)
- {
- Tools::displayAsDeprecated();
- return $this->getCartRules();
- }
- 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 *
- FROM `'._DB_PREFIX_.'cart_cart_rule` cd
- LEFT JOIN `'._DB_PREFIX_.'cart_rule` cr ON cd.`id_cart_rule` = cr.`id_cart_rule`
- LEFT JOIN `'._DB_PREFIX_.'cart_rule_lang` crl ON (
- cd.`id_cart_rule` = crl.`id_cart_rule`
- AND crl.id_lang = '.(int)$this->id_lang.'
- )
- WHERE `id_cart` = '.(int)$this->id.'
- '.($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);
- }
- $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;
-
- 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;
- }
- 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 Cache::retrieve($cache_id);
- }
- 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;
- 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;
- }
- // 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`,
- 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`,
- stock.`quantity` AS quantity_available, p.`width`, p.`height`, p.`depth`, stock.`out_of_stock`, p.`weight`,
- p.`date_add`, p.`date_upd`, IFNULL(stock.quantity, 0) as quantity, pl.`link_rewrite`, cl.`link_rewrite` AS category,
- 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.`wholesale_price`, product_shop.advanced_stock_management, ps.product_supplier_reference supplier_reference');
- // 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', '
- 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', '
- 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`');
- // @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 GROUP BY
- $sql->groupBy('unique_id');
- // Build ORDER BY
- $sql->orderBy('p.`id_product`, cp.`id_product_attribute`, cp.`date_add` 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);
- }
- else
- $sql->select('NULL AS customization_quantity, NULL AS id_customization');
- 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,
- pai.`id_image` as pai_id_image, il.`legend` as pai_legend,
- IFNULL(product_attribute_shop.`minimal_quantity`, product_shop.`minimal_quantity`) as minimal_quantity
- ');
- $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('product_attribute_image', 'pai', 'pai.`id_product_attribute` = pa.`id_product_attribute`');
- $sql->leftJoin('image_lang', 'il', 'il.`id_image` = pai.`id_image` AND il.`id_lang` = '.(int)$this->id_lang);
- }
- else
- $sql->select(
- 'p.`reference` AS reference, p.`ean13`,
- p.`upc` AS upc, product_shop.`minimal_quantity` AS minimal_quantity'
- );
- $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 $row)
- {
- $products_ids[] = $row['id_product'];
- $pa_ids[] = $row['id_product_attribute'];
- }
- // 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);
- $this->_products = array();
- if (empty($result))
- return array();
- $cart_shop_context = Context::getContext()->cloneContext();
- foreach ($result as &$row)
- {
- if (isset($row['ecotax_attr']) && $row['ecotax_attr'] > 0)
- $row['ecotax'] = (float)$row['ecotax_attr'];
- $row['stock_quantity'] = (int)$row['quantity'];
- // for compatibility with 1.2 themes
- $row['quantity'] = (int)$row['cart_quantity'];
- if (isset($row['id_product_attribute']) && (int)$row['id_product_attribute'] && isset($row['weight_attribute']))
- $row['weight'] = (float)$row['weight_attribute'];
- 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;
- if ($cart_shop_context->shop->id != $row['id_shop'])
- $cart_shop_context->shop = new Shop((int)$row['id_shop']);
- if ($this->_taxCalculationMethod == PS_TAX_EXC)
- {
- $row['price'] = Product::getPriceStatic(
- (int)$row['id_product'],
- false,
- isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null,
- 2,
- null,
- false,
- true,
- (int)$row['cart_quantity'],
- false,
- ((int)$this->id_customer ? (int)$this->id_customer : null),
- (int)$this->id,
- ((int)$address_id ? (int)$address_id : null),
- $specific_price_output,
- true,
- true,
- $cart_shop_context
- ); // Here taxes are computed only once the quantity has been applied to the product price
- $row['price_wt'] = Product::getPriceStatic(
- (int)$row['id_product'],
- true,
- isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null,
- 2,
- null,
- false,
- true,
- (int)$row['cart_quantity'],
- false,
- ((int)$this->id_customer ? (int)$this->id_customer : null),
- (int)$this->id,
- ((int)$address_id ? (int)$address_id : null),
- $null,
- true,
- true,
- $cart_shop_context
- );
- $tax_rate = Tax::getProductTaxRate((int)$row['id_product'], (int)$address_id);
- $row['total_wt'] = Tools::ps_round($row['price'] * (float)$row['cart_quantity'] * (1 + (float)$tax_rate / 100), 2);
- $row['total'] = $row['price'] * (int)$row['cart_quantity'];
- }
- else
- {
- $row['price'] = Product::getPriceStatic(
- (int)$row['id_product'],
- false,
- (int)$row['id_product_attribute'],
- 2,
- null,
- false,
- true,
- $row['cart_quantity'],
- false,
- ((int)$this->id_customer ? (int)$this->id_customer : null),
- (int)$this->id,
- ((int)$address_id ? (int)$address_id : null),
- $specific_price_output,
- true,
- true,
- $cart_shop_context
- );
- $row['price_wt'] = Product::getPriceStatic(
- (int)$row['id_product'],
- true,
- (int)$row['id_product_attribute'],
- 2,
- null,
- false,
- true,
- $row['cart_quantity'],
- false,
- ((int)$this->id_customer ? (int)$this->id_customer : null),
- (int)$this->id,
- ((int)$address_id ? (int)$address_id : null),
- $null,
- true,
- true,
- $cart_shop_context
- );
-
- // In case when you use QuantityDiscount, getPriceStatic() can be return more of 2 decimals
- $row['price_wt'] = Tools::ps_round($row['price_wt'], 2);
- $row['total_wt'] = $row['price_wt'] * (int)$row['cart_quantity'];
- $row['total'] = Tools::ps_round($row['price'] * (int)$row['cart_quantity'], 2);
- $row['description_short'] = Tools::nl2br($row['description_short']);
- }
- if (!isset($row['pai_id_image']) || $row['pai_id_image'] == 0)
- {
- $cache_id = 'Cart::getProducts_'.'-pai_id_image-'.(int)$row['id_product'].'-'.(int)$this->id_lang.'-'.(int)$row['id_shop'];
- if (!Cache::isStored($cache_id))
- {
- $row2 = Db::getInstance()->getRow('
- SELECT image_shop.`id_image` id_image, il.`legend`
- FROM `'._DB_PREFIX_.'image` i
- JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (i.id_image = image_shop.id_image AND image_shop.cover=1 AND image_shop.id_shop='.(int)$row['id_shop'].')
- LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$this->id_lang.')
- WHERE i.`id_product` = '.(int)$row['id_product'].' AND image_shop.`cover` = 1'
- );
- Cache::store($cache_id, $row2);
- }
- $row2 = Cache::retrieve($cache_id);
- if (!$row2)
- $row2 = array('id_image' => false, 'legend' => false);
- else
- $row = array_merge($row, $row2);
- }
- else
- {
- $row['id_image'] = $row['pai_id_image'];
- $row['legend'] = $row['pai_legend'];
- }
- $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']);
- 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]);
- $row = Product::getTaxesInformations($row, $cart_shop_context);
- $this->_products[] = $row;
- }
- return $this->_products;
- }
- public static function cacheSomeAttributesLists($ipa_list, $id_lang)
- {
- if (!Combination::isFeatureActive())
- return;
- $pa_implode = array();
- 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`
- LEFT JOIN `'._DB_PREFIX_.'attribute_group` ag ON ag.`id_attribute_group` = a.`id_attribute_group`
- LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON (
- a.`id_attribute` = al.`id_attribute`
- AND al.`id_lang` = '.(int)$id_lang.'
- )
- LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON (
- ag.`id_attribute_group` = agl.`id_attribute_group`
- AND agl.`id_lang` = '.(int)$id_lang.'
- )
- WHERE pac.`id_product_attribute` IN ('.implode(',', $pa_implode).')
- ORDER BY agl.`public_name` 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 ($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'],
- ', '
- );
- }
- }
- /**
- * Return cart products quantity
- *
- * @result integer Products quantity
- */
- public function nbProducts()
- {
- if (!$this->id)
- return 0;
- 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];
- self::$_nbProducts[$id] = (int)Db::getInstance()->getValue('
- SELECT SUM(`quantity`)
- FROM `'._DB_PREFIX_.'cart_product`
- WHERE `id_cart` = '.(int)$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);
- }
- 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 (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;
- 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);
- return true;
- }
- 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 .= '
- 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 ($id_customization)
- $sql .= ' AND c.`id_customization` = '.(int)$id_customization;
- return Db::getInstance()->getRow($sql);
- }
- /**
- * Update product quantity
- *
- * @param integer $quantity Quantity to add (or substract)
- * @param integer $id_product Product ID
- * @param integer $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;
- }
- $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 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 (isset(self::$_nbProducts[$this->id]))
- unset(self::$_nbProducts[$this->id]);
- if (isset(self::$_totalWeight[$this->id]))
- unset(self::$_totalWeight[$this->id]);
- 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'))
- 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
- 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;
- if (!Product::isAvailableWhenOutOfStock((int)$result2['out_of_stock']))
- if ($new_qty > $product_qty)
- return false;
- }
- else if ($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);
- else if ($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 : '').'
- 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
- FROM '._DB_PREFIX_.'product p
- '.Product::sqlStock('p', $id_product_attribute, true, $shop).'
- WHERE p.id_product = '.$id_product;
- $result2 = Db::getInstance()->getRow($sql);
- // 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 ((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')
- ));
- if (!$result_add)
- return false;
- }
- }
- // refresh cache of self::_products
- $this->_products = $this->getProducts(true);
- $this->update(true);
- $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;
- }
- /*
- ** 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);
- /* 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('
- UPDATE `'._DB_PREFIX_.'customization`
- SET
- `quantity` = `quantity` '.($operator == 'up' ? '+ ' : '- ').(int)$quantity.',
- `id_address_delivery` = '.(int)$id_address_delivery.'
- WHERE `id_customization` = '.(int)$id_customization);
- }
- else
- Db::getInstance()->execute('
- UPDATE `'._DB_PREFIX_.'customization`
- SET `id_address_delivery` = '.(int)$id_address_delivery.'
- WHERE `id_customization` = '.(int)$id_customization);
- }
- // refresh cache of self::_products
- $this->_products = $this->getProducts(true);
- $this->update(true);
- 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 boolean 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('
- 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`)
- VALUES ('.(int)$this->id.', '.(int)$id_product.', '.(int)$id_product_attribute.', '.(int)$quantity.')'
- );
- $id_customization = Db::getInstance()->Insert_ID();
- }
-
- $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;
- }
- /**
- * Check if order has already been placed
- *
- * @return boolean 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 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);
- }
- 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()->execute('
- DELETE FROM `'._DB_PREFIX_.'cart_cart_rule`
- WHERE `id_cart_rule` = '.(int)$id_cart_rule.'
- AND `id_cart` = '.(int)$this->id.'
- LIMIT 1');
-
- $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);
-
- return $result;
- }
- /**
- * Delete a product from the cart
- *
- * @param integer $id_product Product ID
- * @param integer $id_product_attribute Attribute ID if needed
- * @param integer $id_customization Customization id
- * @return boolean 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 (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('
- SELECT `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.'
- '.((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;
- // 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('
- 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 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 : '')
- );
-
- /* 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(true);
- // refresh cache of self::_products
- $this->_products = $this->getProducts(true);
- CartRule::autoRemoveFromCart();
- CartRule::autoAddToCart();
-
- return $return;
- }
- return false;
- }
- /**
- * Delete a customization from the cart. If customization is a Picture,
- * then the image is also deleted
- *
- * @param integer $id_customization
- * @return boolean 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 *
- 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'));
- $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`
- 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 : '').'
- AND `id_address_delivery` = '.(int)$id_address_delivery
- );
- if (!$result)
- return false;
- 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 boolean $withTaxes With or without taxes
- * @param integer $type Total type
- * @param boolean $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)
- {
- 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, (boolean)$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;
- 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 (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice')
- $address_id = (int)$this->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 ($this->_taxCalculationMethod == PS_TAX_EXC)
- {
- // Here taxes are computed only once the quantity has been applied to the product price
- $price = Product::getPriceStatic(
- (int)$product['id_product'],
- false,
- (int)$product['id_product_attribute'],
- 2,
- null,
- false,
- true,
- $product['cart_quantity'],
- false,
- (int)$this->id_customer ? (int)$this->id_customer : null,
- (int)$this->id,
- $address_id,
- $null,
- true,
- true,
- $virtual_context
- );
- $total_ecotax = $product['ecotax'] * (int)$product['cart_quantity'];
- $total_price = $price * (int)$product['cart_quantity'];
- if ($with_taxes)
- {
- $product_tax_rate = (float)Tax::getProductTaxRate((int)$product['id_product'], (int)$address_id, $virtual_context);
- $product_eco_tax_rate = Tax::getProductEcotaxRate((int)$address_id);
- $total_price = ($total_price - $total_ecotax) * (1 + $product_tax_rate / 100);
- $total_ecotax = $total_ecotax * (1 + $product_eco_tax_rate / 100);
- $total_price = Tools::ps_round($total_price + $total_ecotax, 2);
- }
- }
- else
- {
- if ($with…
Large files files are truncated, but you can click here to view the full file