From cf1a0adb0b04ea3e89f0ac0b3b4aaffb1e4e27b7 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Tue, 5 May 2026 22:02:04 +0200 Subject: [PATCH] docs: map existing codebase - stack.md (68 lines) - PHP/MySQL/Apache stack, vendored libraries - architecture.md (131 lines) - Custom MVC CMS, dual-layer (front/admin) - structure.md (170 lines) - Directory layout and conventions - conventions.md (98 lines) - PHP snake_case, SCSS $c/$f prefixes, jQuery patterns - testing.md (49 lines) - No automated tests detected - integrations.md (111 lines) - Google Maps, PHPMailer, Pixieset, Facebook - concerns.md (150 lines) - Critical security issues: hardcoded creds, MD5, unserialize - db_schema.md (260 lines) - ~32 tables with pp_ prefix, inferred from source - tech_changelog.md (9 lines) - Initial log entry Co-Authored-By: Claude --- .paul/STATE.md | 53 ++++++ .paul/codebase/architecture.md | 168 ++++++++++++++++ .paul/codebase/concerns.md | 188 ++++++++++++++++++ .paul/codebase/conventions.md | 127 ++++++++++++ .paul/codebase/db_schema.md | 318 +++++++++++++++++++++++++++++++ .paul/codebase/integrations.md | 144 ++++++++++++++ .paul/codebase/stack.md | 91 +++++++++ .paul/codebase/structure.md | 203 ++++++++++++++++++++ .paul/codebase/tech_changelog.md | 14 ++ .paul/codebase/testing.md | 71 +++++++ 10 files changed, 1377 insertions(+) create mode 100644 .paul/STATE.md 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 diff --git a/.paul/STATE.md b/.paul/STATE.md new file mode 100644 index 0000000..504f913 --- /dev/null +++ b/.paul/STATE.md @@ -0,0 +1,53 @@ +# Project State + +## Project Reference + +See: .paul/PROJECT.md (updated 2026-05-05) + +**Core value:** Klienci mogą zapoznać się z ofertą okien i skontaktować się z firmą. +**Current focus:** Project initialized — ready for planning + +## Current Position + +Milestone: v0.1 Initial Release +Phase: Not yet defined +Plan: None yet +Status: Ready to create roadmap and first PLAN +Last activity: 2026-05-05 — Project initialized + +Progress: +- Milestone: [░░░░░░░░░░] 0% + +## Loop Position + +Current loop state: +``` +PLAN ──▶ APPLY ──▶ UNIFY + ○ ○ ○ [Ready for first PLAN] +``` + +## Accumulated Context + +### Codebase Mapped +Date: 2026-05-05 +Documents: `.paul/codebase/` (9 files) +Key findings: Custom PHP MVC CMS, Medoo ORM, MySQL, no tests, critical security issues (hardcoded credentials, MD5 passwords, unserialize on cookies, SQL injection risks) + +### Decisions +None yet. + +### Deferred Issues +None yet. + +### Blockers/Concerns +Multiple critical security vulnerabilities documented in `.paul/codebase/concerns.md` + +## Session Continuity + +Last session: 2026-05-05 +Stopped at: Project initialization complete +Next action: Run /paul:plan to define phases and first plan +Resume file: .paul/PROJECT.md + +--- +*STATE.md — Updated after every significant action* diff --git a/.paul/codebase/architecture.md b/.paul/codebase/architecture.md new file mode 100644 index 0000000..0627d70 --- /dev/null +++ b/.paul/codebase/architecture.md @@ -0,0 +1,168 @@ +# Architecture + +**Analysis Date:** 2026-05-05 + +## Pattern Overview + +**Overall:** Custom MVC CMS (Content Management System) — dual-layer monolith + +**Key Characteristics:** +- Two distinct application layers: public frontend and admin panel +- Namespace-based class autoloading (no Composer PSR-4, custom autoloader) +- Factory (Model) + Controls (Controller) + View separation per layer +- Medoo ORM for all database operations +- Apache `.htaccess` URL rewriting for routing +- Template engine (`Tpl` class) for view rendering with PHP template files +- Plugin hook system for extensibility without modifying core + +## Layers + +**Frontend Layer** (`front` namespace): +- Purpose: Serve public website to visitors +- Contains: Route handlers, page rendering, form processing +- Controls: `autoload/front/controls/` — URL parsing, request dispatch +- Factory: `autoload/front/factory/` — database queries, data retrieval +- View: `autoload/front/view/` — HTML generation +- Templates: `templates/`, `templates_user/` (user overrides take precedence) +- Entry: `index.php` + +**Admin Panel Layer** (`admin` namespace): +- Purpose: CMS content management interface for editors +- Contains: CRUD operations for all content types, user management +- Controls: `autoload/admin/controls/` — admin action handlers +- Factory: `autoload/admin/factory/` — admin database operations +- View: `autoload/admin/view/` — admin UI rendering +- Templates: `admin/templates/` organized by module (articles, pages, users, etc.) +- Entry: `admin/index.php` + +**Core/Shared Layer** (root `autoload/`): +- Purpose: Utilities and helpers shared by both layers +- Key classes: + - `autoload/class.S.php` — static helpers (1328 lines): images, cache, sessions, email, DB utils + - `autoload/class.Tpl.php` — template engine (loads/renders PHP template files) + - `autoload/class.Cache.php` — session-based caching + - `autoload/class.Html.php` — HTML generation helpers + - `autoload/class.Image.php` — image processing (WebP conversion) + +**Database Layer:** +- Medoo ORM (`libraries/medoo/medoo.php`) — all DB access +- MySQL with `pp_` prefixed tables (~32 tables) +- Configuration in `config.php` + +## Data Flow + +**Frontend Page Request:** + +1. HTTP request hits Apache — `.htaccess` rewrites URL to `index.php` query params +2. `index.php` — initializes autoloader, session, Medoo DB instance, loads `config.php` +3. `\front\controls\Site::check_url_params()` — parses `?a=` (action) and `?id=` (resource ID) +4. Language loaded from session (`current-lang`), global settings from `pp_settings` +5. Page determined from `pp_pages` and `pp_layouts` tables +6. `\front\view\Site::show()` — assembles layout HTML +7. Layout HTML has placeholders (`[MENU:id]`, `[ARTYKULY:id]`, `[KONTENER:id]`) replaced at runtime +8. `Tpl::view()` renders PHP template files into final HTML +9. Optional: page-level cache stored/served, WebP images generated + +**Admin Panel Request:** + +1. Request hits `admin/index.php` — `.htaccess` routes `/admin/module/action/` +2. Session check + optional cookie-based auto-login +3. `\admin\factory\Users::check_privileges()` — access control verification +4. Route parsed: module and action determine which class/method to call +5. Factory methods perform DB operations (Medoo queries) +6. Grid library or `Tpl::view()` renders response + +**AJAX Request:** + +1. `ajax.php` (frontend) or `admin/ajax.php` (admin) receives request +2. `?a=action` parameter dispatches to appropriate handler +3. Returns JSON response +4. Examples: `contact_form`, `cookie_close`, `inline-edit-save`, `pixieset_*` + +**State Management:** +- Session-based: language preference, admin auth, inline-edit mode (`front-devel`) +- Database: all persistent content state +- File cache: WebP images in `cache/` directory +- Session cache: page data via `\Cache` class + +## Key Abstractions + +**Factory (Model):** +- Purpose: Database operations for a content domain +- Pattern: Static methods on classes (not instantiated) +- Location: `autoload/front/factory/class.*.php`, `autoload/admin/factory/class.*.php` +- Examples: `\admin\factory\Articles`, `\front\factory\Newsletter` +- Methods: `article_details()`, `articles_list()`, `article_save()`, `article_delete()` + +**Controls (Controller):** +- Purpose: Handle requests, validate input, call factories, pass to views +- Pattern: Static methods, namespaced by layer +- Location: `autoload/front/controls/class.*.php`, `autoload/admin/controls/class.*.php` + +**View:** +- Purpose: Generate HTML for frontend or admin +- Pattern: Static methods that load templates via `Tpl::view()` +- Location: `autoload/front/view/class.*.php`, `autoload/admin/view/class.*.php` + +**Template System:** +- `Tpl::view()` — loads PHP template file, passes variables, captures output +- Fallback: `templates_user/` (custom) overrides `templates/` (default) +- Layout placeholders: `[MENU:id]`, `[ARTYKULY:id]`, `[KONTENER:id]`, `[BANERY]`, `[NEWSLETTER]`, `[WIDGET_TELEFON]`, `[MAPA]...[/MAPA]` + +**Plugin Hooks:** +- `plugins/special-actions.php` — early hooks +- `plugins/special-actions-middle.php` — contact forms, file uploads, reCAPTCHA +- `plugins/special-actions-end.php` — late hooks + +## Entry Points + +**Frontend:** +- `index.php` — primary public entry point; bootstraps app, calls `\front\view\Site::show()` +- `ajax.php` — AJAX handler for contact forms, cookie consent, gallery actions, inline editing + +**Admin Panel:** +- `admin/index.php` — admin entry; handles auth, routes to admin controls/views +- `admin/ajax.php` — admin AJAX handler + +**API:** +- `api/contact_map.php` — JSON API for contact/location map data +- `download.php` — secure file download for article attachments +- `get_file.php` — PDF/document download wrapper + +## Error Handling + +**Strategy:** Inconsistent — errors largely suppressed rather than handled + +**Patterns:** +- `error_reporting(0)` in `admin/ajax.php`, `admin/index.php` — all errors silenced +- `error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT ^ E_WARNING ^ E_DEPRECATED)` in frontend entry points +- No try/catch blocks in most factory methods +- No global exception handler +- Failed DB operations silently return `null` or empty array + +## Cross-Cutting Concerns + +**Caching:** +- `\Cache::fetch()` / `\Cache::store()` — session-based page data cache +- `\S::delete_cache()` — invalidates cache on content changes +- WebP image generation + file caching in `cache/` + +**Multi-language:** +- All content tables have `_langs` counterpart (e.g., `pp_articles_langs`, `pp_pages_langs`) +- Language ID loaded per request from session and `pp_langs` table +- Language strings managed in `pp_langs_translations` + +**Inline Editing (Developer Mode):** +- When `front-devel` session is set, pages render with `contenteditable="true"` +- Saves edits back to `pp_layouts.html` via `ajax.php?a=inline-edit-save` + +**Authentication:** +- Admin only — no frontend user auth +- Session-based with IP validation +- Cookie-based "remember me" with auto-login +- Privilege system: `pp_users_privileges` junction table + +--- + +*Architecture analysis: 2026-05-05* +*Update when major patterns change* diff --git a/.paul/codebase/concerns.md b/.paul/codebase/concerns.md new file mode 100644 index 0000000..b077811 --- /dev/null +++ b/.paul/codebase/concerns.md @@ -0,0 +1,188 @@ +# Codebase Concerns + +**Analysis Date:** 2026-05-05 + +## Security Considerations + +**Hardcoded database credentials in version control:** +- Risk: Database password and host exposed in repository; any repo access = DB access +- Files: `config.php` (primary), also required in `ajax.php`, `admin/ajax.php`, `admin/index.php`, `download.php`, `api/contact_map.php`, `index.php` +- Current mitigation: None +- Fix: Move to `.env` file, add `.env` to `.gitignore`, create `.env.example` + +**Hardcoded Google reCAPTCHA secret key:** +- Risk: Secret key `6Lfaovgl...` hardcoded and repeated 8 times in one file +- Files: `plugins/special-actions-middle.php` (lines ~242, 296, 453, 531, 602, 679, 745) +- Current mitigation: None +- Fix: Move to config/settings, extract to single constant or `pp_settings` entry + +**MD5 password hashing:** +- Risk: MD5 is cryptographically broken — rainbow table attacks trivial +- Files: `autoload/admin/factory/class.Users.php`, `autoload/admin/class.Site.php` +- Current mitigation: None +- Fix: Replace with `password_hash()` (bcrypt) + `password_verify()` + +**PHP object injection via `unserialize()` on cookie data:** +- Risk: Attacker-controlled cookie triggers PHP object injection / RCE +- Files: `admin/ajax/pages.php` (`unserialize($_COOKIE['cookie_menus'])`, `unserialize($_COOKIE['cookie_pages'])`) +- Also in: `admin/templates/articles/article-edit.php`, `admin/templates/layouts/layout-edit.php`, `admin/templates/pages/pages-list.php`, `admin/templates/pages/pages-browse-list.php` +- Current mitigation: None +- Fix: Replace with `json_decode()` for cookie state storage + +**Path traversal in file download:** +- Risk: Arbitrary file read — attacker can request any file on server +- Files: `get_file.php` (no validation on `$_GET['fileUrl']` before `readfile()`) +- Current mitigation: None +- Fix: Whitelist allowed paths, validate against upload directory only + +**File upload without MIME type validation:** +- Risk: Executable files (`.php`) may be uploaded with double extension bypass +- Files: `plugins/special-actions-middle.php` (lines ~313-316, `move_uploaded_file()` with unsanitized `$_FILES['files']['name']`) +- Current mitigation: Extension check only (bypassable) +- Fix: Validate MIME type via `finfo_file()`, restrict upload directory execution, add file size limits + +**SQL injection risk via string concatenation:** +- Risk: Direct variable injection into SQL strings (not all queries use Medoo parameterization) +- Files: + - `autoload/front/factory/class.Languages.php:19` — `domain` parameter in raw SQL + - `autoload/admin/factory/class.Pages.php:353` — `lang` variable in raw SQL + - `autoload/admin/factory/class.Articles.php:149,163,181` — multiple concatenations +- Current mitigation: Medoo handles most queries safely; raw SQL in edge cases +- Fix: Replace raw SQL with Medoo parameterized queries throughout + +**User input echoed without `htmlspecialchars()`:** +- Risk: XSS (Cross-Site Scripting) in email confirmations and form outputs +- Files: `ajax.php:64,82-84`, `plugins/special-actions-middle.php:253-256` +- Current mitigation: None +- Fix: Apply `htmlspecialchars($value, ENT_QUOTES)` before output + +## Tech Debt + +**No environment configuration separation:** +- Issue: Single `config.php` used for dev and production; no `.env` pattern +- Files: `config.php` and all entry points that require it +- Impact: Credentials hardcoded, can't safely commit config, no staging/prod separation +- Fix: Adopt `.env` pattern with `vlucas/phpdotenv` or equivalent + +**God object `class.S.php`:** +- Issue: 1328-line class handling images, caching, sessions, email, DB utilities — no single responsibility +- Files: `autoload/class.S.php` +- Impact: Hard to test, hard to modify, used everywhere so any bug is widespread +- Fix: Gradually extract into dedicated service classes (`ImageService`, `CacheService`, `EmailService`) + +**Duplicate reCAPTCHA verification logic:** +- Issue: reCAPTCHA verification code copy-pasted 8+ times instead of a shared function +- Files: `plugins/special-actions-middle.php` (lines 230-809, repeated blocks) +- Impact: Any bug fix requires 8 changes; any key rotation requires 8 updates +- Fix: Extract to `verify_recaptcha($response)` function called once per form + +**Error suppression instead of error handling:** +- Issue: `error_reporting(0)` silences all errors; no logging to file or monitoring +- Files: `admin/ajax.php:2`, `admin/index.php:14` +- Impact: Silent failures, impossible to debug production issues +- Fix: Implement proper error logging (`error_log()` or PSR-3 logger), use try/catch in DB operations + +**Mixed concerns in templates:** +- Issue: Business logic and data manipulation embedded in template PHP files +- Files: `admin/templates/articles/article-edit.php` (1143 lines), `admin/templates/pages/page-edit.php` +- Impact: Hard to maintain, duplicate logic between templates and factory classes +- Fix: Move all logic to controls/factory, pass pre-computed variables to templates + +**Deprecated function usage:** +- Issue: `mime_content_type()` deprecated since PHP 5.3 +- Files: `autoload/class.S.php:37` +- Fix: Replace with `finfo_file()` + +## Performance Bottlenecks + +**Large data file loaded at runtime:** +- Problem: `wojewodztwa.php` is 6548 lines of PHP arrays — loaded entirely for any request needing province data +- Files: `wojewodztwa.php` +- Cause: Static data embedded in PHP instead of database or JSON +- Fix: Move to `pp_provinces` table or JSON file with lazy loading + +**Template placeholder replacement:** +- Problem: Layout HTML scanned for all placeholder patterns on every page request +- Files: `autoload/front/view/class.Site.php` +- Cause: String replacement for `[MENU:id]`, `[ARTYKULY:id]`, etc. on each render +- Improvement: Page caching (already implemented as opt-in, ensure enabled for high-traffic pages) + +**WebP image generation:** +- Problem: WebP conversion happens on-demand per request (not pre-generated) +- Files: `autoload/class.Image.php`, `autoload/class.S.php` +- Cause: No background job system for image processing +- Impact: First request for each image is slow; cache/ fills over time +- Improvement: Pre-generate WebP on upload + +## Fragile Areas + +**Plugin hook file `special-actions-middle.php`:** +- Files: `plugins/special-actions-middle.php` (very large file with 8+ contact form handlers) +- Why fragile: Monolithic — all contact forms, reCAPTCHA, file uploads in one file; no shared validation +- Common failures: Adding a new form variant requires duplicating entire handler block +- Safe modification: Extract shared validation/email logic before adding new variants + +**Template override system:** +- Files: `autoload/class.Tpl.php`, `templates/`, `templates_user/` +- Why fragile: Silent fallback from `templates_user/` to `templates/` — easy to edit wrong file +- Common failures: Edit `templates/` file thinking it's active, but `templates_user/` override takes precedence +- Safe modification: Always check both directories; `templates_user/` takes precedence + +**Admin session / cookie auto-login:** +- Files: `admin/index.php` (lines 36-84) +- Why fragile: IP-based session validation can lock out admin on IP change; cookie auto-login not encrypted +- Common failures: Admin locked out after ISP IP change +- Safe modification: Test login flow after any changes to session handling + +## Dependencies at Risk + +**jQuery 1.11.1 (admin panel):** +- Risk: EOL since 2016; known XSS vulnerabilities +- Impact: Admin panel DOM manipulation, CKEditor compatibility +- Files: `admin/templates/site/main-layout.php` +- Migration: Upgrade to jQuery 3.x (breaking changes in `.live()`, `.size()` etc.) + +**CKEditor (version unknown):** +- Risk: Older CKEditor 4.x versions have known XSS vulnerabilities +- Files: `libraries/ckeditor/` +- Migration: Audit version, update to latest CKEditor 4 LTS or migrate to CKEditor 5 + +**Medoo (version unknown, likely 1.x):** +- Risk: Medoo 1.x API differs significantly from 2.x; unmaintained in 1.x branch +- Files: `libraries/medoo/medoo.php` +- Migration: Audit API usage before upgrading to Medoo 2.x + +## Missing Critical Features + +**No environment configuration:** +- Problem: No way to run app locally without overwriting production credentials +- Blocks: Safe local development, CI/CD setup, multi-developer workflow +- Complexity: Low — add `.env` loading at top of `config.php` + +**No error logging / monitoring:** +- Problem: Production errors are silently swallowed +- Blocks: Debugging production issues, alerting on failures +- Complexity: Low — configure `error_log()` to file + optional email alert + +**No CSRF protection:** +- Problem: All forms lack CSRF token validation +- Blocks: Prevents CSRF attacks on contact/newsletter/admin forms +- Complexity: Medium — add token generation + validation middleware + +**No automated tests:** +- Problem: Zero test coverage — no regression safety net for changes +- Blocks: Refactoring, safe dependency upgrades, CI/CD +- Complexity: High — requires setting up PHPUnit, test DB, writing tests from scratch + +## Test Coverage Gaps + +**Entire codebase:** +- What's not tested: Everything — factory methods, controls, views, AJAX handlers +- Risk: Any change could break functionality silently +- Priority: High for security-sensitive paths (auth, file uploads, SQL queries) +- Difficulty: High — no test infrastructure exists; factory methods use static Medoo instance + +--- + +*Concerns audit: 2026-05-05* +*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 0000000..1c58c66 --- /dev/null +++ b/.paul/codebase/conventions.md @@ -0,0 +1,127 @@ +# Coding Conventions + +**Analysis Date:** 2026-05-05 + +## Naming Patterns + +**PHP Class Files:** +- Pattern: `class.ClassName.php` (PascalCase class name) +- Examples: `class.Articles.php`, `class.Authors.php`, `class.Users.php` +- Namespace mirrors directory path: `autoload/admin/factory/class.Articles.php` → `namespace admin\factory;` + +**PHP Functions & Variables:** +- Functions: `snake_case` exclusively (`duplicate_article()`, `gallery_order_save()`, `article_save()`) +- Variables: `snake_case` (`$article_id`, `$image_id`, `$output_file`, `$file_type`) +- Class properties: `snake_case` (`$this->article['languages']`) + +**CSS/HTML:** +- CSS classes: `kebab-case` (`.sidebar-menu`, `.menu-left`, `.google-title`) +- No BEM methodology — flat class names with some nesting + +**SCSS Variables:** +- Colors: `$c` prefix + PascalCase (`$cWhite`, `$cBlack`, `$cGrayDarkBg`, `$cYellow`) +- Fonts: `$f` prefix (`$font1`, `$font2`, `$font3`, `$fLeagueSpartan`) +- Defined in: `layout/style-scss/_variables.scss` + +**JavaScript:** +- Variables: camelCase +- Functions: camelCase +- jQuery patterns throughout: `$(document).ready()`, `$('body').on(event, selector, handler)` + +**Templates:** +- PHP templates: `kebab-case` in directory/feature structure +- Examples: `article-edit.php`, `articles-browse-list.php`, `page-contact-v5.php` + +**Database Tables:** +- Prefix: `pp_` on all tables +- Pattern: `pp_[module]` and `pp_[module]_[subresource]` +- Examples: `pp_articles`, `pp_articles_langs`, `pp_articles_images` + +## Code Style + +**PHP:** +- Indentation: 2 spaces +- Braces: opening brace on same line as control structure/function +- Spaces: around operators (`=`, `==`, `!=`), within array parentheses +- PHP tags: short tags `` used in templates (not `` tags in templates +- No import/require (no module bundler) +- Load order defined in `admin/templates/site/main-layout.php` + +## Function Design + +**PHP Factory methods:** +- Static methods named after the operation: `article_save()`, `article_delete()` +- No return type declarations +- Return: Medoo result (array), `true`/`false`, or void + +**AJAX Handlers:** +- `$_POST` / `$_GET` retrieved via `\S::get()` at top of handler +- JSON response at end: `echo json_encode($output)` and `die()` + +--- + +*Convention analysis: 2026-05-05* +*Update when patterns change* diff --git a/.paul/codebase/db_schema.md b/.paul/codebase/db_schema.md new file mode 100644 index 0000000..1f79eef --- /dev/null +++ b/.paul/codebase/db_schema.md @@ -0,0 +1,318 @@ +# Database Schema + +**Updated:** 2026-05-05 | **Total tables:** ~32 | **Engine:** MySQL InnoDB | **Prefix:** `pp_` + +Schema inferred from Medoo ORM queries in PHP source files. No migration files found — schema managed manually. + +--- + +## Content — Articles + +**`pp_articles`** — Main article/content records +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `hash` | VARCHAR | Unique identifier for external reference | +| `status` | TINYINT | Published/draft/archived | +| `date_add` | DATETIME | Creation timestamp | +| `views` | INT | View counter | +| `password` | VARCHAR | Optional password protection | +| `pixieset` | VARCHAR | Pixieset gallery identifier | + +**`pp_articles_langs`** — Language-specific article content +| Column | Type | Notes | +|--------|------|-------| +| `article_id` | INT | FK → `pp_articles.id` | +| `lang_id` | INT | FK → `pp_langs.id` | +| `title` | VARCHAR | Article title | +| `content` | LONGTEXT | Rich text content | +| `seo_link` | VARCHAR | URL slug | +| `noindex` | TINYINT | SEO noindex flag | + +**`pp_articles_images`** — Article gallery images +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `article_id` | INT | FK → `pp_articles.id` | +| `src` | VARCHAR | Image filename/path | +| `o` | INT | Sort order | +| `favorite` | TINYINT | Flagged as favorite | +| `to_delete` | TINYINT | Soft-delete flag | + +**`pp_articles_files`** — Downloadable file attachments +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `article_id` | INT | FK → `pp_articles.id` | +| `src` | VARCHAR | File path | +| `name` | VARCHAR | Display name | +| `to_delete` | TINYINT | Soft-delete flag | + +**`pp_articles_pages`** — Article-to-Page assignments +| Column | Type | Notes | +|--------|------|-------| +| `article_id` | INT | FK → `pp_articles.id` | +| `page_id` | INT | FK → `pp_pages.id` | +| `o` | INT | Sort order on page | +| `status` | TINYINT | Visibility on this page | + +**`pp_articles_tags`** — Many-to-many: Articles ↔ Tags +| Column | Type | Notes | +|--------|------|-------| +| `article_id` | INT | FK → `pp_articles.id` | +| `tag_id` | INT | FK → `pp_tags.id` | + +**`pp_articles_additional_params`** — Custom field definitions per article +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `article_id` | INT | FK → `pp_articles.id` | +| `name` | VARCHAR | Field name | +| `language` | VARCHAR | Language code | +| `status` | TINYINT | Active/inactive | + +**`pp_articles_additional_values`** — Custom field values +| Column | Type | Notes | +|--------|------|-------| +| `param_id` | INT | FK → `pp_articles_additional_params.id` | +| `article_id` | INT | FK → `pp_articles.id` | +| `value` | TEXT | Field value | +| `language_id` | INT | FK → `pp_langs.id` | + +--- + +## Content — Pages & Layouts + +**`pp_pages`** — Website page hierarchy +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `menu_id` | INT | FK → `pp_menus.id` | +| `parent_id` | INT | Self-referencing for nested pages | +| `page_type` | VARCHAR | Type identifier | +| `sort_type` | VARCHAR | Article sort order | +| `status` | TINYINT | Published/hidden | +| `start` | TINYINT | Homepage flag | +| `o` | INT | Sort order in navigation | +| `cache` | TINYINT | Page-level cache toggle | + +**`pp_pages_langs`** — Page language translations +| Column | Type | Notes | +|--------|------|-------| +| `page_id` | INT | FK → `pp_pages.id` | +| `lang_id` | INT | FK → `pp_langs.id` | +| `title` | VARCHAR | Page title | +| `seo_link` | VARCHAR | URL slug | + +**`pp_layouts`** — Template layout containers +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `layout_id` | INT | Parent layout reference | +| `name` | VARCHAR | Layout name | +| `html` | LONGTEXT | Desktop HTML with `[PLACEHOLDER:id]` tags | +| `m_html` | LONGTEXT | Mobile HTML | +| `css` | TEXT | Inline CSS | +| `m_css` | TEXT | Mobile inline CSS | +| `js` | TEXT | Inline JS | +| `m_js` | TEXT | Mobile inline JS | +| `status` | TINYINT | Active/inactive | + +**`pp_layouts_pages`** — Layout-to-page assignments +| Column | Type | Notes | +|--------|------|-------| +| `layout_id` | INT | FK → `pp_layouts.id` | +| `page_id` | INT | FK → `pp_pages.id` | + +--- + +## Content — Static Containers & Banners + +**`pp_scontainers`** — Reusable static content blocks +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `status` | TINYINT | Active/inactive | + +**`pp_scontainers_langs`** — Static container translations +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `scontainer_id` | INT | FK → `pp_scontainers.id` | +| `lang_id` | INT | FK → `pp_langs.id` | +| `html` | LONGTEXT | Content HTML | + +**`pp_banners`** — Promotional banners +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `name` | VARCHAR | Banner name | +| `status` | TINYINT | Active/inactive | + +**`pp_banners_langs`** — Banner language versions +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `id_banner` | INT | FK → `pp_banners.id` | +| `id_lang` | INT | FK → `pp_langs.id` | +| `title` | VARCHAR | Banner title | +| `content` | TEXT | Banner content/HTML | + +--- + +## Navigation & Taxonomy + +**`pp_menus`** — Navigation menu definitions +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `name` | VARCHAR | Menu name | + +**`pp_tags`** — Article tags/categories +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `name` | VARCHAR | Tag name | + +**`pp_authors`** — Article author profiles +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | + +**`pp_authors_langs`** — Author translations +| Column | Type | Notes | +|--------|------|-------| +| `author_id` | INT | FK → `pp_authors.id` | +| `lang_id` | INT | FK → `pp_langs.id` | + +--- + +## Users & Access Control + +**`pp_users`** — Admin panel users +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `login` | VARCHAR | Username | +| `password` | VARCHAR | MD5 hash (security concern — see concerns.md) | +| `status` | TINYINT | Active/inactive | +| `active_to` | DATE | Account expiry date | +| `admin` | TINYINT | Super-admin flag | +| `error_logged_count` | INT | Failed login counter | + +**`pp_users_privileges`** — User permission assignments +| Column | Type | Notes | +|--------|------|-------| +| `id_user` | INT | FK → `pp_users.id` | +| `name` | VARCHAR | Privilege name (string key) | + +--- + +## Multi-language + +**`pp_langs`** — Available language configurations +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `start` | TINYINT | Default language flag | +| `domain` | VARCHAR | Domain for this language | +| `main_domain` | VARCHAR | Primary domain | +| `o` | INT | Sort order | +| `status` | TINYINT | Active/inactive | + +**`pp_langs_translations`** — UI string translations +| Column | Type | Notes | +|--------|------|-------| +| Dynamic columns per language ID | VARCHAR | Translation strings | + +--- + +## Newsletter + +**`pp_newsletter`** — Email subscribers +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `email` | VARCHAR | Subscriber email | +| `status` | TINYINT | Active/unsubscribed | + +**`pp_newsletter_send`** — Sent campaign log +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `email_template_id` | INT | FK → `pp_newsletter_templates.id` | + +**`pp_newsletter_templates`** — Email campaign templates +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | +| `name` | VARCHAR | Template name | +| `subject` | VARCHAR | Email subject | +| `html` | LONGTEXT | Email HTML body | + +--- + +## Contacts & Locations + +**`pp_contacts_maps`** — Location/contact point entries +| Column | Type | Notes | +|--------|------|-------| +| `id` | INT | PK, AUTO_INCREMENT | + +**`pp_contacts_maps_products`** — Product associations for locations +| Column | Type | Notes | +|--------|------|-------| +| `map_id` | INT | FK → `pp_contacts_maps.id` | +| `product_id` | INT | Product reference | + +**`pp_contacts_maps_provinces`** — Province associations for locations +| Column | Type | Notes | +|--------|------|-------| +| `map_id` | INT | FK → `pp_contacts_maps.id` | +| `province_id` | INT | Province reference | + +**`pp_contact_emails`** — Contact form submissions +| Column | Type | Notes | +|--------|------|-------| +| `email` | VARCHAR | Sender email | +| `phone` | VARCHAR | Sender phone | +| `title` | VARCHAR | Subject | +| `mail` | TEXT | Message body | +| `add_date` | DATETIME | Submission timestamp | + +--- + +## SEO & Settings + +**`pp_seo_additional`** — Per-article SEO metadata +| Column | Type | Notes | +|--------|------|-------| +| `article_id` | INT | FK → `pp_articles.id` | +| `lang_id` | INT | FK → `pp_langs.id` | + +**`pp_settings`** — Global CMS configuration (key-value store) +| Column | Type | Notes | +|--------|------|-------| +| `param` | VARCHAR | Setting key (e.g., `google_map_key`, `email_host`) | +| `value` | TEXT | Setting value | + +--- + +## Schema Characteristics + +| Property | Value | +|----------|-------| +| Engine | MySQL InnoDB | +| Table prefix | `pp_` | +| Soft deletes | `to_delete` column on `pp_articles_images`, `pp_articles_files` | +| Multi-language | All content tables have `_langs` counterpart | +| Migrations | None — schema managed manually | +| Timestamps | `date_add` on articles; not standardized across all tables | + +## Key Relationships + +- **1:N** — `pp_articles` → `pp_articles_images`, `pp_articles_files`, `pp_articles_langs` +- **N:N** — `pp_articles` ↔ `pp_tags` (via `pp_articles_tags`) +- **N:N** — `pp_articles` ↔ `pp_pages` (via `pp_articles_pages`) +- **Hierarchical** — `pp_pages.parent_id` self-reference for nested page tree +- **Language join** — all content tables join `pp_langs` on `lang_id` for translation diff --git a/.paul/codebase/integrations.md b/.paul/codebase/integrations.md new file mode 100644 index 0000000..74b68f5 --- /dev/null +++ b/.paul/codebase/integrations.md @@ -0,0 +1,144 @@ +# External Integrations + +**Analysis Date:** 2026-05-05 + +## APIs & External Services + +**Maps & Geolocation:** +- Google Maps API — interactive contact/location maps on frontend + - Integration: JavaScript API via `https://maps.googleapis.com/maps/api/js?key=` + - Auth: API key stored in `pp_settings` table as `google_map_key` + - Toggle: `google_maps` setting in admin settings + - Files: `templates/site/contact.php`, `admin/templates/settings/settings.php` + +- geoPlugin IP Geolocation — visitor IP-to-location lookup with currency detection + - Service URL: `http://www.geoplugin.net/php.gp?ip={IP}&base_currency={CURRENCY}` + - Library: `autoload/class.geoplugin.php` + - No API key required (free service) + +**Fonts & CDN Resources:** +- Google Fonts — `https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700` + - File: `admin/templates/site/main-layout.php` +- Google AJAX CDN — jQuery loaded from `//ajax.googleapis.com/ajax/libs/jquery/2.1.4/` + - File: `admin/templates/site/unlogged-layout.php` + +**Social Media:** +- Facebook Likebox widget — fixed sidebar widget showing Facebook feed + - App ID: `194295077275888` (hardcoded in iframe) + - File: `templates/site/facebook.php` + +**Gallery:** +- Pixieset — external photo gallery service integration + - Features: ZIP download of gallery images, mark favorites + - AJAX endpoints: `ajax.php?a=pixieset_*` + - Files: `templates/articles/article-gallery.php`, `ajax.php` + +## Data Storage + +**Databases:** +- MySQL 5.7+ — primary data store for all CMS content + - Connection: credentials hardcoded in `config.php` (host, user, password, dbname) + - Client: Medoo ORM (`libraries/medoo/medoo.php`) + - Table prefix: `pp_` (~32 tables) + - Migrations: None detected — schema managed manually + +**File Storage:** +- Local filesystem — all user uploads stored on server + - Images: `images/` directory + - Uploads: `upload/` directory + - Temp files: `admin/temp/` + - Cache/WebP: `cache/` directory + - No cloud storage (no AWS S3, no CDN) + +**Caching:** +- Session-based cache via `\Cache` class (`autoload/class.Cache.php`) + - Keys pattern: `page_details:lang:id` + - File-based WebP image cache: `cache/` directory + +## Authentication & Identity + +**Auth Provider:** +- Custom session-based authentication — no OAuth provider + - Implementation: `admin/index.php` (session check + cookie auto-login) + - Password storage: MD5 hashing (insecure — see concerns.md) + - Session security: IP address validation stored in `$_SESSION` + - Files: `autoload/admin/factory/class.Users.php`, `autoload/admin/class.Site.php` + +**OAuth Integrations:** +- None detected + +## Email & Messaging + +**SMTP Mail:** +- PHPMailer — SMTP-based transactional email + - Library: `libraries/phpmailer/class.phpmailer.php`, `libraries/phpmailer/class.smtp.php` + - Config: host, port, login, password stored in `pp_settings` table + - Settings keys: `email_host`, `email_port`, `email_login`, `email_password` + - Function: `\S::send_email()` in `autoload/class.S.php` + - Used for: contact forms, newsletter delivery + +**Newsletter:** +- Custom database-driven newsletter system (no Mailchimp/SendGrid) + - Templates: `pp_newsletter_templates` table + - Subscribers: `pp_newsletter` table + - Send log: `pp_newsletter_send` table + - Files: `autoload/front/factory/class.Newsletter.php` + +## Analytics & Tracking + +**Analytics:** +- Custom code injection — third-party analytics configured via admin settings + - Setting key: `statistic_code` (stored in `pp_settings`) + - Injection point: before `` in `index.php` + - Supports: Google Analytics, Matomo, or any snippet + +**Error Tracking:** +- None detected — no Sentry, Rollbar, or similar + +## Security + +**CAPTCHA:** +- Custom JavaScript captcha for contact forms + - Library: `libraries/jquery/captcha.js`, `libraries/jquery/captcha.css` + - Toggle: `contact_form_captcha` setting + - File: `templates/site/contact.php` + +- Google reCAPTCHA — used in some contact form variants + - Secret key hardcoded in `plugins/special-actions-middle.php` (8 locations — see concerns.md) + +## CI/CD & Deployment + +**Hosting:** +- Shared hosting at `serwer1574995.home.pl` + - Deployment: FTP via VS Code extension (`.vscode/sftp.json`, `.vscode/ftp-kr.json`) + - No automated deployment pipeline + +**CI Pipeline:** +- None detected — no GitHub Actions, no CI configuration + +## Environment Configuration + +**Development:** +- Required config: Database credentials in `config.php` +- No `.env` or `.env.example` — all config hardcoded +- FTP settings: `.vscode/sftp.json` + +**Production:** +- Same `config.php` used for production (no environment separation) +- No staging environment detected + +## Not Detected + +- ❌ Payment gateways (Stripe, PayPal, Przelewy24) +- ❌ SMS services (Twilio, SMSAPI) +- ❌ Cloud storage (AWS S3, Google Cloud Storage) +- ❌ Error tracking (Sentry, Rollbar) +- ❌ OAuth / SSO providers +- ❌ Redis / Memcached +- ❌ CDN (no Cloudflare, no CloudFront) +- ❌ Webhooks (incoming or outgoing) + +--- + +*Integration audit: 2026-05-05* +*Update when adding/removing external services* diff --git a/.paul/codebase/stack.md b/.paul/codebase/stack.md new file mode 100644 index 0000000..69a7f89 --- /dev/null +++ b/.paul/codebase/stack.md @@ -0,0 +1,91 @@ +# Technology Stack + +**Analysis Date:** 2026-05-05 + +## Languages + +**Primary:** +- PHP 7.4+ - All backend logic, templates, AJAX handlers +- HTML (via PHP templates) - Page rendering, admin UI + +**Secondary:** +- JavaScript / jQuery - Frontend interactivity +- SCSS - Admin and frontend styling (compiled to CSS) +- CSS - Compiled output + Bootstrap overrides + +## Runtime + +**Environment:** +- PHP 7.4+ on Apache web server +- Apache with `mod_rewrite` enabled (required for URL routing via `.htaccess`) +- MySQL 5.7+ - Primary database + +**Package Manager:** +- None — all dependencies manually vendored in `libraries/` and `plugins/` directories +- No Composer, npm, or yarn + +## Frameworks + +**Core:** +- Custom CMS framework (cmsPro) — no external PHP framework (no Laravel, Symfony, etc.) +- Medoo ORM 1.x — database abstraction layer (`libraries/medoo/medoo.php`) +- Bootstrap 4.1.3 (`libraries/bootstrap-4.1.3/`) and Bootstrap 5.0 (`libraries/bootstrap-5.0/`) + +**Testing:** +- None detected — no PHPUnit, Jest, or any test runner configured + +**Build/Dev:** +- Live Sass Compiler (VS Code extension) — compiles SCSS to CSS +- No webpack, Vite, or build pipeline +- SCSS output directive at top of files: `// out: ../style-css/style.css, compress: true` + +## Key Dependencies + +**Critical:** +- Medoo ORM — all database operations (`libraries/medoo/medoo.php`) +- PHPMailer — SMTP email sending (`libraries/phpmailer/class.phpmailer.php`, `class.smtp.php`) +- jQuery 1.11.1 (admin) / 2.1.4 (login page CDN) — frontend interactivity +- CKEditor — rich text editing in admin panel (`libraries/ckeditor/`) + +**Admin UI Libraries:** +- Grid library (gdb) — data table component (`libraries/grid/`) +- Select2 — enhanced dropdowns (`plugins/select2/`) +- FancyBox — lightbox (`plugins/fancybox/`) +- File Uploader — file upload UI (`plugins/fileuploader/`) +- Swiper — carousels (`libraries/swiper/`) + +**Frontend Libraries:** +- Font Awesome 6.1.1 — icons (`libraries/font-awesome-6.1.1/`) +- Lozad — lazy image loading (`libraries/jquery/lozad.js`) +- jsCloudimage360 — 360° image viewer (`libraries/jsCloudimage360/`) +- Moment.js — date formatting (`libraries/framework/vendor/plugins/moment/`) +- DateRangePicker — date inputs (`libraries/framework/vendor/plugins/daterange/`) + +## Configuration + +**Environment:** +- No `.env` files — configuration hardcoded in `config.php` +- `config.php` — database host, user, password, database name (credentials in plain text) +- `admin/ip.conf` — optional IP whitelist for admin panel access +- Global site settings stored in `pp_settings` database table + +**Build:** +- `.vscode/settings.json` — VS Code Live Sass Compiler config +- No tsconfig, no webpack.config, no vite.config + +## Platform Requirements + +**Development:** +- Apache + PHP 7.4+ + MySQL 5.7+ +- VS Code with Live Sass Compiler extension for SCSS editing +- FTP access configured in `.vscode/sftp.json` / `.vscode/ftp-kr.json` + +**Production:** +- Shared hosting at `serwer1574995.home.pl` (inferred from `config.php`) +- Apache `.htaccess` URL rewriting +- No Docker, no CI/CD pipeline detected + +--- + +*Stack analysis: 2026-05-05* +*Update after major dependency changes* diff --git a/.paul/codebase/structure.md b/.paul/codebase/structure.md new file mode 100644 index 0000000..80777bf --- /dev/null +++ b/.paul/codebase/structure.md @@ -0,0 +1,203 @@ +# Codebase Structure + +**Analysis Date:** 2026-05-05 + +## Directory Layout + +``` +vidok.com/ +├── index.php # Frontend entry point +├── ajax.php # Frontend AJAX handler +├── config.php # Database credentials (hardcoded) +├── download.php # Secure file download handler +├── get_file.php # PDF/document download wrapper +├── api/ # JSON API endpoints +├── admin/ # Admin panel application +│ ├── index.php # Admin entry point +│ ├── ajax.php # Admin AJAX handler +│ ├── css/ # Admin SCSS source files +│ ├── style-css/ # Compiled admin CSS +│ └── templates/ # Admin UI PHP templates +├── autoload/ # Core PHP classes (MVC layers) +│ ├── class.S.php # Global static helpers +│ ├── class.Tpl.php # Template engine +│ ├── class.Cache.php # Session cache +│ ├── class.Html.php # HTML generation helpers +│ ├── class.Image.php # Image processing +│ ├── front/ # Frontend MVC classes +│ │ ├── controls/ # Frontend controllers +│ │ ├── factory/ # Frontend models (DB queries) +│ │ └── view/ # Frontend HTML generators +│ └── admin/ # Admin MVC classes +│ ├── controls/ # Admin controllers +│ ├── factory/ # Admin models (DB queries) +│ └── view/ # Admin HTML generators +├── templates/ # Default frontend PHP templates +│ ├── articles/ # Article display templates +│ ├── pages/ # Page display templates +│ ├── site/ # Layout partials (header, footer, etc.) +│ ├── newsletter/ # Newsletter form templates +│ └── widgets/ # Widget templates +├── templates_user/ # Custom frontend templates (override defaults) +├── layout/ # Frontend CSS, JS, fonts +│ ├── style-scss/ # SCSS source files +│ │ ├── _variables.scss # Color/font variables +│ │ ├── _mixins.scss # Responsive breakpoints, mixins +│ │ └── style.scss # Main SCSS entry point +│ ├── style-css/ # Compiled frontend CSS +│ └── js/ # Frontend JavaScript +│ ├── main.js # Main frontend JS +│ └── custom.js # Custom frontend JS +├── libraries/ # Vendored PHP/JS libraries +│ ├── medoo/ # Medoo ORM +│ ├── phpmailer/ # PHPMailer for email +│ ├── ckeditor/ # Rich text editor +│ ├── grid/ # Admin data grid component +│ ├── bootstrap-4.1.3/ # Bootstrap 4 +│ ├── bootstrap-5.0/ # Bootstrap 5 +│ ├── font-awesome-6.1.1/ # Icon library +│ ├── swiper/ # Carousel library +│ ├── framework/ # Date pickers, moment.js +│ └── jquery/ # jQuery utilities (lozad, captcha) +├── plugins/ # Hook files for extensibility +│ ├── special-actions.php # Early hooks +│ ├── special-actions-middle.php # Contact forms, file uploads +│ └── special-actions-end.php # Late hooks +├── images/ # User-uploaded images +├── upload/ # User-uploaded files +├── cache/ # Runtime cache + generated WebP images +├── stopki/ # Footer content fragments +├── .paul/ # PAUL project management files +├── .vscode/ # VS Code settings (SCSS compile, SFTP) +└── .htaccess # Apache URL rewriting rules +``` + +## Directory Purposes + +**`autoload/`:** +- Purpose: All PHP application classes — the core of the CMS +- Pattern: `class.ClassName.php` naming +- Namespaced: `front\controls\`, `front\factory\`, `front\view\`, `admin\controls\`, `admin\factory\`, `admin\view\` +- Key files: `class.S.php` (global helpers), `class.Tpl.php` (templating), `class.Image.php` + +**`admin/templates/`:** +- Purpose: PHP template files for admin panel UI +- Organized by module: `articles/`, `pages/`, `users/`, `newsletter/`, `layouts/`, `scontainers/`, `html/` +- Key files: `articles/article-edit.php`, `pages/page-edit.php`, `site/main-layout.php` + +**`templates/` and `templates_user/`:** +- Purpose: Frontend page templates +- `templates/` — default templates (shipped with CMS) +- `templates_user/` — project-specific overrides (take precedence over defaults) +- `Tpl::view()` checks `templates_user/` first, falls back to `templates/` + +**`layout/`:** +- Purpose: All frontend CSS, JS, fonts +- SCSS source in `layout/style-scss/`, compiled output in `layout/style-css/` +- JS in `layout/js/` + +**`libraries/`:** +- Purpose: All vendored third-party libraries (no package manager) +- PHP libraries: Medoo, PHPMailer, Grid +- JS libraries: CKEditor, Bootstrap, Swiper, DatePickers + +**`plugins/`:** +- Purpose: Extension hooks called from `index.php` at different lifecycle stages +- `special-actions-middle.php` is the main plugin — contains all contact form handlers and reCAPTCHA + +**`cache/`:** +- Purpose: Runtime-generated files (WebP images) +- Auto-created by `\Image` class during first request +- Not committed to git (runtime data) + +## Key File Locations + +**Entry Points:** +- `index.php` — public frontend entry +- `ajax.php` — frontend AJAX +- `admin/index.php` — admin panel entry +- `admin/ajax.php` — admin AJAX +- `api/contact_map.php` — contacts/locations JSON API + +**Configuration:** +- `config.php` — database credentials (single config file, no .env) +- `admin/ip.conf` — optional IP whitelist for admin panel +- `.vscode/settings.json` — SCSS compile settings + +**Core Logic:** +- `autoload/class.S.php` — global helpers (images, cache, email, sessions) +- `autoload/class.Tpl.php` — template engine +- `autoload/front/view/class.Site.php` — main frontend page renderer +- `autoload/admin/view/class.Page.php` — main admin page renderer +- `libraries/medoo/medoo.php` — database ORM + +**Templates (Frontend):** +- `templates/articles/` — article display patterns +- `templates/site/` — header, footer, contact, Facebook widget +- `templates_user/page-contact-v*.php` — custom contact page variants + +## Naming Conventions + +**PHP Class Files:** +- Pattern: `class.ClassName.php` (e.g., `class.Articles.php`, `class.Users.php`) +- Namespace mirrors directory: `admin\factory\` = `autoload/admin/factory/class.*.php` + +**PHP Templates:** +- Pattern: `feature-type.php` in kebab-case (e.g., `article-edit.php`, `articles-browse-list.php`) + +**SCSS/CSS:** +- Helper files: `_variables.scss`, `_mixins.scss` (underscore prefix) +- Feature files: kebab-case (e.g., `drzwi-wejsciowe-aluminiowe.scss`) +- Compiled output in `style-css/` mirroring `style-scss/` + +**Directories:** +- Feature groupings in kebab-case +- Plural for collections: `articles/`, `templates/`, `controls/` + +## Where to Add New Code + +**New Content Module (e.g., "Events"):** +- Admin factory: `autoload/admin/factory/class.Events.php` +- Admin controls: `autoload/admin/controls/class.Events.php` +- Admin view: `autoload/admin/view/class.Events.php` +- Admin templates: `admin/templates/events/` +- Frontend factory: `autoload/front/factory/class.Events.php` +- Frontend templates: `templates_user/events/` or `templates/events/` + +**New Frontend Page Template:** +- Custom: `templates_user/page-[name].php` +- Default: `templates/pages/page-[type].php` + +**New Contact Form Variant:** +- Add handler to `plugins/special-actions-middle.php` + +**New AJAX Action:** +- Frontend: add `case` in `ajax.php` +- Admin: add `case` in `admin/ajax.php` + +**New JS/CSS:** +- Frontend JS: `layout/js/custom.js` or new file in `layout/js/` +- Frontend SCSS: `layout/style-scss/` (compiled by Live Sass Compiler) +- Admin SCSS: `admin/css/custom.scss` + +## Special Directories + +**`cache/`:** +- Purpose: Runtime-generated WebP images and temporary cache +- Source: Auto-generated by `\Image` class and `\Cache` class +- Committed: No (runtime data, not in git) + +**`admin/temp/`:** +- Purpose: Temporary file uploads during admin operations +- Source: File upload handlers +- Committed: Should not be committed + +**`templates_user/`:** +- Purpose: Project-specific template overrides +- Source: Manual creation — customizations live here +- Committed: Yes (project-specific content) + +--- + +*Structure analysis: 2026-05-05* +*Update when directory structure changes* diff --git a/.paul/codebase/tech_changelog.md b/.paul/codebase/tech_changelog.md new file mode 100644 index 0000000..59deff1 --- /dev/null +++ b/.paul/codebase/tech_changelog.md @@ -0,0 +1,14 @@ +# Technical Changelog + +> Chronological log of technical changes — what and why. + +## 2026-05-05 — Codebase Mapping + +**Co zrobiono / What changed:** +- Initial codebase map created in `.paul/codebase/` (9 documents) +- Analyzed stack, architecture, structure, conventions, integrations, concerns, DB schema + +**Dlaczego / Why:** +- First-time PAUL project setup — baseline documentation for future planning + +--- diff --git a/.paul/codebase/testing.md b/.paul/codebase/testing.md new file mode 100644 index 0000000..1089bfe --- /dev/null +++ b/.paul/codebase/testing.md @@ -0,0 +1,71 @@ +# Testing Patterns + +**Analysis Date:** 2026-05-05 + +## Test Framework + +**Runner:** +- None detected — no test runner configured + +**Assertion Library:** +- None + +**Run Commands:** +- No test commands available in project + +## Test File Organization + +**Location:** +- No test files found in codebase (searched for `*.test.js`, `*.spec.js`, `*Test.php`, `__tests__/`) + +**Naming:** +- No test naming convention (no tests exist) + +## Test Infrastructure + +**PHPUnit:** +- Not installed — no `phpunit.xml`, no `vendor/phpunit` + +**Jest / Vitest:** +- Not installed — no `package.json`, no test config + +**Coverage Tools:** +- None configured + +**Linting/Static Analysis:** +- No ESLint (no `.eslintrc`) +- No Prettier (no `.prettierrc`) +- No PHP CodeSniffer (no `phpcs.xml`) +- No StyleLint + +## Testing Approach + +**Current state:** +- Manual testing only — no automated test infrastructure +- No CI/CD pipeline to run tests +- No test directories anywhere in the project + +**Quality assurance:** +- Live Sass Compiler (`admin/css/custom.scss`) — validates SCSS syntax at compile time +- FTP deployment via VS Code extension — direct push to production/staging server +- Browser-based manual verification + +## Recommendations (if implementing tests) + +**PHP — PHPUnit:** +- Target the factory layer: `autoload/admin/factory/class.*.php`, `autoload/front/factory/class.*.php` +- These are static methods — use PHPUnit with Medoo mocking + +**JavaScript — Jest or Playwright:** +- Frontend forms and gallery interactions +- Admin grid operations + +**Priority areas to test first (given security concerns):** +1. Input sanitization in `autoload/class.S.php` (the `get()` method) +2. File upload validation in `plugins/special-actions-middle.php` +3. Authentication flow in `admin/index.php` + +--- + +*Testing analysis: 2026-05-05* +*Update when test patterns are introduced*