'.esc_html__('Settings', 'admin-maintance-msg').''; } return $links; }); } /* ==================== Defaults: Single Source of Truth ==================== */ private static function defaults(): array { return [ // Admin Notice (bestehend) 'enabled' => 0, 'from' => '', 'to' => '', 'message' => '', // NEU: Rollensteuerung für Notice 'roles' => [], // Frontend Wartungsmodus // fe_mode: 'page' | 'custom' | 'template' 'fe_enabled' => 0, 'fe_bypass_logged' => 1, 'fe_mode' => 'page', 'fe_page_id' => 0, 'fe_html' => '', 'fe_template' => '', // z. B. 'default.html' ]; } /* ==================== Lifecycle ==================== */ public function on_activate(): void { if (!get_option(self::OPTION)) { $defaults = self::defaults(); $old = get_option(self::OPTION_OLD); if (is_array($old)) { add_option(self::OPTION, wp_parse_args($old, $defaults)); delete_option(self::OPTION_OLD); } else { add_option(self::OPTION, $defaults); } } } /* ==================== Helpers (Options, Dates, Weekday, Window) ==================== */ private function get_opts(): array { $opts = get_option(self::OPTION, []); return wp_parse_args($opts, self::defaults()); } private function parse_local_dt($dt): ?DateTime { if (!$dt) return null; $tz = function_exists('wp_timezone') ? wp_timezone() : new DateTimeZone('UTC'); $norm = str_replace(' ', 'T', $dt); $d = DateTime::createFromFormat('Y-m-d\TH:i', $norm, $tz); if ($d instanceof DateTime) return $d; try { return new DateTime($dt, $tz); } catch (Exception $e) { return null; } } private function weekday_de_short(DateTimeInterface $dt): string { $map = ['So','Mo','Di','Mi','Do','Fr','Sa']; return $map[(int)$dt->format('w')]; } private function weekday_de_long(DateTimeInterface $dt): string { $map = ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag']; return $map[(int)$dt->format('w')]; } private function format_window_text(?DateTime $from, ?DateTime $to): string { if (!$from) return ''; $tzabbr = $from->format('T'); if ($to && $from->format('Y-m-d') !== $to->format('Y-m-d')) { return sprintf( '%s, %s, %s – %s, %s, %s (%s)', $this->weekday_de_short($from), $from->format('d.m.Y'), $from->format('H:i'), $this->weekday_de_short($to), $to->format('d.m.Y'), $to->format('H:i'), $tzabbr ); } return sprintf( '%s, %s, %s–%s (%s)', $this->weekday_de_long($from), $from->format('d.m.Y'), $from->format('H:i'), $to ? $to->format('H:i') : $from->format('H:i'), $tzabbr ); } /* ==================== Admin Assets ==================== */ public function enqueue_admin_assets(): void { $css_url = plugin_dir_url(__FILE__) . 'assets/admin.css'; wp_register_style(self::HANDLE_CSS, $css_url, [], self::VERSION, 'all'); wp_enqueue_style(self::HANDLE_CSS); } /* ==================== Settings Page ==================== */ public function add_settings_page(): void { add_options_page( __('Wartungshinweis', 'admin-maintance-msg'), __('Wartungshinweis', 'admin-maintance-msg'), 'manage_options', self::PAGE_SLUG, [$this, 'render_settings_page'] ); } public function register_settings(): void { register_setting(self::OPTION, self::OPTION, [ 'type' => 'array', 'sanitize_callback' => [$this, 'sanitize_opts'], 'default' => self::defaults(), ]); add_settings_section('ammsg_section_main', '', '__return_null', self::OPTION); // Toggle Notice add_settings_field('enabled', __('Wartung aktiv (Admin-Notice)', 'admin-maintance-msg'), function() { $o = $this->get_opts(); ?> get_opts(); ?>
get_opts(); ?> get_opts(); ?> get_opts(); global $wp_roles; $roles = is_object($wp_roles) ? $wp_roles->roles : []; ?> get_opts(); ?> get_opts(); ?> get_opts(); $mode = $o['fe_mode'] ?: 'page'; ?>' . esc_html__('Wird genutzt, wenn „WordPress-Seite“ gewählt ist.', 'admin-maintance-msg') . '
'; }, self::OPTION, 'ammsg_section_main' ); // Frontend: Template add_settings_field('fe_template', __('Template-Datei (assets)', 'admin-maintance-msg'), function () { $o = $this->get_opts(); $templates = $this->available_templates(); ?> get_opts(); ?> get_opts(); // Notice $out['enabled'] = !empty($input['enabled']) ? 1 : 0; $out['from'] = isset($input['from']) ? sanitize_text_field($input['from']) : ''; $out['to'] = isset($input['to']) ? sanitize_text_field($input['to']) : ''; $out['message'] = isset($input['message']) ? wp_kses_post($input['message']) : ''; foreach (['from','to'] as $k) { if ($out[$k] && !$this->parse_local_dt($out[$k])) { $out[$k] = ''; } } // Rollen $out['roles'] = isset($input['roles']) && is_array($input['roles']) ? array_values(array_map('sanitize_text_field', $input['roles'])) : []; // Frontend-Maintenance $out['fe_enabled'] = !empty($input['fe_enabled']) ? 1 : 0; $out['fe_bypass_logged'] = !empty($input['fe_bypass_logged']) ? 1 : 0; $mode = isset($input['fe_mode']) ? sanitize_text_field($input['fe_mode']) : 'page'; $out['fe_mode'] = in_array($mode, ['page','custom','template'], true) ? $mode : 'page'; $out['fe_page_id'] = isset($input['fe_page_id']) ? (int)$input['fe_page_id'] : 0; // Custom HTML – erlaubte Tags (erweiterbar) $allowed = [ 'a' => ['href'=>[], 'title'=>[], 'target'=>[], 'rel'=>[]], 'p' => [], 'div'=>['class'=>[], 'id'=>[]], 'span'=>['class'=>[], 'id'=>[]], 'h1'=>[], 'h2'=>[], 'h3'=>[], 'h4'=>[], 'h5'=>[], 'h6'=>[], 'ul'=>[], 'ol'=>[], 'li'=>[], 'strong'=>[], 'em'=>[], 'br'=>[], 'hr'=>[], 'img'=>['src'=>[], 'alt'=>[], 'width'=>[], 'height'=>[], 'loading'=>[]], ]; $out['fe_html'] = isset($input['fe_html']) ? wp_kses($input['fe_html'], $allowed) : ''; // Template-Datei $templates = array_keys($this->available_templates()); $tpl = isset($input['fe_template']) ? sanitize_text_field($input['fe_template']) : ''; $out['fe_template'] = in_array($tpl, $templates, true) ? $tpl : ''; return $out; } private function available_templates(): array { $dir = plugin_dir_path(__FILE__) . 'assets/maintenance/templates/'; if (!is_dir($dir)) return []; $files = glob($dir . '*.html'); $out = []; foreach ($files as $f) { $base = basename($f); $out[$base] = $base; } return $out; } public function render_settings_page(): void { if (!current_user_can('manage_options')) return; // Erfolgs-Notice sauber vor Hero ausgeben // Pfade zu (optionalen) Assets $hero_url = plugins_url('assets/hero.png', __FILE__); $promo_url = plugins_url('assets/codekeks.png', __FILE__); ?>
codekeks.de · Andreas Grzybowski', 'admin-maintance-msg'), esc_html( gmdate('Y') ), esc_url('https://codekeks.de') ); ?>
get_opts(); // Rollenfilter if (!empty($o['roles'])) { $user = wp_get_current_user(); $allow = false; foreach ((array)$o['roles'] as $r) { if (in_array($r, (array)$user->roles, true)) { $allow = true; break; } } if (!$allow) return; } $enabled = !empty($o['enabled']); $from = $this->parse_local_dt($o['from']); $to = $this->parse_local_dt($o['to']); $within = false; if ($from && $to) { $now = new DateTime('now', $from->getTimezone()); $within = ($now >= $from && $now <= $to); } if (!$enabled && !$within) return; $window_text = $this->format_window_text($from, $to); $repl = []; if ($from) { $repl['{WEEKDAY}'] = $this->weekday_de_long($from); $repl['{DATE}'] = $from->format('d.m.Y'); $repl['{FROM}'] = $from->format('H:i'); $repl['{DATETIME_FROM}'] = $from->format('d.m.Y H:i'); $repl['{TZ}'] = $from->format('T'); } if ($to) { $repl['{WEEKDAY_TO}'] = $this->weekday_de_long($to); $repl['{DATE_TO}'] = $to->format('d.m.Y'); $repl['{TO}'] = $to->format('H:i'); $repl['{DATETIME_TO}'] = $to->format('d.m.Y H:i'); } $raw = isset($o['message']) ? trim($o['message']) : ''; if ($raw === '' && $from && $to) { $message = sprintf( /* translators: 1: date (dd.mm.yyyy), 2: start time (HH:MM), 3: end time (HH:MM) */ __('Wir führen am %1$s zwischen %2$s und %3$s planmäßige Wartungsarbeiten durch. Innerhalb dieses Zeitraums steht die Website nicht zur Verfügung.', 'admin-maintance-msg'), $from->format('d.m.Y'), $from->format('H:i'), $to->format('H:i') ); if ($window_text) { $message .= ' – ' . $window_text; } } else { $message = $raw !== '' ? $raw : __('Geplante Wartungsarbeiten.', 'admin-maintance-msg'); if ($repl) { $message = strtr($message, $repl); } if ($window_text && !preg_match('/\{(WEEKDAY|DATE|FROM|TO|TZ|DATETIME_FROM|DATETIME_TO|WEEKDAY_TO|DATE_TO)\}/', $raw)) { $message .= ' – ' . $window_text; } } ?>'.esc_html($msg).'
'; if ($win) echo ''.esc_html($win).'
'; echo ''; return; } $html = file_get_contents($real); if ($html === false) { $charset = esc_attr(get_bloginfo('charset')); echo '