Files
shopPRO/CLAUDE.md
Jacek Pyziak f16f5ce8f8 ver. 0.306: hide transport methods with no available payment methods
When all payment methods for a transport are filtered out by
min_order_amount/max_order_amount limits, the transport is now hidden
from the basket. Prevents showing delivery options with empty payment
method lists (e.g. "Kurier - płatność przy odbiorze" when COD exceeds
max amount).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 17:09:38 +01:00

10 KiB

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 a Domain-Driven Design architecture with Dependency Injection (migration from legacy architecture complete).

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

# 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: 739 tests, 2089 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
│   │   ├── Email/              # Email (PHPMailer wrapper)
│   │   ├── Helpers/            # Helpers (formerly class.S.php)
│   │   ├── Html/               # Html utility
│   │   ├── Image/              # ImageManipulator
│   │   └── Tpl/                # Template engine
│   ├── api/                    # REST API layer (\api\)
│   │   ├── ApiRouter.php       # API router (\api\ApiRouter)
│   │   └── Controllers/        # API controllers (\api\Controllers\)
│   ├── admin/                  # Admin panel layer
│   │   ├── App.php             # Admin router (\admin\App)
│   │   ├── Controllers/        # DI controllers (\admin\Controllers\) — 28 controllers
│   │   ├── Support/            # TableListRequestFactory, Forms/FormRequestHandler, Forms/FormFieldRenderer
│   │   ├── Validation/         # FormValidator
│   │   └── ViewModels/         # Forms/ (FormEditViewModel, FormField, FormTab, FormAction, FormFieldType), Common/ (PaginatedTableViewModel)
│   └── front/                  # Frontend layer
│       ├── App.php             # Frontend router (\front\App)
│       ├── LayoutEngine.php    # Layout engine (\front\LayoutEngine)
│       ├── Controllers/        # DI controllers (\front\Controllers\) — 8 controllers
│       └── Views/              # Static views (\front\Views\) — 11 view classes
├── admin/                      # Admin panel
│   ├── templates/              # Admin view templates
│   └── layout/                 # Admin CSS/JS/icons
├── templates/                  # Frontend view templates
├── libraries/                  # Third-party libraries (Medoo, RedBeanPHP, PHPMailer)
├── tests/                      # PHPUnit tests
│   ├── bootstrap.php
│   ├── stubs/                  # Test stubs (CacheHandler, Helpers, ShopProduct)
│   └── Unit/
│       ├── Domain/             # Repository tests
│       ├── admin/Controllers/  # Controller tests
│       └── api/                # API 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 (ordersPRO + Ekomi)

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)
  • \admin\Controllers\autoload/admin/Controllers/ (lowercase a)
  • \Shared\autoload/Shared/
  • \front\autoload/front/
  • \api\autoload/api/
  • Do NOT use \Admin\ (uppercase A) — the server directory is admin/ (lowercase)
  • \shop\ namespace is deleted — all 12 legacy classes migrated to \Domain\, autoload/shop/ directory removed

Domain-Driven Architecture (migration complete)

All legacy directories (admin/controls/, admin/factory/, admin/view/, front/controls/, front/view/, front/factory/, shop/) have been deleted. All modules now 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)

Domain Modules: Article, Attribute, Banner, Basket, Cache, Category, Client, Coupon, Dashboard, Dictionaries, Integrations, Languages, Layouts, Newsletter, Order, Pages, PaymentMethod, Producer, Product, ProductSet, Promotion, Scontainers, Settings, ShopStatus, Transport, Update, User

Admin Controllers (autoload/admin/Controllers/):

  • DI via constructor (repositories injected)
  • Wired in admin\App::getControllerFactories()

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

API Controllers (autoload/api/Controllers/):

  • DI via constructor, stateless (no session)
  • Wired in api\ApiRouter::getControllerFactories()
  • Auth: X-Api-Key header vs pp_settings.api_key

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()
\api\ApiRouter REST API router — auth, routing, response helpers

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. Docs: docs/FORM_EDIT_SYSTEM.md.

  • ViewModels (admin\ViewModels\Forms\): FormEditViewModel, FormField, FormTab, FormAction, FormFieldType
  • Validation: admin\Validation\FormValidator
  • Rendering: admin\Support\Forms\FormFieldRenderer, admin\Support\Forms\FormRequestHandler
  • Template: admin/templates/components/form-edit.php
  • Table lists: admin\Support\TableListRequestFactory + admin\ViewModels\Common\PaginatedTableViewModel

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)
  • Pattern delete: CacheHandler::deletePattern("shop\\product:{$id}:*")
  • Default TTL: 86400 (24h)
  • Data is serialized — requires unserialize() after get()
  • Config: config.php ($config['redis'])

Code Patterns

New code should follow DI pattern

// 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);

Medoo ORM pitfalls

  • $mdb->delete($table, $where) takes 2 arguments, NOT 3 — has caused bugs
  • $mdb->get() returns null when no record, NOT false
  • After $mdb->insert(), check $mdb->id() to confirm success

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/FORM_EDIT_SYSTEM.md, docs/CHANGELOG.md, docs/TESTING.md
  3. SQL migrations (if DB changes): place in migrations/{version}.sql (e.g. migrations/0.304.sql). NOT in updates/ — build script reads from migrations/ automatically
  4. Commit
  5. Push

Before starting implementation, review current state of docs (see AGENTS.md for full list).

Key Documentation

  • docs/MEMORY.md — project memory: known issues, confirmed patterns, ORM pitfalls, caching conventions
  • docs/PROJECT_STRUCTURE.md — current architecture, layers, cache, entry points, integrations
  • docs/DATABASE_STRUCTURE.md — full database schema
  • docs/TESTING.md — test suite guide and structure
  • docs/FORM_EDIT_SYSTEM.md — form system architecture
  • docs/CHANGELOG.md — version history
  • docs/API.md — REST API documentation (ordersPRO)
  • docs/UPDATE_INSTRUCTIONS.md — how to build client update packages