diff --git a/module/oc_telegram_shop/upload/admin/controller/extension/module/tgshop.php b/module/oc_telegram_shop/upload/admin/controller/extension/module/tgshop.php index 111635b..b81e5d5 100755 --- a/module/oc_telegram_shop/upload/admin/controller/extension/module/tgshop.php +++ b/module/oc_telegram_shop/upload/admin/controller/extension/module/tgshop.php @@ -308,6 +308,7 @@ class ControllerExtensionModuleTgshop extends Controller { return [ 'module_tgshop_status' => 1, + 'module_tgshop_debug' => 0, 'module_tgshop_app_name' => $this->config->get('config_meta_title'), 'module_tgshop_app_icon' => $this->config->get('config_image') ?: $this->model_tool_image->resize( 'no_image.png', @@ -415,6 +416,15 @@ TEXT, 'options' => static::$themes, 'help' => 'Выберите стиль, который будет использоваться при отображении вашего магазина в Telegram для ночного режима. Посмотреть как выглядят темы', ], + + 'module_tgshop_debug' => [ + 'type' => 'select', + 'options' => [ + 0 => 'Выключено', + 1 => 'Включено', + ], + 'help' => 'Режим разработчика. Рекомендуется включать только по необходимости. В остальных случаях, для нормальной работы магазина, должен быть выключен.', + ], ], 'telegram' => [ 'module_tgshop_mini_app_url' => [ @@ -457,9 +467,9 @@ HTML, 'statistics' => [ 'module_tgshop_yandex_metrika' => [ 'type' => 'textarea', - 'placeholder' => 'Вставьте код счётчика Яндекс Метрики', + 'placeholder' => 'Вставьте код счётчика Яндекс Метрики.', 'rows' => 15, - 'help' => '' + 'help' => 'Для проверки интеграции через кнопку "Проверить" в интерфейсе Яндекс Метрики, необходимо сначала включить "Режим разработчика" на вкладке "Общие".' ], ], diff --git a/module/oc_telegram_shop/upload/admin/language/ru-ru/extension/module/tgshop.php b/module/oc_telegram_shop/upload/admin/language/ru-ru/extension/module/tgshop.php index 799c701..7fc524b 100755 --- a/module/oc_telegram_shop/upload/admin/language/ru-ru/extension/module/tgshop.php +++ b/module/oc_telegram_shop/upload/admin/language/ru-ru/extension/module/tgshop.php @@ -33,6 +33,7 @@ $_['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'] = 'Режим разработчика'; // Entry $_['entry_status'] = 'Статус'; diff --git a/module/oc_telegram_shop/upload/catalog/controller/extension/tgshop/handle.php b/module/oc_telegram_shop/upload/catalog/controller/extension/tgshop/handle.php index a0be385..3a64c76 100755 --- a/module/oc_telegram_shop/upload/catalog/controller/extension/tgshop/handle.php +++ b/module/oc_telegram_shop/upload/catalog/controller/extension/tgshop/handle.php @@ -7,6 +7,7 @@ use Cart\Currency; use Cart\Tax; 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; @@ -37,8 +38,11 @@ class ControllerExtensionTgshopHandle extends Controller { $this->session->data['language'] = $this->config->get('config_language'); + $appDebug = filter_var($this->config->get('module_tgshop_debug'), FILTER_VALIDATE_BOOLEAN); + $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'), // ID группы покупателей, которая будет использоаваться в заказах через Телеграм. @@ -107,7 +111,13 @@ class ControllerExtensionTgshopHandle extends Controller $app->singleton(Log::class, fn() => $this->log); $app - ->withLogger(fn() => new OpenCartLogAdapter($this->log, 'TeleCart')) + ->withLogger( + fn() => new OpenCartLogAdapter( + $this->log, + 'TeleCart', + $appDebug ? LoggerInterface::LEVEL_DEBUG : LoggerInterface::LEVEL_WARNING, + ) + ) ->bootAndHandleRequest(); } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Http/Request.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Http/Request.php index 30dac5c..5823255 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Http/Request.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Http/Request.php @@ -92,4 +92,27 @@ final class Request return $headers[mb_strtolower($name)] ?? null; } + + /** + * @param array|string $key + * @return bool + */ + public function has($key): bool + { + if (is_array($key)) { + foreach ($key as $k) { + if ($this->has($k)) { + return true; + } + } + + return false; + } + + if (array_key_exists($key, $this->query)) { + return true; + } + + return $this->json($key) !== null; + } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/Logger.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/Logger.php index 34c1634..ce9def4 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/Logger.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/Logger.php @@ -81,4 +81,9 @@ class Logger implements LoggerInterface ) ); } + + public function debug(string $message): void + { + $this->log($message, LoggerInterface::LEVEL_DEBUG); + } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/LoggerInterface.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/LoggerInterface.php index 6d20ce1..2c1f1fa 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/LoggerInterface.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/LoggerInterface.php @@ -6,12 +6,15 @@ use Throwable; interface LoggerInterface { + public const LEVEL_DEBUG = 0; public const LEVEL_INFO = 1; public const LEVEL_WARNING = 2; public const LEVEL_ERROR = 3; public function log($message, $level = self::LEVEL_INFO); + public function debug(string $message): void; + public function info(string $message): void; public function warning(string $message): void; diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/OpenCartLogAdapter.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/OpenCartLogAdapter.php index 3c02fee..3a6941b 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/OpenCartLogAdapter.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/OpenCartLogAdapter.php @@ -9,15 +9,21 @@ class OpenCartLogAdapter implements LoggerInterface { private Log $ocLogger; private string $namespace; + private int $minLogLevel; - public function __construct(Log $ocLogger, string $namespace) + public function __construct(Log $ocLogger, string $namespace, int $minLogLevel = LoggerInterface::LEVEL_WARNING) { $this->ocLogger = $ocLogger; $this->namespace = $namespace; + $this->minLogLevel = $minLogLevel; } - public function log($message, $level = self::LEVEL_INFO): void + public function log($message, $level = LoggerInterface::LEVEL_INFO): void { + if ($level < $this->minLogLevel) { + return; + } + $this->ocLogger->write( sprintf( "[%s] [%s] %s\n", @@ -35,12 +41,12 @@ class OpenCartLogAdapter implements LoggerInterface public function warning(string $message): void { - $this->log($message, self::LEVEL_WARNING); + $this->log($message, LoggerInterface::LEVEL_WARNING); } public function error(string $message): void { - $this->log($message, self::LEVEL_ERROR); + $this->log($message, LoggerInterface::LEVEL_ERROR); } public function logException(Throwable $exception): void @@ -59,6 +65,8 @@ class OpenCartLogAdapter implements LoggerInterface private function getLevelString($level): string { switch ($level) { + case LoggerInterface::LEVEL_DEBUG: + return 'DEBUG'; case LoggerInterface::LEVEL_INFO: return 'INFO'; case LoggerInterface::LEVEL_WARNING: @@ -69,4 +77,9 @@ class OpenCartLogAdapter implements LoggerInterface return 'UNKNOWN'; } } + + public function debug(string $message): void + { + $this->log($message, LoggerInterface::LEVEL_DEBUG); + } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/SignatureValidator.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/SignatureValidator.php index 3c6f3fa..69bad8d 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/SignatureValidator.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/SignatureValidator.php @@ -2,20 +2,31 @@ namespace Openguru\OpenCartFramework\Telegram; +use Openguru\OpenCartFramework\Config\Settings; use Openguru\OpenCartFramework\Http\Request; +use Openguru\OpenCartFramework\Logger\LoggerInterface; use Openguru\OpenCartFramework\Telegram\Exceptions\TelegramInvalidSignatureException; class SignatureValidator { private ?string $botToken; + private Settings $settings; + private LoggerInterface $logger; - public function __construct(?string $botToken = null) + public function __construct(Settings $settings, LoggerInterface $logger, ?string $botToken = null) { $this->botToken = $botToken; + $this->settings = $settings; + $this->logger = $logger; } public function validate(Request $request): void { + if ($this->settings->get('app_debug')) { + $this->logger->warning('Dev Mode is enabled. Ignoring Signature Validation.'); + return; + } + if (! $this->botToken) { return; } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramServiceProvider.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramServiceProvider.php index 07395c2..91bc906 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramServiceProvider.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramServiceProvider.php @@ -3,7 +3,9 @@ namespace Openguru\OpenCartFramework\Telegram; use Openguru\OpenCartFramework\Application; +use Openguru\OpenCartFramework\Config\Settings; use Openguru\OpenCartFramework\Container\ServiceProvider; +use Openguru\OpenCartFramework\Logger\LoggerInterface; class TelegramServiceProvider extends ServiceProvider { @@ -16,6 +18,8 @@ class TelegramServiceProvider extends ServiceProvider $this->container->singleton(SignatureValidator::class, function (Application $app) { return new SignatureValidator( + $app->get(Settings::class), + $app->get(LoggerInterface::class), $app->getConfigValue('telegram.bot_token'), ); }); diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/SettingsHandler.php b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/SettingsHandler.php index 8d726ff..52b2be1 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/SettingsHandler.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/SettingsHandler.php @@ -42,6 +42,7 @@ class SettingsHandler return new JsonResponse([ 'app_name' => $this->settings->get('app_name'), + 'app_debug' => $this->settings->get('app_debug'), 'app_icon' => $appIcon ?? '', 'app_icon192' => $icons['icon192'] ?? '', 'app_icon180' => $icons['icon180'] ?? '', diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/RequestTest.php b/module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/RequestTest.php new file mode 100644 index 0000000..154f70d --- /dev/null +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/RequestTest.php @@ -0,0 +1,62 @@ + 'bar'], + [], + [], + [], + [] + ); + + $this->assertTrue($request->has('foo')); + $this->assertFalse($request->has('xyz')); + } + + public function testHasJsonParam(): void + { + $request = new Request( + [], + [], + [], + [], + [], + [], + '{"foo":"bar"}' + ); + + $this->assertTrue($request->has('foo')); + } + + public function testHasAtLeastOne(): void + { + $request = new Request( + ['foo' => 'bar'], + [], + [], + [], + [], + [], + '{"xyz":"bar"}' + ); + + $this->assertTrue($request->has([ + 'foo', + 'xyz', + 'some_other' + ])); + + $this->assertFalse($request->has([ + 'abc', + 'some_other' + ])); + } +} diff --git a/spa/src/App.vue b/spa/src/App.vue index 154a097..3831b8c 100644 --- a/spa/src/App.vue +++ b/spa/src/App.vue @@ -10,6 +10,9 @@
+ + + @@ -43,6 +46,7 @@ import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js"; import CartButton from "@/components/CartButton.vue"; import Dock from "@/components/Dock.vue"; import Navbar from "@/components/Navbar.vue"; +import AppDebugMessage from "@/components/AppDebugMessage.vue"; const tg = useMiniApp(); const platform = ref(); diff --git a/spa/src/components/AppDebugMessage.vue b/spa/src/components/AppDebugMessage.vue new file mode 100644 index 0000000..44a7839 --- /dev/null +++ b/spa/src/components/AppDebugMessage.vue @@ -0,0 +1,9 @@ + diff --git a/spa/src/components/Dock.vue b/spa/src/components/Dock.vue index 8a6fddb..2830c37 100644 --- a/spa/src/components/Dock.vue +++ b/spa/src/components/Dock.vue @@ -73,8 +73,8 @@ function onDockItemClick() { diff --git a/spa/src/main.js b/spa/src/main.js index eb6135b..9db716c 100644 --- a/spa/src/main.js +++ b/spa/src/main.js @@ -31,6 +31,7 @@ const appLoading = createApp(AppLoading); appLoading.mount('#app'); settings.load() + .then(() => window.Telegram.WebApp.lockOrientation()) .then(async () => { console.debug('Load default filters for the main page'); const filtersStore = useProductFiltersStore(); @@ -63,7 +64,6 @@ settings.load() .then(() => { appLoading.unmount(); app.mount('#app'); }) .then(() => window.Telegram.WebApp.ready()) .then(() => settings.ya_metrika_enabled && injectYaMetrika()) - .then(() => window.Telegram.WebApp.lockOrientation()) .catch(error => { console.error(error); const errorApp = createApp(ApplicationError, {error}); diff --git a/spa/src/stores/SettingsStore.js b/spa/src/stores/SettingsStore.js index 4d07b9e..fbe4fbd 100644 --- a/spa/src/stores/SettingsStore.js +++ b/spa/src/stores/SettingsStore.js @@ -4,6 +4,7 @@ import {fetchSettings} from "@/utils/ftch.js"; export const useSettingsStore = defineStore('settings', { state: () => ({ app_enabled: true, + app_debug: false, store_enabled: true, app_name: 'OpenCart Telegram магазин', app_icon: '', @@ -39,6 +40,7 @@ export const useSettingsStore = defineStore('settings', { this.theme.dark = settings.theme_dark; this.ya_metrika_enabled = settings.ya_metrika_enabled; this.app_enabled = settings.app_enabled; + this.app_debug = settings.app_debug; this.store_enabled = settings.store_enabled; this.feature_coupons = settings.feature_coupons; this.feature_vouchers = settings.feature_vouchers; diff --git a/spa/src/style.css b/spa/src/style.css index 82a1791..5fb038f 100644 --- a/spa/src/style.css +++ b/spa/src/style.css @@ -32,9 +32,9 @@ html { .app-container { /*padding-top: calc(var(--tg-content-safe-area-inset-top) + var(--tg-safe-area-inset-top));*/ - padding-bottom: var(--tg-safe-area-inset-bottom); - padding-left: var(--tg-safe-area-inset-left); - padding-right: var(--tg-safe-area-inset-right); + padding-bottom: var(--tg-safe-area-inset-bottom, 0px); + padding-left: var(--tg-safe-area-inset-left, 0px); + padding-right: var(--tg-safe-area-inset-right, 0px); } .safe-top { @@ -57,7 +57,7 @@ html { } .telecart-main-section { - padding-top: calc(var(--tg-content-safe-area-inset-top) + var(--tg-safe-area-inset-top) + var(--tc-navbar-min-height)); + padding-top: calc(var(--tg-content-safe-area-inset-top, 0rem) + var(--tg-safe-area-inset-top, 0rem) + var(--tc-navbar-min-height)); } .swiper-pagination-bullets > .swiper-pagination-bullet { diff --git a/spa/src/views/Cart.vue b/spa/src/views/Cart.vue index 68851fb..621fe2e 100644 --- a/spa/src/views/Cart.vue +++ b/spa/src/views/Cart.vue @@ -174,6 +174,6 @@ onMounted(async () => { \ No newline at end of file diff --git a/spa/src/views/Home.vue b/spa/src/views/Home.vue index 103d2f9..fef42f9 100644 --- a/spa/src/views/Home.vue +++ b/spa/src/views/Home.vue @@ -4,7 +4,7 @@ -
+