docs(codebase): add codebase map — stack, architecture, structure, schema, conventions, testing, integrations, concerns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
140
.paul/codebase/architecture.md
Normal file
140
.paul/codebase/architecture.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Architecture
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Pattern Overview
|
||||
|
||||
**Overall:** Custom PHP MVC Monolith (dual frontend — public + admin)
|
||||
|
||||
**Key Characteristics:**
|
||||
- Single shared `core/` layer powering both public and admin frontends
|
||||
- Front Controller routing via Apache rewrite → `index.php` → Router → Controller
|
||||
- All templating via Smarty (no JSON API, no SPA)
|
||||
- Session-based admin auth; anonymous public form with reCAPTCHA
|
||||
|
||||
## Layers
|
||||
|
||||
**Router / Front Controller:**
|
||||
- Purpose: Parse URL, select controller and action
|
||||
- Contains: `Router.class.php`, `index.php` entry points
|
||||
- Location: `_rejestracja/index.php`, `_rejestracja/Admin/index.php`
|
||||
- Depends on: Core class loader
|
||||
- Used by: Nothing (entry point)
|
||||
|
||||
**Controller Layer:**
|
||||
- Purpose: Handle request lifecycle — auth, business logic dispatch, template assignment
|
||||
- Contains: `*Controller.php` files; each has `preDispatch`, `{Name}Action`, `postDispatch`
|
||||
- Location: `_rejestracja/controller/` (public), `_rejestracja/Admin/controller/`
|
||||
- Depends on: DAL layer, Smarty, SessionProxy, Request
|
||||
- Used by: Router
|
||||
|
||||
**DAL Layer (Data Access):**
|
||||
- Purpose: Typed database access; maps rows to model objects
|
||||
- Contains: `Mf{Entity}DAL.class.php` files, `DefaultDAL.class.php` base
|
||||
- Location: `_rejestracja/core/model/`
|
||||
- Depends on: MySQL connection, `DalData` query config objects, `DataObject` base model
|
||||
- Used by: Controllers
|
||||
|
||||
**Model Layer:**
|
||||
- Purpose: Typed domain objects with getters/setters
|
||||
- Contains: `Mf{Entity}.class.php` with `$fields` array mapping DB columns to properties
|
||||
- Location: `_rejestracja/core/model/`
|
||||
- Depends on: `DataObject.class.php` base
|
||||
- Used by: DAL (hydration), Controllers, Templates (via Smarty assigns)
|
||||
|
||||
**Template Layer:**
|
||||
- Purpose: HTML rendering via Smarty
|
||||
- Contains: `.tpl` files, Smarty plugins (`{translate}`, `{formField}`, `{url}`, `{dropDownContainer}`)
|
||||
- Location: `_rejestracja/template/`, `_rejestracja/Admin/template/`
|
||||
- Depends on: Variables assigned in controller (`$this->smarty->assign(...)`)
|
||||
- Used by: Nothing (output layer)
|
||||
|
||||
## Data Flow
|
||||
|
||||
**Public Registration Request:**
|
||||
|
||||
1. Browser `POST /_rejestracja/index` → Apache rewrite → `_rejestracja/index.php`
|
||||
2. `Router` parses URL → selects `IndexController`
|
||||
3. `IndexController::preDispatch()` sets up shared context (Smarty, layout)
|
||||
4. `IndexController::IndexAction()` runs:
|
||||
- Validates reCAPTCHA
|
||||
- Reads POST via `Request::GetPost()`
|
||||
- Hydrates `MfParticipant` model
|
||||
- Calls `MfParticipantDAL::Save($obj)` → INSERT/UPDATE
|
||||
- Sends confirmation email via PHPMailer
|
||||
- `$this->smarty->assign(...)` + Smarty renders confirmation template
|
||||
5. HTML response returned to browser
|
||||
|
||||
**Admin Registration List Request:**
|
||||
|
||||
1. Browser `GET /_rejestracja/Admin/Calc/Reg` → `Admin/index.php` → Router
|
||||
2. `CalcController::preDispatch()` — calls `RunShared('Auth', $param)` (session check)
|
||||
3. `CalcController::RegAction()`:
|
||||
- `MfParticipantDAL::GetResult($dalData)` with sort DESC
|
||||
- `$this->smarty->assign('arrayObj', $arrayObjReg)`
|
||||
4. Smarty renders `Admin/template/partial/Calc/Reg.tpl`
|
||||
|
||||
**State Management:**
|
||||
- PHP sessions via `SessionProxy` for admin auth and transient UI state
|
||||
- No in-memory cache; every request hits MySQL
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
**DataObject / Model:**
|
||||
- Purpose: Typed domain objects with `$fields` array auto-mapping DB↔PHP
|
||||
- Examples: `MfParticipant`, `MfParameters`, `MfDictionary`
|
||||
- Pattern: Active-record-lite; `$fields = ['db_col' => 'PropName']`, auto-generates getters/setters via `__get`/`__set` or explicit methods
|
||||
|
||||
**DefaultDAL / DalData:**
|
||||
- Purpose: Generic CRUD over MySQL; `DalData` is a query config object (conditions, sort, limit)
|
||||
- Examples: `MfParticipantDAL`, `MfParametersDAL`, `MfDictionaryDAL`
|
||||
- Pattern: `GetDalDataObj()` → configure → `GetResult()` / `GetById()` / `Save()` / `Delete()`
|
||||
|
||||
**Smarty Plugin Suite:**
|
||||
- Purpose: Template-level abstractions for common patterns
|
||||
- Key plugins: `{translate word='key'}` (dictionary lookup), `{formField name="" type=""}` (form inputs — text/hidden only), `{url label=X}` (router-aware URL generation), `{dropDownContainer}` (collapsible admin sections)
|
||||
- Pattern: Custom Smarty plugins registered in `_rejestracja/core/`
|
||||
|
||||
## Entry Points
|
||||
|
||||
**Public Frontend:**
|
||||
- Location: `_rejestracja/index.php`
|
||||
- Triggers: HTTP request to `/_rejestracja/`
|
||||
- Responsibilities: Bootstrap core, invoke Router → Controller
|
||||
|
||||
**Admin Frontend:**
|
||||
- Location: `_rejestracja/Admin/index.php`
|
||||
- Triggers: HTTP request to `/_rejestracja/Admin/`
|
||||
- Responsibilities: Same bootstrap + admin-specific auth via `RunShared('Auth')`
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Strategy:** Mostly unhandled — exceptions catch in isolated blocks, errors logged to PHP error_log
|
||||
|
||||
**Patterns:**
|
||||
- `try/catch` in `RegDeleteAction` (DAL delete errors logged but swallowed)
|
||||
- `Validator` class collects field errors and returns them to template via `$out` array
|
||||
- No global exception handler observed
|
||||
|
||||
## Cross-Cutting Concerns
|
||||
|
||||
**Logging:**
|
||||
- PHP `error_log` only; `Utils::ArrayDisplay()` for dev debug (should be removed pre-deploy)
|
||||
|
||||
**Validation:**
|
||||
- `Validator` class at controller level for required-field checks
|
||||
- reCAPTCHA for bot protection on public form
|
||||
- No input sanitization layer beyond Smarty auto-escaping in templates
|
||||
|
||||
**Authentication:**
|
||||
- Admin: `RunShared('Auth', $param)` in every admin controller `preDispatch`
|
||||
- Public: None (anonymous registration form)
|
||||
|
||||
**Internationalization:**
|
||||
- `{translate word='key'}` Smarty plugin reads from `mf_dictionary` table
|
||||
- All visible strings for the registration form are dictionary-backed
|
||||
|
||||
---
|
||||
|
||||
*Architecture analysis: 2026-04-27*
|
||||
*Update when major patterns change*
|
||||
132
.paul/codebase/concerns.md
Normal file
132
.paul/codebase/concerns.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Codebase Concerns
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Security Considerations
|
||||
|
||||
**Credentials committed to repository:**
|
||||
- Risk: DB credentials and SMTP credentials checked into version control
|
||||
- Files: `_rejestracja/core/config/db.config.ini`, `_rejestracja/core/config/smtp.config.ini`
|
||||
- Current mitigation: None — production secrets in plaintext in repo
|
||||
- Recommendations: Move to gitignored config files; add `.gitignore` entry; rotate credentials if repo is/was public
|
||||
|
||||
**Web-accessible migration runners:**
|
||||
- Risk: Anyone who knows the URL can trigger `ALTER TABLE` operations on production DB
|
||||
- Files: `_rejestracja/sql/apply-*.php` (all runner files)
|
||||
- Current mitigation: Requires `?run=YYYYMMDD` param to prevent accidental execution
|
||||
- Recommendations: Move runners outside web root, or add IP/auth check before execution
|
||||
|
||||
**`eval()` usage in core:**
|
||||
- Risk: Remote code execution if user input reaches eval
|
||||
- Files: Detected in `_rejestracja/core/class/` (exact file TBD — needs verification)
|
||||
- Current mitigation: Unknown — depends on what is eval'd
|
||||
- Recommendations: Audit eval usage; replace with explicit logic where possible
|
||||
|
||||
**No input sanitization layer:**
|
||||
- Risk: SQL injection if user input bypasses DAL parameterization; XSS if template escaping is skipped
|
||||
- Files: `_rejestracja/controller/IndexController.php` — uses `Request::GetPost()` directly
|
||||
- Current mitigation: Smarty auto-escaping in templates; DAL may use parameterized queries (verify)
|
||||
- Recommendations: Audit DAL for raw query concatenation; confirm all template output uses `|escape`
|
||||
|
||||
## Tech Debt
|
||||
|
||||
**`core/_model/` directory duplication:**
|
||||
- Issue: 78 files in `_rejestracja/core/_model/` mirror `_rejestracja/core/model/` but are NOT loaded by the autoloader
|
||||
- Files: All files in `_rejestracja/core/_model/`
|
||||
- Why: Historical backup that was never deleted
|
||||
- Impact: Confusing when navigating; edits to `_model/` are silently ignored; risk of editing wrong file
|
||||
- Fix approach: Delete `_rejestracja/core/_model/` entirely — it serves no runtime purpose
|
||||
|
||||
**Commented-out debug calls throughout controllers:**
|
||||
- Issue: `//Utils::ArrayDisplay(Request::GetAllPost());` and similar calls left in code
|
||||
- Files: `_rejestracja/Admin/controller/CalcController.php` (lines 54, 118), others
|
||||
- Why: Dev debugging not cleaned up
|
||||
- Impact: Clutter; risk of accidentally uncommenting in production
|
||||
- Fix approach: Remove all commented-out debug calls during any refactor pass
|
||||
|
||||
**`TODO` about disc field in IndexController:**
|
||||
- Issue: Unresolved logic around the `disc` field in fee calculation
|
||||
- Files: `_rejestracja/controller/IndexController.php`
|
||||
- Why: Deferred during earlier development
|
||||
- Impact: Potentially incorrect discount pricing in edge cases
|
||||
- Fix approach: Review `disc` field handling; either implement or document the intended behavior
|
||||
|
||||
**`setSortBy()` raw string injection:**
|
||||
- Issue: `DalData::setSortBy()` injects value directly into `ORDER BY` SQL clause with no escaping
|
||||
- Files: `_rejestracja/core/class/DefaultDAL.class.php`, all callers
|
||||
- Why: Design choice for simplicity
|
||||
- Impact: SQL injection risk if sort value ever comes from user input (currently hardcoded — low risk)
|
||||
- Fix approach: Whitelist allowed sort columns; never pass user input to `setSortBy()`
|
||||
|
||||
## Fragile Areas
|
||||
|
||||
**`core/core.php` autoloader:**
|
||||
- Files: `_rejestracja/core/core.php`
|
||||
- Why fragile: `spl_autoload_register` loads from `core/model/` — if class naming deviates from `Mf{Entity}.class.php` convention, autoload silently fails
|
||||
- Common failures: Editing `core/_model/` instead of `core/model/` (no error, just stale behavior)
|
||||
- Safe modification: Always verify you're editing `core/model/` not `core/_model/`
|
||||
|
||||
**`$fields` array in model classes:**
|
||||
- Files: All `_rejestracja/core/model/Mf*.class.php`
|
||||
- Why fragile: `$fields` array must exactly match DB column names; mismatch means property reads `null` silently
|
||||
- Common failures: Adding a DB column without updating `$fields`; typo in column name
|
||||
- Safe modification: After adding to `$fields`, verify getter returns expected value from DB
|
||||
|
||||
**Smarty template variable assignment:**
|
||||
- Files: All `_rejestracja/template/` and `_rejestracja/Admin/template/` `.tpl` files
|
||||
- Why fragile: If controller doesn't `assign()` a variable, Smarty silently outputs empty string — no error
|
||||
- Common failures: Renaming a controller variable without updating template references
|
||||
- Safe modification: Search for the variable name in both controller and all related templates before renaming
|
||||
|
||||
## Known Bugs
|
||||
|
||||
**`RegDeleteAction` deletes wrong record:**
|
||||
- Symptoms: `CalcController::RegDeleteAction` calls `MfParametersDAL::Delete($dalData)` instead of `MfParticipantDAL::Delete($dalData)` — DAL class mismatch
|
||||
- Files: `_rejestracja/Admin/controller/CalcController.php` lines 187–206
|
||||
- Workaround: Unknown — may delete a pricing parameter row instead of the participant
|
||||
- Root cause: Copy-paste error in controller method; wrong DAL class referenced
|
||||
|
||||
## Performance Bottlenecks
|
||||
|
||||
**No query caching:**
|
||||
- Problem: Every request hits MySQL — `mf_dictionary` is read on every page load for every `{translate}` call
|
||||
- Files: `_rejestracja/core/model/MfDictionaryDAL.class.php`, all templates using `{translate}`
|
||||
- Cause: No caching layer; MySQL query per translation key
|
||||
- Improvement path: Cache dictionary in PHP session or static array per request
|
||||
|
||||
**No pagination on admin registration list:**
|
||||
- Problem: `CalcController::RegAction` loads all `mf_participant` rows into memory with no LIMIT
|
||||
- Files: `_rejestracja/Admin/controller/CalcController.php` (RegAction), `_rejestracja/Admin/template/partial/Calc/Reg.tpl`
|
||||
- Cause: `DalData` has no pagination set; template has commented-out pager HTML
|
||||
- Impact: Will degrade significantly as registration count grows past a few hundred rows
|
||||
|
||||
## Dependencies at Risk
|
||||
|
||||
**PHP 5.x:**
|
||||
- Risk: PHP 5.x is end-of-life since December 2018; no security patches
|
||||
- Impact: Known PHP 5.x vulnerabilities unpatched on production server
|
||||
- Migration plan: Requires testing all code for PHP 7.x/8.x compatibility (significant effort)
|
||||
|
||||
**jQuery 1.x:**
|
||||
- Risk: jQuery 1.x is unmaintained; known XSS vulnerabilities in older versions
|
||||
- Impact: Frontend JS security issues
|
||||
- Migration plan: Upgrade to jQuery 3.x or replace with vanilla JS
|
||||
|
||||
**Bundled Smarty / PHPMailer:**
|
||||
- Risk: Vendor-bundled libraries in `core/lib/` may be outdated versions with unpatched CVEs
|
||||
- Impact: Template injection (Smarty), email header injection (PHPMailer)
|
||||
- Migration plan: Replace with Composer-managed dependencies and current versions
|
||||
|
||||
## Test Coverage Gaps
|
||||
|
||||
**Everything — no tests exist:**
|
||||
- What's not tested: All application logic
|
||||
- Files: All of `_rejestracja/`
|
||||
- Risk: Any code change could introduce silent regressions; verified by manual testing only
|
||||
- Priority: High for `IndexController.php` (primary user-facing flow) and `DefaultDAL.class.php` (affects all DB operations)
|
||||
- Difficulty to test: Medium — PHP 5.x compatible test framework required; DAL tests need DB fixture
|
||||
|
||||
---
|
||||
|
||||
*Concerns audit: 2026-04-27*
|
||||
*Update as issues are fixed or new ones discovered*
|
||||
136
.paul/codebase/conventions.md
Normal file
136
.paul/codebase/conventions.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Coding Conventions
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
**Files:**
|
||||
- `Mf{Entity}.class.php` — model classes (e.g., `MfParticipant.class.php`)
|
||||
- `Mf{Entity}DAL.class.php` — data access classes (e.g., `MfParticipantDAL.class.php`)
|
||||
- `{Name}Controller.php` — controller classes (e.g., `IndexController.php`, `CalcController.php`)
|
||||
- `{Name}.tpl` — Smarty template files (e.g., `Index.tpl`, `Reg.tpl`)
|
||||
|
||||
**Classes:**
|
||||
- PascalCase for all classes: `MfParticipant`, `IndexController`, `DefaultDAL`
|
||||
- `Mf` prefix for domain model/DAL classes (short for "mediaflex")
|
||||
|
||||
**Methods:**
|
||||
- PascalCase for public methods: `GetById()`, `GetResult()`, `GetName()`, `SetStatus()`
|
||||
- camelCase for getters/setters in newer models: `getAdditionalInfo()`, `setAdditionalInfo()`
|
||||
- `{Name}Action` suffix for controller action methods: `IndexAction`, `RegAction`, `RegEditAction`
|
||||
|
||||
**Variables:**
|
||||
- camelCase for local variables: `$objParticipant`, `$arrayObjReg`, `$dalData`
|
||||
- `$array*` prefix for arrays: `$arrayObj`, `$arrayFee`, `$arrayObjParameters`
|
||||
- `$obj*` prefix for single model instances: `$objParam`, `$objParameters`
|
||||
|
||||
**DB Columns:**
|
||||
- `snake_case` in database: `id_mf_participant`, `date_add`, `additional_info`
|
||||
- Mapped to camelCase properties via `$fields` array in model
|
||||
|
||||
## Code Style
|
||||
|
||||
**Formatting:**
|
||||
- Tabs for indentation (not spaces)
|
||||
- No enforced line length
|
||||
- No Prettier/PHP-CS-Fixer — manual formatting
|
||||
- PHP opening tag `<?php`, closing tag `?>` present in all files
|
||||
|
||||
**Linting:**
|
||||
- No configured linter
|
||||
- No static analysis tools
|
||||
|
||||
## Model Field Mapping Pattern
|
||||
|
||||
The `$fields` static array in each model class maps DB column names to property names:
|
||||
|
||||
```php
|
||||
static $fields = array(
|
||||
'id_mf_participant' => 'Id',
|
||||
'name' => 'Name',
|
||||
'nip' => 'Nip',
|
||||
'additional_info' => 'additionalInfo',
|
||||
);
|
||||
```
|
||||
|
||||
Getters/setters follow `get{PropertyName}()` / `set{PropertyName}()` convention.
|
||||
|
||||
## Template Conventions (Smarty)
|
||||
|
||||
**Always use these Smarty plugins — do not inline PHP:**
|
||||
- `{translate word='key'}` — all visible text strings (reads from `mf_dictionary` table)
|
||||
- `{url label=X}` or `{url Calc=Y id=$id}` — all URL generation (never hardcode paths)
|
||||
- `{formField name="x" type="text"}` — text/hidden inputs only; does NOT support textarea
|
||||
- `{dropDownContainer title='...'}` — admin collapsible sections
|
||||
|
||||
**Textarea limitation:**
|
||||
- `{formField}` Smarty plugin only supports `type="text"` and `type="hidden"`
|
||||
- Multi-line fields require raw `<textarea>` with manual POST repopulation:
|
||||
|
||||
```smarty
|
||||
<textarea name="field_name" rows="3">{if isset($smarty.post.field_name)}{$smarty.post.field_name|escape}{/if}</textarea>
|
||||
```
|
||||
|
||||
**Template structure:**
|
||||
- Public templates: `_rejestracja/template/partial/Index/{Name}.tpl`
|
||||
- Admin templates: `_rejestracja/Admin/template/partial/{Controller}/{Name}.tpl`
|
||||
- Smarty `assign`: done in controller via `$this->smarty->assign('key', $value)`
|
||||
|
||||
## Controller Pattern
|
||||
|
||||
Every controller has three methods:
|
||||
|
||||
```php
|
||||
public function preDispatch($param) {
|
||||
$this->RunShared('Auth', $param); // admin only
|
||||
$this->Run($param);
|
||||
$this->smarty->assign('titleAdmin', '...');
|
||||
// nav structure setup
|
||||
}
|
||||
|
||||
public function {Name}Action($param) {
|
||||
// business logic + smarty assigns
|
||||
}
|
||||
|
||||
public function postDispatch($param) {
|
||||
// usually empty
|
||||
}
|
||||
```
|
||||
|
||||
## DAL Usage Pattern
|
||||
|
||||
```php
|
||||
$dalData = Mf{Entity}DAL::GetDalDataObj();
|
||||
$dalData->addCondition('column_name', $value);
|
||||
$dalData->setSortBy('column_name DESC'); // DESC must be in the string
|
||||
$results = Mf{Entity}DAL::GetResult($dalData);
|
||||
$single = Mf{Entity}DAL::GetById($id);
|
||||
Mf{Entity}DAL::Save($obj);
|
||||
```
|
||||
|
||||
## Migration Runner Pattern
|
||||
|
||||
```php
|
||||
// Check before altering (idempotent)
|
||||
$check = $conn->query("SELECT ... FROM INFORMATION_SCHEMA.COLUMNS WHERE ...");
|
||||
if ($check->num_rows > 0) {
|
||||
echo "already exists — skipped";
|
||||
exit;
|
||||
}
|
||||
$conn->query("ALTER TABLE `table` ADD COLUMN `col` TEXT NULL DEFAULT NULL AFTER `other_col`");
|
||||
echo "success";
|
||||
```
|
||||
|
||||
Runner files require `?run=YYYYMMDD` param to prevent accidental execution.
|
||||
|
||||
## Comments
|
||||
|
||||
- Minimal comments in existing code
|
||||
- `//Utils::ArrayDisplay()` debug calls left commented — remove before deploy
|
||||
- PHPDoc-style block headers on controller classes (legacy format, not enforced)
|
||||
- `TODO` comments used sparingly: `// TODO: consider disc field logic`
|
||||
|
||||
---
|
||||
|
||||
*Convention analysis: 2026-04-27*
|
||||
*Update when patterns change*
|
||||
123
.paul/codebase/db_schema.md
Normal file
123
.paul/codebase/db_schema.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Database Schema
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Overview
|
||||
|
||||
MySQL database on mysql7.ceti.pl. Custom DAL layer; no ORM. All migrations are manual SQL files with idempotent PHP runners in `_rejestracja/sql/`.
|
||||
|
||||
## Core Tables
|
||||
|
||||
### `mf_participant`
|
||||
|
||||
Primary registration table. One row per conference registrant.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id_mf_participant` | INT PK AUTO_INCREMENT | Primary key |
|
||||
| `name` | VARCHAR | First name |
|
||||
| `surname` | VARCHAR | Last name |
|
||||
| `degree` | VARCHAR | Academic title/degree |
|
||||
| `position` | VARCHAR | Job position |
|
||||
| `phone` | VARCHAR | Phone number |
|
||||
| `fax` | VARCHAR | Fax number |
|
||||
| `email` | VARCHAR | Email address |
|
||||
| `institution` | VARCHAR | Institution name |
|
||||
| `address` | VARCHAR | Street address |
|
||||
| `post_code` | VARCHAR | Postal code |
|
||||
| `city` | VARCHAR | City |
|
||||
| `nip` | VARCHAR | Tax ID (NIP) |
|
||||
| `additional_info` | TEXT NULL | Free-text notes — added 2026-04-27 |
|
||||
| `referat` | TINYINT | Presentation flag (0/1/2) |
|
||||
| `poster` | TINYINT | Poster flag (0/1/2) |
|
||||
| `message` | TEXT | Presentation topic |
|
||||
| `autor` | VARCHAR | Co-authors |
|
||||
| `participation_option` | VARCHAR | `full` / `one_day_lodging` / `one_day_no_lodging` |
|
||||
| `participation_days` | VARCHAR | Selected days (for one-day option) |
|
||||
| `diet` | TINYINT | Dietary preference (1=standard, 2=special) |
|
||||
| `diet_special` | VARCHAR | Special diet description |
|
||||
| `fee_full` | TEXT | Serialized fee selection array |
|
||||
| `fee_one_day` | VARCHAR | One-day fee value |
|
||||
| `price` | DECIMAL | Calculated total price |
|
||||
| `agree1` | TINYINT | Data processing consent |
|
||||
| `agree2` | TINYINT | Image consent |
|
||||
| `status` | TINYINT | Payment status (1=no, 2=yes) |
|
||||
| `location` | TINYINT | Conference location (1=aktualia, 2=PAN) |
|
||||
| `date_add` | DATETIME | Registration timestamp |
|
||||
|
||||
**Model:** `_rejestracja/core/model/MfParticipant.class.php`
|
||||
**DAL:** `_rejestracja/core/model/MfParticipantDAL.class.php`
|
||||
|
||||
### `mf_parameters`
|
||||
|
||||
Pricing/fee configuration. Each row is a fee option (accommodation, conference fee, etc.).
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id_mf_parameters` | INT PK | Primary key |
|
||||
| `name` | VARCHAR | Display name |
|
||||
| `opis` | TEXT | Description |
|
||||
| `price` | DECIMAL | Regular price (net) |
|
||||
| `price_prom` | DECIMAL | Promotional/discount price |
|
||||
| `price_progres` | TINYINT | Progressive pricing flag |
|
||||
| `count_progres` | INT | Progressive pricing count threshold |
|
||||
| `unit` | VARCHAR | Unit label |
|
||||
| `link_id` | INT | Grouping link ID |
|
||||
| `type` | TINYINT | Parameter type category |
|
||||
| `sort` | INT | Display order |
|
||||
| `publication` | TINYINT | Published/active flag |
|
||||
|
||||
**Model:** `_rejestracja/core/model/MfParameters.class.php`
|
||||
**DAL:** `_rejestracja/core/model/MfParametersDAL.class.php`
|
||||
|
||||
### `mf_dictionary`
|
||||
|
||||
Key-value store for all translatable/editable text strings visible in the UI.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id_mf_dictionary` | INT PK | Primary key |
|
||||
| `keyword` | VARCHAR | Lookup key (e.g., `registration_yes`) |
|
||||
| `value` | TEXT | Display value |
|
||||
| `location` | TINYINT | Site location (1/2) |
|
||||
|
||||
**Model:** `_rejestracja/core/model/MfDictionary.class.php`
|
||||
**DAL:** `_rejestracja/core/model/MfDictionaryDAL.class.php`
|
||||
**Usage:** `{translate word='key'}` Smarty plugin → `MfDictionaryDAL` lookup
|
||||
|
||||
### Supporting Tables
|
||||
|
||||
- `wp_setup` — scalar/list settings for the registration form (Phase 3 form settings)
|
||||
- `mf_article` / `mf_article_content` — content management (HomeSite admin)
|
||||
- Additional tables inferred from DAL files in `core/model/`
|
||||
|
||||
## Migration Pattern
|
||||
|
||||
**SQL file:** `_rejestracja/sql/YYYY-MM-DD-description.sql`
|
||||
**Runner:** `_rejestracja/sql/apply-YYYY-MM-DD-description.php`
|
||||
|
||||
Runner pattern:
|
||||
1. Check `INFORMATION_SCHEMA` (or similar) before altering
|
||||
2. Requires `?run=YYYYMMDD` query param (or `--run` CLI flag) to execute
|
||||
3. Prints "already exists / skipped" or "success" output
|
||||
4. Web-accessible — see CONCERNS.md for security note
|
||||
|
||||
**Applied migrations:**
|
||||
- `2026-04-24-registration-form-settings` — `wp_setup` table (Phase 3, Plan 01)
|
||||
- `2026-04-27-additional-info-field` — `additional_info` column on `mf_participant` (Phase 3, Plan 02)
|
||||
|
||||
## DAL Query Pattern
|
||||
|
||||
```php
|
||||
$dalData = MfParticipantDAL::GetDalDataObj();
|
||||
$dalData->addCondition('location', 1);
|
||||
$dalData->setSortBy('id_mf_participant DESC'); // value injected directly into ORDER BY
|
||||
$results = MfParticipantDAL::GetResult($dalData);
|
||||
```
|
||||
|
||||
`setSortBy()` value is injected verbatim into `ORDER BY` — include `DESC` in the string.
|
||||
|
||||
---
|
||||
|
||||
*Schema analysis: 2026-04-27*
|
||||
*Update when tables or columns change*
|
||||
87
.paul/codebase/integrations.md
Normal file
87
.paul/codebase/integrations.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# External Integrations
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## APIs & External Services
|
||||
|
||||
**Email (Transactional):**
|
||||
- PHPMailer via mediaflex.pl SMTP — registration confirmation emails, admin notifications
|
||||
- SDK/Client: PHPMailer bundled in `_rejestracja/core/lib/`
|
||||
- Auth: SMTP credentials in `_rejestracja/core/config/smtp.config.ini` (committed — HIGH RISK)
|
||||
- Usage: `IndexController.php` triggers email after successful registration save
|
||||
|
||||
**Spam Protection:**
|
||||
- Google reCAPTCHA v2 — public registration form submission guard
|
||||
- Integration: server-side verification via reCAPTCHA API in `IndexController.php`
|
||||
- Site key: embedded in `_rejestracja/template/partial/Index/Index.tpl`
|
||||
- Secret key: in config file
|
||||
|
||||
## Data Storage
|
||||
|
||||
**Databases:**
|
||||
- MySQL on mysql7.ceti.pl — primary data store
|
||||
- Connection: credentials in `_rejestracja/core/config/db.config.ini` (INI format, committed)
|
||||
- Client: custom mysqli-based DAL (`_rejestracja/core/class/DefaultDAL.class.php`)
|
||||
- Migrations: manual SQL files in `_rejestracja/sql/`, applied via PHP runner scripts
|
||||
|
||||
**File Storage:**
|
||||
- Local filesystem — file uploads via `move_uploaded_file()`
|
||||
- Upload directory: within `_rejestracja/Static/` or server path
|
||||
- No cloud storage
|
||||
|
||||
**Caching:**
|
||||
- None — all queries hit MySQL directly, no Redis or Memcached
|
||||
|
||||
## Authentication & Identity
|
||||
|
||||
**Admin Auth:**
|
||||
- Custom session-based auth — `AuthDAL` + `SessionProxy`
|
||||
- Implementation: `_rejestracja/Admin/controller/` calls `$this->RunShared('Auth', $param)` in `preDispatch`
|
||||
- Session storage: PHP sessions via `SessionProxy`
|
||||
- No external identity provider
|
||||
|
||||
**Public (Registration) Form:**
|
||||
- No user authentication — anonymous submission with reCAPTCHA only
|
||||
|
||||
## Rich Text Editing
|
||||
|
||||
**CKEditor:**
|
||||
- Admin templates use CKEditor for content editing (`HomeSite` admin area)
|
||||
- Bundled in `_rejestracja/Static/` or loaded from CDN
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
**Error Tracking:**
|
||||
- None — no Sentry, no error reporting service
|
||||
|
||||
**Analytics:**
|
||||
- None detected
|
||||
|
||||
**Logs:**
|
||||
- PHP error_log only; no structured logging service
|
||||
|
||||
## CI/CD & Deployment
|
||||
|
||||
**Hosting:**
|
||||
- Shared hosting: mediaflex.pl / ceti.pl
|
||||
- Deployment: manual FTP upload via VS Code FTP Sync extension
|
||||
- Config: `.vscode/ftp-kr.sync.cache.json`
|
||||
|
||||
**CI Pipeline:**
|
||||
- None — no GitHub Actions, no automated tests or deployment
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
**Development:**
|
||||
- Required configs: `db.config.ini` (DB host/user/pass/name), `smtp.config.ini` (SMTP credentials)
|
||||
- Both committed to repo — no gitignored secret management
|
||||
- Local dev requires matching PHP 5.x + MySQL
|
||||
|
||||
**Production:**
|
||||
- Same config files deployed via FTP
|
||||
- No environment-specific config switching
|
||||
|
||||
---
|
||||
|
||||
*Integration audit: 2026-04-27*
|
||||
*Update when adding/removing external services*
|
||||
74
.paul/codebase/stack.md
Normal file
74
.paul/codebase/stack.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Technology Stack
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Languages
|
||||
|
||||
**Primary:**
|
||||
- PHP 5.x — all server-side application code
|
||||
- SQL — database schema and migrations in `_rejestracja/sql/`
|
||||
|
||||
**Secondary:**
|
||||
- JavaScript/jQuery 1.x — frontend interactions, form validation
|
||||
- Smarty template language — HTML generation (`_rejestracja/template/`)
|
||||
|
||||
## Runtime
|
||||
|
||||
**Environment:**
|
||||
- PHP 5.x (shared hosting, mediaflex.pl / ceti.pl)
|
||||
- Apache (inferred from .htaccess routing)
|
||||
- No CLI build step; all runtime is PHP-on-request
|
||||
|
||||
**Package Manager:**
|
||||
- None — no Composer, no npm
|
||||
- All dependencies bundled in `_rejestracja/core/lib/` and `_rejestracja/Static/`
|
||||
|
||||
## Frameworks
|
||||
|
||||
**Core:**
|
||||
- Custom PHP MVC — hand-rolled Front Controller, Router, Controller base, DAL
|
||||
- Smarty 3.x — templating engine (loaded from `_rejestracja/core/lib/Smarty/`)
|
||||
|
||||
**Testing:**
|
||||
- None — no test framework detected anywhere in codebase
|
||||
|
||||
**Build/Dev:**
|
||||
- None — no build pipeline; PHP files deployed directly to shared hosting via FTP
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
**Critical:**
|
||||
- Smarty 3.x — template rendering; bundled in `_rejestracja/core/lib/Smarty/`
|
||||
- PHPMailer — SMTP email via mediaflex.pl; bundled in `_rejestracja/core/lib/`
|
||||
- jQuery 1.x — frontend JS; bundled in `_rejestracja/Static/js/`
|
||||
- Google reCAPTCHA v2 — spam protection on public registration form
|
||||
|
||||
**Infrastructure:**
|
||||
- MySQL (mysql7.ceti.pl) — primary data store, accessed via custom DAL wrapping mysqli
|
||||
- Google Fonts / CDN — font loading in templates
|
||||
|
||||
## Configuration
|
||||
|
||||
**Environment:**
|
||||
- INI config files (not .env): `_rejestracja/core/config/db.config.ini` (DB credentials), `smtp.config.ini` (email)
|
||||
- No environment variable system — values hardcoded in config files committed to repo
|
||||
|
||||
**Build:**
|
||||
- No build config files
|
||||
|
||||
## Platform Requirements
|
||||
|
||||
**Development:**
|
||||
- PHP 5.x compatible environment
|
||||
- MySQL server
|
||||
- FTP access for deployment (`.vscode/ftp-kr.sync.cache.json` indicates VS Code FTP sync)
|
||||
|
||||
**Production:**
|
||||
- Shared hosting: mediaflex.pl / ceti.pl
|
||||
- PHP 5.x, MySQL (mysql7.ceti.pl)
|
||||
- Direct FTP upload, no CI/CD
|
||||
|
||||
---
|
||||
|
||||
*Stack analysis: 2026-04-27*
|
||||
*Update after major dependency changes*
|
||||
145
.paul/codebase/structure.md
Normal file
145
.paul/codebase/structure.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Codebase Structure
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
_rejestracja/
|
||||
├── Admin/ # Admin frontend (separate MVC stack)
|
||||
│ ├── controller/ # Admin controllers (CalcController, HomeSiteController, etc.)
|
||||
│ └── template/ # Admin Smarty templates
|
||||
│ └── partial/
|
||||
│ └── Calc/ # Registration admin views (Reg.tpl, RegEdit.tpl, RegPAN.tpl)
|
||||
├── controller/ # Public controllers (IndexController.php)
|
||||
├── core/ # Shared core layer (both frontends)
|
||||
│ ├── class/ # Framework classes (Router, DefaultDAL, DataObject, Validator, etc.)
|
||||
│ ├── config/ # INI config files (db.config.ini, smtp.config.ini)
|
||||
│ ├── lib/ # Third-party libraries (Smarty, PHPMailer)
|
||||
│ ├── model/ # Active models: Mf{Entity}.class.php + Mf{Entity}DAL.class.php
|
||||
│ └── _model/ # Legacy backup of model/ — NOT loaded by autoloader (78 mirror files)
|
||||
├── sql/ # Migration SQL files + PHP runner scripts
|
||||
├── Static/ # Frontend assets (CSS, JS, images)
|
||||
│ └── image/Admin/ # Admin UI images (Thumbs.db ignored)
|
||||
├── template/ # Public Smarty templates
|
||||
│ └── partial/Index/ # Registration form templates (Index.tpl, IndexSent.tpl, etc.)
|
||||
├── index.php # Public frontend entry point
|
||||
└── Admin/index.php # Admin frontend entry point
|
||||
```
|
||||
|
||||
## Directory Purposes
|
||||
|
||||
**`core/model/`** (ACTIVE — edit here):
|
||||
- Purpose: All domain models and DAL classes
|
||||
- Contains: `Mf{Entity}.class.php` (model), `Mf{Entity}DAL.class.php` (data access)
|
||||
- Key files: `MfParticipant.class.php`, `MfParticipantDAL.class.php`, `MfParameters.class.php`, `MfDictionary.class.php`
|
||||
- Loaded by: `core/core.php` autoloader via `spl_autoload_register`
|
||||
|
||||
**`core/_model/`** (LEGACY — do not edit):
|
||||
- Purpose: Stale backup of model directory; 78 files mirroring `core/model/`
|
||||
- NOT loaded by autoloader — changes here have no effect
|
||||
- Should be deleted but kept for historical reference
|
||||
|
||||
**`core/class/`**:
|
||||
- Purpose: Framework infrastructure
|
||||
- Key files: `Router.class.php`, `DefaultDAL.class.php`, `DataObject.class.php`, `Validator.class.php`, `SessionProxy.class.php`, `Request.class.php`, `MainController.class.php`
|
||||
|
||||
**`core/config/`**:
|
||||
- Purpose: Runtime configuration
|
||||
- Key files: `db.config.ini` (DB credentials), `smtp.config.ini` (SMTP credentials)
|
||||
- WARNING: Both committed to repo — contain production secrets
|
||||
|
||||
**`core/lib/`**:
|
||||
- Purpose: Bundled third-party libraries
|
||||
- Contains: Smarty 3.x, PHPMailer, other vendored code
|
||||
|
||||
**`controller/`**:
|
||||
- Purpose: Public-facing request handlers
|
||||
- Key files: `IndexController.php` (registration form — main entry point for all user interactions)
|
||||
|
||||
**`Admin/controller/`**:
|
||||
- Purpose: Admin panel request handlers
|
||||
- Key files: `CalcController.php` (registration list, edit, delete), `HomeSiteController.php` (content editing)
|
||||
|
||||
**`template/partial/Index/`**:
|
||||
- Purpose: Public registration form templates
|
||||
- Key files: `Index.tpl` (main form), `Index_good.tpl` (alternate variant), `IndexSent.tpl` (confirmation), `IndexSent_good.tpl` (alternate confirmation)
|
||||
|
||||
**`Admin/template/partial/Calc/`**:
|
||||
- Purpose: Admin registration management views
|
||||
- Key files: `Reg.tpl` (registration list), `RegEdit.tpl` (edit payment status), `RegPAN.tpl` (alternate location view)
|
||||
|
||||
**`sql/`**:
|
||||
- Purpose: Database migrations
|
||||
- Pattern: `YYYY-MM-DD-description.sql` + `apply-YYYY-MM-DD-description.php` (idempotent runner)
|
||||
- Key files: `apply-2026-04-24-registration-form-settings.php`, `apply-2026-04-27-additional-info-field.php`
|
||||
|
||||
## Key File Locations
|
||||
|
||||
**Entry Points:**
|
||||
- `_rejestracja/index.php` — public registration frontend
|
||||
- `_rejestracja/Admin/index.php` — admin panel frontend
|
||||
|
||||
**Configuration:**
|
||||
- `_rejestracja/core/config/db.config.ini` — database connection
|
||||
- `_rejestracja/core/config/smtp.config.ini` — SMTP email credentials
|
||||
- `.vscode/ftp-kr.sync.cache.json` — FTP deployment sync config
|
||||
|
||||
**Core Logic:**
|
||||
- `_rejestracja/core/class/DefaultDAL.class.php` — generic CRUD base
|
||||
- `_rejestracja/core/model/MfParticipant.class.php` — registration participant model
|
||||
- `_rejestracja/controller/IndexController.php` — registration form controller (save, email, display)
|
||||
- `_rejestracja/Admin/controller/CalcController.php` — admin registration management
|
||||
|
||||
**Testing:**
|
||||
- None
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
**Files:**
|
||||
- `Mf{Entity}.class.php` — model classes (MfParticipant, MfParameters, MfDictionary)
|
||||
- `Mf{Entity}DAL.class.php` — data access layer classes
|
||||
- `{Name}Controller.php` — controller classes
|
||||
- `{Name}.tpl` — Smarty templates
|
||||
- `YYYY-MM-DD-description.sql` — migration SQL files
|
||||
- `apply-YYYY-MM-DD-description.php` — idempotent migration runners
|
||||
|
||||
**Directories:**
|
||||
- PascalCase for Admin sub-directories (Admin/controller/, Admin/template/)
|
||||
- lowercase for core infrastructure directories (core/class/, core/model/)
|
||||
|
||||
## Where to Add New Code
|
||||
|
||||
**New model field:**
|
||||
- Model: `_rejestracja/core/model/Mf{Entity}.class.php` — add to `$fields`, add property + getter/setter
|
||||
- Migration: `_rejestracja/sql/YYYY-MM-DD-description.sql` + `apply-*.php` runner
|
||||
|
||||
**New form field (public):**
|
||||
- Template: `_rejestracja/template/partial/Index/Index.tpl` and `Index_good.tpl`
|
||||
- Controller: `_rejestracja/controller/IndexController.php` — read POST, set on model
|
||||
- Confirmation: `IndexSent.tpl`, `IndexSent_good.tpl`
|
||||
- Admin display: `_rejestracja/Admin/template/partial/Calc/Reg.tpl`
|
||||
|
||||
**New admin action:**
|
||||
- Controller: `_rejestracja/Admin/controller/CalcController.php` — add `{Name}Action` method
|
||||
- Template: `_rejestracja/Admin/template/partial/Calc/{Name}.tpl`
|
||||
|
||||
**New dictionary phrase:**
|
||||
- SQL insert into `mf_dictionary` table + migration runner
|
||||
|
||||
## Special Directories
|
||||
|
||||
**`core/_model/`:**
|
||||
- Purpose: Legacy backup, 78 files mirroring `core/model/`
|
||||
- Source: Manual backup, not updated consistently
|
||||
- NOT in autoloader path — editing here has NO effect
|
||||
|
||||
**`sql/`:**
|
||||
- Purpose: Database migration scripts
|
||||
- Runners are web-accessible (risk) — require `?run=YYYYMMDD` param to execute
|
||||
- Idempotent pattern: check `INFORMATION_SCHEMA` before `ALTER TABLE`
|
||||
|
||||
---
|
||||
|
||||
*Structure analysis: 2026-04-27*
|
||||
*Update when directory structure changes*
|
||||
66
.paul/codebase/testing.md
Normal file
66
.paul/codebase/testing.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Testing Patterns
|
||||
|
||||
**Analysis Date:** 2026-04-27
|
||||
|
||||
## Test Framework
|
||||
|
||||
**Runner:**
|
||||
- None — no test framework detected in the codebase
|
||||
|
||||
**Assertion Library:**
|
||||
- None
|
||||
|
||||
**Run Commands:**
|
||||
- No test commands defined
|
||||
|
||||
## Test File Organization
|
||||
|
||||
**Location:**
|
||||
- No test files exist anywhere in `_rejestracja/`
|
||||
|
||||
**Naming:**
|
||||
- N/A — no test files
|
||||
|
||||
## Current Verification Approach
|
||||
|
||||
All verification is manual:
|
||||
|
||||
1. **PHP syntax check** — `php -l {file}` run manually or via IDE
|
||||
2. **Browser smoke test** — manually load registration form, submit, check DB/email
|
||||
3. **Admin panel check** — manually verify `/_rejestracja/Admin/Calc/Reg` renders correctly
|
||||
4. **Migration runner** — run `apply-*.php?run=YYYYMMDD` and read output message
|
||||
|
||||
## Test Coverage Gaps
|
||||
|
||||
**Everything is untested:**
|
||||
- Form submission and validation logic in `IndexController.php`
|
||||
- Model field mapping in `MfParticipant.class.php` (especially `$fields` array)
|
||||
- DAL query generation in `DefaultDAL.class.php`
|
||||
- Email sending logic
|
||||
- Payment status calculation
|
||||
- Smarty plugin behavior (`{translate}`, `{formField}`, `{url}`)
|
||||
- Migration runners (idempotency)
|
||||
|
||||
## Adding Tests (if introduced)
|
||||
|
||||
If a test framework were added to this PHP project:
|
||||
|
||||
**Recommended framework:** PHPUnit (standard PHP unit testing)
|
||||
|
||||
**What would be easiest to test first:**
|
||||
- Model getter/setter roundtrips (pure PHP, no DB)
|
||||
- `Validator` class required-field checks
|
||||
- Price calculation logic (if extracted from controller)
|
||||
|
||||
**What would require infrastructure:**
|
||||
- DAL tests (require MySQL connection)
|
||||
- Full controller tests (require HTTP or simulated request context)
|
||||
- Email tests (require mock or captured SMTP)
|
||||
|
||||
**Key constraint:**
|
||||
- PHP 5.x compatibility required — PHPUnit 4.x or 5.x (not modern versions)
|
||||
|
||||
---
|
||||
|
||||
*Testing analysis: 2026-04-27*
|
||||
*Update if a test framework is introduced*
|
||||
Reference in New Issue
Block a user