# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview shopPRO is a PHP e-commerce platform with an admin panel and customer-facing storefront. It uses Medoo ORM (`$mdb`), Redis caching, and is undergoing a migration from legacy architecture to Domain-Driven Design with Dependency Injection. ## PHP Version Constraint **Production runs PHP < 8.0.** Do NOT use: - `match` expressions (use ternary operators or if/else) - Named arguments - Union types (`int|string`) - `str_contains()`, `str_starts_with()`, `str_ends_with()` - Other PHP 8.0+ syntax `composer.json` requires `>=7.4`. ## Commands ### Running Tests ```bash # Full suite (recommended — PowerShell, auto-finds php) ./test.ps1 # Specific file ./test.ps1 tests/Unit/Domain/Product/ProductRepositoryTest.php # Specific test method ./test.ps1 --filter testGetQuantityReturnsCorrectValue # Alternative composer test ``` PHPUnit 9.6 via `phpunit.phar`. Bootstrap: `tests/bootstrap.php`. Config: `phpunit.xml`. Current suite: **610 tests, 1816 assertions**. ### Creating Updates See `docs/UPDATE_INSTRUCTIONS.md` for the full procedure. Updates are ZIP packages in `updates/0.XX/`. Never include `*.md` files, `updates/changelog.php`, or root `.htaccess` in update ZIPs. ## Architecture ### Directory Structure ``` shopPRO/ ├── autoload/ # Autoloaded classes (core codebase) │ ├── Domain/ # Business logic repositories (\Domain\) │ ├── Shared/ # Shared utilities (\Shared\) │ │ ├── Cache/ # CacheHandler, RedisConnection │ │ ├── Helpers/ # Helpers (formerly class.S.php) │ │ └── Tpl/ # Template engine │ ├── admin/ # Admin panel layer │ │ └── Controllers/ # DI controllers (\admin\Controllers\) │ ├── front/ # Frontend layer │ │ ├── App.php # Frontend router (\front\App) │ │ ├── LayoutEngine.php # Layout engine (\front\LayoutEngine) │ │ ├── Controllers/ # DI controllers (\front\Controllers\) │ │ └── Views/ # Static views (\front\Views\) │ └── shop/ # Legacy shop classes (Product, Order, etc.) ├── admin/ # Admin panel │ ├── templates/ # Admin view templates │ └── layout/ # Admin CSS/JS/icons ├── templates/ # Frontend view templates ├── libraries/ # Third-party libraries ├── tests/ # PHPUnit tests │ ├── bootstrap.php │ ├── stubs/ # Test stubs (CacheHandler, Helpers, ShopProduct) │ └── Unit/ │ ├── Domain/ # Repository tests │ └── admin/Controllers/ # Controller tests ├── updates/ # Update packages for clients ├── docs/ # Technical documentation ├── config.php # Database/Redis config (not in repo) ├── index.php # Frontend entry point ├── ajax.php # Frontend AJAX handler ├── admin/index.php # Admin entry point ├── admin/ajax.php # Admin AJAX handler ├── cron.php # CRON jobs (Apilo sync) └── api.php # REST API ``` ### Autoloader Custom autoloader in each entry point (not Composer autoload at runtime). Tries two filename conventions: 1. `autoload/{namespace}/class.{ClassName}.php` (legacy) 2. `autoload/{namespace}/{ClassName}.php` (PSR-4 style, fallback) ### Namespace Conventions (case-sensitive on Linux!) - `\Domain\` → `autoload/Domain/` (uppercase D — new directory) - `\admin\Controllers\` → `autoload/admin/Controllers/` (lowercase a — existing directory) - `\Shared\` → `autoload/Shared/` - `\front\` → `autoload/front/` - `\shop\` → `autoload/shop/` - Do NOT use `\Admin\` (uppercase A) — the server directory is `admin/` (lowercase) ### Domain-Driven Architecture (migration complete for admin + frontend) All modules use this pattern: **Domain Layer** (`autoload/Domain/{Module}/`): - `{Module}Repository.php` — data access, business logic, Redis caching - Constructor DI with `$db` (Medoo instance) - Methods serve both admin and frontend (shared Domain, no separate services) **Admin Controllers** (`autoload/admin/Controllers/`): - DI via constructor (repositories injected) - Wired in `admin\App::route()` via `$newControllers` map **Frontend Controllers** (`autoload/front/Controllers/`): - DI via constructor - Wired in `front\App::getControllerFactories()` **Frontend Views** (`autoload/front/Views/`): - Static classes, no state, no DI — pure rendering ### Key Classes | Class | Purpose | |-------|---------| | `\admin\App` | Admin router — maps URL segments to controllers | | `\front\App` | Frontend router — `route()`, `checkUrlParams()` | | `\front\LayoutEngine` | Frontend layout engine — `show()`, tag replacement | | `\Shared\Helpers\Helpers` | Utility methods (SEO, email, cache clearing) | | `\Shared\Tpl\Tpl` | Template engine — `render()`, `set()` | | `\Shared\Cache\CacheHandler` | Redis cache — `get()`, `set()`, `delete()`, `deletePattern()` | ### Database - ORM: Medoo (`$mdb` global variable, injected via DI in new code) - Table prefix: `pp_` - Key tables: `pp_shop_products`, `pp_shop_orders`, `pp_shop_categories`, `pp_shop_clients` - Full schema: `docs/DATABASE_STRUCTURE.md` ### Form Edit System Universal form system for admin edit views. Uses ViewModels (`FormEditViewModel`, `FormField`, `FormTab`, `FormAction`), validation (`FormValidator`), and rendering (`FormFieldRenderer`). Template: `admin/templates/components/form-edit.php`. Docs: `docs/FORM_EDIT_SYSTEM.md`. ### Caching - Redis via `\Shared\Cache\CacheHandler` (singleton `RedisConnection`) - Key pattern for products: `shop\product:{id}:{lang}:{permutation_hash}` - Clear product cache: `\Shared\Helpers\Helpers::clear_product_cache($id)` - Config: `config.php` (`$config['redis']`) ## Code Patterns ### New code should follow DI pattern ```php // Repository with constructor DI class ExampleRepository { private $db; public function __construct($db) { $this->db = $db; } public function find(int $id): ?array { return $this->db->get('pp_table', '*', ['id' => $id]); } } // Controller wiring (in admin\App or front\App) $repo = new \Domain\Example\ExampleRepository($mdb); $controller = new \admin\Controllers\ExampleController($repo); ``` ### File naming - New classes: `ClassName.php` (no `class.` prefix) - Legacy classes: `class.ClassName.php` (leave until migrated) ### Test conventions - Extend `PHPUnit\Framework\TestCase` - Mock Medoo: `$this->createMock(\medoo::class)` - AAA pattern: Arrange, Act, Assert - Tests mirror source structure: `tests/Unit/Domain/{Module}/{Class}Test.php` ## Workflow (AGENTS.md) When user says **"KONIEC PRACY"**, execute in order: 1. Run tests 2. Update documentation if needed: `docs/DATABASE_STRUCTURE.md`, `docs/PROJECT_STRUCTURE.md`, `docs/FRONTEND_REFACTORING_PLAN.md`, `docs/FORM_EDIT_SYSTEM.md`, `docs/CHANGELOG.md`, `docs/TESTING.md` 3. Prepare update package per `docs/UPDATE_INSTRUCTIONS.md` 4. Commit 5. Push Before starting implementation, review current state of docs (see AGENTS.md for full list). ## Key Documentation - `docs/PROJECT_STRUCTURE.md` — detailed project structure and module status - `docs/REFACTORING_PLAN.md` — Domain migration plan and status - `docs/FRONTEND_REFACTORING_PLAN.md` — frontend migration plan (mostly complete) - `docs/DATABASE_STRUCTURE.md` — full database schema - `docs/TESTING.md` — test suite status and history - `docs/FORM_EDIT_SYSTEM.md` — form system architecture - `docs/CHANGELOG.md` — version history - `docs/UPDATE_INSTRUCTIONS.md` — how to build client update packages