Files
shopPRO/autoload/shop/class.Product.php
Jacek Pyziak 89d9e61bec ver. 0.292: ShopProduct + ShopPaymentMethod + ShopPromotion + ShopStatuses + ShopTransport frontend migration to Domain
Full migration of front\factory\ — entire directory removed (all 20 classes migrated).
ProductRepository +20 frontend methods, PromotionRepository +5 applyType methods,
TransportRepository +4 cached methods, PaymentMethodRepository +cached frontend methods.
Fix: broken transports_list() in ajax.php replaced with forPaymentMethod().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:55:16 +01:00

953 lines
36 KiB
PHP

<?php
namespace shop;
use shop\Shop;
use S;
class Product implements \ArrayAccess
{
public function __construct( int $product_id, $lang_id = null, $permutation_hash = null )
{
global $mdb;
if ( !$lang_id )
$lang_id = ( new \Domain\Languages\LanguagesRepository( $mdb ) )->defaultLanguage();
$result = $mdb -> get( 'pp_shop_products', '*', [ 'id' => $product_id ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $result ) ) foreach ( $result as $key => $val )
$this -> $key = $val;
// kombinacja produktu
if ( $this -> parent_id )
{
// pobranie wartości z produktu głównego
if ( !$this -> price_netto or !$this -> price_brutto )
{
$result = $mdb -> get( 'pp_shop_products', [ 'price_netto', 'price_brutto', 'price_netto_promo', 'price_brutto_promo', 'vat', 'wp' ], [ 'id' => $this -> parent_id ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $result ) ) foreach ( $result as $key => $val )
$this -> $key = $val;
}
$results = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => $this -> parent_id, 'lang_id' => $lang_id ] ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $results ) ) foreach ( $results as $row )
{
if ( $row[ 'copy_from' ] )
{
$results2 = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => $this -> parent_id, 'lang_id' => $row[ 'copy_from' ] ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
$this -> language = $row2;
}
else
$this -> language = $row;
}
$this -> images = $mdb -> select( 'pp_shop_products_images', '*', [ 'product_id' => $this -> parent_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'ASC' ] ] );
$this -> files = $mdb -> select( 'pp_shop_products_files', '*', [ 'product_id' => $this -> parent_id] );
$this -> categories = $mdb -> select( 'pp_shop_products_categories', 'category_id', [ 'product_id' => $this -> parent_id ] );
$this -> products_related = $mdb -> select( 'pp_shop_products_related', 'product_related_id', [ 'product_id' => $this -> parent_id ] );
$this -> products_sets = $mdb -> select( 'pp_shop_product_sets_products', 'product_id', [ 'AND' => [ 'set_id' => $this -> set_id, 'product_id[!]' => $this -> parent_id ] ] );
}
else
{
$results = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $lang_id ] ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $results ) ) foreach ( $results as $row )
{
if ( $row[ 'copy_from' ] )
{
$results2 = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $row[ 'copy_from' ] ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
$this -> language = $row2;
}
else
$this -> language = $row;
}
$this -> images = $mdb -> select( 'pp_shop_products_images', '*', [ 'product_id' => $product_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'ASC' ] ] );
$this -> files = $mdb -> select( 'pp_shop_products_files', '*', [ 'product_id' => $product_id ] );
$this -> categories = $mdb -> select( 'pp_shop_products_categories', 'category_id', [ 'product_id' => $product_id ] );
$this -> products_related = $mdb -> select( 'pp_shop_products_related', 'product_related_id', [ 'product_id' => $product_id ] );
$this -> products_sets = $mdb -> select( 'pp_shop_product_sets_products', 'product_id', [ 'AND' => [ 'set_id' => $this -> set_id, 'product_id[!]' => $product_id ] ] );
$results = $mdb -> select( 'pp_shop_products', 'id', [ 'parent_id' => $product_id ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $results ) )
{
foreach ( $results as $row )
$product_combinations[] = \shop\Product::getFromCache( $row, $lang_id );
$this -> product_combinations = $product_combinations;
}
}
$producer = $mdb -> get( 'pp_shop_producer', '*', [ 'id' => (int) $this -> producer_id ] );
$producer_languages = $mdb -> get( 'pp_shop_producer_lang', '*', [ 'AND' => [ 'producer_id' => (int) $this -> producer_id, 'lang_id' => $lang_id ] ] );
$producer['description'] = $producer_languages['description'];
$producer['data'] = $producer_languages['data'];
$producer['meta_title'] = $producer_languages['meta_title'];
$this -> producer = $producer;
if ( $permutation_hash )
{
$permutation_price = $mdb -> get( 'pp_shop_products', [ 'price_netto', 'price_brutto', 'price_netto_promo', 'price_brutto_promo' ], [ 'AND' => [ 'permutation_hash' => $permutation_hash, 'parent_id' => $product_id ] ] );
if ( is_array( $permutation_price ) )
{
if ( $permutation_price[ 'price_netto' ] != null )
$this -> price_netto = $permutation_price[ 'price_netto' ];
if ( $permutation_price[ 'price_brutto' ] != null )
$this -> price_brutto = $permutation_price[ 'price_brutto' ];
if ( $permutation_price[ 'price_netto_promo' ] != null )
$this -> price_netto_promo = $permutation_price[ 'price_netto_promo' ];
if ( $permutation_price[ 'price_brutto_promo' ] != null )
$this -> price_brutto_promo = $permutation_price[ 'price_brutto_promo' ];
}
}
$this -> custom_fields = $mdb -> select( 'pp_shop_products_custom_fields', '*', [ 'id_product' => $product_id ] );
}
/**
* Retrieves a product object from cache or creates a new instance if not found.
*
* @param int $product_id The ID of the product.
* @param int $lang_id The ID of the language.
* @param string $permutation_hash The permutation hash of the product.
* @return \shop\Product The product object.
*/
public static function getFromCache($product_id, $lang_id, $permutation_hash = null)
{
// Check if Redis extension is loaded
if (class_exists('Redis'))
{
try
{
// Get the Redis connection instance
$redis = \Shared\Cache\RedisConnection::getInstance()->getConnection();
// Check if Redis connection is valid
if ( $redis )
{
// Try to retrieve the serialized product object from cache
$objectData = $redis->get("shop\product:$product_id:$lang_id:$permutation_hash");
if (!$objectData)
{
// Product not found in cache, create a new instance and store it in cache
$object = new self($product_id, $lang_id, $permutation_hash);
$redis->setex("shop\product:$product_id:$lang_id:$permutation_hash", 60 * 60 * 24, serialize($object));
}
else
{
// Product found in cache, unserialize it
$object = unserialize($objectData);
}
}
else
{
// Redis connection failed, create a new instance
$object = new self($product_id, $lang_id, $permutation_hash);
}
}
catch (\Exception $e)
{
// Log the exception if needed
$object = new self($product_id, $lang_id, $permutation_hash);
}
}
else
{
// Redis extension not loaded, create a new instance
$object = new self($product_id, $lang_id, $permutation_hash);
}
return $object;
}
public function getDefaultCombinationPrices()
{
$permutation_hash = '';
$attributes = \shop\Product::get_product_attributes( $this -> product_combinations );
foreach ( $attributes as $attribute )
{
foreach ( $attribute['values'] as $value )
{
if ( $value['is_default'] )
{
if ( $permutation_hash )
$permutation_hash .= '|';
$permutation_hash .= $attribute['id'] . '-' . $value['id'];
}
}
}
foreach ( $this -> product_combinations as $product_combination )
{
if ( $product_combination -> permutation_hash == $permutation_hash )
{
$prices['price_netto'] = $product_combination -> price_netto;
$prices['price_brutto'] = $product_combination -> price_brutto;
$prices['price_netto_promo'] = $product_combination -> price_netto_promo;
$prices['price_brutto_promo'] = $product_combination -> price_brutto_promo;
}
}
return $prices;
}
public function generateSubtitleFromAttributes( $permutation_hash )
{
global $lang_id;
$subtitle = '';
$attributes = explode( '|', $permutation_hash );
foreach ( $attributes as $attribute )
{
$attribute = explode( '-', $attribute );
if ( $subtitle )
$subtitle .= ', ';
$subtitle .= \shop\ProductAttribute::getAttributeName( $attribute[0], $lang_id ) . ': ' . \shop\ProductAttribute::get_value_name( $attribute[1], $lang_id );
}
return $subtitle;
}
public function getProductDataBySelectedAttributes( $selected_attribute )
{
global $settings;
foreach ( $this -> product_combinations as $product_combination )
{
if ( $product_combination -> permutation_hash == $selected_attribute )
{
if ( $product_combination -> quantity !== null or $product_combination -> stock_0_buy )
{
$result['quantity'] = $product_combination -> quantity;
$result['stock_0_buy'] = $product_combination -> stock_0_buy;
$result['price_netto'] = Shop::shortPrice( $product_combination -> price_netto );
$result['price_brutto'] = Shop::shortPrice( $product_combination -> price_brutto );
$result['price_netto_promo'] = $product_combination -> price_netto_promo ? Shop::shortPrice( $product_combination -> price_netto_promo ) : null;
$result['price_brutto_promo'] = $product_combination -> price_brutto_promo ? Shop::shortPrice( $product_combination -> price_brutto_promo ) : null;
}
else
{
$result['quantity'] = $this -> quantity;
$result['stock_0_buy'] = $this -> stock_0_buy;
$result['price_netto'] = Shop::shortPrice( $this -> price_netto );
$result['price_brutto'] = Shop::shortPrice( $this -> price_brutto );
$result['price_netto_promo'] = $this -> price_netto_promo ? Shop::shortPrice( $this -> price_netto_promo ) : null;
$result['price_brutto_promo'] = $this -> price_brutto_promo ? Shop::shortPrice( $this -> price_brutto_promo ) : null;
}
}
}
$result['messages']['warehouse_message_zero'] = $this -> language['warehouse_message_zero'] ? $this -> language['warehouse_message_zero'] : $settings['warehouse_message_zero_pl'];
$result['messages']['warehouse_message_nonzero'] = $this -> language['warehouse_message_nonzero'] ? $this -> language['warehouse_message_nonzero'] : $settings['warehouse_message_nonzero_pl'];
$result['permutation_hash'] = $selected_attribute;
return $result;
}
// sprawdź czy produkt jest na promocji
static public function is_product_on_promotion( int $product_id )
{
global $mdb;
if ( $mdb -> get( 'pp_shop_products', 'price_netto_promo', [ 'id' => $product_id ] ) != null )
return true;
return false;
}
// pobierz kod SKU
static public function get_product_sku( int $product_id )
{
global $mdb;
$result = $mdb -> get( 'pp_shop_products', [ 'parent_id', 'sku' ], [ 'id' => $product_id ] );
if ( $result['sku'] )
return $result['sku'];
else
return $mdb -> get( 'pp_shop_products', 'sku', [ 'id' => $result['parent_id'] ] );
}
// pobierz cenę produktu
// FASADA - wywołuje nową klasę Domain\Product\ProductRepository
static public function get_product_price( int $product_id )
{
global $mdb;
$repository = new \Domain\Product\ProductRepository($mdb);
return $repository->getPrice($product_id);
}
// pobierz nazwę produktu
// FASADA - wywołuje nową klasę Domain\Product\ProductRepository
static public function get_product_name( int $product_id, string $lang_id = null )
{
global $mdb;
if ( !$lang_id )
$lang_id = ( new \Domain\Languages\LanguagesRepository( $mdb ) )->defaultLanguage();
$repository = new \Domain\Product\ProductRepository($mdb);
return $repository->getName($product_id, $lang_id);
}
// pobierz i wyświetl produktu do zestawu po dodaniu do koszyka
static public function product_sets_when_add_to_basket( int $product_id )
{
global $mdb;
$cacheHandler = new \Shared\Cache\CacheHandler();
$cacheKey = "\shop\Product::product_sets_when_add_to_basket:$product_id";
$objectData = $cacheHandler -> get( $cacheKey );
if ( !$objectData )
{
if ( $product_id_tmp = $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $product_id ] ) )
$set_id = $mdb -> get( 'pp_shop_products', 'set_id', [ 'id' => $product_id_tmp ] );
else
$set_id = $mdb -> get( 'pp_shop_products', 'set_id', [ 'id' => $product_id ] );
$products = $mdb -> select( 'pp_shop_product_sets_products', 'product_id', [ 'set_id' => $set_id ] );
if ( !$products )
{
$products_intersection = $mdb -> select( 'pp_shop_orders_products_intersection', [ 'product_1_id', 'product_2_id' ], [ 'OR' => [ 'product_1_id' => $product_id, 'product_2_id' => $product_id ], 'ORDER' => [ 'count' => 'DESC' ], 'LIMIT' => 5 ] );
if ( !count( $products_intersection ) )
{
$product_id = $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $product_id ] );
$products_intersection = $mdb -> select( 'pp_shop_orders_products_intersection', [ 'product_1_id', 'product_2_id' ], [ 'OR' => [ 'product_1_id' => $product_id, 'product_2_id' => $product_id ], 'ORDER' => [ 'count' => 'DESC' ], 'LIMIT' => 5 ] );
}
foreach ( $products_intersection as $product_intersection )
{
if ( $product_intersection['product_1_id'] != $product_id )
$products[] = $product_intersection['product_1_id'];
else
$products[] = $product_intersection['product_2_id'];
}
array_unique( $products );
}
$cacheHandler -> set( $cacheKey, $products );
}
else
{
$products = unserialize( $objectData );
}
foreach ( $products as $product_id )
{
if ( !( new \Domain\Product\ProductRepository( $mdb ) )->isProductActiveCached( (int)$product_id ) )
$products = array_diff( $products, [ $product_id ] );
}
return \Shared\Tpl\Tpl::view( 'shop-basket/alert-product-sets', [
'products' => $products
] );
}
// dodaje 1 do licznika odwiedziń produktu
static public function add_visit( int $product_id )
{
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'visits[+]' => 1 ], [ 'id' => $product_id ] );
}
//FIX:ME - do poprawy nazwa
// pobierz zdjęcie główne
static public function getProductImg( int $product_id )
{
global $mdb;
$results = $mdb -> select( 'pp_shop_products_images', 'src', [ 'product_id' => $product_id, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $results ) ) foreach ( $results as $row )
return $row;
}
//FIX:ME - do poprawy nazwa
// pobierz bezpośredni url produktu
static public function getProductUrl( int $product_id )
{
global $mdb;
$lang_id = ( new \Domain\Languages\LanguagesRepository( $mdb ) )->defaultLanguage();
$results = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $lang_id ] ] );
if ( \Shared\Helpers\Helpers::is_array_fix( $results ) ) foreach ( $results as $row )
{
if ( $row[ 'copy_from' ] )
{
$results2 = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $row[ 'copy_from' ] ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
$language = $row2;
}
else
$language = $row;
}
$language['seo_link'] ? $url = '/' . $language['seo_link'] : $url = '/p-' . $product_id . '-' . \Shared\Helpers\Helpers::seo( $language['name'] );
return $url;
}
// pobierz ilość wyników na podstawie wyszukiwanej nazwy
static public function searchProductsByNameCount( $query, $lang_id )
{
global $mdb;
$results = $mdb -> query( 'SELECT COUNT(0) AS c FROM ( '
. 'SELECT psp.id, '
. '( CASE '
. 'WHEN copy_from IS NULL THEN name '
. 'WHEN copy_from IS NOT NULL THEN ( '
. 'SELECT '
. 'name '
. 'FROM '
. 'pp_shop_products_langs '
. 'WHERE '
. 'lang_id = pspl.copy_from AND product_id = psp.id '
. ') '
. 'END ) AS name '
. 'FROM '
. 'pp_shop_products AS psp '
. 'INNER JOIN pp_shop_products_langs AS pspl ON pspl.product_id = psp.id '
. 'WHERE '
. 'status = 1 AND name LIKE :query AND lang_id = :lang_id '
. ') AS q1', [
':query' => '%' . $query . '%',
':lang_id' => $lang_id
] ) -> fetchAll( \PDO::FETCH_ASSOC );
return $results[0]['c'];
}
// pobierz id produktów na podstawie wyszukiwanej nazwy
static public function getProductsIdByName( string $query, string $lang_id, int $products_limit, int $from )
{
global $mdb;
$results = $mdb -> query( 'SELECT '
. 'psp.id, '
. '( CASE '
. 'WHEN copy_from IS NULL THEN name '
. 'WHEN copy_from IS NOT NULL THEN ( '
. 'SELECT '
. 'name '
. 'FROM '
. 'pp_shop_products_langs '
. 'WHERE '
. 'lang_id = pspl.copy_from AND product_id = psp.id '
. ') '
. 'END ) AS name '
. 'FROM '
. 'pp_shop_products AS psp '
. 'INNER JOIN pp_shop_products_langs AS pspl ON pspl.product_id = psp.id '
. 'WHERE '
. 'status = 1 AND name LIKE :query AND lang_id = :lang_id '
. 'ORDER BY '
. 'name ASC '
. 'LIMIT '
. $from . ',' . $products_limit, [
':query' => '%' . $query . '%',
':lang_id' => $lang_id
] ) -> fetchAll( \PDO::FETCH_ASSOC );
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
$output[] = $row['id'];
return $output;
}
static public function searchProductsByName( string $query, string $lang_id, int $bs = 0 )
{
$count = \shop\Product::searchProductsByNameCount( $query, $lang_id );
$ls = ceil( $count / 12 );
if ( $bs < 1 )
$bs = 1;
else if ( $bs > $ls )
$bs = $ls;
$from = 12 * ( $bs - 1 );
if ( $from < 0 )
$from = 0;
$results['products'] = \shop\Product::getProductsIdByName( $query, $lang_id, 12, $from );
$results['count'] = $count;
$results['ls'] = $ls;
return $results;
}
static public function searchProductByNameAjax( string $query, string $lang_id )
{
global $mdb;
return $mdb -> query(
'SELECT
product_id
FROM
pp_shop_products_langs AS pspl
INNER JOIN pp_shop_products AS psp ON psp.id = pspl.product_id
WHERE
status = 1 AND lang_id = :lang_id AND LOWER(name) LIKE :query
ORDER BY visits DESC
LIMIT 12', [
':query' => '%' . $query . '%',
':lang_id' => $lang_id
] ) -> fetchAll( \PDO::FETCH_ASSOC );
}
public function permutations()
{
if ( is_array( $this -> attributes ) ) foreach ( $this -> attributes as $attribute )
{
$attribute_obj = new \shop\ProductAttribute( $attribute['attribute_id'] );
if ( $attribute_obj['stock_influences'] )
$attributes_tmp[ $attribute[ 'attribute_id' ] ][] = $attribute[ 'value_id' ];
}
if ( is_array( $attributes_tmp ) )
return $this -> permutations = self::array_cartesian( $attributes_tmp );
}
/// sprawdź czy produkt można zamawiać przy stanie magazynowym zero
static public function is_stock_0_buy( int $product_id )
{
global $mdb;
// jeżeli jest to kombinacja produktu
if ( $parent_id = $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $product_id ] ) )
return $mdb -> get( 'pp_shop_products', 'stock_0_buy', [ 'id' => $parent_id ] );
else
return $mdb -> get( 'pp_shop_products', 'stock_0_buy', [ 'id' => $product_id ] );
}
// pobierz stan magazynowy i komunikaty dla kombinacji produktu
static public function get_product_permutation_quantity_options( int $product_id, $permutation )
{
global $mdb, $settings;
$cacheHandler = new \Shared\Cache\CacheHandler();
$cacheKey = "\shop\Product::get_product_permutation_quantity_options:v2:$product_id:$permutation";
$objectData = $cacheHandler -> get( $cacheKey );
if ( !$objectData )
{
if ( $mdb -> count( 'pp_shop_products', [ 'AND' => [ 'parent_id' => $product_id, 'permutation_hash' => $permutation ] ] ) )
{
$result['quantity'] = $mdb -> get( 'pp_shop_products', 'quantity', [ 'AND' => [ 'parent_id' => $product_id, 'permutation_hash' => $permutation ] ] );
$result['stock_0_buy'] = $mdb -> get( 'pp_shop_products', 'stock_0_buy', [ 'AND' => [ 'parent_id' => $product_id, 'permutation_hash' => $permutation ] ] );
if ( $result['quantity'] == null )
{
$result['quantity'] = $mdb -> get( 'pp_shop_products', 'quantity', [ 'id' => $product_id ] );
if ( $result['stock_0_buy'] == null )
$result['stock_0_buy'] = $mdb -> get( 'pp_shop_products', 'stock_0_buy', [ 'id' => $product_id] );
$result['messages'] = $mdb -> get( 'pp_shop_products_langs', [ 'warehouse_message_zero', 'warehouse_message_nonzero' ], [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => 'pl' ] ] );
if ( !$result['messages']['warehouse_message_zero'] )
$result['messages']['warehouse_message_zero'] = $settings['warehouse_message_zero_pl'];
if ( !$result['messages']['warehouse_message_nonzero'] )
$result['messages']['warehouse_message_nonzero'] = $settings['warehouse_message_nonzero_pl'];
}
else
{
$result['messages'] = $mdb -> get( 'pp_shop_products_langs', [ 'warehouse_message_zero', 'warehouse_message_nonzero' ], [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => 'pl' ] ] );
if ( !$result['messages']['warehouse_message_zero'] )
$result['messages']['warehouse_message_zero'] = $settings['warehouse_message_zero_pl'];
if ( !$result['messages']['warehouse_message_nonzero'] )
$result['messages']['warehouse_message_nonzero'] = $settings['warehouse_message_nonzero_pl'];
}
}
else
{
$result['quantity'] = $mdb -> get( 'pp_shop_products', 'quantity', [ 'id' => $product_id ] );
$result['stock_0_buy'] = $mdb -> get( 'pp_shop_products', 'stock_0_buy', [ 'id' => $product_id] );
$result['messages'] = $mdb -> get( 'pp_shop_products_langs', [ 'warehouse_message_zero', 'warehouse_message_nonzero' ], [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => 'pl' ] ] );
if ( !$result['messages']['warehouse_message_zero'] )
$result['messages']['warehouse_message_zero'] = $settings['warehouse_message_zero_pl'];
if ( !$result['messages']['warehouse_message_nonzero'] )
$result['messages']['warehouse_message_nonzero'] = $settings['warehouse_message_nonzero_pl'];
}
$cacheHandler -> set( $cacheKey, $result );
}
else
{
return unserialize( $objectData );
}
return $result;
}
// pobierz stan magazynowy produktu
// FASADA - wywołuje nową klasę Domain\Product\ProductRepository
static public function get_product_quantity( int $product_id )
{
global $mdb;
$repository = new \Domain\Product\ProductRepository($mdb);
return $repository->getQuantity($product_id);
}
public static function product_categories( int $product_id )
{
global $mdb;
return $mdb -> select( 'pp_shop_products_categories', 'category_id', [ 'product_id' => $product_id ] );
}
public static function calculate_basket_product_price( float $price_brutto_promo, float $price_brutto, $coupon, $basket_position )
{
// ? produkty przecenione
if ( $price_brutto_promo )
{
$price['price'] = $price_brutto;
$price['price_new'] = $price_brutto_promo;
// ? zastosuje kod rabatowy
if ( $coupon -> type && $coupon -> include_discounted_product )
{
// ? ograniczony do wybranych kategorii
if ( $coupon -> categories != null )
{
$coupon_categories = json_decode( $coupon -> categories );
$product_categories = \shop\Product::product_categories( (int)$basket_position['parent_id'] ? (int)$basket_position['parent_id'] : (int)$basket_position['product-id'] );
if ( is_array( $coupon_categories ) ) foreach ( $coupon_categories as $category_tmp )
{
if ( in_array( $category_tmp, $product_categories ) )
{
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $price['price_new'] - $price['price_new'] * $coupon -> amount / 100 );
break;
}
}
}
// ? nieograniczony kategoriami
else
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $price['price_new'] - $price['price_new'] * $coupon -> amount / 100 );
// ? uwzględnij promocję jeżeli może łączyć się z rabatami i produktami przecenionymi
if ( $basket_position['discount_amount'] && $basket_position['discount_include_coupon'] && $basket_position['include_product_promo'] )
{
// ? najtańszy produkt w koszyku (z wybranych kategorii) za X zł
if ( $basket_position['discount_type'] == 3 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $basket_position['discount_amount'] );
// ? rabat procentowy
if ( $basket_position['discount_type'] == 1 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal($price['price_new'] - $price['price_new'] * $basket_position['discount_amount'] / 100 );
}
}
// ? brak kodu rabatowego
else
{
if ( $basket_position['discount_amount'] && $basket_position['include_product_promo'] )
{
// ? Najtańszy produkt w koszyku (z wybranych kategorii) za X zł
if ( $basket_position['discount_type'] == 3 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $basket_position['discount_amount'] );
// ? rabat procentowy
if ( $basket_position['discount_type'] == 1 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal($price['price_new'] - $price['price_new'] * $basket_position['discount_amount'] / 100 );
}
}
}
// ? produkt nieprzeceniony
else
{
$price['price'] = $price_brutto;
$price['price_new'] = $price_brutto;
// ? zastosuj kod rabatowy
if ( $coupon -> type )
{
// ? ograniczony do wybranych kategorii
if ( $coupon -> categories != null )
{
$coupon_categories = json_decode( $coupon -> categories );
$product_categories = \shop\Product::product_categories( $basket_position['parent_id'] ? $basket_position['parent_id'] : $basket_position['product-id'] );
if ( is_array( $coupon_categories ) ) foreach ( $coupon_categories as $category_tmp )
{
if ( in_array( $category_tmp, $product_categories ) )
{
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $price['price_new'] - $price['price_new'] * $coupon -> amount / 100 );
break;
}
}
}
// ? nieograniczony
else
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal($price['price'] - $price['price'] * $coupon -> amount / 100 );
// ? uwzględnij promocję jeżeli może łączyć się z rabatami i produktami przecenionymi
if ( $basket_position['discount_amount'] && $basket_position['discount_include_coupon'] && $basket_position['include_product_promo'] )
{
// ? najtańszy produkt w koszyku (z wybranych kategorii) za X zł
if ( $basket_position['discount_type'] == 3 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $basket_position['discount_amount'] );
// ? rabat procentowy
if ( $basket_position['discount_type'] == 1 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal($price['price'] - $price['price'] * $basket_position['discount_amount'] / 100 );
}
}
// ? bez kodu rabatowego
else
{
if ( $basket_position['discount_amount'] )
{
// ? Najtańszy produkt w koszyku (z wybranych kategorii) za X zł
if ( $basket_position['discount_type'] == 3 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal( $basket_position['discount_amount'] );
// ? rabat procentowy
if ( $basket_position['discount_type'] == 1 )
$price['price_new'] = \Shared\Helpers\Helpers::normalize_decimal($price['price'] - $price['price'] * $basket_position['discount_amount'] / 100 );
}
}
}
return $price;
}
// pobierz wiadomość zależną od stanu magazynowego
// id_product - id produktu
// attributes - wybrane atrybuty przez użytkownika
public static function getWarehouseMessage( int $id_product, $attributes, string $lang_id )
{
global $settings;
$permutation = self::getPermutation( $attributes );
$quantity = self::getPermutationQuantity( $id_product, $permutation );
if ( $quantity )
{
if ( $msg = ( new \Domain\Product\ProductRepository( $mdb ) )->getWarehouseMessageNonzero( (int)$id_product, $lang_id ) )
$result = [ 'msg' => $msg, 'quantity' => $quantity ];
else if ( $settings[ 'warehouse_message_nonzero_' . $lang_id ] )
$result = [ 'msg' => $settings[ 'warehouse_message_nonzero_' . $lang_id ], 'quantity' => $quantity ];
}
else
{
if ( $msg = ( new \Domain\Product\ProductRepository( $mdb ) )->getWarehouseMessageZero( (int)$id_product, $lang_id ) )
$result = [ 'msg' => $msg, 'quantity' => $quantity ];
else if ( $settings[ 'warehouse_message_zero_' . $lang_id ] )
$result = [ 'msg' => $settings[ 'warehouse_message_zero_' . $lang_id ], 'quantity' => $quantity ];
}
return $result;
}
// pobranie id produktu wg wybranych parametrów
static public function get_product_id_by_attributes( int $parent_id, array $attributes )
{
global $mdb;
return $mdb -> get( 'pp_shop_products', 'id', [ 'AND' => [ 'parent_id' => $parent_id, 'permutation_hash' => implode( '|', $attributes ) ] ] );
}
// pobranie permutation_hash dla kombinacji produktu
static public function get_product_permutation_hash( int $product_id )
{
global $mdb;
return $mdb -> get( 'pp_shop_products', 'permutation_hash', [ 'id' => $product_id ] );
}
// pobranie listy atrybutów z wybranymi wartościami
static public function get_product_attributes( $products )
{
if ( !is_array( $products ) or !count( $products ) )
return false;
$attributes = array();
foreach ( $products as $product )
{
$permutations = explode( '|', $product['permutation_hash'] );
foreach ( $permutations as $permutation )
{
$attribute = explode( '-', $permutation );
$value['id'] = $attribute[1];
$value['is_default'] = \shop\ProductAttribute::is_value_default( $attribute[1] );
if ( array_search( $attribute[1], array_column( $attributes, 'id' ) ) === false )
$attributes[ $attribute[0] ][] = $value;
}
}
$attributes = \Shared\Helpers\Helpers::removeDuplicates( $attributes, 'id' );
foreach ( $attributes as $key => $val )
{
$row['id'] = $key;
$row['values'] = $val;
$attributes_sort[ \shop\ProductAttribute::get_attribute_order( $key ) ] = $row;
}
return $attributes_sort;
}
public static function array_cartesian( $input )
{
$result = array();
foreach ( $input as $key => $values )
{
if ( empty( $values ) )
continue;
if ( empty( $result ) )
{
foreach ( $values as $value )
{
$result[] = array( $key => $value );
}
}
else
{
$append = array();
foreach ( $result as &$product )
{
$product[$key] = array_shift( $values );
$copy = $product;
foreach ( $values as $item )
{
$copy[$key] = $item;
$append[] = $copy;
}
array_unshift( $values, $product[$key] );
}
$result = array_merge( $result, $append );
}
}
return $result;
}
public function __get( $variable )
{
if ( is_array( $this -> data ) and array_key_exists( $variable, $this -> data ) )
return $this -> $variable;
}
public function __set( $variable, $value )
{
$this -> $variable = $value;
}
public function offsetExists( $offset )
{
return isset( $this -> $offset );
}
public function offsetGet( $offset )
{
return $this -> $offset;
}
public function offsetSet( $offset, $value )
{
$this -> $offset = $value;
}
public function offsetUnset( $offset )
{
unset( $this -> $offset );
}
// generate_sku_code
public static function generate_sku_code( int $product_id )
{
global $mdb;
// find product with sku like 'PP-000000'
$skus = $mdb -> select( 'pp_shop_products', 'sku', [ 'sku[~]' => 'PP-' ] );
if ( is_array( $skus ) )
{
foreach ( $skus as $sku )
$sku_codes[] = (int)substr( $sku, 3 );
}
// find max sku
if ( is_array( $sku_codes ) )
$sku = 'PP-' . str_pad( max( $sku_codes ) + 1, 6, '0', STR_PAD_LEFT );
else
$sku = 'PP-000001';
return $sku;
}
// product_xml_name_save
public static function product_xml_name_save( int $product_id, string $xml_name, string $lang_id )
{
global $mdb;
return $mdb -> update( 'pp_shop_products_langs', [ 'xml_name' => $xml_name ], [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $lang_id ] ] );
}
// product_custom_label_suggestions
public static function product_custom_label_suggestions( string $custom_label, string $label_type )
{
global $mdb;
$results = $mdb -> query( 'SELECT DISTINCT
' . $label_type . ' AS label
FROM
pp_shop_products
WHERE
' . $label_type . ' LIKE :custom_label
LIMIT 10', [ ':custom_label' => '%' . $custom_label . '%' ] ) -> fetchAll( \PDO::FETCH_ASSOC );
if ( is_array( $results ) )
{
foreach ( $results as $row )
$output[] = $row;
}
return $output;
}
// product_custom_label_save
public static function product_custom_label_save( int $product_id, string $custom_label, string $label_type )
{
global $mdb;
return $mdb -> update( 'pp_shop_products', [ $label_type => $custom_label ], [ 'id' => $product_id ] );
}
public static function product_meta (int $product_id)
{
global $mdb;
return $mdb->select(
"pp_shop_products_categories (ppc)",
[
"[>]pp_shop_categories_langs (pcl)" => ["ppc.category_id" => "category_id"]
],
[
"pcl.title",
"pcl.seo_link"
],
[
"ppc.product_id" => $product_id
]
);
}
}