<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>wt-modules</title><link>https://bschwede.codeberg.page/wt-modules/de/</link><description>Recent content on wt-modules</description><generator>Hugo</generator><language>de</language><atom:link href="https://bschwede.codeberg.page/wt-modules/de/index.xml" rel="self" type="application/rss+xml"/><item><title>CLI-Skripte</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/cli-scripts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/cli-scripts/</guid><description>&lt;p&gt;Das Modul bringt ausschließlich CLI-Skripte mit. Sie sind geschützt: bei Aufruf über HTTP (das Verzeichnis &lt;code&gt;modules_v4&lt;/code&gt; liegt innerhalb des Web-Roots) antworten sie mit &lt;code&gt;403&lt;/code&gt; anstatt auszuführen.&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Skript&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Zweck&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Braucht eine webtrees-Installation + DB?&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;cli/build-link-index.php [--limit=N] [--tree=&amp;lt;id&amp;gt;] [--rebuild] [--flush]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;baut/aktualisiert den Link-Index für die XREF-Übersicht&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ja&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;cli/build-uid-index.php [--limit=N] [--tree=&amp;lt;id&amp;gt;] [--rebuild] [--flush] [--force]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;baut/aktualisiert den UID-Index für die UID-Suche&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ja&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;cli/refresh-wthb-toc.php [--all] [--lang=&amp;lt;list&amp;gt;] [--clear] [--force]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;aktualisiert den WTHB-Inhaltsverzeichnis-Cache (&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/wthb-toc-lang/"&gt;Produktion&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ja&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-text-tag-collector.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-text-tag-collector.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;eigenständige Unit-Tests für den Text-Tag-Collector&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nein&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-link-classifier.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-link-classifier.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;eigenständige Unit-Tests für den Link-Klassifizierer (inkl. Ziel-Extraktion)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nein&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-uid-tag-collector.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-uid-tag-collector.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;eigenständige Unit-Tests für den UID-Tag-Collector&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nein&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-uid-index-service.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-uid-index-service.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;eigenständige Unit-Tests für den UID-Index-Service&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nein&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;tests/smoke-text-tag-collector.php [limit]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;scannt Datensätze mit erweiterten Links, gibt jeden erfassten Wert aus&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ja&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/smoke-migration5.php" target="_blank" rel="noopener"&gt;&lt;code&gt;smoke-migration5.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SQLite-Smoke-Test für Migration5 (UID-Index-Schema)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ja&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;tests/p1-measure.php [--tree=&amp;lt;id&amp;gt;]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Read-only-Scaling-Messung für die XREF-Übersicht&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ja&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Ausführen vom webtrees-Root aus mit der &lt;strong&gt;gleichen PHP-Version&lt;/strong&gt;, mit der die Instanz läuft (webtrees benötigt PHP 8.3+):&lt;/p&gt;</description></item><item><title>Service API</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/howto-use/service-api/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/howto-use/service-api/</guid><description>&lt;p&gt;Benachbarte Module fragen den Status des Moduls über eine stabile, schreibgeschützte Schnittstelle (&lt;code&gt;CronjobService&lt;/code&gt;) ab, anstatt auf dessen interne Dienste zurückzugreifen. Überprüfen Sie zunächst die Verfügbarkeit –&#10;das Modul ist möglicherweise nicht installiert, und die Klasse kann nur automatisch geladen werden, wenn die Datei&#10;&lt;a href="https://github.com/bschwede/wt-cronjob/tree/main/module.php" target="_blank" rel="noopener"&gt;&lt;code&gt;module.php&lt;/code&gt;&lt;/a&gt;&#10; geladen wurde:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;&amp;lt;?&lt;/span&gt;php&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;use&lt;/span&gt; Schwendinger\Webtrees\Module\Cronjob\Services\CronjobService;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;if&lt;/span&gt; (class_exists(CronjobService&lt;span style="color:#91d7e3;font-weight:bold"&gt;::&lt;/span&gt;&lt;span style="color:#8aadf4"&gt;class&lt;/span&gt;) &lt;span style="color:#91d7e3;font-weight:bold"&gt;&amp;amp;&amp;amp;&lt;/span&gt; CronjobService&lt;span style="color:#91d7e3;font-weight:bold"&gt;::&lt;/span&gt;&lt;span style="color:#8aadf4"&gt;isFunctional&lt;/span&gt;()) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f4dbd6"&gt;$status&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt; CronjobService&lt;span style="color:#91d7e3;font-weight:bold"&gt;::&lt;/span&gt;&lt;span style="color:#8aadf4"&gt;jobStatus&lt;/span&gt;(&lt;span style="color:#a6da95"&gt;&amp;#39;mymodule:backup&amp;#39;&lt;/span&gt;); &lt;span style="color:#6e738d;font-style:italic"&gt;// null = unknown job&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f4dbd6"&gt;$age&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt; CronjobService&lt;span style="color:#91d7e3;font-weight:bold"&gt;::&lt;/span&gt;&lt;span style="color:#8aadf4"&gt;lastTickAge&lt;/span&gt;(); &lt;span style="color:#6e738d;font-style:italic"&gt;// seconds since last tick&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f4dbd6"&gt;$listened&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt; CronjobService&lt;span style="color:#91d7e3;font-weight:bold"&gt;::&lt;/span&gt;&lt;span style="color:#8aadf4"&gt;listenedEvents&lt;/span&gt;(); &lt;span style="color:#6e738d;font-style:italic"&gt;// event name =&amp;gt; job names&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Frage&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Methode(n)&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Ist der Dienst funktionsfähig?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;isFunctional()&lt;/code&gt;, &lt;code&gt;problems()&lt;/code&gt; (Codes: &lt;code&gt;module_disabled&lt;/code&gt;, &lt;code&gt;not_migrated&lt;/code&gt;, &lt;code&gt;cron_library_missing&lt;/code&gt;, &lt;code&gt;tick_stale&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Welche Funktionen sind aktiviert?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;features()&lt;/code&gt; (&lt;code&gt;watch&lt;/code&gt;, &lt;code&gt;pseudo_events&lt;/code&gt;, &lt;code&gt;route_events&lt;/code&gt;), &lt;code&gt;watchStatus()&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Wann wurde der letzte Tick ausgeführt?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;lastTick()&lt;/code&gt; / &lt;code&gt;lastTickAge()&lt;/code&gt; – beide Trigger-Typen (Marker-Datei &lt;code&gt;data/cronjob/tick.last&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Ist ein Job aktiviert / wann wurde er zuletzt ausgeführt?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;isJobEnabled($name)&lt;/code&gt;, &lt;code&gt;jobStatus($name)&lt;/code&gt;, &lt;code&gt;lastRun($name)&lt;/code&gt; – Jobnamen sind mit einem Namespace versehen (&lt;code&gt;&amp;lt;Modul&amp;gt;:&amp;lt;Name&amp;gt;&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Auf welche Ereignisse wird gewartet?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;listenedEvents()&lt;/code&gt;, &lt;code&gt;listenersFor($event)&lt;/code&gt;; Kataloge: &lt;code&gt;eventCatalog()&lt;/code&gt;, &lt;code&gt;pseudoEvents()&lt;/code&gt;, &lt;code&gt;routeEvents()&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Aktionen (die einzigen beiden)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;runJobNow($name)&lt;/code&gt; (wird beim nächsten Tick in die Warteschlange gestellt), &lt;code&gt;pushEvent($name, $payload)&lt;/code&gt; (Ereigniswarteschlange)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Vertrag: Schreibgeschützte Methoden lösen niemals einen Fehler aus, wenn das Schema fehlt (sichere Standardwerte),&#10;Beschreibungen sind Quelltext-Strings (werden niemals vorab übersetzt), und &lt;code&gt;lastRun()&lt;/code&gt; schließt bewusst&#10;die Job-Ausgabe aus, da diese personenbezogene Daten enthalten kann.&lt;/p&gt;</description></item><item><title>Voraussetzungen</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/setup/requirements/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/setup/requirements/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;webtrees 2.2.x (PHP 8.3+)&lt;/li&gt;&#10;&lt;li&gt;PHP CLI mit &lt;a href="https://www.php.net/manual/de/function.proc-open.php"&gt;&lt;code&gt;proc_open&lt;/code&gt;&lt;/a&gt; verfügbar (Standard)&lt;/li&gt;&#10;&lt;li&gt;Ein Trigger: klassisches Cron, ein systemd-Timer, eine Windows Task Scheduler-Aufgabe, &lt;strong&gt;oder&lt;/strong&gt; der eingebaute Watch-Daemon (kein OS-Timer nötig — siehe &amp;ldquo;Trigger-Installation&amp;rdquo;)&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>Voraussetzungen</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/requirements/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/requirements/</guid><description>&lt;p&gt;Dieses Modul benötigt &lt;strong&gt;webtrees&lt;/strong&gt; Version 2.2 oder 2.3&#10;und hat dieselben Anforderungen wie &lt;a href="https://github.com/fisharebest/webtrees#system-requirements"&gt;webtrees#system-requirements&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Es wurde ursprünglich für Version 2.2.4 erstellt; seit LinkEnhancer 1.6.1 sollte es auch mit webtrees 2.3 funktionieren. Tests werden normalerweise mit eingebauten Themes und einigen anderen Custom-Modulen durchgeführt.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Tipp:&lt;/strong&gt; Es wird empfohlen, das &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/"&gt;Cronjob&lt;/a&gt;-Modul ebenfalls zu installieren. Das erleichtert das Ausführen der CLI-Skripte zur Index-Wartung.&lt;/p&gt;&#10;&lt;/blockquote&gt;</description></item><item><title>Installation</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/setup/installation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/setup/installation/</guid><description>&lt;ol&gt;&#10;&lt;li&gt;Modulordner nach &lt;code&gt;modules_v4/cronjob/&lt;/code&gt; kopieren (ZIP-Installation geht auch). Die Cron-Bibliothek ist im Modul enthalten — nichts zu holen.&lt;/li&gt;&#10;&lt;li&gt;Webtrees einmal öffnen (irgendeine Seite als Admin), damit das Modul-&lt;code&gt;boot()&lt;/code&gt; seine Tabellen erstellt.&lt;/li&gt;&#10;&lt;li&gt;Trigger installieren (klassisches Cron, systemd-Timer oder Windows Task Scheduler — die Admin-Seite des Moduls generiert den Block für Ihr OS mit den Pfaden &lt;em&gt;dieser&lt;/em&gt; Installation bereits ausgefüllt).&lt;/li&gt;&#10;&lt;li&gt;Trigger-Installation (einmalig) — siehe unten.&lt;/li&gt;&#10;&lt;li&gt;Erstellen Sie Ihren ersten Job in der Admin-UI oder konfigurieren und aktivieren Sie registrierte Jobs.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="trigger-installation-einmalig"&gt;Trigger-Installation (einmalig)&lt;a class="td-heading-self-link" href="#trigger-installation-einmalig" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/cj/installation.png"&#10; alt="Installation"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;</description></item><item><title>Installation</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/installation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/installation/</guid><description>&lt;h3 id="über-custom-module-manager-empfohlen"&gt;Über Custom Module Manager (empfohlen)&lt;a class="td-heading-self-link" href="#%c3%bcber-custom-module-manager-empfohlen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Installieren Sie &lt;a href="https://github.com/Jefferson49/CustomModuleManager"&gt;Custom Module Manager&lt;/a&gt; für eine einfache und bequeme Installation von webtrees Custom-Modulen.&lt;/li&gt;&#10;&lt;li&gt;Öffnen Sie die Custom Module Manager-Ansicht in webtrees, wählen Sie &amp;ldquo;linkenhancer&amp;rdquo; aus und klicken Sie auf die &amp;ldquo;Install Module&amp;rdquo;-Schaltfläche.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="manuelle-installation"&gt;Manuelle Installation&lt;a class="td-heading-self-link" href="#manuelle-installation" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Laden Sie die &lt;a href="https://codeberg.org/bschwede/linkenhancer/releases/latest"&gt;neueste Version&lt;/a&gt; des Moduls herunter.&lt;/li&gt;&#10;&lt;li&gt;Laden Sie die heruntergeladene Datei auf Ihren Webserver hoch.&lt;/li&gt;&#10;&lt;li&gt;Entpacken Sie das Paket in Ihr &lt;code&gt;modules_v4&lt;/code&gt;-Verzeichnis.&lt;/li&gt;&#10;&lt;li&gt;Benennen Sie den Ordner in &lt;code&gt;linkenhancer&lt;/code&gt; um.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Wenn alles erfolgreich war, sollten Sie im &lt;code&gt;modules_v4&lt;/code&gt;-Verzeichnis einen Unterordner &lt;code&gt;linkenhancer&lt;/code&gt; mit dem entpackten Inhalt sehen.&lt;/p&gt;</description></item><item><title>Mitwirken</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/contributing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/contributing/</guid><description>&lt;p&gt;Wenn Sie zu diesem Modul beitragen möchten, großartig! Sie können beitragen, indem Sie:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Code beisteuern&lt;/strong&gt; — schauen Sie sich die &lt;a href="https://codeberg.org/bschwede/linkenhancer/issues"&gt;Issues&lt;/a&gt; für Dinge an, die Aufmerksamkeit brauchen. Wenn Sie Änderungen vornehmen möchten, die nicht in einem Issue aufgeführt sind, erstellen Sie bitte eines, damit Sie Ihren Pull Request verlinken können.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Testen&lt;/strong&gt; — derzeit ist alles manuell; bitte &lt;a href="https://codeberg.org/bschwede/linkenhancer/issues"&gt;erstellen Sie ein Issue&lt;/a&gt; für jeden Bug, den Sie finden.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="übersetzung"&gt;Übersetzung&lt;a class="td-heading-self-link" href="#%c3%bcbersetzung" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;Sie können zu diesem Projekt auf &lt;a href="https://translate.codeberg.org/projects/linkenhancer/"&gt;Codeberg Weblate&lt;/a&gt; beitragen. Aktualisierte Übersetzungen werden in der nächsten Version dieses Moduls enthalten sein.&lt;/p&gt;</description></item><item><title>Projektstruktur</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/project-structure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/project-structure/</guid><description>&lt;h2 id="verzeichnislayout"&gt;Verzeichnislayout&lt;a class="td-heading-self-link" href="#verzeichnislayout" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;linkenhancer/&#10;├── module.php ← webtrees-Entry-Point&#10;├── autoload.php ← PSR-4-Autoloader&#10;├── cron-jobs.php ← Self-Registration-Manifest für cronjob&#10;├── latest-version.txt ← aktuelle Version (mit LinkEnhancerModule.php synchron)&#10;├── composer.json ← PHP-Abhängigkeiten (wt-shared-libs, phpstan)&#10;├── package.json ← JS-Abhängigkeiten (gulp, rollup, mocha)&#10;├── gulpfile.mjs ← Build-Tasks&#10;├── phpstan.neon ← Konfiguration der statischen Analyse&#10;├── phpstan-bootstrap.php ← PSR-4-Bootstrap für PHPStan&#10;├── phpstan-baseline.neon ← bekannte Probleme&#10;├── src/ ← PHP (PSR-4)&#10;│ ├── LinkEnhancerModule.php&#10;│ ├── LinkEnhancerModuleExt.php&#10;│ ├── LinkEnhancerUtils.php&#10;│ ├── SettingInterface.php&#10;│ ├── CommonMark/ ← CommonMark-Extensionen&#10;│ ├── DataFix/ ← Datenkorrektur-Handler + Dispatcher&#10;│ ├── Factories/ ← CustomMarkdownFactory&#10;│ ├── Http/ ← Request-Handler&#10;│ ├── Schema/ ← Migrations + SeedHelpTable&#10;│ └── Services/ ← Geschäftslogik&#10;├── resources/&#10;│ ├── js/ ← JS-Quellcode (src/) + Build-Ausgabe (bundle-*)&#10;│ ├── css/ ← CSS-Quellcode + Build-Ausgabe&#10;│ ├── lang/ ← .pot / .po / .php (Übersetzungen)&#10;│ ├── views/ ← PHTML-Views&#10;│ └── img/ ← Screenshots&#10;├── cli/ ← CLI-Wartungsskripte&#10;├── tests/ ← Standalone- + Smoke-Tests&#10;└── util/ ← Build-/Wartungs-Shell-Skripte&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="abhängigkeiten"&gt;Abhängigkeiten&lt;a class="td-heading-self-link" href="#abh%c3%a4ngigkeiten" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;PHP&lt;/strong&gt; (&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/composer.json" target="_blank" rel="noopener"&gt;&lt;code&gt;composer.json&lt;/code&gt;&lt;/a&gt;&#10;):&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;bschwede/wt-shared-libs&lt;/code&gt; (Path-Repo &lt;code&gt;../wt-shared-libs&lt;/code&gt;)&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/phpstan/"&gt;&lt;code&gt;phpstan&lt;/code&gt;&lt;/a&gt; (dev).&lt;/li&gt;&#10;&lt;li&gt;Konflikte mit:&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;webtrees &amp;lt;2.2&lt;/code&gt; und&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/elysch/webtrees-mitalteli-misc-features"&gt;&lt;code&gt;elysch/webtrees-mitalteli-misc-features&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;JS&lt;/strong&gt; (&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/package.json" target="_blank" rel="noopener"&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/a&gt;&#10;):&#10;&lt;ul&gt;&#10;&lt;li&gt;Laufzeit-Abhängigkeit &lt;a href="https://github.com/jefago/tiny-markdown-editor"&gt;&lt;code&gt;tiny-markdown-editor&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Dev-Tooling — Gulp, Rollup, PostCSS (autoprefixer, cssnano), Mocha + chai + sinon, jsdom&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="datenbank-schema"&gt;Datenbank-Schema&lt;a class="td-heading-self-link" href="#datenbank-schema" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Das Modul besitzt fünf Tabellen (Präfix &lt;code&gt;le_&lt;/code&gt;), die inkrementell durch &lt;code&gt;src/Schema/Migration#.php&lt;/code&gt; erstellt werden. Jede Migration ist additiv und idempotent, sodass das Schema bei jedem Modul-Load konvergiert.&lt;/p&gt;</description></item><item><title>Pseudo-Events</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/pseudo/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/pseudo/</guid><description>&lt;p&gt;Webtrees hat keinen Event-Bus, daher werden Core-Aktionen (Logins, fehlgeschlagene Logins, Logouts, Datensatz-Edits, Fehler, Suchen) durch &lt;strong&gt;Polling der webtrees-Log-Tabelle&lt;/strong&gt; (&lt;code&gt;app/Log.php&lt;/code&gt;, Tabelle &lt;code&gt;log&lt;/code&gt;) detektiert und pro neuem passenden Log-Eintrag ein Ereignis ausgelöst. Es ist &lt;strong&gt;standardmäßig deaktiviert&lt;/strong&gt;: nichts läuft, bis der angebotene &lt;code&gt;cronjob:pseudo-events&lt;/code&gt;-Job aktiviert wird.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Eingebaute Events&lt;/strong&gt; (ein &lt;code&gt;cj_event&lt;/code&gt; pro neuer Log-Zeile, Payload = die Zeile):&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Ereignis&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Log-Filter (log_type, Nachricht-Präfix)&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Feuer bei&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-auth-failed&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;Login failed&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein Login-Versuch fehlgeschlagen (falsches Passwort, unbekannter Benutzer, nicht verifiziert, nicht genehmigt, keine Session-Cookies)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-auth-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;Login:&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein Benutzer eingeloggt&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-auth-logout&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;Logout:&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein Benutzer ausgeloggt&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-error&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;error&lt;/code&gt;, –&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;eine Ausnahme erfasst und geloggt (die Nachricht ist der Trace)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-edit-update&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;Update:&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein Datensatz aktualisiert (&lt;code&gt;GedcomRecord::updateRecord()&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-edit-delete&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;Delete:&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein Datensatz gelöscht (&lt;code&gt;GedcomRecord::deleteRecord()&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;cronjob:log-search&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;code&gt;search&lt;/code&gt;, –&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;eine Suche ausgeführt (&lt;strong&gt;eine Log-Zeile pro durchsuchtem Baum&lt;/strong&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;strong&gt;Payload:&lt;/strong&gt; &lt;code&gt;log_id&lt;/code&gt;, &lt;code&gt;log_time&lt;/code&gt;, &lt;code&gt;log_message&lt;/code&gt; (auf 250 Zeichen gekürzt, UTF-8-safe) plus &lt;code&gt;gedcom_id&lt;/code&gt; / &lt;code&gt;user_id&lt;/code&gt;, wenn die Log-Zeile sie trägt. Die Nachrichten-Präfixe sind die hartkodierten englischen Strings des aktuellen Cores; ein Core-Update, das sie ändert, stoppt das passende Ereignis still (kein Fallback per Design) — die Event-Katalog-Beschreibungen und die &lt;code&gt;test-pseudo-events&lt;/code&gt;-Suite fixieren die aktuelle Zuordnung.&lt;/p&gt;</description></item><item><title>Selbst-Registrierung</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/howto-use/self-registration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/howto-use/self-registration/</guid><description>&lt;p&gt;Andere Module können ihre &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/"&gt;geplanten Jobs&lt;/a&gt; &lt;em&gt;anbieten&lt;/em&gt;, damit sie in der Admin-UI erscheinen, ohne dass jemand die Registry manuell editiert. Dazu können zwei Wege beschritten werden (ein Modul kann beide verwenden) - beide werden automatisch bei jedem &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/"&gt;Tick&lt;/a&gt; entdeckt, wobei dies nur für &lt;strong&gt;aktivierte&lt;/strong&gt; Module gilt:&lt;/p&gt;&#10;&lt;h2 id="marker-methode"&gt;Marker-Methode&lt;a class="td-heading-self-link" href="#marker-methode" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;getCronJobs(): array&lt;/code&gt; in der Modul-&lt;a href="https://github.com/bschwede/wt-cronjob/tree/main/module.php" target="_blank" rel="noopener"&gt;&lt;code&gt;module.php&lt;/code&gt;&lt;/a&gt;&#10;-Klasse, die dasselbe Format zurückgibt. Entsprechend: &lt;code&gt;getModuleEvents(): array&lt;/code&gt;, &lt;code&gt;getModuleCommands(): array&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="manifest-datei-empfohlen"&gt;Manifest-Datei (empfohlen)&lt;a class="td-heading-self-link" href="#manifest-datei-empfohlen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Bereitstellung einer Datei im Modulverzeichnis (&lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cron-jobs.php&lt;/code&gt;), die ein Array von Job-Spezifikationen zurückgibt:&lt;/p&gt;</description></item><item><title>Admin-Einstellungen</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/setup/settings/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/setup/settings/</guid><description>&lt;p&gt;Verfügbare Optionen auf der Admin-Seite:&lt;/p&gt;&#10;&lt;h2 id="ereignis-katalog"&gt;Ereignis-Katalog&lt;a class="td-heading-self-link" href="#ereignis-katalog" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Die Admin-Seite (Events-Abschnitt) und die Ereignisnamen-Vorschläge im Job-Formular werden von einer &lt;strong&gt;Ereignis-Inventur&lt;/strong&gt; (&lt;code&gt;cj_event_catalog&lt;/code&gt;, vom &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/"&gt;Tick&lt;/a&gt; synchronisiert wie die Job-Registry) gespeist. Sie mischt in dieser Prioritätsreihenfolge:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/"&gt;Events&lt;/a&gt;, &lt;strong&gt;von Modulen angekündigt&lt;/strong&gt; (Manifest-&lt;code&gt;events&lt;/code&gt;-Abschnitt / &lt;code&gt;getModuleEvents()&lt;/code&gt;), namespaced &lt;code&gt;&amp;lt;module&amp;gt;:&amp;lt;name&amp;gt;&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/pseudo/"&gt;&lt;strong&gt;eingebaute Pseudo-Events&lt;/strong&gt;&lt;/a&gt; (&lt;code&gt;cronjob:*&lt;/code&gt;, von den Detektoren)&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/route/"&gt;&lt;strong&gt;Route-Events&lt;/strong&gt;&lt;/a&gt; (&lt;code&gt;_route:*&lt;/code&gt;, abgeleitet aus der live Routentabelle)&lt;/li&gt;&#10;&lt;li&gt;Ereignisnamen, die derzeit &lt;strong&gt;abgehört&lt;/strong&gt; werden von einem aktiven Event-Job (Quelle &lt;code&gt;listening&lt;/code&gt;) — dies deckt Webhook-only-Namen ab&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Jeder Eintrag trägt seine Quelle, eine Beschreibung (als Übersetzungsschlüssel gespeichert, nur zur Render-Zeit übersetzt) und die bekannten Payload-Parameter-Namen. Für &lt;strong&gt;Route-Events&lt;/strong&gt; wird der Payload &lt;strong&gt;aus dem Routenpfad abgeleitet&lt;/strong&gt;: die &lt;code&gt;{param}&lt;/code&gt;-Platzhalter in der Reihenfolge ihres Auftretens, wobei &lt;code&gt;{tree}&lt;/code&gt; sich zu &lt;code&gt;tree&lt;/code&gt; + &lt;code&gt;tree_name&lt;/code&gt; ausdehnt (spiegelnd, was der live Event-Payload trägt). Für &lt;strong&gt;Pseudo-Events&lt;/strong&gt; kommen beide vom Detektor (&lt;code&gt;description()&lt;/code&gt; / &lt;code&gt;payloadKeys()&lt;/code&gt;). Die vollständige Liste ist auch das, was das &amp;ldquo;Ereignisname&amp;rdquo;-Datalist im Job-Formular bietet. Der Katalog wird als Client-seitige &lt;strong&gt;DataTables&lt;/strong&gt; (Sortieren/Filtern/Paginieren) im Events-Abschnitt gerendert.&lt;/p&gt;</description></item><item><title>Admin-Einstellungen</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/settings/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/settings/</guid><description>&lt;p&gt;Im oberen Bereich der Admin-Seite ist es möglich auf die administrative &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/xref-overview/"&gt;Querverweis-Übersicht&lt;/a&gt; und die Funktion &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/renumber/"&gt;xref_IDs neu nummerieren (mit Verweisen)&lt;/a&gt; zuzugreifen. &lt;br&gt;&#10;Ferner können die Grundfunktionen (de-)aktiviert werden:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/"&gt;Erweiterte Links&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/"&gt;Markdown Verbesserungen&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Hilfsfunktionen (&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/wthb/"&gt;Webtrees Handbuch&lt;/a&gt;)&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/home-link/"&gt;Home-Link&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/uid-lookup/"&gt;UID-Abfrage&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Bei Aktivierung der ersten vier Grundfunktionen können weiter unten noch detailliertere Einstellungen vorgenommen werden. Auch gibt es zwei globale Einstellungen für Debugausgaben in der JavaScript-Konsole des Browsers und der Webserver-Fehlerlogdatei und man kann sich entscheiden, ob Links grundsätzlich in einem neuen Browsertab geöffnet werden sollen (je nach Grundfunktion differenzierte Einstellung ist auch möglich).&lt;/p&gt;</description></item><item><title>Klassenhierarchie</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/class-hierarchy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/class-hierarchy/</guid><description>&lt;p&gt;&lt;em&gt;Automatisch generiert durch &lt;code&gt;docs/tools/generate-class-hierarchy.php&lt;/code&gt; — nicht manuell bearbeiten.&lt;/em&gt;&lt;/p&gt;&#10;&lt;h2 id="modul"&gt;Modul&lt;a class="td-heading-self-link" href="#modul" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;LinkEnhancerModule&lt;/code&gt; extends &lt;code&gt;AbstractModule&lt;/code&gt; implements &lt;code&gt;MiddlewareInterface&lt;/code&gt;, &lt;code&gt;ModuleCustomInterface&lt;/code&gt;, &lt;code&gt;ModuleGlobalInterface&lt;/code&gt;, &lt;code&gt;ModuleConfigInterface&lt;/code&gt;, &lt;code&gt;ModuleDataFixInterface&lt;/code&gt;, &lt;code&gt;ModuleListInterface&lt;/code&gt;, &lt;code&gt;ModuleTabInterface&lt;/code&gt;, &lt;code&gt;SettingInterface&lt;/code&gt; — &lt;code&gt;LinkEnhancerModule.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;SettingInterface&lt;/code&gt; — &lt;code&gt;SettingInterface.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;LinkEnhancerUtils&lt;/code&gt; — &lt;code&gt;LinkEnhancerUtils.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;LinkEnhancerModuleExt&lt;/code&gt; extends &lt;code&gt;LinkEnhancerModule&lt;/code&gt; implements &lt;code&gt;ModuleExtGlobalInterface&lt;/code&gt; — &lt;code&gt;LinkEnhancerModuleExt.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="commonmark-extensions"&gt;CommonMark (Extensions)&lt;a class="td-heading-self-link" href="#commonmark-extensions" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;LeImageRenderer&lt;/code&gt; (final) implements &lt;code&gt;NodeRendererInterface&lt;/code&gt;, &lt;code&gt;XmlNodeRendererInterface&lt;/code&gt;, &lt;code&gt;ConfigurationAwareInterface&lt;/code&gt; — &lt;code&gt;CommonMark/LeImageRenderer.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;SmartPunctHelper&lt;/code&gt; — &lt;code&gt;CommonMark/SmartPunctHelper.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;LeTableOfContentsRenderer&lt;/code&gt; (final) implements &lt;code&gt;NodeRendererInterface&lt;/code&gt;, &lt;code&gt;XmlNodeRendererInterface&lt;/code&gt; — &lt;code&gt;CommonMark/LeTableOfContentsRenderer.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="factories"&gt;Factories&lt;a class="td-heading-self-link" href="#factories" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;CustomMarkdownFactory&lt;/code&gt; extends &lt;code&gt;MarkdownFactory&lt;/code&gt; — &lt;code&gt;Factories/CustomMarkdownFactory.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="request-handler"&gt;Request-Handler&lt;a class="td-heading-self-link" href="#request-handler" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;DataFixBlocksAction&lt;/code&gt; implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/DataFixBlocksAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;HelpWthbAction&lt;/code&gt; implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/HelpWthbAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;XrefDetailData&lt;/code&gt; (final) implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/XrefDetailData.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;XrefOverviewListData&lt;/code&gt; (final) implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/XrefOverviewListData.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;GotoIdTreeAction&lt;/code&gt; extends &lt;code&gt;GotoIdAction&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/GotoIdTreeAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;GotoUidTreeAction&lt;/code&gt; extends &lt;code&gt;GotoUidAction&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/GotoUidTreeAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;GotoXrefAction&lt;/code&gt; implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/GotoXrefAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;DataFixRebuildIndexAction&lt;/code&gt; implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/DataFixRebuildIndexAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;RenumberActionHandler&lt;/code&gt; (final) — &lt;code&gt;Http/RequestHandlers/RenumberActionHandler.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;HelpMdAction&lt;/code&gt; implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/HelpMdAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;AdminXrefOverviewData&lt;/code&gt; (final) implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/AdminXrefOverviewData.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;GotoIdAction&lt;/code&gt; extends &lt;code&gt;AbstractGotoAction&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/GotoIdAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;HelpWtCoreAction&lt;/code&gt; implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/HelpWtCoreAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;WthbAdminHandler&lt;/code&gt; (final) — &lt;code&gt;Http/RequestHandlers/WthbAdminHandler.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;GotoUidAction&lt;/code&gt; extends &lt;code&gt;AbstractGotoAction&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/GotoUidAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;AbstractGotoAction&lt;/code&gt; (abstract) implements &lt;code&gt;RequestHandlerInterface&lt;/code&gt; — &lt;code&gt;Http/RequestHandlers/AbstractGotoAction.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="schema"&gt;Schema&lt;a class="td-heading-self-link" href="#schema" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;SeedHelpTable&lt;/code&gt; implements &lt;code&gt;SeedInterface&lt;/code&gt; — &lt;code&gt;Schema/SeedHelpTable.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration6&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration6.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration2&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration2.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration7&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration7.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration3&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration3.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration4&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration4.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration1&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration1.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration5&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration5.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Migration0&lt;/code&gt; implements &lt;code&gt;MigrationInterface&lt;/code&gt; — &lt;code&gt;Schema/Migration0.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="services"&gt;Services&lt;a class="td-heading-self-link" href="#services" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;AdminSettingsBuilder&lt;/code&gt; (final) — &lt;code&gt;Services/AdminSettingsBuilder.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;MarkdownEditorActivationService&lt;/code&gt; (final) — &lt;code&gt;Services/MarkdownEditorActivationService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;IndexRebuildScheduler&lt;/code&gt; (final) — &lt;code&gt;Services/IndexRebuildScheduler.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;UidTagCollector&lt;/code&gt; (final) — &lt;code&gt;Services/UidTagCollector.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;TextTagCollector&lt;/code&gt; (final) — &lt;code&gt;Services/TextTagCollector.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ContentBuilder&lt;/code&gt; (final) — &lt;code&gt;Services/ContentBuilder.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;RenumberWithLinksService&lt;/code&gt; (final) — &lt;code&gt;Services/RenumberWithLinksService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;DataFiles&lt;/code&gt; (final) — &lt;code&gt;Services/DataFiles.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;XrefOverviewColumns&lt;/code&gt; (final) — &lt;code&gt;Services/XrefOverviewColumns.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;LinkIndexService&lt;/code&gt; (final) — &lt;code&gt;Services/LinkIndexService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;XrefsService&lt;/code&gt; (final) — &lt;code&gt;Services/XrefsService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;XrefDetailService&lt;/code&gt; (final) — &lt;code&gt;Services/XrefDetailService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;WthbService&lt;/code&gt; — &lt;code&gt;Services/WthbService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;IdResolver&lt;/code&gt; (final) — &lt;code&gt;Services/IdResolver.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;LinkRenderer&lt;/code&gt; (final) — &lt;code&gt;Services/LinkRenderer.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;WthbTocService&lt;/code&gt; (final) — &lt;code&gt;Services/WthbTocService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;UidIndexService&lt;/code&gt; (final) — &lt;code&gt;Services/UidIndexService.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="datafix"&gt;DataFix&lt;a class="td-heading-self-link" href="#datafix" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;FixHandlerInterface&lt;/code&gt; — &lt;code&gt;DataFix/FixHandlerInterface.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;DataFixDispatcher&lt;/code&gt; — &lt;code&gt;DataFix/DataFixDispatcher.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;TreeLookupTrait&lt;/code&gt; — &lt;code&gt;DataFix/TreeLookupTrait.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;DanglingLinksFix&lt;/code&gt; (final) implements &lt;code&gt;FixHandlerInterface&lt;/code&gt; — &lt;code&gt;DataFix/Handlers/DanglingLinksFix.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;DuplicateUidFix&lt;/code&gt; (final) implements &lt;code&gt;FixHandlerInterface&lt;/code&gt; — &lt;code&gt;DataFix/Handlers/DuplicateUidFix.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;WtTypeFix&lt;/code&gt; (final) implements &lt;code&gt;FixHandlerInterface&lt;/code&gt; — &lt;code&gt;DataFix/Handlers/WtTypeFix.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;XrefUidSwapFix&lt;/code&gt; (final) implements &lt;code&gt;FixHandlerInterface&lt;/code&gt; — &lt;code&gt;DataFix/Handlers/XrefUidSwapFix.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;AmbiguousUidFix&lt;/code&gt; (final) implements &lt;code&gt;FixHandlerInterface&lt;/code&gt; — &lt;code&gt;DataFix/Handlers/AmbiguousUidFix.php&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>Route-Events</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/route/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/route/</guid><description>&lt;p&gt;Ein ergänzender, &lt;em&gt;sofortiger&lt;/em&gt; Detektionsmechanismus: anstatt Zustand nach Zeitplan zu pollen, beobachtet das Modul die HTTP-Anfrage selbst. Wenn eine Anfrage an eine &lt;strong&gt;abgebildete mutierende Route&lt;/strong&gt; erfolgreich bearbeitet wurde (2xx/3xx), queue sie das passende Ereignis in dieselbe &lt;code&gt;cj_event&lt;/code&gt;-Queue — ein abhörender Event-Job reagiert dann beim nächsten Tick (~60 s), ohne Polling-Latenz.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Welche Routes abgebildet sind&lt;/strong&gt; — zwei Regeln, beide abgeleitet aus der live webtrees-Routentabelle. Gemeinsame Voraussetzungen: Pfad beginnt mit &lt;code&gt;/tree/{tree}/&lt;/code&gt;, der Handler ist im webtrees-Request-Handler-Namespace (&lt;code&gt;RequestHandlers&lt;/code&gt; in 2.2.6, &lt;code&gt;Controllers&lt;/code&gt; in 2.3), und die Anfrage ist eine &lt;strong&gt;POST&lt;/strong&gt;-Mutation. In 2.2.6 wird dies bei der Abbildung erzwungen (GET-Seiten-Routes werden nicht abgebildet); in 2.3 trägt die Route keine HTTP-Methode, daher erfolgt die POST-Prüfung zur Auslösezeit und das GET-Formular-Load derselben Route wird ignoriert.&lt;/p&gt;</description></item><item><title>Verwendung</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/usage/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/usage/</guid><description>&lt;h2 id="job-erstellen"&gt;Job erstellen&lt;a class="td-heading-self-link" href="#job-erstellen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;Steuerungspanel → Cron Job Scheduler → Neuer Job&lt;/code&gt;:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Feld&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Bedeutung&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Name (Slug)&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;technischer Bezeichner, &lt;code&gt;a-z 0-9 _ -&lt;/code&gt;. &lt;strong&gt;Nur-lesen für &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/howto-use/self-registration/"&gt;durch Module angebotene Jobs&lt;/a&gt;&lt;/strong&gt; (deren &lt;code&gt;&amp;lt;module&amp;gt;:&amp;lt;name&amp;gt;&lt;/code&gt;-Schlüssel ist fix); editierbar für selbst erstellte Jobs.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Titel&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;menschenlesbarer Name&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Trigger&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein oder mehrere &lt;strong&gt;Zeit-Trigger&lt;/strong&gt; (Cron-Zeitpläne) und/oder &lt;strong&gt;Ereignis-Trigger&lt;/strong&gt; — der Job feuert, wenn &lt;em&gt;irgendein&lt;/em&gt; Trigger feuert. Mindestens einer ist erforderlich.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Cron-Ausdruck&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;(Zeit-Trigger) Standard-5-Feld-Cron oder ein Makro (&lt;code&gt;@daily&lt;/code&gt;, &lt;code&gt;@weekly&lt;/code&gt;, …). &lt;strong&gt;Zeiten sind UTC.&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Ereignisname&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;(Ereignis-Trigger) das &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/"&gt;Ereignis&lt;/a&gt;, auf das dieser Job reagiert. Slug oder &lt;code&gt;&amp;lt;domain&amp;gt;:slug&lt;/code&gt;, max. 64 Zeichen.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Befehl&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein &lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cli/&amp;lt;script&amp;gt;.php&lt;/code&gt;-Pfad oder ein erlaubter Core-Befehl.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Argumente&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;nur einfache Optionen/Werte (z.B. &lt;code&gt;--limit=5000&lt;/code&gt;), max. 10 Tokens&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Timeout&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;30 - 3600 s&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Bei Fehler benachrichtigen&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Opt-in: Admin-Konten bei Job-Fehlern benachrichtigen&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Verfügbare Ereignisnamen und Befehle werden als Datalists bereitgestellt, um die Dateneingabe zu erleichtern.&lt;/p&gt;</description></item><item><title>Markdown-Bild-Unterstützung</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/md-image/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/md-image/</guid><description>&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/le/screenshot_note-with-links-and-img.png"&#10; alt="Notiz mit Links"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;&#10;&lt;p&gt;Diese Funktion erlaubt es, Bilder aus GEDCOM-Mediendatensätzen (die hinter der Media-Firewall liegen) oder aus dem öffentlichen Verzeichnis in Notizen einzubetten. Wenn Restriktionsregeln auf den Datensatz zutreffen, wird statt des Bildes eine Meldung angezeigt.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;![Alternativtext für GEDCOM-Objekt](#@id=@M1@)&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;![Alternativtext für Bild im öffentlichen Ordner](#@public=webtrees.png &amp;quot;Titel&amp;quot;)&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;![Bild mit definierter Höhe, Breite und zusätzlicher CSS-Klasse](#@id=@M1@&amp;amp;h=200&amp;amp;w=200&amp;amp;cname=float-right)&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Technisch werden die Bilder in einen div-Container zusammen mit einem Bild-Untertitel gepackt — der auch ein Link zum Mediendatensatz ist. Die Darstellung kann wie gewünscht mit den Standard-CSS-Klassen oder zusätzlichen per-Bild-CSS-Klassen angepasst werden (z.B. &lt;code&gt;float-start&lt;/code&gt; oder &lt;code&gt;float-end&lt;/code&gt; aus webtrees vendor.css).&lt;/p&gt;</description></item><item><title>Markdown-Editor</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/mde/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/mde/</guid><description>&lt;p&gt;Man kann einen visuellen &lt;strong&gt;Markdown-Editor&lt;/strong&gt; (mde) für Notiz-Textareas aktivieren. Unter der Haube wird das Projekt &lt;a href="https://github.com/jefago/tiny-markdown-editor"&gt;TinyMDE - A tiny, dependency-free embeddable HTML/JavaScript Markdown editor&lt;/a&gt; verwendet.&lt;/p&gt;&#10;&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/le/screenshot_tinymde-sharednote.png"&#10; alt="Markdown-Editor"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;&#10;&lt;p&gt;Neben der Syntax-Hervorhebung wird eine Icon-Leiste für gängige Formatierungsbefehle, ein Hilfe-Popup und Zeilennummerierung mitgeliefert.&lt;/p&gt;&#10;&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/le/screenshot_markdown-help.png"&#10; alt="Markdown-Hilfe"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Hinweis:&lt;/strong&gt; Die On-Screen-Tastatur funktioniert leider nicht mehr wie zuvor mit dem vorherigen Texteingabefeld. Die gewählten Zeichen landen als Zwischenschritt im kleinen Textfeld unter dem Markdown-Editor und müssen manuell an die gewünschte Position kopiert werden.&lt;/p&gt;</description></item><item><title>Markdown-Erweiterungen</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/md-extensions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/md-extensions/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Warnung:&lt;/strong&gt; Bitte bedenken Sie bei der Verwendung dieser Erweiterungen, dass Sie vom kleinsten gemeinsamen Markdown-Dialekt abweichen. Wenn die Bibliothek, die Markdown in HTML rendert, aus irgendeinem Grund geändert werden muss, ist es möglich, dass nicht alle hier verwendeten erweiterten Markup unterstützt werden (siehe auch &lt;a href="https://codeberg.org/bschwede/linkenhancer/issues/32"&gt;#32&lt;/a&gt;). Da das Markup nicht aufdringlich ist, sollte der Impact nicht gravierend sein — natürlich ist es ein kleiner Nachteil.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;Das Paket &lt;a href="https://commonmark.thephpleague.com/"&gt;League\CommonMarkdown&lt;/a&gt;, das zur Verarbeitung von Markdown-Texten verwendet wird, bietet mehrere nützliche Erweiterungen, die optional aktiviert werden können:&lt;/p&gt;</description></item><item><title>Der Tick</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/</guid><description>&lt;p&gt;Der &lt;strong&gt;Tick&lt;/strong&gt; ist das Herz des Moduls: einmal pro Minute prüft er alle aktivierten Jobs, entscheidet, was fällig ist, und führt es aus. Weder das webtrees-Core noch das Betriebssystem planen selbst — sie starten nur &lt;a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/tick.php" target="_blank" rel="noopener"&gt;&lt;code&gt;tick.php&lt;/code&gt;&lt;/a&gt;&#10;.&lt;/p&gt;&#10;&#10;&#10;&#10;&lt;pre class="mermaid"&gt;flowchart TD&#10; subgraph Triggers[&amp;#34;`⏱ Auslöser *(once per minute)*`&amp;#34;]&#10; CRON[&amp;#34;`🕑 OS cron / systemd&amp;lt;br/&amp;gt;*every minute*`&amp;#34;]&#10; WATCH[&amp;#34;`👁 watch-Daemon&amp;lt;br/&amp;gt;*(in-module)*`&amp;#34;]&#10; end&#10;&#10; subgraph Guard[&amp;#34;🛡 Guard&amp;#34;]&#10; TP[&amp;#34;`📄 cli/tick.php · **cron:tick**&amp;lt;br/&amp;gt;*guard(): 403 over HTTP*`&amp;#34;]&#10; OFF{&amp;#34;`⚠ site offline?&amp;lt;br/&amp;gt;*data/offline.txt*`&amp;#34;}&#10; BOOT[&amp;#34;`🚀 boot()&amp;lt;br/&amp;gt;*webtrees &amp;#43; DB*`&amp;#34;]&#10; end&#10;&#10; subgraph Selection[&amp;#34;🔎 Arbeit auswählen&amp;#34;]&#10; TIME[&amp;#34;`📅 time-based jobs&amp;lt;br/&amp;gt;**next_run_at due** *(UTC)*`&amp;#34;]&#10; CE[(&amp;#34;`📦 cj_event&amp;lt;br/&amp;gt;*Event-Warteschlange*`&amp;#34;)]&#10; DRAIN[&amp;#34;`🧮 drain queue&amp;lt;br/&amp;gt;*coalesced · 60 s budget*`&amp;#34;]&#10; end&#10;&#10; subgraph Execution[&amp;#34;`⚙ Ausführung *(isolated child)*`&amp;#34;]&#10; RUN[&amp;#34;`🧪 JobRunner&amp;lt;br/&amp;gt;**proc_open**`&amp;#34;]&#10; LIM[&amp;#34;`⏲ timeout 30–3600 s&amp;lt;br/&amp;gt;last **64 KB** · exit code`&amp;#34;]&#10; end&#10;&#10; subgraph Storage[&amp;#34;💾 Speicherung&amp;#34;]&#10; CJRUN[(&amp;#34;`cj_run&amp;lt;br/&amp;gt;*Laufverlauf*`&amp;#34;)]&#10; MARK[&amp;#34;`🏷 tick.last&amp;lt;br/&amp;gt;*stale &amp;gt; 300 s → tick_stale*`&amp;#34;]&#10; end&#10;&#10; CRON --&amp;gt; Guard&#10; WATCH --&amp;gt; Guard&#10; TP --&amp;gt; OFF&#10; OFF --&amp;gt;|&amp;#34;offline&amp;#34;| SKIP[&amp;#34;⏭ Tick überspringen&amp;#34;]&#10; OFF --&amp;gt;|&amp;#34;online&amp;#34;| BOOT&#10; BOOT --&amp;gt; TIME&#10; BOOT --&amp;gt; DRAIN&#10; CE --&amp;gt; DRAIN&#10; TIME --&amp;gt; Execution&#10; DRAIN --&amp;gt; Execution&#10; RUN --&amp;gt; LIM&#10; LIM --&amp;gt; CJRUN&#10; BOOT --&amp;gt; MARK&#10;&#10; classDef sourceStyle fill:#e3f2fd,stroke:#1565C0,stroke-width:2px&#10; classDef queueStyle fill:#fff3e0,stroke:#E65100,stroke-width:2px&#10; classDef tickStyle fill:#e8f5e9,stroke:#2E7D32,stroke-width:2px&#10; classDef execStyle fill:#fce4ec,stroke:#C2185B,stroke-width:2px&#10; classDef storageStyle fill:#f5f5f5,stroke:#616161,stroke-width:1px&#10;&#10; class CRON,WATCH sourceStyle&#10; class OFF,CE queueStyle&#10; class TP,TIME,DRAIN tickStyle&#10; class RUN,LIM execStyle&#10; class CJRUN,MARK,SKIP storageStyle&#10;&lt;/pre&gt;&#10;&lt;h2 id="was-einen-tick-startet"&gt;Was einen Tick startet&lt;a class="td-heading-self-link" href="#was-einen-tick-startet" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Einen Trigger wählen (einmalig):&lt;/p&gt;</description></item><item><title>Deutsches webtrees Handbuch (WTHB)</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/wthb/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/wthb/</guid><description>&lt;figure class="logo-figure float-end m-3"&gt;&#10; &lt;img src="https://bschwede.codeberg.page/wt-modules/img/heros/CG-Logo-2018_135px.png" alt="CompGen-Logo" style="width: 160px; height: auto;" loading="lazy" title=""&gt;&#10;&#10; &#10;&lt;/figure&gt;&#10;&lt;p&gt;Ein &lt;strong&gt;kontextsensitiver Hilfe-Link&lt;/strong&gt; zum &lt;a href="https://wiki.genealogy.net/Webtrees_Handbuch"&gt;deutschen webtrees Handbuch&lt;/a&gt; kann dem kleinen Navigationsmenü hinzugefügt werden. Kontext-Links sind auch für Komponenten auf Seiten von Custom-Modulen verfügbar (z.B. auf der Personenseite, der Startseite oder bei Elementen im Hauptmenü) — diese sind an den i-Symbolen in einem Kreis erkennbar.&lt;/p&gt;&#10;&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/le/screenshot_small-menu-wthb-link.png"&#10; alt="Kopfmenü mit Hilfe-Link"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/le/screenshot_wthb-subcontext.png"&#10; alt="WTHB Subkontext-Hilfe"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;&#10;&lt;p&gt;Zur Sicherstellung, dass diese Funktion auch im Admin-Bereich verfügbar ist, muss eine modifizierte Version von &lt;a href="https://github.com/fisharebest/webtrees/blob/main/resources/views/layouts/administration.phtml"&gt;views/layouts/administration.phtml&lt;/a&gt; registriert werden. Dieses Modul versucht, das Custom-Modul &lt;a href="https://github.com/vesta-webtrees-2-custom-modules/vesta_common"&gt;vesta_common&lt;/a&gt; zu verwenden (falls installiert und aktiviert) oder seine eigene Version der View-Layout-Datei. Alternativ kann auch Patch P002 auf den Core-Code angewendet werden.&lt;/p&gt;</description></item><item><title>Entwicklungsumgebung</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/dev-environment/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/dev-environment/</guid><description>&lt;p&gt;Was man zum Bauen und Testen des Moduls lokal braucht.&lt;/p&gt;&#10;&lt;h2 id="voraussetzungen"&gt;Voraussetzungen&lt;a class="td-heading-self-link" href="#voraussetzungen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Komponente&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Version&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Hinweise&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PHP&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;8.3+&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;dieselbe Version, mit der die webtrees-Instanz läuft&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Composer&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2.x&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;installiert &lt;code&gt;wt-shared-libs&lt;/code&gt; + &lt;code&gt;phpstan&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Node.js&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;18+ (LTS)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;für Gulp / Rollup / Mocha&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;webtrees&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2.2.x oder 2.3.x&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nötig für PHPStan (&lt;code&gt;app/&lt;/code&gt;-Klassen) und die Smoke-Tests&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/wt-shared-libs/"&gt;wt-shared-libs&lt;/a&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;neueste Version&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Schwester-Repo unter &lt;code&gt;modules_v4/wt-shared-libs&lt;/code&gt; (Composer-Path-Repo)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="lage"&gt;Lage&lt;a class="td-heading-self-link" href="#lage" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Das Modul liegt innerhalb einer webtrees-Installation unter &lt;code&gt;modules_v4/linkenhancer/&lt;/code&gt;. Sein &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/composer.json" target="_blank" rel="noopener"&gt;&lt;code&gt;composer.json&lt;/code&gt;&lt;/a&gt;&#10; zieht die Schwester-Bibliothek als lokales Path-Repository ein:&lt;/p&gt;</description></item><item><title>Tabellen-Zellenhöhe steuern</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/cell-height/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/markdown/cell-height/</guid><description>&lt;p&gt;Für längere Markdown-Notiztexte ist es manchmal mühsam, scrollen zu müssen, wenn man sich für die Fakten darunter interessiert. Diese Funktion sollte hier weiterhelfen: Durch Aktivieren des Häkchens in der oberen rechten Ecke der Titelspalte (erste Tabellenspalte) wird die maximale Höhe der Inhaltszelle mit der langen Notiz auf ca. 80% der Viewport-Höhe gesetzt. Damit wird der Inhalt selbst scrollbar.&lt;/p&gt;&#10;&lt;p&gt;Wo anwendbar, kann die Funktion standardmäßig aktiviert (oder einfach verfügbar gemacht) und auch unabhängig deaktiviert werden.&lt;/p&gt;</description></item><item><title>Home-Link</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/home-link/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/home-link/</guid><description>&lt;p&gt;Der Seitentitel kann ein Link zur Baum-Startseite oder zur Benutzer-Mein-Seite sein. Der Webmaster kann auch eine benutzerdefinierte URL setzen.&lt;/p&gt;&#10;&lt;p&gt;&#10;&#10;&#10;&#10; &#10;&#10; &#10;&#10; &#10; &#10; &#10;&#10; &#10; &#10; &#10;&#10;&#10;&lt;img&#10; src="https://bschwede.codeberg.page/wt-modules/img/le/screenshot_sitetitle-as-link.png"&#10; alt="Seitentitel als Link"&#10; &#10; loading="lazy"&#10;&gt;&lt;/p&gt;&#10;&lt;p&gt;Dynamische CSS-Stile können angewendet werden, um dem aktuellen Theme zu entsprechen und sicherzustellen, dass die Anzeige gut kontrastiert. Natürlich ist es nicht auf den Home-Link-Fall beschränkt - Details siehe &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/setup/settings/"&gt;Admin-Einstellungen&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>CLI-Skripte</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/</guid><description>&lt;h2 id="skripte"&gt;Skripte&lt;a class="td-heading-self-link" href="#skripte" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php &lt;span style="color:#6e738d;font-style:italic"&gt;# alle fälligen Jobs ausführen&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --dry-run &lt;span style="color:#6e738d;font-style:italic"&gt;# anzeigen, was ausgeführt würde&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --job&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&amp;lt;name&amp;gt; &lt;span style="color:#6e738d;font-style:italic"&gt;# einen bestimmten Job jetzt ausführen&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --strict &lt;span style="color:#6e738d;font-style:italic"&gt;# Exit 1 wenn ein Job fehlgeschlagen ist&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --full-output &lt;span style="color:#6e738d;font-style:italic"&gt;# vollständige Job-Ausgabe echo (Debugging!)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/watch.php &lt;span style="color:#6e738d;font-style:italic"&gt;# Watch-Daemon starten&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Exit-Codes: &lt;code&gt;0&lt;/code&gt; = Tick lief (Job-Fehler werden in der DB protokolliert), &lt;code&gt;1&lt;/code&gt; = Umgebungsproblem oder (mit &lt;code&gt;--strict&lt;/code&gt;) mindestens ein Job fehlgeschlagen.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Log-Hygiene:&lt;/strong&gt; stdout trägt nur Summary-Zeilen. Die vollständige Job-Ausgabe liegt in der Ausführungshistorie (nur Admin). &lt;code&gt;--full-output&lt;/code&gt; niemals in einen weltlesbaren Ort umleiten.&lt;/p&gt;</description></item><item><title>Querverweis-Übersicht</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/xref-overview/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/xref-overview/</guid><description>&lt;p&gt;Es gibt drei Arten von Übersichten:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Übersicht über alle Daten für den Admin (&lt;strong&gt;Admin-Übersicht&lt;/strong&gt;),&lt;/li&gt;&#10;&lt;li&gt;auf einen Stammbaum begrenzte Übersicht (&lt;strong&gt;Benutzer-Übersicht&lt;/strong&gt;) und&lt;/li&gt;&#10;&lt;li&gt;auf einen Datensatz bezogene Übersicht in der Detailansicht (&lt;strong&gt;Datensatz-Übersicht&lt;/strong&gt;, als Tab oder Modal).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Die &lt;strong&gt;Admin-Übersicht&lt;/strong&gt; (Verwaltung → LinkEnhancer → Querverweis-Übersicht) ist eine serverseitig paginierte DataTable. Sie listet alle Datensätze auf, die klassische &lt;code&gt;@XREF@&lt;/code&gt;-Querverweise oder LinkEnhancer-Links enthalten, mit einer Link-Auflistung pro-Datensatz.&lt;/p&gt;&#10;&lt;p&gt;Optionale Filter:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;referenzierte XREF (nur verfügbar, während ein frischer Link-Index aktiv ist — im Live-Scan-Modus ist das Feld ausgeblendet, da es dort nur ein grober Vorfilter wäre — keine klassischen Referenzen würden gefunden),&lt;/li&gt;&#10;&lt;li&gt;Datensatz-Typ,&lt;/li&gt;&#10;&lt;li&gt;Stammbaum und&lt;/li&gt;&#10;&lt;li&gt;die Anzahl der pro Link-Klasse angezeigten Token (alle / 5 / 10 / 20, Default 5).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Die XREF-Zelle zeigt den Stammbaumnamen als zweite Zeile in dezenter Schrift. Der Datensatz-Typ ist eine eigene sortierbare Spalte. Jedes Inventar-Token wird als kurzer Anzeigekontext (Snippet) mit dem Link-Token selbst in Fett angezeigt.&lt;/p&gt;</description></item><item><title>Build-System</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/build-system/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/build-system/</guid><description>&lt;p&gt;Bundling, Übersetzungs-Kompilierung und Versionierung werden über &lt;a href="https://gulpjs.com/"&gt;&lt;strong&gt;Gulp&lt;/strong&gt;&lt;/a&gt;-Tasks in &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/gulpfile.mjs" target="_blank" rel="noopener"&gt;&lt;code&gt;gulpfile.mjs&lt;/code&gt;&lt;/a&gt;&#10; gesteuert, aufgerufen mit &lt;code&gt;npx gulp &amp;lt;task&amp;gt;&lt;/code&gt;. Die &lt;code&gt;npm run *&lt;/code&gt;-Skripte decken nur das Testing ab — siehe die Seite &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/testing/"&gt;Testing&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="tasks"&gt;Tasks&lt;a class="td-heading-self-link" href="#tasks" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Task&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Befehl&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Wirkung&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;build&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp build&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;clean&lt;/code&gt; → JS (&lt;a href="https://rollupjs.org/"&gt;Rollup&lt;/a&gt;) + CSS (&lt;a href="https://postcss.org/"&gt;PostCSS&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;devbuild&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp devbuild&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;wie &lt;code&gt;build&lt;/code&gt;, aber Dev-Mode (kein Minify, SourceMaps)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;updatepo&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp updatepo&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;führt &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/util/update-po-files.sh" target="_blank" rel="noopener"&gt;&lt;code&gt;update-po-files.sh&lt;/code&gt;&lt;/a&gt;&#10; aus → &lt;code&gt;xgettext&lt;/code&gt; über &lt;code&gt;src/&lt;/code&gt; → &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/resources/lang/messages.pot" target="_blank" rel="noopener"&gt;&lt;code&gt;messages.pot&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;po2php&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp po2php&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;kompiliert &lt;code&gt;resources/lang/*.po&lt;/code&gt; → &lt;code&gt;resources/lang/*.php&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;syncversion&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp syncversion&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;hält &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/latest-version.txt" target="_blank" rel="noopener"&gt;&lt;code&gt;latest-version.txt&lt;/code&gt;&lt;/a&gt;&#10; ↔ &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/src/LinkEnhancerModule.php" target="_blank" rel="noopener"&gt;&lt;code&gt;LinkEnhancerModule.php&lt;/code&gt;&lt;/a&gt;&#10; synchron&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;bumpversion&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp bumpversion&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;erfordert einen sauberen git-Tree → Version-Bump → &lt;code&gt;syncversion&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;archive&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp archive&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;build&lt;/code&gt; + &lt;code&gt;po2php&lt;/code&gt; + &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/util/create-archive.sh" target="_blank" rel="noopener"&gt;&lt;code&gt;create-archive.sh&lt;/code&gt;&lt;/a&gt;&#10; (Release-ZIP)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;forgejo:issue-refs&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;npx gulp forgejo:issue-refs[:dry]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ergänzt Issue-Referenzen in Commit-Messages (braucht &lt;code&gt;FORGEJO_TOKEN&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt;) - wurde nur einmalig angewendet für die Übernahme des Repos von GitHub zu Codeberg&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="js--css-bundling"&gt;JS / CSS Bundling&lt;a class="td-heading-self-link" href="#js--css-bundling" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;build&lt;/code&gt; = &lt;code&gt;clean&lt;/code&gt; → (parallel) JS + CSS.&lt;/p&gt;</description></item><item><title>Sicherheit</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/security/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Nie eine Shell.&lt;/strong&gt; Befehle werden via &lt;a href="https://www.php.net/manual/de/function.proc-open.php"&gt;&lt;code&gt;proc_open&lt;/code&gt;&lt;/a&gt; mit einem &lt;a href="https://www.php.net/manual/de/reserved.variables.argv.php"&gt;argv-Array&lt;/a&gt; ausgeführt.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Befehls-Whitelist.&lt;/strong&gt; &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/"&gt;Modulskripte&lt;/a&gt; müssen &lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cli/&amp;lt;script&amp;gt;.php&lt;/code&gt; entsprechen, existieren und sich in einem &lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cli/&lt;/code&gt;-Verzeichnis auflösen. Core-Befehle sind auf die Read-only/Export-Allowlist beschränkt.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Argument-Validierung.&lt;/strong&gt; Jedes Argument-Token muss eine einfache Option oder ein Wert sein — keine Shell-Metazeichen, keine Leerzeichen in Tokens, max. 10 Tokens.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Arbeitsverzeichnisse.&lt;/strong&gt; Modulskripte laufen vom webtrees-Root; Core-Befehle laufen von &lt;code&gt;data/&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Keine sensiblen Daten in stdout.&lt;/strong&gt; Der &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/"&gt;Tick&lt;/a&gt; gibt nur Zusammenfassungen aus; die vollständige Ausgabe bleibt in der Ausführungshistorie (admin-only).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;UI-Aktionen&lt;/strong&gt; sind alle als &lt;code&gt;*Admin*&lt;/code&gt; benannt (nur Admin, &lt;a href="https://developer.mozilla.org/de/docs/Web/Security/Attacks/CSRF"&gt;CSRF&lt;/a&gt;-geschützt).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Notaus-Schalter:&lt;/strong&gt; Modul deaktivieren — der Tick tut dann nichts.&lt;/li&gt;&#10;&lt;li&gt;Der Tick ist Single-Instance (flock), und der Kindprozess eines Jobs wird nach dem Timeout hart getötet (&lt;a href="https://de.wikipedia.org/wiki/SIGKILL"&gt;&lt;code&gt;SIGKILL&lt;/code&gt;&lt;/a&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Bündelung von Ereigniswarteschlangen.&lt;/strong&gt; Eine Flut identischer &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/"&gt;Ereignisse&lt;/a&gt; wird zusammengeführt zu einem Joblauf.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Webhook-Token nur im Header.&lt;/strong&gt; Das Token wird ausschließlich im &lt;code&gt;X-Cronjob-Token&lt;/code&gt;-Header gesendet.&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>xref_IDs neu nummerieren (mit Verweisen)</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/renumber/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/renumber/</guid><description>&lt;p&gt;Die webtrees Standardfunktion für die Umnummerierung (Verwaltung → Stammbäume verwalten → [Stammbaum] → xref_IDs neu nummerieren) löst Stammbaumübergreifende XREF-Kollisionen auf, aktualisiert aber keine LinkEnhancer- oder klassischen Links. Dieses Modul bietet eine erweiterte Umnummerierungsfunktion, die alle betroffenen Links in einem Schritt repariert.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Zugriff:&lt;/strong&gt; Verwaltung → LinkEnhancer → xref_IDs neu nummerieren (mit Verweisen)&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Ablauf:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Den Stammbaum mit XREF-Kollisionen auswählen (doppelte XREFs mit anderen Bäumen).&lt;/li&gt;&#10;&lt;li&gt;Die Seite zeigt jede kollidierende XREF, ihren Record-Typ und die Anzahl der eingehenden LinkEnhancer-Referenzen aus dem Link-Index.&lt;/li&gt;&#10;&lt;li&gt;Beim Absenden wird jede kollidierende XREF:&#10;&lt;ul&gt;&#10;&lt;li&gt;in den GEDCOM-Core-Tabellen umbenannt (gleich wie die Standard-Umnummerierung)&lt;/li&gt;&#10;&lt;li&gt;alle &lt;code&gt;wt=@XREF@&lt;/code&gt; / &lt;code&gt;id=@XREF@&lt;/code&gt;-Links in Notizen und Blöcken aktualisiert&lt;/li&gt;&#10;&lt;li&gt;der Link-Index (&lt;code&gt;le_link_index&lt;/code&gt;) und UID-Index (&lt;code&gt;le_uid_index&lt;/code&gt;) werden inline oder an Cron delegiert repariert&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Jeder umnummerierte Datensatz wird im Edit-Log protokolliert (Admin → Änderungslog), z.B. &lt;code&gt;Renumbered @I456@ → @I457@ (INDI, 3 core rows, 2 links)&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Wenn die PHP-Ausführungszeitgrenze erreicht wird, stoppt der Lauf mit teilweisem Fortschritt — die verbleibenden Kollisionen werden im nächsten Lauf umnummeriert.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Hinweis:&lt;/strong&gt; Die Standard-webtrees-Umnummerierung (ohne Links) bleibt verfügbar und ist nicht betroffen. Verwenden Sie die Umnummerierung dieses Moduls, wenn Ihre Notizen oder Blöcke LinkEnhancer-Links enthalten.&#10;Siehe auch: &lt;a href="https://github.com/fisharebest/webtrees/issues/5156"&gt;fisharebest/webtrees#5156&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Übersetzungs-Pipeline</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/translation-pipeline/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/translation-pipeline/</guid><description>&lt;p&gt;Das Modul bringt seine eigenen Übersetzungen über die Standard-gettext-Kette ein, gehostet auf &lt;a href="https://translate.codeberg.org/projects/wt-modules/linkenhancer/"&gt;&lt;strong&gt;Codeberg Weblate&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="ablauf"&gt;Ablauf&lt;a class="td-heading-self-link" href="#ablauf" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&#10;&#10;&#10;&lt;pre class="mermaid"&gt;flowchart TB&#10; subgraph Extraction[&amp;#34;1️⃣ Quellcode → POT&amp;#34;]&#10; direction LR&#10; PHP[&amp;#34;📝 src/*.php&amp;#34;] --&amp;gt;|npx gulp updatepo| POT[&amp;#34;📄 messages.pot&amp;#34;]&#10; end&#10;&#10; subgraph Translation[&amp;#34;2️⃣ Übersetzung&amp;#34;]&#10; direction LR&#10; WEBLATE[&amp;#34;🌐 Weblate&amp;#34;] --&amp;gt;|download| PO[&amp;#34;🗝 &amp;lt;lang&amp;gt;.po&amp;#34;]&#10; end&#10;&#10; subgraph Rendering[&amp;#34;3️⃣ Webtrees&amp;#34;]&#10; direction LR&#10; PHPARR[&amp;#34;📦 lang.php&amp;#34;] --&amp;gt;|I18N| RENDER[&amp;#34;✅ Rendering&amp;#34;]&#10; end&#10;&#10; POT --&amp;gt;|upload| Translation&#10; PO --&amp;gt;|npx gulp po2php| Rendering&#10;&#10; classDef sourceStyle fill:#e3f2fd,stroke:#1565C0,stroke-width:2px&#10; classDef fileStyle fill:#e8f5e9,stroke:#2E7D32,stroke-width:2px&#10; classDef weblateStyle fill:#f3e5f5,stroke:#7B1FA2,stroke-width:2px&#10; classDef renderStyle fill:#fce4ec,stroke:#C2185B,stroke-width:2px&#10;&#10; class PHP sourceStyle&#10; class POT,PO,PHPARR fileStyle&#10; class WEBLATE weblateStyle&#10; class RENDER renderStyle&#10;&lt;/pre&gt;&#10;&lt;h2 id="strings-extrahieren"&gt;Strings extrahieren&lt;a class="td-heading-self-link" href="#strings-extrahieren" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/util/update-po-files.sh" target="_blank" rel="noopener"&gt;&lt;code&gt;update-po-files.sh&lt;/code&gt;&lt;/a&gt;&#10; führt &lt;code&gt;xgettext&lt;/code&gt; über jede &lt;code&gt;*.php&lt;/code&gt; / &lt;code&gt;*.phtml&lt;/code&gt; aus, außer &lt;code&gt;util/&lt;/code&gt;, &lt;code&gt;vendor/&lt;/code&gt;, &lt;code&gt;node_modules/&lt;/code&gt; und &lt;code&gt;tests/&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>WTHB-TOC-Language-Pipeline</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/wthb-toc-lang/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/wthb-toc-lang/</guid><description>&lt;h2 id="überblick"&gt;Überblick&lt;a class="td-heading-self-link" href="#%c3%bcberblick" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Das Paket &lt;strong&gt;&lt;code&gt;linkenhancer-wthb-toc-lang&lt;/code&gt;&lt;/strong&gt; stellt das Inhaltsverzeichnis (TOC) des deutschen webtrees-Handbuchs — samt Übersetzungen — der &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/wthb/"&gt;WTHB-Hilfefunktion&lt;/a&gt; zur Verfügung. Die Produktion ist ein &lt;strong&gt;Rundlauf&lt;/strong&gt;, der komplett außerhalb der webtrees-Installation läuft: Er liest das Handbuch von &lt;strong&gt;GenWiki&lt;/strong&gt;, erzeugt das TOC neu, schreibt das Ergebnis als &lt;strong&gt;MediaWiki-Template&lt;/strong&gt; zurück nach GenWiki und — parallel — die strukturierten Daten in ein &lt;strong&gt;externes Codeberg-Repo&lt;/strong&gt;, das &lt;strong&gt;Codeberg Pages&lt;/strong&gt;, &lt;strong&gt;Weblate&lt;/strong&gt; (Übersetzungen) und schließlich das &lt;strong&gt;Modul&lt;/strong&gt; versorgt. Diese Seite dokumentiert die &lt;em&gt;Produktionsseite&lt;/em&gt;; die &lt;em&gt;Konsumenten-Seite&lt;/em&gt; (Cache, CLI, Rendering) steht auf der &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/wthb/"&gt;WTHB-Funktionsseite&lt;/a&gt; und der Seite &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/cli-scripts/"&gt;CLI-Skripte&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Datenkorrekturen</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/data-fixes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/enhanced-links/data-fixes/</guid><description>&lt;p&gt;Das Modul bietet eine Reihe von Datenkorrektur-Handlern, die über die webtrees &lt;a href="https://wiki.genealogy.net/Webtrees_Handbuch/Anleitung_f%C3%BCr_Verwalter#Datenkorrekturen"&gt;Datenkorrektur&lt;/a&gt;-Schnittstelle erreichbar sind (Steuerungspanel → Datenkorrekturen → LinkEnhancer). Jeder Handler adressiert ein spezifisches Link-Integritätsproblem:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Korrektur&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Was sie tut&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;XREF ⇄ UID Referenz-Tausch&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Konvertiert LinkEnhancer-Link-Ziele zwischen XREF- und UID-Form. Richtung ist wählbar (XREF→UID oder UID→XREF). Erfordert, dass der UID-Index aufgebaut ist.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;&lt;code&gt;wt=&lt;/code&gt; Typ-Buchstabe korrigieren&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Setzt, repariert oder entfernt den Legacy-Typ-Buchstaben in &lt;code&gt;wt=&amp;lt;type&amp;gt;@REF@&lt;/code&gt;-Links. Modi: &lt;em&gt;setzen&lt;/em&gt; (fehlenden Typ hinzufügen), &lt;em&gt;reparieren&lt;/em&gt; (falschen Typ korrigieren), &lt;em&gt;entfernen&lt;/em&gt; (Typ-Buchstaben streichen).&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Verwaiste Link-Ziele melden&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;Nur Bericht&lt;/em&gt;: Listet LinkEnhancer-Links auf, deren Ziel-Datensatz nicht mehr existiert. Es werden keine Änderungen vorgenommen.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Mehrdeutige UID-Ziele melden&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;Nur Bericht&lt;/em&gt;: Listet Links auf, deren UID-Ziel auf mehr als einen Datensatz auflöst. Es werden keine Änderungen vorgenommen.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Doppelte UIDs im Index melden&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;Nur Bericht&lt;/em&gt;: Listet UIDs auf, die im UID-Index mehreren Datensätzen zugewiesen sind. Es werden keine Änderungen vorgenommen.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Jede Korrektur folgt dem webtrees Datenkorrektur-Workflow: Korrekturtyp wählen → Vorschau → anwenden. Die Datenkorrektur-Seite zeigt auch den aktuellen Status der Link- und UID-Indizes und ob Index-Aktualisierungen an den Cron-Job delegiert werden.&lt;/p&gt;</description></item><item><title>Testing</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/testing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/testing/</guid><description>&lt;p&gt;Die komplette Kette läuft mit:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm &lt;span style="color:#91d7e3"&gt;test&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das führt &lt;code&gt;test:php&lt;/code&gt; → &lt;code&gt;analyse:php&lt;/code&gt; → &lt;code&gt;test:js&lt;/code&gt; aus, wobei jeder Schritt bestehen muss, bevor der nächste läuft.&lt;/p&gt;&#10;&lt;h2 id="javascript-mocha--jsdom"&gt;JavaScript (Mocha + jsdom)&lt;a class="td-heading-self-link" href="#javascript-mocha--jsdom" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm run test:js&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# mocha &amp;#39;resources/js/tests/**/*.test.js&amp;#39; --require jsdom-global/register&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="php-standalone-unit-tests"&gt;PHP-Standalone-Unit-Tests&lt;a class="td-heading-self-link" href="#php-standalone-unit-tests" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm run test:php&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# führt jedes tests/test-*.php mit dem System-PHP aus — ohne webtrees, ohne DB&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Test&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Abgedeckt&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-text-tag-collector.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-text-tag-collector.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Text-Tag-Collector&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-link-classifier.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-link-classifier.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Link-Klassifizierer (inkl. Ziel-Extraktion)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-uid-tag-collector.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-uid-tag-collector.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;UID-Tag-Collector&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-uid-index-service.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-uid-index-service.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;UID-Index-Service&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-i18n-mark.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-i18n-mark.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;i18n-Marker&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/tests/test-wthb-toc-service.php" target="_blank" rel="noopener"&gt;&lt;code&gt;test-wthb-toc-service.php&lt;/code&gt;&lt;/a&gt;&#10;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;WTHB-TOC-Service&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="php-statische-analyse"&gt;PHP-Statische Analyse&lt;a class="td-heading-self-link" href="#php-statische-analyse" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm run analyse:php &lt;span style="color:#6e738d;font-style:italic"&gt;# oder: composer analyse&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# PHPStan Level 6 — siehe die PHPStan-Seite&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="smoke-tests-brauchen-webtrees--db"&gt;Smoke-Tests (brauchen webtrees + DB)&lt;a class="td-heading-self-link" href="#smoke-tests-brauchen-webtrees--db" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Diese üben eine echte Installation und sind &lt;strong&gt;nicht&lt;/strong&gt; Teil von &lt;code&gt;npm test&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>PHPStan</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/phpstan/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/phpstan/</guid><description>&lt;p&gt;Benötigt wird: &lt;a href="https://phpstan.org/"&gt;PHPstan&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Die statische Analyse ist über &lt;code&gt;phpstan.neon&lt;/code&gt; konfiguriert (Level 6, Baseline in &lt;code&gt;phpstan-baseline.neon&lt;/code&gt;).&lt;/p&gt;&#10;&lt;h3 id="ausführen"&gt;Ausführen&lt;a class="td-heading-self-link" href="#ausf%c3%bchren" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;composer analyse&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Analyse benötigt eine webtrees-Installation (für die &lt;code&gt;app/&lt;/code&gt;-Klassen + &lt;code&gt;vendor/autoload.php&lt;/code&gt;). Ausführen vom bind-mounted-Pfad:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3"&gt;cd&lt;/span&gt; /path/to/webtrees/modules_v4/linkenhancer&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;composer analyse&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="konfiguration"&gt;Konfiguration&lt;a class="td-heading-self-link" href="#konfiguration" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Level&lt;/strong&gt;: 6&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Baseline&lt;/strong&gt;: &lt;code&gt;phpstan-baseline.neon&lt;/code&gt; (bekannte Probleme)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Bootstrap&lt;/strong&gt;: &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/phpstan-bootstrap.php" target="_blank" rel="noopener"&gt;&lt;code&gt;phpstan-bootstrap.php&lt;/code&gt;&lt;/a&gt;&#10; registriert die PSR-4-Namespaces direkt (umgeht den versionsgeprüften Autoloader in &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/wt-shared-libs/"&gt;&lt;code&gt;wt-shared-libs&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Scan-Verzeichnisse&lt;/strong&gt;: &lt;code&gt;../../app/&lt;/code&gt; (webtrees-Core-Klassen)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Ausgeschlossene Pfade&lt;/strong&gt;: &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/src/LinkEnhancerModuleExt.php" target="_blank" rel="noopener"&gt;&lt;code&gt;LinkEnhancerModuleExt.php&lt;/code&gt;&lt;/a&gt;&#10; (Verwendung im Zusammenhang mit &lt;a href="https://github.com/vesta-webtrees-2-custom-modules"&gt;Vesta-Modulen&lt;/a&gt;)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Speichergrenze&lt;/strong&gt;: 1G&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Parallel&lt;/strong&gt;: deaktiviert (Single-Prozess, zuverlässiger in CI)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="wichtige-einstellungen"&gt;Wichtige Einstellungen&lt;a class="td-heading-self-link" href="#wichtige-einstellungen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;treatPhpDocTypesAsCertain: false&lt;/code&gt; — verhindert False Positives aus &lt;code&gt;@var&lt;/code&gt;-Assertions&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ignoreErrors&lt;/code&gt; für:&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;AccessLevel&lt;/code&gt; Enum (nur-Klasse in WT 2.3, in der 2.2-Laufzeit nicht verfügbar)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;DB::prefix('')&lt;/code&gt; — beabsichtigt (Präfix ohne Identifier holen)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="baseline-neu-generieren"&gt;Baseline neu generieren&lt;a class="td-heading-self-link" href="#baseline-neu-generieren" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;Nach beabsichtigten Änderungen, die neue (akzeptable) Fehler einführen:&lt;/p&gt;</description></item><item><title>UID-Suche</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/uid-lookup/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/uid-lookup/</guid><description>&lt;p&gt;Eine &lt;strong&gt;UID&lt;/strong&gt; (&lt;code&gt;_UID&lt;/code&gt; in GEDCOM 5.5.1, &lt;code&gt;UID&lt;/code&gt; in GEDCOM 7.0) ist eine persistente Kennung, die einem Datensatz zugewiesen wird. Die UID übersteht XREF-Umnummerierungen und Baum-Migrationen und ist damit ein stabiler Referenzpunkt.&lt;/p&gt;&#10;&lt;p&gt;Diese Funktion ermöglicht die direkte Navigation zu einem Datensatz über seine UID. Das URL-Muster ist:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;/tree/{baum}/goto-uid/{uid}&lt;/code&gt; — auf einen Baum beschränkt&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;/goto-uid/{uid}&lt;/code&gt; — global (durchsucht alle Bäume)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;Verhalten:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;0 Treffer&lt;/strong&gt; → 404&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;1 sichtbarer Treffer&lt;/strong&gt; → Weiterleitung zum Datensatz&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&amp;gt;1 sichtbarer Treffer&lt;/strong&gt; → Auswahl-Liste (UIDs mit unterschiedlicher Groß/Klein-Schreibung oder dieselbe UID in mehreren Datensätzen)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Der UID-Vergleich ist &lt;strong&gt;case-insensitive&lt;/strong&gt; (GEDCOM-Spezifikationen definieren UID nicht als case-sensitive). Der gespeicherte Wert ist wörtlich; die Übereinstimmung wird case-insensitiv geprüft, sodass UIDs mit unterschiedlicher Groß/Klein-Schreibung eine Auswahl-Liste zurückliefern statt einer möglicherweise falschen einzelnen Weiterleitung.&lt;/p&gt;</description></item><item><title>Patches</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/patches/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/features/patches/</guid><description>&lt;p&gt;&lt;strong&gt;Die Patches können zusätzlich angewendet werden — das Modul funktioniert auch ohne sie!&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;Der &lt;code&gt;util&lt;/code&gt;-Unterordner enthält kleine Patches für den webtrees-Core. Dies sind &lt;a href="https://www.gnu.org/software/diffutils/"&gt;Diff-Dateien&lt;/a&gt;, die per Shell aus dem installierten Modulordner heraus leicht angewendet oder entfernt werden können (notwendig für die Auto-Erkennung der webtrees-Quellen):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Usage: util/wt-patch.sh &lt;span style="color:#91d7e3;font-weight:bold"&gt;[&lt;/span&gt;-R&lt;span style="color:#91d7e3;font-weight:bold"&gt;]&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;[&lt;/span&gt;FILTER&lt;span style="color:#91d7e3;font-weight:bold"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -R Patch rückgängig machen &lt;span style="color:#91d7e3;font-weight:bold"&gt;(&lt;/span&gt;patch -R&lt;span style="color:#91d7e3;font-weight:bold"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FILTER &lt;span style="color:#a6da95"&gt;&amp;#39;*&amp;#39;&lt;/span&gt; für alle oder spezifisch &lt;span style="color:#91d7e3;font-weight:bold"&gt;(&lt;/span&gt;z.B. &lt;span style="color:#a6da95"&gt;&amp;#39;01&amp;#39;&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vergessen Sie nicht, die Patches nach einem webtrees-Update neu anzuwenden.&lt;/p&gt;&#10;&lt;p&gt;Es handelt sich um kleine Bugfixes oder Funktionserweiterungen — meist in einer einzelnen Datei — die dazu dienen, die Lücke bis zu einer offiziellen Behebung/Implementierung im webtrees-Core zu überbrücken.&lt;/p&gt;</description></item><item><title>Release</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/release/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/linkenhancer/dev/release/</guid><description>&lt;h2 id="schritte"&gt;Schritte&lt;a class="td-heading-self-link" href="#schritte" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# 1. Version erhöhen (erfordert einen sauberen git-Tree)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx gulp bumpversion&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# 2. Build + Übersetzungen kompilieren + Release-Archiv erstellen&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx gulp archive&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="was-archive-tut"&gt;Was &lt;code&gt;archive&lt;/code&gt; tut&lt;a class="td-heading-self-link" href="#was-archive-tut" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;npx gulp archive&lt;/code&gt; führt &lt;code&gt;build&lt;/code&gt; → &lt;code&gt;po2php&lt;/code&gt; → &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/util/create-archive.sh" target="_blank" rel="noopener"&gt;&lt;code&gt;create-archive.sh&lt;/code&gt;&lt;/a&gt;&#10; aus. Das Skript:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Liest die Version aus &lt;a href="https://codeberg.org/bschwede/linkenhancer/src/branch/main/latest-version.txt" target="_blank" rel="noopener"&gt;&lt;code&gt;latest-version.txt&lt;/code&gt;&lt;/a&gt;&#10;.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;rsync&lt;/code&gt; das Modul nach &lt;code&gt;dist/linkenhancer/&lt;/code&gt; und schließt alles aus, das nicht ausgeliefert wird (unten).&lt;/li&gt;&#10;&lt;li&gt;Erzeugt &lt;code&gt;dist/linkenhancer_v&amp;lt;version&amp;gt;.zip&lt;/code&gt;.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="aus-dem-archiv-ausgeschlossen"&gt;Aus dem Archiv ausgeschlossen&lt;a class="td-heading-self-link" href="#aus-dem-archiv-ausgeschlossen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;create-archive.sh&lt;/code&gt; lässt unter anderem aus: &lt;code&gt;node_modules/&lt;/code&gt;, &lt;code&gt;.git*&lt;/code&gt;, &lt;code&gt;gulpfile.mjs&lt;/code&gt;, &lt;code&gt;package*.json&lt;/code&gt;, &lt;code&gt;phpstan*&lt;/code&gt;, &lt;code&gt;tests/&lt;/code&gt;, die &lt;code&gt;util/*&lt;/code&gt;-Buildskripte, &lt;code&gt;resources/js/src&lt;/code&gt;, &lt;code&gt;resources/js/tests&lt;/code&gt;, &lt;code&gt;resources/img/&lt;/code&gt;, &lt;code&gt;resources/lang/*.po&lt;/code&gt; / &lt;code&gt;*.mo&lt;/code&gt; und &lt;code&gt;.env&lt;/code&gt;. Ausgeliefert werden nur die gebauten &lt;code&gt;bundle*&lt;/code&gt;-JS/CSS, die kompilierten &lt;code&gt;resources/lang/*.php&lt;/code&gt;, &lt;code&gt;src/&lt;/code&gt;, &lt;code&gt;resources/views/&lt;/code&gt;, &lt;code&gt;resources/css/&lt;/code&gt; und die Modul-Entry-Dateien.&lt;/p&gt;</description></item><item><title>Websiten-Informationen</title><link>https://bschwede.codeberg.page/wt-modules/de/site/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/site/</guid><description>&lt;p&gt;Site built with &lt;a href="https://github.com/docsy/docsy/releases/v0.18.0"&gt;&lt;span class="badge bg-primary text-bg-primary fs-6"&gt;Docsy&#10;v0.18.0 &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="build-information"&gt;Build information&lt;a class="td-heading-self-link" href="#build-information" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;</description></item><item><title>Suchergebnisse</title><link>https://bschwede.codeberg.page/wt-modules/de/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/search/</guid><description/></item></channel></rss>