Reference

Events and Integration

Events

The module triggers two events on an event manager whose identifier is ThemeFileEditor\Service\FileEditor. Attach listeners through the shared event manager in your module's attachListeners().

Event When Parameters
theme_file_editor.file_save After a file has been written to disk and its revision stored theme, path (relative to view/), revision_id, user_id (null if no identity)
theme_file_editor.file_rollback After a rollback has been written and its new revision stored theme, path, from_revision_id, new_revision_id, user_id

Copy to Theme and Copy Theme create revisions but do not fire events. Listener exceptions are caught and written to the PHP error log; they cannot abort the save, which has already happened.

use Laminas\EventManager\Event;
use Laminas\EventManager\SharedEventManagerInterface;

public function attachListeners(SharedEventManagerInterface $sharedEvents): void
{
    $sharedEvents->attach(
        \ThemeFileEditor\Service\FileEditor::class,
        'theme_file_editor.file_save',
        function (Event $event): void {
            $p = $event->getParams();
            // $p['theme'], $p['path'], $p['revision_id'], $p['user_id']
        }
    );
}

AuditTrail module

If the AuditTrail module is installed and its AuditTrail\Service\AuditLogger service is available, saves and rollbacks are logged automatically. No configuration is needed and nothing happens when the module is absent.

Event AuditTrail action Detail
Save theme_file_edit Theme: <theme> | Path: <path> | Rev: <id>
Rollback theme_file_rollback Theme: <theme> | Path: <path> | From rev: <id> | New rev: <id>

Independently of AuditTrail, every save and theme copy is written to the PHP error log with the theme, path, size, user ID and revision ID. File content is never logged.

Services

Other modules can use the module's services from the service manager:

Service Purpose
ThemeFileEditor\Service\FileBrowser List themes, list and search view/ directories, resolve and validate paths
ThemeFileEditor\Service\FileEditor Read, save, roll back, copy to theme, copy theme; fires the events above
ThemeFileEditor\Service\RevisionManager Create, list, compare, prune and roll back revisions
ThemeFileEditor\Service\DiffService Pure PHP unified diff (unified()), HTML rendering (toHtml(), toSideBySideHtml())
ThemeFileEditor\Service\SyntaxChecker check(string): ?string, isExecAvailable(): bool

Security violations throw ThemeFileEditor\Exception\SecurityException (a RuntimeException).

Database table

CREATE TABLE theme_file_revision (
    id             INT UNSIGNED  NOT NULL AUTO_INCREMENT,
    theme          VARCHAR(128)  NOT NULL,
    relative_path  VARCHAR(512)  NOT NULL,
    content        MEDIUMTEXT    NOT NULL,
    user_id        INT UNSIGNED  DEFAULT NULL,
    created_at     DATETIME      NOT NULL,
    change_summary VARCHAR(255)  DEFAULT NULL,
    checksum       CHAR(64)      NOT NULL,
    file_size      INT UNSIGNED  NOT NULL,
    PRIMARY KEY (id),
    KEY idx_theme_path (theme, relative_path(191)),
    KEY idx_created    (created_at),
    KEY idx_user       (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

created_at is stored in UTC. checksum is the SHA-256 hex digest of content. user_id has no foreign key, so revisions survive the deletion of the user who made them.

Tests

The module ships PHPUnit unit and integration tests that use mocks and a temporary directory; they never touch real theme files or a database. From the Omeka S root:

vendor/bin/phpunit -c modules/ThemeFileEditor/test/phpunit.xml
vendor/bin/phpunit -c modules/ThemeFileEditor/test/phpunit.xml --testsuite unit
THEME_FILE_EDITOR_TEST_DIR=/tmp/tfe-tests vendor/bin/phpunit -c modules/ThemeFileEditor/test/phpunit.xml

Use the phpunit binary from wherever Omeka's development dependencies are installed (vendor/bin or application/vendor/bin).

Log in for Support