diff --git a/.cursor/agents.md b/.cursor/agents.md index fc201db..ce5bd81 100644 --- a/.cursor/agents.md +++ b/.cursor/agents.md @@ -19,6 +19,7 @@ 3. **Следуй соглашениям именования проекта** 4. **Тестируй изменения перед коммитом** 5. **Документируй публичные API** +6. **Комментарии только на английском языке и только если они действительно оправданы** ### Правила коммитов diff --git a/docker-compose.yaml b/docker-compose.yaml index d87e117..e1997da 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -32,7 +32,6 @@ services: - PHP_IDE_CONFIG=serverName=telecart - php.session.gc_maxlifetime=28800 - php.session.cookie_lifetime=0 - - TELECART_CACHE_DRIVER=database - TELECART_REDIS_HOST=redis - TELECART_REDIS_PORT=6379 - TELECART_REDIS_DATABASE=0 diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/.env b/module/oc_telegram_shop/upload/oc_telegram_shop/.env index ff0cf1f..de3a2e1 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/.env +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/.env @@ -1,3 +1,8 @@ APP_DEBUG=true PULSE_API_HOST=https://pulse.telecart.pro/api/ PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb + +TELECART_CACHE_DRIVER=redis +#TELECART_REDIS_HOST=redis +#TELECART_REDIS_PORT=6379 +#TELECART_REDIS_DATABASE=0 \ No newline at end of file diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/.env.example b/module/oc_telegram_shop/upload/oc_telegram_shop/.env.example index fd5f298..2ea7400 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/.env.example +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/.env.example @@ -1,3 +1,7 @@ APP_DEBUG=false PULSE_API_HOST=http://host.docker.internal:8086/api/ PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb +TELECART_CACHE_DRIVER=database +TELECART_REDIS_HOST=redis +TELECART_REDIS_PORT=6379 +TELECART_REDIS_DATABASE=0 diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/.env.production b/module/oc_telegram_shop/upload/oc_telegram_shop/.env.production index a300883..2aa08b4 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/.env.production +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/.env.production @@ -1,3 +1,7 @@ APP_DEBUG=false PULSE_API_HOST=https://pulse.telecart.pro/api/ PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb +TELECART_CACHE_DRIVER=mysql +TELECART_REDIS_HOST=redis +TELECART_REDIS_PORT=6379 +TELECART_REDIS_DATABASE=0 diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Tasks/CachePruneTask.php b/module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Tasks/CachePruneTask.php deleted file mode 100755 index 9233759..0000000 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Tasks/CachePruneTask.php +++ /dev/null @@ -1,30 +0,0 @@ -cache = $cache; - } - - public function handle(): void - { - $this->cache->prune(); - } - - public function interval(): ?DateInterval - { - return new DateInterval('P1D'); - } -} diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/configs/maintenance.php b/module/oc_telegram_shop/upload/oc_telegram_shop/configs/maintenance.php index 08dc33e..d2c646b 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/configs/maintenance.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/configs/maintenance.php @@ -1,11 +1,9 @@ [ CleanUpOldAssetsTask::class, - CachePruneTask::class, ], ]; diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Application.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Application.php index 5914a19..0c7a4c9 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Application.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Application.php @@ -56,8 +56,7 @@ class Application extends Container implements LoggerAwareInterface return new Settings($container->getConfigValue()); }); - $dotenv = Dotenv::createImmutable(__DIR__ . '/../'); - $dotenv->load(); + $this->loadEnvironmentVariables(); $errorHandler = new ErrorHandler( $this->get(LoggerInterface::class), @@ -172,4 +171,30 @@ class Application extends Container implements LoggerAwareInterface { $this->logger = $logger; } + + /** + * Loads environment variables from .env files. + * First loads internal .env (from phar or module directory), + * then external .env (if exists next to phar/directory) which overrides values. + */ + private function loadEnvironmentVariables(): void + { + if (!defined('BP_PHAR_BASE_PATH') || !defined('BP_REAL_BASE_PATH')) { + $dotenv = Dotenv::createMutable(__DIR__ . '/../'); + $dotenv->load(); + return; + } + + $internalEnvPath = BP_PHAR_BASE_PATH; + if (is_readable($internalEnvPath . '/.env')) { + $dotenv = Dotenv::createImmutable($internalEnvPath); + $dotenv->load(); + } + + $externalEnvPath = BP_REAL_BASE_PATH; + if (is_readable($externalEnvPath . '/.env')) { + $dotenv = Dotenv::createImmutable($externalEnvPath); + $dotenv->load(); + } + } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/CacheInterface.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/CacheInterface.php index 1ceede4..ee45dc4 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/CacheInterface.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/CacheInterface.php @@ -11,6 +11,4 @@ interface CacheInterface public function delete(string $key): void; public function clear(): void; - - public function prune(): void; } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyMySqlCache.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyMySqlCache.php index 198d734..31cfb6b 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyMySqlCache.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyMySqlCache.php @@ -41,9 +41,4 @@ class SymfonyMySqlCache implements CacheInterface { $this->cache->clear(); } - - public function prune(): void - { - $this->cache->prune(); - } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyRedisCache.php b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyRedisCache.php index 2793a7d..ff784d4 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyRedisCache.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/framework/Cache/SymfonyRedisCache.php @@ -41,9 +41,4 @@ class SymfonyRedisCache implements CacheInterface { $this->cache->clear(); } - - public function prune(): void - { - $this->cache->prune(); - } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php index 81f7f4d..29c2ac3 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php @@ -6,6 +6,7 @@ namespace App\Handlers; use App\Services\SettingsService; use App\Support\Utils; +use Openguru\OpenCartFramework\Cache\CacheInterface; use Openguru\OpenCartFramework\Http\Request; use Openguru\OpenCartFramework\ImageTool\ImageFactory; use Openguru\OpenCartFramework\QueryBuilder\Builder; @@ -21,52 +22,66 @@ class CategoriesHandler private Builder $queryBuilder; private ImageFactory $image; private SettingsService $settings; + private CacheInterface $cache; - public function __construct(Builder $queryBuilder, ImageFactory $ocImageTool, SettingsService $settings) - { + public function __construct( + Builder $queryBuilder, + ImageFactory $ocImageTool, + SettingsService $settings, + CacheInterface $cache + ) { $this->queryBuilder = $queryBuilder; $this->image = $ocImageTool; $this->settings = $settings; + $this->cache = $cache; } public function index(Request $request): JsonResponse { - $languageId = $this->settings->config()->getApp()->getLanguageId(); - $storeId = $this->settings->get('store.oc_store_id', 0); + $cacheKey = 'categories.index'; - $perPage = $request->get('perPage', 100); + $categories = $this->cache->get($cacheKey); - $categoriesFlat = $this->queryBuilder->newQuery() - ->select([ - 'categories.category_id' => 'id', - 'categories.parent_id' => 'parent_id', - 'categories.image' => 'image', - 'descriptions.name' => 'name', - 'descriptions.description' => 'description', - ]) - ->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); - } - ) - ->join( - new Table(db_table('category_to_store'), 'category_to_store'), - function (JoinClause $join) use ($storeId) { - $join->on('category_to_store.category_id', '=', 'categories.category_id') - ->where('category_to_store.store_id', '=', $storeId); - } - ) - ->where('categories.status', '=', 1) - ->orderBy('parent_id') - ->orderBy('sort_order') - ->get(); + if ($categories === null) { + $languageId = $this->settings->config()->getApp()->getLanguageId(); + $storeId = $this->settings->get('store.oc_store_id', 0); - $categories = $this->buildCategoryTree($categoriesFlat); + $perPage = $request->get('perPage', 100); - $categories = array_slice($categories, 0, $perPage); + $categoriesFlat = $this->queryBuilder->newQuery() + ->select([ + 'categories.category_id' => 'id', + 'categories.parent_id' => 'parent_id', + 'categories.image' => 'image', + 'descriptions.name' => 'name', + 'descriptions.description' => 'description', + ]) + ->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); + } + ) + ->join( + new Table(db_table('category_to_store'), 'category_to_store'), + function (JoinClause $join) use ($storeId) { + $join->on('category_to_store.category_id', '=', 'categories.category_id') + ->where('category_to_store.store_id', '=', $storeId); + } + ) + ->where('categories.status', '=', 1) + ->orderBy('parent_id') + ->orderBy('sort_order') + ->get(); + + $categories = $this->buildCategoryTree($categoriesFlat); + + $categories = array_slice($categories, 0, $perPage); + + $this->cache->set($cacheKey, $categories, 60 * 60 * 24); + } return new JsonResponse([ 'data' => array_map(static function ($category) {