Files
shopPRO/.paul/codebase/stack.md
2026-03-12 13:36:06 +01:00

142 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Technology Stack & Integrations
## Languages
| Language | Version | Notes |
|----------|---------|-------|
| PHP | 7.4 <8.0 | Production constraint — no PHP 8.0+ syntax |
| JavaScript | ES5 + jQuery 2.1.3 | No modern framework |
| CSS | Bootstrap 4.x (pre-compiled SCSS) | No build pipeline |
**PHP 8.0+ features explicitly forbidden:**
- `match` expressions → use ternary / if-else
- Named arguments
- Union types (`int|string`) → use single type + docblock
- `str_contains()`, `str_starts_with()`, `str_ends_with()` → use `strpos()`
## Core Libraries
| Library | Version | Location | Purpose |
|---------|---------|----------|---------|
| Medoo | 1.7.10 | `libraries/medoo/medoo.php` | Database ORM |
| PHPMailer | classic | `libraries/phpmailer/` | Email sending |
| RedBeanPHP | — | `libraries/rb.php` | Legacy ORM — **unused, candidate for removal** |
## Frontend Libraries
| Library | Location | Purpose |
|---------|----------|---------|
| jQuery | 2.1.3 | DOM / AJAX |
| jQuery Migrate | 1.0.0 | Backward compat |
| Bootstrap | 4.1.3 / 4.5.2 | `libraries/bootstrap*/` |
| CKEditor | 4.x | `libraries/ckeditor/` | Rich text editor |
| ApexCharts | — | `libraries/apexcharts/` | Admin charts |
| FancyBox | 2 + 3 | `libraries/fancyBox/`, `fancybox3/` | Lightbox |
| Plupload | — | `libraries/plupload/` | File uploads |
| Selectize.js | — | — | Select dropdowns |
| Lozad.js | — | — | Lazy loading |
| Swiper | — | — | Carousel/slider |
| CodeMirror | — | `libraries/codemirror/` | Code editor |
| Font Awesome | 5.7.0 | `libraries/fontawesome-5.7.0/` | Icons |
| File Manager | 9.14.1 & 9.14.2 | `libraries/filemanager-9.14.*/` | File browsing |
## Database
- **ORM**: Medoo 1.7.10 (custom-extended with Redis support)
- **Engine**: MySQL
- **Table prefix**: `pp_`
- **Connection**: `new medoo([...])` in each entry point via credentials from `config.php`
- **Key tables**: `pp_shop_products`, `pp_shop_orders`, `pp_shop_categories`, `pp_shop_clients`
## Caching
- **Technology**: Redis
- **PHP extension**: Native `Redis` class
- **Wrapper**: `\Shared\Cache\CacheHandler` (singleton via `RedisConnection`)
- **Config**: `config.php``$config['redis']['host/port/password']`
- **Serialization**: PHP `serialize()` / `unserialize()`
- **Default TTL**: 86400 seconds (24h)
- **Key patterns**:
- `shop\product:{id}:{lang_id}:{hash}` — product details
- `ProductRepository::getProductPermutationQuantityOptions:v2:{id}:*`
- `pp_routes:all` — URL routing patterns
- `pp_settings_cache` — shop settings
## Email
- **Library**: PHPMailer (classic, not v6)
- **Config**: `config.php` (host, port, login, password)
- **Helpers**:
- `\Shared\Helpers\Helpers::send_email($to, $subject, $text, $reply, $file)`
- `\Shared\Email\Email::send(...)` — newsletter / template-based
- **Issue**: Duplicate PHPMailer logic in both classes — should be unified
## HTTP Client
- **Technology**: Native PHP cURL (`curl_init`, `curl_setopt`, `curl_exec`)
- **No abstraction library** (no Guzzle, Symfony HTTP Client)
- **Used in**: `IntegrationsRepository.php` (Apilo calls), `cron.php` (image downloads)
## Dev & Build Tools
| Tool | Purpose |
|------|---------|
| Composer | PHP dependency management |
| PHPUnit 9.6 | Testing (`phpunit.phar`) |
| PowerShell `test.ps1` | Recommended test runner |
| No webpack/Vite/Gulp | SCSS pre-compiled, assets served as-is |
## External Integrations
### Apilo (ERP/WMS)
- **Auth**: OAuth 2.0 Bearer token (client_id + client_secret from `pp_shop_apilo_settings`)
- **Base URL**: `https://projectpro.apilo.com/rest/api/`
- **Sync operations**: order sending, payment sync, status polling, product qty/price sync, pricelist sync
- **Code**: `autoload/Domain/Integrations/IntegrationsRepository.php`
- **Cron jobs**: `APILO_SEND_ORDER`, `APILO_SYNC_PAYMENT`, `APILO_STATUS_POLL`, `APILO_PRODUCT_SYNC`, `APILO_PRICELIST_SYNC`
- **Logging**: `\Domain\Integrations\ApiloLogger``pp_log` table
### Ekomi (Reviews)
- **Type**: CSV export
- **Code**: `api.php` → generates `/ekomi/ekomi-{date}.csv`
### TrustMate (Review Invitations)
- **Type**: Browser-based (requires JS execution)
- **Code**: `cron.php` (line ~741), `cron-trustmate.php`
- **Config**: `$config['trustmate']['enabled']`
### Google Shopping Feed
- **Type**: XML feed generation
- **Cron job**: `GOOGLE_XML_FEED`
- **Code**: `cron.php``ProductRepository::generateGoogleFeedXml()`
### shopPRO Product Import
- **Type**: Direct MySQL connection to remote shopPRO instance
- **Config**: `pp_shop_shoppro_settings` (domain, db credentials)
- **Code**: `IntegrationsRepository.php` (lines 668850)
- **Logs**: `/logs/shoppro-import-debug.log`
### REST API (ordersPRO — outbound)
- **Auth**: `X-Api-Key` header
- **Endpoints**: orders (list/get/status/paid), products (list/get), dictionaries, categories
- **Code**: `api.php``autoload/api/ApiRouter.php``autoload/api/Controllers/`
## Cron Job System
| Job Type | Purpose |
|----------|---------|
| `APILO_TOKEN_KEEPALIVE` | OAuth token refresh |
| `APILO_SEND_ORDER` | Sync orders to Apilo (priority 40) |
| `APILO_SYNC_PAYMENT` | Sync payment status |
| `APILO_STATUS_POLL` | Poll order status changes |
| `APILO_PRODUCT_SYNC` | Update product qty & prices |
| `APILO_PRICELIST_SYNC` | Update pricelist |
| `PRICE_HISTORY` | Record price history |
| `ORDER_ANALYSIS` | Order/product correlation |
| `TRUSTMATE_INVITATION` | Review invitations |
| `GOOGLE_XML_FEED` | Google Shopping XML |
- **Priority levels**: CRITICAL(10), HIGH(50), NORMAL(100), LOW(200)
- **Backoff**: Exponential on failure (60s → 3600s max)
- **Storage**: `pp_cron_jobs` table