$args Weitere Parameter. * @return string */ public static function tab_url( $tab, array $args = array() ) { return add_query_arg( array_merge( array( 'tab' => $tab ), $args ), self::page_url() ); } public static function register_menu() { self::$hook = (string) add_submenu_page( Wp360_Staging_Guard_Orbit_Menu::SLUG, __( 'Staging Guard', '360-orbit-staging-guard' ), __( 'Staging Guard', '360-orbit-staging-guard' ), self::CAPABILITY, self::SLUG, array( __CLASS__, 'render_page' ) ); } /** * @param string[] $links Bisherige Links. * @return string[] */ public static function action_links( $links ) { array_unshift( $links, '' . esc_html__( 'Settings', '360-orbit-staging-guard' ) . '' ); return $links; } /** * @param string $hook_suffix Hook-Suffix des aktuellen Bildschirms. */ public static function enqueue_assets( $hook_suffix ) { if ( '' === self::$hook || self::$hook !== $hook_suffix ) { return; } wp_enqueue_style( 'wp360-sg-admin', WP360_SG_URL . 'assets/admin.css', array(), WP360_SG_VERSION ); } /** * Zeile fuer die Orbit-Uebersicht. * * @param string[] $lines Bisherige Zeilen. * @param string $slug Plugin, fuer das die Zeilen gefragt sind. * @return string[] */ public static function health_lines( array $lines, $slug ) { if ( '360-orbit-staging-guard' !== $slug ) { return $lines; } $state = Wp360_Staging_Guard_Environment::state(); if ( Wp360_Staging_Guard_Plugin::is_disabled() ) { $lines[] = __( 'Switched off by WP360_SG_DISABLE.', '360-orbit-staging-guard' ); } elseif ( $state['active'] ) { $lines[] = __( 'Protection is active.', '360-orbit-staging-guard' ); } elseif ( $state['notice'] ) { $lines[] = __( 'Not protected: this address differs from the live site.', '360-orbit-staging-guard' ); } else { $lines[] = __( 'Protection is off.', '360-orbit-staging-guard' ); } return $lines; } /* ---------------------------------------------------------------- */ /* Admin-Leiste und Hinweise */ /* ---------------------------------------------------------------- */ /** * Kurzbezeichnung der Umgebung fuer die Admin-Leiste. * * @param array{active: bool, reason: string, notice: bool, environment: string} $state Zustand. * @return string */ private static function environment_label( array $state ) { $labels = array( 'local' => __( 'LOCAL', '360-orbit-staging-guard' ), 'development' => __( 'DEV', '360-orbit-staging-guard' ), 'staging' => __( 'STAGING', '360-orbit-staging-guard' ), ); return $labels[ $state['environment'] ] ?? __( 'STAGING', '360-orbit-staging-guard' ); } /** * Begruendung, warum der Schutz gerade aktiv ist. * * @param array{active: bool, reason: string, notice: bool, environment: string} $state Zustand. * @return string */ private static function reason_text( array $state ) { if ( Wp360_Staging_Guard_Environment::REASON_FORCED === $state['reason'] ) { return __( 'Switched on manually.', '360-orbit-staging-guard' ); } /* translators: %s: environment type such as staging, local or development */ return sprintf( __( 'Environment type: %s.', '360-orbit-staging-guard' ), $state['environment'] ); } /** * Eintrag in der Admin-Leiste: rot bei aktivem Schutz, amber bei dem * Hinweis "Adresse weicht ab". * * @param WP_Admin_Bar $bar Admin-Leiste. */ public static function admin_bar_node( $bar ) { if ( ! self::can_manage() ) { return; } $state = Wp360_Staging_Guard_Environment::state(); if ( $state['active'] ) { $bar->add_node( array( 'id' => 'wp360-sg', 'title' => '' . esc_html( self::environment_label( $state ) ) . '', 'href' => self::page_url(), 'meta' => array( 'class' => 'wp360-sg-active' ), ) ); return; } if ( $state['notice'] ) { $bar->add_node( array( 'id' => 'wp360-sg', 'title' => '' . esc_html__( 'NOT PROTECTED', '360-orbit-staging-guard' ) . '', 'href' => self::page_url(), 'meta' => array( 'class' => 'wp360-sg-notice' ), ) ); } } /** Farben des Eintrags; nur ausgegeben, wenn die Admin-Leiste ihn zeigt. */ public static function enqueue_bar_styles() { if ( ! is_admin_bar_showing() || ! self::can_manage() ) { return; } $state = Wp360_Staging_Guard_Environment::state(); if ( ! $state['active'] && ! $state['notice'] ) { return; } $css = '#wpadminbar .wp360-sg-active > .ab-item{background:' . self::COLOR_ACTIVE . ';color:#fff;font-weight:600}'; $css .= '#wpadminbar .wp360-sg-active:hover > .ab-item,#wpadminbar .wp360-sg-active > .ab-item:focus{background:#9f1d1d;color:#fff}'; $css .= '#wpadminbar .wp360-sg-notice > .ab-item{background:' . self::COLOR_NOTICE . ';color:#fff;font-weight:600}'; $css .= '#wpadminbar .wp360-sg-notice:hover > .ab-item,#wpadminbar .wp360-sg-notice > .ab-item:focus{background:#92400e;color:#fff}'; $css .= '#wpadminbar .wp360-sg-active > .ab-item .ab-icon:before,#wpadminbar .wp360-sg-notice > .ab-item .ab-icon:before{content:"\f334";top:2px;color:#fff}'; wp_register_style( 'wp360-sg-bar', false, array(), WP360_SG_VERSION ); wp_enqueue_style( 'wp360-sg-bar' ); wp_add_inline_style( 'wp360-sg-bar', $css ); } /** Hinweise im Backend (nicht im Dashboard). */ public static function render_notices() { if ( ! self::can_manage() ) { return; } $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; if ( $screen && 'dashboard' === $screen->id ) { return; } if ( Wp360_Staging_Guard_Plugin::is_disabled() ) { echo '

' . esc_html__( 'Staging Guard is switched off.', '360-orbit-staging-guard' ) . ' '; echo esc_html__( 'The constant WP360_SG_DISABLE is set in wp-config.php. Remove it to switch the protection back on.', '360-orbit-staging-guard' ) . '

'; return; } $state = Wp360_Staging_Guard_Environment::state(); // Bei aktivem Schutz zeigt die rote Markierung in der Admin-Leiste, dass // dies eine Kopie ist; ein grosser Hinweis auf jeder Seite entfaellt // (Entscheidung 12.10.2026). Der Knopf "Das ist die Live-Seite" steht auf // der Status-Seite. if ( $state['notice'] ) { echo '

' . esc_html__( 'This site runs under a different address than the live site.', '360-orbit-staging-guard' ) . ' '; echo esc_html__( 'It is not protected yet: emails and outgoing calls still go out for real.', '360-orbit-staging-guard' ) . '

'; echo '

'; self::render_action_form( 'wp360_sg_enable', __( 'Switch protection on now', '360-orbit-staging-guard' ), 'primary', false ); self::render_action_form( 'wp360_sg_is_live', __( 'This is the live site', '360-orbit-staging-guard' ), 'secondary', false, __( 'Use this address as the live address? Only do this if this really is the live site.', '360-orbit-staging-guard' ) ); echo '

'; } } /** * Kleines Formular, das eine der admin-post-Aktionen ausloest. * * @param string $action Aktionsname. * @param string $label Beschriftung. * @param string $type primary oder secondary. * @param bool $wrap In einen Absatz einhuellen. * @param string $confirm Rueckfrage vor dem Absenden (leer = keine). */ private static function render_action_form( $action, $label, $type, $wrap = true, $confirm = '' ) { if ( $wrap ) { echo '

'; } $onsubmit = '' !== $confirm ? ' onsubmit="return confirm(' . esc_attr( wp_json_encode( $confirm ) ) . ');"' : ''; echo '

'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $onsubmit ist oben escaped. echo ''; wp_nonce_field( 'wp360_sg_state', '_wpnonce', true, true ); echo ''; echo '
'; if ( $wrap ) { echo '

'; } } /* ---------------------------------------------------------------- */ /* Seite */ /* ---------------------------------------------------------------- */ /** @return string Aktiver Reiter. */ private static function current_tab() { $valid = array( 'status', 'settings', 'log', 'mails', 'pro' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nur lesende Auswahl des Reiters. $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; return in_array( $tab, $valid, true ) ? $tab : 'status'; } /** * @param string $current_tab Aktiver Reiter. */ private static function render_tabs( $current_tab ) { $tabs = array( 'status' => __( 'Status', '360-orbit-staging-guard' ), 'settings' => __( 'Settings', '360-orbit-staging-guard' ), 'log' => __( 'Log', '360-orbit-staging-guard' ), 'mails' => __( 'Mail catcher', '360-orbit-staging-guard' ), ); $show_pro_tab = true; if ( $show_pro_tab ) { $tabs['pro'] = __( 'Staging Guard Pro', '360-orbit-staging-guard' ); } echo ''; } public static function render_page() { if ( ! self::can_manage() ) { return; } $tab = self::current_tab(); $edition = 'Free'; echo '
'; echo ''; echo '

360 Orbit ' . esc_html__( 'Staging Guard', '360-orbit-staging-guard' ) . ' (' . esc_html( $edition ) . ')


'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nur Anzeige einer Meldung. $notice = isset( $_GET['wp360_sg_notice'] ) ? sanitize_key( wp_unslash( $_GET['wp360_sg_notice'] ) ) : ''; $notices = array( 'saved' => array( 'success', __( 'Settings saved.', '360-orbit-staging-guard' ) ), 'allowed' => array( 'success', __( 'The host was added to the allow list.', '360-orbit-staging-guard' ) ), 'bad_host' => array( 'error', __( 'That is not a valid host name.', '360-orbit-staging-guard' ) ), 'log_cleared' => array( 'success', __( 'The log was cleared.', '360-orbit-staging-guard' ) ), 'bad_live_url' => array( 'error', __( 'The live address could not be read and was not saved. Please enter a full address such as https://example.com.', '360-orbit-staging-guard' ) ), ); if ( isset( $notices[ $notice ] ) ) { echo '

' . esc_html( $notices[ $notice ][1] ) . '

'; } self::render_tabs( $tab ); switch ( $tab ) { case 'settings': self::render_settings_tab(); break; case 'log': self::render_log_tab(); break; case 'mails': Wp360_Staging_Guard_Mail_Viewer::render(); break; case 'pro': self::render_pro_tab(); break; default: self::render_status_tab(); } echo '
'; } /* ---------------------------------------------------------------- */ /* Reiter: Status */ /* ---------------------------------------------------------------- */ private static function render_status_tab() { $state = Wp360_Staging_Guard_Environment::state(); $settings = Wp360_Staging_Guard_Settings::get(); $disabled = Wp360_Staging_Guard_Plugin::is_disabled(); echo '
'; echo '

' . esc_html__( 'Protection', '360-orbit-staging-guard' ) . '

'; if ( $disabled ) { echo '

' . esc_html__( 'Switched off', '360-orbit-staging-guard' ) . ' ' . esc_html__( 'The constant WP360_SG_DISABLE is set in wp-config.php.', '360-orbit-staging-guard' ) . '

'; } elseif ( $state['active'] ) { echo '

' . esc_html__( 'Active', '360-orbit-staging-guard' ) . ' ' . esc_html( self::reason_text( $state ) ) . '

'; echo '

' . esc_html__( 'Protection runs on the wrong site? Use this only if this really is the live site; it switches the protection off and remembers this address as the live address.', '360-orbit-staging-guard' ) . '

'; self::render_action_form( 'wp360_sg_is_live', __( 'This is the live site', '360-orbit-staging-guard' ), 'secondary', true, __( 'Use this address as the live address? Only do this if this really is the live site.', '360-orbit-staging-guard' ) ); if ( Wp360_Staging_Guard_Host_Matcher::is_live_host( Wp360_Staging_Guard_Host_Matcher::host_of( home_url() ), $settings['live_url'] ) ) { echo '

' . esc_html__( 'This address is the same as the saved live address. Calls to the live site cannot be told apart from calls to this site. If this is a copy of the live database, update the site address first.', '360-orbit-staging-guard' ) . '

'; } } elseif ( $state['notice'] ) { echo '

' . esc_html__( 'Not protected', '360-orbit-staging-guard' ) . ' ' . esc_html__( 'This address differs from the live site, but the protection is not on.', '360-orbit-staging-guard' ) . '

'; } else { echo '

' . esc_html__( 'Off', '360-orbit-staging-guard' ) . ' ' . esc_html__( 'This looks like the live site, nothing is blocked.', '360-orbit-staging-guard' ) . '

'; } echo ''; self::row( __( 'Environment type', '360-orbit-staging-guard' ), esc_html( $state['environment'] ) . ' (' . esc_html( self::environment_source() ) . ')' ); self::row( __( 'Mode', '360-orbit-staging-guard' ), esc_html( self::mode_label( $settings['mode'] ) ) ); self::row( __( 'This address', '360-orbit-staging-guard' ), esc_html( home_url() ) ); self::row( __( 'Live address', '360-orbit-staging-guard' ), '' !== $settings['live_url'] ? esc_html( $settings['live_url'] ) : '' . esc_html__( 'not set', '360-orbit-staging-guard' ) . '' ); echo '
'; echo '
'; $totals = Wp360_Staging_Guard_Log_Summary::totals( (array) get_option( Wp360_Staging_Guard_Http_Guard::LOG_OPTION, array() ) ); $counts = Wp360_Staging_Guard_Cron_Guard::counts(); echo '
'; echo '

' . esc_html__( 'What is happening', '360-orbit-staging-guard' ) . '

'; echo ''; self::row( __( 'Outgoing calls', '360-orbit-staging-guard' ), sprintf( /* translators: 1: blocked calls, 2: allowed calls, 3: number of hosts */ esc_html__( '%1$d blocked, %2$d allowed, %3$d hosts', '360-orbit-staging-guard' ), $totals['blocked'], $totals['allowed'], $totals['hosts'] ) . ' ' . esc_html__( 'Log', '360-orbit-staging-guard' ) . '' ); self::row( __( 'Emails', '360-orbit-staging-guard' ), esc_html( self::mail_mode_label( $settings['mail_mode'] ) ) . ' · ' . sprintf( /* translators: %d: number of caught emails */ esc_html__( '%d caught', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Mail_Store::count() ) . ' ' . esc_html__( 'Mail catcher', '360-orbit-staging-guard' ) . '' ); self::row( __( 'Scheduled tasks', '360-orbit-staging-guard' ), $settings['pause_cron'] ? sprintf( /* translators: 1: due events, 2: scheduled events */ esc_html__( 'Paused: %1$d due, %2$d scheduled', '360-orbit-staging-guard' ), $counts['due'], $counts['scheduled'] ) : esc_html__( 'Running', '360-orbit-staging-guard' ) ); self::row( __( 'Search engines', '360-orbit-staging-guard' ), $settings['noindex'] ? esc_html__( 'Kept away (noindex, robots.txt)', '360-orbit-staging-guard' ) : esc_html__( 'Not touched', '360-orbit-staging-guard' ) ); self::row( __( 'Visitors', '360-orbit-staging-guard' ), $settings['lock_visitors'] ? esc_html__( 'Locked out (administrators, allowed IP addresses and the access link get in)', '360-orbit-staging-guard' ) : esc_html__( 'Not locked out', '360-orbit-staging-guard' ) ); echo '
'; $constants = array(); foreach ( array( 'WP_HTTP_BLOCK_EXTERNAL', 'WP_ACCESSIBLE_HOSTS', 'WP_ENVIRONMENT_TYPE', 'DISABLE_WP_CRON' ) as $name ) { if ( defined( $name ) ) { $value = constant( $name ); $constants[] = '' . esc_html( $name ) . ' = ' . esc_html( is_bool( $value ) ? ( $value ? 'true' : 'false' ) : (string) $value ); } } if ( $constants ) { echo '

' . esc_html__( 'Set in wp-config.php:', '360-orbit-staging-guard' ) . ' ' . implode( ', ', $constants ) . '

'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Namen und Werte oben einzeln escaped. } echo '
'; echo '
'; echo '

' . esc_html__( 'What this protects, and what it does not', '360-orbit-staging-guard' ) . '

'; echo '

' . esc_html__( 'Staging Guard is a safeguard against accidents, not an isolation. It stops what goes through the WordPress HTTP API and wp_mail().', '360-orbit-staging-guard' ) . '

'; echo '
'; } /** * Eine Tabellenzeile; $value ist bereits escaped. * * @param string $label Beschriftung. * @param string $value HTML des Werts. */ private static function row( $label, $value ) { echo '' . esc_html( $label ) . '' . $value . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Aufrufer escapen den Wert. } /** * Woher stammt der Umgebungstyp? * * @return string */ private static function environment_source() { if ( defined( 'WP_ENVIRONMENT_TYPE' ) && WP_ENVIRONMENT_TYPE ) { return __( 'from the constant WP_ENVIRONMENT_TYPE', '360-orbit-staging-guard' ); } if ( function_exists( 'getenv' ) && false !== getenv( 'WP_ENVIRONMENT_TYPE' ) ) { return __( 'from the environment variable WP_ENVIRONMENT_TYPE', '360-orbit-staging-guard' ); } return __( 'not set, WordPress assumes production', '360-orbit-staging-guard' ); } /** * @param string $mode Betriebsart. * @return string */ private static function mode_label( $mode ) { $labels = array( 'auto' => __( 'Automatic (protected unless the environment type is production)', '360-orbit-staging-guard' ), 'on' => __( 'Always on', '360-orbit-staging-guard' ), 'off' => __( 'Off', '360-orbit-staging-guard' ), ); return $labels[ $mode ] ?? $mode; } /** * @param string $mode Mail-Modus. * @return string */ private static function mail_mode_label( $mode ) { $labels = array( 'catch' => __( 'Catch in the mail catcher', '360-orbit-staging-guard' ), 'redirect' => __( 'Redirect to one address', '360-orbit-staging-guard' ), 'discard' => __( 'Discard', '360-orbit-staging-guard' ), 'allow' => __( 'Let through', '360-orbit-staging-guard' ), ); return $labels[ $mode ] ?? $mode; } /* ---------------------------------------------------------------- */ /* Reiter: Einstellungen */ /* ---------------------------------------------------------------- */ private static function render_settings_tab() { $s = Wp360_Staging_Guard_Settings::get(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nur lesend: Pruefung eines Hosts gegen die Regeln. $test_host = isset( $_GET['test_host'] ) ? sanitize_text_field( wp_unslash( $_GET['test_host'] ) ) : ''; ?>

$settings Einstellungen. */ private static function render_host_check( $input, array $settings ) { $decision = Wp360_Staging_Guard_Http_Policy::decide( 'https://' . ltrim( preg_replace( '#^[a-z]+://#i', '', $input ), '/' ), $settings, array( get_option( 'siteurl' ), get_option( 'home' ) ) ); $reasons = array( Wp360_Staging_Guard_Http_Policy::REASON_INVALID => __( 'Not a valid host name, WordPress decides.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_UNPARSABLE => __( 'Blocked: the address could not be read.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_OWN => __( 'This is your own site: always allowed.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_LIVE => __( 'This is the live site: always blocked from a copy.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_LISTED => __( 'Allowed: it is on the allow list.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_WPORG => __( 'Allowed: WordPress.org.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_ALWAYS => __( 'Allowed.', '360-orbit-staging-guard' ), Wp360_Staging_Guard_Http_Policy::REASON_BLOCKED => __( 'Blocked: it is not on the allow list.', '360-orbit-staging-guard' ), ); echo '

' . esc_html( $decision['host'] ?: $input ) . ': ' . esc_html( $reasons[ $decision['reason'] ] ?? '' ) . '

'; } /* ---------------------------------------------------------------- */ /* Reiter: Protokoll */ /* ---------------------------------------------------------------- */ private static function render_log_tab() { $rows = Wp360_Staging_Guard_Http_Guard::log_rows(); $settings = Wp360_Staging_Guard_Settings::get(); echo '
'; echo '

' . esc_html__( 'Outgoing calls seen on this copy, per host. Only host names and counters are stored, never paths, parameters or content.', '360-orbit-staging-guard' ) . '

'; if ( ! $rows ) { echo '

' . esc_html__( 'No outgoing calls recorded yet.', '360-orbit-staging-guard' ) . '

'; return; } echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $rows as $row ) { $decision = Wp360_Staging_Guard_Http_Policy::decide( 'https://' . $row['host'], $settings, array( get_option( 'siteurl' ), get_option( 'home' ) ) ); echo ''; echo ''; } echo '
' . esc_html__( 'Host', '360-orbit-staging-guard' ) . '' . esc_html__( 'Blocked', '360-orbit-staging-guard' ) . '' . esc_html__( 'Allowed', '360-orbit-staging-guard' ) . '' . esc_html__( 'Last seen', '360-orbit-staging-guard' ) . '
' . esc_html( $row['host'] ) . ''; if ( $row['live'] ) { echo ' ' . esc_html__( 'live site', '360-orbit-staging-guard' ) . ''; } echo '' . (int) $row['blocked'] . '' . (int) $row['allowed'] . '' . esc_html( wp_date( 'd.m.Y H:i:s', $row['last'] ) ) . ''; if ( ! $decision['allow'] && ! $row['live'] ) { echo '
'; echo ''; echo ''; wp_nonce_field( 'wp360_sg_allow_host' ); echo '
'; } echo '
'; echo '

'; echo ''; wp_nonce_field( 'wp360_sg_clear_log' ); echo '

'; echo ''; } private static function render_pro_tab() { $url = 'https://360wporbit.com/plugins/360-orbit-staging-guard'; ?>

403 ) ); } check_admin_referer( $nonce_action ); } /** * @param string $notice Meldungskennung. * @param string $tab Ziel-Reiter. */ private static function redirect_back( $notice, $tab ) { wp_safe_redirect( self::tab_url( $tab, array( 'wp360_sg_notice' => $notice ) ) ); exit; } private static function back() { $target = wp_get_referer(); wp_safe_redirect( $target ? $target : admin_url() ); exit; } /** * Schaltet den Schutz bewusst auf "Immer an". * * @return array Gespeicherte Einstellungen. */ public static function apply_enable() { $settings = Wp360_Staging_Guard_Settings::get(); $settings['mode'] = 'on'; return Wp360_Staging_Guard_Settings::save( $settings ); } public static function handle_enable() { self::authorize(); self::apply_enable(); self::back(); } /** * "Das ist die Live-Seite": merkt sich die aktuelle Adresse als * Live-Adresse. War der Schutz dabei aktiv (versehentlich eingeschaltet), * wird er auf "Aus" gestellt. * * @param bool $was_active Ob der Schutz im Moment der Aktion aktiv war. * @return array Gespeicherte Einstellungen. */ public static function apply_is_live( $was_active ) { $settings = Wp360_Staging_Guard_Settings::get(); $settings['live_url'] = Wp360_Staging_Guard_Settings::normalize_live_url( home_url() ); if ( $was_active ) { $settings['mode'] = 'off'; } return Wp360_Staging_Guard_Settings::save( $settings ); } public static function handle_is_live() { self::authorize(); self::apply_is_live( Wp360_Staging_Guard_Environment::state()['active'] ); self::back(); } /** * Uebernimmt die Eingaben des Einstellungsformulars. Nicht angehakte * Kontrollkaestchen fehlen in der Anfrage und bedeuten "aus". * * @param array $raw Rohdaten aus $_POST['wp360_sg']. * @return array Gespeicherte Einstellungen. */ public static function apply_save( array $raw ) { $values = Wp360_Staging_Guard_Settings::get(); foreach ( array( 'mode', 'mail_mode', 'mail_redirect_to', 'mail_keep_days', 'allowed_hosts', 'live_url', 'access_ips' ) as $key ) { if ( array_key_exists( $key, $raw ) ) { $values[ $key ] = $raw[ $key ]; } } foreach ( array( 'pause_cron', 'allow_wporg', 'noindex', 'lock_visitors' ) as $key ) { $values[ $key ] = ! empty( $raw[ $key ] ); } // Der Zugangslink entsteht beim ersten Einschalten der Sperre oder auf Wunsch neu. if ( ! empty( $raw['regenerate_token'] ) || ( $values['lock_visitors'] && ! Wp360_Staging_Guard_Access_Gate::is_valid_token( $values['access_token'] ) ) ) { $values['access_token'] = Wp360_Staging_Guard_Access_Gate::generate_token(); } return Wp360_Staging_Guard_Settings::save( $values ); } public static function handle_save() { self::authorize( 'wp360_sg_save' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce oben geprueft; jeder Wert laeuft durch Wp360_Staging_Guard_Settings::sanitize(). $raw = isset( $_POST['wp360_sg'] ) && is_array( $_POST['wp360_sg'] ) ? wp_unslash( $_POST['wp360_sg'] ) : array(); $saved = self::apply_save( $raw ); // Eine eingegebene, aber nicht lesbare Live-Adresse nicht still verwerfen. $entered = isset( $raw['live_url'] ) && is_string( $raw['live_url'] ) ? trim( $raw['live_url'] ) : ''; if ( '' !== $entered && '' === $saved['live_url'] ) { self::redirect_back( 'bad_live_url', 'settings' ); } self::redirect_back( 'saved', 'settings' ); } /** * Nimmt einen Host in die Erlaubnisliste auf. * * @param string $host Host oder URL. * @return bool False, wenn es kein gueltiger Host war. */ public static function apply_allow_host( $host ) { $pattern = Wp360_Staging_Guard_Settings::normalize_host_pattern( $host ); if ( '' === $pattern ) { return false; } $settings = Wp360_Staging_Guard_Settings::get(); $settings['allowed_hosts'] = trim( $settings['allowed_hosts'] . "\n" . $pattern ); Wp360_Staging_Guard_Settings::save( $settings ); return true; } public static function handle_allow_host() { self::authorize( 'wp360_sg_allow_host' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce oben geprueft. $host = isset( $_POST['host'] ) ? sanitize_text_field( wp_unslash( $_POST['host'] ) ) : ''; self::redirect_back( self::apply_allow_host( $host ) ? 'allowed' : 'bad_host', 'log' ); } public static function handle_clear_log() { self::authorize( 'wp360_sg_clear_log' ); delete_option( Wp360_Staging_Guard_Http_Guard::LOG_OPTION ); self::redirect_back( 'log_cleared', 'log' ); } }