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

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