966 lines
32 KiB
PHP
966 lines
32 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Product - Vollständige Produktverwaltung
|
|
*/
|
|
class Product extends ObjectModel
|
|
{
|
|
/** @var string Tax name */
|
|
public $tax_name = 'deprecated';
|
|
|
|
/** @var float Tax rate */
|
|
public $tax_rate;
|
|
|
|
/** @var int Manufacturer identifier */
|
|
public $id_manufacturer;
|
|
|
|
/** @var int Supplier identifier */
|
|
public $id_supplier;
|
|
|
|
/** @var int default Category identifier */
|
|
public $id_category_default;
|
|
|
|
/** @var int default Shop identifier */
|
|
public $id_shop_default;
|
|
|
|
/** @var string Manufacturer name */
|
|
public $manufacturer_name;
|
|
|
|
/** @var string Supplier name */
|
|
public $supplier_name;
|
|
|
|
/** @var string|array Name or array of names by id_lang */
|
|
public $name;
|
|
|
|
/** @var string|array Long description or array of long description by id_lang */
|
|
public $description;
|
|
|
|
/** @var string|array Short description or array of short description by id_lang */
|
|
public $description_short;
|
|
|
|
/** @var int Quantity available */
|
|
public $quantity = 0;
|
|
|
|
/** @var int Minimal quantity for add to cart */
|
|
public $minimal_quantity = 1;
|
|
|
|
/** @var int|null Low stock for mail alert */
|
|
public $low_stock_threshold = null;
|
|
|
|
/** @var bool Low stock mail alert activated */
|
|
public $low_stock_alert = false;
|
|
|
|
/** @var string|array Text when in stock or array of text by id_lang */
|
|
public $available_now;
|
|
|
|
/** @var string|array Text when not in stock but available to order or array of text by id_lang */
|
|
public $available_later;
|
|
|
|
/** @var float|null Price */
|
|
public $price = 0;
|
|
|
|
/** @var array|int|null Will be filled by reference by priceCalculation() */
|
|
public $specificPrice = 0;
|
|
|
|
/** @var float Additional shipping cost */
|
|
public $additional_shipping_cost = 0;
|
|
|
|
/** @var float Wholesale Price in euros */
|
|
public $wholesale_price = 0;
|
|
|
|
/** @var bool on_sale */
|
|
public $on_sale = false;
|
|
|
|
/** @var bool online_only */
|
|
public $online_only = false;
|
|
|
|
/** @var string unity */
|
|
public $unity = null;
|
|
|
|
/** @var float|null price for product's unity */
|
|
public $unit_price = 0;
|
|
|
|
/** @var float price for product's unity ratio */
|
|
public $unit_price_ratio = 0;
|
|
|
|
/** @var float|null Ecotax */
|
|
public $ecotax = 0;
|
|
|
|
/** @var string Reference */
|
|
public $reference;
|
|
|
|
/** @var string Supplier Reference */
|
|
public $supplier_reference;
|
|
|
|
/** @var string Location */
|
|
public $location = '';
|
|
|
|
/** @var string|float Width in default width unit */
|
|
public $width = 0;
|
|
|
|
/** @var string|float Height in default height unit */
|
|
public $height = 0;
|
|
|
|
/** @var string|float Depth in default depth unit */
|
|
public $depth = 0;
|
|
|
|
/** @var string|float Weight in default weight unit */
|
|
public $weight = 0;
|
|
|
|
/** @var string Ean-13 barcode */
|
|
public $ean13;
|
|
|
|
/** @var string ISBN */
|
|
public $isbn;
|
|
|
|
/** @var string Upc barcode */
|
|
public $upc;
|
|
|
|
/** @var string MPN */
|
|
public $mpn;
|
|
|
|
/** @var string|string[] Friendly URL or array of friendly URL by id_lang */
|
|
public $link_rewrite;
|
|
|
|
/** @var string|array Meta description or array of meta description by id_lang */
|
|
public $meta_description;
|
|
|
|
/** @var string|array Meta title or array of meta title by id_lang */
|
|
public $meta_title;
|
|
|
|
/** @var mixed */
|
|
public $quantity_discount = 0;
|
|
|
|
/** @var bool|int Product customization */
|
|
public $customizable;
|
|
|
|
/** @var bool|null Product is new */
|
|
public $new = null;
|
|
|
|
/** @var int Number of uploadable files (concerning customizable products) */
|
|
public $uploadable_files;
|
|
|
|
/** @var int Number of text fields */
|
|
public $text_fields;
|
|
|
|
/** @var bool Active */
|
|
public $active = true;
|
|
|
|
/** @var bool Redirect type */
|
|
public $redirect_type = '';
|
|
|
|
/** @var int Redirect target */
|
|
public $id_type_redirected = 0;
|
|
|
|
/** @var bool Available for order */
|
|
public $available_for_order = true;
|
|
|
|
/** @var string Available date */
|
|
public $available_date = '0000-00-00';
|
|
|
|
/** @var bool Show price */
|
|
public $show_price = true;
|
|
|
|
/** @var bool indexed */
|
|
public $indexed = false;
|
|
|
|
/** @var string Visibility */
|
|
public $visibility = 'both';
|
|
|
|
/** @var bool Cache is pack */
|
|
public $cache_is_pack = false;
|
|
|
|
/** @var bool Cache has attachments */
|
|
public $cache_has_attachments = false;
|
|
|
|
/** @var bool Is virtual */
|
|
public $is_virtual = false;
|
|
|
|
/** @var int Cache default attribute */
|
|
public $cache_default_attribute = 0;
|
|
|
|
/** @var string Date add */
|
|
public $date_add;
|
|
|
|
/** @var string Date upd */
|
|
public $date_upd;
|
|
|
|
/** @var array Product definition */
|
|
public static $definition = [
|
|
'table' => 'product',
|
|
'primary' => 'id_product',
|
|
'multilang' => true,
|
|
'multilang_shop' => true,
|
|
'fields' => [
|
|
'id_manufacturer' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'id_supplier' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'id_category_default' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'id_shop_default' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'id_tax_rules_group' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'on_sale' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'online_only' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'ecotax' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
|
'minimal_quantity' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
|
'low_stock_threshold' => ['type' => self::TYPE_INT],
|
|
'low_stock_alert' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true],
|
|
'wholesale_price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
|
'unity' => ['type' => self::TYPE_STRING, 'validate' => 'isString'],
|
|
'unit_price_ratio' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'],
|
|
'additional_shipping_cost' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
|
'customizable' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
|
'uploadable_files' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
|
'text_fields' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
|
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'redirect_type' => ['type' => self::TYPE_STRING, 'validate' => 'isString'],
|
|
'id_type_redirected' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'available_for_order' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'available_date' => ['type' => self::TYPE_DATE, 'validate' => 'isDateFormat'],
|
|
'show_price' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'indexed' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'visibility' => ['type' => self::TYPE_STRING, 'validate' => 'isProductVisibility'],
|
|
'cache_is_pack' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'cache_has_attachments' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'is_virtual' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
|
'cache_default_attribute' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
|
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
|
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
|
/* Lang fields */
|
|
'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128],
|
|
'description' => ['type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'],
|
|
'description_short' => ['type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'],
|
|
'available_now' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName'],
|
|
'available_later' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName'],
|
|
'link_rewrite' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128],
|
|
'meta_description' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255],
|
|
'meta_keywords' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255],
|
|
'meta_title' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128],
|
|
],
|
|
];
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, $context = null)
|
|
{
|
|
parent::__construct($id_product, $id_lang, $id_shop);
|
|
|
|
if ($id_product) {
|
|
$this->id = (int) $id_product;
|
|
if ($full) {
|
|
$this->loadFullProduct();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load full product data
|
|
*/
|
|
protected function loadFullProduct()
|
|
{
|
|
// Load basic product data
|
|
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'product` WHERE `id_product` = ' . (int) $this->id;
|
|
$result = Db::getInstance()->getRow($sql);
|
|
|
|
if ($result) {
|
|
$this->hydrate($result);
|
|
}
|
|
|
|
// Load multilingual data
|
|
if ($this->id_lang) {
|
|
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'product_lang` WHERE `id_product` = ' . (int) $this->id . ' AND `id_lang` = ' . (int) $this->id_lang;
|
|
$result = Db::getInstance()->getRow($sql);
|
|
|
|
if ($result) {
|
|
$this->hydrate($result);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get products
|
|
*/
|
|
public static function getProducts($id_lang, $start, $limit, $order_by, $order_way, $id_category = false, $only_active = false, $context = null)
|
|
{
|
|
$sql = 'SELECT p.*, pl.*, m.`name` as manufacturer_name, s.`name` as supplier_name
|
|
FROM `' . _DB_PREFIX_ . 'product` p
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product`)
|
|
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`)
|
|
WHERE pl.`id_lang` = ' . (int) $id_lang;
|
|
|
|
if ($id_category) {
|
|
$sql .= ' AND cp.`id_category` = ' . (int) $id_category;
|
|
}
|
|
|
|
if ($only_active) {
|
|
$sql .= ' AND p.`active` = 1';
|
|
}
|
|
|
|
$sql .= ' ORDER BY ' . pSQL($order_by) . ' ' . pSQL($order_way);
|
|
$sql .= ' LIMIT ' . (int) $start . ', ' . (int) $limit;
|
|
|
|
$results = Db::getInstance()->executeS($sql);
|
|
$products = [];
|
|
|
|
foreach ($results as $result) {
|
|
$product = new Product();
|
|
$product->hydrate($result);
|
|
$products[] = $product;
|
|
}
|
|
|
|
return $products;
|
|
}
|
|
|
|
/**
|
|
* Get new products
|
|
*/
|
|
public static function getNewProducts($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, $context = null)
|
|
{
|
|
$sql = 'SELECT p.*, pl.*, m.`name` as manufacturer_name, s.`name` as supplier_name
|
|
FROM `' . _DB_PREFIX_ . 'product` p
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product`)
|
|
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`)
|
|
WHERE pl.`id_lang` = ' . (int) $id_lang . '
|
|
AND p.`active` = 1
|
|
AND p.`new` = 1';
|
|
|
|
if ($order_by) {
|
|
$sql .= ' ORDER BY ' . pSQL($order_by) . ' ' . pSQL($order_way);
|
|
}
|
|
|
|
if (!$count) {
|
|
$sql .= ' LIMIT ' . (int) ($page_number * $nb_products) . ', ' . (int) $nb_products;
|
|
}
|
|
|
|
$results = Db::getInstance()->executeS($sql);
|
|
|
|
if ($count) {
|
|
return count($results);
|
|
}
|
|
|
|
$products = [];
|
|
foreach ($results as $result) {
|
|
$product = new Product();
|
|
$product->hydrate($result);
|
|
$products[] = $product;
|
|
}
|
|
|
|
return $products;
|
|
}
|
|
|
|
/**
|
|
* Get 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 = null)
|
|
{
|
|
$sql = 'SELECT p.*, pl.*, m.`name` as manufacturer_name, s.`name` as supplier_name
|
|
FROM `' . _DB_PREFIX_ . 'product` p
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product`)
|
|
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`)
|
|
WHERE pl.`id_lang` = ' . (int) $id_lang . '
|
|
AND p.`active` = 1
|
|
AND p.`on_sale` = 1';
|
|
|
|
if ($beginning && $ending) {
|
|
$sql .= ' AND p.`date_add` BETWEEN "' . pSQL($beginning) . '" AND "' . pSQL($ending) . '"';
|
|
}
|
|
|
|
if ($order_by) {
|
|
$sql .= ' ORDER BY ' . pSQL($order_by) . ' ' . pSQL($order_way);
|
|
}
|
|
|
|
if (!$count) {
|
|
$sql .= ' LIMIT ' . (int) ($page_number * $nb_products) . ', ' . (int) $nb_products;
|
|
}
|
|
|
|
$results = Db::getInstance()->executeS($sql);
|
|
|
|
if ($count) {
|
|
return count($results);
|
|
}
|
|
|
|
$products = [];
|
|
foreach ($results as $result) {
|
|
$product = new Product();
|
|
$product->hydrate($result);
|
|
$products[] = $product;
|
|
}
|
|
|
|
return $products;
|
|
}
|
|
|
|
/**
|
|
* Get price
|
|
*/
|
|
public function getPrice($tax = true, $id_product_attribute = null, $decimals = 6, $divisor = null, $only_reduc = false, $usereduc = true, $quantity = 1)
|
|
{
|
|
$price = $this->price;
|
|
|
|
if ($tax) {
|
|
$price = $price * (1 + ($this->tax_rate / 100));
|
|
}
|
|
|
|
return Tools::ps_round($price, $decimals);
|
|
}
|
|
|
|
/**
|
|
* Get price static
|
|
*/
|
|
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 = null, $use_customer_price = true, $id_customization = null)
|
|
{
|
|
$product = new Product($id_product);
|
|
return $product->getPrice($usetax, $id_product_attribute, $decimals, $divisor, $only_reduc, $usereduc, $quantity);
|
|
}
|
|
|
|
/**
|
|
* Get quantity
|
|
*/
|
|
public static function getQuantity($idProduct, $idProductAttribute = null, $cacheIsPack = null, $cart = null, $idCustomization = null)
|
|
{
|
|
$sql = 'SELECT `quantity` FROM `' . _DB_PREFIX_ . 'stock_available` WHERE `id_product` = ' . (int) $idProduct;
|
|
|
|
if ($idProductAttribute) {
|
|
$sql .= ' AND `id_product_attribute` = ' . (int) $idProductAttribute;
|
|
}
|
|
|
|
$result = Db::getInstance()->getRow($sql);
|
|
return $result ? (int) $result['quantity'] : 0;
|
|
}
|
|
|
|
/**
|
|
* Check quantity
|
|
*/
|
|
public function checkQty($qty)
|
|
{
|
|
$quantity = self::getQuantity($this->id);
|
|
return $qty <= $quantity;
|
|
}
|
|
|
|
/**
|
|
* Get images
|
|
*/
|
|
public function getImages($id_lang, $context = null)
|
|
{
|
|
$sql = 'SELECT i.*, il.*
|
|
FROM `' . _DB_PREFIX_ . 'image` i
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (i.`id_image` = il.`id_image`)
|
|
WHERE i.`id_product` = ' . (int) $this->id . '
|
|
AND il.`id_lang` = ' . (int) $id_lang . '
|
|
ORDER BY i.`position`';
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Get cover
|
|
*/
|
|
public static function getCover($id_product, $context = null)
|
|
{
|
|
$sql = 'SELECT i.*
|
|
FROM `' . _DB_PREFIX_ . 'image` i
|
|
WHERE i.`id_product` = ' . (int) $id_product . '
|
|
AND i.`cover` = 1';
|
|
|
|
return Db::getInstance()->getRow($sql);
|
|
}
|
|
|
|
/**
|
|
* Get categories
|
|
*/
|
|
public function getCategories()
|
|
{
|
|
$sql = 'SELECT c.*, cl.*
|
|
FROM `' . _DB_PREFIX_ . 'category_product` cp
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'category` c ON (cp.`id_category` = c.`id_category`)
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'category_lang` cl ON (c.`id_category` = cl.`id_category`)
|
|
WHERE cp.`id_product` = ' . (int) $this->id . '
|
|
AND cl.`id_lang` = ' . (int) $this->id_lang;
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Add to categories
|
|
*/
|
|
public function addToCategories($categories = [])
|
|
{
|
|
if (empty($categories)) {
|
|
return false;
|
|
}
|
|
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'category_product` (`id_product`, `id_category`) VALUES ';
|
|
$values = [];
|
|
|
|
foreach ($categories as $id_category) {
|
|
$values[] = '(' . (int) $this->id . ', ' . (int) $id_category . ')';
|
|
}
|
|
|
|
$sql .= implode(', ', $values);
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Update categories
|
|
*/
|
|
public function updateCategories($categories, $keeping_current_pos = false)
|
|
{
|
|
if (!$keeping_current_pos) {
|
|
$this->deleteCategories();
|
|
}
|
|
|
|
return $this->addToCategories($categories);
|
|
}
|
|
|
|
/**
|
|
* Delete categories
|
|
*/
|
|
public function deleteCategories($clean_positions = false)
|
|
{
|
|
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'category_product` WHERE `id_product` = ' . (int) $this->id;
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get features
|
|
*/
|
|
public function getFeatures()
|
|
{
|
|
$sql = 'SELECT f.*, fl.*, fp.`id_feature_value`
|
|
FROM `' . _DB_PREFIX_ . 'feature_product` fp
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'feature` f ON (fp.`id_feature` = f.`id_feature`)
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'feature_lang` fl ON (f.`id_feature` = fl.`id_feature`)
|
|
WHERE fp.`id_product` = ' . (int) $this->id . '
|
|
AND fl.`id_lang` = ' . (int) $this->id_lang;
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Add features to DB
|
|
*/
|
|
public function addFeaturesToDB($id_feature, $id_value, $cust = 0)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'feature_product` (`id_feature`, `id_product`, `id_feature_value`) VALUES (' . (int) $id_feature . ', ' . (int) $this->id . ', ' . (int) $id_value . ')';
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Delete features
|
|
*/
|
|
public function deleteFeatures()
|
|
{
|
|
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'feature_product` WHERE `id_product` = ' . (int) $this->id;
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get accessories
|
|
*/
|
|
public function getAccessories($id_lang, $active = true)
|
|
{
|
|
$sql = 'SELECT p.*, pl.*, m.`name` as manufacturer_name, s.`name` as supplier_name
|
|
FROM `' . _DB_PREFIX_ . 'accessory` a
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'product` p ON (a.`id_product_2` = p.`id_product`)
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product`)
|
|
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`)
|
|
WHERE a.`id_product_1` = ' . (int) $this->id . '
|
|
AND pl.`id_lang` = ' . (int) $id_lang;
|
|
|
|
if ($active) {
|
|
$sql .= ' AND p.`active` = 1';
|
|
}
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Add accessories
|
|
*/
|
|
public function addAccessories($accessories)
|
|
{
|
|
foreach ($accessories as $id_product_2) {
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'accessory` (`id_product_1`, `id_product_2`) VALUES (' . (int) $this->id . ', ' . (int) $id_product_2 . ')';
|
|
Db::getInstance()->execute($sql);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete accessories
|
|
*/
|
|
public function deleteAccessories()
|
|
{
|
|
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'accessory` WHERE `id_product_1` = ' . (int) $this->id;
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get tags
|
|
*/
|
|
public function getTags($id_lang)
|
|
{
|
|
$sql = 'SELECT t.*, tl.*
|
|
FROM `' . _DB_PREFIX_ . 'product_tag` pt
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'tag` t ON (pt.`id_tag` = t.`id_tag`)
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'tag_lang` tl ON (t.`id_tag` = tl.`id_tag`)
|
|
WHERE pt.`id_product` = ' . (int) $this->id . '
|
|
AND tl.`id_lang` = ' . (int) $id_lang;
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Add tags
|
|
*/
|
|
public function addTags($tags)
|
|
{
|
|
foreach ($tags as $id_tag) {
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'product_tag` (`id_product`, `id_tag`) VALUES (' . (int) $this->id . ', ' . (int) $id_tag . ')';
|
|
Db::getInstance()->execute($sql);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete tags
|
|
*/
|
|
public function deleteTags()
|
|
{
|
|
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'product_tag` WHERE `id_product` = ' . (int) $this->id;
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get attachments
|
|
*/
|
|
public function getAttachments($id_lang)
|
|
{
|
|
$sql = 'SELECT a.*, al.*
|
|
FROM `' . _DB_PREFIX_ . 'product_attachment` pa
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'attachment` a ON (pa.`id_attachment` = a.`id_attachment`)
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'attachment_lang` al ON (a.`id_attachment` = al.`id_attachment`)
|
|
WHERE pa.`id_product` = ' . (int) $this->id . '
|
|
AND al.`id_lang` = ' . (int) $id_lang;
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Add attachments
|
|
*/
|
|
public function addAttachments($attachments)
|
|
{
|
|
foreach ($attachments as $id_attachment) {
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'product_attachment` (`id_product`, `id_attachment`) VALUES (' . (int) $this->id . ', ' . (int) $id_attachment . ')';
|
|
Db::getInstance()->execute($sql);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete attachments
|
|
*/
|
|
public function deleteAttachments($update_attachment_cache = true)
|
|
{
|
|
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'product_attachment` WHERE `id_product` = ' . (int) $this->id;
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get customization fields
|
|
*/
|
|
public function getCustomizationFields($id_lang = false, $id_shop = null)
|
|
{
|
|
$sql = 'SELECT cf.*, cfl.*
|
|
FROM `' . _DB_PREFIX_ . 'customization_field` cf
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'customization_field_lang` cfl ON (cf.`id_customization_field` = cfl.`id_customization_field`)
|
|
WHERE cf.`id_product` = ' . (int) $this->id;
|
|
|
|
if ($id_lang) {
|
|
$sql .= ' AND cfl.`id_lang` = ' . (int) $id_lang;
|
|
}
|
|
|
|
$sql .= ' ORDER BY cf.`position`';
|
|
|
|
return Db::getInstance()->executeS($sql);
|
|
}
|
|
|
|
/**
|
|
* Create labels
|
|
*/
|
|
public function createLabels($uploadable_files, $text_fields)
|
|
{
|
|
$languages = Language::getLanguages();
|
|
|
|
foreach ($languages as $language) {
|
|
$this->_createLabel($language['id_lang'], $uploadable_files, $text_fields);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create label
|
|
*/
|
|
protected function _createLabel($id_lang, $uploadable_files, $text_fields)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'customization_field_lang` (`id_customization_field`, `id_lang`, `name`) VALUES ';
|
|
$values = [];
|
|
|
|
for ($i = 1; $i <= $uploadable_files; $i++) {
|
|
$values[] = '(' . (int) $this->id . ', ' . (int) $id_lang . ', "Uploadable file ' . $i . '")';
|
|
}
|
|
|
|
for ($i = 1; $i <= $text_fields; $i++) {
|
|
$values[] = '(' . (int) $this->id . ', ' . (int) $id_lang . ', "Text field ' . $i . '")';
|
|
}
|
|
|
|
$sql .= implode(', ', $values);
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Delete customization
|
|
*/
|
|
public function deleteCustomization()
|
|
{
|
|
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'customization_field` WHERE `id_product` = ' . (int) $this->id;
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get link
|
|
*/
|
|
public function getLink($context = null)
|
|
{
|
|
if (!$context) {
|
|
$context = Context::getContext();
|
|
}
|
|
|
|
return $context->link->getProductLink($this);
|
|
}
|
|
|
|
/**
|
|
* Search by name
|
|
*/
|
|
public static function searchByName($id_lang, $query, $context = null, $limit = null)
|
|
{
|
|
$sql = 'SELECT p.*, pl.*
|
|
FROM `' . _DB_PREFIX_ . 'product` p
|
|
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product`)
|
|
WHERE pl.`id_lang` = ' . (int) $id_lang . '
|
|
AND p.`active` = 1
|
|
AND (pl.`name` LIKE "%' . pSQL($query) . '%" OR pl.`description` LIKE "%' . pSQL($query) . '%")';
|
|
|
|
if ($limit) {
|
|
$sql .= ' LIMIT ' . (int) $limit;
|
|
}
|
|
|
|
$results = Db::getInstance()->executeS($sql);
|
|
$products = [];
|
|
|
|
foreach ($results as $result) {
|
|
$product = new Product();
|
|
$product->hydrate($result);
|
|
$products[] = $product;
|
|
}
|
|
|
|
return $products;
|
|
}
|
|
|
|
/**
|
|
* Duplicate object
|
|
*/
|
|
public function duplicateObject()
|
|
{
|
|
$old_id = $this->id;
|
|
$this->id = null;
|
|
$this->id_product = null;
|
|
|
|
$this->add();
|
|
|
|
$new_id = $this->id;
|
|
|
|
// Duplicate categories
|
|
$this->duplicateCategories($old_id, $new_id);
|
|
|
|
// Duplicate features
|
|
$this->duplicateFeatures($old_id, $new_id);
|
|
|
|
// Duplicate accessories
|
|
$this->duplicateAccessories($old_id, $new_id);
|
|
|
|
// Duplicate tags
|
|
$this->duplicateTags($old_id, $new_id);
|
|
|
|
// Duplicate attachments
|
|
$this->duplicateAttachments($old_id, $new_id);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Duplicate categories
|
|
*/
|
|
public static function duplicateCategories($id_product_old, $id_product_new)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'category_product` (`id_product`, `id_category`)
|
|
SELECT ' . (int) $id_product_new . ', `id_category`
|
|
FROM `' . _DB_PREFIX_ . 'category_product`
|
|
WHERE `id_product` = ' . (int) $id_product_old;
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Duplicate features
|
|
*/
|
|
public static function duplicateFeatures($id_product_old, $id_product_new)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'feature_product` (`id_feature`, `id_product`, `id_feature_value`)
|
|
SELECT `id_feature`, ' . (int) $id_product_new . ', `id_feature_value`
|
|
FROM `' . _DB_PREFIX_ . 'feature_product`
|
|
WHERE `id_product` = ' . (int) $id_product_old;
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Duplicate accessories
|
|
*/
|
|
public static function duplicateAccessories($id_product_old, $id_product_new)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'accessory` (`id_product_1`, `id_product_2`)
|
|
SELECT ' . (int) $id_product_new . ', `id_product_2`
|
|
FROM `' . _DB_PREFIX_ . 'accessory`
|
|
WHERE `id_product_1` = ' . (int) $id_product_old;
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Duplicate tags
|
|
*/
|
|
public static function duplicateTags($id_product_old, $id_product_new)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'product_tag` (`id_product`, `id_tag`)
|
|
SELECT ' . (int) $id_product_new . ', `id_tag`
|
|
FROM `' . _DB_PREFIX_ . 'product_tag`
|
|
WHERE `id_product` = ' . (int) $id_product_old;
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Duplicate attachments
|
|
*/
|
|
public static function duplicateAttachments($id_product_old, $id_product_new)
|
|
{
|
|
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'product_attachment` (`id_product`, `id_attachment`)
|
|
SELECT ' . (int) $id_product_new . ', `id_attachment`
|
|
FROM `' . _DB_PREFIX_ . 'product_attachment`
|
|
WHERE `id_product` = ' . (int) $id_product_old;
|
|
|
|
return Db::getInstance()->execute($sql);
|
|
}
|
|
|
|
/**
|
|
* Get tax rate
|
|
*/
|
|
public function getTaxesRate($address = null)
|
|
{
|
|
if (!$address) {
|
|
$address = new Address();
|
|
}
|
|
|
|
$tax_manager = TaxManagerFactory::getManager($address, Product::getIdTaxRulesGroupByIdProduct($this->id));
|
|
$tax_calculator = $tax_manager->getTaxCalculator();
|
|
|
|
return $tax_calculator->getTotalRate();
|
|
}
|
|
|
|
/**
|
|
* Get ID by reference
|
|
*/
|
|
public static function getIdByReference($reference)
|
|
{
|
|
$sql = 'SELECT `id_product` FROM `' . _DB_PREFIX_ . 'product` WHERE `reference` = "' . pSQL($reference) . '"';
|
|
$result = Db::getInstance()->getRow($sql);
|
|
|
|
return $result ? (int) $result['id_product'] : false;
|
|
}
|
|
|
|
/**
|
|
* Get ID by EAN13
|
|
*/
|
|
public static function getIdByEan13($ean13)
|
|
{
|
|
$sql = 'SELECT `id_product` FROM `' . _DB_PREFIX_ . 'product` WHERE `ean13` = "' . pSQL($ean13) . '"';
|
|
$result = Db::getInstance()->getRow($sql);
|
|
|
|
return $result ? (int) $result['id_product'] : false;
|
|
}
|
|
|
|
/**
|
|
* Get ID by UPC
|
|
*/
|
|
public static function getIdByUpc($upc)
|
|
{
|
|
$sql = 'SELECT `id_product` FROM `' . _DB_PREFIX_ . 'product` WHERE `upc` = "' . pSQL($upc) . '"';
|
|
$result = Db::getInstance()->getRow($sql);
|
|
|
|
return $result ? (int) $result['id_product'] : false;
|
|
}
|
|
|
|
/**
|
|
* Check if product is new
|
|
*/
|
|
public function isNew()
|
|
{
|
|
$sql = 'SELECT COUNT(*) as total FROM `' . _DB_PREFIX_ . 'product` WHERE `date_add` > DATE_SUB(NOW(), INTERVAL ' . (int) Configuration::get('PS_NB_DAYS_NEW_PRODUCT') . ' DAY) AND `id_product` = ' . (int) $this->id;
|
|
$result = Db::getInstance()->getRow($sql);
|
|
|
|
return (int) $result['total'] > 0;
|
|
}
|
|
|
|
/**
|
|
* Check if product is on sale
|
|
*/
|
|
public function isOnSale()
|
|
{
|
|
return (bool) $this->on_sale;
|
|
}
|
|
|
|
/**
|
|
* Check if product is available for order
|
|
*/
|
|
public function isAvailableForOrder()
|
|
{
|
|
return (bool) $this->available_for_order;
|
|
}
|
|
|
|
/**
|
|
* Check if product is virtual
|
|
*/
|
|
public function isVirtual()
|
|
{
|
|
return (bool) $this->is_virtual;
|
|
}
|
|
|
|
/**
|
|
* Get product type
|
|
*/
|
|
public function getProductType()
|
|
{
|
|
if ($this->is_virtual) {
|
|
return 'virtual';
|
|
}
|
|
|
|
if ($this->cache_is_pack) {
|
|
return 'pack';
|
|
}
|
|
|
|
return 'standard';
|
|
}
|
|
}
|