405 lines
15 KiB
PHP
405 lines
15 KiB
PHP
<?php
|
|
if (!defined('_PS_VERSION_')) {
|
|
exit;
|
|
}
|
|
|
|
use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever;
|
|
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
|
|
use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever;
|
|
use PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductPresenterFactory;
|
|
use PrestaShop\PrestaShop\Adapter\Product\ProductAssembler;
|
|
use PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductListingPresenter;
|
|
|
|
class Project_Pro_News extends Module
|
|
{
|
|
const CFG_CATEGORY_ID = 'PROJECT_PRO_NEWS_CATEGORY_ID';
|
|
const CFG_MAX_PRODUCTS = 'PROJECT_PRO_NEWS_MAX_PRODUCTS';
|
|
const CFG_TITLE = 'PROJECT_PRO_NEWS_TITLE';
|
|
const CFG_SUBTITLE = 'PROJECT_PRO_NEWS_SUBTITLE';
|
|
const CFG_BUTTON_LABEL = 'PROJECT_PRO_NEWS_BUTTON_LABEL';
|
|
const CFG_BUTTON_URL = 'PROJECT_PRO_NEWS_BUTTON_URL';
|
|
const CFG_PRICE_SUFFIX = 'PROJECT_PRO_NEWS_PRICE_SUFFIX';
|
|
|
|
public function __construct()
|
|
{
|
|
$this->name = 'project_pro_news';
|
|
$this->tab = 'front_office_features';
|
|
$this->version = '1.0.1';
|
|
$this->author = 'RomekDev';
|
|
$this->need_instance = 0;
|
|
$this->bootstrap = true;
|
|
|
|
parent::__construct();
|
|
|
|
$this->displayName = $this->l('Project Pro: News slider (category products)');
|
|
$this->description = $this->l('Shows products from selected category as a slider with configurable title, subtitle and button (multilanguage).');
|
|
|
|
$this->ps_versions_compliancy = ['min' => '1.7.0.0', 'max' => _PS_VERSION_];
|
|
}
|
|
|
|
public function install()
|
|
{
|
|
return parent::install()
|
|
&& $this->registerHook('displayHome')
|
|
&& $this->registerHook('displayHeader')
|
|
&& $this->setDefaultConfig();
|
|
}
|
|
|
|
public function uninstall()
|
|
{
|
|
$this->deleteConfig();
|
|
return parent::uninstall();
|
|
}
|
|
|
|
private function setDefaultConfig()
|
|
{
|
|
$langs = Language::getLanguages(false);
|
|
$title = [];
|
|
$subtitle = [];
|
|
$btn = [];
|
|
$suffix = [];
|
|
|
|
foreach ($langs as $lang) {
|
|
$id = (int)$lang['id_lang'];
|
|
$title[$id] = 'Nowości';
|
|
$subtitle[$id] = 'znajdź swoją inspirację';
|
|
$btn[$id] = 'Zobacz więcej';
|
|
$suffix[$id] = ''; // наприклад: '/m²'
|
|
}
|
|
|
|
Configuration::updateValue(self::CFG_CATEGORY_ID, 0);
|
|
Configuration::updateValue(self::CFG_MAX_PRODUCTS, 12);
|
|
Configuration::updateValue(self::CFG_BUTTON_URL, '');
|
|
|
|
Configuration::updateValue(self::CFG_TITLE, $title, true);
|
|
Configuration::updateValue(self::CFG_SUBTITLE, $subtitle, true);
|
|
Configuration::updateValue(self::CFG_BUTTON_LABEL, $btn, true);
|
|
Configuration::updateValue(self::CFG_PRICE_SUFFIX, $suffix, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
private function deleteConfig()
|
|
{
|
|
Configuration::deleteByName(self::CFG_CATEGORY_ID);
|
|
Configuration::deleteByName(self::CFG_MAX_PRODUCTS);
|
|
Configuration::deleteByName(self::CFG_TITLE);
|
|
Configuration::deleteByName(self::CFG_SUBTITLE);
|
|
Configuration::deleteByName(self::CFG_BUTTON_LABEL);
|
|
Configuration::deleteByName(self::CFG_BUTTON_URL);
|
|
Configuration::deleteByName(self::CFG_PRICE_SUFFIX);
|
|
}
|
|
|
|
public function getContent()
|
|
{
|
|
$output = '';
|
|
|
|
if (Tools::isSubmit('submitProjectProNews')) {
|
|
try {
|
|
$categoryId = (int)Tools::getValue(self::CFG_CATEGORY_ID);
|
|
$max = (int)Tools::getValue(self::CFG_MAX_PRODUCTS);
|
|
$buttonUrl = trim((string)Tools::getValue(self::CFG_BUTTON_URL));
|
|
|
|
if ($max <= 0) {
|
|
$max = 12;
|
|
}
|
|
|
|
$langs = Language::getLanguages(false);
|
|
$title = [];
|
|
$subtitle = [];
|
|
$btn = [];
|
|
$suffix = [];
|
|
|
|
foreach ($langs as $lang) {
|
|
$id = (int)$lang['id_lang'];
|
|
|
|
$title[$id] = (string)Tools::getValue(self::CFG_TITLE . '_' . $id);
|
|
$subtitle[$id] = (string)Tools::getValue(self::CFG_SUBTITLE . '_' . $id);
|
|
$btn[$id] = (string)Tools::getValue(self::CFG_BUTTON_LABEL . '_' . $id);
|
|
$suffix[$id] = (string)Tools::getValue(self::CFG_PRICE_SUFFIX . '_' . $id);
|
|
|
|
// на всяк випадок обрізаємо (щоб не вбити конфіг через дуже довгий текст)
|
|
$title[$id] = Tools::substr($title[$id], 0, 255);
|
|
$subtitle[$id] = Tools::substr($subtitle[$id], 0, 255);
|
|
$btn[$id] = Tools::substr($btn[$id], 0, 255);
|
|
$suffix[$id] = Tools::substr($suffix[$id], 0, 64);
|
|
}
|
|
|
|
if (!Configuration::updateValue(self::CFG_CATEGORY_ID, $categoryId)) {
|
|
throw new Exception('Cannot save category id');
|
|
}
|
|
if (!Configuration::updateValue(self::CFG_MAX_PRODUCTS, $max)) {
|
|
throw new Exception('Cannot save max products');
|
|
}
|
|
if (!Configuration::updateValue(self::CFG_BUTTON_URL, $buttonUrl)) {
|
|
throw new Exception('Cannot save button url');
|
|
}
|
|
|
|
if (!Configuration::updateValue(self::CFG_TITLE, $title, true)) {
|
|
throw new Exception('Cannot save title');
|
|
}
|
|
if (!Configuration::updateValue(self::CFG_SUBTITLE, $subtitle, true)) {
|
|
throw new Exception('Cannot save subtitle');
|
|
}
|
|
if (!Configuration::updateValue(self::CFG_BUTTON_LABEL, $btn, true)) {
|
|
throw new Exception('Cannot save button label');
|
|
}
|
|
if (!Configuration::updateValue(self::CFG_PRICE_SUFFIX, $suffix, true)) {
|
|
throw new Exception('Cannot save price suffix');
|
|
}
|
|
|
|
$output .= $this->displayConfirmation($this->l('Settings saved.'));
|
|
} catch (Exception $e) {
|
|
$output .= $this->displayError('Save error: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
return $output . $this->renderForm();
|
|
}
|
|
|
|
private function renderForm()
|
|
{
|
|
$defaultLang = (int)Configuration::get('PS_LANG_DEFAULT');
|
|
|
|
$categories = Category::getCategories($defaultLang, true, false);
|
|
$categoryOptions = $this->flattenCategoriesForSelect($categories);
|
|
|
|
$fieldsForm = [
|
|
'form' => [
|
|
'legend' => [
|
|
'title' => $this->l('Project Pro News: settings'),
|
|
'icon' => 'icon-cogs',
|
|
],
|
|
'input' => [
|
|
[
|
|
'type' => 'select',
|
|
'label' => $this->l('Category (source products)'),
|
|
'name' => self::CFG_CATEGORY_ID,
|
|
'options' => [
|
|
'query' => $categoryOptions,
|
|
'id' => 'id',
|
|
'name' => 'name',
|
|
],
|
|
'required' => true,
|
|
'desc' => $this->l('Select category that contains the products (e.g. Nowości).'),
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Max products'),
|
|
'name' => self::CFG_MAX_PRODUCTS,
|
|
'class' => 'fixed-width-sm',
|
|
'required' => true,
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Title'),
|
|
'name' => self::CFG_TITLE,
|
|
'lang' => true,
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Subtitle'),
|
|
'name' => self::CFG_SUBTITLE,
|
|
'lang' => true,
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Button label'),
|
|
'name' => self::CFG_BUTTON_LABEL,
|
|
'lang' => true,
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Button URL'),
|
|
'name' => self::CFG_BUTTON_URL,
|
|
'desc' => $this->l('Leave empty to link to selected category automatically.'),
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Price suffix (optional)'),
|
|
'name' => self::CFG_PRICE_SUFFIX,
|
|
'lang' => true,
|
|
'desc' => $this->l('Example: /m²'),
|
|
],
|
|
],
|
|
'submit' => [
|
|
'title' => $this->l('Save'),
|
|
'name' => 'submitProjectProNews',
|
|
],
|
|
],
|
|
];
|
|
|
|
$helper = new HelperForm();
|
|
$helper->show_toolbar = false;
|
|
$helper->table = $this->table;
|
|
$helper->module = $this;
|
|
$helper->default_form_language = $defaultLang;
|
|
$helper->allow_employee_form_lang = (int)Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG');
|
|
$helper->identifier = $this->identifier;
|
|
$helper->submit_action = 'submitProjectProNews';
|
|
$helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
|
|
$helper->token = Tools::getAdminTokenLite('AdminModules');
|
|
|
|
$helper->languages = $this->context->controller->getLanguages();
|
|
$helper->id_language = (int)$this->context->language->id;
|
|
|
|
$helper->fields_value[self::CFG_CATEGORY_ID] = (int)Configuration::get(self::CFG_CATEGORY_ID);
|
|
$helper->fields_value[self::CFG_MAX_PRODUCTS] = (int)Configuration::get(self::CFG_MAX_PRODUCTS);
|
|
$helper->fields_value[self::CFG_BUTTON_URL] = (string)Configuration::get(self::CFG_BUTTON_URL);
|
|
|
|
$langs = Language::getLanguages(false);
|
|
foreach ($langs as $lang) {
|
|
$id = (int)$lang['id_lang'];
|
|
$helper->fields_value[self::CFG_TITLE][$id] = (string)Configuration::get(self::CFG_TITLE, $id);
|
|
$helper->fields_value[self::CFG_SUBTITLE][$id] = (string)Configuration::get(self::CFG_SUBTITLE, $id);
|
|
$helper->fields_value[self::CFG_BUTTON_LABEL][$id] = (string)Configuration::get(self::CFG_BUTTON_LABEL, $id);
|
|
$helper->fields_value[self::CFG_PRICE_SUFFIX][$id] = (string)Configuration::get(self::CFG_PRICE_SUFFIX, $id);
|
|
}
|
|
|
|
return $helper->generateForm([$fieldsForm]);
|
|
}
|
|
|
|
private function flattenCategoriesForSelect($categoriesTree, $depth = 0, &$out = [])
|
|
{
|
|
foreach ($categoriesTree as $node) {
|
|
if (!isset($node['id_category'], $node['name'])) {
|
|
continue;
|
|
}
|
|
$prefix = str_repeat('—', max(0, $depth));
|
|
$out[] = [
|
|
'id' => (int)$node['id_category'],
|
|
'name' => trim($prefix . ' ' . $node['name']),
|
|
];
|
|
if (!empty($node['children'])) {
|
|
$this->flattenCategoriesForSelect($node['children'], $depth + 1, $out);
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function hookDisplayHeader()
|
|
{
|
|
$this->context->controller->registerStylesheet(
|
|
'project_pro_news_swiper_css',
|
|
'modules/' . $this->name . '/views/lib/swiper/swiper-bundle.min.css',
|
|
['media' => 'all', 'priority' => 150]
|
|
);
|
|
|
|
$this->context->controller->registerStylesheet(
|
|
'project_pro_news_css',
|
|
'modules/' . $this->name . '/views/css/project_pro_news.css',
|
|
['media' => 'all', 'priority' => 151]
|
|
);
|
|
|
|
$this->context->controller->registerJavascript(
|
|
'project_pro_news_swiper_js',
|
|
'modules/' . $this->name . '/views/lib/swiper/swiper-bundle.min.js',
|
|
['position' => 'bottom', 'priority' => 150]
|
|
);
|
|
|
|
$this->context->controller->registerJavascript(
|
|
'project_pro_news_js',
|
|
'modules/' . $this->name . '/views/js/project_pro_news.js',
|
|
['position' => 'bottom', 'priority' => 151]
|
|
);
|
|
}
|
|
|
|
public function hookDisplayHome($params)
|
|
{
|
|
return $this->renderWidget('displayHome', []);
|
|
}
|
|
|
|
public function renderWidget($hookName = null, array $configuration = [])
|
|
{
|
|
$categoryId = (int)Configuration::get(self::CFG_CATEGORY_ID);
|
|
$max = (int)Configuration::get(self::CFG_MAX_PRODUCTS);
|
|
if ($max <= 0) {
|
|
$max = 12;
|
|
}
|
|
|
|
if ($categoryId <= 0) {
|
|
return '';
|
|
}
|
|
|
|
$idLang = (int)$this->context->language->id;
|
|
|
|
$title = (string)Configuration::get(self::CFG_TITLE, $idLang);
|
|
$subtitle = (string)Configuration::get(self::CFG_SUBTITLE, $idLang);
|
|
$buttonLabel = (string)Configuration::get(self::CFG_BUTTON_LABEL, $idLang);
|
|
$buttonUrl = trim((string)Configuration::get(self::CFG_BUTTON_URL));
|
|
$priceSuffix = (string)Configuration::get(self::CFG_PRICE_SUFFIX, $idLang);
|
|
|
|
$category = new Category($categoryId, $idLang);
|
|
if (!Validate::isLoadedObject($category)) {
|
|
return '';
|
|
}
|
|
|
|
if ($buttonUrl === '') {
|
|
$buttonUrl = $this->context->link->getCategoryLink($category);
|
|
}
|
|
|
|
$products = $this->getCategoryProductsPresented($categoryId, $max);
|
|
|
|
$this->context->smarty->assign([
|
|
'ppn_title' => $title,
|
|
'ppn_subtitle' => $subtitle,
|
|
'ppn_button_label' => $buttonLabel,
|
|
'ppn_button_url' => $buttonUrl,
|
|
'ppn_price_suffix' => $priceSuffix,
|
|
'ppn_products' => $products,
|
|
]);
|
|
|
|
return $this->fetch('module:' . $this->name . '/views/templates/hook/project_pro_news.tpl');
|
|
}
|
|
|
|
public function getWidgetVariables($hookName = null, array $configuration = [])
|
|
{
|
|
return [];
|
|
}
|
|
|
|
private function getCategoryProductsPresented($categoryId, $limit)
|
|
{
|
|
$idLang = (int)$this->context->language->id;
|
|
|
|
$rawProducts = Category::getProducts(
|
|
(int)$categoryId,
|
|
$idLang,
|
|
1,
|
|
(int)$limit,
|
|
'position',
|
|
'asc'
|
|
);
|
|
|
|
if (empty($rawProducts)) {
|
|
return [];
|
|
}
|
|
|
|
$assembler = new ProductAssembler($this->context);
|
|
$presenterFactory = new ProductPresenterFactory($this->context);
|
|
|
|
$presentationSettings = $presenterFactory->getPresentationSettings();
|
|
$imageRetriever = new ImageRetriever($this->context->link);
|
|
$priceFormatter = new PriceFormatter();
|
|
$colorsRetriever = new ProductColorsRetriever();
|
|
|
|
$listingPresenter = new ProductListingPresenter(
|
|
$imageRetriever,
|
|
$this->context->link,
|
|
$priceFormatter,
|
|
$colorsRetriever,
|
|
$this->getTranslator()
|
|
);
|
|
|
|
$products = [];
|
|
foreach ($rawProducts as $raw) {
|
|
$assembled = $assembler->assembleProduct($raw);
|
|
$products[] = $listingPresenter->present(
|
|
$presentationSettings,
|
|
$assembled,
|
|
$this->context->language
|
|
);
|
|
}
|
|
|
|
return $products;
|
|
}
|
|
} |