# 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*