Files
wyczarujprezent.pl/modules/an_homeproducts/classes/anHomeProductsBlocks.php
Jacek Pyziak 64bcc1a6be Add new templates and update existing ones for An Home Products module
- Created new index.php files for various directories to establish structure.
- Added form.tpl and index.php for form helpers to enhance form handling.
- Introduced suggestions.tpl and top.tpl for improved admin interface.
- Implemented ajax-products.tpl and banners.tpl for front-end product display.
- Developed content.tpl and widget-blocks.tpl for dynamic content rendering.
- Enhanced widget-tabs.tpl and widget-wrapper.tpl for better tabbed navigation.
- Included necessary licensing information in all new files.
2025-05-16 14:21:29 +02:00

781 lines
25 KiB
PHP

<?php
/**
* 2024 Anvanto
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
*
* @author Anvanto <anvantoco@gmail.com>
* @copyright 2024 Anvanto
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
if (!defined('_PS_VERSION_')) {
exit;
}
use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShop\PrestaShop\Core\Product\ProductListingPresenter;
use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever;
// Featured
use PrestaShop\PrestaShop\Adapter\Category\CategoryProductSearchProvider;
// PricesDrop
use PrestaShop\PrestaShop\Adapter\PricesDrop\PricesDropProductSearchProvider;
// BestSellers
use PrestaShop\PrestaShop\Adapter\BestSales\BestSalesProductSearchProvider;
// New
use PrestaShop\PrestaShop\Adapter\NewProducts\NewProductsProductSearchProvider;
use PrestaShop\PrestaShop\Core\Product\Search\ProductSearchContext;
use PrestaShop\PrestaShop\Core\Product\Search\ProductSearchQuery;
use PrestaShop\PrestaShop\Core\Product\Search\SortOrder;
require_once _PS_MODULE_DIR_ . 'an_homeproducts/classes/anHomeProductFiles.php';
class anHomeProductsBlocks extends ObjectModel
{
/**
* @var int
*/
public $id_block;
/**
* @var int
*/
public $id;
public $special_id_block;
public $type = 'new-products';
public $active = 1;
public $show_sort = 0;
public $show_sub_cat = 0;
public $products_display = 8;
public $id_category = 0;
public $position;
public $title;
public $text;
public $link;
/**
* @var array
*/
public static $definition = [
'table' => 'an_homeproducts_blocks',
'primary' => 'id_block',
'multilang' => true,
'fields' => [
'special_id_block' => ['type' =>self::TYPE_STRING ],
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
'show_sort' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
'products_display' => ['type' =>self::TYPE_INT ],
'id_category' => ['type' =>self::TYPE_INT ],
'show_sub_cat' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
'position' => ['type' =>self::TYPE_INT ],
'type' => ['type' =>self::TYPE_STRING ],
'title' => ['type' =>self::TYPE_STRING,'lang' => true, 'validate' => 'isString', 'required' => true, 'size' => 256 ],
'text' => ['type' =>self::TYPE_HTML,'lang' => true ],
'link' => ['type' =>self::TYPE_STRING,'lang' => true ]
],
];
public function __construct($id = null, $id_lang = null)
{
parent::__construct($id, $id_lang);
}
public function add($auto_date = true, $null_values = false)
{
if (empty($this->special_id_block)) {
$this->special_id_block = uniqid();
}
return parent::add($auto_date, $null_values);
}
public function getData($params = [])
{
$context = Context::getContext();
$data = self::getBlockData((array) $this, $params);
$this->sort = $data['sort'];
$this->products = $data['products'];
$this->totalProducts = $data['totalProducts'];
$this->productsNextPage = $data['productsNextPage'];
if ($this->id_category){
$this->childrenCats = Category::getChildren(
$this->id_category,
$context->language->id,
true,
$context->shop->id
);
}
}
public static function getBlockData($block, $params = [])
{
switch ($block['type']){
case 'new-products':
return self::getNewProducts($block['products_display'], $params);
break;
case 'best-sales':
return self::getBestSellers($block['products_display'], $params);
break;
case 'prices-drop':
return self::getSpecials($block['products_display'], $params);
break;
case 'prices-drop-percentage':
return self::getSpecialsPercentage($block['products_display'], $params);
break;
case 'category':
return self::getProductsCategory($block, $params);
break;
case 'categories':
return self::getProductsCategories($block, $params);
break;
case 'products':
return self::getProductsByIds($block, $params);
break;
}
}
public static function getBlocks($mergeData = true, $all = false)
{
$sql = '
SELECT * FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks` sw
LEFT JOIN `' . _DB_PREFIX_ . 'an_homeproducts_blocks_lang` sl
ON (sw.`id_block` = sl.`id_block`
AND sl.`id_lang` = ' . (int) Context::getContext()->language->id . ')
';
if (!$all){
$sql .= 'WHERE sw.`active`=1 ';
}
if (Shop::isFeatureActive()) {
$sql .= ' AND sw.`id_block` IN (
SELECT sa.`id_block`
FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks_shop` sa
WHERE sa.id_shop IN (' . implode(', ', Shop::getContextListShopID()) . ')
)';
}
$sql .= ' ORDER BY sw.`position`';
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
foreach ($result as $key => $field){
$sql_lang = 'SELECT * FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks_lang` WHERE `id_block` = ' . (int) $field['id_block'] . '';
$res_lang = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql_lang);
$langContent = [];
foreach ($res_lang as $item){
$item['iso_code'] = Language::getIsoById($item['id_lang']);
$langContent[$item['iso_code']] = $item;
}
$result[$key]['languages'] = $langContent;
}
if ($mergeData){
foreach ($result as $id => $block){
$result[$id] = array_merge($result[$id], (array) self::getBlockData($block));
}
}
if (!$result) {
return [];
} else {
return $result;
}
}
public static function getProductsCategory($block, $params = [])
{
$context = Context::getContext();
$nProducts = $block['products_display'];
if (!isset($params['sort']) || $params['sort'] == ''){
$params['sort'] = 'product.position.asc';
}
$page = 1;
if (isset($params['page']) && $params['page'] > 0){
$page = intval($params['page']);
}
$childrenCats = Category::getChildren(
$block['id_category'],
$context->language->id,
true,
$context->shop->id
);
$return['childrenCats'] = $childrenCats;
if (isset($params['idCategory']) && $params['idCategory']){
$category = new Category((int) $params['idCategory']);
} else {
$category = new Category((int) $block['id_category']);
}
$searchProvider = new CategoryProductSearchProvider(
$context->getTranslator(),
$category
);
$contextSearch = new ProductSearchContext($context);
$query = new ProductSearchQuery();
$query
->setResultsPerPage($nProducts)
->setPage($page)
;
$query->setSortOrder(SortOrder::newFromString(
$params['sort']
));
$result = $searchProvider->runQuery(
$contextSearch,
$query
);
$products = $result->getProducts();
$availableSort = [];
foreach ($result->getAvailableSortOrders() as $itemSort){
$availableSort[] = $itemSort->toArray();
}
$return['sort'] = $availableSort;
$return['products'] = self::productsPrepareForTemplate($context, $products);
$return['totalProducts'] = $result->getTotalProductsCount();
$return['productsNextPage'] = $return['totalProducts'] - ($page * $nProducts);
if ($return['productsNextPage'] < 0) {
$return['productsNextPage'] = 0;
}
return $return;
// return self::productsPrepareForTemplate($context, $products);
}
public static function getProductsByIds($block, $params = [])
{
$nProducts = $block['products_display'];
$id_block = $block['id_block'];
$randomize = false;
$context = Context::getContext();
$langId = Context::getContext()->language->id;
$sql = '
SELECT *, p.*
FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks_products` awl
LEFT JOIN `' . _DB_PREFIX_ . 'product` p
ON (p.`id_product` = awl.`id_product`)
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl
ON (p.`id_product` = pl.`id_product`
AND pl.`id_lang` = ' . (int) $langId . Shop::addSqlRestrictionOnLang('pl') . ')
WHERE awl.`id_block` = ' . (int) $id_block . '
ORDER BY awl.`position`
LIMIT 0,'.(int) $nProducts.'
';
$products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false);
if (!$products){
$products = [];
}
$return['sort'] = [];
$return['products'] = self::productsPrepareForTemplate($context, $products);
$return['totalProducts'] = 0;
$return['productsNextPage'] = 0;
return $return;
}
public static function getProductsCategories($block, $params = [])
{
$randomize = false;
$context = Context::getContext();
$nProducts = $block['products_display'];
$cats = self::getBlockCategories($block['id_block']);
$query = new ProductSearchQuery();
if ($randomize) {
$query->setSortOrder(SortOrder::random());
} else {
$query->setSortOrder(new SortOrder('product', 'position', 'asc'));
}
$products = [];
while (count($products) < $nProducts && count($cats)){
foreach ($cats as $id => $categoryId){
$page = 1;
while ($page){
$query
->setResultsPerPage($nProducts)
->setPage($page)
;
$category = new Category((int) $categoryId);
$searchProvider = new CategoryProductSearchProvider(
$context->getTranslator(),
$category
);
$result = $searchProvider->runQuery(
new ProductSearchContext($context),
$query
);
$productsCat = $result->getProducts();
if (count($productsCat) == 0){
unset($cats[$id]);
break;
}
$products = array_merge($products, $productsCat);
if (count($products) >= $nProducts){
break;
}
$page++;
}
}
}
// shuffle($products);
$products = array_chunk($products, $nProducts, true);
$products = array_shift($products);
$return['sort'] = [];
$return['products'] = self::productsPrepareForTemplate($context, $products);
$return['totalProducts'] = 0;
$return['productsNextPage'] = 0;
return $return;
// return self::productsPrepareForTemplate($context, $products);
}
public static function getBlockCategories($idBlock)
{
if (!$idBlock){
return [];
}
$sql = 'SELECT `id_category` FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks_categories` WHERE `id_block` = ' . (int) $idBlock . ' ';
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false);
$cats = [];
if ($result) {
foreach ($result as $item){
$cats[] = $item['id_category'];
}
}
return $cats;
}
public static function getBestSellers($nProducts = 8, $params = [])
{
if (Configuration::get('PS_CATALOG_MODE')) {
return false;
}
$context = Context::getContext();
if (!isset($params['sort']) || $params['sort'] == ''){
$params['sort'] = 'product.name.asc';
}
$page = 1;
if (isset($params['page']) && $params['page'] > 0){
$page = intval($params['page']);
}
$contextSearch = new ProductSearchContext($context);
$query = new ProductSearchQuery();
$query
->setResultsPerPage($nProducts)
->setPage($page)
;
$query->setQueryType('best-sales');
$query->setSortOrder(SortOrder::newFromString(
$params['sort']
));
$searchProvider = new BestSalesProductSearchProvider(
$context->getTranslator()
);
$result = $searchProvider->runQuery(
$contextSearch,
$query
);
$products = $result->getProducts();
$availableSort = [];
foreach ($result->getAvailableSortOrders() as $itemSort){
$availableSort[] = $itemSort->toArray();
}
$return['sort'] = $availableSort;
$return['products'] = self::productsPrepareForTemplate($context, $products);
$return['totalProducts'] = $result->getTotalProductsCount();
$return['productsNextPage'] = $return['totalProducts'] - ($page * $nProducts);
if ($return['productsNextPage'] < 0) {
$return['productsNextPage'] = 0;
}
return $return;
// return self::productsPrepareForTemplate($context, $products);
}
public static function getNewProducts($nProducts = 8, $params = [])
{
$context = Context::getContext();
if (!isset($params['sort']) || $params['sort'] == ''){
$params['sort'] = 'product.date_add.desc';
}
$page = 1;
if (isset($params['page']) && $params['page'] > 0){
$page = intval($params['page']);
}
$searchProvider = new NewProductsProductSearchProvider(
$context->getTranslator()
);
$contextSearch = new ProductSearchContext($context);
$query = new ProductSearchQuery();
$query
->setResultsPerPage($nProducts)
->setPage($page)
;
$query->setQueryType('new-products');
$query->setSortOrder(SortOrder::newFromString(
$params['sort']
));
$result = $searchProvider->runQuery(
$contextSearch,
$query
);
// totalProductsCount availableSortOrders currentSortOrder
//echo '<pre>'; var_dump($result); die;
// $result->getAvailableSortOrders()['0']->getLabel() - доступные методы сортировки для блока
// echo '<pre>'; var_dump($result->getCurrentSortOrder()); die;
$products = $result->getProducts();
$availableSort = [];
foreach ($result->getAvailableSortOrders() as $itemSort){
$availableSort[] = $itemSort->toArray();
}
$return['sort'] = $availableSort;
$return['products'] = self::productsPrepareForTemplate($context, $products);
$return['totalProducts'] = $result->getTotalProductsCount();
$return['productsNextPage'] = $return['totalProducts'] - ($page * $nProducts);
if ($return['productsNextPage'] < 0) {
$return['productsNextPage'] = 0;
}
return $return;
// return self::productsPrepareForTemplate($context, $products);
}
public static function getSpecials($nProducts = 8, $params = [])
{
$context = Context::getContext();
if (!isset($params['sort']) || $params['sort'] == ''){
$params['sort'] = 'product.name.asc';
}
$page = 1;
if (isset($params['page']) && $params['page'] > 0){
$page = intval($params['page']);
}
$searchProvider = new PricesDropProductSearchProvider(
$context->getTranslator()
);
$contextSearch = new ProductSearchContext($context);
$query = new ProductSearchQuery();
$query
->setResultsPerPage($nProducts)
->setPage($page)
;
$query->setQueryType('prices-drop');
$query->setSortOrder(SortOrder::newFromString(
$params['sort']
));
$result = $searchProvider->runQuery(
$contextSearch,
$query
);
$products = $result->getProducts();
$availableSort = [];
foreach ($result->getAvailableSortOrders() as $itemSort){
$availableSort[] = $itemSort->toArray();
}
$return['sort'] = $availableSort;
$return['products'] = self::productsPrepareForTemplate($context, $products);
$return['totalProducts'] = $result->getTotalProductsCount();
$return['productsNextPage'] = $return['totalProducts'] - ($page * $nProducts);
if ($return['productsNextPage'] < 0) {
$return['productsNextPage'] = 0;
}
return $return;
// return self::productsPrepareForTemplate($context, $products);
}
public static function getSpecialsPercentage($nProducts = 8, $params = [])
{
$page = 1;
if (isset($params['page']) && $params['page'] > 0){
$page = intval($params['page']);
}
$context = Context::getContext();
$id_lang = $context->language->id;
$front = true;
$sql = '
SELECT
p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`,
IFNULL(product_attribute_shop.id_product_attribute, 0) id_product_attribute,
pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`,
pl.`name`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name,
DATEDIFF(
p.`date_add`,
DATE_SUB(
"' . date('Y-m-d') . ' 00:00:00",
INTERVAL ' . (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20) . ' DAY
)
) > 0 AS new
FROM `' . _DB_PREFIX_ . 'specific_price` sprc, `' . _DB_PREFIX_ . 'product` p
' . Shop::addSqlAssociation('product', 'p') . '
LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_shop` product_attribute_shop
ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop=' . (int) $context->shop->id . ')
' . Product::sqlStock('p', 0, false, $context->shop) . '
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (
p.`id_product` = pl.`id_product`
AND pl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('pl') . '
)
LEFT JOIN `' . _DB_PREFIX_ . 'image_shop` image_shop
ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop=' . (int) $context->shop->id . ')
LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = ' . (int) $id_lang . ')
LEFT JOIN `' . _DB_PREFIX_ . 'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
WHERE product_shop.`active` = 1
AND p.id_product = sprc.id_product
AND sprc.reduction_type = "percentage"
AND product_shop.`show_price` = 1
' . ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') . '
';
$sql .= '
ORDER BY sprc.reduction DESC
LIMIT ' . (int) (($page - 1) * $nProducts) . ', ' . (int) $nProducts;
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
if (!$result) {
return false;
}
$products = Product::getProductsProperties($id_lang, $result);
$return['products'] = self::productsPrepareForTemplate($context, $products);;
// $return['totalProducts'] = $result->getTotalProductsCount();
// $return['productsNextPage'] = $return['totalProducts'] - ($page * $nProducts);
$return['productsNextPage'] = 0;
if ($return['productsNextPage'] < 0) {
$return['productsNextPage'] = 0;
}
return $return;
}
public static function productsPrepareForTemplate($context, $products)
{
$assembler = new ProductAssembler($context);
$presenterFactory = new ProductPresenterFactory($context);
$presentationSettings = $presenterFactory->getPresentationSettings();
$presenter = $presenterFactory->getPresenter();
$products_for_template = [];
if (is_array($products)) {
foreach ($products as $rawProduct) {
$products_for_template[] = $presenter->present(
$presentationSettings,
$assembler->assembleProduct($rawProduct),
$context->language
);
}
}
return $products_for_template;
}
public static function getProducsByIdBlock($id_block)
{
if (!$id_block){
return [];
}
$langId = Context::getContext()->language->id;
$sql = '
SELECT *, p.*
FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks_products` awl
LEFT JOIN `' . _DB_PREFIX_ . 'product` p
ON (p.`id_product` = awl.`id_product`)
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl
ON (p.`id_product` = pl.`id_product`
AND pl.`id_lang` = ' . (int) $langId . Shop::addSqlRestrictionOnLang('pl') . ')
WHERE awl.`id_block` = ' . (int) $id_block . '
ORDER BY awl.`position`';
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false);
return Product::getProductsProperties($langId, $result);
}
public static function exportJsonBlocks($filesManager)
{
$blocks = self::getBlocks(false, true);
@file_put_contents($filesManager->getJsonDirblocks(), json_encode($blocks, JSON_PRETTY_PRINT));
}
public static function importJsonBlocks($filesManager)
{
$data = json_decode($filesManager->getJsonBlocksPathFile(), true);
$languages = Language::getLanguages();
if ($data){
foreach ($data as $item){
$blockObj = new anHomeProductsBlocks();
$blockObj->special_id_block = $item['special_id_block'];
$blockObj->active = $item['active'];
$blockObj->show_sort = $item['show_sort'];
$blockObj->products_display = $item['products_display'];
$blockObj->id_category = $item['id_category'];
$blockObj->show_sub_cat = $item['show_sub_cat'];
$blockObj->position = $item['position'];
$blockObj->type = $item['type'];
if (isset($item['languages']) && is_array($item['languages'])) {
foreach ($item['languages'] as $key => $field) {
$langId = Language::getIdByIso($field['iso_code']);
$blockObj->title[$langId] = $field['title'];
$blockObj->text[$langId] = $field['text'];
$blockObj->link[$langId] = $field['link'];
}
}
foreach ($languages as $language) {
if (!isset($blockObj->title[$language['id_lang']])){
$blockObj->title[$language['id_lang']] = $item['title'];
}
if (!isset($blockObj->text[$language['id_lang']])){
$blockObj->text[$language['id_lang']] = $item['text'];
}
if (!isset($blockObj->link[$language['id_lang']])){
$blockObj->link[$language['id_lang']] = $item['link'];
}
}
$blockObj->save();
Db::getInstance()->insert('an_homeproducts_blocks_shop', [
'id_block' => (int) $blockObj->id,
'id_shop' => (int) Context::getContext()->shop->id
]);
}
}
}
public static function getCountBlocks()
{
$sql = '
SELECT count(*) FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks` sw
LEFT JOIN `' . _DB_PREFIX_ . 'an_homeproducts_blocks_lang` sl
ON (sw.`id_block` = sl.`id_block`
AND sl.`id_lang` = ' . (int) Context::getContext()->language->id . ')
';
if (Shop::isFeatureActive()) {
$sql .= ' WHERE sw.`id_block` IN (
SELECT sa.`id_block`
FROM `' . _DB_PREFIX_ . 'an_homeproducts_blocks_shop` sa
WHERE sa.id_shop IN (' . implode(', ', Shop::getContextListShopID()) . ')
)';
}
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
}
}