# Vvveb CMS — Agent Guide

## Project Structure
- **Root**: `/home/www/vvveb/vvveb/` — PHP 8.5+ CMS
- **Core dirs**: `system/` (framework), `admin/` (backend), `app/` (frontend), `plugins/` (extensions), `public/` (assets + themes), `config/` (settings), `install/` (setup), `storage/` (cache, uploads, `compiled-templates/`)
- **System core**: `system/core/` (frontcontroller, request, response, startup, view), `system/db/` (DB drivers), `system/sqlp/` (SQL parser), `system/vtpl/` (template engine), `system/traits/` (CRUD, listing, field, cart), `system/media/` (image processing), `system/extensions/plugins.php` (plugin lifecycle), `system/queue.php` + `system/queue/providers/` (background job queue — Redis & database backends behind `Vvveb\Queue\Providers\Provider`, see `docs/developer/queue.md`)
- **Themes**: `public/themes/<slug>/` — plain HTML files; dynamic data via `data-v-*` attributes compiled by Vtpl at runtime. Reference theme: `public/themes/landing`. `landing-tailwind` is built from `src/` with Vite + Tailwind (`npm run build` inside the theme folder).
- **Plugin pattern**: `plugins/{slug}/` contains `plugin.php` (main, required), `admin/controller|template|validate/`, `app/controller|template|validate/`, `sql/{mysqli,pgsql,sqlite}/` (query models), `install/sql/{engine}/` (schema run on activation), `component/`, `public/` (copied/symlinked to `public/plugins/<slug>/` on activation)
- **Templates**: `admin/template/*.tpl` and `app/template/*.tpl` (Vtpl syntax); `admin/template/{crud,listing,common}.tpl` are reusable bases. Page-builder HTML sources live in `public/admin/*.html` / `public/themes/<theme>/**`
- **Docs**: `docs/developer/` — developer guides (architecture, caching, components, events, REST/GraphQL APIs, theming, Vtpl reference)

## Core APIs & Conventions

### Events (`Vvveb\System\Event::on`)
- Signature: `Event::on(string $namespace, string $name, string $id, callable $callback, int $priority = 1000)` — **four required args**; 3-arg calls fatal at runtime
- **Listeners must return their parameters as an array tuple** (e.g. `return [$menu];`) or values are silently lost
- Lower priority runs first (ksort ascending); default 1000
- Common hooks: `Vvveb\Controller\Base::init-menu` (admin menu), `Vvveb\System\Routes::init` (routes), `Vvveb\Component\*::results` (filter component data), `Vvveb\System\Core\View::compile:after` (inject tpl commands), `Vvveb\System\Core\FrontController::call`

### Models & SQL
- `model('Plugins\<Name>\<table>')` → class `Vvveb\Sql\Plugins\<Name>\<Table>SQL` generated by SqlP from `plugins/<slug>/sql/<engine>/<table>.sql`
- SQL model files use `CREATE PROCEDURE <name>(IN/OUT params)` blocks (no `CREATE` keyword — pgsql/sqlite compatible) with `@IF isset(:param) && !empty(:param) THEN … END @IF` conditionals, `:param` bindings, `_` alias keeps rows in main result array
- Generated methods per procedure: `get()`, `getAll()`, `add()`, `edit()`, `delete()` depending on IN/OUT params
- Backtick identifiers for mysqli/sqlite, double quotes for pgsql

### Settings & config
- `\Vvveb\getSetting($namespace, $key = null, $default = null, $site_id)` — `$key` null returns all settings for namespace; array returns subset
- `\Vvveb\setSetting($ns, $key, $value)` / `\Vvveb\setMultiSetting($ns, array $settings)`
- `\Vvveb\getConfig($key)` / `\Vvveb\setConfig($key, $value)` — global config (e.g. `plugins.$site_id.$slug.status`)

### Controllers
- Extend `Vvveb\Controller\Base`: `$this->request`, `$this->view`, `$this->response`, `$this->session`, `$this->global`
- JSON responses: `$this->response->setType('json'); $this->response->output([...]);`
- CSRF: `protected function checkCsrf(): bool` on admin Base; forms carry `<input type="hidden" name="csrf" data-v-csrf>`
- Plugin controllers use namespace `Vvveb\Plugins\<Name>\Controller` for BOTH admin and app — the folder (`admin/controller/` vs `app/controller/`) selects context

## Vtpl Engine (`system/vtpl/vtpl.php`)
- Compiles `.tpl` command files against plain-HTML documents; output cached in `storage/compiled-templates/`
- **Core flow**: `loadTemplateFile()` → `processTemplateFile()` = `expandImports()` + placeholder extraction (`processPhpcode/processVariables/processFroms/processStrings`) + `parseSelectorLines()` → document load via `loadHtml()` → `processTemplate()` = `expandCommaSelectors()` + per-selector `query()` → `processElements()`
- **Modifiers**: `outerHTML`, `innerText` (alias `text`), `before`, `after`, `append`, `prepend`, `delete`, `deleteAllButFirst(Child)`, `if_exists`, `hide`, `addClass`, `removeClass`, `addNewAttribute`, `removeAttribute`; unknown modifiers become attribute assignments (`sel|attr = value`)
- **Robustness**: `processElements()` accepts `DOMNodeList|false|null` and no-ops on empty/invalid xpath; undefined constants in `cleanHtml()` emit empty string; syntax check runs before writing compiled file
- **Helpers**: `createXmlFragment()` (null-safe fragment build), `loadDomFromString()`, `saveDocument()`, `createDomDocument()`, `cssToXpath()` (CSS→XPath, 30-rule table), `processAttributeFilters()` (`data-filter-*` chains, `$$N` placeholders), `processAttributeConstants()` (`@@__attr__@@` placeholders, macros `@@macro Name(args)@@`, json-path lookups)
- **Multi-language pass**: `setMultiLanguageText()` wraps text nodes with the translation function; per-attribute handling extracted to `processNodeAttributes()`
- Theme-side dynamic content uses `data-v-component-*` / item attributes — see Skills → theme-building

## Important Details
- Namespaces: `Vvveb\Controller\*`, `Vvveb\System\*`, `Vvveb\Plugins\*`; global helpers in the `Vvveb` namespace (`\Vvveb\model`, `\Vvveb\__`, `\Vvveb\getSetting` …) organized as thematic modules under `system/functions/` (url, config, settings, meta, text, security, arrays, translation, html, fs, http, xml, ui, themes, site, debug, loader) — `system/functions.php` is only the load manifest; add new helpers to the matching module
- DB drivers extend abstract `Vvveb\System\Db\DBDriver` with `$quote` property, `escape()`, `escapeLiteral()` — no `escapeIdentifier()` method
- JS: VvvebJS page builder in `public/js/vvvebjs/builder.js` — component registry via `Vvveb.Components.add()/extend()`, chrome-element cache `Builder._$()`, rAF-throttled highlight, precompiled class regexes
- PHP 8.5.8 at `/usr/bin/php` — use for `php -l` and for parsing SQL models via `Vvveb\System\Sqlp\Sqlp` (needs `DB_PREFIX`/`DB_ENGINE` constants plus `Db`/`dotToArrayKey` stubs; see harness examples below)
- Model tests (`tests/model`) select their backend via `tests/support/TestDb.php`: MySQL when reachable, otherwise a throwaway SQLite database built from `install/sql/sqlite/schema` + `install/sql/insert` (requires the `sqlite3` PHP extension). An explicitly targeted EMPTY MySQL database is auto-provisioned the same way; existing databases are never touched. See `docs/developer/testing.md`
- CI (`.github/workflows/ci.yml`): lint job (`php -l` all tracked files), test matrix (PHP 8.3/8.5 × MySQL/SQLite) and a non-blocking phpstan job. No DB server available — no phpstan/php-cs-fixer or live runtime tests
- Node ≥ 20 available (`node --check` for JS); npm registry reachable

## Testing & Verification Workflow
1. `php -l` every touched PHP file; `node --check` for JS
2. SQL models: parse each engine's files through a stubbed Sqlp harness (see `/tmp/opencode/t_{plugin}_{engine}.php` pattern — defines constants, evals a `Db` stub with `$quote` set per engine, globs `sql/<engine>/*.sql`, generates models, lints output)
3. Logic tests: stub `Vvveb\` functions in a namespace block, require the plugin's `system/*.php`, exercise public methods with fake models/transports (examples: `/tmp/opencode/test_*_logic.php`)
4. Vtpl changes: compile-and-render harness at `/tmp/opencode/vtpltest/run.php` (loads tpl commands against an HTML doc, compiles, renders in object scope, asserts output)
5. No formal test suite exists — when fixing bugs, add a focused harness first, then fix until green

## Skills
- **Theme building**: `skills/theme-building/SKILL.md` — read before creating or editing themes in `public/themes/` (page structure, `data-v-*` attributes, save-global shared parts, cart/checkout/product JS contracts, child themes, page-builder integration, and the landing-tailwind Vite/Tailwind build). Reference themes: `public/themes/landing` (Bootstrap 5) and `public/themes/landing-tailwind` (Tailwind, built from `src/**`).
- **Plugin building**: `skills/plugin-building/SKILL.md` — read before creating or editing plugins in `plugins/` (plugin.php header, folder structure, controllers, events/hooks, menu, routes, components, settings, validation, SQL models, lifecycle). Reference plugin: `plugins/insert-scripts` (minimal), `plugins/contact-form` (component + tables).
- **SqlP query models**: `skills/sqlp/SKILL.md` — read before creating or editing `.sql` model files (`admin/sql/`, `app/sql/`, `plugins/*/sql/`): procedure syntax, IN/OUT params, macros (@IF/@FILTER/@LIST/@KEYS/@EACH/@SQL_COUNT/@SQL_LIMIT), result shaping, @result references, multi-engine sync and offline compile/lint harness. Reference model: `admin/sql/mysqli/product.sql`.
- **Vtpl templating**: `skills/vtpl-building/SKILL.md` — read before writing or editing `.tpl` template files (`admin/template/`, `app/template/`, plugin templates, theme `template/` overrides): selector commands and modifiers, placeholders, filters, macros, imports/from(), conditionals, compile flow and the offline compile harness. Reference tpls: `admin/template/crud.tpl`, `app/template/common.tpl`.
- **Tools backup**: `skills/tools-backup/SKILL.md` — read before creating or editing admin backup tools (`admin/controller/tools/*-backup.php`, `admin/template/tools/*-backup.tpl`, `public/admin/default/src/tools/*-backup.html`, `public/js/admin/controller/*-backup.js`): AJAX stepped save/nextBackup/nextRestore with 8s chunking, per-file vs folder actions, progress-bar JS, menu registration and `storage/backup/` layout. Reference controllers: `tools/backup.php` (database), `tools/plugins-backup.php`, `tools/themes-backup.php`, `tools/media-backup.php`.
- **Admin controllers**: `skills/admin-controllers/SKILL.md` — read before creating or editing admin controllers (`admin/controller/<group>/<name>.php`): Crud/Listing bases and traits, request/view/response/session services, validation rule files, CSRF and permissions, admin menu registration, admin Vtpl templates and admin HTML sources with gulp. Reference: `admin/controller/base.php`, `crud.php`, `listing.php`, `docs/developer/controller-guide.md`.
- **Headless API**: `skills/headless-api/SKILL.md` — read before exposing or debugging REST (`/rest/`) or GraphQL (`/graphql`) access: enabling, auth, `config/rest-routes.php` / `config/graphql-routes.php` tables, placeholder styles and schemas. Reference docs: `docs/developer/rest-api.md`, `docs/developer/graphql-api.md`.
- **Agent ops**: `skills/agent-ops/SKILL.md` — read before any multi-step task for precise tool use (read offset/limit, glob/grep scoping, bounded bash with timeout/cwd, exact unique edits, remote cwd/memory discipline) and the verify loop. Reference: tool schemas in `mcp/tools.php`, `docs/developer/testing.md`.
- **Page builder (AI tool use)**: `skills/page-builder/SKILL.md` — read before editing live pages through the AI `page`/`builder` eval tools (tool semantics, querying, edit patterns, page CSS in `style#vvvebjs-styles`, `inspect()` discovery, pitfalls). Reference code: `public/js/vvvebjs/builder.js` (`exec`, `eval_page`, `inspect`).
