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).