Check pages removeOrphans() deleted in this request; renderIntro() reports them. */ private array $removed = []; /** * @param FeatureOverview|null $overview null = a table without the affected tools. * @param (Closure(): string)|null $version Installed Divi version ('' = none); null = DiviEnvironment. * @param CheckReportStore|null $reports null = the Divi store. */ public function __construct( private ?FeatureOverview $overview = null, private ?Closure $version = null, private ?CheckReportStore $reports = null ) { } public function register(): void { add_action('admin_notices', [$this, 'renderNotice']); add_action(CompatibilityTab::LOAD_ACTION, [$this, 'removeOrphans']); add_action(CompatibilityTab::INTRO_ACTION, [$this, 'renderIntro']); add_action(CompatibilityTab::EXTRA_ACTION, [$this, 'renderExtras']); add_filter(CompatibilityTab::EXPLANATION_FILTER, [$this, 'explanation'], 10, 3); add_filter(CompatibilityTab::COLUMNS_FILTER, [$this, 'columns'], 10, 2); } /** * Only for administrators, only with Divi active, only while a feature is not usable – and not on the tab * "Compatibility", which shows the same table. Reads the cached matrix (D7), so no check runs on an admin page. */ public function renderNotice(): void { if (! current_user_can('manage_options') || $this->version() === '' || $this->onCompatibilityTab()) { return; } $unusable = ReleaseGate::status()->matrix->unusable(); if ($unusable === []) { return; } printf( '
%s %s
%s
' . esc_html__( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument. 'Die Prüfung legt eine private Testseite an, prüft Lesen und Schreiben und löscht sie wieder.', 'wp-lit-mcp' ) . '
'; } /** * Filter lit_mcp_compat_explanation: Divi says where its release comes from (plugin, automatic, this website) * instead of the generic sentence, so the section does not explain the state twice. */ public function explanation(string $text, string $profileId, ReleaseState $state): string { if ($profileId !== DiviProfile::ID) { return $text; } $status = ReleaseGate::status(); return match (true) { $status->state === ReleaseState::Incompatible => __( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument. 'Divi hat Stellen geändert, die LIT MCP nutzt. Die betroffenen Fähigkeiten (Tabelle unten) bleiben gesperrt, bis ein Plugin-Update von LIT MCP eingespielt ist; alle anderen laufen weiter.', 'wp-lit-mcp' ), $status->state === ReleaseState::Untested => __( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument. 'Diese Version ist nicht geprüft. Die Tools der ungetesteten Fähigkeiten (Tabelle unten) lehnen ab, bis die Version freigegeben ist; alle anderen laufen weiter.', 'wp-lit-mcp' ), $status->source === ReleaseStatus::SOURCE_CODE => __( 'Diese Version ist im Plugin als getestet hinterlegt.', 'wp-lit-mcp' ), $status->source === ReleaseStatus::SOURCE_AUTO => __( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument. 'Automatisch freigegeben: Alle Divi-Stellen, die LIT MCP nutzt, stimmen mit der geprüften Referenz überein.', 'wp-lit-mcp' ), default => $this->releasedOnThisSite($status), }; } private function releasedOnThisSite(ReleaseStatus $status): string { $user = get_userdata((int) ($status->release['user_id'] ?? 0)); $releasedAt = (int) strtotime((string) ($status->release['released_at'] ?? '')); return sprintf( /* translators: 1: date, 2: user name */ __('Auf dieser Website freigegeben am %1$s von %2$s.', 'wp-lit-mcp'), date_i18n((string) get_option('date_format'), $releasedAt), is_object($user) && isset($user->display_name) ? (string) $user->display_name : '?' ); } /** lit_mcp_compat_profile_extra('divi'): the end of the Divi section (shown only while Divi is active). */ public function renderExtras(string $profileId): void { if ($profileId !== DiviProfile::ID) { return; } $this->renderAutomationNote(); $reports = $this->reports ?? new CheckReportStore(DiviProfile::ID, DiviProfile::REPORT_VERSION_KEY); if ($reports->latest() !== null) { echo '' . esc_html__( 'Optional: eine Divi-Seite im Visual Builder öffnen und speichern.', 'wp-lit-mcp' ) . '
'; } } /** One sentence on what to do now; a released version needs none. */ private function renderNextStep(ReleaseStatus $status): void { $text = match ($status->state) { ReleaseState::Untested => sprintf( /* translators: %s: Divi version */ __( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text. 'Divi %s ist noch nicht geprüft. Starte die Prüfung; danach kannst du die Version freigeben.', 'wp-lit-mcp' ), $status->version ), ReleaseState::Incompatible => sprintf( /* translators: %s: Divi version */ __( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text. 'Divi %s hat Stellen geändert, die LIT MCP nutzt. Die betroffenen Tools bleiben gesperrt, bis ein Plugin-Update erscheint.', 'wp-lit-mcp' ), $status->version ), default => null, }; if ($text === null) { return; } printf( '%s
' . esc_html__( // phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument. 'Automatik: Ist die installierte Divi-Version im Plugin nicht als getestet hinterlegt, gibt LIT MCP jede Fähigkeit einzeln frei, wenn alle benutzten Divi-Funktionen vorhanden sind, ihre Aufrufe (Signaturen) und die Fingerabdrücke nachgebauter Divi-Abläufe unverändert sind und alle Konstanten definiert sind. Das prüft Aufrufformen, nicht das Verhalten von Divi. Fehlt für eine Stelle die Referenz, ist die Fähigkeit ungetestet; weicht etwas ab, ist sie inkompatibel.', 'wp-lit-mcp' ) . '
'; echo '' . sprintf(
/* translators: %s: filter name in a code element */
esc_html__(
// phpcs:ignore Generic.Files.LineLength.TooLong -- WordPress.WP.I18n forbids splitting the text argument.
'Die Automatik abschalten: Filter %s auf false setzen (z. B. in einem mu-Plugin). Dann gelten nicht hinterlegte Divi-Versionen bis zur Freigabe als ungetestet.',
'wp-lit-mcp'
),
'lit_mcp_divi_auto_release'
) . '