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 <noreply@anthropic.com>
This commit is contained in:
2026-05-05 22:02:04 +02:00
parent 2d3bb66d42
commit cf1a0adb0b
10 changed files with 1377 additions and 0 deletions

View File

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

188
.paul/codebase/concerns.md Normal file
View File

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

View File

@@ -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 `<?` and `?>` used in templates (not `<?php`)
- Array formatting: multi-line with aligned assignment operators
**SCSS:**
- Indentation: 2 spaces
- Compilation directive at file top: `// out: ../style-css/style.css, compress: true, sourceMap: true`
- Responsive mixins in `layout/style-scss/_mixins.scss` (breakpoints: xxs, xs, sm, md, lg, xl, xxl, xxxl)
- Vendor prefixes included manually (`-webkit-`, `-moz-`)
**JavaScript:**
- jQuery as primary library (not vanilla JS for DOM)
- ES6 template literals used (`#${boxHref}`)
- No module system — all global scope
**Linting:**
- No ESLint configured
- No Prettier configured
- No PHP CodeSniffer
- No StyleLint
- Code style enforced only by convention/habit
## Architecture Conventions
**MVC Layer Separation:**
- Controls handle requests and call factories — no direct DB queries in controls
- Factories contain all DB queries (Medoo) — static methods
- Views generate HTML and call `Tpl::view()` — no DB queries
- Templates are pure HTML+PHP interpolation — minimal logic
**Namespace Usage:**
- `namespace admin\controls;` / `namespace admin\factory;` / `namespace admin\view;`
- `namespace front\controls;` / `namespace front\factory;` / `namespace front\view;`
- Cross-layer calls use fully qualified names: `\admin\factory\Articles::duplicate_article()`
**Global Helpers:**
- `\S::get()` — parameter retrieval with optional sanitization
- `\S::alert()` — admin notification system
- `\Html::` — HTML generation utilities
## Comments & Documentation
**Comment style:**
- Line comments: `// comment` (mix of Polish and English)
- Block markers: `/* sekcja */` used to label code sections
- Examples from `autoload/admin/factory/class.Articles.php`:
- `/* tłumaczenia */` (translations section)
- `/* parametry bez wersji językowych */` (params without language versions)
- `/* pliki */` (files section)
**Documentation:**
- No PHPDoc blocks
- No `@param` / `@return` / `@throws` annotations
- No type hints in function signatures
- Comments describe sections, not individual functions
## Import / Include Patterns
**PHP:**
- Classes auto-loaded via custom autoloader (not Composer)
- Libraries included directly in entry points: `require 'libraries/medoo/medoo.php'`
- No `use` statements for namespaced imports — always fully qualified calls
**JavaScript:**
- All libraries loaded via `<script>` 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*

318
.paul/codebase/db_schema.md Normal file
View File

@@ -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

View File

@@ -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=<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 `</head>` 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*

91
.paul/codebase/stack.md Normal file
View File

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

203
.paul/codebase/structure.md Normal file
View File

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

View File

@@ -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
---

71
.paul/codebase/testing.md Normal file
View File

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