# Architecture — rank24.pl

## Pattern
Custom PHP MVC — no framework. Layered as **controls → factory → view**, with Savant3 templates.

## Entry Points

| File | Purpose |
|------|---------|
| `index.php` | Front controller — bootstraps app, routes all page requests |
| `ajax.php` | xajax AJAX endpoint |
| `json.php` | JSON responses for AJAX calls |
| `api.php` | External API integration endpoint |
| `cron.php` | Background job runner |
| `proxy.php` | Proxy management endpoint |
| `ajax-check.php` | Health check / secondary AJAX |
| `dsf.php` | DataForSEO callback handler |

## Directory Structure

```
rank24.pl/
├── index.php               Front controller & bootstrap
├── config.php              All configuration (DB, proxy, intervals)
├── cron.php                Cron job runner
├── .htaccess               URL rewriting rules
│
├── autoload/               PSR-0-style autoloaded classes
│   ├── class.*.php         Core utility classes
│   ├── controls/           Page controllers (routing + business logic)
│   ├── factory/            Data access layer (DB queries via Medoo)
│   ├── view/               View renderers (build Savant3 template output)
│   ├── savant3/            Savant3 template engine internals
│   └── opd*/               Legacy PDO debug wrapper
│
├── templates/              PHP view templates
│   ├── page/               Admin main/unlogged layouts
│   ├── client/             Client dashboard templates
│   ├── ranker/             Admin/ranker management templates
│   ├── reseller/           Reseller dashboard templates
│   ├── html/               Reusable form component templates
│   ├── other/              Pagination, alerts, misc templates
│   └── cron/               Cron management view
│
├── functions/              xajax AJAX handler functions
│   ├── xajax.php           xajax init & config
│   ├── xajax-ranker.php    Rank-related AJAX
│   ├── xajax-messages.php  Messaging AJAX
│   ├── xajax-analysis.php  Analysis AJAX
│   └── xajax-settings.php  Settings AJAX
│
├── libraries/              Third-party libraries
│   ├── medoo.php           ORM
│   ├── grid/               Custom DataTables grid
│   └── framework/          Bootstrap + jQuery + 57 plugins
│
├── layout/                 Static assets, compiled CSS
├── resources/              xajax, phpmailer, mPDF
└── temp/, temp_t/          File cache directories
```

## Autoloading

Defined in `index.php`:
```php
// namespace\ClassName → autoload/namespace/class.ClassName.php
// ClassName           → autoload/class.ClassName.php
spl_autoload_register('__autoload_my_classes');
```

## Request Flow

```
HTTP request
  → .htaccess: rewrites /m/a/params → ?module=m&action=a&params
  → index.php: load config, init $db (OPD) + $mdb (Medoo), start session, init $cache
  → \controls\Page::checkUrlParams()   (handles ?rw= special actions)
  → \controls\Page::getContent()       (resolves module+action → controller class)
  → \controls\[Module]::method()       (business logic, calls factory)
  → \factory\[Module]::query()         (Medoo DB queries)
  → \view\[Module]::render()           (assigns data to Savant3, returns HTML)
  → \view\Page::show()                 (wraps in role-appropriate layout)
  → HTML → browser
```

## User Roles & Routing

| Role | Source table | Layout |
|------|-------------|--------|
| `admin` | `pro_users` | `templates/page/main-layout.php` |
| `client` | `pro_rr_clients` (type=0) | `templates/client/main-layout.php` |
| `worker` | `pro_rr_clients` (type=2) | `templates/client/main-layout.php` |
| `reseller` | `pro_rr_clients` (type=1) | `templates/reseller/main-layout.php` |

## Template System

Two systems co-exist:

**Savant3** (primary): `$tpl = new \Savant3; $tpl->varName = $val; return $tpl->fetch('ranker/summary');`

**Tpl** (lightweight): `$tpl = new \Tpl; $tpl->render('other/pager');`
- Template search order: `templates_a/` → `templates_b/` → `templates/`

## Database Layer

Two connections initialized in `index.php`:
- `$db` — OPD (legacy PDO debug wrapper), used in older code paths
- `$mdb` — Medoo ORM, used in all newer code

Factory pattern: controllers call `\factory\Ranker::getClient($id)` which does `global $mdb; return $mdb->get(...)`.

## Cron System

`cron.php` → `\Cron::staticMethod()` — jobs defined as static methods in `autoload/class.Cron.php`:
- `fill_missing_positions()` — interpolates missing rank records
- `archive_positions()` / `archive_empty()` — data archiving
- `check_proxy()` — validates proxy pool
- `get_phrases_positions_dfs3()` / `post_phrases_positions_dfs3()` — DataForSEO rank fetching

## AJAX System

`functions/xajax.php` registers handler functions → `ajax.php` processes incoming xajax requests → returns DOM update commands to jQuery on client.

## Caching

`\FileCache` stores serialized data in `temp/` and `temp_t/`. Invalidated via `\S::deleteCache()`.
