{"id":20855,"date":"2026-10-07T11:52:00","date_gmt":"2026-10-07T09:52:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=20855"},"modified":"2026-09-30T12:13:32","modified_gmt":"2026-09-30T10:13:32","slug":"plugin-check-lokal-und-ci","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/","title":{"rendered":"Plugin Check lokal und in der CI: Befunde vor dem Review"},"content":{"rendered":"<p>Jedes Plugin, das im Verzeichnis von WordPress.org eingereicht wird, durchl\u00e4uft zuerst einen automatischen Scan, erst danach liest jemand aus dem Plugins Team den Code. Ein Teil dessen, was im Review beanstandet wird, l\u00e4sst sich maschinell finden: ein fehlender Lizenz-Header, ungesch\u00fctzte Ausgaben, ein Skript von einem \u00f6ffentlichen CDN, eine Text Domain, die nicht zum Slug passt. Plugin Check, kurz PCP, ist das Werkzeug, das WordPress.org genau daf\u00fcr ver\u00f6ffentlicht. Laut Beschreibung f\u00fchrt es die meisten Pr\u00fcfungen aus, die auch bei neuen Einreichungen laufen, und zwar auf jeder WordPress-Installation, bevor irgendetwas hochgeladen wird.<\/p>\n<p>Dieser Beitrag zeigt Plugin Check 2.1.0 an drei Stellen: in der Oberfl\u00e4che im Backend, auf der Kommandozeile mit WP-CLI und in einem GitHub-Actions-Workflow mit der offiziellen Action. Als Pr\u00fcfobjekt dient ein kleines Plugin mit absichtlich eingebauten Fehlern. Zu jedem Fehler nennt der Text die Pr\u00fcfung und den Ergebniscode, den ein Lauf von Plugin Check 2.1.0 unter WordPress 7.1.2 meldet, und zeigt danach die korrigierte Fassung.<\/p>\n<h2>Was Plugin Check pr\u00fcft<\/h2>\n<p>Aktuell im Verzeichnis ist Version 2.1.0 vom 16. August 2026. Vorausgesetzt werden WordPress 6.3 und PHP 7.4; die Plugin-Seite nennt \u201eTested up to\u201c 7.0.6, w\u00e4hrend die aktuelle WordPress-Version 7.1.2 lautet. Neu in 2.1.0 ist unter anderem eine Pr\u00fcfung auf \u00c4nderungen an der PHP-Fehlerausgabe zur Laufzeit.<\/p>\n<p>Im Quelltext von 2.1.0 registriert die Klasse <code>Default_Check_Repository<\/code> 34 Pr\u00fcfungen. Jede tr\u00e4gt einen Slug wie <code>late_escaping<\/code> und geh\u00f6rt zu einer oder mehreren Kategorien. Es gibt zwei Arten. Statische Pr\u00fcfungen lesen den Code, ohne ihn auszuf\u00fchren, meist \u00fcber PHP_CodeSniffer-Sniffs aus den WordPress Coding Standards oder aus dem eigenen Sniff-Satz von Plugin Check, teils \u00fcber eigene Logik. Laufzeitpr\u00fcfungen f\u00fchren das Plugin, das daf\u00fcr aktiviert sein muss, mit einem abgetrennten Satz Datenbanktabellen aus und beobachten, was es tut; in 2.1.0 sind das die f\u00fcnf Performance-Pr\u00fcfungen zu Reichweite und Gr\u00f6\u00dfe von Skripten und Stylesheets sowie zur Ladestrategie.<\/p>\n<table>\n<thead>\n<tr>\n<th>Kategorie (Slug)<\/th>\n<th>Beispiele f\u00fcr Pr\u00fcfungen in 2.1.0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>General (<code>general<\/code>)<\/td>\n<td><code>i18n_usage<\/code>, <code>php_error_reporting<\/code>, <code>ai_provider<\/code><\/td>\n<\/tr>\n<tr>\n<td>Plugin Repo (<code>plugin_repo<\/code>)<\/td>\n<td><code>plugin_readme<\/code>, <code>plugin_header_fields<\/code>, <code>file_type<\/code>, <code>offloading_files<\/code>, <code>setting_sanitization<\/code>, <code>prefixing<\/code>, <code>plugin_review_phpcs<\/code>, <code>trademarks<\/code><\/td>\n<\/tr>\n<tr>\n<td>Security (<code>security<\/code>)<\/td>\n<td><code>late_escaping<\/code>, <code>direct_file_access<\/code>, <code>safe_redirect<\/code>, <code>direct_db_queries<\/code>, <code>direct_db<\/code><\/td>\n<\/tr>\n<tr>\n<td>Performance (<code>performance<\/code>)<\/td>\n<td><code>enqueued_scripts_in_footer<\/code>, <code>performant_wp_query_params<\/code>, <code>enqueued_scripts_scope<\/code>, <code>non_blocking_scripts<\/code><\/td>\n<\/tr>\n<tr>\n<td>Accessibility (<code>accessibility<\/code>)<\/td>\n<td>keine: Die Kategorie ist definiert, aber keine mitgelieferte Pr\u00fcfung aus 2.1.0 ist ihr zugeordnet<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Alle in 2.1.0 registrierten Security-Pr\u00fcfungen tragen zus\u00e4tzlich die Kategorie <code>plugin_repo<\/code>. Ein Lauf nur \u00fcber Plugin Repo deckt also Escaping und direkten Dateizugriff bereits ab. Das ist wichtig, weil die FAQ des Plugins festh\u00e4lt, dass ein Plugin f\u00fcr die Aufnahme ins Verzeichnis in der Regel alle Pr\u00fcfungen der Kategorie Plugin Repo bestehen muss. Die \u00fcbrigen Kategorien gelten als zus\u00e4tzlich.<\/p>\n<p>Jedes Ergebnis ist entweder <code>ERROR<\/code> oder <code>WARNING<\/code> und hat eine Schwere (Severity); Standard ist 5, eine fehlende Lizenz im Plugin-Header meldet die Pr\u00fcfung mit 9. Fehler stehen f\u00fcr Verst\u00f6\u00dfe gegen Anforderungen des Verzeichnisses. Warnungen markieren Code, der oft, aber nicht immer ein Problem ist: <code>$_GET<\/code> ohne Nonce zu lesen ist bei einem harmlosen Anzeigeparameter unkritisch und in einem Formular-Handler eine echte L\u00fccke. Den Typ legt die jeweilige Pr\u00fcfung fest. Das PHPCS-Regelwerk von Plugin Check stuft einige Sniffs bewusst auf Warnungen herunter, etwa die Nonce-Pr\u00fcfung und die Bereinigung von Eingaben.<\/p>\n<h2>Lokal ausf\u00fchren: Backend und WP-CLI<\/h2>\n<p>Plugin Check wird wie jedes andere Plugin installiert. Das README des Projekts r\u00e4t vom Einsatz auf Produktivseiten ab, weil Laufzeitpr\u00fcfungen das gepr\u00fcfte Plugin tats\u00e4chlich ausf\u00fchren. Nach der Aktivierung steht unter Werkzeuge \u2192 Plugin Check eine Seite bereit, die nur Nutzer mit dem Recht zur Plugin-Verwaltung sehen. Dort gibt es eine Plugin-Auswahl sowie Checkboxen f\u00fcr Kategorien und Ergebnistypen. Die Ergebnisse erscheinen je Datei mit Zeile, Spalte, Typ, Code und Meldung; seit Version 1.8.0 lassen sie sich als CSV, JSON oder Markdown exportieren.<\/p>\n<p>F\u00fcr wiederholte L\u00e4ufe ist der WP-CLI-Befehl praktischer. Als Argument akzeptiert er einen Plugin-Slug, einen Pfad oder die URL einer ZIP-Datei. Standardm\u00e4\u00dfig laufen nur statische Pr\u00fcfungen. F\u00fcr Laufzeitpr\u00fcfungen beschreibt das README einen Umweg: <code>--require<\/code> l\u00e4dt die Datei <code>cli.php<\/code> von Plugin Check, bevor WordPress startet. Au\u00dferdem muss das gepr\u00fcfte Plugin aktiv sein; bei einem inaktiven Plugin l\u00e4sst Plugin Check die Laufzeitpr\u00fcfungen ohne Hinweis weg, und <code>--checks=enqueued_scripts_scope<\/code> endet dann mit \u201edoes not exist\u201c.<\/p>\n<pre><code># Install and activate Plugin Check (2.1.0 at the time of writing).\nwp plugin install plugin-check --activate\n\n# All static checks for wp-content\/plugins\/lw-hello-banner.\nwp plugin check lw-hello-banner\n\n# Include runtime checks (plugin must be active): load cli.php before WordPress boots.\nwp plugin check lw-hello-banner --require=.\/wp-content\/plugins\/plugin-check\/cli.php\n\n# Limit the run to categories or to single checks.\nwp plugin check lw-hello-banner --categories=plugin_repo,security\nwp plugin check lw-hello-banner --checks=late_escaping,i18n_usage\n\n# Errors only, as one JSON array for scripts.\nwp plugin check lw-hello-banner --ignore-warnings --format=strict-json\n\n# Show result codes, then ignore one specific code.\nwp plugin check lw-hello-banner --format=csv --fields=code,message\nwp plugin check lw-hello-banner --ignore-codes=textdomain_mismatch\n\n# Checks for an update of an existing directory plugin.\nwp plugin check lw-hello-banner --mode=update\n\n# What is available in the installed version.\nwp plugin list-checks --format=csv\nwp plugin list-check-categories<\/code><\/pre>\n<p>Die wichtigsten Optionen von <code>wp plugin check<\/code> in Version 2.1.0:<\/p>\n<table>\n<thead>\n<tr>\n<th>Option<\/th>\n<th>Wirkung<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>--checks=<\/code>, <code>--exclude-checks=<\/code><\/td>\n<td>nur die genannten Pr\u00fcfungen ausf\u00fchren oder sie auslassen<\/td>\n<\/tr>\n<tr>\n<td><code>--categories=<\/code><\/td>\n<td>Lauf auf Kategorien beschr\u00e4nken, kommagetrennt<\/td>\n<\/tr>\n<tr>\n<td><code>--ignore-codes=<\/code><\/td>\n<td>einzelne Ergebniscodes ausblenden, etwa <code>textdomain_mismatch<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>--ignore-warnings<\/code>, <code>--ignore-errors<\/code><\/td>\n<td>einen der beiden Ergebnistypen ausblenden<\/td>\n<\/tr>\n<tr>\n<td><code>--format=<\/code><\/td>\n<td><code>table<\/code> (Standard), <code>csv<\/code>, <code>json<\/code>, <code>ctrf<\/code> sowie <code>strict-table<\/code>, <code>strict-csv<\/code>, <code>strict-json<\/code>, <code>strict-ctrf<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>--fields=<\/code><\/td>\n<td>Spalten w\u00e4hlen, zum Beispiel <code>code,message<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>--exclude-directories=<\/code>, <code>--exclude-files=<\/code><\/td>\n<td>Pfade bei dateibasierten Scans \u00fcberspringen; <code>.git<\/code>, <code>vendor<\/code>, <code>vendor_prefixed<\/code>, <code>vendor-prefixed<\/code> und <code>node_modules<\/code> sind ohnehin ausgenommen<\/td>\n<\/tr>\n<tr>\n<td><code>--severity=<\/code>, <code>--error-severity=<\/code>, <code>--warning-severity=<\/code><\/td>\n<td>nur Ergebnisse ab einer bestimmten Schwere zeigen<\/td>\n<\/tr>\n<tr>\n<td><code>--mode=<\/code><\/td>\n<td><code>new<\/code> (Standard) oder <code>update<\/code>; im Update-Modus ist ein veraltetes \u201eTested up to\u201c eine Warnung statt eines Fehlers<\/td>\n<\/tr>\n<tr>\n<td><code>--slug=<\/code><\/td>\n<td>den Slug \u00fcberschreiben, gegen den Text Domain und Readme verglichen werden<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Pr\u00fcfungs-Slugs und Ergebniscodes sind zweierlei. <code>--checks=i18n_usage<\/code> w\u00e4hlt eine Pr\u00fcfung aus, <code>--ignore-codes=WordPress.WP.I18n.TextDomainMismatch<\/code> blendet einen einzelnen Befund daraus aus. Zum Nachschlagen der Codes empfiehlt die CLI-Dokumentation <code>--format=csv --fields=code,message<\/code>. F\u00fcr Skripte z\u00e4hlt noch ein Detail: Im Quelltext von 2.1.0 gibt der Befehl die Befunde aus, setzt ihretwegen aber keinen Fehler-Exitcode. Ein Shell-Skript, das bei Befunden scheitern soll, muss die Ausgabe also selbst auswerten; im Test meldete der Befehl beim fehlerhaften Beispiel zw\u00f6lf Fehler und endete trotzdem mit Exitcode 0. Die GitHub Action erledigt genau das. Mit <code>--format=json<\/code> steht vor jeder Datei eine Zeile <code>FILE: \u2026<\/code> mit einem eigenen JSON-Array, die Ausgabe als Ganzes ist also kein g\u00fcltiges JSON; <code>--format=strict-json<\/code> liefert ein einziges Array, allerdings ohne Dateinamen. Ohne Befunde geben beide Formate nur eine Erfolgszeile aus.<\/p>\n<h2>Ein Beispiel-Plugin mit eingebauten Fehlern<\/h2>\n<p>Das Beispiel besteht aus einer Datei im Ordner <code>wp-content\/plugins\/lw-hello-banner\/<\/code>, der Slug lautet damit <code>lw-hello-banner<\/code>. Das Plugin zeigt oben auf der Seite einen Gru\u00df, liest einen optionalen Namen aus der URL, bietet unter Einstellungen \u2192 Allgemein ein Notizfeld und l\u00e4dt ein dekoratives Skript. Neun Fehler sind absichtlich enthalten: keine <code>readme.txt<\/code>, kein Lizenz-Header, eine vom Slug abweichende Text Domain, kein Schutz gegen direkten Dateiaufruf, ein Aufruf von <code>error_reporting()<\/code>, <code>register_setting()<\/code> ohne Bereinigung, Ausgaben ohne Escaping, ein \u00fcbersetzbarer String mit Platzhalter, aber ohne \u00dcbersetzerkommentar, und ein Skript vom CDN ohne Version und Ladeargumente.<\/p>\n<pre><code>&lt;?php\n\/**\n * Plugin Name: LW Hello Banner\n * Description: Shows a greeting banner at the top of the front page.\n * Version:     0.1.0\n * Author:      Lukas Wojcik\n * Text Domain: hello-banner\n *\/\n\n\/\/ Intentionally faulty example for Plugin Check. Do not use on a live site.\n\nerror_reporting( E_ALL );\n\nfunction lw_hello_banner_register_setting() {\n\tregister_setting( 'general', 'lw_hello_banner_note' );\n\n\tadd_settings_field(\n\t\t'lw_hello_banner_note',\n\t\t__( 'Banner note', 'hello-banner' ),\n\t\t'lw_hello_banner_field',\n\t\t'general'\n\t);\n}\nadd_action( 'admin_init', 'lw_hello_banner_register_setting' );\n\nfunction lw_hello_banner_field() {\n\techo '&lt;input type=\"text\" name=\"lw_hello_banner_note\" value=\"' . get_option( 'lw_hello_banner_note' ) . '\"&gt;';\n}\n\nfunction lw_hello_banner_assets() {\n\twp_enqueue_script( 'lw-hello-banner', 'https:\/\/cdn.jsdelivr.net\/npm\/canvas-confetti@1.9.3\/dist\/confetti.browser.min.js' );\n}\nadd_action( 'wp_enqueue_scripts', 'lw_hello_banner_assets' );\n\nfunction lw_hello_banner_render() {\n\t$name = isset( $_GET['lw_name'] ) ? $_GET['lw_name'] : 'Guest';\n\t$note = get_option( 'lw_hello_banner_note', '' );\n\n\techo '&lt;div class=\"lw-hello-banner\"&gt;&lt;p&gt;' . sprintf( __( 'Hello, %s!', 'hello-banner' ), $name ) . ' ' . $note . '&lt;\/p&gt;&lt;\/div&gt;';\n}\nadd_action( 'wp_body_open', 'lw_hello_banner_render' );<\/code><\/pre>\n<h2>Was Plugin Check dazu meldet<\/h2>\n<p>Die Tabelle f\u00fchrt die Befunde auf, die <code>wp plugin check lw-hello-banner<\/code> mit Plugin Check 2.1.0 unter WordPress 7.1.2 meldet, zusammen zw\u00f6lf Fehler und neun Warnungen; ein Lauf mit <code>--require<\/code> liefert dieselbe Liste. Zeilennummern fehlen; <code>OutputNotEscaped<\/code> erscheint viermal, <code>TextDomainMismatch<\/code> und <code>NonceVerification.Recommended<\/code> je zweimal.<\/p>\n<table>\n<thead>\n<tr>\n<th>Ergebniscode<\/th>\n<th>Pr\u00fcfung (Kategorie)<\/th>\n<th>Typ<\/th>\n<th>Ursache im Beispiel<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>no_plugin_readme<\/code><\/td>\n<td><code>plugin_readme<\/code> (plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td>keine <code>readme.txt<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>plugin_header_no_license<\/code><\/td>\n<td><code>plugin_header_fields<\/code> (plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td>kein <code>License<\/code>-Header<\/td>\n<\/tr>\n<tr>\n<td><code>textdomain_mismatch<\/code><\/td>\n<td><code>plugin_header_fields<\/code> (plugin_repo)<\/td>\n<td>WARNING<\/td>\n<td>Header nennt <code>hello-banner<\/code>, Slug ist <code>lw-hello-banner<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>missing_direct_file_access_protection<\/code><\/td>\n<td><code>direct_file_access<\/code> (security, plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td>Funktionen und Hooks ohne <code>ABSPATH<\/code>-Abfrage<\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.WP.I18n.TextDomainMismatch<\/code><\/td>\n<td><code>i18n_usage<\/code> (general, plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td><code>__()<\/code>-Aufrufe mit falscher Text Domain<\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.WP.I18n.MissingTranslatorsComment<\/code><\/td>\n<td><code>i18n_usage<\/code> (general, plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td><code>%s<\/code> ohne <code>translators:<\/code>-Kommentar<\/td>\n<\/tr>\n<tr>\n<td><code>PluginCheck.CodeAnalysis.PHPErrorReporting.DirectErrorReportingCall<\/code><\/td>\n<td><code>php_error_reporting<\/code> (general)<\/td>\n<td>WARNING<\/td>\n<td><code>error_reporting( E_ALL )<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting<\/code><\/td>\n<td><code>plugin_review_phpcs<\/code> (plugin_repo)<\/td>\n<td>WARNING<\/td>\n<td><code>error_reporting( E_ALL )<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>PluginCheck.CodeAnalysis.SettingSanitization.register_settingMissing<\/code><\/td>\n<td><code>setting_sanitization<\/code> (plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td><code>register_setting()<\/code> ohne drittes Argument<\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.Security.EscapeOutput.OutputNotEscaped<\/code><\/td>\n<td><code>late_escaping<\/code> (security, plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td><code>get_option()<\/code>, <code>__()<\/code>, <code>$name<\/code> und <code>$note<\/code> im <code>echo<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>PluginCheck.CodeAnalysis.EnqueuedResourceOffloading.OffloadedContent<\/code><\/td>\n<td><code>offloading_files<\/code> (plugin_repo)<\/td>\n<td>ERROR<\/td>\n<td>Skript-URL auf <code>cdn.jsdelivr.net<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.WP.EnqueuedResourceParameters.MissingVersion<\/code>, <code>.NotInFooter<\/code><\/td>\n<td><code>enqueued_scripts_in_footer<\/code> (performance)<\/td>\n<td>WARNING<\/td>\n<td>keine Version, kein f\u00fcnftes Argument<\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.Security.NonceVerification.Recommended<\/code><\/td>\n<td><code>plugin_review_phpcs<\/code> (plugin_repo)<\/td>\n<td>WARNING<\/td>\n<td><code>$_GET['lw_name']<\/code> ohne Nonce-Pr\u00fcfung<\/td>\n<\/tr>\n<tr>\n<td><code>WordPress.Security.ValidatedSanitizedInput.MissingUnslash<\/code>, <code>.InputNotSanitized<\/code><\/td>\n<td><code>plugin_review_phpcs<\/code> (plugin_repo)<\/td>\n<td>WARNING<\/td>\n<td><code>$_GET['lw_name']<\/code> unbehandelt verwendet<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<figure class=\"lw-diagram\">\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/wp-plugin-check-de.png?v=20260930\" width=\"1120\" height=\"580\" alt=\"Vom fehlerhaften Beispiel-Plugin zum sauberen Plugin-Check-Lauf\"><figcaption>Plugin Check 2.1.0 ordnet Pr\u00fcfungen Kategorien zu; Fehler stoppen die CI, Warnungen werden annotiert<\/figcaption><\/figure>\n<p>Drei Dinge fallen auf. Erstens meldet Plugin Check die Text Domain doppelt, aus zwei verschiedenen Pr\u00fcfungen: Die Header-Pr\u00fcfung vergleicht den Header <code>Text Domain<\/code> mit dem Slug und gibt eine Warnung aus, der i18n-Sniff vergleicht jeden \u00dcbersetzungsaufruf mit dem Slug und gibt einen Fehler aus. Zweitens stammen die Befunde zu Nonce und Bereinigung nicht aus der Kategorie Security, sondern aus <code>plugin_review_phpcs<\/code>, einem PHPCS-Lauf mit dem Review-Regelwerk von Plugin Check; ein Lauf mit <code>--categories=security<\/code> zeigt sie nicht. Drittens enth\u00e4lt das Regelwerk auch die Sniff-Gruppe <code>WordPress.PHP.DevelopmentFunctions<\/code> als Warnung. Sie meldet die Zeile mit <code>error_reporting()<\/code> tats\u00e4chlich ein zweites Mal, als <code>prevent_path_disclosure_error_reporting<\/code>.<\/p>\n<p>Beim CDN-Skript kommt ein weiterer Punkt hinzu: Die Laufzeitpr\u00fcfungen zu Reichweite und Ladestrategie von Skripten werten nur Skripte aus, deren URL im Plugin-Ordner liegt. Das CDN-Skript melden deshalb nur die statischen Pr\u00fcfungen, und der Lauf mit <code>--require<\/code> liefert dieselbe Liste wie der ohne. Zum Tragen kommen die Laufzeitpr\u00fcfungen erst bei der korrigierten Fassung mit mitgeliefertem Skript: Ohne die Bedingung <code>is_front_page()<\/code> meldet Plugin Check es als <code>EnqueuedScriptsScope<\/code> (\u201eThis script is being loaded in all frontend contexts.\u201c), aber nur in einem Lauf mit <code>--require<\/code>.<\/p>\n<h2>Die korrigierte Fassung<\/h2>\n<p>Das korrigierte Plugin besteht aus drei Dateien: der Hauptdatei, einer <code>readme.txt<\/code> und einem kleinen lokalen Skript in <code>assets\/<\/code>. Die Hauptdatei erh\u00e4lt einen vollst\u00e4ndigen Header mit Lizenz, <code>Requires at least<\/code> und der Text Domain <code>lw-hello-banner<\/code> sowie eine <code>ABSPATH<\/code>-Abfrage. Der Aufruf von <code>error_reporting()<\/code> entf\u00e4llt. <code>register_setting()<\/code> bekommt Typ, <code>sanitize_callback<\/code> und Standardwert. Ausgaben werden erst beim Ausgeben mit <code>esc_attr()<\/code>, <code>esc_html()<\/code> und <code>esc_html__()<\/code> gesch\u00fctzt. Das Skript liegt im Plugin, tr\u00e4gt eine Version und wird nur auf der Startseite mit <code>in_footer<\/code> und <code>strategy<\/code> geladen. Die Array-Form des f\u00fcnften Arguments von <code>wp_enqueue_script()<\/code> gibt es seit WordPress 6.3, was zur angegebenen Mindestversion passt.<\/p>\n<pre><code>&lt;?php\n\/**\n * Plugin Name:       LW Hello Banner\n * Description:       Shows a greeting banner at the top of the front page.\n * Version:           0.2.0\n * Requires at least: 6.3\n * Requires PHP:      7.4\n * Author:            Lukas Wojcik\n * License:           GPLv2 or later\n * License URI:       https:\/\/www.gnu.org\/licenses\/gpl-2.0.html\n * Text Domain:       lw-hello-banner\n *\/\n\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n\ndefine( 'LW_HELLO_BANNER_VERSION', '0.2.0' );\n\n\/**\n * Registers the banner note setting and its field on Settings &gt; General.\n *\/\nfunction lw_hello_banner_register_setting() {\n\tregister_setting(\n\t\t'general',\n\t\t'lw_hello_banner_note',\n\t\tarray(\n\t\t\t'type'              =&gt; 'string',\n\t\t\t'sanitize_callback' =&gt; 'sanitize_text_field',\n\t\t\t'default'           =&gt; '',\n\t\t)\n\t);\n\n\tadd_settings_field(\n\t\t'lw_hello_banner_note',\n\t\t__( 'Banner note', 'lw-hello-banner' ),\n\t\t'lw_hello_banner_field',\n\t\t'general',\n\t\t'default',\n\t\tarray( 'label_for' =&gt; 'lw_hello_banner_note' )\n\t);\n}\nadd_action( 'admin_init', 'lw_hello_banner_register_setting' );\n\n\/**\n * Prints the input field for the banner note.\n *\/\nfunction lw_hello_banner_field() {\n\tprintf(\n\t\t'&lt;input type=\"text\" class=\"regular-text\" id=\"lw_hello_banner_note\" name=\"lw_hello_banner_note\" value=\"%s\"&gt;',\n\t\tesc_attr( get_option( 'lw_hello_banner_note', '' ) )\n\t);\n}\n\n\/**\n * Loads the bundled script on the front page only.\n *\/\nfunction lw_hello_banner_assets() {\n\tif ( ! is_front_page() ) {\n\t\treturn;\n\t}\n\n\twp_enqueue_script(\n\t\t'lw-hello-banner',\n\t\tplugins_url( 'assets\/lw-hello-banner.js', __FILE__ ),\n\t\tarray(),\n\t\tLW_HELLO_BANNER_VERSION,\n\t\tarray(\n\t\t\t'in_footer' =&gt; true,\n\t\t\t'strategy'  =&gt; 'defer',\n\t\t)\n\t);\n}\nadd_action( 'wp_enqueue_scripts', 'lw_hello_banner_assets' );\n\n\/**\n * Prints the banner on the front page.\n *\/\nfunction lw_hello_banner_render() {\n\tif ( ! is_front_page() ) {\n\t\treturn;\n\t}\n\n\t\/\/ phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display value, nothing is stored.\n\t$name = isset( $_GET['lw_name'] ) ? sanitize_text_field( wp_unslash( $_GET['lw_name'] ) ) : '';\n\tif ( '' === $name ) {\n\t\t$name = __( 'Guest', 'lw-hello-banner' );\n\t}\n\n\t$greeting = sprintf(\n\t\t\/* translators: %s: visitor name *\/\n\t\t__( 'Hello, %s!', 'lw-hello-banner' ),\n\t\t$name\n\t);\n\n\t$note = get_option( 'lw_hello_banner_note', '' );\n\n\techo '&lt;div class=\"lw-hello-banner\"&gt;&lt;p&gt;' . esc_html( $greeting );\n\tif ( '' !== $note ) {\n\t\techo ' ' . esc_html( $note );\n\t}\n\techo '&lt;\/p&gt;&lt;button type=\"button\"&gt;' . esc_html__( 'Dismiss', 'lw-hello-banner' ) . '&lt;\/button&gt;&lt;\/div&gt;';\n}\nadd_action( 'wp_body_open', 'lw_hello_banner_render' );<\/code><\/pre>\n<p>Den Namen aus der URL beh\u00e4lt die Fassung bewusst bei, und zwar im Parameter <code>lw_name<\/code>: WordPress selbst liest <code>name<\/code> als Beitrags-Slug, <code>?name=Anna<\/code> macht aus der Startseite deshalb eine 404-Seite, auf der <code>is_front_page()<\/code> false liefert. Er wird mit <code>wp_unslash()<\/code> und <code>sanitize_text_field()<\/code> behandelt, die verbleibende Nonce-Warnung unterdr\u00fcckt ein <code>phpcs:ignore<\/code>-Kommentar, der den Sniff nennt und eine Begr\u00fcndung tr\u00e4gt. Die FAQ von Plugin Check beschreibt solche Annotationen als vorgesehenen Weg f\u00fcr Fehlalarme von PHPCS in einer bestimmten Zeile. Die Begr\u00fcndung tr\u00e4gt hier nur, weil der Wert nichts ver\u00e4ndert: Er wird nicht gespeichert und l\u00f6st keine Aktion aus. Bei einem Formular, das Daten speichert, geh\u00f6ren Nonce und Capability-Pr\u00fcfung dazu; das behandelt <a href=\"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/sanitizing-escaping-nonces-capabilities-plugin-review\/\">ein eigener Beitrag dieser Reihe<\/a> ausf\u00fchrlich.<\/p>\n<pre><code>=== LW Hello Banner ===\nContributors: lukaswojcik\nTags: banner, greeting\nRequires at least: 6.3\nTested up to: 7.1\nRequires PHP: 7.4\nStable tag: 0.2.0\nLicense: GPLv2 or later\nLicense URI: https:\/\/www.gnu.org\/licenses\/gpl-2.0.html\n\nShows a short, dismissible greeting banner at the top of the front page.\n\n== Description ==\n\nLW Hello Banner prints a greeting on the front page. An optional note can be set under Settings &gt; General.\n\n== Changelog ==\n\n= 0.2.0 =\n* Fix all findings reported by Plugin Check.\n\n= 0.1.0 =\n* Initial version.<\/code><\/pre>\n<p>Zwei Details der Readme ergeben sich direkt aus dem Code der Pr\u00fcfung. \u201eTested up to\u201c muss der aktuellen Hauptversion von WordPress entsprechen, derzeit 7.1. Ein \u00e4lterer Wert ist bei neuen Plugins ein Fehler und im Update-Modus eine Warnung; ein Wert mit Patch-Stufe wie 7.1.2 wird als <code>invalid_tested_upto_minor<\/code> gemeldet. Au\u00dferdem vergleicht die Pr\u00fcfung die Lizenz in der Readme mit der im Plugin-Header und meldet Abweichungen als <code>license_mismatch<\/code>, deshalb steht in beiden Dateien derselbe Wortlaut. Die Felder von Readme und Plugin-Header behandelt <span class=\"lw-artikel-geplant\">ein eigener Beitrag dieser Reihe<\/span>.<\/p>\n<pre><code>\/\/ assets\/lw-hello-banner.js\n( function () {\n\tconst banner = document.querySelector( '.lw-hello-banner' );\n\tif ( ! banner ) {\n\t\treturn;\n\t}\n\n\tconst button = banner.querySelector( 'button' );\n\tif ( button ) {\n\t\tbutton.addEventListener( 'click', function () {\n\t\t\tbanner.hidden = true;\n\t\t} );\n\t}\n} )();<\/code><\/pre>\n<h2>Plugin Check in GitHub Actions<\/h2>\n<p>Die offizielle Anbindung ist das Repository WordPress\/plugin-check-action. Die neueste Version ist v1.1.9 vom 11. August 2026, das mitwandernde Tag <code>v1<\/code> zeigt derzeit auf denselben Commit. Es handelt sich um eine Composite Action: Zuerst richtet sie Node 24 ein, installiert <code>@wordpress\/env<\/code>, startet eine WordPress-Instanz mit dem Plugin-Ordner unter <code>wp-content\/plugins<\/code>, installiert Plugin Check aus dem Verzeichnis, dazu die unter <code>Requires Plugins<\/code> genannten Plugins, und ruft dann <code>wp plugin check<\/code> mit <code>--format=json<\/code> und <code>--require=.\/wp-content\/plugins\/plugin-check\/cli.php<\/code> auf. Laufzeitpr\u00fcfungen sind also dabei. Laut Dokumentation l\u00e4uft wp-env standardm\u00e4\u00dfig auf Docker, der \u00fcbliche Ubuntu-Runner ist deshalb die naheliegende Wahl.<\/p>\n<p>Ein Node-Skript wertet die JSON-Datei aus. Jedes Ergebnis wird zu einer Annotation an der betroffenen Datei, mit dem Ergebniscode als Titel. Jedes <code>ERROR<\/code> setzt den Exitcode auf 1 und l\u00e4sst den Job scheitern, Warnungen erscheinen nur als Annotation. Mit <code>strict: true<\/code> z\u00e4hlt jedes Ergebnis als Fehler. Bei Pull Requests schreibt oder aktualisiert die Action zus\u00e4tzlich einen Zusammenfassungskommentar, das Rohergebnis landet als Artefakt <code>plugin-check-results<\/code>.<\/p>\n<p>Eingaben in v1.1.9: <code>build-dir<\/code> (Standard <code>.\/<\/code>), <code>checks<\/code>, <code>exclude-checks<\/code>, <code>categories<\/code>, <code>exclude-files<\/code>, <code>exclude-directories<\/code>, <code>ignore-codes<\/code>, <code>ignore-warnings<\/code>, <code>ignore-errors<\/code>, <code>include-experimental<\/code>, <code>wp-version<\/code> (<code>latest<\/code> oder <code>trunk<\/code>), <code>severity<\/code>, <code>error-severity<\/code>, <code>warning-severity<\/code>, <code>include-low-severity-errors<\/code>, <code>include-low-severity-warnings<\/code>, <code>slug<\/code>, <code>strict<\/code> und <code>repo-token<\/code>. Listen-Eingaben nehmen einen Eintrag je Zeile.<\/p>\n<p>Zwei Details entscheiden dar\u00fcber, ob die Ergebnisse stimmen. Die Action leitet den Slug aus dem letzten Teil von <code>build-dir<\/code> ab. Beim Standard <code>.\/<\/code> ist das der Name des Checkout-Verzeichnisses, und der entspricht laut GitHub-Dokumentation dem Repository-Namen, etwa <code>\/home\/runner\/work\/my-repo-name\/my-repo-name<\/code>. Hei\u00dft das Repository anders als das Plugin, f\u00e4llt jeder \u00dcbersetzungsaufruf durch. Zudem warnt die Pr\u00fcfung <code>file_type<\/code> in 2.1.0 vor einem Ordner <code>.github<\/code> im Plugin und beanstandet weitere versteckte Dateien. Wer das Repository-Wurzelverzeichnis pr\u00fcft, pr\u00fcft also Dateien, die nie ausgeliefert werden. Der folgende Workflow baut deshalb mit <code>git archive<\/code> den Ordner, der tats\u00e4chlich hochgeladen w\u00fcrde, ber\u00fccksichtigt dabei die <code>export-ignore<\/code>-Eintr\u00e4ge aus <code>.gitattributes<\/code> und \u00fcbergibt diesen Ordner als <code>build-dir<\/code>.<\/p>\n<pre><code># .github\/workflows\/plugin-check.yml\nname: Plugin Check\n\non:\n  pull_request:\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: read\n  pull-requests: write # only for the summary comment on pull requests\n\njobs:\n  plugin-check:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions\/checkout@v7\n\n      # Build the folder that would be shipped, without .github and other\n      # development files (see export-ignore in .gitattributes).\n      - name: Build distributable plugin folder\n        run: |\n          mkdir -p build\n          git archive --format=tar --prefix=lw-hello-banner\/ HEAD | tar -x -C build\n\n      - name: Run Plugin Check\n        uses: wordpress\/plugin-check-action@v1\n        with:\n          # The folder name becomes the slug (text domain check, readme check).\n          build-dir: .\/build\/lw-hello-banner\n          wp-version: latest\n          # Optional filters, one entry per line:\n          # categories: |\n          #   plugin_repo\n          #   security\n          # exclude-checks: |\n          #   enqueued_scripts_scope\n          # ignore-codes: |\n          #   textdomain_mismatch\n          # Fail on warnings as well:\n          # strict: true<\/code><\/pre>\n<pre><code># .gitattributes: files that git archive leaves out of the build\n\/.gitattributes export-ignore\n\/.github        export-ignore\n\/.gitignore     export-ignore\n\/build          export-ignore<\/code><\/pre>\n<p>Die Berechtigung <code>pull-requests: write<\/code> ist nur f\u00fcr den Zusammenfassungskommentar n\u00f6tig; laut den Berechtigungstabellen von GitHub deckt sie den Kommentar-Endpunkt ab. Fehlt sie, protokolliert die Action eine Warnung beim Kommentieren, wertet die Ergebnisse aber trotzdem aus. Wer feste Versionen bevorzugt, verweist statt auf <code>v1<\/code> auf <code>wordpress\/plugin-check-action@v1.1.9<\/code> oder auf dessen Commit-Hash.<\/p>\n<h2>Grenzen und offene Punkte<\/h2>\n<ul>\n<li>Plugin Check ersetzt das manuelle Review nicht. Die Plugin-Seite sagt das ausdr\u00fccklich, und ein sauberer Lauf garantiert keine Freigabe.<\/li>\n<li>Die Befundtabelle zum Beispiel-Plugin stammt aus einem lokalen Lauf von <code>wp plugin check<\/code> unter WordPress 7.1.2. Auf GitHub lief der Workflow nicht; lokal erzeugte der Schritt mit <code>git archive<\/code> den erwarteten Ordner, und das Auswerteskript der Action (v1.1.9) endete beim fehlerhaften Beispiel mit Exitcode 1, bei der korrigierten Fassung mit 0.<\/li>\n<li>Manche Pr\u00fcfungen arbeiten mit Heuristiken. Die Pr\u00e4fix-Pr\u00fcfung leitet die erwarteten Pr\u00e4fixe aus dem Plugin-Code ab, deshalb z\u00e4hlt ein durchg\u00e4ngiges Pr\u00e4fix wie <code>lw_hello_banner_<\/code>.<\/li>\n<li>Die Action installiert die Plugin-Check-Version, die das Verzeichnis zum Zeitpunkt des Laufs anbietet, und hat keine Eingabe, um sie festzuschreiben. Eine Pipeline kann also nach einem Plugin-Check-Release rot werden, ohne dass sich am Plugin etwas ge\u00e4ndert hat.<\/li>\n<li>F\u00fcr die PHP-Version gibt es keine Eingabe, und <code>wp-version<\/code> unterscheidet nur zwischen aktueller Version und trunk. Tests gegen \u00e4ltere WordPress- oder PHP-Versionen brauchen einen eigenen Aufbau, etwa mit wp-env oder Playground; darum geht es in <span class=\"lw-artikel-geplant\">einem eigenen Beitrag dieser Reihe<\/span>.<\/li>\n<li>Performance-Befunde zur Reichweite von Skripten h\u00e4ngen davon ab, wie das Plugin Dateien einbindet; die andere Seite des Problems zeigt <a href=\"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/performance-optimierung-via-functions-php-selektives-dequeuing\/\">der Beitrag zum gezielten Dequeuing von Plugin-Skripten<\/a>.<\/li>\n<\/ul>\n<div class=\"lw-faq\">\n<h2>Fragen und Antworten<\/h2>\n<h3>Garantiert ein Lauf ohne Befunde, dass das Plugin ins Verzeichnis aufgenommen wird?<\/h3>\n<p>Nein. Laut FAQ von Plugin Check muss ein Plugin in der Regel alle Pr\u00fcfungen der Kategorie <code>plugin_repo<\/code> bestehen, die Freigabe h\u00e4ngt aber weiter vom manuellen Review ab. Die Plugin-Seite h\u00e4lt ausdr\u00fccklich fest, dass Plugin Check das manuelle Review nicht ersetzt; ein sauberer Lauf beschleunigt es nur.<\/p>\n<h3>Warum meldet die GitHub Action mehr als der lokale Aufruf von wp plugin check?<\/h3>\n<p>Daf\u00fcr gibt es drei typische Gr\u00fcnde:<\/p>\n<ul>\n<li>Die Action l\u00e4dt immer <code>cli.php<\/code> per <code>--require<\/code> und aktiviert das Plugin, lokal laufen ohne diesen Umweg oder bei inaktivem Plugin nur statische Pr\u00fcfungen.<\/li>\n<li>Die Action installiert die jeweils aktuelle Plugin-Check-Version aus dem Verzeichnis, lokal kann eine \u00e4ltere aktiv sein.<\/li>\n<li>Mit <code>build-dir: .\/<\/code> pr\u00fcft sie das ganze Repository samt <code>.github<\/code> und versteckten Dateien.<\/li>\n<\/ul>\n<h3>Wann ist es vertretbar, eine Warnung zu unterdr\u00fccken?<\/h3>\n<p>Wenn der Befund im konkreten Fall nachweislich kein Problem ist, etwa ein nur angezeigter, bereinigter URL-Parameter ohne Speichervorgang. Dann geh\u00f6rt ein <code>phpcs:ignore<\/code>-Kommentar mit Sniff-Name und Begr\u00fcndung direkt an die Zeile. <code>--ignore-codes<\/code> oder die Action-Eingabe <code>ignore-codes<\/code> blenden einen Code dagegen im ganzen Plugin aus und verdecken damit auch echte Treffer.<\/p>\n<h3>Warum wird dieselbe Text Domain zweimal beanstandet?<\/h3>\n<p>Zwei Pr\u00fcfungen vergleichen mit dem Slug: <code>plugin_header_fields<\/code> pr\u00fcft den Header <code>Text Domain<\/code> und meldet <code>textdomain_mismatch<\/code> als Warnung, <code>i18n_usage<\/code> pr\u00fcft jeden \u00dcbersetzungsaufruf und meldet <code>WordPress.WP.I18n.TextDomainMismatch<\/code>. Der Slug ist der Ordnername; in der CI l\u00e4sst er sich mit der Eingabe <code>slug<\/code> oder lokal mit <code>--slug<\/code> festlegen.<\/p>\n<\/div>\n<div class=\"lw-quellen\">\n<h2>Quellen<\/h2>\n<ul>\n<li><a href=\"https:\/\/wordpress.org\/plugins\/plugin-check\/\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Check (PCP) auf WordPress.org<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress\/plugin-check, README<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/releases\/tag\/2.1.0\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Check Release 2.1.0<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/blob\/2.1.0\/docs\/CLI.md\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Check: WP-CLI-Dokumentation (docs\/CLI.md)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/blob\/2.1.0\/docs\/checks.md\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin Check: verf\u00fcgbare Pr\u00fcfungen (docs\/checks.md)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/blob\/2.1.0\/includes\/Checker\/Default_Check_Repository.php\" target=\"_blank\" rel=\"noopener noreferrer\">Default_Check_Repository.php (Tag 2.1.0)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/blob\/2.1.0\/includes\/Checker\/Check_Categories.php\" target=\"_blank\" rel=\"noopener noreferrer\">Check_Categories.php (Tag 2.1.0)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/blob\/2.1.0\/includes\/CLI\/Plugin_Check_Command.php\" target=\"_blank\" rel=\"noopener noreferrer\">Plugin_Check_Command.php (Tag 2.1.0)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/blob\/2.1.0\/phpcs-rulesets\/plugin-check.ruleset.xml\" target=\"_blank\" rel=\"noopener noreferrer\">plugin-check.ruleset.xml (Tag 2.1.0)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/tree\/2.1.0\/includes\/Checker\/Checks\" target=\"_blank\" rel=\"noopener noreferrer\">Quelltext der Pr\u00fcfungen (Tag 2.1.0)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check\/tree\/2.1.0\/tests\/phpunit\/tests\/Checker\/Checks\" target=\"_blank\" rel=\"noopener noreferrer\">Unit-Tests der Pr\u00fcfungen (Tag 2.1.0)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check-action\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress\/plugin-check-action, README<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check-action\/blob\/v1.1.9\/action.yml\" target=\"_blank\" rel=\"noopener noreferrer\">plugin-check-action: action.yml (v1.1.9)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check-action\/blob\/v1.1.9\/src\/main.ts\" target=\"_blank\" rel=\"noopener noreferrer\">plugin-check-action: src\/main.ts (v1.1.9)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/WordPress\/plugin-check-action\/releases\/tag\/v1.1.9\" target=\"_blank\" rel=\"noopener noreferrer\">plugin-check-action Release v1.1.9<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_enqueue_script\/\" target=\"_blank\" rel=\"noopener noreferrer\">wp_enqueue_script() \u2013 Developer Resources<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/packages\/packages-env\/\" target=\"_blank\" rel=\"noopener noreferrer\">@wordpress\/env \u2013 Block Editor Handbook<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/api.wordpress.org\/core\/version-check\/1.7\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress.org Versions-API (aktuelle Version 7.1.2)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/github.com\/actions\/checkout\/releases\" target=\"_blank\" rel=\"noopener noreferrer\">actions\/checkout Releases (v7.0.1)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/docs.github.com\/en\/actions\/reference\/workflows-and-actions\/variables\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub Docs: Variablen (GITHUB_WORKSPACE)<\/a>, abgerufen am 29.09.2026<\/li>\n<li><a href=\"https:\/\/docs.github.com\/en\/rest\/authentication\/permissions-required-for-github-apps\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub Docs: Berechtigungen f\u00fcr GitHub Apps<\/a>, abgerufen am 29.09.2026<\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Plugin Check 2.1.0 im Backend, per WP-CLI und in GitHub Actions, vorgef\u00fchrt an einem absichtlich fehlerhaften Beispiel-Plugin und seiner korrigierten Fassung.<\/p>\n","protected":false},"author":1,"featured_media":20889,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[92644],"tags":[92214,92274,92235,92071,92277],"class_list":["post-20855","post","type-post","status-publish","format-standard","hentry","category-tutorials-de-wordpress-plugins-tricks-de","tag-devops-de","tag-php-de","tag-tutorial-de","tag-web-security-de","tag-wordpress-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Plugin Check lokal und in der CI: Befunde vor dem Review | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"Plugin Check 2.1.0 mit wp plugin check und der offiziellen GitHub Action: Kategorien, Ergebniscodes und ein fehlerhaftes Beispiel-Plugin samt Korrektur.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Plugin Check lokal und in der CI: Befunde vor dem Review | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Plugin Check 2.1.0 mit wp plugin check und der offiziellen GitHub Action: Kategorien, Ergebniscodes und ein fehlerhaftes Beispiel-Plugin samt Korrektur.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-07T09:52:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20855-plugin-check-lokal-und-ci.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Plugin Check lokal und in der CI: Befunde vor dem Review\",\"datePublished\":\"2026-10-07T09:52:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/\"},\"wordCount\":2462,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20855-plugin-check-lokal-und-ci.png\",\"keywords\":[\"DevOps\",\"PHP\",\"Tutorial\",\"Web Security\",\"WordPress\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/\",\"name\":\"Plugin Check lokal und in der CI: Befunde vor dem Review | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20855-plugin-check-lokal-und-ci.png\",\"datePublished\":\"2026-10-07T09:52:00+00:00\",\"description\":\"Plugin Check 2.1.0 mit wp plugin check und der offiziellen GitHub Action: Kategorien, Ergebniscodes und ein fehlerhaftes Beispiel-Plugin samt Korrektur.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20855-plugin-check-lokal-und-ci.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/fi-20855-plugin-check-lokal-und-ci.png\",\"width\":1200,\"height\":630,\"caption\":\"Plugin Check lokal und in der CI: Befunde vor dem Review\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/wordpress-plugins-tricks-de\\\/tutorials-de-wordpress-plugins-tricks-de\\\/plugin-check-lokal-und-ci\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Plugin Check lokal und in der CI: Befunde vor dem Review\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Plugin Check lokal und in der CI: Befunde vor dem Review | Lukas Wojcik","description":"Plugin Check 2.1.0 mit wp plugin check und der offiziellen GitHub Action: Kategorien, Ergebniscodes und ein fehlerhaftes Beispiel-Plugin samt Korrektur.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/","og_locale":"en_US","og_type":"article","og_title":"Plugin Check lokal und in der CI: Befunde vor dem Review | Lukas Wojcik","og_description":"Plugin Check 2.1.0 mit wp plugin check und der offiziellen GitHub Action: Kategorien, Ergebniscodes und ein fehlerhaftes Beispiel-Plugin samt Korrektur.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-10-07T09:52:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20855-plugin-check-lokal-und-ci.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Plugin Check lokal und in der CI: Befunde vor dem Review","datePublished":"2026-10-07T09:52:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/"},"wordCount":2462,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20855-plugin-check-lokal-und-ci.png","keywords":["DevOps","PHP","Tutorial","Web Security","WordPress"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/","name":"Plugin Check lokal und in der CI: Befunde vor dem Review | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20855-plugin-check-lokal-und-ci.png","datePublished":"2026-10-07T09:52:00+00:00","description":"Plugin Check 2.1.0 mit wp plugin check und der offiziellen GitHub Action: Kategorien, Ergebniscodes und ein fehlerhaftes Beispiel-Plugin samt Korrektur.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20855-plugin-check-lokal-und-ci.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/fi-20855-plugin-check-lokal-und-ci.png","width":1200,"height":630,"caption":"Plugin Check lokal und in der CI: Befunde vor dem Review"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/wordpress-plugins-tricks-de\/tutorials-de-wordpress-plugins-tricks-de\/plugin-check-lokal-und-ci\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Plugin Check lokal und in der CI: Befunde vor dem Review"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/20855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=20855"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/20855\/revisions"}],"predecessor-version":[{"id":21692,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/20855\/revisions\/21692"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/20889"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=20855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=20855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}