From 80a3cb3814fc5c0900e23a49e1a9fcb939795739 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Sun, 10 May 2026 21:32:38 +0200 Subject: [PATCH] update --- .paul/codebase/architecture.md | 158 +++++++++++++++ .paul/codebase/concerns.md | 137 +++++++++++++ .paul/codebase/conventions.md | 150 ++++++++++++++ .paul/codebase/db_schema.md | 117 +++++++++++ .paul/codebase/integrations.md | 167 +++++++++++++++ .paul/codebase/stack.md | 96 +++++++++ .paul/codebase/structure.md | 201 +++++++++++++++++++ .paul/codebase/tech_changelog.md | 22 ++ .paul/codebase/testing.md | 134 +++++++++++++ .paul/governance/governance_2026-05-10.jsonl | 37 ++++ 10 files changed, 1219 insertions(+) create mode 100644 .paul/codebase/architecture.md create mode 100644 .paul/codebase/concerns.md create mode 100644 .paul/codebase/conventions.md create mode 100644 .paul/codebase/db_schema.md create mode 100644 .paul/codebase/integrations.md create mode 100644 .paul/codebase/stack.md create mode 100644 .paul/codebase/structure.md create mode 100644 .paul/codebase/tech_changelog.md create mode 100644 .paul/codebase/testing.md create mode 100644 .paul/governance/governance_2026-05-10.jsonl diff --git a/.paul/codebase/architecture.md b/.paul/codebase/architecture.md new file mode 100644 index 00000000..e441a335 --- /dev/null +++ b/.paul/codebase/architecture.md @@ -0,0 +1,158 @@ +# Architecture + +**Analysis Date:** 2026-05-10 + +## Pattern Overview + +**Overall:** PrestaShop 1.7.8.x MVC e-commerce monolith with hook-based module extensibility and a Symfony admin layer. + +**Key Characteristics:** +- Front-office: legacy PrestaShop dispatcher + Smarty templates +- Back-office (admin): Symfony 4-style kernel (`app/AppKernel.php`) at non-standard path `iadmin/` +- Hook-based publish/subscribe extension model — modules attach to named hooks +- Core class overrides via `override/classes/` (monkey-patch layer) +- Multi-domain (`drmaterac.pl` + `lulandia.pl`) served from a single install via `.htaccess` rules + +## Layers + +**Entry / Routing Layer:** +- Purpose: Route HTTP requests via mod_rewrite to dispatcher / Symfony kernel +- Contains: `.htaccess` (429 lines), `index.php` (front), `iadmin/index.php` (back-office) +- Used by: All HTTP requests +- Key class: `classes/Dispatcher.php` (overridden in `override/classes/Dispatcher.php`) + +**Controller Layer:** +- Purpose: Handle request-specific logic (cart, product, checkout, search) +- Contains: `controllers/front/*.php` (CartController, OrderController, ProductController…) +- Base classes: `classes/controller/FrontController.php`, `ModuleFrontController.php`, `AdminController.php`, `ProductListingFrontController.php` +- Overrides: `override/classes/controller/FrontController.php`, `override/classes/controller/ProductListingFrontController.php` + +**Model / Domain Layer (ObjectModel):** +- Purpose: ORM-style domain entities (Product, Cart, Order, Customer, Category…) +- Contains: `classes/Product.php`, `classes/Cart.php`, `classes/Order.php`, `classes/Customer.php`, etc. +- Base: `classes/ObjectModel.php` +- Overrides: 31 files in `override/classes/` (e.g. `override/classes/Product.php` adds Google Shopping fields; `override/classes/Cart.php` extends `getOrderTotal()` for ets_promotion pricing) + +**Module Layer (extensibility):** +- Purpose: Optional features attached via hooks; first-class extension mechanism +- Contains: `modules/*/` (50+ installed modules, ~138 entries on disk) +- Custom in this project: `modules/crosssellpro/` (Cross Sell PRO carousel), `modules/caraty/` +- Active third-party: `modules/paynow/`, `modules/santandercredit/`, `modules/empikmarketplace/`, `modules/dpdpoland/`, `modules/pdgoogleanalytycs4pro/`, `modules/fbpixel/`, `modules/ekomiratingsandreviews/`, `modules/ceneo_trustedreviews/`, etc. + +**Theme / Presentation Layer:** +- Purpose: Page templates and visual assets +- Contains: `themes/leo_gstore/` (active child theme, Leo Gstore v1.4) +- Templates: `themes/leo_gstore/templates/*.tpl` (layout, cart, checkout, product…) +- Per-module overrides: `themes/leo_gstore/modules//views/templates/hook/*.tpl` +- Assets: `themes/leo_gstore/assets/cache/` (bundled JS/CSS) + +**Cross-cutting / Hook System:** +- `classes/Hook.php` + `override/classes/Hook.php` (PageCache module integration) +- Hooks dispatch from controllers/templates → fire each registered module's `hook()` method +- Registration table: `ps_hook_module` + +## Data Flow + +**HTTP Request lifecycle (front-office):** + +1. Apache receives request → `.htaccess` rewrite rule (line ~353) routes non-physical URLs to `index.php` +2. `Dispatcher::getInstance()->dispatch()` resolves URL to a controller (e.g. `CartController`) +3. Controller `init()` / `initContent()` runs; sets up `Context` (cart, customer, shop, language) +4. Controller dispatches display hooks (`displayHeader`, `displayShoppingCartFooter`, `actionFrontControllerSetMedia`, etc.) +5. Each subscribing module's `hook()` method runs and may render Smarty partials +6. Smarty renders the theme template (`themes/leo_gstore/templates/cart.tpl`) injecting hook output +7. Response (HTML + CSS + JS) returned to client + +**Admin lifecycle:** +- `iadmin/index.php` boots `app/AppKernel.php` (Symfony) — `iadmin/` is the renamed admin folder (security-by-obscurity) +- Symfony routes to controllers; falls back to legacy `Dispatcher` if Symfony routing fails (`iadmin/index.php` line ~93) + +**API:** +- `webservice/dispatcher.php` — REST endpoint reached via `.htaccess` line ~323 + +**State Management:** +- Per-request state held in `classes/Context.php` singleton (`$context->cart`, `$context->customer`, `$context->shop`, `$context->controller`, `$context->language`) +- Persistent state in MySQL (`materac_*` tables) +- Caching configured but disabled (Memcached driver inactive) + +## Key Abstractions + +**Module:** +- Purpose: Attachable feature unit registering hook callbacks +- Examples: `modules/crosssellpro/crosssellpro.php`, `modules/paynow/paynow.php`, `modules/fbpixel/fbpixel.php` +- Pattern: subclasses `Module` (`classes/Module.php`); `install()` registers hooks; `hook()` methods are invoked dynamically + +**ObjectModel:** +- Purpose: ORM base for domain entities — handles `add()`, `update()`, `delete()`, hydration, validation +- Examples: `classes/Product.php`, `classes/Cart.php`, `classes/Order.php` +- Pattern: declarative `$definition` array describes table + fields + +**Hook (publish/subscribe):** +- Purpose: Decouple core from extensions +- Examples: `displayShoppingCartFooter`, `displayCheckoutSummaryTop`, `displayHeader`, `actionFrontControllerSetMedia` +- Pattern: `Hook::exec('hookName', ...)` dispatches; `$module->hookHookName(...)` receives + +**Context:** +- Purpose: Per-request global container (cart, customer, shop, language, controller) +- Pattern: Singleton — `Context::getContext()` + +**Override:** +- Purpose: Patch core class behavior without editing core +- Examples: `override/classes/Cart.php` (custom totals), `override/classes/Hook.php` (PageCache hooks) +- Pattern: Files in `override/classes/.php` override `classes/.php` via PrestaShop autoloader + +## Entry Points + +**Front-office:** +- Location: `index.php` (root) — invoked implicitly via `.htaccess` +- Triggers: Any non-physical URL on the public domains +- Responsibilities: Bootstrap → Dispatcher → controller dispatch + +**Back-office:** +- Location: `iadmin/index.php` (custom-named admin folder) +- Triggers: Admin URL access +- Responsibilities: Boot `AppKernel`, fall back to legacy dispatcher when needed + +**Web service:** +- Location: `webservice/dispatcher.php` +- Triggers: REST API calls + +**Custom Cross-Sell module:** +- Location: `modules/crosssellpro/crosssellpro.php` +- Hooks registered (in `install()`): `displayShoppingCartFooter`, `displayCheckoutSummaryTop`, `displayHeader`, `actionFrontControllerSetMedia` +- Key methods: `hookDisplayShoppingCartFooter()`, `hookDisplayCheckoutSummaryTop()`, `buildCrossSellProducts()`, `collectAccessoryIds()`, `getCombinationFlags()`, `presentProducts()` +- Templates: `modules/crosssellpro/views/templates/hook/cartCrossSell.tpl`, `…/checkoutCrossSell.tpl` +- Front assets: `modules/crosssellpro/views/css/cartCrossSell.css`, `modules/crosssellpro/views/js/cartCrossSell.js` + +## Error Handling + +**Strategy:** PrestaShop legacy approach — `Tools::displayError()`, exceptions logged to `iadmin/errors.log` and `errors.log` (root). Exceptions in hooks may silently degrade module output. + +**Patterns:** +- `try/catch` rare in custom code; `import-product.php` lacks transaction wrapping/rollback +- Mail send paths in `buy-by-phone.php` minimally handle PHPMailer failures +- `errors.log` at repo root + `iadmin/errors.log` (5 MB historical) — both inside webroot (concern, see `concerns.md`) + +## Cross-Cutting Concerns + +**Logging:** +- File-based: `errors.log` (root), `iadmin/errors.log` +- Symfony Monolog wired in admin via `MonologBundle` + +**Caching:** +- `pagecache` module +- Memcached configured but disabled (`app/config/parameters.php`) +- Smarty compiled templates: `themes/leo_gstore/cache/` + +**Authentication:** +- Customer auth: PrestaShop core (cookies + DB) +- Admin auth: Symfony Security via `iadmin/` + +**Image handling:** +- WebP delivery via `.htaccess` content negotiation + `modules/x13webp/` +- Lazy-loading image override (`pshowlazyimg` override) + +--- + +*Architecture analysis: 2026-05-10* +*Update when major patterns change* diff --git a/.paul/codebase/concerns.md b/.paul/codebase/concerns.md new file mode 100644 index 00000000..8774ea88 --- /dev/null +++ b/.paul/codebase/concerns.md @@ -0,0 +1,137 @@ +# Codebase Concerns + +**Analysis Date:** 2026-05-10 + +> Severity legend: **CRITICAL** (immediate fix), **HIGH** (next sprint), **MEDIUM** (planned), **LOW** (track). + +## Critical Security + +**Hardcoded credentials committed to repository — CRITICAL** +- Files: `buy-by-phone.php` (lines ~11–28: reCAPTCHA secret `6LeJAUUsAAAAAIyCrwFMrsw9yQLPgnCWCOHPcjc8`, SMTP passwords `8njIZnAb`, `kM4BU_F_`), `app/config/parameters.php` (DB password `eRbZ]Ioh-0-2]fM+`, app secret `LStbzv3bfsMaq5dvsVR5wXt8dEpe63IAx2uOHffpbK9gy9x4EZsjWeRM`, cookie keys) +- Why: convenience during development — never moved to env vars +- Impact: full DB compromise, mail account takeover, session forgery if repo or backups leak; secrets remain valid in git history +- Fix: rotate ALL exposed credentials immediately → move to environment variables (or Docker secrets) → load via `getenv()` → purge from git history (`git filter-repo` / BFG) → add the file to `.gitignore` + +**Diagnostic / phpinfo files exposed in webroot — CRITICAL** +- Files: `diag_20792_tmp.php` (2.6 KB), `diag_upload_tmp.php` (4.4 KB), `diag_fix_tmp.php` (14 B), `info.php` (14 B — almost certainly `disconnect()` + reconnect for long-running batch jobs + +## Test Coverage Gaps + +- **Custom modules have NO tests** — `modules/crosssellpro/`, `modules/caraty/` +- **No tests for `import-product.php`** (highest-risk script — bulk DB writes, no rollback) +- **No tests for `buy-by-phone.php`** (handles user input + sends mail) +- Risk: regressions land silently; manual browser testing is the only safety net + +## Documentation Gaps + +- No `README.md` at repo root (only PrestaShop's stock files) +- 31 core overrides — none have purpose comments +- `iadmin/errors.log` retains 26 months of error history but no rotation policy + +## Deletion Candidates (Quick Wins) + +``` +diag_20792_tmp.php +diag_fix_tmp.php +diag_upload_tmp.php +info.php +errors.log +backup_before_patch/ +iadmin/errors.log +iadmin/autoupgrade/prestashop_1.7.5.1.zip +themes/classic.zip # (verify needed) +themes/leo_gstore.zip +``` + +Add to `.gitignore`: `errors.log`, `*.log`, `*.backup`, `backup_before_patch/`, `iadmin/backups/`, `iadmin/errors.log`, `iadmin/autoupgrade/*.zip`. + +--- + +*Concerns audit: 2026-05-10* +*Update as issues are fixed or new ones discovered* diff --git a/.paul/codebase/conventions.md b/.paul/codebase/conventions.md new file mode 100644 index 00000000..0c21dbe0 --- /dev/null +++ b/.paul/codebase/conventions.md @@ -0,0 +1,150 @@ +# Coding Conventions + +**Analysis Date:** 2026-05-10 + +## Naming Patterns + +**Files:** +- PHP class files: PascalCase matching class — `classes/Product.php`, `classes/Cart.php` +- Module entry file: lowercase, matches directory — `modules/crosssellpro/crosssellpro.php` +- Smarty templates: camelCase per module — `cartCrossSell.tpl`, `checkoutCrossSell.tpl` +- Asset files: camelCase — `cartCrossSell.css`, `cartCrossSell.js` + +**Functions / Methods:** +- camelCase — `buildCrossSellProducts()`, `collectAccessoryIds()`, `getCombinationFlags()`, `presentProducts()` (`modules/crosssellpro/crosssellpro.php`) +- Hook handlers: literal prefix `hook` + PascalCase hook name — `hookDisplayShoppingCartFooter()`, `hookActionFrontControllerSetMedia()` + +**Variables:** +- New custom code: `$camelCase` — `$cartProducts`, `$inCartProductIds`, `$productId` +- Legacy / DB-driven code: `$snake_case` — `$id_product`, `$id_cart`, `$id_shop` (mirrors PrestaShop column names; expected when interacting with ObjectModel data) + +**Classes:** +- PascalCase, suffixed `Core` for PrestaShop core — `class ProductCore extends ObjectModel` (`classes/Product.php`) +- Module classes: PascalCase matching folder — `class Crosssellpro extends Module` + +**Hook names (string identifiers):** +- camelCase, registered as strings — `displayShoppingCartFooter`, `displayHeader`, `actionFrontControllerSetMedia` + +## Code Style + +**PHP Formatting:** +- 4-space indentation (no tabs) +- PSR-12-compatible style for new custom code +- Opening braces on same line: `class Crosssellpro extends Module {` +- Single quotes preferred for strings +- Escape filter pattern in templates: `{$product.name|escape:'htmlall':'UTF-8'}` + +**JavaScript Formatting:** +- 2-space indentation +- Legacy ES5 in custom module JS (`var` declarations) — `modules/crosssellpro/views/js/cartCrossSell.js` +- camelCase for functions/variables +- Data-attribute targeting: `[data-crosssellpro-block="1"]` + +**Smarty:** +- `{$variable|filter:'arg':'arg'}` for output with escaping +- `{if}…{/if}`, `{foreach}…{/foreach}`, `{assign}` block syntax + +**Linting:** +- No root-level `.php-cs-fixer.php` or `phpstan.neon` +- Per-module PHPStan/PHP-CS-Fixer config available in some PrestaShop modules (`modules//tests/phpstan/phpstan.neon`) + +## Import Organization + +**PHP:** +- ` + */ +protected function getCombinationFlags(array $productIds) +``` +Property form: +```php +/** @var int Manufacturer identifier */ +public $id_manufacturer; +``` + +**TODO Comments:** +- Format varies (`// TODO`, `// FIXME`, `// HACK`) — found in core, rare in custom code + +## Function Design + +**Size:** +- Module hook methods kept short; logic delegated to private helpers (e.g. `buildCrossSellProducts()`, `presentProducts()`) +- Long legacy scripts exist (`import-product.php` 813 lines) — anti-pattern + +**Parameters:** +- Hook method signatures match PrestaShop dispatcher: `hookXxx(array $params)` where `$params` carries context + +## Module Design (PrestaShop-specific) + +**Module class skeleton:** +- Constructor sets `$this->name`, `$this->tab`, `$this->version`, `$this->author`, `$this->bootstrap`, then `parent::__construct()` +- `install()` calls `parent::install()` and chains `$this->registerHook(...)` calls +- `uninstall()` calls `parent::uninstall()` (cleans hook table) +- Hook handlers named `hook()` + +**Template overrides:** +- Module ships defaults in `modules//views/templates/hook/` +- Theme overrides resolved at `themes//modules//views/templates/hook/` + +**Assets:** +- Registered in `hookActionFrontControllerSetMedia()` via `$this->context->controller->registerStylesheet()` / `registerJavascript()` + +## Override Design + +- Place in `override/classes/.php` or `override/classes/controller/.php` +- Extend the core class verbatim and add/override methods only +- Document the *why* of each override (currently undocumented in this project — see `concerns.md`) + +--- + +*Convention analysis: 2026-05-10* +*Update when patterns change* diff --git a/.paul/codebase/db_schema.md b/.paul/codebase/db_schema.md new file mode 100644 index 00000000..92c85191 --- /dev/null +++ b/.paul/codebase/db_schema.md @@ -0,0 +1,117 @@ +# Database Schema + +**Analysis Date:** 2026-05-10 + +## Database Engine + +- **MySQL with InnoDB** — `app/config/parameters.php` +- **Schema:** `admin_drmaterac` +- **Table prefix:** `materac_` (referenced as `ps_*` in PrestaShop convention; effective name is `materac_`) + +Examples below use the `ps_` prefix per PrestaShop documentation; in this install they map to `materac_*`. + +## ORM / Migration Approach + +- **Front-office:** PrestaShop `ObjectModel` (in `classes/ObjectModel.php`). Each domain class declares a `$definition` array with `table`, `primary`, `multilang`, `fields`. `add()` / `update()` / `delete()` operate on the corresponding row. +- **Admin / Symfony:** Doctrine ORM bundled (`DoctrineBundle` in `app/AppKernel.php`). +- **Migrations:** PrestaShop has no first-class migration tool. Schema is shipped with core in `install/` SQL dumps; modules create tables in their `install()` method. + +## Custom Tables Created by This Project + +**The custom Cross Sell PRO module creates NO custom tables.** +- `modules/crosssellpro/crosssellpro.php::install()` only registers hooks (`displayShoppingCartFooter`, `displayCheckoutSummaryTop`, `displayHeader`, `actionFrontControllerSetMedia`) +- No `sql/` directory; no `Db::getInstance()->execute("CREATE TABLE ...")` call +- All cross-sell relationships read from PrestaShop core table `ps_accessory` + +Other custom code: +- `import-product.php` updates existing `ps_product*` tables from external XML feed — does not create tables +- `buy-by-phone.php` does not touch the database +- `modules/caraty/` — investigate when relevant; not analyzed in detail + +## Custom Columns Added Via Override + +`override/classes/Product.php` extends `ps_product` / `ps_product_lang` with Google Shopping fields (declared in the `$definition` array — actual ALTER TABLE must have been run manually or via a separate install script): +- `in_google_shopping` — BOOL, shop-scoped +- `product_name_google_shopping` — STRING, lang-scoped +- `product_short_desc_google_shopping` — HTML, lang-scoped +- `custom_label_0` … `custom_label_4` — STRING, lang-scoped + +These are unrelated to the cross-sell module. + +## PrestaShop Core Tables Touched by Cross Sell PRO + +| Table | Purpose | How module uses it | +|---|---|---| +| `ps_product` | Product master data | Filtered by `active = 1` and shop visibility | +| `ps_accessory` | Related-product associations | Read via `Product::getAccessoriesLight($id_lang, $id_product)` | +| `ps_product_attribute` | Product variants/combinations | `getCombinationFlags()` checks if a product has combinations (decides direct add-to-cart vs link to product page) | +| `ps_cart` | Cart entity | Reached via `$context->cart` | +| `ps_cart_product` | Items currently in cart | `Cart::getProducts(true)` excludes already-in-cart products from cross-sell list | +| `ps_product_lang` | Multilingual product names/descriptions | Used by `ProductListingPresenter` | +| `ps_product_shop` | Shop-specific visibility | `WHERE product_shop.visibility IN ('both', 'catalog')` | +| `ps_image` | Product images | Cover image fetched by `ImageRetriever` | +| `ps_category_lang` | Category names | Used in product presentation | +| `ps_feature`, `ps_feature_value`, `ps_product_feature` | Product features | May appear in presented data | +| `ps_hook_module` | Hook registrations | Written by `parent::install()` when module installs | + +## Key Queries (in `modules/crosssellpro/crosssellpro.php`) + +**Combination check** (lines ~237–243): +```sql +SELECT p.id_product, COUNT(pa.id_product_attribute) AS combinations +FROM `ps_product` p +LEFT JOIN `ps_product_attribute` pa ON (pa.id_product = p.id_product) +WHERE p.id_product IN (...) +GROUP BY p.id_product +``` + +**Visibility filter** (lines ~264–275): +```sql +SELECT p.id_product +FROM `ps_product` p +[Shop::addSqlAssociation] +WHERE p.id_product IN (...) + AND p.active = 1 + AND product_shop.visibility IN ('both', 'catalog') +ORDER BY FIELD(p.id_product, ...) +``` + +## Relationships (Cross-Sell Data Path) + +``` +ps_cart (id_cart) + └─1:N─ ps_cart_product (id_product) + └─1:1─ ps_product (id_product) + └─1:N─ ps_accessory (id_product_2) + └─1:1─ ps_product [the cross-sell candidate] + ├─1:N─ ps_product_attribute (combinations) + ├─1:N─ ps_image (cover) + └─1:N─ ps_product_lang (name, description) +``` + +## Module Install / Uninstall + +**Install** — `modules/crosssellpro/crosssellpro.php` lines ~37–44: +```php +return parent::install() + && $this->registerHook('displayShoppingCartFooter') + && $this->registerHook('displayCheckoutSummaryTop') + && $this->registerHook('displayHeader') + && $this->registerHook('actionFrontControllerSetMedia'); +``` + +**Uninstall** — lines ~46–48: +```php +return parent::uninstall(); +``` + +`parent::install()` / `parent::uninstall()` write to / clean up `ps_module` and `ps_hook_module`. + +## Backups + +- Snapshots of the schema are present in `iadmin/backups/` (e.g. `1698930967-7683b7af.sql.bz2`) — **see `concerns.md`**: these are inside the webroot and should be moved out or denied via `.htaccess`. + +--- + +*DB schema analysis: 2026-05-10* +*Update when adding/modifying tables, modules, or overrides that affect schema* diff --git a/.paul/codebase/integrations.md b/.paul/codebase/integrations.md new file mode 100644 index 00000000..91ed7246 --- /dev/null +++ b/.paul/codebase/integrations.md @@ -0,0 +1,167 @@ +# External Integrations + +**Analysis Date:** 2026-05-10 + +## APIs & External Services + +### Payment Gateways + +- **PayNow (BLIK / bank transfer / card)** — `modules/paynow/paynow.php` (v1.6.35) + - SDK: `pay-now-php-sdk` (Guzzle HTTP, PSR-7) + - Auth: API key / signature (configured in module back-office) + - Functions: payment authorization, refund, GDPR + - Webhook: payment status notification with retry/stop logic + +- **Santander eRaty (installment credit)** — `modules/santandercredit/santandercredit.php` (v5.5) + - PL-specific Santander Consumer Bank + - Calculator widget + simulator iframe + - Hooks: order state confirmation + +- **Check Payment** — `modules/ps_checkpayment/` +- **Wire Transfer** — `modules/ps_wirepayment/` + +### Marketplace + +- **Empik Marketplace** — `modules/empikmarketplace/empikmarketplace.php` (v1.6.5) + - Guzzle HTTP client + - Symfony DI container + - Sync orders, products, inventory with Empik.com + - Cron controllers — `modules/empikmarketplace/controllers/cron/` + +### Shipping & Logistics + +- **DPD Polska** — `modules/dpdpoland/dpdpoland.php` + - Custom API integration — `modules/dpdpoland/config.api.php` + - Manifest, package, pickup webservices + - PDF label generation + +### Reviews & Ratings + +- **Ceneo.pl Trusted Reviews** — `modules/ceneo_trustedreviews/ceneo_trustedreviews.php` (v1.0.1) +- **eKomi Ratings & Reviews** — `modules/ekomiratingsandreviews/ekomiratingsandreviews.php` + - API: `https://plugins-dashboard.ekomiapps.de/api/v1/order` + - Validation: `https://api.ekomi.de/v3/getSettings` + - Cron-based export +- **eKomi SFF (Shop Feedback Form)** — `modules/ekomiSff/` +- **PrestaShop Product Comments** — `modules/productcomments/` + +### Analytics & Tracking + +- **Google Analytics 4 Pro** — `modules/pdgoogleanalytycs4pro/pdgoogleanalytycs4pro.php` (v1.0.2) + - SDK: `br33f/php-ga4-mp` (GA4 Measurement Protocol) + - Enhanced conversions with phone (uses `libphonenumber-for-php`) + - Refund tracking, Google Ads (AW) conversions, Merchant Center + +- **Google Merchant Center Pro** — `modules/pdgooglemerchantcenterpro/` + +- **BAE Commerce Tracking** — `modules/baecommercetracking/baecommercetracking.php` (v1.0.6) + - GA + Google Ads conversion + Facebook Pixel events + +- **Facebook Conversion Pixel** — `modules/fbpixel/fbpixel.php` (v2.0.2) + - Purchase event injection at order confirmation + +- **20+ PrestaShop stats modules** — `modules/dash*`, `modules/stats*` + +### Customer Communication + +- **Smartsupp Live Chat** — `modules/smartsupp/smartsupp.php` + +### Spam / Bot Protection + +- **Google reCAPTCHA** — `modules/eicaptcha/vendor/google/recaptcha/` + - Also referenced in `buy-by-phone.php` (key hardcoded — see `concerns.md`) + +### Content / SEO + +- **XML Feeds** — `modules/xmlfeeds/` +- **Google Sitemap** — `modules/gsitemap/` +- **Advanced SEO Pro** — `modules/arseopro/` +- **Link Rewriter** — `modules/x13linkrewrite/` + +### Product / Content Management + +- **App Page Builder** — `modules/appagebuilder/` (CodeMirror editor) +- **Cross-Sell Pro (custom)** — `modules/crosssellpro/` +- **Image Hover Effects** — `modules/ybc_productimagehover/` +- **WebP Optimization** — `modules/x13webp/` (uses `.htaccess` rewrite) + +### GDPR / Security + +- **GDPR Data Privacy** — `modules/ps_dataprivacy/` +- **Cookies Plus** — `modules/cookiesplus/` +- **Security Watcher** — `modules/securitywatcher/` + +### External XML Feed (custom script) + +- `import-product.php` fetches `https://amz.com.pl/bazy-produktow-export/produkty-amz.xml` for batch product updates + +## Data Storage + +**Database:** +- MySQL with InnoDB +- Connection: `app/config/parameters.php` (DB host, name, user, password — currently committed; see `concerns.md`) +- DB prefix: `materac_` (schema `admin_drmaterac`) +- ORM: PrestaShop `ObjectModel` (front-office), Doctrine (admin Symfony layer) + +**File Storage:** +- Local filesystem (PrestaShop default) +- Image variants in `img/` (PrestaShop core layout) +- WebP variants generated by `modules/x13webp/` + +**Caching:** +- Memcached configured but disabled — `app/config/parameters.php` (`ps_caching: CacheMemcached`, `ps_cache_enable: false`) +- `modules/pagecache/` — page-level cache module (uses override of `Hook.php`) + +## Authentication & Identity + +**Customer auth:** +- PrestaShop core (cookies + DB) + +**Admin auth:** +- Symfony Security via `iadmin/` AppKernel +- Custom-named admin folder is *not* a security control (security through obscurity — see `concerns.md`) + +**Service auth (per-integration):** +- API keys / OAuth tokens stored in PrestaShop `Configuration` (DB `ps_configuration` / `materac_configuration` table) per module + +## Email / SMTP + +- SMTP at `127.0.0.1:25` — `app/config/parameters.php` +- PrestaShop mail templates: `mails/{en,pl}/` +- Custom transactional: `buy-by-phone.php` uses bundled `phpmailer/` (with hardcoded SMTP credentials — see `concerns.md`) + +## Multi-Domain Routing + +- Two domains served from one install — `.htaccess` + - `drmaterac.pl` (primary) + - `lulandia.pl` (secondary) +- Per-domain image rewrite + WebP fallback rules + +## Webhooks + +**Incoming:** +- PayNow payment notifications — `modules/paynow/` controllers +- Empik Marketplace cron callbacks — `modules/empikmarketplace/controllers/cron/` +- eKomi cron-based order export + +**Outgoing:** +- GA4 Measurement Protocol — `modules/pdgoogleanalytycs4pro/` +- Facebook Pixel events — `modules/fbpixel/` +- Empik order/inventory sync — `modules/empikmarketplace/` + +## Environment Configuration + +- All secrets currently in `app/config/parameters.php` (committed) — DB password, app secret, cookie keys +- No `.env` / `.env.example` mechanism in use +- **Rotation required** for any credential exposed in git history (see `concerns.md`) + +## CI/CD & Deployment + +- No CI workflows detected (no `.github/workflows/`, no `.gitlab-ci.yml`) +- Deploy method appears manual / FTP — daily Polish changelog at `changelog/YYYY-MM-DD.md` +- `iadmin/autoupgrade/` contains `prestashop_1.7.5.1.zip` — appears to be an upgrade payload left in webroot + +--- + +*Integration audit: 2026-05-10* +*Update when adding/removing external services* diff --git a/.paul/codebase/stack.md b/.paul/codebase/stack.md new file mode 100644 index 00000000..b584df13 --- /dev/null +++ b/.paul/codebase/stack.md @@ -0,0 +1,96 @@ +# Technology Stack + +**Analysis Date:** 2026-05-10 + +## Languages + +**Primary:** +- PHP 7.4 / 8.2.x runtime — All application code (PrestaShop targets PHP 7.4; current server reports 8.2.12) +- JavaScript (ES5/ES6 transpiled) — Theme assets and module front-end behavior + +**Secondary:** +- Smarty templates (`.tpl`) — Front-end rendering layer +- Twig templates — Symfony admin layer +- Sass/SCSS — Theme styling (`themes/leo_gstore/config.rb` Compass config) +- HTML5/CSS3 — Presentation +- SQL (MySQL) — Data layer + +## Runtime + +**Environment:** +- PHP (declared 7.4 in PrestaShop core; current PHP-CLI 8.2.12) — `app/AppKernel.php` +- Apache web server with `mod_rewrite` — `.htaccess` (429 lines of rewrite rules) +- MySQL with InnoDB — `app/config/parameters.php` + +**Package Manager:** +- Composer (PHP) — `composer.lock` present at root +- npm (JS, theme-only) — `themes/package-lock.json` + +## Frameworks + +**Core:** +- PrestaShop 1.7.8.11 — `app/AppKernel.php` line 35 +- Symfony (FrameworkBundle, SecurityBundle, TwigBundle, MonologBundle, SwiftmailerBundle, DoctrineBundle) — `app/AppKernel.php` +- Doctrine ORM — used for admin/back-office Symfony layer +- Smarty — front-office template engine — `config/smarty.config.inc.php`, `config/smartyfront.config.inc.php` + +**Testing:** +- PHPUnit (~5.7) — present only in select PrestaShop modules (`modules/ps_facetedsearch/`, `modules/gamification/`) +- Mockery — `modules/ps_facetedsearch/tests/php/` +- PHPStan via `prestashop/php-dev-tools` — `modules/*/tests/phpstan/phpstan.neon` (40+ modules) +- **No root-level test setup; custom modules have no tests** + +**Build/Dev:** +- Babel 7.0.0-rc.1 — `themes/package-lock.json` +- Compass/Sass — `themes/leo_gstore/config.rb` +- Pre-built theme bundles — `themes/leo_gstore/assets/cache/*.js`, `themes/leo_gstore/assets/cache/*.css` + +## Key Dependencies + +**Critical (PHP):** +- Guzzle HTTP client (v6/v7) — used by paynow, empikmarketplace, smartsupp +- Symfony components (Cache, DI, YAML, FileSystem) — core + modules +- PSR-7/PSR-11/PSR-15 interfaces — HTTP messaging +- `pay-now-php-sdk` — payment integration in `modules/paynow/` +- `br33f/php-ga4-mp` — GA4 Measurement Protocol — `modules/pdgoogleanalytycs4pro/` +- `libphonenumber-for-php` — phone validation (GA4 enhanced conversions) +- `google/recaptcha` — `modules/eicaptcha/vendor/google/recaptcha/` + +**Critical (JS):** +- jQuery — bundled in theme (`themes/leo_gstore/assets/cache/bottom-*.js`) +- Slick carousel — `themes/leo_gstore/assets/js/custom.js` +- Moment.js — `js/date.js` +- CodeMirror — `modules/advancedpopupcreator/` + +## Configuration + +**Environment:** +- Database/secrets in `app/config/parameters.php` (plain PHP — **secrets currently committed**, see concerns.md) +- Symfony YAML — `app/config/config.yml`, `app/config/parameters.yml` +- Constants: `config/defines.inc.php` (paths, `_PS_ADMIN_DIR_` etc.) +- Bootstrap: `config/bootstrap.php`, `config/config.inc.php` +- Locale: pl-PL — `app/config/parameters.php` +- DB prefix: `materac_` (schema `admin_drmaterac`) + +**Build:** +- Theme assets: pre-bundled to `themes/leo_gstore/assets/cache/` +- No root `composer.json` build pipeline; modules ship pre-built + +## Platform Requirements + +**Development:** +- Apache + PHP 7.4+ + MySQL stack +- Composer for PHP dependencies +- Node/npm only required for theme rebuild + +**Production:** +- Shared/dedicated hosting with Apache + mod_rewrite +- SMTP transport configured to `127.0.0.1:25` — `app/config/parameters.php` +- Memcached configured but disabled (`ps_caching: CacheMemcached`, `ps_cache_enable: false`) +- WebP image delivery via `.htaccess` content negotiation + `modules/x13webp/` +- Multi-domain: serves both `drmaterac.pl` and `lulandia.pl` from same install — `.htaccess` + +--- + +*Stack analysis: 2026-05-10* +*Update after major dependency changes* diff --git a/.paul/codebase/structure.md b/.paul/codebase/structure.md new file mode 100644 index 00000000..662bbb38 --- /dev/null +++ b/.paul/codebase/structure.md @@ -0,0 +1,201 @@ +# Codebase Structure + +**Analysis Date:** 2026-05-10 + +## Directory Layout + +``` +drmaterac.pl/ +├── index.php # Front-office entry (invoked via .htaccess rewrite) +├── .htaccess # 429-line rewrite rules (multi-domain routing, SEO redirects) +├── autoload.php # PSR-4 autoloader bootstrap +├── composer.lock # PHP dependency lock +├── app/ # Symfony AppKernel + admin config +│ ├── AppKernel.php # PrestaShop 1.7.8.11 kernel +│ ├── AppCache.php +│ └── config/ # parameters.php, parameters.yml, config.yml, services/ +├── classes/ # PrestaShop core classes (ObjectModel-based) +│ ├── Product.php, Cart.php, Order.php, Customer.php, … +│ ├── Dispatcher.php, Hook.php, Context.php, ObjectModel.php +│ ├── controller/ # FrontController, AdminController, ModuleFrontController… +│ └── db/, cache/ # Database + caching primitives +├── controllers/ # Page controllers (dispatch targets) +│ ├── front/ # CartController, OrderController, ProductController… +│ └── admin/ # Legacy admin (Symfony preferred via iadmin/) +├── modules/ # All installed modules (~138 entries; 50+ active) +│ ├── crosssellpro/ # CUSTOM — Cross Sell PRO carousel module +│ │ ├── crosssellpro.php +│ │ └── views/{templates/hook,css,js}/ +│ ├── caraty/ # CUSTOM — site-specific module +│ ├── paynow/, santandercredit/, ps_checkpayment/, ps_wirepayment/ # Payments +│ ├── empikmarketplace/, dpdpoland/ # Marketplace + shipping +│ ├── pdgoogleanalytycs4pro/, fbpixel/, baecommercetracking/ # Analytics +│ ├── ekomiratingsandreviews/, ceneo_trustedreviews/, ekomiSff/ # Reviews +│ └── pagecache/, leo*/, ets_megamenu/, advancedpopupcreator/, … +├── override/ # Core class overrides (107 files; 31 in override/classes/) +│ └── classes/ # Cart.php, CartRule.php, Product.php, Hook.php, Dispatcher.php, +│ # FrontController.php, ProductListingFrontController.php … +├── themes/ # Theme layer +│ ├── leo_gstore/ # ACTIVE child theme (Leo Gstore v1.4) +│ │ ├── templates/ # *.tpl (layout, cart, checkout, product, …) +│ │ ├── modules/ # Per-module template overrides +│ │ ├── assets/cache/ # Pre-bundled JS/CSS +│ │ └── config.xml, config.rb +│ └── _libraries/, classic.zip, leo_gstore.zip +├── config/ # Bootstrap + Smarty config (NOT app/config/) +│ ├── config.inc.php, defines.inc.php, bootstrap.php +│ └── smarty*.config.inc.php +├── src/ # Custom PSR-4 namespaced code +│ └── Core/Localization/Locale.php +├── translations/{en,pl}/ # Localization files +├── mails/{en,pl}/ # Email templates +├── js/ # Global JavaScript (jquery/, date.js) +├── vendor/ # Composer dependencies +├── webservice/dispatcher.php # REST API dispatcher +├── iadmin/ # CUSTOM-NAMED admin folder (5 MB errors.log inside) +│ ├── index.php # Symfony admin entry +│ ├── backups/, filemanager/, autoupgrade/, api/, export/, import/ +│ └── errors.log # ⚠ committed log (see concerns.md) +├── changelog/ # Daily Polish changelog markdown files +├── docs/ # Project docs +├── localization/ # Localization data +├── scripts/, calculate/ # Utility scripts +├── backup_before_patch/ # ⚠ committed *.backup files (see concerns.md) +├── buy-by-phone.php # Form handler — sends order-by-phone email +├── import-product.php # 813-line XML feed importer +├── category-description.php # Category description endpoint +├── diag_*_tmp.php, info.php # ⚠ diagnostic files (see concerns.md) +└── errors.log # PHP error log (committed; should be gitignored) +``` + +## Directory Purposes + +**`classes/`** +- Purpose: PrestaShop core domain layer (ObjectModel + service classes) +- Key files: `Product.php`, `Cart.php`, `Hook.php`, `Dispatcher.php`, `Context.php`, `ObjectModel.php` +- Subdirectories: `controller/` (controller base classes), `db/`, `cache/` + +**`controllers/front/`** +- Purpose: Front-office page controllers — dispatch targets matched by URL +- Key files: `CartController.php`, `OrderController.php`, `ProductController.php`, `CategoryController.php` + +**`modules/`** +- Purpose: Extension layer — all features beyond core live here as hook-registered modules +- Key custom: `modules/crosssellpro/crosssellpro.php` (cross-sell carousel) +- Key third-party: payment (paynow, santandercredit), shipping (dpdpoland), marketplace (empikmarketplace), analytics (pdgoogleanalytycs4pro, fbpixel), reviews (ekomi*, ceneo_*) + +**`modules/crosssellpro/`** — CUSTOM module (Pyziak Jacek) +- `crosssellpro.php` — module class (~335 lines, v1.1.6) +- `views/templates/hook/cartCrossSell.tpl` — cart carousel +- `views/templates/hook/checkoutCrossSell.tpl` — checkout carousel +- `views/css/cartCrossSell.css` — styles (~159 lines) +- `views/js/cartCrossSell.js` — carousel + AJAX add-to-cart (~99 lines) + +**`override/classes/`** +- Purpose: Monkey-patch PrestaShop core without editing core +- Key files: `Cart.php`, `CartRule.php`, `Product.php`, `Hook.php`, `Dispatcher.php`, `controller/FrontController.php`, `controller/ProductListingFrontController.php` + +**`themes/leo_gstore/`** +- Purpose: Active child theme (`config.xml`) +- Templates: `templates/*.tpl` (page-level), `modules//views/templates/hook/*.tpl` (module override) +- Assets: pre-bundled in `assets/cache/` + +**`app/`** +- Purpose: Symfony kernel + admin config (NOT to be confused with `config/`) +- Key files: `AppKernel.php`, `config/parameters.php` (DB credentials — currently committed), `config/config.yml` + +**`config/`** +- Purpose: Legacy PrestaShop bootstrap + Smarty configuration +- Key files: `config.inc.php`, `defines.inc.php`, `bootstrap.php`, `smarty.config.inc.php` + +**`iadmin/`** +- Purpose: Renamed back-office (PrestaShop default is `admin/`) +- Note: contains `errors.log` (5 MB), `backups/` (SQL dumps), `autoupgrade/` payload — investigate cleanup + +## Key File Locations + +**Entry Points:** +- `index.php` — front-office (rewrite target) +- `iadmin/index.php` — back-office (Symfony AppKernel) +- `webservice/dispatcher.php` — REST API + +**Configuration:** +- `app/config/parameters.php` — DB / mail / secrets (PHP) +- `app/config/parameters.yml` — Symfony parameters +- `app/config/config.yml` — Symfony service config +- `config/defines.inc.php` — path constants +- `.htaccess` — Apache rewrite rules (multi-domain) + +**Core Logic:** +- Custom cross-sell: `modules/crosssellpro/crosssellpro.php` +- Custom site logic: `modules/caraty/caraty.php` +- Domain models: `classes/Product.php`, `classes/Cart.php`, `classes/Order.php` +- Core overrides: `override/classes/` + +**Testing:** +- No project-level test suite +- Examples (third-party module tests): `modules/ps_facetedsearch/tests/`, `modules/gamification/tests/` + +**Documentation:** +- `AGENTS.md` (root) +- `docs/` (project docs) +- `changelog/YYYY-MM-DD.md` (daily Polish changelog) + +## Naming Conventions + +**Files:** +- PHP classes: `PascalCase.php` (e.g. `classes/Product.php`) +- Module entry file: lowercase matching directory (`modules/crosssellpro/crosssellpro.php`) +- Smarty templates: `kebab-case.tpl` or `camelCase.tpl` per module (`cartCrossSell.tpl`) +- Asset files: `camelCase.{js,css}` per module +- Templates in theme module overrides: match hook names (`displayShoppingCartFooter.tpl` style not always followed; module-defined name common) + +**Directories:** +- Module folders: lowercase, no underscores preferred (`crosssellpro`, `paynow`, `dpdpoland`) +- Snake_case allowed for compound names (`empikmarketplace`, `ets_megamenu`, `leo_gstore`) + +**Special Patterns:** +- Module hook handler: `hook()` in module class — e.g. `hookDisplayShoppingCartFooter()` +- Hook registration uses camelCase string: `$this->registerHook('displayShoppingCartFooter')` +- Theme module template path: `themes//modules//views/templates/hook/.tpl` + +## Where to Add New Code + +**New Module / Feature:** +- Primary: `modules//.php` (extends `Module`) +- Templates: `modules//views/templates/hook/.tpl` +- Theme override: `themes/leo_gstore/modules//views/templates/hook/.tpl` +- CSS/JS: `modules//views/css/`, `modules//views/js/` + +**Core class extension:** +- Place in `override/classes/.php` extending the core class — NOT inside `classes/` + +**New page controller (rare; usually a module):** +- `controllers/front/Controller.php` + +**New translation:** +- `translations/{en,pl}/.{xlf,php}` + +**New PSR-4 utility:** +- `src//.php` (autoloader configured in `composer.lock`) + +## Special Directories + +**`backup_before_patch/`** +- Purpose: Manual backup of search engine module pre-patch +- Source: Manual snapshot +- Committed: Yes (should be removed — see `concerns.md`) + +**`themes/leo_gstore/cache/`** +- Purpose: Compiled Smarty templates +- Source: Auto-generated at runtime +- Committed: Should be gitignored (verify) + +**`iadmin/backups/`** +- Purpose: PrestaShop database backups (e.g. `1698930967-7683b7af.sql.bz2`) +- Committed: Yes (security risk — see `concerns.md`) + +--- + +*Structure analysis: 2026-05-10* +*Update when directory structure changes* diff --git a/.paul/codebase/tech_changelog.md b/.paul/codebase/tech_changelog.md new file mode 100644 index 00000000..93d8656e --- /dev/null +++ b/.paul/codebase/tech_changelog.md @@ -0,0 +1,22 @@ +# Technical Changelog + +**Started:** 2026-05-10 + +Chronological log of technical changes (architecture decisions, refactors, dependency upgrades, schema changes, security fixes). Populated over time by `/paul:apply` and ad-hoc edits. + +Format per entry: +``` +## YYYY-MM-DD — short title +- What changed (file paths) +- Why +- Impact / migration notes +``` + +--- + +## 2026-05-10 — Initial codebase mapping +- Created `.paul/codebase/` (stack, architecture, structure, conventions, testing, integrations, concerns, db_schema, tech_changelog) +- Why: bootstrap PAUL workflow; document the PrestaShop 1.7.8.11 install + custom Cross Sell PRO module before further work +- Impact: future phases reference these documents instead of re-exploring the codebase + +--- diff --git a/.paul/codebase/testing.md b/.paul/codebase/testing.md new file mode 100644 index 00000000..5f893f07 --- /dev/null +++ b/.paul/codebase/testing.md @@ -0,0 +1,134 @@ +# Testing Patterns + +**Analysis Date:** 2026-05-10 + +## Test Framework + +**Runner:** +- PHPUnit (~5.7) — present only in select PrestaShop-shipped modules, NOT at project root +- Mockery — used by `modules/ps_facetedsearch/` + +**Assertion Library:** +- PHPUnit built-in assertions +- Mockery for mocks: `Mockery::mock(Configuration::class)` + +**Run Commands:** +- **No project-level test command exists.** Custom modules (`modules/crosssellpro/`, `modules/caraty/`) have no test suites. +- For modules that ship tests: +```bash +cd modules/ps_facetedsearch && php vendor/bin/phpunit -c tests/php/phpunit.xml +cd modules/gamification && php vendor/bin/phpunit +``` + +## Test File Organization + +**Location:** +- Per-module: `modules//tests/` +- No root-level `tests/` directory +- No collocated tests + +**Examples (third-party PrestaShop modules):** +- `modules/ps_facetedsearch/tests/php/FacetedSearch/Filters/BlockTest.php` +- `modules/gamification/tests/unit/AdviceTest.php` +- `modules/gamification/tests/functional/` + +**Naming:** +- `*Test.php` suffix +- PSR-4 namespace under `Tests\` + +**Custom modules in this project:** +- `modules/crosssellpro/` — **NO tests directory** +- `modules/caraty/` — **NO tests directory** + +## Test Structure + +Example from `modules/ps_facetedsearch/tests/php/FacetedSearch/Filters/BlockTest.php`: +```php +namespace PrestaShop\Module\FacetedSearch\Tests\Filters; + +use Mockery; +use Mockery\Adapter\Phpunit\MockeryTestCase; + +class BlockTest extends MockeryTestCase +{ + protected function setUp() + { + $mock = Mockery::mock(Configuration::class); + $mock->shouldReceive('get')->andReturnUsing(function ($arg) { /* … */ }); + } +} +``` + +PHPUnit config example (`modules/gamification/phpunit.xml`): +```xml + + + tests/unit/ + tests/functional/ + + + + + +``` + +## Mocking + +**Framework:** +- Mockery (in modules that test, e.g. `ps_facetedsearch`) + +**Pattern:** +```php +$mock = Mockery::mock(Configuration::class); +$mock->shouldReceive('get')->andReturn('value'); +``` + +## Static Analysis + +**PHPStan:** +- Configured in 40+ PrestaShop modules via `prestashop/php-dev-tools` +- Standard config — `modules//tests/phpstan/phpstan.neon`: +```neon +includes: + - %currentWorkingDirectory%/vendor/prestashop/php-dev-tools/phpstan/ps-module-extension.neon +parameters: + paths: + - ../../.php + level: 5 +``` +- **No project-root PHPStan config.** + +**PHP-CS-Fixer:** +- Some module `composer.json` scripts reference it: `"lint": ["php-cs-fixer fix --no-interaction --dry-run --diff"]` +- **No project-root config.** + +## Coverage + +- No project-wide coverage target +- `modules/gamification/phpunit.xml` writes Clover output to `build/clover.xml` +- No CI enforcement detected + +## Test Types + +**Unit tests:** Present in some PS modules (`modules/gamification/tests/unit/`). +**Functional tests:** Present in `modules/gamification/tests/functional/`, `modules/ps_facetedsearch/tests/php/`. +**E2E:** None detected. + +## Inferred Testing Strategy for This Project + +Custom code (`modules/crosssellpro/`, `modules/caraty/`, `import-product.php`, `buy-by-phone.php`) is tested **manually** in browser: +- Verify cross-sell carousel renders on cart page (`/cart`) and checkout summary +- Verify "add to cart" works for products without combinations +- Verify products with combinations link to product detail page +- Smoke-test admin via `iadmin/` +- No regression suite — every change is risk + +**If adding tests in the future:** +- Use PrestaShop's `prestashop/php-dev-tools` package per-module pattern +- Place under `modules/crosssellpro/tests/` mirroring PS conventions +- Mock `Db`, `Context`, `Module` core dependencies via Mockery + +--- + +*Testing analysis: 2026-05-10* +*Update when test patterns change* diff --git a/.paul/governance/governance_2026-05-10.jsonl b/.paul/governance/governance_2026-05-10.jsonl new file mode 100644 index 00000000..71553803 --- /dev/null +++ b/.paul/governance/governance_2026-05-10.jsonl @@ -0,0 +1,37 @@ +{"ts":"2026-05-10T17:57:04Z","tool":"Bash","cmd":"mkdir -p .paul/codebase\",\"description\":\"Create codebase directory\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"noOutputExpected\":true},\"tool_us","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:57:36Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find . -maxdepth 1 -type f -o -type d | head -40\"},\"tool_response\":{\"stdout\":\".\\n./.claude\\n./.git\\n./.htaccess\\n./.idea\\n./.paul\\","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:57:41Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la modules/ | head -60\"},\"tool_response\":{\"stdout\":\"total 1069\\ndrwxr-xr-x 1 jacek 197121 0 maj 10 19:37 .\\ndrwxr-xr-x 1 jacek","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:57:46Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find modules/crosssellpro -type f | head -50\"},\"tool_response\":{\"stdout\":\"modules/crosssellpro/crosssellpro.php\\nmodules/crosssellpro/v","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:57:51Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la | grep -E \"index.php|iadmin\" && ls -la themes/\"},\"tool_response\":{\"stdout\":\"drwxr-xr-x 1 jacek 197121 0 maj 10 19:37 iadmin","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:57:56Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la themes/leo_gstore/ | head -40\"},\"tool_response\":{\"stdout\":\"total 176\\ndrwxr-xr-x 1 jacek 197121 0 maj 10 19:38 .\\ndrwxr-xr","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:01Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find override -type f | head -30\"},\"tool_response\":{\"stdout\":\"override/.htaccess\\noverride/classes/assets/index.php\\noverride/classes/","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:08Z","tool":"Bash","cmd":"wc -l \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\import-product.php\" \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\buy-by-phone.php\" \"C:\\\\visual studio code\\\\projekty","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:12Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la *.php | head -20\"},\"tool_response\":{\"stdout\":\"-rw-r--r-- 1 jacek 197121 4511 maj 10 19:37 buy-by-phone.php\\n-rw-r--r-- 1 jacek ","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:20Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find . -name \"Dispatcher.php\" -type f | head -5 && find . -name \"*FrontController*\" -type f | head -5\"},\"tool_response\":{\"stdout\":\".","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:26Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la app/ && echo -e \"\\\\n--- iadmin structure ---\" && ls -la iadmin/ | head -30\"},\"tool_response\":{\"stdout\":\"total 33\\ndrwxr-xr-x","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:32Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la classes/ | head -50\"},\"tool_response\":{\"stdout\":\"total 2801\\ndrwxr-xr-x 1 jacek 197121 0 maj 10 19:37 .\\ndrwxr-xr-x 1 jace","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:37Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la src/ && find classes -name \"Product.php\" -o -name \"ObjectModel.php\" | head -5\"},\"tool_response\":{\"stdout\":\"total 8\\ndrwxr-xr","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:41Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find modules/crosssellpro -name \"*.sql\" -o -name \"sql*\" -type f\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":fals","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:47Z","tool":"Bash","cmd":"wc -l \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.htaccess\"\"},\"tool_response\":{\"stdout\":\"429 C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.htaccess\",\"stderr\":\"\",\","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:47Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find themes -path \"*crosssellpro*\" -type f\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"n","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:58:52Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find src -type f && echo -e \"\\\\n--- Override summary ---\" && find override/classes -type f | wc -l\"},\"tool_response\":{\"stdout\":\"src/","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:59:01Z","tool":"Bash","cmd":"php -v 2>/dev/null || echo \"PHP check not available\"\"},\"tool_response\":{\"stdout\":\"PHP 8.2.12 (cli) (built: Oct 24 2023 21:15:15) (ZTS Visual C++ 2019 x64)\\nCopyright (c) The PHP Group\\nZend ","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:59:06Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && ls -la config/ && echo -e \"\\\\n--- Controllers structure ---\" && ls -la controllers/ | head -30\"},\"tool_response\":{\"stdout\":\"total 11","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:59:12Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && find . -maxdepth 1 -name \"*.php\" -type f | xargs ls -la\"},\"tool_response\":{\"stdout\":\"-rw-r--r-- 1 jacek 197121 4511 maj 10 19:37 ./bu","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:59:24Z","tool":"Bash","cmd":"cd /c/visual\\\\ studio\\\\ code/projekty/drmaterac.pl && grep -n \"getAccessories\" classes/Product.php | head -10\"},\"tool_response\":{\"stdout\":\"4587: public static function getAccessoriesLig","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:59:54Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\" && git log --oneline diag_20792_tmp.php diag_fix_tmp.php diag_upload_tmp.php info.php 2>/dev/null | head -10\"},\"tool_response\":{\"stdout\","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T17:59:57Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\" && git log --oneline --all | head -20\"},\"tool_response\":{\"stdout\":\"d6f5706a update\\na69616e8 update\\nbe3965e2 update\\n4a2135cf upda","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:00:05Z","tool":"Bash","cmd":"wc -l \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\override\\\\classes\\\\Cart.php\" \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\override\\\\classes\\\\Hook.php\"\"},\"tool_","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:00:36Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\" && git log --all --oneline --grep=\"diag\\\\|diagnostic\" 2>/dev/null\"},\"tool_response\":{\"stdout\":\"194405bc feat: update diagnostic sc","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:00:41Z","tool":"Bash","cmd":"wc -l \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.htaccess\" \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\iadmin\\\\.htaccess\"\"},\"tool_response\":{\"stdout\":\" 429 C:\","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:00:45Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\" && git show 194405bc --stat 2>/dev/null | head -20\"},\"tool_response\":{\"stdout\":\"commit 194405bce0ceb5f263c9934c8a0d666ce7b629dd\\nAuth","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:01:31Z","tool":"Bash","cmd":"for f in stack architecture structure conventions testing integrations concerns db_schema tech_changelog; do echo \"===$f===\"; cat \"C:/Users/jacek/.claude/paul-framework/templates/codebase/$f.md\"; ","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:02:10Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\stack.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:02:59Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\architecture.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:03:50Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\structure.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:04:23Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\conventions.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:04:46Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\testing.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:05:28Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\integrations.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:06:35Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\concerns.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:07:07Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\db_schema.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"} +{"ts":"2026-05-10T18:07:12Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\drmaterac.pl\\\\.paul\\\\codebase\\\\tech_changelog.md","cwd":"/c/visual studio code/projekty/drmaterac.pl"}