feat: new settings and mainpage blocks
This commit is contained in:
@@ -361,13 +361,11 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
'module_tgshop_owner_notification_template' => 'telegram.owner_notification_template',
|
||||
'module_tgshop_text_order_created_success' => 'texts.text_order_created_success',
|
||||
'module_tgshop_enable_store' => 'store.enable_store',
|
||||
'module_tgshop_mainpage_products' => 'store.mainpage_products',
|
||||
'module_tgshop_yandex_metrika' => 'metrics.yandex_metrika_counter',
|
||||
'module_tgshop_customer_notification_template' => 'telegram.customer_notification_template',
|
||||
'module_tgshop_feature_vouchers' => 'store.feature_vouchers',
|
||||
'module_tgshop_order_default_status_id' => 'orders.order_default_status_id',
|
||||
'module_tgshop_feature_coupons' => 'store.feature_coupons',
|
||||
'module_tgshop_mainpage_categories' => 'store.mainpage_categories',
|
||||
'module_tgshop_text_no_more_products' => 'texts.text_no_more_products',
|
||||
'module_tgshop_text_empty_cart' => 'texts.text_empty_cart',
|
||||
];
|
||||
|
||||
@@ -7,38 +7,6 @@ $_['text_module'] = 'Модули';
|
||||
$_['text_success'] = 'Настройки успешно изменены!';
|
||||
$_['text_edit'] = 'Настройки';
|
||||
|
||||
$_['tab_telegram'] = 'Telegram';
|
||||
$_['tab_statistics'] = 'Статистика';
|
||||
$_['tab_shop'] = 'Магазин';
|
||||
$_['tab_orders'] = 'Заказы';
|
||||
$_['tab_texts'] = 'Тексты';
|
||||
|
||||
$_['lbl_module_tgshop_status'] = 'Статус';
|
||||
$_['lbl_module_tgshop_app_name'] = 'Название приложения';
|
||||
$_['lbl_module_tgshop_app_icon'] = 'Иконка приложения';
|
||||
$_['lbl_module_tgshop_bot_token'] = 'Telegram Bot Token';
|
||||
$_['lbl_module_tgshop_chat_id'] = 'Chat ID для уведомлений';
|
||||
$_['lbl_module_tgshop_owner_notification_template'] = 'Шаблон уведомления о новом заказе владельцу';
|
||||
$_['lbl_module_tgshop_customer_notification_template'] = 'Шаблон уведомления о новом заказе покупателю';
|
||||
$_['lbl_module_tgshop_yandex_metrika'] = 'Код счётчика Яндекс Метрики';
|
||||
$_['lbl_module_tgshop_theme_light'] = 'Светлая тема';
|
||||
$_['lbl_module_tgshop_theme_dark'] = 'Тёмная тема';
|
||||
$_['lbl_module_tgshop_mainpage_products'] = 'Товары на главной';
|
||||
$_['lbl_module_tgshop_featured_products'] = 'Избранные товары';
|
||||
$_['lbl_module_tgshop_order_customer_group_id'] = 'Группа покупателей';
|
||||
$_['lbl_module_tgshop_order_default_status_id'] = 'Статус заказов';
|
||||
$_['lbl_module_tgshop_mini_app_url'] = 'Ссылка на Telegram Mini App';
|
||||
$_['lbl_module_tgshop_mainpage_categories'] = 'Категории на главной';
|
||||
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
|
||||
$_['lbl_module_tgshop_enable_store'] = 'Разрешить покупки';
|
||||
$_['lbl_module_tgshop_feature_coupons'] = 'Промокоды';
|
||||
$_['lbl_module_tgshop_feature_vouchers'] = 'Подарочные сертификаты';
|
||||
$_['lbl_module_tgshop_home_banner_id'] = 'Баннер на главной';
|
||||
$_['lbl_module_tgshop_debug'] = 'Режим разработчика';
|
||||
$_['lbl_module_tgshop_text_no_more_products'] = 'Текст в конце списка товаров';
|
||||
$_['lbl_module_tgshop_text_empty_cart'] = 'Текст пустой корзины';
|
||||
$_['lbl_module_tgshop_text_order_created_success'] = 'Текст для успешного заказа';
|
||||
|
||||
// Entry
|
||||
$_['entry_status'] = 'Статус';
|
||||
|
||||
|
||||
@@ -33,18 +33,9 @@
|
||||
order_statuses: '{{ order_statuses | json_encode }}',
|
||||
};
|
||||
</script>
|
||||
<div id="app">App Loading...</div>
|
||||
<div id="app" class="telecart-admin-app">App Loading...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ footer }}
|
||||
|
||||
<script>
|
||||
const $element = $('#thumb-image-module_tgshop_app_icon');
|
||||
$('#button-clear').on('click', function () {
|
||||
$element.find('img').attr('src', $element.find('img').attr('data-placeholder'));
|
||||
$element.parent().find('input').val('');
|
||||
$element.popover('destroy');
|
||||
});
|
||||
</script>
|
||||
@@ -5,11 +5,13 @@ use App\ApplicationFactory;
|
||||
use Cart\Cart;
|
||||
use Cart\Currency;
|
||||
use Cart\Tax;
|
||||
use Openguru\OpenCartFramework\Http\Response as HttpResponse;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageTool;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\Logger\LoggerInterface;
|
||||
use Openguru\OpenCartFramework\Logger\OpenCartLogAdapter;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
|
||||
$sysLibPath = rtrim(DIR_SYSTEM, '/') . '/library/oc_telegram_shop';
|
||||
$basePath = rtrim(DIR_APPLICATION, '/') . '/..';
|
||||
@@ -23,6 +25,7 @@ if (is_readable($sysLibPath . '/oc_telegram_shop.phar')) {
|
||||
|
||||
/**
|
||||
* @property Config $config
|
||||
* @property Log $log
|
||||
*/
|
||||
class ControllerExtensionTgshopHandle extends Controller
|
||||
{
|
||||
@@ -32,98 +35,79 @@ class ControllerExtensionTgshopHandle extends Controller
|
||||
|
||||
$this->load->model('catalog/product');
|
||||
$this->load->model('checkout/order');
|
||||
$this->load->model('setting/setting');
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$this->session->data['language'] = $this->config->get('config_language');
|
||||
try {
|
||||
$this->session->data['language'] = $this->config->get('config_language');
|
||||
|
||||
$appDebug = filter_var($this->config->get('module_tgshop_debug'), FILTER_VALIDATE_BOOLEAN);
|
||||
$json = $this->model_setting_setting->getSetting('module_telecart');
|
||||
if (! isset($json['module_telecart_settings'])) {
|
||||
$json['module_telecart_settings'] = [];
|
||||
}
|
||||
|
||||
$app = ApplicationFactory::create([
|
||||
'app_enabled' => filter_var($this->config->get('module_tgshop_status'), FILTER_VALIDATE_BOOLEAN),
|
||||
'app_debug' => $appDebug,
|
||||
'oc_config_tax' => $this->config->get('config_tax'),
|
||||
'oc_default_currency' => $this->config->get('config_currency'),
|
||||
'oc_customer_group_id' => $this->config->get('config_customer_group_id'),
|
||||
// ID магазина, для которого будут создаваться заказы из Телеграм
|
||||
'oc_store_id' => 0,
|
||||
// Название магазина, для которого будут создаваться заказы из Телеграм
|
||||
'oc_store_name' => $this->config->get('config_name'),
|
||||
// ID статуса, с которым будут создаваться заказы через Телеграм по умолчанию.
|
||||
'oc_order_status_id' => (int) $this->config->get('module_tgshop_order_default_status_id'),
|
||||
'timezone' => $this->config->get('config_timezone', 'UTC'),
|
||||
'language_id' => (int) $this->config->get('config_language_id'),
|
||||
'shop_base_url' => HTTPS_SERVER,
|
||||
'dir_image' => DIR_IMAGE,
|
||||
'app_name' => $this->config->get('module_tgshop_app_name'),
|
||||
'app_icon' => $this->config->get('module_tgshop_app_icon'),
|
||||
'theme_light' => $this->config->get('module_tgshop_theme_light'),
|
||||
'theme_dark' => $this->config->get('module_tgshop_theme_dark'),
|
||||
'mainpage_products' => $this->config->get('module_tgshop_mainpage_products'),
|
||||
'featured_products' => (array) $this->config->get('module_tgshop_featured_products'),
|
||||
'mainpage_categories' => $this->config->get('module_tgshop_mainpage_categories'),
|
||||
'featured_categories' => (array) $this->config->get('module_tgshop_featured_categories'),
|
||||
'store_enabled' => filter_var($this->config->get('module_tgshop_enable_store'), FILTER_VALIDATE_BOOLEAN),
|
||||
'base_url' => HTTPS_SERVER,
|
||||
'ya_metrika_counter' => trim($this->config->get('module_tgshop_yandex_metrika')),
|
||||
'ya_metrika_enabled' => ! empty(trim($this->config->get('module_tgshop_yandex_metrika'))),
|
||||
'telegram' => [
|
||||
'bot_token' => $this->config->get('module_tgshop_bot_token'),
|
||||
'chat_id' => $this->config->get('module_tgshop_chat_id'),
|
||||
'owner_notification_template' => $this->config->get('module_tgshop_owner_notification_template'),
|
||||
'customer_notification_template' => $this->config->get('module_tgshop_customer_notification_template'),
|
||||
],
|
||||
'db' => [
|
||||
'host' => DB_HOSTNAME,
|
||||
'database' => DB_DATABASE,
|
||||
'username' => DB_USERNAME,
|
||||
'password' => DB_PASSWORD,
|
||||
'prefix' => DB_PREFIX,
|
||||
'port' => DB_PORT,
|
||||
],
|
||||
'logs' => [
|
||||
'path' => DIR_LOGS,
|
||||
],
|
||||
'cache_categories_main' => 60 * 10,
|
||||
'cache_products_main' => 60 * 10,
|
||||
'feature_coupons' => filter_var(
|
||||
$this->config->get('module_tgshop_feature_coupons'),
|
||||
FILTER_VALIDATE_BOOLEAN
|
||||
),
|
||||
'feature_vouchers' => filter_var(
|
||||
$this->config->get('module_tgshop_feature_vouchers'),
|
||||
FILTER_VALIDATE_BOOLEAN
|
||||
),
|
||||
'mainpage_slider' => $this->safeJsonDecode($this->config->get('module_tgshop_mainpage_slider'), []),
|
||||
'texts' => [
|
||||
'no_more_products' => $this->config->get('module_tgshop_text_no_more_products'),
|
||||
'empty_cart' => $this->config->get('module_tgshop_text_empty_cart'),
|
||||
'order_created_success' => $this->config->get('module_tgshop_text_order_created_success'),
|
||||
],
|
||||
]);
|
||||
$items = Arr::mergeArraysRecursively($json['module_telecart_settings'], [
|
||||
'app' => [
|
||||
'shop_base_url' => HTTPS_SERVER, // for catalog: HTTPS_SERVER, for admin: HTTPS_CATALOG
|
||||
'language_id' => (int) $this->config->get('config_language_id'),
|
||||
],
|
||||
'logs' => [
|
||||
'path' => DIR_LOGS,
|
||||
],
|
||||
'database' => [
|
||||
'host' => DB_HOSTNAME,
|
||||
'database' => DB_DATABASE,
|
||||
'username' => DB_USERNAME,
|
||||
'password' => DB_PASSWORD,
|
||||
'prefix' => DB_PREFIX,
|
||||
'port' => (int) DB_PORT,
|
||||
],
|
||||
'store' => [
|
||||
'oc_store_id' => 0,
|
||||
'oc_default_currency' => $this->config->get('config_currency'),
|
||||
'oc_config_tax' => filter_var($this->config->get('config_tax'), FILTER_VALIDATE_BOOLEAN),
|
||||
],
|
||||
'orders' => [
|
||||
'oc_customer_group_id' => (int) $this->config->get('config_customer_group_id'),
|
||||
],
|
||||
]);
|
||||
|
||||
$app->bind(OcModelCatalogProductAdapter::class, function () {
|
||||
return new OcModelCatalogProductAdapter($this->model_catalog_product);
|
||||
});
|
||||
$appDebug = Arr::get($items, 'app.app_debug');
|
||||
|
||||
$app->bind(Url::class, fn() => $this->url);
|
||||
$app->bind(Currency::class, fn() => $this->currency);
|
||||
$app->bind(Tax::class, fn() => $this->tax);
|
||||
$app->bind(ImageToolInterface::class, fn() => new ImageTool(DIR_IMAGE, HTTPS_SERVER));
|
||||
$app->bind(Cart::class, fn() => $this->cart);
|
||||
$app->bind(OcRegistryDecorator::class, fn() => new OcRegistryDecorator($this->registry));
|
||||
$app->singleton(Log::class, fn() => $this->log);
|
||||
$app = ApplicationFactory::create($items);
|
||||
|
||||
$app
|
||||
->withLogger(
|
||||
fn() => new OpenCartLogAdapter(
|
||||
$this->log,
|
||||
'TeleCart',
|
||||
$appDebug ? LoggerInterface::LEVEL_DEBUG : LoggerInterface::LEVEL_WARNING,
|
||||
$app->bind(OcModelCatalogProductAdapter::class, function () {
|
||||
return new OcModelCatalogProductAdapter($this->model_catalog_product);
|
||||
});
|
||||
|
||||
$app->bind(Url::class, fn() => $this->url);
|
||||
$app->bind(Currency::class, fn() => $this->currency);
|
||||
$app->bind(Tax::class, fn() => $this->tax);
|
||||
$app->bind(ImageToolInterface::class, fn() => new ImageTool(DIR_IMAGE, HTTPS_SERVER));
|
||||
$app->bind(Cart::class, fn() => $this->cart);
|
||||
$app->bind(OcRegistryDecorator::class, fn() => new OcRegistryDecorator($this->registry));
|
||||
$app->singleton(Log::class, fn() => $this->log);
|
||||
|
||||
$app
|
||||
->withLogger(
|
||||
fn() => new OpenCartLogAdapter(
|
||||
$this->log,
|
||||
'TeleCart',
|
||||
$appDebug ? LoggerInterface::LEVEL_DEBUG : LoggerInterface::LEVEL_WARNING,
|
||||
)
|
||||
)
|
||||
)
|
||||
->bootAndHandleRequest();
|
||||
->bootAndHandleRequest();
|
||||
} catch (Exception $e) {
|
||||
$logger = new OpenCartLogAdapter($this->log, 'TeleCart');
|
||||
$logger->logException($e);
|
||||
http_response_code(HttpResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'error' => 'Server Error.',
|
||||
], JSON_THROW_ON_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
function extractPureJs($input)
|
||||
@@ -153,15 +137,20 @@ class ControllerExtensionTgshopHandle extends Controller
|
||||
|
||||
public function ya_metrika(): void
|
||||
{
|
||||
$raw = html_entity_decode($this->config->get('module_tgshop_yandex_metrika'), ENT_QUOTES | ENT_HTML5);
|
||||
$raw = $this->extractPureJs($raw);
|
||||
$json = $this->model_setting_setting->getSetting('module_telecart');
|
||||
if (isset($json['module_telecart_settings'])) {
|
||||
$raw = Arr::get($json, 'module_telecart_settings.metrics.yandex_metrika_counter');
|
||||
$raw = $this->extractPureJs($raw);
|
||||
|
||||
http_response_code(200);
|
||||
header('Content-Type: application/javascript');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, POST');
|
||||
header('Access-Control-Allow-Headers: Content-Type, Authorization');
|
||||
header('Access-Control-Allow-Credentials: true');
|
||||
echo $raw;
|
||||
http_response_code(200);
|
||||
header('Content-Type: application/javascript');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, POST');
|
||||
header('Access-Control-Allow-Headers: Content-Type, Authorization');
|
||||
header('Access-Control-Allow-Credentials: true');
|
||||
echo $raw;
|
||||
} else {
|
||||
http_response_code(404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class ApplicationFactory
|
||||
{
|
||||
public static function create(array $settings): Application
|
||||
{
|
||||
$defaultConfig = require __DIR__ . '/config.php';
|
||||
$defaultConfig = require __DIR__ . '/../src/config.php';
|
||||
$routes = require __DIR__ . '/routes.php';
|
||||
|
||||
$merged = Arr::mergeArraysRecursively($defaultConfig, $settings);
|
||||
|
||||
@@ -51,6 +51,7 @@ class SettingsHandler
|
||||
'orders',
|
||||
'texts',
|
||||
'sliders',
|
||||
'mainpage_blocks',
|
||||
]);
|
||||
|
||||
return new JsonResponse(compact('data'));
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Handlers/StatsHandler.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Handlers/StatsHandler.php
Normal file → Executable file
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'app' => [
|
||||
'app_enabled' => true,
|
||||
'app_name' => 'Telecart',
|
||||
'app_icon' => null,
|
||||
"theme_light" => "light",
|
||||
"theme_dark" => "dark",
|
||||
"app_debug" => false
|
||||
],
|
||||
|
||||
'telegram' => [
|
||||
"bot_token" => "",
|
||||
"chat_id" => null,
|
||||
"owner_notification_template" => <<<TEXT
|
||||
*Новый заказ \#{order_id}* в магазине *{store_name}*
|
||||
|
||||
*Покупатель:* {customer}
|
||||
*Email:* {email}
|
||||
*Телефон:* {phone}
|
||||
*IP:* {ip}
|
||||
|
||||
*Адрес доставки:*
|
||||
{address}
|
||||
|
||||
*Комментарий:*
|
||||
{comment}
|
||||
|
||||
*Сумма заказа:* {total}
|
||||
*Дата оформления:* {created_at}
|
||||
TEXT,
|
||||
"customer_notification_template" => <<<TEXT
|
||||
Спасибо за Ваш заказ в магазине *{store_name}*
|
||||
|
||||
*Номер заказа* \#{order_id}
|
||||
*Сумма заказа:* {total}
|
||||
*Дата оформления:* {created_at}
|
||||
|
||||
Мы свяжемся с вами при необходимости\.
|
||||
Хорошего дня\!
|
||||
TEXT,
|
||||
"mini_app_url" => "",
|
||||
],
|
||||
|
||||
"metrics" => [
|
||||
"yandex_metrika_enabled" => false,
|
||||
"yandex_metrika_counter" => "",
|
||||
],
|
||||
|
||||
'store' => [
|
||||
'enable_store' => true,
|
||||
'mainpage_products' => 'most_viewed',
|
||||
'featured_products' => [],
|
||||
'mainpage_categories' => 'latest10',
|
||||
'featured_categories' => [],
|
||||
'feature_coupons' => true,
|
||||
'feature_vouchers' => true,
|
||||
],
|
||||
|
||||
'texts' => [
|
||||
'text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
||||
'text_empty_cart' => 'Ваша корзина пуста.',
|
||||
'text_order_created_success' => 'Ваш заказ успешно оформлен и будет обработан в ближайшее время.'
|
||||
],
|
||||
|
||||
'orders' => [
|
||||
'order_default_status_id' => 1,
|
||||
],
|
||||
|
||||
'sliders' => [
|
||||
'mainpage_slider' => [
|
||||
'is_enabled' => false,
|
||||
'effect' => 'slide',
|
||||
'pagination' => true,
|
||||
'scrollbar' => false,
|
||||
'free_mode' => false,
|
||||
'space_between' => 30,
|
||||
'autoplay' => false,
|
||||
'loop' => false,
|
||||
'slides' => [],
|
||||
],
|
||||
],
|
||||
];
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Config/SettingsInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Config/SettingsInterface.php
Normal file → Executable file
@@ -10,7 +10,6 @@ final class ConfigDTO
|
||||
private StoreDTO $store;
|
||||
private OrdersDTO $orders;
|
||||
private TextsDTO $texts;
|
||||
private SlidersDTO $sliders;
|
||||
private DatabaseDTO $database;
|
||||
private LogsDTO $logs;
|
||||
|
||||
@@ -21,7 +20,6 @@ final class ConfigDTO
|
||||
StoreDTO $store,
|
||||
OrdersDTO $orders,
|
||||
TextsDTO $texts,
|
||||
SlidersDTO $sliders,
|
||||
DatabaseDTO $database,
|
||||
LogsDTO $logs
|
||||
) {
|
||||
@@ -31,7 +29,6 @@ final class ConfigDTO
|
||||
$this->store = $store;
|
||||
$this->orders = $orders;
|
||||
$this->texts = $texts;
|
||||
$this->sliders = $sliders;
|
||||
$this->database = $database;
|
||||
$this->logs = $logs;
|
||||
}
|
||||
@@ -66,11 +63,6 @@ final class ConfigDTO
|
||||
return $this->texts;
|
||||
}
|
||||
|
||||
public function getSliders(): SlidersDTO
|
||||
{
|
||||
return $this->sliders;
|
||||
}
|
||||
|
||||
public function getDatabase(): DatabaseDTO
|
||||
{
|
||||
return $this->database;
|
||||
@@ -89,7 +81,6 @@ final class ConfigDTO
|
||||
'logs' => $this->logs->toArray(),
|
||||
'metrics' => $this->metrics->toArray(),
|
||||
'orders' => $this->orders->toArray(),
|
||||
'sliders' => $this->sliders->toArray(),
|
||||
'store' => $this->store->toArray(),
|
||||
'telegram' => $this->telegram->toArray(),
|
||||
'texts' => $this->texts->toArray(),
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO\Settings\MainpageSlider;
|
||||
|
||||
final class LinkDTO
|
||||
{
|
||||
private string $type;
|
||||
private ?LinkValueDTO $value;
|
||||
|
||||
public function __construct(
|
||||
string $type,
|
||||
?LinkValueDTO $value
|
||||
) {
|
||||
$this->type = $type;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getValue(): ?LinkValueDTO
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$result = [
|
||||
'type' => $this->type,
|
||||
'value' => null,
|
||||
];
|
||||
|
||||
if ($this->value !== null) {
|
||||
$result['value'] = $this->value->toArray();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO\Settings\MainpageSlider;
|
||||
|
||||
final class LinkType
|
||||
{
|
||||
public const NONE = 'none';
|
||||
public const CATEGORY = 'category';
|
||||
public const PRODUCT = 'product';
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO\Settings\MainpageSlider;
|
||||
|
||||
final class LinkValueDTO
|
||||
{
|
||||
private ?int $categoryId;
|
||||
private ?string $name;
|
||||
private ?int $productId;
|
||||
|
||||
public function __construct(
|
||||
?int $categoryId = null,
|
||||
?string $name = null,
|
||||
?int $productId = null
|
||||
) {
|
||||
$this->categoryId = $categoryId;
|
||||
$this->name = $name;
|
||||
$this->productId = $productId;
|
||||
}
|
||||
|
||||
public function getCategoryId(): ?int
|
||||
{
|
||||
return $this->categoryId;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getProductId(): ?int
|
||||
{
|
||||
return $this->productId;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
if ($this->categoryId !== null) {
|
||||
$result['category_id'] = $this->categoryId;
|
||||
}
|
||||
|
||||
if ($this->name !== null) {
|
||||
$result['name'] = $this->name;
|
||||
}
|
||||
|
||||
if ($this->productId !== null) {
|
||||
$result['product_id'] = $this->productId;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO\Settings\MainpageSlider;
|
||||
|
||||
final class MainpageSliderDTO
|
||||
{
|
||||
private bool $isEnabled;
|
||||
private string $effect;
|
||||
private bool $pagination;
|
||||
private bool $scrollbar;
|
||||
private bool $freeMode;
|
||||
private int $spaceBetween;
|
||||
private bool $autoplay;
|
||||
private bool $loop;
|
||||
/** @var SlideDTO[] */
|
||||
private array $slides;
|
||||
|
||||
/**
|
||||
* @param SlideDTO[] $slides
|
||||
*/
|
||||
public function __construct(
|
||||
bool $isEnabled,
|
||||
string $effect,
|
||||
bool $pagination,
|
||||
bool $scrollbar,
|
||||
bool $freeMode,
|
||||
int $spaceBetween,
|
||||
bool $autoplay,
|
||||
bool $loop,
|
||||
array $slides
|
||||
) {
|
||||
$this->isEnabled = $isEnabled;
|
||||
$this->effect = $effect;
|
||||
$this->pagination = $pagination;
|
||||
$this->scrollbar = $scrollbar;
|
||||
$this->freeMode = $freeMode;
|
||||
$this->spaceBetween = $spaceBetween;
|
||||
$this->autoplay = $autoplay;
|
||||
$this->loop = $loop;
|
||||
$this->slides = $slides;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->isEnabled;
|
||||
}
|
||||
|
||||
public function getEffect(): string
|
||||
{
|
||||
return $this->effect;
|
||||
}
|
||||
|
||||
public function isPagination(): bool
|
||||
{
|
||||
return $this->pagination;
|
||||
}
|
||||
|
||||
public function isScrollbar(): bool
|
||||
{
|
||||
return $this->scrollbar;
|
||||
}
|
||||
|
||||
public function isFreeMode(): bool
|
||||
{
|
||||
return $this->freeMode;
|
||||
}
|
||||
|
||||
public function getSpaceBetween(): int
|
||||
{
|
||||
return $this->spaceBetween;
|
||||
}
|
||||
|
||||
public function isAutoplay(): bool
|
||||
{
|
||||
return $this->autoplay;
|
||||
}
|
||||
|
||||
public function isLoop(): bool
|
||||
{
|
||||
return $this->loop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SlideDTO[]
|
||||
*/
|
||||
public function getSlides(): array
|
||||
{
|
||||
return $this->slides;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$slides = [];
|
||||
foreach ($this->slides as $slide) {
|
||||
$slides[] = $slide->toArray();
|
||||
}
|
||||
|
||||
return [
|
||||
'is_enabled' => $this->isEnabled,
|
||||
'effect' => $this->effect,
|
||||
'pagination' => $this->pagination,
|
||||
'scrollbar' => $this->scrollbar,
|
||||
'free_mode' => $this->freeMode,
|
||||
'space_between' => $this->spaceBetween,
|
||||
'autoplay' => $this->autoplay,
|
||||
'loop' => $this->loop,
|
||||
'slides' => $slides,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO\Settings\MainpageSlider;
|
||||
|
||||
final class SlideDTO
|
||||
{
|
||||
private string $title;
|
||||
private LinkDTO $link;
|
||||
private string $image;
|
||||
|
||||
public function __construct(
|
||||
string $title,
|
||||
LinkDTO $link,
|
||||
string $image
|
||||
) {
|
||||
$this->title = $title;
|
||||
$this->link = $link;
|
||||
$this->image = $image;
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function getLink(): LinkDTO
|
||||
{
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
public function getImage(): string
|
||||
{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'title' => $this->title,
|
||||
'link' => $this->link->toArray(),
|
||||
'image' => $this->image,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO\Settings;
|
||||
|
||||
use App\DTO\Settings\MainpageSlider\MainpageSliderDTO;
|
||||
|
||||
final class SlidersDTO
|
||||
{
|
||||
private MainpageSliderDTO $mainpageSlider;
|
||||
|
||||
public function __construct(MainpageSliderDTO $mainpageSlider)
|
||||
{
|
||||
$this->mainpageSlider = $mainpageSlider;
|
||||
}
|
||||
|
||||
public function getMainpageSlider(): MainpageSliderDTO
|
||||
{
|
||||
return $this->mainpageSlider;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'mainpage_slider' => $this->mainpageSlider->toArray(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,28 +5,14 @@ namespace App\DTO\Settings;
|
||||
final class StoreDTO
|
||||
{
|
||||
private bool $enableStore;
|
||||
private string $mainpageProducts;
|
||||
/** @var int[] */
|
||||
private array $featuredProducts;
|
||||
private string $mainpageCategories;
|
||||
/** @var int[] */
|
||||
private array $featuredCategories;
|
||||
private bool $featureCoupons;
|
||||
private bool $featureVouchers;
|
||||
private string $ocDefaultCurrency;
|
||||
private bool $ocConfigTax;
|
||||
private int $ocStoreId;
|
||||
|
||||
/**
|
||||
* @param int[] $featuredProducts
|
||||
* @param int[] $featuredCategories
|
||||
*/
|
||||
public function __construct(
|
||||
bool $enableStore,
|
||||
string $mainpageProducts,
|
||||
array $featuredProducts,
|
||||
string $mainpageCategories,
|
||||
array $featuredCategories,
|
||||
bool $featureCoupons,
|
||||
bool $featureVouchers,
|
||||
string $ocDefaultCurrency,
|
||||
@@ -34,10 +20,6 @@ final class StoreDTO
|
||||
int $ocStoreId
|
||||
) {
|
||||
$this->enableStore = $enableStore;
|
||||
$this->mainpageProducts = $mainpageProducts;
|
||||
$this->featuredProducts = $featuredProducts;
|
||||
$this->mainpageCategories = $mainpageCategories;
|
||||
$this->featuredCategories = $featuredCategories;
|
||||
$this->featureCoupons = $featureCoupons;
|
||||
$this->featureVouchers = $featureVouchers;
|
||||
$this->ocDefaultCurrency = $ocDefaultCurrency;
|
||||
@@ -50,32 +32,6 @@ final class StoreDTO
|
||||
return $this->enableStore;
|
||||
}
|
||||
|
||||
public function getMainpageProducts(): string
|
||||
{
|
||||
return $this->mainpageProducts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getFeaturedProducts(): array
|
||||
{
|
||||
return $this->featuredProducts;
|
||||
}
|
||||
|
||||
public function getMainpageCategories(): string
|
||||
{
|
||||
return $this->mainpageCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getFeaturedCategories(): array
|
||||
{
|
||||
return $this->featuredCategories;
|
||||
}
|
||||
|
||||
public function isFeatureCoupons(): bool
|
||||
{
|
||||
return $this->featureCoupons;
|
||||
@@ -105,10 +61,6 @@ final class StoreDTO
|
||||
{
|
||||
return [
|
||||
'enable_store' => $this->enableStore,
|
||||
'mainpage_products' => $this->mainpageProducts,
|
||||
'featured_products' => $this->featuredProducts,
|
||||
'mainpage_categories' => $this->mainpageCategories,
|
||||
'featured_categories' => $this->featuredCategories,
|
||||
'feature_coupons' => $this->featureCoupons,
|
||||
'feature_vouchers' => $this->featureVouchers,
|
||||
'oc_default_currency' => $this->ocDefaultCurrency,
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class ProductForMainPage extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_FOR_MAIN_PAGE';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_for_main_page' => new Criterion(static::CRITERIA_OPTION_PRODUCT_MODEL, [
|
||||
'operator' => static::CRITERIA_OPERATOR_EQUALS,
|
||||
'value' => false,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
$criterion = $this->criteria[static::CRITERIA_OPTION_PRODUCT_FOR_MAIN_PAGE] ?? false;
|
||||
if (! $criterion || $criterion->params['value'] === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$featuredProducts = config('featured_products', []);
|
||||
$mainpageProducts = config('mainpage_products');
|
||||
|
||||
if ($mainpageProducts === 'featured' && $featuredProducts) {
|
||||
$builder->whereIn('products.product_id', $featuredProducts);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($mainpageProducts === 'latest') {
|
||||
$builder->orders = [];
|
||||
$builder->orderBy('products.date_modified', 'DESC');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($mainpageProducts === 'most_viewed') {
|
||||
$builder->orders = [];
|
||||
$builder->orderBy('products.viewed', 'DESC');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use App\Services\SettingsService;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
|
||||
class BannerHandler
|
||||
{
|
||||
private OcRegistryDecorator $registry;
|
||||
private ImageToolInterface $imageTool;
|
||||
private SettingsService $settings;
|
||||
|
||||
public function __construct(OcRegistryDecorator $registry, ImageToolInterface $imageTool, SettingsService $settings)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->imageTool = $imageTool;
|
||||
$this->settings = $settings;
|
||||
|
||||
$this->registry->load->model('design/banner');
|
||||
}
|
||||
|
||||
public function show(): JsonResponse
|
||||
{
|
||||
$slider = $this->settings->config()->getSliders()->getMainpageSlider();
|
||||
$data = [];
|
||||
|
||||
foreach ($slider->getSlides() as $index => $slide) {
|
||||
if (is_file(DIR_IMAGE . $slide->getImage())) {
|
||||
$data['slides'][$index] = [
|
||||
'id' => $index,
|
||||
'title' => $slide->getTitle(),
|
||||
'link' => $slide->getLink(),
|
||||
'image' => $this->imageTool->cover($slide->getImage(), 1110, 600),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return new JsonResponse(compact('data'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use App\Services\BlocksService;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
|
||||
class BlocksHandler
|
||||
{
|
||||
private BlocksService $blocksService;
|
||||
|
||||
public function __construct(BlocksService $blocksService)
|
||||
{
|
||||
$this->blocksService = $blocksService;
|
||||
}
|
||||
|
||||
public function processBlock(Request $request): JsonResponse
|
||||
{
|
||||
$block = $request->json();
|
||||
|
||||
$data = $this->blocksService->process($block);
|
||||
|
||||
return new JsonResponse(compact('data'));
|
||||
}
|
||||
}
|
||||
@@ -32,17 +32,6 @@ class CategoriesHandler
|
||||
$languageId = $this->settings->config()->getApp()->getLanguageId();
|
||||
|
||||
$perPage = $request->get('perPage', 100);
|
||||
$forMainPage = filter_var($request->get('forMainPage', false), FILTER_VALIDATE_BOOLEAN);
|
||||
$featuredCategories = $this->settings->config()->getStore()->getFeaturedCategories();
|
||||
$mainpageCategories = $this->settings->config()->getStore()->getMainpageCategories();
|
||||
|
||||
if ($forMainPage && $mainpageCategories === 'no_categories') {
|
||||
return new JsonResponse(['data' => []]);
|
||||
}
|
||||
|
||||
if ($forMainPage && $mainpageCategories === 'latest10') {
|
||||
$perPage = 10;
|
||||
}
|
||||
|
||||
$categoriesFlat = $this->queryBuilder->newQuery()
|
||||
->select([
|
||||
@@ -61,12 +50,6 @@ class CategoriesHandler
|
||||
}
|
||||
)
|
||||
->where('categories.status', '=', 1)
|
||||
->when(
|
||||
$forMainPage && $mainpageCategories === 'featured' && $featuredCategories,
|
||||
function (Builder $query) use ($featuredCategories) {
|
||||
$query->whereIn('categories.category_id', $featuredCategories);
|
||||
}
|
||||
)
|
||||
->orderBy('parent_id')
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Handlers;
|
||||
|
||||
use App\Filters\ProductCategory;
|
||||
use App\Filters\ProductForMainPage;
|
||||
use App\Filters\ProductPrice;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
|
||||
@@ -29,18 +28,6 @@ class FiltersHandler
|
||||
],
|
||||
],
|
||||
|
||||
ProductForMainPage::NAME => [
|
||||
'criteria' => [
|
||||
'product_for_main_page' => [
|
||||
'type' => 'boolean',
|
||||
'params' => [
|
||||
'operator' => 'equals',
|
||||
'value' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
ProductCategory::NAME => [
|
||||
'criteria' => [
|
||||
'product_category_id' => [
|
||||
|
||||
@@ -31,12 +31,13 @@ class ProductsHandler
|
||||
{
|
||||
$page = (int) $request->json('page', 1);
|
||||
$perPage = min((int) $request->json('perPage', 6), 15);
|
||||
$maxPages = (int) $request->json('maxPages', 10);
|
||||
$search = trim($request->get('search', ''));
|
||||
$filters = $request->json('filters');
|
||||
$languageId = $this->settings->config()->getApp()->getLanguageId();
|
||||
|
||||
$response = $this->productsService->getProductsResponse(
|
||||
compact('page', 'perPage', 'search', 'filters'),
|
||||
compact('page', 'perPage', 'search', 'filters', 'maxPages'),
|
||||
$languageId,
|
||||
);
|
||||
|
||||
|
||||
@@ -64,17 +64,13 @@ class SettingsHandler
|
||||
'feature_vouchers' => $this->settings->config()->getStore()->isFeatureVouchers(),
|
||||
'currency_code' => $this->settings->config()->getStore()->getOcDefaultCurrency(),
|
||||
'texts' => $this->settings->config()->getTexts()->toArray(),
|
||||
'mainpage_slider' => $this->settings->config()->getSliders()->getMainpageSlider()->toArray(),
|
||||
'mainpage_blocks' => $this->settings->get('mainpage_blocks', []),
|
||||
]);
|
||||
}
|
||||
|
||||
public function manifest(): JsonResponse
|
||||
{
|
||||
$appIcon = $this->settings->config()->getApp()->getAppIcon();
|
||||
$icon192 = $this->imageTool->resize($appIcon, 192, 192, 'no_image.png', 'png');
|
||||
$icon512 = $this->imageTool->resize($appIcon, 512, 512, 'no_image.png', 'png');
|
||||
|
||||
return new JsonResponse([
|
||||
$manifest = [
|
||||
'name' => $this->settings->config()->getApp()->getAppName(),
|
||||
'short_name' => $this->settings->config()->getApp()->getAppName(),
|
||||
'start_url' => '/image/catalog/tgshopspa/',
|
||||
@@ -82,7 +78,13 @@ class SettingsHandler
|
||||
'background_color' => '#ffffff',
|
||||
'theme_color' => '#000000',
|
||||
'orientation' => 'portrait',
|
||||
'icons' => [
|
||||
];
|
||||
|
||||
$appIcon = $this->settings->config()->getApp()->getAppIcon();
|
||||
if ($appIcon) {
|
||||
$icon192 = $this->imageTool->resize($appIcon, 192, 192, 'no_image.png', 'png');
|
||||
$icon512 = $this->imageTool->resize($appIcon, 512, 512, 'no_image.png', 'png');
|
||||
$manifest['icons'] = [
|
||||
[
|
||||
'src' => $icon192,
|
||||
'sizes' => '192x192',
|
||||
@@ -93,8 +95,10 @@ class SettingsHandler
|
||||
'sizes' => '512x512',
|
||||
'type' => 'image/png',
|
||||
]
|
||||
]
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
return new JsonResponse($manifest);
|
||||
}
|
||||
|
||||
public function testTgMessage(Request $request): JsonResponse
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Exceptions\CustomExceptionHandler;
|
||||
use App\Filters\ProductAttribute;
|
||||
use App\Filters\ProductCategories;
|
||||
use App\Filters\ProductCategory;
|
||||
use App\Filters\ProductForMainPage;
|
||||
use App\Filters\ProductManufacturer;
|
||||
use App\Filters\ProductModel;
|
||||
use App\Filters\ProductPrice;
|
||||
@@ -64,7 +63,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
ProductPrice::NAME => ProductPrice::class,
|
||||
ProductQuantity::NAME => ProductQuantity::class,
|
||||
ProductStatus::NAME => ProductStatus::class,
|
||||
ProductForMainPage::NAME => ProductForMainPage::class,
|
||||
ProductCategory::NAME => ProductCategory::class,
|
||||
]);
|
||||
}
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/src/ServiceProviders/SettingsServiceProvider.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/src/ServiceProviders/SettingsServiceProvider.php
Normal file → Executable file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Openguru\OpenCartFramework\Cache\CacheInterface;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\Logger\LoggerInterface;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
use RuntimeException;
|
||||
|
||||
class BlocksService
|
||||
{
|
||||
private static array $processors = [
|
||||
'slider' => [self::class, 'processSlider'],
|
||||
'categories_top' => [self::class, 'processCategoriesTop'],
|
||||
'products_feed' => [self::class, 'processProductsFeed'],
|
||||
];
|
||||
|
||||
private LoggerInterface $logger;
|
||||
private ImageToolInterface $imageTool;
|
||||
private CacheInterface $cache;
|
||||
private SettingsService $settings;
|
||||
private Builder $queryBuilder;
|
||||
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
ImageToolInterface $imageTool,
|
||||
CacheInterface $cache,
|
||||
SettingsService $settings,
|
||||
Builder $queryBuilder
|
||||
) {
|
||||
$this->logger = $logger;
|
||||
$this->imageTool = $imageTool;
|
||||
$this->cache = $cache;
|
||||
$this->settings = $settings;
|
||||
$this->queryBuilder = $queryBuilder;
|
||||
}
|
||||
|
||||
public function process(array $block): array
|
||||
{
|
||||
$method = self::$processors[$block['type']] ?? null;
|
||||
|
||||
if (! $method) {
|
||||
throw new RuntimeException('Processor for block type ' . $block['type'] . ' does not exist');
|
||||
}
|
||||
|
||||
return call_user_func_array($method, [$block]);
|
||||
}
|
||||
|
||||
private function processSlider(array $block): array
|
||||
{
|
||||
$slides = $block['data']['slides'];
|
||||
foreach ($slides as $slideIndex => $slide) {
|
||||
if (is_file(DIR_IMAGE . $slide['image'])) {
|
||||
$block['data']['slides'][$slideIndex]['image'] = $this->imageTool->cover(
|
||||
$slide['image'],
|
||||
1110,
|
||||
600
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
private function processCategoriesTop(array $block): array
|
||||
{
|
||||
$count = $block['data']['count'];
|
||||
$languageId = $this->settings->config()->getApp()->getLanguageId();
|
||||
$categories = [];
|
||||
|
||||
if ($count > 0) {
|
||||
$categories = $this->queryBuilder->newQuery()
|
||||
->select([
|
||||
'categories.category_id' => 'id',
|
||||
'descriptions.name' => 'name',
|
||||
])
|
||||
->from(db_table('category'), 'categories')
|
||||
->join(
|
||||
db_table('category_description') . ' AS descriptions',
|
||||
function (JoinClause $join) use ($languageId) {
|
||||
$join->on('categories.category_id', '=', 'descriptions.category_id')
|
||||
->where('descriptions.language_id', '=', $languageId);
|
||||
}
|
||||
)
|
||||
->where('categories.status', '=', 1)
|
||||
->where('categories.parent_id', '=', 0)
|
||||
->orderBy('sort_order')
|
||||
->orderBy('descriptions.name')
|
||||
->limit($count)
|
||||
->get();
|
||||
|
||||
$categories = array_map(static function ($category) {
|
||||
$category['id'] = (int) $category['id'];
|
||||
|
||||
return $category;
|
||||
}, $categories);
|
||||
}
|
||||
|
||||
$block['data']['categories'] = $categories;
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
private function processProductsFeed(array $block): array
|
||||
{
|
||||
return $block;
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,8 @@ use App\DTO\Settings\AppDTO;
|
||||
use App\DTO\Settings\ConfigDTO;
|
||||
use App\DTO\Settings\DatabaseDTO;
|
||||
use App\DTO\Settings\LogsDTO;
|
||||
use App\DTO\Settings\MainpageSlider\LinkDTO;
|
||||
use App\DTO\Settings\MainpageSlider\LinkValueDTO;
|
||||
use App\DTO\Settings\MainpageSlider\MainpageSliderDTO;
|
||||
use App\DTO\Settings\MainpageSlider\SlideDTO;
|
||||
use App\DTO\Settings\MetricsDTO;
|
||||
use App\DTO\Settings\OrdersDTO;
|
||||
use App\DTO\Settings\SlidersDTO;
|
||||
use App\DTO\Settings\StoreDTO;
|
||||
use App\DTO\Settings\TelegramDTO;
|
||||
use App\DTO\Settings\TextsDTO;
|
||||
@@ -22,7 +17,7 @@ class SettingsSerializerService
|
||||
{
|
||||
public function fromArray(array $data): ConfigDTO
|
||||
{
|
||||
$keys = ['app', 'telegram', 'metrics', 'store', 'orders', 'texts', 'sliders', 'database', 'logs'];
|
||||
$keys = ['app', 'telegram', 'metrics', 'store', 'orders', 'texts', 'database', 'logs'];
|
||||
foreach ($keys as $key) {
|
||||
if (! array_key_exists($key, $data)) {
|
||||
throw new InvalidArgumentException("Settings key '$key' is required!");
|
||||
@@ -35,7 +30,6 @@ class SettingsSerializerService
|
||||
$this->validateStore($data['store']);
|
||||
$this->validateOrders($data['orders']);
|
||||
$this->validateTexts($data['texts']);
|
||||
$this->validateSliders($data['sliders']);
|
||||
$this->validateDatabase($data['database']);
|
||||
$this->validateLogs($data['logs']);
|
||||
|
||||
@@ -46,7 +40,6 @@ class SettingsSerializerService
|
||||
$this->deserializeStore($data['store']),
|
||||
$this->deserializeOrders($data['orders']),
|
||||
$this->deserializeTexts($data['texts']),
|
||||
$this->deserializeSliders($data['sliders']),
|
||||
$this->deserializeDatabase($data['database']),
|
||||
$this->deserializeLogs($data['logs']),
|
||||
);
|
||||
@@ -146,10 +139,6 @@ class SettingsSerializerService
|
||||
|
||||
return new StoreDTO(
|
||||
$data['enable_store'] ?? true,
|
||||
$data['mainpage_products'] ?? 'most_viewed',
|
||||
$data['featured_products'] ?? [],
|
||||
$data['mainpage_categories'] ?? 'latest10',
|
||||
$data['featured_categories'] ?? [],
|
||||
$data['feature_coupons'] ?? true,
|
||||
$data['feature_vouchers'] ?? true,
|
||||
$data['oc_default_currency'],
|
||||
@@ -183,66 +172,6 @@ class SettingsSerializerService
|
||||
);
|
||||
}
|
||||
|
||||
private function deserializeSliders(array $data): SlidersDTO
|
||||
{
|
||||
return new SlidersDTO(
|
||||
$this->deserializeMainpageSlider($data['mainpage_slider'] ?? [])
|
||||
);
|
||||
}
|
||||
|
||||
private function deserializeMainpageSlider(array $data): MainpageSliderDTO
|
||||
{
|
||||
$slides = [];
|
||||
if (isset($data['slides']) && is_array($data['slides'])) {
|
||||
foreach ($data['slides'] as $slideData) {
|
||||
$slides[] = $this->deserializeSlide($slideData);
|
||||
}
|
||||
}
|
||||
|
||||
return new MainpageSliderDTO(
|
||||
$data['is_enabled'] ?? false,
|
||||
$data['effect'] ?? 'slide',
|
||||
$data['pagination'] ?? true,
|
||||
$data['scrollbar'] ?? false,
|
||||
$data['free_mode'] ?? false,
|
||||
$data['space_between'] ?? 30,
|
||||
$data['autoplay'] ?? false,
|
||||
$data['loop'] ?? false,
|
||||
$slides
|
||||
);
|
||||
}
|
||||
|
||||
private function deserializeSlide(array $data): SlideDTO
|
||||
{
|
||||
return new SlideDTO(
|
||||
$data['title'] ?? '',
|
||||
$this->deserializeLink($data['link'] ?? []),
|
||||
$data['image'] ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
private function deserializeLink(array $data): LinkDTO
|
||||
{
|
||||
$value = null;
|
||||
if (isset($data['value'])) {
|
||||
$value = $this->deserializeLinkValue($data['value']);
|
||||
}
|
||||
|
||||
return new LinkDTO(
|
||||
$data['type'] ?? 'none',
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
private function deserializeLinkValue(array $data): LinkValueDTO
|
||||
{
|
||||
return new LinkValueDTO(
|
||||
$data['category_id'] ?? null,
|
||||
$data['name'] ?? null,
|
||||
$data['product_id'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
// ==================== Validation Methods ====================
|
||||
|
||||
private function validateApp(array $data): void
|
||||
@@ -340,44 +269,6 @@ class SettingsSerializerService
|
||||
throw new InvalidArgumentException('store.enable_store must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['mainpage_products']) && ! is_string($data['mainpage_products'])) {
|
||||
throw new InvalidArgumentException('store.mainpage_products must be a string');
|
||||
}
|
||||
|
||||
if (isset($data['featured_products'])) {
|
||||
if (! is_array($data['featured_products'])) {
|
||||
throw new InvalidArgumentException('store.featured_products must be an array');
|
||||
}
|
||||
foreach ($data['featured_products'] as $index => $productId) {
|
||||
if (! is_int($productId)) {
|
||||
throw new InvalidArgumentException("store.featured_products[$index] must be an integer");
|
||||
}
|
||||
if ($productId <= 0) {
|
||||
throw new InvalidArgumentException("store.featured_products[$index] must be a positive integer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['mainpage_categories']) && ! is_string($data['mainpage_categories'])) {
|
||||
throw new InvalidArgumentException('store.mainpage_categories must be a string');
|
||||
}
|
||||
|
||||
if (isset($data['featured_categories'])) {
|
||||
if (! is_array($data['featured_categories'])) {
|
||||
throw new InvalidArgumentException('store.featured_categories must be an array');
|
||||
}
|
||||
foreach ($data['featured_categories'] as $index => $categoryId) {
|
||||
if (! is_int($categoryId)) {
|
||||
throw new InvalidArgumentException("store.featured_categories[$index] must be an integer");
|
||||
}
|
||||
if ($categoryId <= 0) {
|
||||
throw new InvalidArgumentException(
|
||||
"store.featured_categories[$index] must be a positive integer"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['feature_coupons']) && ! is_bool($data['feature_coupons'])) {
|
||||
throw new InvalidArgumentException('store.feature_coupons must be a boolean');
|
||||
}
|
||||
@@ -454,178 +345,6 @@ class SettingsSerializerService
|
||||
}
|
||||
}
|
||||
|
||||
private function validateSliders(array $data): void
|
||||
{
|
||||
if (isset($data['mainpage_slider'])) {
|
||||
if (! is_array($data['mainpage_slider'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider must be an object');
|
||||
}
|
||||
$this->validateMainpageSlider($data['mainpage_slider']);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateMainpageSlider(array $data): void
|
||||
{
|
||||
if (isset($data['is_enabled']) && ! is_bool($data['is_enabled'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.is_enabled must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['effect'])) {
|
||||
if (! is_string($data['effect'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.effect must be a string');
|
||||
}
|
||||
$allowedEffects = ['slide', 'fade', 'cube', 'coverflow', 'flip'];
|
||||
if (! in_array($data['effect'], $allowedEffects, true)) {
|
||||
throw new InvalidArgumentException(
|
||||
'sliders.mainpage_slider.effect must be one of: ' . implode(', ', $allowedEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['pagination']) && ! is_bool($data['pagination'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.pagination must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['scrollbar']) && ! is_bool($data['scrollbar'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.scrollbar must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['free_mode']) && ! is_bool($data['free_mode'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.free_mode must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['space_between'])) {
|
||||
if (! is_int($data['space_between'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.space_between must be an integer');
|
||||
}
|
||||
if ($data['space_between'] < 0) {
|
||||
throw new InvalidArgumentException(
|
||||
'sliders.mainpage_slider.space_between must be a non-negative integer'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['autoplay']) && ! is_bool($data['autoplay'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.autoplay must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['loop']) && ! is_bool($data['loop'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.loop must be a boolean');
|
||||
}
|
||||
|
||||
if (isset($data['slides'])) {
|
||||
if (! is_array($data['slides'])) {
|
||||
throw new InvalidArgumentException('sliders.mainpage_slider.slides must be an array');
|
||||
}
|
||||
foreach ($data['slides'] as $index => $slideData) {
|
||||
if (! is_array($slideData)) {
|
||||
throw new InvalidArgumentException("sliders.mainpage_slider.slides[$index] must be an object");
|
||||
}
|
||||
$this->validateSlide($slideData, $index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function validateSlide(array $data, int $index): void
|
||||
{
|
||||
if (isset($data['title']) && ! is_string($data['title'])) {
|
||||
throw new InvalidArgumentException("sliders.mainpage_slider.slides[$index].title must be a string");
|
||||
}
|
||||
|
||||
if (isset($data['link'])) {
|
||||
if (! is_array($data['link'])) {
|
||||
throw new InvalidArgumentException("sliders.mainpage_slider.slides[$index].link must be an object");
|
||||
}
|
||||
$this->validateLink($data['link'], $index);
|
||||
}
|
||||
|
||||
if (isset($data['image']) && ! is_string($data['image'])) {
|
||||
throw new InvalidArgumentException("sliders.mainpage_slider.slides[$index].image must be a string");
|
||||
}
|
||||
}
|
||||
|
||||
private function validateLink(array $data, int $slideIndex): void
|
||||
{
|
||||
if (isset($data['type'])) {
|
||||
if (! is_string($data['type'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.type must be a string"
|
||||
);
|
||||
}
|
||||
$allowedTypes = ['none', 'category', 'product'];
|
||||
if (! in_array($data['type'], $allowedTypes, true)) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.type must be one of: " . implode(
|
||||
', ',
|
||||
$allowedTypes
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['value'])) {
|
||||
if ($data['value'] !== null) {
|
||||
if (! is_array($data['value'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value must be an object or null"
|
||||
);
|
||||
}
|
||||
$this->validateLinkValue($data['value'], $data['type'] ?? 'none', $slideIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function validateLinkValue(array $data, string $linkType, int $slideIndex): void
|
||||
{
|
||||
if ($linkType === 'category') {
|
||||
if (isset($data['category_id'])) {
|
||||
if (! is_int($data['category_id'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value.category_id must be an integer"
|
||||
);
|
||||
}
|
||||
if ($data['category_id'] <= 0) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value.category_id must be a positive integer"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isset($data['name']) && ! is_string($data['name'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value.name must be a string"
|
||||
);
|
||||
}
|
||||
} elseif ($linkType === 'product') {
|
||||
if (isset($data['product_id'])) {
|
||||
if (! is_int($data['product_id'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value.product_id must be an integer"
|
||||
);
|
||||
}
|
||||
if ($data['product_id'] <= 0) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value.product_id must be a positive integer"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isset($data['name']) && ! is_string($data['name'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value.name must be a string"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем, что не переданы лишние поля
|
||||
$allowedFields = ['category_id', 'product_id', 'name'];
|
||||
foreach (array_keys($data) as $field) {
|
||||
if (! in_array($field, $allowedFields, true)) {
|
||||
throw new InvalidArgumentException(
|
||||
"sliders.mainpage_slider.slides[$slideIndex].link.value contains unknown field: $field"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deserializeLogs(array $logs): LogsDTO
|
||||
{
|
||||
return new LogsDTO(
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/src/Services/SettingsService.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/src/Services/SettingsService.php
Normal file → Executable file
@@ -1,20 +1,79 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'config_timezone' => 'UTC',
|
||||
'lang' => 'en-gb',
|
||||
'language_id' => 1,
|
||||
'auth_user_id' => 0,
|
||||
'base_url' => 'http://localhost',
|
||||
|
||||
'db' => [
|
||||
'host' => 'localhost',
|
||||
'database' => 'not_set',
|
||||
'username' => 'not_set',
|
||||
'password' => 'not_set',
|
||||
'app' => [
|
||||
'app_enabled' => true,
|
||||
'app_name' => 'Telecart',
|
||||
'app_icon' => null,
|
||||
"theme_light" => "light",
|
||||
"theme_dark" => "dark",
|
||||
"app_debug" => false
|
||||
],
|
||||
|
||||
'logs' => [
|
||||
'path' => 'not_set',
|
||||
'telegram' => [
|
||||
"bot_token" => "",
|
||||
"chat_id" => null,
|
||||
"owner_notification_template" => <<<TEXT
|
||||
*Новый заказ \#{order_id}* в магазине *{store_name}*
|
||||
|
||||
*Покупатель:* {customer}
|
||||
*Email:* {email}
|
||||
*Телефон:* {phone}
|
||||
*IP:* {ip}
|
||||
|
||||
*Адрес доставки:*
|
||||
{address}
|
||||
|
||||
*Комментарий:*
|
||||
{comment}
|
||||
|
||||
*Сумма заказа:* {total}
|
||||
*Дата оформления:* {created_at}
|
||||
TEXT,
|
||||
"customer_notification_template" => <<<TEXT
|
||||
Спасибо за Ваш заказ в магазине *{store_name}*
|
||||
|
||||
*Номер заказа* \#{order_id}
|
||||
*Сумма заказа:* {total}
|
||||
*Дата оформления:* {created_at}
|
||||
|
||||
Мы свяжемся с вами при необходимости\.
|
||||
Хорошего дня\!
|
||||
TEXT,
|
||||
"mini_app_url" => "",
|
||||
],
|
||||
|
||||
"metrics" => [
|
||||
"yandex_metrika_enabled" => false,
|
||||
"yandex_metrika_counter" => "",
|
||||
],
|
||||
|
||||
'store' => [
|
||||
'enable_store' => true,
|
||||
'feature_coupons' => true,
|
||||
'feature_vouchers' => true,
|
||||
],
|
||||
|
||||
'texts' => [
|
||||
'text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
||||
'text_empty_cart' => 'Ваша корзина пуста.',
|
||||
'text_order_created_success' => 'Ваш заказ успешно оформлен и будет обработан в ближайшее время.'
|
||||
],
|
||||
|
||||
'orders' => [
|
||||
'order_default_status_id' => 1,
|
||||
],
|
||||
|
||||
'mainpage_blocks' => [
|
||||
[
|
||||
'type' => 'products_feed',
|
||||
'title' => '',
|
||||
'description' => '',
|
||||
'is_enabled' => true,
|
||||
'goal_name' => '',
|
||||
'data' => [
|
||||
'max_page_count' => 10,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Handlers\BannerHandler;
|
||||
use App\Handlers\BlocksHandler;
|
||||
use App\Handlers\CartHandler;
|
||||
use App\Handlers\CategoriesHandler;
|
||||
use App\Handlers\FiltersHandler;
|
||||
@@ -27,7 +28,6 @@ return [
|
||||
'manifest' => [SettingsHandler::class, 'manifest'],
|
||||
'testTgMessage' => [SettingsHandler::class, 'testTgMessage'],
|
||||
|
||||
'banner' => [BannerHandler::class, 'show'],
|
||||
|
||||
'webhook' => [TelegramHandler::class, 'webhook'],
|
||||
'processBlock' => [BlocksHandler::class, 'processBlock'],
|
||||
];
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace Tests\Unit\Framework;
|
||||
use App\Filters\ProductAttribute;
|
||||
use App\Filters\ProductCategories;
|
||||
use App\Filters\ProductCategory;
|
||||
use App\Filters\ProductForMainPage;
|
||||
use App\Filters\ProductManufacturer;
|
||||
use App\Filters\ProductModel;
|
||||
use App\Filters\ProductPrice;
|
||||
@@ -89,7 +88,6 @@ class CriteriaBuilderTest extends TestCase
|
||||
$rulesRegistry->register(ProductManufacturer::NAME, ProductManufacturer::class);
|
||||
$rulesRegistry->register(ProductQuantity::NAME, ProductQuantity::class);
|
||||
$rulesRegistry->register(ProductAttribute::NAME, ProductAttribute::class);
|
||||
$rulesRegistry->register(ProductForMainPage::NAME, ProductForMainPage::class);
|
||||
$rulesRegistry->register(ProductCategory::NAME, ProductCategory::class);
|
||||
|
||||
$this->builder = $application->get(Builder::class);
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/ExecutionTimeProfilerTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/ExecutionTimeProfilerTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/JsonResponseTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/JsonResponseTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/PaginationHelperTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/PaginationHelperTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/QueryResultTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/QueryResultTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/RawExpressionTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/RawExpressionTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/UtilsTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/Framework/UtilsTest.php
Normal file → Executable file
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"mainpage_products": "featured",
|
||||
"featured_products": [1, 2, 3]
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"mainpage_products": "featured",
|
||||
"featured_products": []
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"mainpage_products": "latest"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"mainpage_products": "most_viewed"
|
||||
}
|
||||
Reference in New Issue
Block a user