Project Structure

Directory layout, dependencies and database schema

Directory layout

linkenhancer/
├── module.php            ← webtrees entry point
├── autoload.php          ← PSR-4 autoloader
├── cron-jobs.php         ← cronjob self-registration manifest
├── latest-version.txt    ← current version (synced to LinkEnhancerModule.php)
├── composer.json         ← PHP deps (wt-shared-libs, phpstan)
├── package.json          ← JS deps (gulp, rollup, mocha)
├── gulpfile.mjs          ← build tasks
├── phpstan.neon          ← static analysis config
├── phpstan-bootstrap.php ← PSR-4 bootstrap for PHPStan
├── phpstan-baseline.neon ← known issues
├── src/                  ← PHP (PSR-4)
│   ├── LinkEnhancerModule.php
│   ├── LinkEnhancerModuleExt.php
│   ├── LinkEnhancerUtils.php
│   ├── SettingInterface.php
│   ├── CommonMark/       ← CommonMark extensions
│   ├── DataFix/          ← data-fix handlers + dispatcher
│   ├── Factories/        ← CustomMarkdownFactory
│   ├── Http/             ← request handlers
│   ├── Schema/           ← Migrations + SeedHelpTable
│   └── Services/         ← business logic
├── resources/
│   ├── js/               ← JS source (src/) + build output (bundle-*)
│   ├── css/              ← CSS source + build output
│   ├── lang/             ← .pot / .po / .php (translations)
│   ├── views/            ← PHTML views
│   └── img/              ← screenshots
├── cli/                  ← CLI maintenance scripts
├── tests/                ← standalone + smoke tests
└── util/                 ← build/maintenance shell scripts

Dependencies

Database schema

The module owns five tables (prefix le_), created incrementally by src/Schema/Migration#.php. Every migration is additive and idempotent, so the schema converges on each module load.

le_route_help_map

Maps a webtrees route (path / handler / method) to a help entry — the backing store for context-sensitive manual help. Seeded by SeedHelpTable.

ColumnTypeNotes
idint, PK (auto)
pathvarchar(255)route path
handlervarchar(150)fully-qualified handler class
handler_keyvarchar(150), indexversion-neutral key (2.2.6 + 2.3 compatible)
methodvarchar(20)
extrasvarchar(60)
subcontextvarchar(250)
categoryvarchar(60)standard / custom module / generic …
orderint, default 10
urlvarchar(250)
updated_attimestamp, nullable

Index on (path, handler) and on handler_key.

le_record_scan

One row per scanned GEDCOM record, with an MD5 fingerprint of the record text — lets the CLI index diff incrementally.

ColumnTypeNotes
fileinttree id (part of PK)
xrefvarchar(20)(part of PK)
rectypevarchar(15)GEDCOM tag, e.g. INDI, OBJE (part of PK)
hashvarchar(32)MD5 of the record text
scanned_attimestamp, nullable

Primary key (file, xref, rectype).

One row per (link, target) found in a record — the foundation for the planned Backlink feature.

ColumnTypeNotes
idint, PK (auto)
fileinttree id
xrefvarchar(20)
rectypevarchar(15)
tag_pathvarchar(255)where the link sits in the record
link_classvarchar(10)xref / ext / pic / classic / other
tokentextthe raw link token
snippettext, nullabledisplay context captured at build time
target_xrefvarchar(20), nullableXREF link target
target_treevarchar(255), nullable
target_uidvarchar(255), nullable, indexUID link target (filled by a length heuristic)

Indexes on (file, xref, rectype), target_xref and target_uid.

le_uid_index

One row per UID tag found in a record (record-level and fact-level). No unique constraint — UIDs are not guaranteed to be unique.

ColumnTypeNotes
idint, PK (auto)
fileinttree id
xrefvarchar(20)
uidvarchar(255), indexverbatim UID value (no normalization)
rectypevarchar(15)
tag_pathvarchar(255)
hashvarchar(32)MD5 fingerprint (incremental change detection)

Indexes on uid and (file, xref, rectype).

le_index_meta

A single row (id = 1) holding the freshness state of both the link index and the UID index.

ColumnTypeNotes
idint, PK, default 1single row
last_runtimestamp, nullablelast complete link-index run
rowsint, default 0link-index row count
uid_last_runtimestamp, nullablelast complete UID-index run
uid_rowsint, default 0UID-index row count
Last modified November 2, 2026: applied repoFileURL, where applicable (21fa655)