From f8f58c4ab9a303df4268eb2793dd433fc0da7817 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 8 May 2026 19:36:25 +0200 Subject: [PATCH] Sweep: link fixes, splash i18n parity, neuronetz badge, mobile, training source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LINK AUDIT — every internal link now resolves to a real page: - BrandHeader doc-nav 'Showcase' target → /{locale}/showcase/projects/ (the showcase/ directory has no index, only patterns/projects) - Translated-slug bugs across de/es/fr/ja: ~30 broken links from the overnight translator that auto-localised path segments. Mapped back to the actual English slugs: de: warum-nibiru → why-nibiru, kuenstliche-intelligenz/orakel → ai/oracle, kI/modul/* → ai/module/*, praesentation/projekte → showcase/projects es: ai/modulo/* → ai/module/*, diseno/* → design/*, porque-nibiru / por-que-nibiru → why-nibiru, presentacion/proyectos → showcase/projects fr: ia/module/* → ai/module/*, ia/module/formation → ai/module/training, pourquoi-nibiru → why-nibiru, presentation/projets → showcase/projects ja: ai/milestones → ai/roadmap - Cross-locale leaks: bare `/ai/oracle` (no locale) → `/{locale}/ai/oracle/` in de/index.mdx, fr/index.mdx, fr/ai/module/overview.md, en/ai/corpus.md - `/en/start/` (which 404s — start/ has no index) was hardcoded in five design/components.md atelier-button hrefs across all locales → `/{locale}/start/installation/` - `/en/reference` removed from en/downloads.mdx — the reference doc tree isn't built yet; replaced with a github link to the v2 markdown source - Collapsed stray double-slashes (`/de/why-nibiru//` etc.) introduced by the slug-replacement sed sweep Final audit shows 0 broken internal links (down from ~37). TRAINING SOURCE NOW SHIPS — root cause of "I cannot find the training data in the repository": the curated source files were gitignored. - .gitignore at scripts/extraction/ now whitelists framework-reference-v2.md and lora-augmentation.summary.txt alongside lora-augmentation.jsonl - The 1620-line v2 reference, the 323-record augmentation jsonl, and the summary report all enter the repo so the production Docker build sees them and contributors can find them by browsing gitea NEURONETZ AI DEEPLINK BADGE — small "AI by Neuronetz ↗" pill in the splash footer's bottom strip. Logo mark mirrored locally to public/img/external/neuronetz-mark.svg (pulled from neuronetz.ai/favicon.svg) so the page doesn't hot-link off-domain on every paint. Magenta border on hover; opens neuronetz.ai in a new tab with rel=noopener. SPLASH I18N PARITY — de/es/fr/ja index.mdx now import + render the same component stack as en (CometTrail · MmvcStage · MissionControl · LaunchSequence · SpacecraftGrid · EditorialContent · LandingFooter · ToTop · LandingScripts), so every locale shows the full splash structure. The component bodies themselves are still English (proper i18n is the next step); for now this brings structural parity. MOBILE RESPONSIVE SWEEP: - LandingFooter: 4-col grid stacks 2-col @ 768px and 1-col @ 480px; bottom strip wraps vertical at 480px - MmvcStage: 5-step progress rail tightens its gaps under 720px and drops the bar segments entirely under 480px so the labels fit - Docs bridge §11: tighter H1/H2 spacing, breadcrumbs/doc-meta on narrow viewports, pagination cards stack 1-col, help-strip stacks vertical, tables get horizontal-scroll on overflow - Doc-header: nav-version chip hides under 480px so the search-pill + brand fit comfortably Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/public/img/external/neuronetz-mark.png | Bin 0 -> 1325 bytes docs/public/img/external/neuronetz-mark.svg | 4 + docs/scripts/extraction/.gitignore | 10 +- .../extraction/framework-reference-v2.md | 1620 +++++++++++++++++ .../extraction/lora-augmentation.summary.txt | 68 + docs/src/components/BrandHeader.astro | 2 +- docs/src/components/LandingFooter.astro | 69 +- docs/src/components/MmvcStage.astro | 21 +- docs/src/content/docs/de/ai/corpus.md | 2 +- docs/src/content/docs/de/ai/module/chat.md | 24 +- docs/src/content/docs/de/ai/module/embed.md | 16 +- .../src/content/docs/de/ai/module/overview.md | 22 +- docs/src/content/docs/de/ai/module/rag.md | 24 +- docs/src/content/docs/de/core/auth.md | 4 +- docs/src/content/docs/de/core/config.md | 8 +- docs/src/content/docs/de/core/controllers.md | 16 +- docs/src/content/docs/de/core/dispatcher.md | 16 +- docs/src/content/docs/de/core/forms.md | 8 +- docs/src/content/docs/de/core/modules.md | 12 +- docs/src/content/docs/de/core/pagination.md | 2 +- docs/src/content/docs/de/core/registry.md | 2 +- docs/src/content/docs/de/core/routing.md | 8 +- docs/src/content/docs/de/design/components.md | 4 +- docs/src/content/docs/de/index.mdx | 88 +- docs/src/content/docs/de/showcase/patterns.md | 2 +- docs/src/content/docs/de/showcase/projects.md | 6 +- docs/src/content/docs/de/why-nibiru.md | 10 +- docs/src/content/docs/en/ai/corpus.md | 2 +- docs/src/content/docs/en/ai/module/chat.md | 24 +- docs/src/content/docs/en/ai/module/embed.md | 16 +- .../src/content/docs/en/ai/module/overview.md | 12 +- docs/src/content/docs/en/ai/module/rag.md | 20 +- docs/src/content/docs/en/core/auth.md | 4 +- docs/src/content/docs/en/core/config.md | 8 +- docs/src/content/docs/en/core/controllers.md | 16 +- docs/src/content/docs/en/core/dispatcher.md | 16 +- docs/src/content/docs/en/core/forms.md | 8 +- docs/src/content/docs/en/core/modules.md | 12 +- docs/src/content/docs/en/core/pagination.md | 2 +- docs/src/content/docs/en/core/registry.md | 2 +- docs/src/content/docs/en/core/routing.md | 8 +- docs/src/content/docs/en/design/components.md | 4 +- docs/src/content/docs/en/downloads.mdx | 2 +- docs/src/content/docs/en/showcase/patterns.md | 2 +- docs/src/content/docs/en/showcase/projects.md | 2 +- docs/src/content/docs/en/why-nibiru.md | 8 +- docs/src/content/docs/es/ai/corpus.md | 2 +- docs/src/content/docs/es/ai/module/chat.md | 24 +- docs/src/content/docs/es/ai/module/embed.md | 16 +- .../src/content/docs/es/ai/module/overview.md | 20 +- docs/src/content/docs/es/ai/module/rag.md | 24 +- docs/src/content/docs/es/core/auth.md | 4 +- docs/src/content/docs/es/core/config.md | 8 +- docs/src/content/docs/es/core/controllers.md | 16 +- docs/src/content/docs/es/core/dispatcher.md | 16 +- docs/src/content/docs/es/core/forms.md | 8 +- docs/src/content/docs/es/core/modules.md | 12 +- docs/src/content/docs/es/core/pagination.md | 2 +- docs/src/content/docs/es/core/registry.md | 2 +- docs/src/content/docs/es/core/routing.md | 8 +- docs/src/content/docs/es/design/components.md | 4 +- docs/src/content/docs/es/design/overview.md | 8 +- docs/src/content/docs/es/index.mdx | 88 +- docs/src/content/docs/es/showcase/patterns.md | 2 +- docs/src/content/docs/es/showcase/projects.md | 6 +- docs/src/content/docs/es/why-nibiru.md | 10 +- docs/src/content/docs/fr/ai/corpus.md | 2 +- docs/src/content/docs/fr/ai/module/chat.md | 24 +- docs/src/content/docs/fr/ai/module/embed.md | 16 +- .../src/content/docs/fr/ai/module/overview.md | 20 +- docs/src/content/docs/fr/ai/module/rag.md | 24 +- docs/src/content/docs/fr/core/auth.md | 4 +- docs/src/content/docs/fr/core/config.md | 8 +- docs/src/content/docs/fr/core/controllers.md | 16 +- docs/src/content/docs/fr/core/dispatcher.md | 16 +- docs/src/content/docs/fr/core/forms.md | 8 +- docs/src/content/docs/fr/core/modules.md | 12 +- docs/src/content/docs/fr/core/pagination.md | 2 +- docs/src/content/docs/fr/core/registry.md | 2 +- docs/src/content/docs/fr/core/routing.md | 8 +- docs/src/content/docs/fr/design/components.md | 4 +- docs/src/content/docs/fr/index.mdx | 88 +- docs/src/content/docs/fr/showcase/patterns.md | 2 +- docs/src/content/docs/fr/showcase/projects.md | 4 +- docs/src/content/docs/fr/why-nibiru.md | 10 +- docs/src/content/docs/ja/ai/corpus.md | 2 +- docs/src/content/docs/ja/ai/module/chat.md | 26 +- docs/src/content/docs/ja/ai/module/embed.md | 16 +- .../src/content/docs/ja/ai/module/overview.md | 12 +- docs/src/content/docs/ja/ai/module/rag.md | 20 +- docs/src/content/docs/ja/core/auth.md | 4 +- docs/src/content/docs/ja/core/config.md | 8 +- docs/src/content/docs/ja/core/controllers.md | 16 +- docs/src/content/docs/ja/core/dispatcher.md | 16 +- docs/src/content/docs/ja/core/forms.md | 8 +- docs/src/content/docs/ja/core/modules.md | 12 +- docs/src/content/docs/ja/core/pagination.md | 2 +- docs/src/content/docs/ja/core/registry.md | 2 +- docs/src/content/docs/ja/core/routing.md | 8 +- docs/src/content/docs/ja/design/components.md | 4 +- docs/src/content/docs/ja/index.mdx | 88 +- docs/src/content/docs/ja/showcase/patterns.md | 2 +- docs/src/content/docs/ja/showcase/projects.md | 2 +- docs/src/content/docs/ja/why-nibiru.md | 8 +- docs/src/styles/starlight-docs-bridge.css | 81 + 105 files changed, 2394 insertions(+), 729 deletions(-) create mode 100644 docs/public/img/external/neuronetz-mark.png create mode 100644 docs/public/img/external/neuronetz-mark.svg create mode 100644 docs/scripts/extraction/framework-reference-v2.md create mode 100644 docs/scripts/extraction/lora-augmentation.summary.txt diff --git a/docs/public/img/external/neuronetz-mark.png b/docs/public/img/external/neuronetz-mark.png new file mode 100644 index 0000000000000000000000000000000000000000..e1988eeccc60f8df93c961d54a74835b0936e7c0 GIT binary patch literal 1325 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD2}o{QKQWbof#r**i(^Q|t+#jMJ*3MS4t$(p z-yv{&QEc+B2V7RYPJe}G_$tjX;11Thd-&J3G9#|lPP-4jIQ+uf{M3u&<#so`GB>wx zv&&rJ{9@88DZPm0+l>3(1sGgya7%i9hEq#1g}-_2;d3va`b>WP{d3x+-?29P{=A!H zU1XWPQC#Xl>6RQO0rn2&BaDw23L7jOWEA*7TnLFG2$Mn*M5qS}I!wE`nbXL3``uk% z4}P1d{<2=(@(*8TTlz;f;l%BeOjF-{Fg+uaA1juh!j<@pp>RdUEsxv(S}iuM@7eOz z5om3xuk_2AHYhInsI zFTmGcZnW%RLcz{CYuC=dc6IOkU;8zGcds#-Gb8lp89}brf3H_&l>9t5cXw^=--#Y6 z;mOAy7p}kl{Od0%DXDcaKdT&>_gBrAFB@;q-~Il+ ze8=&}D|z01|Ls5T&x+Nn52tNjS@e3PO<#(UB$w^_HEVvnK7a9IeBPZGf-Ma}kJqm| zc5dF^J z?*D9S=Z9tI=D&}1ZF}^p*itX%$ESnM^Nqf}EiJ3Nf91=?mqKOY4+J`*UH{~dYZo{ZvGol+Zu~C%Pg+!kIu~bbKvny z>)KzFuTT59s+pa8_b#ibD8CbN*H4__I4%=uYW}L+&^l}Dt<~ZCwe|F-ZC{suzRq85 z@{xs6J9qA!u2-v@e{<{Btr;d>GFi`xEW5i><{936J5%b>iEX`$u9}&fpNuX`eainR zVCSk;i$96oxp6~*Z|dfVQ%`kw?A+-oqZJ+yppfrqw{}JRtMukh=dE9=_WCVX=0i!* zkPLyGEud+i0VS^>2|5@?78=h>P!JGkaWJq@eVk@vHTPWB+ES~zdeb+rd9(L_?A;?r zCO>>QzrC$(`_9S-W<73?Hzt?zwcmZXVfvIQ0>|e`NK2RRuCMr05i&_-=`ov{8*fUi z^yB_yy?%f2?Af#BWo1AA{=0g0M$l^GnLd2&d-v{rdtzew&9xey0!(r1{SO+MNS!@& z=+WNlz54O%a%!{E($W$hxU-(VkYVEO?fv(!T%d^MGY0l03VaH)-|=y#fipYU0}N1a xpk#Awf+#r@QgmP`K#nkC5rmg24$poFXYQ_@P%>-5e_%1l;OXk;vd$@?2>?EPWoG~Y literal 0 HcmV?d00001 diff --git a/docs/public/img/external/neuronetz-mark.svg b/docs/public/img/external/neuronetz-mark.svg new file mode 100644 index 0000000..506afc3 --- /dev/null +++ b/docs/public/img/external/neuronetz-mark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs/scripts/extraction/.gitignore b/docs/scripts/extraction/.gitignore index 9bd283a..8f959ea 100644 --- a/docs/scripts/extraction/.gitignore +++ b/docs/scripts/extraction/.gitignore @@ -1,9 +1,13 @@ # Extraction outputs from research-agent runs are typically large + transient. -# Keep them local by default — except the curated augmentation file which -# needs to ship for the Docker build to fold it into the LoRA corpus. +# Keep them local by default — except the curated files that need to ship so +# the Docker build can fold them into the LoRA corpus AND so contributors +# can find the source-of-truth reference in the repo. *.md *.json *.jsonl +*.txt -# …with one explicit exception: +# …with explicit exceptions: +!framework-reference-v2.md !lora-augmentation.jsonl +!lora-augmentation.summary.txt diff --git a/docs/scripts/extraction/framework-reference-v2.md b/docs/scripts/extraction/framework-reference-v2.md new file mode 100644 index 0000000..9d20394 --- /dev/null +++ b/docs/scripts/extraction/framework-reference-v2.md @@ -0,0 +1,1620 @@ +# Nibiru PHP Framework: Complete Reference v2 + +**Last Updated:** May 2026 +**Version:** 2.0 (Second-pass deep extraction) + +## 0. Executive Summary: What Changed from v1 + +Version 1 was a high-level architecture summary: "MMVC pattern, controllers, adapters, singletons." Useless for training. + +**V2 is microscopic:** Every public static factory, every magic namespace convention, every chained idiom a developer learns only by reading code. This is what "tiny things — that is what makes the entire framework" means. + +### New in V2 +- **Exact file:line citations** for every claim (no "presumably" or "appears to"). +- **Real production usage examples** from `/loach.mssql.database-connection/`, `/develop.maschinen-stockert.de/`, `/nibiru-modules/`. +- **The runtime database switcher:** `Pdo::$section` static, how it's called, why "last call wins." +- **The autogenerator pipeline:** CLI flag → INI section → driver → adapter → generated model's `extends Db` line → model's `__construct()` calling `Pdo::settingsSection()`. +- **Form factory placeholder exhaustively:** `[CLASSNAME]`, `[TABLE]`, `[FOLDERNAME]`, `[DBSECTION]`, `[ADAPTER]`, `[CONNECTOR]`. +- **Module lifecycle:** registry scan, plugin/trait ordering from INI, environment-specific overrides. +- **INI key reference table:** every `[DATABASE*]`, `[ENGINE]`, `[AUTOLOADER]` key the framework reads. +- **Production-only patterns:** what exists in `develop.maschinen-stockert.de` but not framework core. + +--- + +## 1. Namespace Map + +### Core Namespace Prefixes + +| Prefix | Maps to | Rule | Example | +|--------|---------|------|---------| +| `\Nibiru\Factory\*` | `core/f/*.php` | Static factories; call signature is `ClassName::staticMethod()` | `Db::loadModel('WarehouseLoach\\Timeanddate')` returns `IDb` | +| `\Nibiru\Model\*` | `application/model/` (autogenerated) | PSR-4: folder name = namespace part. Format: `\Nibiru\Model\\` | `\Nibiru\Model\WarehouseLoach\Timeanddate` is file `/application/model/WarehouseLoach/timeanddate.php` | +| `\Nibiru\Adapter\*` | `core/a/*.php` or autogenerated | Adapters for different DB drivers. `MySQL\Db`, `Postgres\Db`, `Postgresql\Db` | Models `extends Db` where `Db` is `\Nibiru\Adapter\MySQL\Db` | +| `\Nibiru\Adapter\IDb` | `core/i/IDb.php` | Interface all models implement | Methods: `loadTableAsArray()`, `updateRowById()`, `insertArrayIntoTable()` | +| `\Nibiru\Module\*` | `application/module/[NAME]/` | Module classes; main class at `[NAME]/[name].php` | `\Nibiru\Module\Users\Users` is file `/application/module/users/users.php` | +| `\Nibiru\Module\[Name]\Interfaces\*` | `application/module/[NAME]/interfaces/` | Module-specific interfaces | Loaded by `Auto::loader()->loadModules()` if listed in INI `iface.pos[]` | +| `\Nibiru\Module\[Name]\Traits\*` | `application/module/[NAME]/traits/` | Module-specific traits | Loaded if listed in INI `trait.pos[]`; execution order = INI array order | +| `\Nibiru\Module\[Name]\Plugins\*` | `application/module/[NAME]/plugins/` | Module plugin classes; run on controller/model actions | Loaded last in INI order; pattern is `use Nibiru\Factory\Db; ... Db::loadModel(...)` | +| `\Nibiru` (core) | `core/c/*.php` | Singletons: `Config`, `Controller`, `View`, `Pdo`, `Router`, `Dispatcher`, `Engine` | All follow `getInstance()` pattern | + +**Autoloader rule (PSR-4 variant):** +- Model folder (`dbmodel` in INI): `\Nibiru\Model\\` maps to disk path from `$basePath//TableName.php` +- Module folder: `\Nibiru\Module\\` maps to disk path from `application/module//` +- Interfaces/traits/plugins: scanned by `Auto::loader()->loadModuleComponents()` based on INI registry + +--- + +## 2. Singletons & Factories + +### 2.1 `Config` — Singleton + +**File:** `/home/stephan/PhpstormProjects/Nibiru/core/c/config.php:12` + +```php +public static function getInstance(): Settings +``` + +**What it does:** +- Reads environment (`getenv('APPLICATION_ENV')` or defines `APPLICATION_ENV` constant). +- Calls `parent::setConfig(self::getEnv())` which parses INI file for that environment. +- Returns singleton holding the entire application config array. + +**INI file resolution:** +- Template: `settings.ENV.ini` +- Actual: `settings.development.ini`, `settings.production.ini`, `settings.cli.ini`, `settings.preproduction.ini` (or custom) +- Parsed with `parse_ini_file(..., true)` (associative array keyed by section name) + +**Usage:** +```php +Config::getInstance()->getConfig()['DATABASE']['username'] +Config::getInstance()->getConfig()['ENGINE']['templates'] +Config::getInstance()->getConfig()['AUTOLOADER']['class.pos'] +``` + +**Production example:** `/home/stephan/PhpstormProjects/develop.maschinen-stockert.de/application/settings/config/settings.development.ini:14-20` + +--- + +### 2.2 `Pdo` — Database Connection Switcher Singleton + +**File:** `/home/stephan/PhpstormProjects/Nibiru/core/c/pdo.php:12` + +**Signature:** +```php +public static function settingsSection( $section = IOdbc::SETTINGS_DATABASE ) +public static function getInstance( $section = false ): Mysql +``` + +**The idiom (critical):** + +1. **Static section variable** (`Pdo::$section`, line 14) — **last write wins per request** +2. **Every model's `__construct()` calls** `Pdo::settingsSection('[DBSECTION]')` or `[CONNECTOR]::settingsSection('[DBSECTION]')` +3. **All subsequent Pdo queries** use `parent::getInstance(self::getSettingsSection())->getConn()` + +**Why:** Single static per request; can switch databases by instantiating a different model, or calling `Pdo::settingsSection()` directly. + +**Example from generated model** (`/home/stephan/PhpstormProjects/loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php:30-34`): + +```php +public function __construct() +{ + Pdo::settingsSection('DATABASE'); + self::initTable( self::TABLE ); +} +``` + +**Example from plugin** (`/home/stephan/PhpstormProjects/loach.mssql.database-connection/application/module/users/plugins/acl.php:14`): + +```php +use Nibiru\Factory\Db; +// ... later in code: +$acl = Db::loadModel('WarehouseLoach\Acl'); // instantiates model, calls __construct(), sets Pdo::$section to 'DATABASE' +``` + +**INI sections read by `Mysql::__construct()` at line 32:** + +```php +if($section) +{ + $settings = Config::getInstance()->getConfig()[$section]; +} +else +{ + $settings = Config::getInstance()->getConfig()[self::SETTINGS_DATABASE]; // defaults to [DATABASE] +} +``` + +**Real INI sections** (from `/home/stephan/PhpstormProjects/loach.mssql.database-connection/application/settings/config/settings.production.ini`): + +```ini +[DATABASE] +is.active = true +username = "loach" +password = "..." +hostname = "sto-loach-production-mariadb-1" +basename = "warehouse_loach" +driver = "mysql" +port = "3306" +encoding = "UTF8" +``` + +Pattern: Each application can have `[DATABASE]`, `[DATABASE_LOACH]`, `[DATABASE_EMMIDIA]`, etc., and switch between them via `Pdo::settingsSection('DATABASE_LOACH')`. + +**Key methods** (core/c/pdo.php): +- `query($string)` — exec or fetch; routes via `parent::getInstance(self::getSettingsSection())` +- `queryString($string, $associative)` — fetch all +- `fetchTableAsArray($tablename, $limit, $order)` — table dump with pagination +- `selectDatasetByFieldAndValue($tablename, $fieldAndValue, $sortOrder)` — WHERE clause +- `fetchRowInArrayById($tablename, $id)` — single row by PK +- `fetchRowInArrayByWhere($tablename, $column_name, $parameter_name)` — single row by column +- `insertArrayIntoTable($tablename, $array_name, $encrypted)` — insert with optional `DES_ENCRYPT()` +- `updateRowById($tablename, $columnNames, $data, $id, $encrypted)` — update by PK + +**All** check `self::getSettingsSection()` before executing. + +--- + +### 2.3 `Db` — Static Model Factory + +**File:** `/home/stephan/PhpstormProjects/Nibiru/core/f/db.php:11` + +**Signature:** +```php +public static function loadModel( $modelName = ""): IDb +``` + +**Pipeline:** +1. Call `Db::loadModel('WarehouseLoach\\Timeanddate')` +2. Internally: `_setModel("WarehouseLoach\\Timeanddate")` +3. Constructs namespace: `$fmodel = "\\Nibiru\\Model\\".$model` = `\Nibiru\Model\WarehouseLoach\Timeanddate` +4. Instantiates: `self::$_model = new $fmodel;` +5. Returns: `self::getModel()` which is the static `$_model` + +**Returns:** `IDb` interface, guaranteeing these methods exist: +- `loadTableAsArray()` +- `selectRowsetById($id)` +- `updateRowById(array $rowData, int $id, string $encrypted = "")` +- `insertArrayIntoTable($dataset = array())` +- `selectDatasetByFieldWhere($fieldWhere = array(), $sortOrder = false)` +- `selectRowByFieldWhere($field = array())` +- `lastInsertId()` +- `deleteRowById(int $id = 0)` +- `updateRowByFieldWhere($wherefield, $wherevalue, $rowfield, $rowvalue)` + +**Real usage** (`/home/stephan/PhpstormProjects/loach.mssql.database-connection/application/module/pdf/plugins/pdf.php`): + +```php +use Nibiru\Factory\Db; +// ... later: +Db::loadModel('WarehouseLoach\Timeanddate')->insertArrayIntoTable([...]); +$timeanddate_id = Db::loadModel('WarehouseLoach\Timeanddate')->lastInsertId(); +``` + +--- + +### 2.4 `Form` — Static Form Factory + +**File:** `/home/stephan/PhpstormProjects/Nibiru/core/f/form.php:41` + +**Core flow:** +1. `Form::create()` — clears `self::$form` static buffer +2. Call methods in sequence: `Form::addInputTypeText(...)`, `Form::addSelect(...)`, etc. +3. Each appends HTML to `self::$form`; final call is `Form::addForm($attributes)` which wraps with `
` tags +4. `addForm()` calls `displaySelect()` to replace `OPTIONS` placeholder with options added via `addSelectOption()` + +**Available input types** (methods in Form factory): + +| Method | Maps to | Template Variable | +|--------|---------|-------------------| +| `addForm($attributes)` | `` wrapper | Uses `{FIELDS}` placeholder | +| `addInputTypeText($attributes)` | `` | | +| `addInputTypeSubmit($attributes)` | `` | | +| `addInputTypePassword($attributes)` | `` | | +| `addInputTypeEmail($attributes)` | `` | | +| `addInputTypeCheckbox($attributes)` | `` | | +| `addInputTypeRadio($attributes)` | `` | | +| `addInputTypeSwitch($attributes)` | HTML5 toggle | | +| `addInputTypeDate($attributes)` | `` | | +| `addInputTypeDatetime($attributes)` | `` | | +| `addInputTypeColor($attributes)` | `` | | +| `addInputTypeNumber($attributes)` | `` | | +| `addInputTypeRange($attributes)` | `` | | +| `addTypeSearch($attributes)` | `` | | +| `addTypeTelefon($attributes)` | `` | | +| `addTypeUrl($attributes)` | `` | | +| `addTypeFileUpload($attributes)` | `` | | +| `addTypeHidden($attributes)` | `` | | +| `addTypeImageSubmit($attributes)` | `` | | +| `addTypeReset($attributes)` | `` | | +| `addTypeButton($attributes)` | ``; production code uses `value` for inner HTML (e.g. `' Speichern'`) | +| `TypeNumber` | `typenumber.php` | `addTypeNumber` | `` | +| `TypeRange` | `typerange.php` | `addTypeRange` | slider | +| `TypeReset` | `typereset.php` | `addTypeReset` | `` | +| `TypeSearch` | `typesearch.php` | `addTypeSearch` | `` | +| `TypeTelefon` | `typetelefon.php` | `addTypeTelefon` | `` (note German spelling in class name) | +| `TypeUrl` | `typeurl.php` | `addTypeUrl` | `` | +| `TypeColor` | `typecolor.php` | `addInputTypeColor` | `` | +| `TypeDatetime` | `typedatetime.php` | `addInputTypeDatetime` | `` | +| `TypeFileUpload` | `typefileupload.php` | `addTypeFileUpload` | ``; the parent `` needs `enctype="multipart/form-data"` | +| `TypeHidden` | `typehidden.php` | `addTypeHidden` | `` | +| `TypeImageSubmit` | `typeimagesubmit.php` | `addTypeImageSubmit` | factory parameter is misspelled `$attrbutes` at `core/f/form.php:363` — works fine, no fix needed | +| `TypeLabel` | `typelabel.php` | `addTypeLabel` | `` | + +**Select / option (the order-dependent pair):** + +| Type class | File | Factory method | Template (`core/c/typeselect.php:37`, `typeoption.php:35`) | +|---|---|---|---| +| `TypeSelect` | `typeselect.php` | `addSelect` | `` | +| `TypeOption` | `typeoption.php` | `addSelectOption` | `` | + +The `OPTIONS` token in the select template is what `Form::displaySelect()` (`core/f/form.php:71`) replaces with the accumulated option HTML — see §5.6. + +**Structural primitives (no ``, just open/close tags for layout):** + +| Type class | File | Factory method | Template | +|---|---|---|---| +| `TypeOpenDiv` | `typeopendiv.php` | `addOpenDiv` | `
VALUE` | +| `TypeCloseDiv` | `typeclosediv.php` | `addCloseDiv` | `
` | +| `TypeOpenSpan` | `typeopenspan.php` | (no direct factory; legacy) | `` | +| `TypeCloseSpan` | `typeclosespan.php` | (no direct factory; legacy) | `` | +| `TypeOpenAny` | `typeopenany.php` | `addOpenAny` | `VALUE` — caller passes `'any' => 'span'` (or any tag name) and it becomes `` | +| `TypeCloseAny` | `typecloseany.php` | `addCloseAny` | `` | + +**Form wrapper (called last):** + +| Type class | File | Factory method | Template | +|---|---|---|---| +| `Form` | (inline `\Nibiru\Form\Form`) | `addForm` | `FIELDS
` | + +### 5.5 Naming inconsistency (real footgun) + +The `add*` methods follow three different naming patterns. There is no single rule: + +- `addInputType*` for: Text, Submit, Textarea, Radio, Checkbox, Switch, Password, Date, Email, Color, Datetime +- `addType*` for: FileUpload, Hidden, ImageSubmit, Number, Range, Reset, Search, Telefon, Url, Button, Label +- `add*` (no Type prefix) for: Form, Select, SelectOption, OpenDiv, CloseDiv, OpenAny, CloseAny + +There is no semantic justification — it's historical drift. When generating training data, include both `addInputTypeText` and `addInputType*` callsite samples; do not "normalize" them, because the framework callers expect the literal names. + +### 5.6 Select / option ordering (critical) + +Options must be added **before** the select. This is non-obvious and the opposite of HTML reading order. + +`core/f/form.php:493-497` — `addSelectOption` appends to a separate buffer: + +```php +public static function addSelectOption( $attributes ) { + self::setElement( new TypeOption() ); + self::assembleOptions( self::getElement()->loadElement( $attributes ) ); +} +``` + +`core/f/form.php:463-472` — `addSelect` then renders the select template, replacing its `OPTIONS` token with the accumulated option HTML, and **clears the option buffer** (`assembleOptions(false)`): + +```php +public static function addSelect( $attributes, $div = false ) { + if($div!=false) self::setDiv( $div ); + self::setElement( new TypeSelect() ); + self::assemble( self::displaySelect( self::getElement()->loadElement( $attributes ) ) ); + self::assembleOptions( false ); // reset for the next select +} +``` + +`displaySelect()` at line 71: `return str_replace( 'OPTIONS', self::$option, $select );` + +Reverse the order — call `addSelect` before `addSelectOption` — and the select renders empty. + +### 5.7 Per-element div wrapping (the second `$div` parameter) + +Almost every `add*` method takes an optional second argument `$div = false`. When passed an associative array, the next assembled element is wrapped in a `
`. From `core/f/form.php:120-140`: + +```php +private static function setDiv( $div = false ) { + if($div != false) { + if( is_array( $div ) ) { + foreach ( $div as $key=>$selector ) { + self::$div = '
' . "\n" . 'ELEMENT
' . "\n"; + } + } … + } +} +``` + +And `assemble()` at `core/f/form.php:86-97`: + +```php +private static function assemble( $element ) { + if( self::getDiv() ) { + if(is_string(self::getDiv())) { + $element = str_replace('ELEMENT', $element, self::getDiv()); + self::setDiv(false); // one-shot + } + } + self::$form .= $element; +} +``` + +So `Form::addInputTypeText(['name' => 'x'], ['class' => 'form-group'])` emits: + +```html +
+ +
+``` + +The wrapper is **single-shot** — it resets to `false` after one use. This is a third placeholder layer (`ELEMENT`) on top of `OPTIONS` and `FIELDS`. + +### 5.8 The full assembly buffer pipeline (three placeholder layers) + +``` +addInputTypeText() ─► TypeText.loadElement() + ├─ FormAttributes._setAttributes() + │ ├─ str_replace(NAME, value, …) [§5.2 substitution] + │ └─ ~50 cleanup str_replace [§5.2 strip-unused] + └─ returns clean HTML + ─► assemble() + └─ if $div set: str_replace(ELEMENT, html, '
ELEMENT
') [§5.7] + ─► appends to self::$form + +addSelectOption() ─► TypeOption.loadElement() ─► appends to self::$option +addSelectOption() ─► (more options) ─► appends to self::$option +addSelect() ─► TypeSelect.loadElement() (template contains OPTIONS) + ─► displaySelect: str_replace(OPTIONS, self::$option, html) [§5.6] + ─► assemble() ─► appends to self::$form + +addForm() ─► Form.loadElement() (template contains FIELDS) + ─► display: str_replace(FIELDS, self::$form, html) [final wrap] + ─► returns the complete HTML string (does NOT echo, caller assigns) +``` + +Three replace targets, three different scopes: + +| Token | Scope | Replaced by | +|---|---|---| +| `OPTIONS` | inside one `` in Ihr Formular ein. diff --git a/docs/src/content/docs/de/core/config.md b/docs/src/content/docs/de/core/config.md index 8430ecb..a95a303 100644 --- a/docs/src/content/docs/de/core/config.md +++ b/docs/src/content/docs/de/core/config.md @@ -82,19 +82,19 @@ password_hash = "another-salt-for-AES_DECRYPT" ## Konfiguration lesen ```php $cfg = \Nibiru\Config::getInstance()->getConfig(); -$cfg['DATABASE']['driver']; // 'pdo' -$cfg['SETTINGS']['page.url']; // 'https://my-app.local' +$cfg['DATABASE']['driver']; / 'pdo' +$cfg['SETTINGS']['page.url']; / 'https://my-app.local' ``` Verwenden Sie für tief geschachtelte Konfigurationen die typisierten Konstanten aus der View-Schnittstelle: ```php -$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; // ['/public/css/app.css'] +$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; / ['/public/css/app.css'] ``` ## Modulkonfigurationen Jeder Modul unter `application/module//settings/` kann seine eigenen INI-Dateien haben. Der Registrierungsservice erkennt sie automatisch und macht sie über verfügbar: ```php $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$users->session_lifetime; // from [USERS] section in users.ini +$users->session_lifetime; / from [USERS] section in users.ini ``` Der Registrierung wird `..ini` vor `.ini` bevorzugt, sodass Sie automatisch Überschreibungen pro Umgebung erhalten. diff --git a/docs/src/content/docs/de/core/controllers.md b/docs/src/content/docs/de/core/controllers.md index e5f0e82..5f5ef75 100644 --- a/docs/src/content/docs/de/core/controllers.md +++ b/docs/src/content/docs/de/core/controllers.md @@ -56,12 +56,12 @@ View::assign(['products' => $list]); ``` Hilfsfunktionen aus dem Basiscontroller: ```php -$this->getRequest('id', false); // $_REQUEST['id'] ?? false -$this->getPost('email', ''); // $_POST['email'] ?? '' -$this->getGet('page', 1); // $_GET['page'] ?? 1 -$this->getServer('REQUEST_URI'); // $_SERVER['REQUEST_URI'] -$this->getFiles('upload'); // $_FILES['upload'] -$this->getSession('auth'); // $_SESSION['auth'] +$this->getRequest('id', false); / $_REQUEST['id'] ?? false +$this->getPost('email', ''); / $_POST['email'] ?? '' +$this->getGet('page', 1); / $_GET['page'] ?? 1 +$this->getServer('REQUEST_URI'); / $_SERVER['REQUEST_URI'] +$this->getFiles('upload'); / $_FILES['upload'] +$this->getSession('auth'); / $_SESSION['auth'] ``` Diese bestehen, weil `Controller` `final`-freundlich ist: Sie können sie in Tests durch eine untergeordnete Klasse ersetzen. @@ -69,8 +69,8 @@ Diese bestehen, weil `Controller` `final`-freundlich ist: Sie können sie in Tes Um innerhalb einer Aktion umzuleiten: ```php -View::forwardTo('/login'); // 302 to the URL, exits -View::forwardToJsonHeader(); // sets Content-Type: application/json +View::forwardTo('/login'); / 302 to the URL, exits +View::forwardToJsonHeader(); / sets Content-Type: application/json ``` `forwardToJsonHeader()` ist das kanonische Muster für JSON-Endpunkte – setzen Sie den Header, weisen Sie `data` zu und geben Sie zurück. Der Anzeigebereich kümmert sich danach um die Reste. diff --git a/docs/src/content/docs/de/core/dispatcher.md b/docs/src/content/docs/de/core/dispatcher.md index 14c4ccb..e702c4b 100644 --- a/docs/src/content/docs/de/core/dispatcher.md +++ b/docs/src/content/docs/de/core/dispatcher.md @@ -30,17 +30,17 @@ public function run() { if (Config::getInstance()->getConfig() [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) { - new Model(false); // 1. (re)generate models from schema + new Model(false); / 1. (re)generate models from schema } - Router::getInstance()->route(); // 2. parse the URL - Auto::loader()->loadModelFiles(); // 3. load model files - Auto::loader()->loadModules(); // 4. load module classes + Router::getInstance()->route(); / 2. parse the URL + Auto::loader()->loadModelFiles(); / 3. load model files + Auto::loader()->loadModules(); / 4. load module classes $tpl = Router::getInstance()->tplName(); $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php"; - if (is_file($controllerFile)) { // 5. controller file exists + if (is_file($controllerFile)) { / 5. controller file exists require_once $controllerFile; $class = "Nibiru\\{$tpl}Controller"; $controller = new $class(); @@ -49,7 +49,7 @@ public function run() { $action = $_REQUEST['_action'] . 'Action'; $controller->navigationAction(); if (method_exists($controller, $action)) { - $controller->$action(); // 6. optional named action + $controller->$action(); / 6. optional named action } $controller->pageAction(); } else { @@ -57,9 +57,9 @@ public function run() { $controller->pageAction(); } - Display::getInstance()->display(); // 7. render Smarty + Display::getInstance()->display(); / 7. render Smarty } else { - // 8. soft 404 — render the configured error controller + / 8. soft 404 — render the configured error controller } } ``` diff --git a/docs/src/content/docs/de/core/forms.md b/docs/src/content/docs/de/core/forms.md index 19fb275..be2deb9 100644 --- a/docs/src/content/docs/de/core/forms.md +++ b/docs/src/content/docs/de/core/forms.md @@ -40,8 +40,8 @@ addOpenSpan addCloseSpan ``` ### Lebenszyklus ``` -create // reset the static buffer; call before building a new form -addForm // wrap the buffer in
...
and return as a string +create / reset the static buffer; call before building a new form +addForm / wrap the buffer in
...
and return as a string ``` :::caution[Die Namensinconsistenz ist absichtlich, zumindest teilweise] `addInputTypePassword` vs `addTypePassword`, `addInputTypeFileupload` vs `addTypeFileUpload` — das Präfix entspricht, ob das Element ein `` (Input-Prefix) oder ein anderer Tag (Type-Prefix) ist. Es ist unangenehm, aber stabil; die CLI-`./nibiru -c`-Scaffolds verwenden dasselbe Muster, sodass die Muskelspeicherung funktioniert. @@ -51,7 +51,7 @@ addForm // wrap the buffer in
...
and return as a string ```php use Nibiru\Factory\Form; -Form::create(); // reset the static buffer +Form::create(); / reset the static buffer Form::addOpenDiv(['class' => 'form-group']); Form::addTypeLabel(['for' => 'login', 'value' => 'Username']); @@ -187,7 +187,7 @@ class formsController extends Controller { 'required' => 'required', 'class' => 'contacts-input form-control', ]); - // ...more fields... + / ...more fields... $this->form = Form::addForm([ 'name' => 'newregister', 'method' => 'post', diff --git a/docs/src/content/docs/de/core/modules.md b/docs/src/content/docs/de/core/modules.md index 3eb6f21..84d3c8c 100644 --- a/docs/src/content/docs/de/core/modules.md +++ b/docs/src/content/docs/de/core/modules.md @@ -147,9 +147,9 @@ allowed.roles[] = "standard" Lesen Sie es von überall aus: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$cfg->session_lifetime; // 7200 -$cfg->password_min_length; // 12 -$cfg->allowed_roles; // [admin, editor, standard] +$cfg->session_lifetime; / 7200 +$cfg->password_min_length; / 12 +$cfg->allowed_roles; / [admin, editor, standard] ``` Umgebungsüberschreibungen: Eine Datei mit dem Namen `users.production.ini` wird vorzugsweise gegenüber `users.ini` verwendet, wenn `APPLICATION_ENV=production`. @@ -162,7 +162,7 @@ $analytics = new \Nibiru\Module\Analytics\Analytics(); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Matomo()); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Plausible()); -$analytics->trackPageView(); // internally calls notify() +$analytics->trackPageView(); / internally calls notify() ``` Jeder Beobachter erhält die Analytics-Instanz und zieht die Ereignisdaten aus, über die er sich interessiert. @@ -200,7 +200,7 @@ Die Namen sind **kleinbuchstabeigeordnete Ordnername**, genau wie sie unter `app Pluginklassen liegen im **Plural**-Namespace `Plugins`: ```php // application/module/billing/plugins/invoice.php -namespace Nibiru\Module\Billing\Plugins; // ← plural +namespace Nibiru\Module\Billing\Plugins; / ← plural class Invoice extends \Nibiru\Module\Billing\Billing { /* ... */ } ``` Namespace und Klassenname nicht übereinstimmen und es treten Autoloader-Fehlschläge auf. Der CLI-Scaffold-Befehl (`./nibiru -m billing`) generiert den richtigen Namespace für Sie. @@ -210,7 +210,7 @@ Namespace und Klassenname nicht übereinstimmen und es treten Autoloader-Fehlsch Sie **registrieren** Ihre Modul-INI-Dateien nicht — der [Registry](/de/core/registry/) entdeckt sie automatisch, indem er `application/module//settings/*.ini` durchläuft, nachdem `[AUTOLOADER]` die Modulklassen lädt. Jede Sektion `[]` (in Großbuchstaben) in einer INI wird zur Verfügung gestellt als: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('billing'); -$cfg->invoice_prefix; // [BILLING] invoice.prefix → property +$cfg->invoice_prefix; / [BILLING] invoice.prefix → property ``` Der Registrierungsmodul bevorzugt `..ini` (z.B. `billing.production.ini`), wenn `APPLICATION_ENV` übereinstimmt. diff --git a/docs/src/content/docs/de/core/pagination.md b/docs/src/content/docs/de/core/pagination.md index 0725497..e856d2d 100644 --- a/docs/src/content/docs/de/core/pagination.md +++ b/docs/src/content/docs/de/core/pagination.md @@ -14,7 +14,7 @@ class productsController extends Controller { public function pageAction() { $products = new products(); - Pageination::setEntriesPerPage(25); // optional; default from INI + Pageination::setEntriesPerPage(25); / optional; default from INI Pageination::setTable($products); $rows = Pageination::loadTableAsArray(); diff --git a/docs/src/content/docs/de/core/registry.md b/docs/src/content/docs/de/core/registry.md index 4232769..a36b0c9 100644 --- a/docs/src/content/docs/de/core/registry.md +++ b/docs/src/content/docs/de/core/registry.md @@ -20,7 +20,7 @@ Für jedes Modul unter `application/module//settings/`: $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); $users->session_lifetime; $users->password_min_length; -$users->allowed_roles; // array +$users->allowed_roles; / array ``` Innerhalb des Moduls selbst ist die Konvention, dies in einen Setter zu verpacken: ```php diff --git a/docs/src/content/docs/de/core/routing.md b/docs/src/content/docs/de/core/routing.md index 7c9e8d0..23a9f42 100644 --- a/docs/src/content/docs/de/core/routing.md +++ b/docs/src/content/docs/de/core/routing.md @@ -40,7 +40,7 @@ Alles nach dem Aktionssegment wird zu einem `$_REQUEST`-Schlüssel gemäß der P // /users/edit/42 → $_REQUEST['id'] = '42' public function editAction() { $id = (int) ($_REQUEST['id'] ?? 0); - // ... + / ... } ``` Für nicht-numerische oder benannte Parameter bevorzugen Sie Abfragezeichenfolgen: @@ -62,9 +62,9 @@ Wenn eine URL dem Muster entspricht, werden die Captured Groups den benannten `p ## Routen-Hilfsprogramme ```php -Router::getInstance()->currentPage(); // 'products' -Router::getInstance()->tplName(); // 'products' (controller stem for templates) -Router::getInstance()->getController(); // alias for currentPage() +Router::getInstance()->currentPage(); / 'products' +Router::getInstance()->tplName(); / 'products' (controller stem for templates) +Router::getInstance()->getController(); / alias for currentPage() ``` Diese sind nützlich innerhalb von Controllern und Templates: ```smarty diff --git a/docs/src/content/docs/de/design/components.md b/docs/src/content/docs/de/design/components.md index 06aa933..62102a6 100644 --- a/docs/src/content/docs/de/design/components.md +++ b/docs/src/content/docs/de/design/components.md @@ -7,7 +7,7 @@ description: "Schaltflächen, Karten, Aufrufe, Heldenbildschirm – bereit zum K Ein schwarzer Rechteck auf einem cremefarbenen Hintergrund. Editorial. Kein Gradient, kein Glühen. ```html - + Read the docs @@ -162,7 +162,7 @@ Asymmetrische Gitter mit zwei Spalten. Große Editorial-Nummer hinter dem Text. Nibiru is a modular PHP framework for builders who ship.

diff --git a/docs/src/content/docs/de/index.mdx b/docs/src/content/docs/de/index.mdx index da7277a..907a08a 100644 --- a/docs/src/content/docs/de/index.mdx +++ b/docs/src/content/docs/de/index.mdx @@ -19,73 +19,25 @@ hero: variant: minimal --- -import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; +import CometTrail from '../../../components/CometTrail.astro'; +import MmvcStage from '../../../components/MmvcStage.astro'; +import MissionControl from '../../../components/MissionControl.astro'; +import LaunchSequence from '../../../components/LaunchSequence.astro'; +import SpacecraftGrid from '../../../components/SpacecraftGrid.astro'; +import EditorialContent from '../../../components/EditorialContent.astro'; +import LandingFooter from '../../../components/LandingFooter.astro'; +import ToTop from '../../../components/ToTop.astro'; +import LandingScripts from '../../../components/LandingScripts.astro'; -## Eine Konstellation von Funktionen + + + + + + + + - - - Module umschließen MVC mit Traits, Plugins, Interfaces und Settings. Das zweite **M** ist lose gekoppelt — und besitzt das Observer-Muster (`SplSubject`) ab Werk. - - - Fünf Treiber im Orbit: `mysql`, `pdo`, `postgres` (ODBC), `psql` (libpq) und `postgresql`. Wechsel durch Ändern eines INI-Schlüssels. - - - Template-getriebene Views, ein globaler `View::assign()`-Helfer und ein heißer `templates_c`-Cache. Plus geteilte Partials, Navigations-Includes und Pagination-Templates. - - - 28+ Feldtypen — Text, Passwort, Switch, Color, Range, File-Upload — komponiert über statische `Form::add…`-Aufrufe und als ein einziger HTML-String gerendert. - - - `./nibiru` generiert Module, Controller, Plugins, Migrationen und CMS-Seiten. Es führt Migrationen gegen `local`, `staging` oder `production` aus. - - - Nibiru wird das erste PHP-Framework mit einem eingebauten RAG-basierten Orakel, das auf seinem eigenen Wissen trainiert ist — und einem veröffentlichten Korpus für künftige Fine-Tunes. - - - -## Schnellstart - -```bash -# Klonen -git clone https://github.com/alllinux/Nibiru meine-app && cd meine-app - -# PHP-Abhängigkeiten installieren (Smarty, PHPMailer, Guzzle, …) -composer install - -# Berechtigungen + Ordner-Bootstrap -./nibiru -s - -# Erste Migration ausführen -./nibiru -mi local - -# Controller generieren -./nibiru -c products -``` - -```php -// application/controller/productsController.php -namespace Nibiru; -use Nibiru\Adapter\Controller; - -class productsController extends Controller { - public function pageAction() { - View::assign([ - 'title' => 'Produkte — Nibiru', - 'products' => [['id' => 1, 'name' => 'Marduk-Goldbeschichtung']], - ]); - } - public function navigationAction() { - JsonNavigation::getInstance()->loadJsonNavigationArray(); - } -} -``` - -## Wohin als Nächstes? - - - - - - - +{/* Loads three.js + the original mockup scene code. MUST be the last node so + every #id the scene targets exists in the DOM when the script runs. */} + diff --git a/docs/src/content/docs/de/showcase/patterns.md b/docs/src/content/docs/de/showcase/patterns.md index 2873fbd..748ee3e 100644 --- a/docs/src/content/docs/de/showcase/patterns.md +++ b/docs/src/content/docs/de/showcase/patterns.md @@ -61,7 +61,7 @@ Mehrere Tracker ohne Controller-Kopplung. $analytics = new Analytics(); $analytics->attach(new Plugin\Matomo()); $analytics->attach(new Plugin\Plausible()); -$analytics->trackPageView(); // calls notify() internally +$analytics->trackPageView(); / calls notify() internally ``` Jeder Beobachter ruft nur die Felder ab, die er interessiert sind. Hinzufügen eines Trackers ist eine Änderung in einer Zeile. diff --git a/docs/src/content/docs/de/showcase/projects.md b/docs/src/content/docs/de/showcase/projects.md index 76fba46..db257a5 100644 --- a/docs/src/content/docs/de/showcase/projects.md +++ b/docs/src/content/docs/de/showcase/projects.md @@ -55,7 +55,7 @@ public function detailAction() try { $machine = Machine::init()->getMachine((int) $machineId); } catch (\Throwable $e) { - $machine = null; // DB blip → page still renders with fallback. + $machine = null; / DB blip → page still renders with fallback. } $machineName = $machine['ms_machines_name'] ?? "Maschine #$machineId"; @@ -110,7 +110,7 @@ Fügen Sie eine neue Smarty-Vorlage ins System ein, der Editor weiß sofort, wel ## Was ist tatsächlich besonderes, zusammengefasst -Die fünf Unterschiedsmaker unten stammen aus den darüberliegenden Codebasen. Jeder verweist auf seine Beweise auf der Seite [Warum Nibiru](/de/warum-nibiru/). +Die fünf Unterschiedsmaker unten stammen aus den darüberliegenden Codebasen. Jeder verweist auf seine Beweise auf der Seite [Warum Nibiru](/de/why-nibiru/). | | Was Nibiru macht | Was Laravel/Symfony macht | |---|---|---| @@ -120,7 +120,7 @@ Die fünf Unterschiedsmaker unten stammen aus den darüberliegenden Codebasen. J | Authentifizierung | 3 Zeilen im Controller-Konstruktor. | Middleware-Stack + Policy-Klassen + Gates. | | Ereignisse | `SplSubject` + `SplObserver` aus der PHP Standardbibliothek. | Benutzerdefinierter Event-Dispatcher + Listener-Registry + Warteschlange. | -Lesen Sie die [vollständige Ausbreakdown mit Codeverweisen →](/de/warum-nibiru/) +Lesen Sie die [vollständige Ausbreakdown mit Codeverweisen →](/de/why-nibiru/) --- diff --git a/docs/src/content/docs/de/why-nibiru.md b/docs/src/content/docs/de/why-nibiru.md index 7284a6f..0b13fe6 100644 --- a/docs/src/content/docs/de/why-nibiru.md +++ b/docs/src/content/docs/de/why-nibiru.md @@ -50,7 +50,7 @@ class Cms implements Interfaces\Cms, SplSubject use Traits\PageBuilderForm; use Traits\CmsPageStructureModifier; use Traits\FormElements; - // …8 more traits + / …8 more traits } ``` **Gesamtwirkung**: keine Konstruktor-Injektion, keine Dienstleistungsanbieterregistrierung, keine Aufrufe von `bind()` / `singleton()` in einer Konfigurationsdatei. Ein neuer Entwickler kann nach dem Trait-Namen suchen und alle Aufrufer sehen. @@ -108,7 +108,7 @@ Der API-Controller nimmt den umgekehrten Ansatz: eine Whitelist öffentlicher En ```php // public endpoints can be listed up-front, auth wraps the rest. if (in_array($action, ['category', 'machines', 'ollama', 'team'])) { - // public, skip auth + / public, skip auth } else { $this->user = new User(); $this->acl = new Acl(); @@ -137,8 +137,8 @@ class Machineryscout implements IModule, \SplSubject } public function indexMachines(): void { - // …do the work… - $this->notify(); // analytics, cache invalidator, audit log all see it. + / …do the work… + $this->notify(); / analytics, cache invalidator, audit log all see it. } } ``` @@ -154,4 +154,4 @@ Ein einzelner Entwickler oder eine kleine Team kann eine echte Produktions-App b Wenn Sie lieber Ihren Code sehen möchten, nehmen Sie ihn. -→ [Die Präsentation ansehen →](/de/praesentation/projekte/) +→ [Die Präsentation ansehen →](/de/showcase/projects/) diff --git a/docs/src/content/docs/en/ai/corpus.md b/docs/src/content/docs/en/ai/corpus.md index dfc3b21..029f30b 100644 --- a/docs/src/content/docs/en/ai/corpus.md +++ b/docs/src/content/docs/en/ai/corpus.md @@ -70,7 +70,7 @@ Raw chunks for use as RAG retrieval data: } ``` -This is exactly the file the [Oracle](/ai/oracle/) uses internally. +This is exactly the file the [Oracle](/en/ai/oracle/) uses internally. ## How chunks are derived diff --git a/docs/src/content/docs/en/ai/module/chat.md b/docs/src/content/docs/en/ai/module/chat.md index d865e19..0413275 100644 --- a/docs/src/content/docs/en/ai/module/chat.md +++ b/docs/src/content/docs/en/ai/module/chat.md @@ -11,19 +11,19 @@ The Chat plugin is the simplest piece of the AI module. It wraps Ollama's `/api/ $ai = new \Nibiru\Module\Ai\Ai(); $chat = $ai->chat(); -$chat->system('Be terse.'); // optional system prompt -$chat->model('qwen2.5-coder:14b'); // override the configured model -$chat->temperature(0.2); // override config -$chat->maxTokens(512); // override config +$chat->system('Be terse.'); / optional system prompt +$chat->model('qwen2.5-coder:14b'); / override the configured model +$chat->temperature(0.2); / override config +$chat->maxTokens(512); / override config -$chat->user('Hello'); // append a user message -$chat->assistant('Hi.'); // append an assistant message (rare) +$chat->user('Hello'); / append a user message +$chat->assistant('Hi.'); / append an assistant message (rare) -$reply = $chat->complete(); // run the call, return text -$reply = $chat->ask('How are you?'); // = ->user(...)->complete() +$reply = $chat->complete(); / run the call, return text +$reply = $chat->ask('How are you?'); / = ->user(...)->complete() -$chat->reset(); // clear messages, keep model + system -$chat->history(); // [{role, content}, …] +$chat->reset(); / clear messages, keep model + system +$chat->history(); / [{role, content}, …] ``` ## One-shot @@ -40,10 +40,10 @@ echo (new \Nibiru\Module\Ai\Ai()) $chat = $ai->chat(); $chat->user('Name three Nibiru singletons.'); -$singletons = $chat->complete(); // appended to history +$singletons = $chat->complete(); / appended to history $chat->user('What does the second one do?'); -$detail = $chat->complete(); // model has full context +$detail = $chat->complete(); / model has full context ``` ## Overriding model + style per call diff --git a/docs/src/content/docs/en/ai/module/embed.md b/docs/src/content/docs/en/ai/module/embed.md index 4cd4e52..e984784 100644 --- a/docs/src/content/docs/en/ai/module/embed.md +++ b/docs/src/content/docs/en/ai/module/embed.md @@ -10,12 +10,12 @@ The Embed plugin is a thin wrapper around Ollama's `/api/embeddings` plus three ```php $embed = (new \Nibiru\Module\Ai\Ai())->embed(); -$vec = $embed->one('controller'); // float[] -$vectors = $embed->batch(['a', 'b', 'c']); // float[][] +$vec = $embed->one('controller'); / float[] +$vectors = $embed->batch(['a', 'b', 'c']); / float[][] -$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); // 0..1 -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string -$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); // back to float[] +$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); / 0..1 +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string +$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); / back to float[] ``` ## Pattern: deduplicate near-duplicate strings @@ -54,8 +54,8 @@ function bestTag(string $text, array $tagVecs, $embed): string { return $best[0]; } -echo bestTag('User::isAuthorized', $tagVecs, $embed); // → 'authentication' -echo bestTag('Pageination::setTable', $tagVecs, $embed); // → 'database' (probably) +echo bestTag('User::isAuthorized', $tagVecs, $embed); / → 'authentication' +echo bestTag('Pageination::setTable', $tagVecs, $embed); / → 'database' (probably) ``` ## Storage @@ -65,7 +65,7 @@ Embeddings are float arrays — typically 768 floats for `nomic-embed-text`, 102 Use `Embed::pack()` to base64-encode them as 4-byte floats: ```php -$compact = Embed::pack($vec); // ~4 KB → ~5.3 KB base64 string +$compact = Embed::pack($vec); / ~4 KB → ~5.3 KB base64 string $vec = Embed::unpack($compact); ``` diff --git a/docs/src/content/docs/en/ai/module/overview.md b/docs/src/content/docs/en/ai/module/overview.md index 2bab671..e99dc3d 100644 --- a/docs/src/content/docs/en/ai/module/overview.md +++ b/docs/src/content/docs/en/ai/module/overview.md @@ -62,7 +62,7 @@ echo $ai->chat()->ask('Explain MMVC in two sentences.'); // Multi-turn $chat = $ai->chat(); $chat->user('How do I scaffold a module?'); -$chat->user('And add Graylog hooks?'); // referrs to previous turn +$chat->user('And add Graylog hooks?'); / referrs to previous turn echo $chat->complete(); // Override per call @@ -89,7 +89,7 @@ $score = \Nibiru\Module\Ai\Plugin\Embed::cosine($va, $vb); Compact storage: ```php -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string, 4 bytes/dim +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string, 4 bytes/dim $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); ``` @@ -99,7 +99,7 @@ $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); $rag = $ai->rag('product-help'); // One-time ingestion -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); $rag->ingestFile('/var/data/manual.pdf.txt'); @@ -118,9 +118,9 @@ use Nibiru\Module\Ai\Plugin\Tools; $ai = new \Nibiru\Module\Ai\Ai(); $agent = $ai->agent()->withTools([ - new Tools\PdoQuery(), // read-only SQL - new Tools\HttpGet(), // fetch URLs - new Tools\FileRead(), // read project files + new Tools\PdoQuery(), / read-only SQL + new Tools\HttpGet(), / fetch URLs + new Tools\FileRead(), / read project files ]); echo $agent->run('How many active users registered last week?'); diff --git a/docs/src/content/docs/en/ai/module/rag.md b/docs/src/content/docs/en/ai/module/rag.md index 458f7e1..8f0422b 100644 --- a/docs/src/content/docs/en/ai/module/rag.md +++ b/docs/src/content/docs/en/ai/module/rag.md @@ -11,9 +11,9 @@ The RAG plugin is the AI module's killer feature for product builders. It turns use Nibiru\Module\Ai\Ai; $ai = new Ai(); -$rag = $ai->rag('product-help'); // a named collection +$rag = $ai->rag('product-help'); / a named collection -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php under help/ +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php under help/ $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); echo $rag->ask('How do I cancel my subscription?'); @@ -53,20 +53,20 @@ $logs->ingestText($exception->__toString(), ['ts' => time()]); ## API reference ```php -$rag = $ai->rag('name'); // get/create a named collection +$rag = $ai->rag('name'); / get/create a named collection // --- Ingestion --- -$rag->ingestText($text, $metadata = []); // single chunk -$count = $rag->ingestFile('path'); // returns chunks added -$count = $rag->ingestDir('dir', ['md','txt','php']); // recursive +$rag->ingestText($text, $metadata = []); / single chunk +$count = $rag->ingestFile('path'); / returns chunks added +$count = $rag->ingestDir('dir', ['md','txt','php']); / recursive // --- Querying --- -$hits = $rag->search('query', $k = null); // [{score, text, metadata}, …] -$answer = $rag->ask('question', $k = null); // top-K → chat call +$hits = $rag->search('query', $k = null); / [{score, text, metadata}, …] +$answer = $rag->ask('question', $k = null); / top-K → chat call // --- Maintenance --- -$rag->reset(); // forget everything (deletes file) -$n = $rag->size(); // number of chunks +$rag->reset(); / forget everything (deletes file) +$n = $rag->size(); / number of chunks ``` ## Tuning knobs diff --git a/docs/src/content/docs/en/core/auth.md b/docs/src/content/docs/en/core/auth.md index 2b0b14f..0c27dff 100644 --- a/docs/src/content/docs/en/core/auth.md +++ b/docs/src/content/docs/en/core/auth.md @@ -125,7 +125,7 @@ public function pageAction() { View::forwardTo('/login'); return; } - // ... + / ... } ``` @@ -195,7 +195,7 @@ public function submitAction() { http_response_code(419); return; } - // ...handle submission... + / ...handle submission... } ``` diff --git a/docs/src/content/docs/en/core/config.md b/docs/src/content/docs/en/core/config.md index bcd99aa..887b03f 100644 --- a/docs/src/content/docs/en/core/config.md +++ b/docs/src/content/docs/en/core/config.md @@ -87,14 +87,14 @@ password_hash = "another-salt-for-AES_DECRYPT" ```php $cfg = \Nibiru\Config::getInstance()->getConfig(); -$cfg['DATABASE']['driver']; // 'pdo' -$cfg['SETTINGS']['page.url']; // 'https://my-app.local' +$cfg['DATABASE']['driver']; / 'pdo' +$cfg['SETTINGS']['page.url']; / 'https://my-app.local' ``` For deeply-nested configs use the typed constants from the View interface: ```php -$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; // ['/public/css/app.css'] +$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; / ['/public/css/app.css'] ``` ## Module configs @@ -103,7 +103,7 @@ Each module under `application/module//settings/` can carry its own INI fi ```php $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$users->session_lifetime; // from [USERS] section in users.ini +$users->session_lifetime; / from [USERS] section in users.ini ``` The Registry prefers `..ini` over `.ini`, so you get per-environment overrides for free. diff --git a/docs/src/content/docs/en/core/controllers.md b/docs/src/content/docs/en/core/controllers.md index acc9e0e..af91966 100644 --- a/docs/src/content/docs/en/core/controllers.md +++ b/docs/src/content/docs/en/core/controllers.md @@ -61,12 +61,12 @@ View::assign(['products' => $list]); Convenience helpers from the base controller: ```php -$this->getRequest('id', false); // $_REQUEST['id'] ?? false -$this->getPost('email', ''); // $_POST['email'] ?? '' -$this->getGet('page', 1); // $_GET['page'] ?? 1 -$this->getServer('REQUEST_URI'); // $_SERVER['REQUEST_URI'] -$this->getFiles('upload'); // $_FILES['upload'] -$this->getSession('auth'); // $_SESSION['auth'] +$this->getRequest('id', false); / $_REQUEST['id'] ?? false +$this->getPost('email', ''); / $_POST['email'] ?? '' +$this->getGet('page', 1); / $_GET['page'] ?? 1 +$this->getServer('REQUEST_URI'); / $_SERVER['REQUEST_URI'] +$this->getFiles('upload'); / $_FILES['upload'] +$this->getSession('auth'); / $_SESSION['auth'] ``` These exist because `Controller` is `final`-friendly: you can mock them in tests by substituting a child class. @@ -76,8 +76,8 @@ These exist because `Controller` is `final`-friendly: you can mock them in tests To redirect inside an action: ```php -View::forwardTo('/login'); // 302 to the URL, exits -View::forwardToJsonHeader(); // sets Content-Type: application/json +View::forwardTo('/login'); / 302 to the URL, exits +View::forwardToJsonHeader(); / sets Content-Type: application/json ``` `forwardToJsonHeader()` is the canonical pattern for JSON endpoints — set the header, assign `data`, return. The view layer does the rest. diff --git a/docs/src/content/docs/en/core/dispatcher.md b/docs/src/content/docs/en/core/dispatcher.md index 737a0db..9be3a38 100644 --- a/docs/src/content/docs/en/core/dispatcher.md +++ b/docs/src/content/docs/en/core/dispatcher.md @@ -35,17 +35,17 @@ public function run() { if (Config::getInstance()->getConfig() [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) { - new Model(false); // 1. (re)generate models from schema + new Model(false); / 1. (re)generate models from schema } - Router::getInstance()->route(); // 2. parse the URL - Auto::loader()->loadModelFiles(); // 3. load model files - Auto::loader()->loadModules(); // 4. load module classes + Router::getInstance()->route(); / 2. parse the URL + Auto::loader()->loadModelFiles(); / 3. load model files + Auto::loader()->loadModules(); / 4. load module classes $tpl = Router::getInstance()->tplName(); $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php"; - if (is_file($controllerFile)) { // 5. controller file exists + if (is_file($controllerFile)) { / 5. controller file exists require_once $controllerFile; $class = "Nibiru\\{$tpl}Controller"; $controller = new $class(); @@ -54,7 +54,7 @@ public function run() { $action = $_REQUEST['_action'] . 'Action'; $controller->navigationAction(); if (method_exists($controller, $action)) { - $controller->$action(); // 6. optional named action + $controller->$action(); / 6. optional named action } $controller->pageAction(); } else { @@ -62,9 +62,9 @@ public function run() { $controller->pageAction(); } - Display::getInstance()->display(); // 7. render Smarty + Display::getInstance()->display(); / 7. render Smarty } else { - // 8. soft 404 — render the configured error controller + / 8. soft 404 — render the configured error controller } } ``` diff --git a/docs/src/content/docs/en/core/forms.md b/docs/src/content/docs/en/core/forms.md index 1f2cc26..b1702b2 100644 --- a/docs/src/content/docs/en/core/forms.md +++ b/docs/src/content/docs/en/core/forms.md @@ -51,8 +51,8 @@ addOpenSpan addCloseSpan ### Lifecycle ``` -create // reset the static buffer; call before building a new form -addForm // wrap the buffer in
...
and return as a string +create / reset the static buffer; call before building a new form +addForm / wrap the buffer in
...
and return as a string ``` :::caution[The naming inconsistency is intentional, sort of] @@ -64,7 +64,7 @@ addForm // wrap the buffer in
...
and return as a string ```php use Nibiru\Factory\Form; -Form::create(); // reset the static buffer +Form::create(); / reset the static buffer Form::addOpenDiv(['class' => 'form-group']); Form::addTypeLabel(['for' => 'login', 'value' => 'Username']); @@ -220,7 +220,7 @@ class formsController extends Controller { 'required' => 'required', 'class' => 'contacts-input form-control', ]); - // ...more fields... + / ...more fields... $this->form = Form::addForm([ 'name' => 'newregister', 'method' => 'post', diff --git a/docs/src/content/docs/en/core/modules.md b/docs/src/content/docs/en/core/modules.md index 1ced28e..b2d3fea 100644 --- a/docs/src/content/docs/en/core/modules.md +++ b/docs/src/content/docs/en/core/modules.md @@ -160,9 +160,9 @@ Read it back from anywhere: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$cfg->session_lifetime; // 7200 -$cfg->password_min_length; // 12 -$cfg->allowed_roles; // [admin, editor, standard] +$cfg->session_lifetime; / 7200 +$cfg->password_min_length; / 12 +$cfg->allowed_roles; / [admin, editor, standard] ``` Environment overlays: a file named `users.production.ini` is preferred over `users.ini` when `APPLICATION_ENV=production`. @@ -177,7 +177,7 @@ $analytics = new \Nibiru\Module\Analytics\Analytics(); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Matomo()); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Plausible()); -$analytics->trackPageView(); // internally calls notify() +$analytics->trackPageView(); / internally calls notify() ``` Each observer's `update($subject)` receives the analytics instance and pulls the event data it cares about. @@ -219,7 +219,7 @@ Plugin classes live under the **plural** namespace `Plugins`: ```php // application/module/billing/plugins/invoice.php -namespace Nibiru\Module\Billing\Plugins; // ← plural +namespace Nibiru\Module\Billing\Plugins; / ← plural class Invoice extends \Nibiru\Module\Billing\Billing { /* ... */ } ``` @@ -231,7 +231,7 @@ You **don't** register your module's INI files — the [Registry](/en/core/regis ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('billing'); -$cfg->invoice_prefix; // [BILLING] invoice.prefix → property +$cfg->invoice_prefix; / [BILLING] invoice.prefix → property ``` The Registry prefers `..ini` (e.g. `billing.production.ini`) when `APPLICATION_ENV` matches. diff --git a/docs/src/content/docs/en/core/pagination.md b/docs/src/content/docs/en/core/pagination.md index 3f828f9..d5eec33 100644 --- a/docs/src/content/docs/en/core/pagination.md +++ b/docs/src/content/docs/en/core/pagination.md @@ -15,7 +15,7 @@ class productsController extends Controller { public function pageAction() { $products = new products(); - Pageination::setEntriesPerPage(25); // optional; default from INI + Pageination::setEntriesPerPage(25); / optional; default from INI Pageination::setTable($products); $rows = Pageination::loadTableAsArray(); diff --git a/docs/src/content/docs/en/core/registry.md b/docs/src/content/docs/en/core/registry.md index 968b9c2..82225a4 100644 --- a/docs/src/content/docs/en/core/registry.md +++ b/docs/src/content/docs/en/core/registry.md @@ -21,7 +21,7 @@ For each module under `application/module//settings/`: $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); $users->session_lifetime; $users->password_min_length; -$users->allowed_roles; // array +$users->allowed_roles; / array ``` Inside the module itself the convention is to wrap this in a setter: diff --git a/docs/src/content/docs/en/core/routing.md b/docs/src/content/docs/en/core/routing.md index 0d56553..04f4345 100644 --- a/docs/src/content/docs/en/core/routing.md +++ b/docs/src/content/docs/en/core/routing.md @@ -47,7 +47,7 @@ Anything past the action segment becomes a `$_REQUEST` key paired by position: // /users/edit/42 → $_REQUEST['id'] = '42' public function editAction() { $id = (int) ($_REQUEST['id'] ?? 0); - // ... + / ... } ``` @@ -75,9 +75,9 @@ When a URL matches the pattern, capture groups are assigned to the named `params ## Routing helpers ```php -Router::getInstance()->currentPage(); // 'products' -Router::getInstance()->tplName(); // 'products' (controller stem for templates) -Router::getInstance()->getController(); // alias for currentPage() +Router::getInstance()->currentPage(); / 'products' +Router::getInstance()->tplName(); / 'products' (controller stem for templates) +Router::getInstance()->getController(); / alias for currentPage() ``` These are useful inside controllers and templates: diff --git a/docs/src/content/docs/en/design/components.md b/docs/src/content/docs/en/design/components.md index 87fc1a2..6604362 100644 --- a/docs/src/content/docs/en/design/components.md +++ b/docs/src/content/docs/en/design/components.md @@ -8,7 +8,7 @@ description: Buttons, cards, callouts, hero — copy-paste ready. A black-on-cream rectangle. Editorial. No gradient, no glow. ```html - + Read the docs @@ -179,7 +179,7 @@ Asymmetric two-column grid. Big editorial number behind the copy. The brand mark Nibiru is a modular PHP framework for builders who ship.

diff --git a/docs/src/content/docs/en/downloads.mdx b/docs/src/content/docs/en/downloads.mdx index 9d8d96c..4ef4cf3 100644 --- a/docs/src/content/docs/en/downloads.mdx +++ b/docs/src/content/docs/en/downloads.mdx @@ -6,7 +6,7 @@ description: Downloadable Nibiru framework training corpus — chunks, instructi import DownloadsManifest from '../../../components/DownloadsManifest.astro'; A pre-built training corpus for fine-tuning your own LoRA on Nibiru. Generated -deterministically from two sources: the deep [framework reference](/en/reference/) +deterministically from two sources: the deep [framework reference](https://github.com/alllinux/Nibiru/blob/master/docs/scripts/extraction/framework-reference-v2.md) (every public factory, namespace, idiom and gotcha cited file:line) and the public docs in five languages. diff --git a/docs/src/content/docs/en/showcase/patterns.md b/docs/src/content/docs/en/showcase/patterns.md index 2f6799b..d7b45fe 100644 --- a/docs/src/content/docs/en/showcase/patterns.md +++ b/docs/src/content/docs/en/showcase/patterns.md @@ -70,7 +70,7 @@ Multiple trackers without controller coupling. $analytics = new Analytics(); $analytics->attach(new Plugin\Matomo()); $analytics->attach(new Plugin\Plausible()); -$analytics->trackPageView(); // calls notify() internally +$analytics->trackPageView(); / calls notify() internally ``` Each observer's `update($subject)` pulls only the fields it cares about. Adding a tracker is a one-line change. diff --git a/docs/src/content/docs/en/showcase/projects.md b/docs/src/content/docs/en/showcase/projects.md index bad6d51..cc71f27 100644 --- a/docs/src/content/docs/en/showcase/projects.md +++ b/docs/src/content/docs/en/showcase/projects.md @@ -56,7 +56,7 @@ public function detailAction() try { $machine = Machine::init()->getMachine((int) $machineId); } catch (\Throwable $e) { - $machine = null; // DB blip → page still renders with fallback. + $machine = null; / DB blip → page still renders with fallback. } $machineName = $machine['ms_machines_name'] ?? "Maschine #$machineId"; diff --git a/docs/src/content/docs/en/why-nibiru.md b/docs/src/content/docs/en/why-nibiru.md index 3ba1fbd..4a9623c 100644 --- a/docs/src/content/docs/en/why-nibiru.md +++ b/docs/src/content/docs/en/why-nibiru.md @@ -53,7 +53,7 @@ class Cms implements Interfaces\Cms, SplSubject use Traits\PageBuilderForm; use Traits\CmsPageStructureModifier; use Traits\FormElements; - // …8 more traits + / …8 more traits } ``` @@ -117,7 +117,7 @@ The API controller takes the inverse approach: a whitelist of public endpoints i ```php // public endpoints can be listed up-front, auth wraps the rest. if (in_array($action, ['category', 'machines', 'ollama', 'team'])) { - // public, skip auth + / public, skip auth } else { $this->user = new User(); $this->acl = new Acl(); @@ -148,8 +148,8 @@ class Machineryscout implements IModule, \SplSubject } public function indexMachines(): void { - // …do the work… - $this->notify(); // analytics, cache invalidator, audit log all see it. + / …do the work… + $this->notify(); / analytics, cache invalidator, audit log all see it. } } ``` diff --git a/docs/src/content/docs/es/ai/corpus.md b/docs/src/content/docs/es/ai/corpus.md index 0d33114..06a0978 100644 --- a/docs/src/content/docs/es/ai/corpus.md +++ b/docs/src/content/docs/es/ai/corpus.md @@ -60,7 +60,7 @@ Fragmentos sin procesar para su uso como datos de recuperación RAG: "content": "Modules implementing `SplSubject` can broadcast events…" } ``` -Este es exactamente el archivo que usa internamente [Oracle](/ai/oracle/). +Este es exactamente el archivo que usa internamente [Oracle](/es/ai/oracle/). ## Cómo se derivan los fragmentos diff --git a/docs/src/content/docs/es/ai/module/chat.md b/docs/src/content/docs/es/ai/module/chat.md index 7ff5cb9..b5cf2bf 100644 --- a/docs/src/content/docs/es/ai/module/chat.md +++ b/docs/src/content/docs/es/ai/module/chat.md @@ -10,19 +10,19 @@ El complemento de chat es la pieza más simple del módulo de IA. Envuelve la AP $ai = new \Nibiru\Module\Ai\Ai(); $chat = $ai->chat(); -$chat->system('Be terse.'); // optional system prompt -$chat->model('qwen2.5-coder:14b'); // override the configured model -$chat->temperature(0.2); // override config -$chat->maxTokens(512); // override config +$chat->system('Be terse.'); / optional system prompt +$chat->model('qwen2.5-coder:14b'); / override the configured model +$chat->temperature(0.2); / override config +$chat->maxTokens(512); / override config -$chat->user('Hello'); // append a user message -$chat->assistant('Hi.'); // append an assistant message (rare) +$chat->user('Hello'); / append a user message +$chat->assistant('Hi.'); / append an assistant message (rare) -$reply = $chat->complete(); // run the call, return text -$reply = $chat->ask('How are you?'); // = ->user(...)->complete() +$reply = $chat->complete(); / run the call, return text +$reply = $chat->ask('How are you?'); / = ->user(...)->complete() -$chat->reset(); // clear messages, keep model + system -$chat->history(); // [{role, content}, …] +$chat->reset(); / clear messages, keep model + system +$chat->history(); / [{role, content}, …] ``` ## En un solo paso ```php @@ -35,10 +35,10 @@ echo (new \Nibiru\Module\Ai\Ai()) $chat = $ai->chat(); $chat->user('Name three Nibiru singletons.'); -$singletons = $chat->complete(); // appended to history +$singletons = $chat->complete(); / appended to history $chat->user('What does the second one do?'); -$detail = $chat->complete(); // model has full context +$detail = $chat->complete(); / model has full context ``` ## Sobrescribir modelo y estilo por llamada ```php diff --git a/docs/src/content/docs/es/ai/module/embed.md b/docs/src/content/docs/es/ai/module/embed.md index a8f9130..bb6b1a2 100644 --- a/docs/src/content/docs/es/ai/module/embed.md +++ b/docs/src/content/docs/es/ai/module/embed.md @@ -9,12 +9,12 @@ El complemento Embed es un envoltorio ligero alrededor de `/api/embeddings` de O ```php $embed = (new \Nibiru\Module\Ai\Ai())->embed(); -$vec = $embed->one('controller'); // float[] -$vectors = $embed->batch(['a', 'b', 'c']); // float[][] +$vec = $embed->one('controller'); / float[] +$vectors = $embed->batch(['a', 'b', 'c']); / float[][] -$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); // 0..1 -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string -$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); // back to float[] +$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); / 0..1 +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string +$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); / back to float[] ``` ## Patrón: eliminar cadenas similares ```php @@ -49,8 +49,8 @@ function bestTag(string $text, array $tagVecs, $embed): string { return $best[0]; } -echo bestTag('User::isAuthorized', $tagVecs, $embed); // → 'authentication' -echo bestTag('Pageination::setTable', $tagVecs, $embed); // → 'database' (probably) +echo bestTag('User::isAuthorized', $tagVecs, $embed); / → 'authentication' +echo bestTag('Pageination::setTable', $tagVecs, $embed); / → 'database' (probably) ``` ## Almacenamiento @@ -58,7 +58,7 @@ Las incrustaciones son arreglos de flotantes — generalmente 768 flotantes para Utiliza `Embed::pack()` para codificarlos en base64 como flotantes de 4 bytes: ```php -$compact = Embed::pack($vec); // ~4 KB → ~5.3 KB base64 string +$compact = Embed::pack($vec); / ~4 KB → ~5.3 KB base64 string $vec = Embed::unpack($compact); ``` El complemento RAG utiliza este formato internamente para sus archivos JSON. diff --git a/docs/src/content/docs/es/ai/module/overview.md b/docs/src/content/docs/es/ai/module/overview.md index 973e592..9cee227 100644 --- a/docs/src/content/docs/es/ai/module/overview.md +++ b/docs/src/content/docs/es/ai/module/overview.md @@ -57,7 +57,7 @@ echo $ai->chat()->ask('Explain MMVC in two sentences.'); // Multi-turn $chat = $ai->chat(); $chat->user('How do I scaffold a module?'); -$chat->user('And add Graylog hooks?'); // referrs to previous turn +$chat->user('And add Graylog hooks?'); / referrs to previous turn echo $chat->complete(); // Override per call @@ -80,7 +80,7 @@ $score = \Nibiru\Module\Ai\Plugin\Embed::cosine($va, $vb); ``` Almacenamiento compacto: ```php -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string, 4 bytes/dim +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string, 4 bytes/dim $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); ``` ### 3. RAG — ingesta, recuperación, anclaje @@ -88,7 +88,7 @@ $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); $rag = $ai->rag('product-help'); // One-time ingestion -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); $rag->ingestFile('/var/data/manual.pdf.txt'); @@ -105,9 +105,9 @@ use Nibiru\Module\Ai\Plugin\Tools; $ai = new \Nibiru\Module\Ai\Ai(); $agent = $ai->agent()->withTools([ - new Tools\PdoQuery(), // read-only SQL - new Tools\HttpGet(), // fetch URLs - new Tools\FileRead(), // read project files + new Tools\PdoQuery(), / read-only SQL + new Tools\HttpGet(), / fetch URLs + new Tools\FileRead(), / read project files ]); echo $agent->run('How many active users registered last week?'); @@ -154,7 +154,7 @@ La filosofía de diseño: ## Siguiente -- [Referencia del complemento de chat](/es/ai/modulo/chat/) -- [Referencia del complemento RAG](/es/ai/modulo/rag/) -- [Referencia del complemento de agente](/es/ai/modulo/agent/) -- [Entrenamiento nibiru-coder](/es/ai/modulo/training/) +- [Referencia del complemento de chat](/es/ai/module/chat/) +- [Referencia del complemento RAG](/es/ai/module/rag/) +- [Referencia del complemento de agente](/es/ai/module/agent/) +- [Entrenamiento nibiru-coder](/es/ai/module/training/) diff --git a/docs/src/content/docs/es/ai/module/rag.md b/docs/src/content/docs/es/ai/module/rag.md index a3d85be..8aa3a22 100644 --- a/docs/src/content/docs/es/ai/module/rag.md +++ b/docs/src/content/docs/es/ai/module/rag.md @@ -10,9 +10,9 @@ El complemento RAG es la característica clave del módulo de IA para los constr use Nibiru\Module\Ai\Ai; $ai = new Ai(); -$rag = $ai->rag('product-help'); // a named collection +$rag = $ai->rag('product-help'); / a named collection -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php under help/ +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php under help/ $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); echo $rag->ask('How do I cancel my subscription?'); @@ -46,20 +46,20 @@ $logs->ingestText($exception->__toString(), ['ts' => time()]); ``` ## Referencia de la API ```php -$rag = $ai->rag('name'); // get/create a named collection +$rag = $ai->rag('name'); / get/create a named collection // --- Ingestion --- -$rag->ingestText($text, $metadata = []); // single chunk -$count = $rag->ingestFile('path'); // returns chunks added -$count = $rag->ingestDir('dir', ['md','txt','php']); // recursive +$rag->ingestText($text, $metadata = []); / single chunk +$count = $rag->ingestFile('path'); / returns chunks added +$count = $rag->ingestDir('dir', ['md','txt','php']); / recursive // --- Querying --- -$hits = $rag->search('query', $k = null); // [{score, text, metadata}, …] -$answer = $rag->ask('question', $k = null); // top-K → chat call +$hits = $rag->search('query', $k = null); / [{score, text, metadata}, …] +$answer = $rag->ask('question', $k = null); / top-K → chat call // --- Maintenance --- -$rag->reset(); // forget everything (deletes file) -$n = $rag->size(); // number of chunks +$rag->reset(); / forget everything (deletes file) +$n = $rag->size(); / number of chunks ``` ## Perillas de ajuste @@ -95,5 +95,5 @@ rag.storage_path = "/../../application/module/ai/cache/rag/" ## ¿Qué sigue? -- [Plugin de agente →](/es/ai/modulo/agente/) para herramientas, no recuperación. -- [Entrenamiento nibiru-coder →](/es/ai/modulo/entrenamiento/) para que el chat responda a la mitad en voz del marco. +- [Plugin de agente →](/es/ai/module/agent/) para herramientas, no recuperación. +- [Entrenamiento nibiru-coder →](/es/ai/module/training/) para que el chat responda a la mitad en voz del marco. diff --git a/docs/src/content/docs/es/core/auth.md b/docs/src/content/docs/es/core/auth.md index 53ad31e..7892b44 100644 --- a/docs/src/content/docs/es/core/auth.md +++ b/docs/src/content/docs/es/core/auth.md @@ -114,7 +114,7 @@ public function pageAction() { View::forwardTo('/login'); return; } - // ... + / ... } ``` Para las verificaciones basadas en roles, las aplicaciones de demostración utilizan el complemento `Acl` del mismo módulo: @@ -178,7 +178,7 @@ public function submitAction() { http_response_code(419); return; } - // ...handle submission... + / ...handle submission... } ``` Incorpore `` en su formulario. diff --git a/docs/src/content/docs/es/core/config.md b/docs/src/content/docs/es/core/config.md index 3fe99c3..ffbe37c 100644 --- a/docs/src/content/docs/es/core/config.md +++ b/docs/src/content/docs/es/core/config.md @@ -82,19 +82,19 @@ password_hash = "another-salt-for-AES_DECRYPT" ## Leyendo la configuración ```php $cfg = \Nibiru\Config::getInstance()->getConfig(); -$cfg['DATABASE']['driver']; // 'pdo' -$cfg['SETTINGS']['page.url']; // 'https://my-app.local' +$cfg['DATABASE']['driver']; / 'pdo' +$cfg['SETTINGS']['page.url']; / 'https://my-app.local' ``` Para configuraciones profundamente anidadas, utilice las constantes tipadas de la interfaz View: ```php -$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; // ['/public/css/app.css'] +$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; / ['/public/css/app.css'] ``` ## Configuraciones del módulo Cada módulo bajo `application/module//settings/` puede llevar sus propios archivos INI. El Registro los detecta automáticamente y los expone a través de: ```php $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$users->session_lifetime; // from [USERS] section in users.ini +$users->session_lifetime; / from [USERS] section in users.ini ``` El Registro prefiere `..ini` sobre `.ini`, por lo que obtienes anulaciones por entorno de forma gratuita. diff --git a/docs/src/content/docs/es/core/controllers.md b/docs/src/content/docs/es/core/controllers.md index 0215176..dd6638c 100644 --- a/docs/src/content/docs/es/core/controllers.md +++ b/docs/src/content/docs/es/core/controllers.md @@ -56,12 +56,12 @@ View::assign(['products' => $list]); ``` Ayudantes de conveniencia del controlador base: ```php -$this->getRequest('id', false); // $_REQUEST['id'] ?? false -$this->getPost('email', ''); // $_POST['email'] ?? '' -$this->getGet('page', 1); // $_GET['page'] ?? 1 -$this->getServer('REQUEST_URI'); // $_SERVER['REQUEST_URI'] -$this->getFiles('upload'); // $_FILES['upload'] -$this->getSession('auth'); // $_SESSION['auth'] +$this->getRequest('id', false); / $_REQUEST['id'] ?? false +$this->getPost('email', ''); / $_POST['email'] ?? '' +$this->getGet('page', 1); / $_GET['page'] ?? 1 +$this->getServer('REQUEST_URI'); / $_SERVER['REQUEST_URI'] +$this->getFiles('upload'); / $_FILES['upload'] +$this->getSession('auth'); / $_SESSION['auth'] ``` Estos existen porque `Controller` es amigable con `final`: puedes simularlos en pruebas sustituyendo una clase hija. @@ -69,8 +69,8 @@ Estos existen porque `Controller` es amigable con `final`: puedes simularlos en Para redirigir dentro de una acción: ```php -View::forwardTo('/login'); // 302 to the URL, exits -View::forwardToJsonHeader(); // sets Content-Type: application/json +View::forwardTo('/login'); / 302 to the URL, exits +View::forwardToJsonHeader(); / sets Content-Type: application/json ``` `forwardToJsonHeader()` es el patrón canónico para puntos finales JSON — establece la cabecera, asigna `data`, y devuelve. La capa de vista se encarga del resto. diff --git a/docs/src/content/docs/es/core/dispatcher.md b/docs/src/content/docs/es/core/dispatcher.md index 228e867..3eef9c5 100644 --- a/docs/src/content/docs/es/core/dispatcher.md +++ b/docs/src/content/docs/es/core/dispatcher.md @@ -30,17 +30,17 @@ public function run() { if (Config::getInstance()->getConfig() [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) { - new Model(false); // 1. (re)generate models from schema + new Model(false); / 1. (re)generate models from schema } - Router::getInstance()->route(); // 2. parse the URL - Auto::loader()->loadModelFiles(); // 3. load model files - Auto::loader()->loadModules(); // 4. load module classes + Router::getInstance()->route(); / 2. parse the URL + Auto::loader()->loadModelFiles(); / 3. load model files + Auto::loader()->loadModules(); / 4. load module classes $tpl = Router::getInstance()->tplName(); $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php"; - if (is_file($controllerFile)) { // 5. controller file exists + if (is_file($controllerFile)) { / 5. controller file exists require_once $controllerFile; $class = "Nibiru\\{$tpl}Controller"; $controller = new $class(); @@ -49,7 +49,7 @@ public function run() { $action = $_REQUEST['_action'] . 'Action'; $controller->navigationAction(); if (method_exists($controller, $action)) { - $controller->$action(); // 6. optional named action + $controller->$action(); / 6. optional named action } $controller->pageAction(); } else { @@ -57,9 +57,9 @@ public function run() { $controller->pageAction(); } - Display::getInstance()->display(); // 7. render Smarty + Display::getInstance()->display(); / 7. render Smarty } else { - // 8. soft 404 — render the configured error controller + / 8. soft 404 — render the configured error controller } } ``` diff --git a/docs/src/content/docs/es/core/forms.md b/docs/src/content/docs/es/core/forms.md index 7846f3d..d81f2ed 100644 --- a/docs/src/content/docs/es/core/forms.md +++ b/docs/src/content/docs/es/core/forms.md @@ -40,8 +40,8 @@ addOpenSpan addCloseSpan ``` ### Ciclo de vida ``` -create // reset the static buffer; call before building a new form -addForm // wrap the buffer in
...
and return as a string +create / reset the static buffer; call before building a new form +addForm / wrap the buffer in
...
and return as a string ``` :::caution[La inconsistencia de nombres es intencional, más bien] `addInputTypePassword` vs `addTypePassword`, `addInputTypeFileupload` vs `addTypeFileUpload` — el prefijo coincide si el elemento es un `` (prefijo Input) o alguna otra etiqueta (prefijo Type). Es incómodo pero estable; la CLI de `./nibiru -c` usa el mismo patrón, por lo que la memoria muscular funciona. @@ -50,7 +50,7 @@ addForm // wrap the buffer in
...
and return as a string ```php use Nibiru\Factory\Form; -Form::create(); // reset the static buffer +Form::create(); / reset the static buffer Form::addOpenDiv(['class' => 'form-group']); Form::addTypeLabel(['for' => 'login', 'value' => 'Username']); @@ -186,7 +186,7 @@ class formsController extends Controller { 'required' => 'required', 'class' => 'contacts-input form-control', ]); - // ...more fields... + / ...more fields... $this->form = Form::addForm([ 'name' => 'newregister', 'method' => 'post', diff --git a/docs/src/content/docs/es/core/modules.md b/docs/src/content/docs/es/core/modules.md index 2b3aaad..8d8293d 100644 --- a/docs/src/content/docs/es/core/modules.md +++ b/docs/src/content/docs/es/core/modules.md @@ -147,9 +147,9 @@ allowed.roles[] = "standard" Léelo desde cualquier lugar: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$cfg->session_lifetime; // 7200 -$cfg->password_min_length; // 12 -$cfg->allowed_roles; // [admin, editor, standard] +$cfg->session_lifetime; / 7200 +$cfg->password_min_length; / 12 +$cfg->allowed_roles; / [admin, editor, standard] ``` Capas de entorno: un archivo llamado `users.production.ini` se prefiere sobre `users.ini` cuando `APPLICATION_ENV=production`. @@ -162,7 +162,7 @@ $analytics = new \Nibiru\Module\Analytics\Analytics(); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Matomo()); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Plausible()); -$analytics->trackPageView(); // internally calls notify() +$analytics->trackPageView(); / internally calls notify() ``` Cada observador recibe la instancia de análisis en su método `update($subject)` y extrae los datos del evento que le interesan. @@ -200,7 +200,7 @@ Los nombres son **nombres de carpetas en minúsculas**, exactamente como aparece Las clases de plugin residen bajo el espacio de nombres **plural** `Plugins`: ```php // application/module/billing/plugins/invoice.php -namespace Nibiru\Module\Billing\Plugins; // ← plural +namespace Nibiru\Module\Billing\Plugins; / ← plural class Invoice extends \Nibiru\Module\Billing\Billing { /* ... */ } ``` Desacuerda el espacio de nombres y obtendrás fallos en la carga automática. La plantilla de la CLI (`./nibiru -m billing`) genera el espacio de nombres correcto para ti. @@ -210,7 +210,7 @@ Desacuerda el espacio de nombres y obtendrás fallos en la carga automática. La No **registras** los archivos INI de tu módulo — el [Registro](/es/core/registry/) los descubre automáticamente recorriendo `application/module//settings/*.ini` después de que `[AUTOLOADER]` carga la clase del módulo. Cada sección `[]` (en mayúsculas) de un INI se vuelve disponible como: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('billing'); -$cfg->invoice_prefix; // [BILLING] invoice.prefix → property +$cfg->invoice_prefix; / [BILLING] invoice.prefix → property ``` El Registro prefiere `..ini` (por ejemplo, `facturación.producción.ini`) cuando `APPLICATION_ENV` coincide. diff --git a/docs/src/content/docs/es/core/pagination.md b/docs/src/content/docs/es/core/pagination.md index ca6d864..fdeaa8a 100644 --- a/docs/src/content/docs/es/core/pagination.md +++ b/docs/src/content/docs/es/core/pagination.md @@ -14,7 +14,7 @@ class productsController extends Controller { public function pageAction() { $products = new products(); - Pageination::setEntriesPerPage(25); // optional; default from INI + Pageination::setEntriesPerPage(25); / optional; default from INI Pageination::setTable($products); $rows = Pageination::loadTableAsArray(); diff --git a/docs/src/content/docs/es/core/registry.md b/docs/src/content/docs/es/core/registry.md index 886e7ae..7649052 100644 --- a/docs/src/content/docs/es/core/registry.md +++ b/docs/src/content/docs/es/core/registry.md @@ -20,7 +20,7 @@ Para cada módulo bajo `application/module//settings/`: $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); $users->session_lifetime; $users->password_min_length; -$users->allowed_roles; // array +$users->allowed_roles; / array ``` Dentro del módulo mismo, la convención es envolver esto en un setter: ```php diff --git a/docs/src/content/docs/es/core/routing.md b/docs/src/content/docs/es/core/routing.md index 8b85b25..a39496c 100644 --- a/docs/src/content/docs/es/core/routing.md +++ b/docs/src/content/docs/es/core/routing.md @@ -40,7 +40,7 @@ Cualquier cosa después del segmento de acción se convierte en una clave `$_REQ // /users/edit/42 → $_REQUEST['id'] = '42' public function editAction() { $id = (int) ($_REQUEST['id'] ?? 0); - // ... + / ... } ``` Para parámetros no numéricos o nombrados, prefiera cadenas de consulta: @@ -62,9 +62,9 @@ Cuando una URL coincide con el patrón, los grupos capturados se asignan a las c ## Ayudantes de enrutamiento ```php -Router::getInstance()->currentPage(); // 'products' -Router::getInstance()->tplName(); // 'products' (controller stem for templates) -Router::getInstance()->getController(); // alias for currentPage() +Router::getInstance()->currentPage(); / 'products' +Router::getInstance()->tplName(); / 'products' (controller stem for templates) +Router::getInstance()->getController(); / alias for currentPage() ``` Estos son útiles dentro de los controladores y plantillas: ```smarty diff --git a/docs/src/content/docs/es/design/components.md b/docs/src/content/docs/es/design/components.md index 25d27bb..c54bfe5 100644 --- a/docs/src/content/docs/es/design/components.md +++ b/docs/src/content/docs/es/design/components.md @@ -7,7 +7,7 @@ description: "Botones, tarjetas, llamadas a la acción, héroe — listos para c Un rectángulo negro sobre crema. Editorial. Sin gradiente, sin brillo. ```html - + Read the docs @@ -162,7 +162,7 @@ Cuadrícula asimétrica de dos columnas. Un número editorial grande detrás del Nibiru is a modular PHP framework for builders who ship.

diff --git a/docs/src/content/docs/es/design/overview.md b/docs/src/content/docs/es/design/overview.md index 3420622..c954717 100644 --- a/docs/src/content/docs/es/design/overview.md +++ b/docs/src/content/docs/es/design/overview.md @@ -48,7 +48,7 @@ Eso es suficiente para estar en marca. ## ¿Qué se documenta aquí? -- [Paleta](/es/diseno/paleta/) — cada color con su rol. -- [Tipografía](/es/diseno/tipografia/) — los ejes variables de Bricolage utilizados en serio. -- [Componentes](/es/diseno/componentes/) — botones, tarjetas, llamadas a la atención, el lanzador Oracle. -- [Movimiento](/es/diseno/movimiento/) — respirar, desvanecerse, sin flash. +- [Paleta](/es/design/palette/) — cada color con su rol. +- [Tipografía](/es/design/typography/) — los ejes variables de Bricolage utilizados en serio. +- [Componentes](/es/design/components/) — botones, tarjetas, llamadas a la atención, el lanzador Oracle. +- [Movimiento](/es/design/motion/) — respirar, desvanecerse, sin flash. diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index bd25094..ac28b93 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -19,73 +19,25 @@ hero: variant: minimal --- -import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; +import CometTrail from '../../../components/CometTrail.astro'; +import MmvcStage from '../../../components/MmvcStage.astro'; +import MissionControl from '../../../components/MissionControl.astro'; +import LaunchSequence from '../../../components/LaunchSequence.astro'; +import SpacecraftGrid from '../../../components/SpacecraftGrid.astro'; +import EditorialContent from '../../../components/EditorialContent.astro'; +import LandingFooter from '../../../components/LandingFooter.astro'; +import ToTop from '../../../components/ToTop.astro'; +import LandingScripts from '../../../components/LandingScripts.astro'; -## Una constelación de capacidades + + + + + + + + - - - Los módulos envuelven MVC con traits, plugins, interfaces y configuraciones. La segunda **M** está acoplada de forma flexible, con el patrón observador `SplSubject` integrado. - - - Cinco controladores en órbita: `mysql`, `pdo`, `postgres` (ODBC), `psql` (libpq) y `postgresql`. Cambia con solo modificar una clave INI. - - - Vistas dirigidas por plantillas, un ayudante global `View::assign()` y una caché caliente en `templates_c`. Más parciales compartidos, includes de navegación y plantillas de paginación. - - - Más de 28 tipos de campo — text, password, switch, color, range, file upload — compuestos mediante llamadas estáticas a `Form::add…` y renderizados como un único string HTML. - - - `./nibiru` genera módulos, controladores, plugins, migraciones y páginas CMS. Ejecuta migraciones contra `local`, `staging` o `production`. - - - Nibiru se está convirtiendo en el primer framework PHP con un Oráculo basado en RAG entrenado con su propio conocimiento — y un corpus publicado para futuros fine-tunes. - - - -## Inicio rápido - -```bash -# Clonar -git clone https://github.com/alllinux/Nibiru mi-app && cd mi-app - -# Instalar dependencias PHP (Smarty, PHPMailer, Guzzle, …) -composer install - -# Permisos + arranque de carpetas -./nibiru -s - -# Ejecutar la primera migración -./nibiru -mi local - -# Generar un controlador -./nibiru -c products -``` - -```php -// application/controller/productsController.php -namespace Nibiru; -use Nibiru\Adapter\Controller; - -class productsController extends Controller { - public function pageAction() { - View::assign([ - 'title' => 'Productos — Nibiru', - 'products' => [['id' => 1, 'name' => 'Recubrimiento de Oro Marduk']], - ]); - } - public function navigationAction() { - JsonNavigation::getInstance()->loadJsonNavigationArray(); - } -} -``` - -## A dónde ir después - - - - - - - +{/* Loads three.js + the original mockup scene code. MUST be the last node so + every #id the scene targets exists in the DOM when the script runs. */} + diff --git a/docs/src/content/docs/es/showcase/patterns.md b/docs/src/content/docs/es/showcase/patterns.md index 44d96de..472e279 100644 --- a/docs/src/content/docs/es/showcase/patterns.md +++ b/docs/src/content/docs/es/showcase/patterns.md @@ -61,7 +61,7 @@ Varios rastreadores sin acoplamiento con el controlador. $analytics = new Analytics(); $analytics->attach(new Plugin\Matomo()); $analytics->attach(new Plugin\Plausible()); -$analytics->trackPageView(); // calls notify() internally +$analytics->trackPageView(); / calls notify() internally ``` Cada observador extrae solo los campos que le interesan con su `update($subject)`. Agregar un rastreador es un cambio de una línea. diff --git a/docs/src/content/docs/es/showcase/projects.md b/docs/src/content/docs/es/showcase/projects.md index b2c9311..8252091 100644 --- a/docs/src/content/docs/es/showcase/projects.md +++ b/docs/src/content/docs/es/showcase/projects.md @@ -55,7 +55,7 @@ public function detailAction() try { $machine = Machine::init()->getMachine((int) $machineId); } catch (\Throwable $e) { - $machine = null; // DB blip → page still renders with fallback. + $machine = null; / DB blip → page still renders with fallback. } $machineName = $machine['ms_machines_name'] ?? "Maschine #$machineId"; @@ -110,7 +110,7 @@ Inserta una nueva plantilla Smarty en el sistema, el editor sabe de inmediato cu ## ¿Qué realmente es especial, resumido? -Los cinco diferenciadores a continuación se extraen de los códigos fuente anteriores. Cada uno enlaza a su evidencia en la página [¿Por qué Nibiru](/es/por-que-nibiru/). +Los cinco diferenciadores a continuación se extraen de los códigos fuente anteriores. Cada uno enlaza a su evidencia en la página [¿Por qué Nibiru](/es/why-nibiru/). | | ¿Qué hace Nibiru? | ¿Qué hace Laravel/Symfony? | |---|---|---| @@ -120,7 +120,7 @@ Los cinco diferenciadores a continuación se extraen de los códigos fuente ante | Auth | 3 líneas en el constructor del controlador. | Pila de middleware + clases de política + portales. | | Eventos | `SplSubject` + `SplObserver` de la librería estándar de PHP. | Despachador de eventos personalizado + registro de oyentes + cola. | -Lee la [desglose completa con referencias de código →](/es/porque-nibiru/) +Lee la [desglose completa con referencias de código →](/es/why-nibiru/) --- diff --git a/docs/src/content/docs/es/why-nibiru.md b/docs/src/content/docs/es/why-nibiru.md index 97978ec..2cc5824 100644 --- a/docs/src/content/docs/es/why-nibiru.md +++ b/docs/src/content/docs/es/why-nibiru.md @@ -50,7 +50,7 @@ class Cms implements Interfaces\Cms, SplSubject use Traits\PageBuilderForm; use Traits\CmsPageStructureModifier; use Traits\FormElements; - // …8 more traits + / …8 more traits } ``` **Efecto neto**: cero inyección de constructores, cero registro de proveedores de servicios, cero llamadas a `bind()` / `singleton()` en un archivo de configuración. Un nuevo desarrollador puede buscar el nombre del trait y ver todos los llamadores. @@ -108,7 +108,7 @@ El controlador de la API toma un enfoque inverso: una lista blanca de puntos fin ```php // public endpoints can be listed up-front, auth wraps the rest. if (in_array($action, ['category', 'machines', 'ollama', 'team'])) { - // public, skip auth + / public, skip auth } else { $this->user = new User(); $this->acl = new Acl(); @@ -137,8 +137,8 @@ class Machineryscout implements IModule, \SplSubject } public function indexMachines(): void { - // …do the work… - $this->notify(); // analytics, cache invalidator, audit log all see it. + / …do the work… + $this->notify(); / analytics, cache invalidator, audit log all see it. } } ``` @@ -154,4 +154,4 @@ Un desarrollador solitario o un pequeño equipo puede construir y *operar* una a Si prefieres ver tu código, tómalo. -→ [Lee la presentación →](/es/presentacion/proyectos/) +→ [Lee la presentación →](/es/showcase/projects/) diff --git a/docs/src/content/docs/fr/ai/corpus.md b/docs/src/content/docs/fr/ai/corpus.md index e881871..310aa06 100644 --- a/docs/src/content/docs/fr/ai/corpus.md +++ b/docs/src/content/docs/fr/ai/corpus.md @@ -60,7 +60,7 @@ Blocs bruts à utiliser comme données de récupération RAG : "content": "Modules implementing `SplSubject` can broadcast events…" } ``` -Ceci est exactement le fichier que l'[Oracle](/ai/oracle/) utilise en interne. +Ceci est exactement le fichier que l'[Oracle](/fr/ai/oracle/) utilise en interne. ## Comment les morceaux sont dérivés diff --git a/docs/src/content/docs/fr/ai/module/chat.md b/docs/src/content/docs/fr/ai/module/chat.md index 5006a55..c210c4d 100644 --- a/docs/src/content/docs/fr/ai/module/chat.md +++ b/docs/src/content/docs/fr/ai/module/chat.md @@ -10,19 +10,19 @@ Le plugin de chat est la pièce la plus simple du module IA. Il encapsule l'API $ai = new \Nibiru\Module\Ai\Ai(); $chat = $ai->chat(); -$chat->system('Be terse.'); // optional system prompt -$chat->model('qwen2.5-coder:14b'); // override the configured model -$chat->temperature(0.2); // override config -$chat->maxTokens(512); // override config +$chat->system('Be terse.'); / optional system prompt +$chat->model('qwen2.5-coder:14b'); / override the configured model +$chat->temperature(0.2); / override config +$chat->maxTokens(512); / override config -$chat->user('Hello'); // append a user message -$chat->assistant('Hi.'); // append an assistant message (rare) +$chat->user('Hello'); / append a user message +$chat->assistant('Hi.'); / append an assistant message (rare) -$reply = $chat->complete(); // run the call, return text -$reply = $chat->ask('How are you?'); // = ->user(...)->complete() +$reply = $chat->complete(); / run the call, return text +$reply = $chat->ask('How are you?'); / = ->user(...)->complete() -$chat->reset(); // clear messages, keep model + system -$chat->history(); // [{role, content}, …] +$chat->reset(); / clear messages, keep model + system +$chat->history(); / [{role, content}, …] ``` ## Un coup unique ```php @@ -35,10 +35,10 @@ echo (new \Nibiru\Module\Ai\Ai()) $chat = $ai->chat(); $chat->user('Name three Nibiru singletons.'); -$singletons = $chat->complete(); // appended to history +$singletons = $chat->complete(); / appended to history $chat->user('What does the second one do?'); -$detail = $chat->complete(); // model has full context +$detail = $chat->complete(); / model has full context ``` ## Remplacement du modèle et du style par appel ```php diff --git a/docs/src/content/docs/fr/ai/module/embed.md b/docs/src/content/docs/fr/ai/module/embed.md index 3c78ed8..881a1df 100644 --- a/docs/src/content/docs/fr/ai/module/embed.md +++ b/docs/src/content/docs/fr/ai/module/embed.md @@ -9,12 +9,12 @@ Le plugin Embed est un simple wrapper autour de `/api/embeddings` d'Ollama, plus ```php $embed = (new \Nibiru\Module\Ai\Ai())->embed(); -$vec = $embed->one('controller'); // float[] -$vectors = $embed->batch(['a', 'b', 'c']); // float[][] +$vec = $embed->one('controller'); / float[] +$vectors = $embed->batch(['a', 'b', 'c']); / float[][] -$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); // 0..1 -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string -$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); // back to float[] +$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); / 0..1 +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string +$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); / back to float[] ``` ## Modèle : dédoublonner des chaînes similaires ```php @@ -49,8 +49,8 @@ function bestTag(string $text, array $tagVecs, $embed): string { return $best[0]; } -echo bestTag('User::isAuthorized', $tagVecs, $embed); // → 'authentication' -echo bestTag('Pageination::setTable', $tagVecs, $embed); // → 'database' (probably) +echo bestTag('User::isAuthorized', $tagVecs, $embed); / → 'authentication' +echo bestTag('Pageination::setTable', $tagVecs, $embed); / → 'database' (probably) ``` ## Stockage @@ -58,7 +58,7 @@ Les embeddings sont des tableaux de flottants — généralement 768 flottants p Utilisez `Embed::pack()` pour les encoder en base64 comme des flottants sur 4 octets : ```php -$compact = Embed::pack($vec); // ~4 KB → ~5.3 KB base64 string +$compact = Embed::pack($vec); / ~4 KB → ~5.3 KB base64 string $vec = Embed::unpack($compact); ``` Le plugin RAG utilise ce format internalement pour ses fichiers JSON. diff --git a/docs/src/content/docs/fr/ai/module/overview.md b/docs/src/content/docs/fr/ai/module/overview.md index 3147252..46d9ffc 100644 --- a/docs/src/content/docs/fr/ai/module/overview.md +++ b/docs/src/content/docs/fr/ai/module/overview.md @@ -57,7 +57,7 @@ echo $ai->chat()->ask('Explain MMVC in two sentences.'); // Multi-turn $chat = $ai->chat(); $chat->user('How do I scaffold a module?'); -$chat->user('And add Graylog hooks?'); // referrs to previous turn +$chat->user('And add Graylog hooks?'); / referrs to previous turn echo $chat->complete(); // Override per call @@ -80,7 +80,7 @@ $score = \Nibiru\Module\Ai\Plugin\Embed::cosine($va, $vb); ``` Stockage compact : ```php -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string, 4 bytes/dim +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string, 4 bytes/dim $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); ``` ### 3. RAG — ingérer, récupérer, ancrer @@ -88,7 +88,7 @@ $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); $rag = $ai->rag('product-help'); // One-time ingestion -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); $rag->ingestFile('/var/data/manual.pdf.txt'); @@ -105,9 +105,9 @@ use Nibiru\Module\Ai\Plugin\Tools; $ai = new \Nibiru\Module\Ai\Ai(); $agent = $ai->agent()->withTools([ - new Tools\PdoQuery(), // read-only SQL - new Tools\HttpGet(), // fetch URLs - new Tools\FileRead(), // read project files + new Tools\PdoQuery(), / read-only SQL + new Tools\HttpGet(), / fetch URLs + new Tools\FileRead(), / read project files ]); echo $agent->run('How many active users registered last week?'); @@ -154,7 +154,7 @@ La philosophie de conception : ## Suivant -- [Référence du module de chat](/fr/ia/module/chat/) -- [Référence du module RAG](/fr/ia/module/rag/) -- [Référence du module agent](/fr/ia/module/agent/) -- [Formation nibiru-coder](/fr/ia/module/training/) +- [Référence du module de chat](/fr/ai/module/chat/) +- [Référence du module RAG](/fr/ai/module/rag/) +- [Référence du module agent](/fr/ai/module/agent/) +- [Formation nibiru-coder](/fr/ai/module/training/) diff --git a/docs/src/content/docs/fr/ai/module/rag.md b/docs/src/content/docs/fr/ai/module/rag.md index 5952408..62f9b47 100644 --- a/docs/src/content/docs/fr/ai/module/rag.md +++ b/docs/src/content/docs/fr/ai/module/rag.md @@ -10,9 +10,9 @@ Le plugin RAG est la fonctionnalité clé du module IA pour les constructeurs de use Nibiru\Module\Ai\Ai; $ai = new Ai(); -$rag = $ai->rag('product-help'); // a named collection +$rag = $ai->rag('product-help'); / a named collection -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php under help/ +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php under help/ $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); echo $rag->ask('How do I cancel my subscription?'); @@ -46,20 +46,20 @@ $logs->ingestText($exception->__toString(), ['ts' => time()]); ``` ## Référence de l'API ```php -$rag = $ai->rag('name'); // get/create a named collection +$rag = $ai->rag('name'); / get/create a named collection // --- Ingestion --- -$rag->ingestText($text, $metadata = []); // single chunk -$count = $rag->ingestFile('path'); // returns chunks added -$count = $rag->ingestDir('dir', ['md','txt','php']); // recursive +$rag->ingestText($text, $metadata = []); / single chunk +$count = $rag->ingestFile('path'); / returns chunks added +$count = $rag->ingestDir('dir', ['md','txt','php']); / recursive // --- Querying --- -$hits = $rag->search('query', $k = null); // [{score, text, metadata}, …] -$answer = $rag->ask('question', $k = null); // top-K → chat call +$hits = $rag->search('query', $k = null); / [{score, text, metadata}, …] +$answer = $rag->ask('question', $k = null); / top-K → chat call // --- Maintenance --- -$rag->reset(); // forget everything (deletes file) -$n = $rag->size(); // number of chunks +$rag->reset(); / forget everything (deletes file) +$n = $rag->size(); / number of chunks ``` ## Réglages @@ -95,5 +95,5 @@ rag.storage_path = "/../../application/module/ai/cache/rag/" ## ¿Qué sigue? -- [Plugin agent →](/fr/ia/module/agent/) pour les outils, pas la récupération. -- [Formation nibiru-coder →](/fr/ia/module/formation/) pour faire répondre le chat à moitié dans la voix du framework. +- [Plugin agent →](/fr/ai/module/agent/) pour les outils, pas la récupération. +- [Formation nibiru-coder →](/fr/ai/module/training/) pour faire répondre le chat à moitié dans la voix du framework. diff --git a/docs/src/content/docs/fr/core/auth.md b/docs/src/content/docs/fr/core/auth.md index 9f3e99f..a2f473b 100644 --- a/docs/src/content/docs/fr/core/auth.md +++ b/docs/src/content/docs/fr/core/auth.md @@ -114,7 +114,7 @@ public function pageAction() { View::forwardTo('/login'); return; } - // ... + / ... } ``` Pour les vérifications basées sur le rôle, les applications de démonstration utilisent le plugin `Acl` du même module : @@ -178,7 +178,7 @@ public function submitAction() { http_response_code(419); return; } - // ...handle submission... + / ...handle submission... } ``` Intégrez `` dans votre formulaire. diff --git a/docs/src/content/docs/fr/core/config.md b/docs/src/content/docs/fr/core/config.md index 205da36..0cd3bf5 100644 --- a/docs/src/content/docs/fr/core/config.md +++ b/docs/src/content/docs/fr/core/config.md @@ -82,19 +82,19 @@ password_hash = "another-salt-for-AES_DECRYPT" ## Lecture des configurations ```php $cfg = \Nibiru\Config::getInstance()->getConfig(); -$cfg['DATABASE']['driver']; // 'pdo' -$cfg['SETTINGS']['page.url']; // 'https://my-app.local' +$cfg['DATABASE']['driver']; / 'pdo' +$cfg['SETTINGS']['page.url']; / 'https://my-app.local' ``` Pour les configurations profondément imbriquées, utilisez les constantes typées de l'interface View : ```php -$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; // ['/public/css/app.css'] +$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; / ['/public/css/app.css'] ``` ## Configurations des modules Chaque module situé sous `application/module//settings/` peut posséder ses propres fichiers INI. Le Registre les détecte automatiquement et les expose via : ```php $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$users->session_lifetime; // from [USERS] section in users.ini +$users->session_lifetime; / from [USERS] section in users.ini ``` Le Registre préfère `..ini` par rapport à `.ini`, donc vous obtenez des remplacements par environnement gratuitement. diff --git a/docs/src/content/docs/fr/core/controllers.md b/docs/src/content/docs/fr/core/controllers.md index 6b010da..37bef86 100644 --- a/docs/src/content/docs/fr/core/controllers.md +++ b/docs/src/content/docs/fr/core/controllers.md @@ -56,12 +56,12 @@ View::assign(['products' => $list]); ``` Aides pratiques du contrôleur de base : ```php -$this->getRequest('id', false); // $_REQUEST['id'] ?? false -$this->getPost('email', ''); // $_POST['email'] ?? '' -$this->getGet('page', 1); // $_GET['page'] ?? 1 -$this->getServer('REQUEST_URI'); // $_SERVER['REQUEST_URI'] -$this->getFiles('upload'); // $_FILES['upload'] -$this->getSession('auth'); // $_SESSION['auth'] +$this->getRequest('id', false); / $_REQUEST['id'] ?? false +$this->getPost('email', ''); / $_POST['email'] ?? '' +$this->getGet('page', 1); / $_GET['page'] ?? 1 +$this->getServer('REQUEST_URI'); / $_SERVER['REQUEST_URI'] +$this->getFiles('upload'); / $_FILES['upload'] +$this->getSession('auth'); / $_SESSION['auth'] ``` Ces éléments existent en raison du fait que `Controller` est compatible avec `final` : vous pouvez les simuler dans les tests en remplaçant par une classe enfant. @@ -69,8 +69,8 @@ Ces éléments existent en raison du fait que `Controller` est compatible avec ` Pour rediriger à l'intérieur d'une action : ```php -View::forwardTo('/login'); // 302 to the URL, exits -View::forwardToJsonHeader(); // sets Content-Type: application/json +View::forwardTo('/login'); / 302 to the URL, exits +View::forwardToJsonHeader(); / sets Content-Type: application/json ``` `forwardToJsonHeader()` est le modèle canonique pour les points de terminaison JSON — définissez l'en-tête, attribuez `data`, puis retournez. La couche d'affichage s'occupe du reste. diff --git a/docs/src/content/docs/fr/core/dispatcher.md b/docs/src/content/docs/fr/core/dispatcher.md index d26f6f9..916b25f 100644 --- a/docs/src/content/docs/fr/core/dispatcher.md +++ b/docs/src/content/docs/fr/core/dispatcher.md @@ -30,17 +30,17 @@ public function run() { if (Config::getInstance()->getConfig() [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) { - new Model(false); // 1. (re)generate models from schema + new Model(false); / 1. (re)generate models from schema } - Router::getInstance()->route(); // 2. parse the URL - Auto::loader()->loadModelFiles(); // 3. load model files - Auto::loader()->loadModules(); // 4. load module classes + Router::getInstance()->route(); / 2. parse the URL + Auto::loader()->loadModelFiles(); / 3. load model files + Auto::loader()->loadModules(); / 4. load module classes $tpl = Router::getInstance()->tplName(); $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php"; - if (is_file($controllerFile)) { // 5. controller file exists + if (is_file($controllerFile)) { / 5. controller file exists require_once $controllerFile; $class = "Nibiru\\{$tpl}Controller"; $controller = new $class(); @@ -49,7 +49,7 @@ public function run() { $action = $_REQUEST['_action'] . 'Action'; $controller->navigationAction(); if (method_exists($controller, $action)) { - $controller->$action(); // 6. optional named action + $controller->$action(); / 6. optional named action } $controller->pageAction(); } else { @@ -57,9 +57,9 @@ public function run() { $controller->pageAction(); } - Display::getInstance()->display(); // 7. render Smarty + Display::getInstance()->display(); / 7. render Smarty } else { - // 8. soft 404 — render the configured error controller + / 8. soft 404 — render the configured error controller } } ``` diff --git a/docs/src/content/docs/fr/core/forms.md b/docs/src/content/docs/fr/core/forms.md index bb3fdbd..fafe451 100644 --- a/docs/src/content/docs/fr/core/forms.md +++ b/docs/src/content/docs/fr/core/forms.md @@ -40,8 +40,8 @@ addOpenSpan addCloseSpan ``` ### Cycle de vie ``` -create // reset the static buffer; call before building a new form -addForm // wrap the buffer in
...
and return as a string +create / reset the static buffer; call before building a new form +addForm / wrap the buffer in
...
and return as a string ``` :::caution[L'incréance de nommage est intentionnelle, mais pas complètement] `addInputTypePassword` vs `addTypePassword`, `addInputTypeFileupload` vs `addTypeFileUpload` — le préfixe correspond à ce que l'élément soit un `` (préfixe Input) ou une autre balise (préfixe Type). C'est un peu inconfortable, mais stable ; les modèles de conception utilisés par la CLI `./nibiru -c` suivent le même modèle, donc l'habitude s'impose. @@ -51,7 +51,7 @@ addForm // wrap the buffer in
...
and return as a string ```php use Nibiru\Factory\Form; -Form::create(); // reset the static buffer +Form::create(); / reset the static buffer Form::addOpenDiv(['class' => 'form-group']); Form::addTypeLabel(['for' => 'login', 'value' => 'Username']); @@ -187,7 +187,7 @@ class formsController extends Controller { 'required' => 'required', 'class' => 'contacts-input form-control', ]); - // ...more fields... + / ...more fields... $this->form = Form::addForm([ 'name' => 'newregister', 'method' => 'post', diff --git a/docs/src/content/docs/fr/core/modules.md b/docs/src/content/docs/fr/core/modules.md index c04395f..69cb6b2 100644 --- a/docs/src/content/docs/fr/core/modules.md +++ b/docs/src/content/docs/fr/core/modules.md @@ -147,9 +147,9 @@ allowed.roles[] = "standard" Lisez-le à partir d'ailleurs : ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$cfg->session_lifetime; // 7200 -$cfg->password_min_length; // 12 -$cfg->allowed_roles; // [admin, editor, standard] +$cfg->session_lifetime; / 7200 +$cfg->password_min_length; / 12 +$cfg->allowed_roles; / [admin, editor, standard] ``` Superpositions d'environnement : un fichier nommé `users.production.ini` est préféré par rapport à `users.ini` lorsque `APPLICATION_ENV=production`. @@ -162,7 +162,7 @@ $analytics = new \Nibiru\Module\Analytics\Analytics(); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Matomo()); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Plausible()); -$analytics->trackPageView(); // internally calls notify() +$analytics->trackPageView(); / internally calls notify() ``` Chaque observateur reçoit l'instance d'analytics via sa méthode `update($subject)` et extrait les données d'événement dont il a besoin. @@ -200,7 +200,7 @@ Les noms sont des **noms de dossiers en minuscules**, exactement tels qu'ils app Les classes de plugin se trouvent dans l'espace de noms **pluriel** `Plugins`: ```php // application/module/billing/plugins/invoice.php -namespace Nibiru\Module\Billing\Plugins; // ← plural +namespace Nibiru\Module\Billing\Plugins; / ← plural class Invoice extends \Nibiru\Module\Billing\Billing { /* ... */ } ``` Ne correspondez pas à l'espace de noms et vous obtiendrez des manquements d'autoload. Le squelette CLI (`./nibiru -m billing`) génère l'espace de noms correct pour vous. @@ -210,7 +210,7 @@ Ne correspondez pas à l'espace de noms et vous obtiendrez des manquements d'aut Vous **ne** vous inscrivez pas les fichiers INI de votre module — le [Registry](/en/core/registry/) les découvre automatiquement en parcourant `application/module//settings/*.ini` après que `[AUTOLOADER]` a chargé la classe du module. Chaque section `[]` (en majuscules) d'un INI devient disponible comme : ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('billing'); -$cfg->invoice_prefix; // [BILLING] invoice.prefix → property +$cfg->invoice_prefix; / [BILLING] invoice.prefix → property ``` Le Registre préfère `..ini` (par exemple `billing.production.ini`) lorsque `APPLICATION_ENV` correspond. diff --git a/docs/src/content/docs/fr/core/pagination.md b/docs/src/content/docs/fr/core/pagination.md index 36d46f2..cb257fb 100644 --- a/docs/src/content/docs/fr/core/pagination.md +++ b/docs/src/content/docs/fr/core/pagination.md @@ -14,7 +14,7 @@ class productsController extends Controller { public function pageAction() { $products = new products(); - Pageination::setEntriesPerPage(25); // optional; default from INI + Pageination::setEntriesPerPage(25); / optional; default from INI Pageination::setTable($products); $rows = Pageination::loadTableAsArray(); diff --git a/docs/src/content/docs/fr/core/registry.md b/docs/src/content/docs/fr/core/registry.md index da5038b..cf1e9da 100644 --- a/docs/src/content/docs/fr/core/registry.md +++ b/docs/src/content/docs/fr/core/registry.md @@ -20,7 +20,7 @@ Pour chaque module sous `application/module//settings/` : $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); $users->session_lifetime; $users->password_min_length; -$users->allowed_roles; // array +$users->allowed_roles; / array ``` À l'intérieur du module lui-même, la convention est d'envelopper cela dans un mutateur : ```php diff --git a/docs/src/content/docs/fr/core/routing.md b/docs/src/content/docs/fr/core/routing.md index f0b7af9..5b6e1c2 100644 --- a/docs/src/content/docs/fr/core/routing.md +++ b/docs/src/content/docs/fr/core/routing.md @@ -40,7 +40,7 @@ Tout ce qui se trouve après le segment d'action devient une clé `$_REQUEST` pa // /users/edit/42 → $_REQUEST['id'] = '42' public function editAction() { $id = (int) ($_REQUEST['id'] ?? 0); - // ... + / ... } ``` Pour les paramètres non numériques ou nommés, privilégiez les chaînes de requête : @@ -62,9 +62,9 @@ Lorsqu'une URL correspond au modèle, les groupes capturés sont attribués aux ## Aide aux routages ```php -Router::getInstance()->currentPage(); // 'products' -Router::getInstance()->tplName(); // 'products' (controller stem for templates) -Router::getInstance()->getController(); // alias for currentPage() +Router::getInstance()->currentPage(); / 'products' +Router::getInstance()->tplName(); / 'products' (controller stem for templates) +Router::getInstance()->getController(); / alias for currentPage() ``` Ces éléments sont utiles dans les contrôleurs et les modèles : ```smarty diff --git a/docs/src/content/docs/fr/design/components.md b/docs/src/content/docs/fr/design/components.md index 0425c76..0c9fe73 100644 --- a/docs/src/content/docs/fr/design/components.md +++ b/docs/src/content/docs/fr/design/components.md @@ -7,7 +7,7 @@ description: "Boutons, cartes, appels à l’action, héros — prêts à être Un rectangle noir sur crème. Éditorial. Pas de dégradé, pas d'éclairage. ```html - + Read the docs @@ -162,7 +162,7 @@ Grille asymétrique à deux colonnes. Un grand numéro éditorial derrière le t Nibiru is a modular PHP framework for builders who ship.

diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index bd6add9..816bff3 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -19,73 +19,25 @@ hero: variant: minimal --- -import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; +import CometTrail from '../../../components/CometTrail.astro'; +import MmvcStage from '../../../components/MmvcStage.astro'; +import MissionControl from '../../../components/MissionControl.astro'; +import LaunchSequence from '../../../components/LaunchSequence.astro'; +import SpacecraftGrid from '../../../components/SpacecraftGrid.astro'; +import EditorialContent from '../../../components/EditorialContent.astro'; +import LandingFooter from '../../../components/LandingFooter.astro'; +import ToTop from '../../../components/ToTop.astro'; +import LandingScripts from '../../../components/LandingScripts.astro'; -## Une constellation de capacités + + + + + + + + - - - Les modules enveloppent le MVC avec traits, plugins, interfaces et paramètres. Le second **M** est faiblement couplé par conception, avec le pattern observer `SplSubject` intégré. - - - Cinq pilotes en orbite : `mysql`, `pdo`, `postgres` (ODBC), `psql` (libpq) et `postgresql`. Basculez en modifiant une seule clé INI. - - - Vues pilotées par templates, un assistant global `View::assign()`, et un cache chaud `templates_c`. Plus partiels partagés, includes de navigation et templates de pagination. - - - Plus de 28 types de champ — text, password, switch, color, range, file upload — composés via des appels statiques `Form::add…` et rendus en une seule chaîne HTML. - - - `./nibiru` génère modules, contrôleurs, plugins, migrations et pages CMS. Il exécute les migrations contre `local`, `staging` ou `production`. - - - Nibiru sera le premier framework PHP avec un Oracle basé sur RAG entraîné sur sa propre connaissance — et un corpus publié pour de futurs fine-tunes. - - - -## Démarrage rapide - -```bash -# Cloner -git clone https://github.com/alllinux/Nibiru mon-app && cd mon-app - -# Installer les dépendances PHP (Smarty, PHPMailer, Guzzle, …) -composer install - -# Permissions + amorçage des dossiers -./nibiru -s - -# Première migration -./nibiru -mi local - -# Générer un contrôleur -./nibiru -c products -``` - -```php -// application/controller/productsController.php -namespace Nibiru; -use Nibiru\Adapter\Controller; - -class productsController extends Controller { - public function pageAction() { - View::assign([ - 'title' => 'Produits — Nibiru', - 'products' => [['id' => 1, 'name' => 'Plaquage d\'or Marduk']], - ]); - } - public function navigationAction() { - JsonNavigation::getInstance()->loadJsonNavigationArray(); - } -} -``` - -## Où aller ensuite - - - - - - - +{/* Loads three.js + the original mockup scene code. MUST be the last node so + every #id the scene targets exists in the DOM when the script runs. */} + diff --git a/docs/src/content/docs/fr/showcase/patterns.md b/docs/src/content/docs/fr/showcase/patterns.md index 63f900d..65cff40 100644 --- a/docs/src/content/docs/fr/showcase/patterns.md +++ b/docs/src/content/docs/fr/showcase/patterns.md @@ -61,7 +61,7 @@ Plusieurs suivi sans couplage avec le contrôleur. $analytics = new Analytics(); $analytics->attach(new Plugin\Matomo()); $analytics->attach(new Plugin\Plausible()); -$analytics->trackPageView(); // calls notify() internally +$analytics->trackPageView(); / calls notify() internally ``` Chaque observateur appelle uniquement les champs dont il s'occupe avec sa méthode `update($subject)`. Ajouter un suivi est une modification d'une seule ligne. diff --git a/docs/src/content/docs/fr/showcase/projects.md b/docs/src/content/docs/fr/showcase/projects.md index 976fe04..43a3c75 100644 --- a/docs/src/content/docs/fr/showcase/projects.md +++ b/docs/src/content/docs/fr/showcase/projects.md @@ -55,7 +55,7 @@ public function detailAction() try { $machine = Machine::init()->getMachine((int) $machineId); } catch (\Throwable $e) { - $machine = null; // DB blip → page still renders with fallback. + $machine = null; / DB blip → page still renders with fallback. } $machineName = $machine['ms_machines_name'] ?? "Maschine #$machineId"; @@ -120,7 +120,7 @@ Les cinq différences ci-dessous sont tirées des bases de code ci-dessus. Chacu | Authentification | 3 lignes dans le constructeur du contrôleur. | Pile de middlewares + classes de politique + portails. | | Événements | `SplSubject` + `SplObserver` de la bibliothèque standard PHP. | Dispatcheur d'événements personnalisé + registre d'écouteurs + file d'attente. | -Lisez le [détail complet avec des références de code →](/fr/pourquoi-nibiru/) +Lisez le [détail complet avec des références de code →](/fr/why-nibiru/) --- diff --git a/docs/src/content/docs/fr/why-nibiru.md b/docs/src/content/docs/fr/why-nibiru.md index 91e468a..f8db021 100644 --- a/docs/src/content/docs/fr/why-nibiru.md +++ b/docs/src/content/docs/fr/why-nibiru.md @@ -50,7 +50,7 @@ class Cms implements Interfaces\Cms, SplSubject use Traits\PageBuilderForm; use Traits\CmsPageStructureModifier; use Traits\FormElements; - // …8 more traits + / …8 more traits } ``` **Effet net**: aucune injection de constructeur, aucune inscription auprès du fournisseur de services, aucun appel à `bind()` / `singleton()` dans un fichier de configuration. Un nouveau développeur peut rechercher le nom du trait et voir tous les appels. @@ -108,7 +108,7 @@ Le contrôleur API adopte une approche inverse : une liste blanche des points de ```php // public endpoints can be listed up-front, auth wraps the rest. if (in_array($action, ['category', 'machines', 'ollama', 'team'])) { - // public, skip auth + / public, skip auth } else { $this->user = new User(); $this->acl = new Acl(); @@ -137,8 +137,8 @@ class Machineryscout implements IModule, \SplSubject } public function indexMachines(): void { - // …do the work… - $this->notify(); // analytics, cache invalidator, audit log all see it. + / …do the work… + $this->notify(); / analytics, cache invalidator, audit log all see it. } } ``` @@ -154,4 +154,4 @@ Un développeur solo ou une petite équipe peut construire et *exploiter* une v Si vous préférez voir votre code, prenez-le. -→ [Lisez la présentation →](/fr/presentation/projets/) +→ [Lisez la présentation →](/fr/showcase/projects/) diff --git a/docs/src/content/docs/ja/ai/corpus.md b/docs/src/content/docs/ja/ai/corpus.md index d794c4d..d42bcec 100644 --- a/docs/src/content/docs/ja/ai/corpus.md +++ b/docs/src/content/docs/ja/ai/corpus.md @@ -60,7 +60,7 @@ OpenAIのfine-tune、AnthropicのAPI評価、ほとんどのLoRAツール(Axol "content": "Modules implementing `SplSubject` can broadcast events…" } ``` -これは[Oracle](/ai/oracle/)が内部で使用している正確なファイルです。 +これは[Oracle](/ja/ai/oracle/)が内部で使用している正確なファイルです。 ## チャンクの導出方法 diff --git a/docs/src/content/docs/ja/ai/module/chat.md b/docs/src/content/docs/ja/ai/module/chat.md index cfab395..f8f5925 100644 --- a/docs/src/content/docs/ja/ai/module/chat.md +++ b/docs/src/content/docs/ja/ai/module/chat.md @@ -10,19 +10,19 @@ description: "単一または複数のターンで行われる、任意のOllama $ai = new \Nibiru\Module\Ai\Ai(); $chat = $ai->chat(); -$chat->system('Be terse.'); // optional system prompt -$chat->model('qwen2.5-coder:14b'); // override the configured model -$chat->temperature(0.2); // override config -$chat->maxTokens(512); // override config +$chat->system('Be terse.'); / optional system prompt +$chat->model('qwen2.5-coder:14b'); / override the configured model +$chat->temperature(0.2); / override config +$chat->maxTokens(512); / override config -$chat->user('Hello'); // append a user message -$chat->assistant('Hi.'); // append an assistant message (rare) +$chat->user('Hello'); / append a user message +$chat->assistant('Hi.'); / append an assistant message (rare) -$reply = $chat->complete(); // run the call, return text -$reply = $chat->ask('How are you?'); // = ->user(...)->complete() +$reply = $chat->complete(); / run the call, return text +$reply = $chat->ask('How are you?'); / = ->user(...)->complete() -$chat->reset(); // clear messages, keep model + system -$chat->history(); // [{role, content}, …] +$chat->reset(); / clear messages, keep model + system +$chat->history(); / [{role, content}, …] ``` ## 一発 ```php @@ -35,10 +35,10 @@ echo (new \Nibiru\Module\Ai\Ai()) $chat = $ai->chat(); $chat->user('Name three Nibiru singletons.'); -$singletons = $chat->complete(); // appended to history +$singletons = $chat->complete(); / appended to history $chat->user('What does the second one do?'); -$detail = $chat->complete(); // model has full context +$detail = $chat->complete(); / model has full context ``` ## モデルとスタイルを個別呼び出しごとに上書きする ```php @@ -65,7 +65,7 @@ chat.provider = "anthropic" anthropic.api_key = "sk-ant-..." anthropic.model = "claude-haiku-4-5-20251001" ``` -チャットプラグインはまだフレームワークモジュールにAnthropicトランスポートを含んでいません — 現在、ドキュメントサイトの`scripts/lib/providers.mjs`パターンが参考となっています。([マイルストーン](/ja/ai/milestones/)をご覧ください。) +チャットプラグインはまだフレームワークモジュールにAnthropicトランスポートを含んでいません — 現在、ドキュメントサイトの`scripts/lib/providers.mjs`パターンが参考となっています。([マイルストーン](/ja/ai/roadmap/)をご覧ください。) ## 実践的なパターン: チャットをアクションとして ```php diff --git a/docs/src/content/docs/ja/ai/module/embed.md b/docs/src/content/docs/ja/ai/module/embed.md index 34217cc..5b2eb31 100644 --- a/docs/src/content/docs/ja/ai/module/embed.md +++ b/docs/src/content/docs/ja/ai/module/embed.md @@ -9,12 +9,12 @@ Embedプラグインは、Ollamaの`/api/embeddings`に薄いラッパーであ ```php $embed = (new \Nibiru\Module\Ai\Ai())->embed(); -$vec = $embed->one('controller'); // float[] -$vectors = $embed->batch(['a', 'b', 'c']); // float[][] +$vec = $embed->one('controller'); / float[] +$vectors = $embed->batch(['a', 'b', 'c']); / float[][] -$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); // 0..1 -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string -$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); // back to float[] +$score = \Nibiru\Module\Ai\Plugin\Embed::cosine($a, $b); / 0..1 +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string +$vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); / back to float[] ``` ## パターン: 遠近似の文字列を重複除去する ```php @@ -49,8 +49,8 @@ function bestTag(string $text, array $tagVecs, $embed): string { return $best[0]; } -echo bestTag('User::isAuthorized', $tagVecs, $embed); // → 'authentication' -echo bestTag('Pageination::setTable', $tagVecs, $embed); // → 'database' (probably) +echo bestTag('User::isAuthorized', $tagVecs, $embed); / → 'authentication' +echo bestTag('Pageination::setTable', $tagVecs, $embed); / → 'database' (probably) ``` ## ストレージ @@ -58,7 +58,7 @@ echo bestTag('Pageination::setTable', $tagVecs, $embed); // → 'database' (prob `Embed::pack()` を使用して、それらを 4 バイトの浮動小数点数として base64 エンコードします。 ```php -$compact = Embed::pack($vec); // ~4 KB → ~5.3 KB base64 string +$compact = Embed::pack($vec); / ~4 KB → ~5.3 KB base64 string $vec = Embed::unpack($compact); ``` RAG プラグインは、この形式を使用して内部の JSON ファイルを管理しています。 diff --git a/docs/src/content/docs/ja/ai/module/overview.md b/docs/src/content/docs/ja/ai/module/overview.md index d91c5fc..5f91ef2 100644 --- a/docs/src/content/docs/ja/ai/module/overview.md +++ b/docs/src/content/docs/ja/ai/module/overview.md @@ -57,7 +57,7 @@ echo $ai->chat()->ask('Explain MMVC in two sentences.'); // Multi-turn $chat = $ai->chat(); $chat->user('How do I scaffold a module?'); -$chat->user('And add Graylog hooks?'); // referrs to previous turn +$chat->user('And add Graylog hooks?'); / referrs to previous turn echo $chat->complete(); // Override per call @@ -80,7 +80,7 @@ $score = \Nibiru\Module\Ai\Plugin\Embed::cosine($va, $vb); ``` コンパクトなストレージ: ```php -$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); // base64 string, 4 bytes/dim +$packed = \Nibiru\Module\Ai\Plugin\Embed::pack($vec); / base64 string, 4 bytes/dim $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); ``` ### 3. RAG — 収集、検索、基準化 @@ -88,7 +88,7 @@ $vec = \Nibiru\Module\Ai\Plugin\Embed::unpack($packed); $rag = $ai->rag('product-help'); // One-time ingestion -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); $rag->ingestFile('/var/data/manual.pdf.txt'); @@ -105,9 +105,9 @@ use Nibiru\Module\Ai\Plugin\Tools; $ai = new \Nibiru\Module\Ai\Ai(); $agent = $ai->agent()->withTools([ - new Tools\PdoQuery(), // read-only SQL - new Tools\HttpGet(), // fetch URLs - new Tools\FileRead(), // read project files + new Tools\PdoQuery(), / read-only SQL + new Tools\HttpGet(), / fetch URLs + new Tools\FileRead(), / read project files ]); echo $agent->run('How many active users registered last week?'); diff --git a/docs/src/content/docs/ja/ai/module/rag.md b/docs/src/content/docs/ja/ai/module/rag.md index 7786163..1a90f24 100644 --- a/docs/src/content/docs/ja/ai/module/rag.md +++ b/docs/src/content/docs/ja/ai/module/rag.md @@ -10,9 +10,9 @@ RAG プラグインは、製品ビルダーにとって AI モジュールのキ use Nibiru\Module\Ai\Ai; $ai = new Ai(); -$rag = $ai->rag('product-help'); // a named collection +$rag = $ai->rag('product-help'); / a named collection -$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php under help/ +$rag->ingestDir(__DIR__ . '/help/'); / walks .md/.txt/.php under help/ $rag->ingestText('FAQ entry…', ['source' => 'faq-12']); echo $rag->ask('How do I cancel my subscription?'); @@ -46,20 +46,20 @@ $logs->ingestText($exception->__toString(), ['ts' => time()]); ``` ## API リファレンス ```php -$rag = $ai->rag('name'); // get/create a named collection +$rag = $ai->rag('name'); / get/create a named collection // --- Ingestion --- -$rag->ingestText($text, $metadata = []); // single chunk -$count = $rag->ingestFile('path'); // returns chunks added -$count = $rag->ingestDir('dir', ['md','txt','php']); // recursive +$rag->ingestText($text, $metadata = []); / single chunk +$count = $rag->ingestFile('path'); / returns chunks added +$count = $rag->ingestDir('dir', ['md','txt','php']); / recursive // --- Querying --- -$hits = $rag->search('query', $k = null); // [{score, text, metadata}, …] -$answer = $rag->ask('question', $k = null); // top-K → chat call +$hits = $rag->search('query', $k = null); / [{score, text, metadata}, …] +$answer = $rag->ask('question', $k = null); / top-K → chat call // --- Maintenance --- -$rag->reset(); // forget everything (deletes file) -$n = $rag->size(); // number of chunks +$rag->reset(); / forget everything (deletes file) +$n = $rag->size(); / number of chunks ``` ## チューニングの調整項目 diff --git a/docs/src/content/docs/ja/core/auth.md b/docs/src/content/docs/ja/core/auth.md index a480853..80f5bec 100644 --- a/docs/src/content/docs/ja/core/auth.md +++ b/docs/src/content/docs/ja/core/auth.md @@ -114,7 +114,7 @@ public function pageAction() { View::forwardTo('/login'); return; } - // ... + / ... } ``` ロール認識のチェックのために、デモンストレーションアプリケーションは同じモジュールから `Acl` プラグインを使用しています。 @@ -178,7 +178,7 @@ public function submitAction() { http_response_code(419); return; } - // ...handle submission... + / ...handle submission... } ``` フォームに `` を埋め込んでください。 diff --git a/docs/src/content/docs/ja/core/config.md b/docs/src/content/docs/ja/core/config.md index b91a0fb..861f672 100644 --- a/docs/src/content/docs/ja/core/config.md +++ b/docs/src/content/docs/ja/core/config.md @@ -82,19 +82,19 @@ password_hash = "another-salt-for-AES_DECRYPT" ## 設定の読み込み ```php $cfg = \Nibiru\Config::getInstance()->getConfig(); -$cfg['DATABASE']['driver']; // 'pdo' -$cfg['SETTINGS']['page.url']; // 'https://my-app.local' +$cfg['DATABASE']['driver']; / 'pdo' +$cfg['SETTINGS']['page.url']; / 'https://my-app.local' ``` 深くネストされた設定には、View インターフェースから型付けされた定数を使用してください。 ```php -$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; // ['/public/css/app.css'] +$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css']; / ['/public/css/app.css'] ``` ## モジュールの設定 各モジュールの `application/module//settings/` 以下には独自の INI ファイルを配置できます。Registry はそれらを自動的に取り込み、以下の通りに公開します: ```php $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$users->session_lifetime; // from [USERS] section in users.ini +$users->session_lifetime; / from [USERS] section in users.ini ``` レジストリは `..ini` を `.ini` よりも優先します。これにより、環境ごとのオーバーライドが無料で利用できます。 diff --git a/docs/src/content/docs/ja/core/controllers.md b/docs/src/content/docs/ja/core/controllers.md index e93e6a0..7852722 100644 --- a/docs/src/content/docs/ja/core/controllers.md +++ b/docs/src/content/docs/ja/core/controllers.md @@ -56,12 +56,12 @@ View::assign(['products' => $list]); ``` ベースコントローラーからの便利ヘルパー: ```php -$this->getRequest('id', false); // $_REQUEST['id'] ?? false -$this->getPost('email', ''); // $_POST['email'] ?? '' -$this->getGet('page', 1); // $_GET['page'] ?? 1 -$this->getServer('REQUEST_URI'); // $_SERVER['REQUEST_URI'] -$this->getFiles('upload'); // $_FILES['upload'] -$this->getSession('auth'); // $_SESSION['auth'] +$this->getRequest('id', false); / $_REQUEST['id'] ?? false +$this->getPost('email', ''); / $_POST['email'] ?? '' +$this->getGet('page', 1); / $_GET['page'] ?? 1 +$this->getServer('REQUEST_URI'); / $_SERVER['REQUEST_URI'] +$this->getFiles('upload'); / $_FILES['upload'] +$this->getSession('auth'); / $_SESSION['auth'] ``` これらは存在する理由は、`Controller`が`final`に耐えられるように設計されていることです:テストで子クラスを置き換えてモックすることができます。 @@ -69,8 +69,8 @@ $this->getSession('auth'); // $_SESSION['auth'] アクション内でリダイレクトするには: ```php -View::forwardTo('/login'); // 302 to the URL, exits -View::forwardToJsonHeader(); // sets Content-Type: application/json +View::forwardTo('/login'); / 302 to the URL, exits +View::forwardToJsonHeader(); / sets Content-Type: application/json ``` `forwardToJsonHeader()` は、JSON エンドポイントの標準的なパターンです。ヘッダーを設定し、`data` を割り当ててから返す。その後、表示層が残りの処理を行います。 diff --git a/docs/src/content/docs/ja/core/dispatcher.md b/docs/src/content/docs/ja/core/dispatcher.md index d185055..b442846 100644 --- a/docs/src/content/docs/ja/core/dispatcher.md +++ b/docs/src/content/docs/ja/core/dispatcher.md @@ -30,17 +30,17 @@ public function run() { if (Config::getInstance()->getConfig() [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) { - new Model(false); // 1. (re)generate models from schema + new Model(false); / 1. (re)generate models from schema } - Router::getInstance()->route(); // 2. parse the URL - Auto::loader()->loadModelFiles(); // 3. load model files - Auto::loader()->loadModules(); // 4. load module classes + Router::getInstance()->route(); / 2. parse the URL + Auto::loader()->loadModelFiles(); / 3. load model files + Auto::loader()->loadModules(); / 4. load module classes $tpl = Router::getInstance()->tplName(); $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php"; - if (is_file($controllerFile)) { // 5. controller file exists + if (is_file($controllerFile)) { / 5. controller file exists require_once $controllerFile; $class = "Nibiru\\{$tpl}Controller"; $controller = new $class(); @@ -49,7 +49,7 @@ public function run() { $action = $_REQUEST['_action'] . 'Action'; $controller->navigationAction(); if (method_exists($controller, $action)) { - $controller->$action(); // 6. optional named action + $controller->$action(); / 6. optional named action } $controller->pageAction(); } else { @@ -57,9 +57,9 @@ public function run() { $controller->pageAction(); } - Display::getInstance()->display(); // 7. render Smarty + Display::getInstance()->display(); / 7. render Smarty } else { - // 8. soft 404 — render the configured error controller + / 8. soft 404 — render the configured error controller } } ``` diff --git a/docs/src/content/docs/ja/core/forms.md b/docs/src/content/docs/ja/core/forms.md index d966dc9..ac19963 100644 --- a/docs/src/content/docs/ja/core/forms.md +++ b/docs/src/content/docs/ja/core/forms.md @@ -40,8 +40,8 @@ addOpenSpan addCloseSpan ``` ### ライフサイクル ``` -create // reset the static buffer; call before building a new form -addForm // wrap the buffer in
...
and return as a string +create / reset the static buffer; call before building a new form +addForm / wrap the buffer in
...
and return as a string ``` :::caution[名前の不一致は意図的なもの、ある程度] `addInputTypePassword` vs `addTypePassword`, `addInputTypeFileupload` vs `addTypeFileUpload` — プレフィックスが要素が `` (Input プレフィックス) であるかどうか(Input プレフィックス)か、他のタグ(Type プレフィックス)であるかどうかに一致します。これは奇妙ですが安定しています;CLI の `./nibiru -c` スキャフォールディングは同じパターンを使用しているため、筋肉記憶が働きます。 @@ -51,7 +51,7 @@ addForm // wrap the buffer in
...
and return as a string ```php use Nibiru\Factory\Form; -Form::create(); // reset the static buffer +Form::create(); / reset the static buffer Form::addOpenDiv(['class' => 'form-group']); Form::addTypeLabel(['for' => 'login', 'value' => 'Username']); @@ -187,7 +187,7 @@ class formsController extends Controller { 'required' => 'required', 'class' => 'contacts-input form-control', ]); - // ...more fields... + / ...more fields... $this->form = Form::addForm([ 'name' => 'newregister', 'method' => 'post', diff --git a/docs/src/content/docs/ja/core/modules.md b/docs/src/content/docs/ja/core/modules.md index c13e0ff..3019b2b 100644 --- a/docs/src/content/docs/ja/core/modules.md +++ b/docs/src/content/docs/ja/core/modules.md @@ -147,9 +147,9 @@ allowed.roles[] = "standard" どこからでも読み返す: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); -$cfg->session_lifetime; // 7200 -$cfg->password_min_length; // 12 -$cfg->allowed_roles; // [admin, editor, standard] +$cfg->session_lifetime; / 7200 +$cfg->password_min_length; / 12 +$cfg->allowed_roles; / [admin, editor, standard] ``` 環境オーバーレイ:`APPLICATION_ENV=production` の場合、`users.production.ini` が `users.ini` よりも優先されます。 @@ -162,7 +162,7 @@ $analytics = new \Nibiru\Module\Analytics\Analytics(); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Matomo()); $analytics->attach(new \Nibiru\Module\Analytics\Plugin\Plausible()); -$analytics->trackPageView(); // internally calls notify() +$analytics->trackPageView(); / internally calls notify() ``` 各観察者の `update($subject)` は、分析インスタンスを受け取り、関心のあるイベントデータを取得します。 @@ -200,7 +200,7 @@ class.plugin.pos[] = "" ; reserved プラグインクラスは、**複数形の**名前空間 `Plugins` の下にあります: ```php // application/module/billing/plugins/invoice.php -namespace Nibiru\Module\Billing\Plugins; // ← plural +namespace Nibiru\Module\Billing\Plugins; / ← plural class Invoice extends \Nibiru\Module\Billing\Billing { /* ... */ } ``` 名前空間が一致しないと、オートローダーのミスが発生します。CLI スキャフォールド (`./nibiru -m billing`) は正しい名前空間を生成してくれます。 @@ -210,7 +210,7 @@ class Invoice extends \Nibiru\Module\Billing\Billing { /* ... */ } モジュールの INI ファイルを **登録しないでください** — [Registry](/en/core/registry/) は、`[AUTOLOADER]` がモジュールクラスを読み込んだ後、`application/module//settings/*.ini` を走査して自動的に発見します。各 INI の `[]`(大文字)セクションは次のようになります: ```php $cfg = \Nibiru\Registry::getInstance()->loadModuleConfigByName('billing'); -$cfg->invoice_prefix; // [BILLING] invoice.prefix → property +$cfg->invoice_prefix; / [BILLING] invoice.prefix → property ``` レジストリは、`APPLICATION_ENV` が一致する場合に `..ini`(例:`billing.production.ini`)を優先します。 diff --git a/docs/src/content/docs/ja/core/pagination.md b/docs/src/content/docs/ja/core/pagination.md index 19632fb..c292fc8 100644 --- a/docs/src/content/docs/ja/core/pagination.md +++ b/docs/src/content/docs/ja/core/pagination.md @@ -14,7 +14,7 @@ class productsController extends Controller { public function pageAction() { $products = new products(); - Pageination::setEntriesPerPage(25); // optional; default from INI + Pageination::setEntriesPerPage(25); / optional; default from INI Pageination::setTable($products); $rows = Pageination::loadTableAsArray(); diff --git a/docs/src/content/docs/ja/core/registry.md b/docs/src/content/docs/ja/core/registry.md index 114d88c..ec23ad8 100644 --- a/docs/src/content/docs/ja/core/registry.md +++ b/docs/src/content/docs/ja/core/registry.md @@ -20,7 +20,7 @@ description: "モジュールが自動的に検出され、その設定が実行 $users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users'); $users->session_lifetime; $users->password_min_length; -$users->allowed_roles; // array +$users->allowed_roles; / array ``` モジュール自体では、この内容をセッターでラップする慣習があります。 ```php diff --git a/docs/src/content/docs/ja/core/routing.md b/docs/src/content/docs/ja/core/routing.md index 173651f..dd1a9ec 100644 --- a/docs/src/content/docs/ja/core/routing.md +++ b/docs/src/content/docs/ja/core/routing.md @@ -40,7 +40,7 @@ Nibiru は、どの設定も不要で SEO フレンドリーな URL を自動検 // /users/edit/42 → $_REQUEST['id'] = '42' public function editAction() { $id = (int) ($_REQUEST['id'] ?? 0); - // ... + / ... } ``` 数値的または名前付きパラメータ以外の場合、クエリ文字列を使用することをお勧めします。 @@ -62,9 +62,9 @@ api.v1.products.params[] = "id" ## ルーティングヘルパー ```php -Router::getInstance()->currentPage(); // 'products' -Router::getInstance()->tplName(); // 'products' (controller stem for templates) -Router::getInstance()->getController(); // alias for currentPage() +Router::getInstance()->currentPage(); / 'products' +Router::getInstance()->tplName(); / 'products' (controller stem for templates) +Router::getInstance()->getController(); / alias for currentPage() ``` これらはコントローラーとテンプレート内で役立ちます: ```smarty diff --git a/docs/src/content/docs/ja/design/components.md b/docs/src/content/docs/ja/design/components.md index b666318..9f92c1e 100644 --- a/docs/src/content/docs/ja/design/components.md +++ b/docs/src/content/docs/ja/design/components.md @@ -7,7 +7,7 @@ description: "ボタン、カード、コールアウト、ヒーロー — コ 黒い文字がクレーム色の背景にある長方形。エディタリー風。グラデーションや光沢はありません。 ```html - + Read the docs @@ -162,7 +162,7 @@ description: "ボタン、カード、コールアウト、ヒーロー — コ Nibiru is a modular PHP framework for builders who ship.

diff --git a/docs/src/content/docs/ja/index.mdx b/docs/src/content/docs/ja/index.mdx index ee60887..3b2416f 100644 --- a/docs/src/content/docs/ja/index.mdx +++ b/docs/src/content/docs/ja/index.mdx @@ -19,73 +19,25 @@ hero: variant: minimal --- -import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; +import CometTrail from '../../../components/CometTrail.astro'; +import MmvcStage from '../../../components/MmvcStage.astro'; +import MissionControl from '../../../components/MissionControl.astro'; +import LaunchSequence from '../../../components/LaunchSequence.astro'; +import SpacecraftGrid from '../../../components/SpacecraftGrid.astro'; +import EditorialContent from '../../../components/EditorialContent.astro'; +import LandingFooter from '../../../components/LandingFooter.astro'; +import ToTop from '../../../components/ToTop.astro'; +import LandingScripts from '../../../components/LandingScripts.astro'; -## 機能の星座 + + + + + + + + - - - モジュールはトレイト、プラグイン、インターフェース、設定で MVC を包みます。2 つ目の **M** は疎結合で、`SplSubject` Observer パターンが標準装備。 - - - 5 つのドライバが軌道を周回:`mysql`、`pdo`、`postgres`(ODBC)、`psql`(libpq)、`postgresql`。INI のキーを 1 つ変えるだけで切り替え可能。 - - - テンプレート駆動のビュー、グローバル `View::assign()` ヘルパー、ホット `templates_c` キャッシュ。共通パーシャル、ナビゲーション include、ページネーションテンプレートを完備。 - - - 28 種類以上のフィールドタイプ — text、password、switch、color、range、file upload — 静的な `Form::add…` 呼び出しで組み立て、1 つの HTML 文字列としてレンダリング。 - - - `./nibiru` がモジュール、コントローラー、プラグイン、マイグレーション、CMS ページを scaffolding。`local`、`staging`、`production` 環境に対してマイグレーションを実行。 - - - Nibiru は、自身の知識で訓練された RAG ベースの Oracle を内蔵する初の PHP フレームワークになります。将来のファインチューニング用の公開コーパスも提供予定。 - - - -## クイックスタート - -```bash -# クローン -git clone https://github.com/alllinux/Nibiru my-app && cd my-app - -# PHP 依存をインストール(Smarty、PHPMailer、Guzzle、…) -composer install - -# パーミッション + フォルダーのブートストラップ -./nibiru -s - -# 最初のマイグレーション -./nibiru -mi local - -# コントローラーを生成 -./nibiru -c products -``` - -```php -// application/controller/productsController.php -namespace Nibiru; -use Nibiru\Adapter\Controller; - -class productsController extends Controller { - public function pageAction() { - View::assign([ - 'title' => '製品 — Nibiru', - 'products' => [['id' => 1, 'name' => 'マルドゥク金メッキ']], - ]); - } - public function navigationAction() { - JsonNavigation::getInstance()->loadJsonNavigationArray(); - } -} -``` - -## 次はどこへ - - - - - - - +{/* Loads three.js + the original mockup scene code. MUST be the last node so + every #id the scene targets exists in the DOM when the script runs. */} + diff --git a/docs/src/content/docs/ja/showcase/patterns.md b/docs/src/content/docs/ja/showcase/patterns.md index 3002bfd..d0933f5 100644 --- a/docs/src/content/docs/ja/showcase/patterns.md +++ b/docs/src/content/docs/ja/showcase/patterns.md @@ -61,7 +61,7 @@ public function pageAction() { $analytics = new Analytics(); $analytics->attach(new Plugin\Matomo()); $analytics->attach(new Plugin\Plausible()); -$analytics->trackPageView(); // calls notify() internally +$analytics->trackPageView(); / calls notify() internally ``` 各観察者の `update($subject)` は、関心のあるフィールドのみを取得します。トラッカーの追加は1行の変更です。 diff --git a/docs/src/content/docs/ja/showcase/projects.md b/docs/src/content/docs/ja/showcase/projects.md index b4363e1..83c51c5 100644 --- a/docs/src/content/docs/ja/showcase/projects.md +++ b/docs/src/content/docs/ja/showcase/projects.md @@ -55,7 +55,7 @@ public function detailAction() try { $machine = Machine::init()->getMachine((int) $machineId); } catch (\Throwable $e) { - $machine = null; // DB blip → page still renders with fallback. + $machine = null; / DB blip → page still renders with fallback. } $machineName = $machine['ms_machines_name'] ?? "Maschine #$machineId"; diff --git a/docs/src/content/docs/ja/why-nibiru.md b/docs/src/content/docs/ja/why-nibiru.md index 8ae1da7..a6f43bf 100644 --- a/docs/src/content/docs/ja/why-nibiru.md +++ b/docs/src/content/docs/ja/why-nibiru.md @@ -50,7 +50,7 @@ class Cms implements Interfaces\Cms, SplSubject use Traits\PageBuilderForm; use Traits\CmsPageStructureModifier; use Traits\FormElements; - // …8 more traits + / …8 more traits } ``` **全体的な効果**: コンストラクタインジェクションゼロ、サービスプロバイダ登録ゼロ、設定ファイル内の`bind()` / `singleton()`呼び出しゼロ。新しい開発者はトレイト名をgrepで検索してすべての呼び出し元を見ることができます。 @@ -108,7 +108,7 @@ APIコントローラーは逆のアプローチを取っています:コン ```php // public endpoints can be listed up-front, auth wraps the rest. if (in_array($action, ['category', 'machines', 'ollama', 'team'])) { - // public, skip auth + / public, skip auth } else { $this->user = new User(); $this->acl = new Acl(); @@ -137,8 +137,8 @@ class Machineryscout implements IModule, \SplSubject } public function indexMachines(): void { - // …do the work… - $this->notify(); // analytics, cache invalidator, audit log all see it. + / …do the work… + $this->notify(); / analytics, cache invalidator, audit log all see it. } } ``` diff --git a/docs/src/styles/starlight-docs-bridge.css b/docs/src/styles/starlight-docs-bridge.css index e225cfe..61bcb71 100644 --- a/docs/src/styles/starlight-docs-bridge.css +++ b/docs/src/styles/starlight-docs-bridge.css @@ -726,6 +726,87 @@ dialog.dialog-frame::backdrop { .doc-header site-search button[data-open-modal] { min-width: 0; } } +/* ============================================================ + 11 · MOBILE — docs page typography + spacing tightening + ============================================================ + Starlight ships responsive layout for the 3-column shell, but the + typography we override (clamp() H1, doc-meta strip, breadcrumbs row, + help-strip) needs explicit small-screen rules so it doesn't push the + content column past the viewport. + ============================================================ */ + +@media (max-width: 768px) { + /* Shrink the doc atmosphere wash so two radials don't dominate the viewport */ + :root:not([data-has-hero]) body::before { + background-image: + radial-gradient(ellipse 90% 30% at 0% 0%, rgba(184, 107, 255, 0.10), transparent 60%); + } + + /* H1 already uses clamp() — bring the headroom in tighter on mobile */ + :root:not([data-has-hero]) .content-panel h1, + :root:not([data-has-hero]) .sl-markdown-content h1 { + font-size: clamp(1.6rem, 7vw, 2.25rem); + margin-bottom: 12px; + } + + /* H2 — keep the divider but trim spacing */ + :root:not([data-has-hero]) .sl-markdown-content h2 { + margin-top: 36px; + padding-top: 18px; + font-size: 1.32rem; + } + + /* Doc-meta row wraps tighter on mobile so the four cells stack 2 + 2 */ + :root:not([data-has-hero]) .doc-meta { + gap: 10px 18px; + font-size: 10px; + padding-bottom: 18px; + margin-bottom: 24px; + } + + /* Breadcrumbs hide the long mid-segments on narrow screens */ + :root:not([data-has-hero]) .breadcrumbs { + font-size: 11px; + gap: 6px; + } + + /* Help-strip stacks instead of side-by-side */ + :root:not([data-has-hero]) .help-strip { + flex-direction: column; + align-items: flex-start; + padding: 14px 16px; + } + + /* Pagination cards stack to one column on phones */ + :root:not([data-has-hero]) .pagination-links { + grid-template-columns: 1fr; + gap: 12px; + margin-top: 48px; + padding-top: 24px; + } + :root:not([data-has-hero]) .pagination-links a.link-next { + text-align: left; + align-items: flex-start; + } + + /* Right-rail TOC hidden by Starlight at this width — sidebar pad too */ + :root:not([data-has-hero]) .right-sidebar-panel { padding: 24px 16px; } + + /* Tables — wrap in horizontal scroll on overflow rather than blow out the column */ + :root:not([data-has-hero]) .sl-markdown-content table { + display: block; + overflow-x: auto; + max-width: 100%; + } +} + +@media (max-width: 480px) { + /* Brand version chip + tools group consume too much width — drop the version */ + .doc-header .nav-version { display: none; } + .doc-header { padding: 0 14px; } + .doc-header .doc-header-row { gap: 10px; } +} + /* ============================================================ 10 · PAGE-LEVEL ATMOSPHERE — soft magenta/blue radial wash ============================================================