Purpose
Holds the per-request services and state the bundled editor
theme (editor/theme/*.php) consumes as $editor. Plugin-side
modules receive an Editor instance as the second argument of
their factory (function(Container, Editor): Module) so they
can read the URL, log, redirect, queue messages, and write into
the layout's pageTitle / pageContent slots.
Plugins almost never subclass Editor. The class is documented
here for the few places where a module needs to reach for a
service that is not on Module itself: container, CSRF, i18n,
logger, sanitizer.
FQCN + file path
- FQCN:
Scriptor\Boot\Editor\Editor - Source:
boot/Editor/Editor.php
When to use
You touch Editor in one place: inside a Module (or its
factory). The module receives the Editor instance and reads /
writes through it:
final class MyModule implements Module
{
public function __construct(
private Container $container,
private Editor $editor,
) {}
public function execute(): void
{
$this->editor->pageTitle = 'My module';
$this->editor->pageContent = '<h1>Hello editor</h1>';
}
}
You do not subclass Editor, do not instantiate it, do not
mutate the resources arrays directly (use addResource()).
Surface
Public properties (request-scoped)
| Property | Type | Purpose |
|---|---|---|
baseUrl |
string |
Host URL, no path (e.g. https://example.com) |
siteUrl |
string |
Admin mount point ($baseUrl/$admin_path) |
themeUrl |
string |
Public URL of public/editor-assets/ |
version |
string |
Scriptor version string |
pageTitle |
string |
What the module wants in the <title> and H1 |
pageContent |
string |
The module's rendered HTML body |
breadcrumbs |
string |
Pre-rendered breadcrumbs HTML |
jsConfig |
string |
JSON the module wants to expose as a <script> body before its own JS runs |
msgs |
list<array{...}> |
In-request message queue (use addMsg()) |
csrf |
Imanager\Http\Csrf |
CSRF token manager |
input |
Imanager\Http\Request |
$_GET / $_POST / $_FILES wrapper |
sanitizer |
Sanitizer |
Same façade themes see (see Sanitizer) |
urlSegments |
UrlSegments |
Editor path segments, stripped of the admin mount prefix |
session |
SessionStore |
iManager session-bag accessor |
logger |
Psr\Log\LoggerInterface |
PSR-3 logger, bound by FileLogger |
templateParser |
TemplateRenderer |
iManager's {{ tag }} parser |
config |
array<string,mixed> |
Scriptor config array verbatim |
i18n |
array<string,string> |
Editor translations from editor/lang/<lang>.php |
Public methods
public function isLoggedIn(): bool
public function currentUserId(): ?int
Auth shortcuts. isLoggedIn() checks the session for the
loggedin = true flag the AuthModule sets after a successful
login. currentUserId() returns the user id or null for
anonymous requests.
public function addMsg(string $type, string $text, string $header = ''): void
public function flashMsg(string $type, string $text): void
public function renderMsgs(): string
Same message-queue shape as the frontend Site: addMsg is
in-request, flashMsg survives a redirect via the session,
renderMsgs drains both into a <ul class="messages">. The
flash bag lives under the session key msgs (the editor's own
namespace, separate from the frontend's frontend_msgs).
public function redirect(string $url, int $status = 302): never
Identical status-code cheat sheet to Site::redirect(). 303 for
post-form, 301 for permanent, 302 default, 307 for
method-preserving.
public function addResource(string $kind, string $html, string $position = 'head'): void
public function getResources(string $kind, string $position = 'head'): string
Module-supplied <link> / <script> tags. $kind is 'link'
or 'script'; $position is 'head' or 'body'. Pass the
whole tag (not a URL); the editor template prints the strings
back verbatim into the slot.
public function getProperty(string $name): mixed
Convenience read of one of the layout slots (pageTitle,
pageContent, breadcrumbs, jsConfig, messages). The
editor template calls this; modules normally read the
properties directly.
public function csrfQueryString(string $name = 'logout_token'): string
Builds ?tokenName=…&tokenValue=… for logout-style GET links
that need a CSRF token in the URL.
public function assetUrl(string $relative): string
Public URL for an editor static asset (CSS, JS, image, font)
under public/editor-assets/. Use this from a module's
rendered HTML when you need to reference an admin-side asset
the editor ships.
public function templateName(string $value): string
Filename-safe template name ([a-zA-Z0-9_\-/] only). Same as
$site->sanitizer->templateName(); exposed at the top level so
older module code reads cleanly.
Lifecycle
One instance per request, constructed in editor/index.php from
the League container plus the Scriptor config. The constructor
pulls a fixed set of services out of the container (CSRF,
session, logger, sanitizer, request, template parser), wires
baseUrl / siteUrl / themeUrl / urlSegments / i18n,
and is done.
After construction, the EditorRouter (not documented here) maps
$urlSegments to a registered module via ModuleRegistry,
calls the module's factory (function(Container, Editor): Module)
with this instance, and finally calls Module::execute(). The
template then renders $editor->pageTitle, $editor->pageContent,
the resources, and the message queue.
The session is always opened for /editor/ requests because the
admin assumes a session (login state, flash messages, CSRF
tokens). No opt-in shape like the frontend has.
Common patterns
A module that sets the title, content, and flash
public function execute(): void
{
$this->editor->pageTitle = 'Settings';
if ($this->editor->input->method() === 'POST') {
// ...save handling...
$this->editor->flashMsg('success', 'Settings saved.');
$this->editor->redirect($this->editor->siteUrl . '/settings/', 303);
}
$this->editor->pageContent = $this->renderSettingsForm();
}
Module-supplied CSS
public function execute(): void
{
$this->editor->addResource(
'link',
sprintf(
'<link rel="stylesheet" href="%s">',
$this->editor->sanitizer->entities(
$this->editor->siteUrl . '/plugin-assets/my-plugin.css',
),
),
'head',
);
// ...
}
Reading an i18n key with a sane fallback
$label = $this->editor->i18n['my_module.save'] ?? 'Save';
See also
Module: the interface every plugin module implementsMenuItem: how a plugin pins a sidebar link to its modulePluginContext: theregisterEditorModule()/addEditorMenuItem()entry pointsSanitizer: shared façade- Concept: Editor extensions: walkthrough of the module + menu + container flow