'Blue Professional Default', 'admin_bar' => '#1f2933', 'admin_bar_text' => '#ffffff', 'admin_bar_hover' => '#0274be', 'admin_bar_hover_text' => '#ffffff', 'menu_bg' => '#27313a', 'submenu_bg' => '#323f4b', 'menu_text' => '#d1d5db', 'menu_icon' => '#9ca3af', 'active_bg' => '#0274be', 'active_text' => '#ffffff', 'hover_bg' => '#025e9a', 'hover_text' => '#ffffff', 'hover_icon' => '#ffffff', 'button_bg' => '#0274be', 'button_bg_hover' => '#025e9a', 'button_text' => '#ffffff', 'focus_color' => '#0274be', ); } public static function get_options() { $saved = get_option(self::OPTION, array()); if (!is_array($saved)) { $saved = array(); } return wp_parse_args($saved, self::defaults()); } public static function get_saved_defaults() { $saved_defaults = get_option(self::DEFAULT_OPTION, array()); if (!is_array($saved_defaults)) { $saved_defaults = array(); } return wp_parse_args($saved_defaults, self::defaults()); } public function register_color_scheme() { $o = self::get_options(); $name = !empty($o['scheme_name']) ? $o['scheme_name'] : self::t('Eigene Farben', 'Custom Colors'); wp_admin_css_color( self::SLUG, $name, plugin_dir_url(__FILE__) . 'empty-admin-scheme.css', array($o['admin_bar'], $o['menu_bg'], $o['active_bg'], '#2271b1') ); } public function add_settings_page() { add_options_page( 'ACD Admin Designer', 'ACD Admin Designer', 'manage_options', 'acd-admin-designer', array($this, 'render_settings_page') ); } public function register_settings() { register_setting('acd_admin_color_designer_group', self::OPTION, array($this, 'sanitize_options')); } public function sanitize_options($input) { $nonce_valid = isset($_POST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'acd_admin_color_designer_group-options'); $restore_saved_default = $nonce_valid && isset($_POST['iaf_restore_saved_default']); $save_current_as_default = $nonce_valid && isset($_POST['iaf_save_current_as_default']); if ($restore_saved_default) { add_settings_error( self::OPTION, 'iaf_default_restored', self::t('Der gespeicherte Standard wurde wiederhergestellt.', 'The saved default has been restored.'), 'updated' ); return self::get_saved_defaults(); } $defaults = self::defaults(); $output = array(); $output['scheme_name'] = isset($input['scheme_name']) ? sanitize_text_field($input['scheme_name']) : $defaults['scheme_name']; foreach ($defaults as $key => $default) { if ($key === 'scheme_name') { continue; } $value = isset($input[$key]) ? sanitize_hex_color($input[$key]) : false; $output[$key] = $value ? $value : $default; } if ($save_current_as_default) { update_option(self::DEFAULT_OPTION, $output, false); add_settings_error( self::OPTION, 'iaf_default_saved', self::t('Die aktuellen Farben wurden als neuer Standard gespeichert.', 'The current colors have been saved as the new default.'), 'updated' ); } return $output; } private function sanitize_imported_options($input) { if (!is_array($input)) { return false; } $defaults = self::defaults(); $output = array(); $output['scheme_name'] = isset($input['scheme_name']) ? sanitize_text_field($input['scheme_name']) : $defaults['scheme_name']; foreach ($defaults as $key => $default) { if ($key === 'scheme_name') { continue; } $value = isset($input[$key]) ? sanitize_hex_color($input[$key]) : false; $output[$key] = $value ? $value : $default; } return $output; } public function export_scheme() { if (!current_user_can('manage_options')) { wp_die(esc_html(self::t('Keine Berechtigung.', 'Insufficient permissions.'))); } check_admin_referer('acd_export_scheme'); $export = array( 'plugin' => 'ACD Admin Designer', 'version' => '5.3.4', 'exported_at' => current_time('mysql'), 'current' => self::get_options(), 'default' => self::get_saved_defaults(), ); nocache_headers(); header('Content-Type: application/json; charset=utf-8'); header('Content-Disposition: attachment; filename="acd-admin-designer-scheme-' . gmdate('Y-m-d-H-i') . '.json"'); echo wp_json_encode($export, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; } private function redirect_with_import_message($message, $redirect) { set_transient( 'acd_admin_designer_import_message_' . get_current_user_id(), sanitize_key($message), 30 ); wp_safe_redirect($redirect); exit; } public function import_scheme() { if (!current_user_can('manage_options')) { wp_die(esc_html(self::t('Keine Berechtigung.', 'Insufficient permissions.'))); } check_admin_referer('acd_import_scheme'); $redirect = add_query_arg(array('page' => 'acd-admin-designer'), admin_url('options-general.php')); if (empty($_FILES['iaf_import_file']['tmp_name'])) { $this->redirect_with_import_message('import_missing', $redirect); } $tmp_name = isset($_FILES['iaf_import_file']['tmp_name']) ? sanitize_text_field(wp_unslash($_FILES['iaf_import_file']['tmp_name'])) : ''; if (!$tmp_name || !is_uploaded_file($tmp_name)) { $this->redirect_with_import_message('import_invalid', $redirect); } $raw = file_get_contents($tmp_name); $data = json_decode($raw, true); if (!is_array($data)) { $this->redirect_with_import_message('import_invalid', $redirect); } $current_source = isset($data['current']) && is_array($data['current']) ? $data['current'] : $data; $default_source = isset($data['default']) && is_array($data['default']) ? $data['default'] : $current_source; $current = $this->sanitize_imported_options($current_source); $default = $this->sanitize_imported_options($default_source); if (!$current || !$default) { $this->redirect_with_import_message('import_invalid', $redirect); } update_option(self::OPTION, $current, false); update_option(self::DEFAULT_OPTION, $default, false); $this->redirect_with_import_message('import_success', $redirect); } public function enqueue_admin_assets($hook) { wp_register_style('acd-admin-designer-dynamic', false, array(), '5.3.4'); wp_enqueue_style('acd-admin-designer-dynamic'); if ($this->is_custom_scheme_active()) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Inline CSS is generated only from sanitized hex colors and hardcoded selectors, then added via the WordPress enqueue API. wp_add_inline_style('acd-admin-designer-dynamic', $this->get_dynamic_admin_css()); wp_enqueue_script( 'acd-admin-designer-icons', plugin_dir_url(__FILE__) . 'assets/icon-mask.js', array(), '5.3.4', true ); } if ('settings_page_acd-admin-designer' === $hook) { wp_enqueue_style( 'acd-admin-designer-settings', plugin_dir_url(__FILE__) . 'assets/admin-page.css', array(), '5.3' ); wp_enqueue_script( 'acd-admin-designer-settings', plugin_dir_url(__FILE__) . 'assets/admin-page.js', array('jquery'), '5.3.4', true ); wp_localize_script( 'acd-admin-designer-settings', 'acdAdminDesigner', array( 'defaultColors' => array_intersect_key(self::get_saved_defaults(), self::defaults()), 'i18n' => array( 'defaultsRestored' => self::t('Standardfarben wiederhergestellt – bitte speichern.', 'Default colors restored – please save.'), 'unsavedChanges' => self::t('Ungespeicherte Änderungen', 'Unsaved changes'), ), ) ); } } private function get_dynamic_admin_css() { $o = self::get_options(); $defaults = self::defaults(); foreach ($o as $key => $value) { if ('scheme_name' === $key) { continue; } $sanitized = sanitize_hex_color($value); $o[$key] = $sanitized ? $sanitized : $defaults[$key]; } $css = <<<'CSS' :root { --iaf-admin-bar: {admin_bar}; --iaf-admin-bar-text: {admin_bar_text}; --iaf-admin-bar-hover: {admin_bar_hover}; --iaf-admin-bar-hover-text: {admin_bar_hover_text}; --iaf-menu-bg: {menu_bg}; --iaf-submenu-bg: {submenu_bg}; --iaf-menu-text: {menu_text}; --iaf-menu-icon: {menu_icon}; --iaf-active-bg: {active_bg}; --iaf-active-text: {active_text}; --iaf-hover-bg: {hover_bg}; --iaf-hover-text: {hover_text}; --iaf-hover-icon: {hover_icon}; --iaf-button-bg: {button_bg}; --iaf-button-bg-hover: {button_bg_hover}; --iaf-button-text: {button_text}; --iaf-focus: {focus_color}; } /* Adminbar */ #wpadminbar, #wpadminbar .menupop .ab-sub-wrapper, #wpadminbar .shortlink-input { background: var(--iaf-admin-bar) !important; } #wpadminbar .ab-item, #wpadminbar a.ab-item, #wpadminbar > #wp-toolbar span.ab-label, #wpadminbar > #wp-toolbar span.noticon, #wpadminbar .ab-icon:before, #wpadminbar .ab-item:before, #wpadminbar #adminbarsearch:before { color: var(--iaf-admin-bar-text) !important; } #wpadminbar .ab-top-menu > li.hover > .ab-item, #wpadminbar.nojq .quicklinks .ab-top-menu > li > .ab-item:focus, #wpadminbar:not(.mobile) .ab-top-menu > li:hover > .ab-item, #wpadminbar:not(.mobile) .ab-top-menu > li > .ab-item:focus { background: var(--iaf-admin-bar-hover) !important; color: var(--iaf-admin-bar-hover-text) !important; } #wpadminbar .quicklinks .menupop ul li a:hover, #wpadminbar .quicklinks .menupop ul li a:focus, #wpadminbar .quicklinks .menupop ul li a:hover strong, #wpadminbar .quicklinks .menupop ul li a:focus strong, #wpadminbar .quicklinks .menupop.hover ul li a:hover, #wpadminbar .quicklinks .menupop.hover ul li a:focus { background: var(--iaf-admin-bar-hover) !important; color: var(--iaf-admin-bar-hover-text) !important; } #wpadminbar .quicklinks .menupop ul li a:hover .ab-icon:before, #wpadminbar .quicklinks .menupop ul li a:focus .ab-icon:before, #wpadminbar .quicklinks .menupop ul li a:hover:before, #wpadminbar .quicklinks .menupop ul li a:focus:before { color: var(--iaf-admin-bar-text) !important; } /* WooCommerce Site-Visibility-Badge (Live / Kommt bald) nicht durch globale Adminbar-Farben überschreiben */ #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge { padding: 7px 0 !important; } #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge a.ab-item, #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge a.ab-item:before, #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge a.ab-item .ab-label { color: #3c434a !important; } #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge a.ab-item { background-color: #f6f7f7 !important; border-radius: 2px !important; display: flex !important; height: 18px !important; min-height: 18px !important; line-height: 16px !important; padding: 0 6px !important; align-items: center !important; gap: 8px !important; font-size: 12px !important; font-weight: 500 !important; margin: 0 !important; } #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge a.ab-item:hover, #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge a.ab-item:focus { background-color: #dcdcde !important; color: #3c434a !important; } #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge.woocommerce-site-status-badge-live a.ab-item, #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge.woocommerce-site-status-badge-live a.ab-item .ab-label { background-color: #e6f2e8 !important; color: #00450c !important; } #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge.woocommerce-site-status-badge-live a.ab-item:hover, #wpadminbar .quicklinks #wp-admin-bar-woocommerce-site-visibility-badge.woocommerce-site-status-badge-live a.ab-item:focus { background-color: #b8e6bf !important; color: #00450c !important; } /* Menu base */ #adminmenuback, #adminmenuwrap, #adminmenu { background: var(--iaf-menu-bg) !important; } #adminmenu a, #adminmenu .wp-submenu a { color: var(--iaf-menu-text) !important; } #adminmenu .wp-submenu, #adminmenu .wp-has-current-submenu .wp-submenu { background: var(--iaf-submenu-bg) !important; } /* Admin-Menü-Icons: Dashicons, Inline-SVG, SVG-Backgrounds und SVG-IMGs einfarbig steuern */ #adminmenu div.wp-menu-image, #adminmenu div.wp-menu-image:before, #adminmenu div.wp-menu-image svg, #adminmenu div.wp-menu-image svg *, #adminmenu div.wp-menu-image.iaf-masked-icon:before { color: var(--iaf-menu-icon) !important; fill: currentColor !important; stroke: currentColor !important; } #adminmenu div.wp-menu-image img { opacity: 1 !important; filter: grayscale(1) brightness(0) opacity(.82) !important; } #adminmenu div.wp-menu-image.iaf-masked-icon { background-image: none !important; background-position: center center !important; background-repeat: no-repeat !important; } #adminmenu div.wp-menu-image.iaf-masked-icon:before { content: "" !important; display: block !important; width: 20px !important; height: 20px !important; margin: 7px auto 0 !important; background-color: currentColor !important; -webkit-mask-image: var(--iaf-icon-mask) !important; mask-image: var(--iaf-icon-mask) !important; -webkit-mask-repeat: no-repeat !important; mask-repeat: no-repeat !important; -webkit-mask-position: center center !important; mask-position: center center !important; -webkit-mask-size: contain !important; mask-size: contain !important; } #adminmenu div.wp-menu-image.iaf-masked-icon img { display: none !important; } /* Active */ #adminmenu li.current a.menu-top, #adminmenu li.wp-has-current-submenu > a.wp-has-current-submenu, #adminmenu li.wp-has-current-submenu .wp-menu-arrow, #adminmenu li.current .wp-menu-arrow { background: var(--iaf-active-bg) !important; color: var(--iaf-active-text) !important; } #adminmenu li.current div.wp-menu-image, #adminmenu li.current div.wp-menu-image:before, #adminmenu li.current div.wp-menu-image svg, #adminmenu li.current div.wp-menu-image svg *, #adminmenu li.wp-has-current-submenu div.wp-menu-image, #adminmenu li.wp-has-current-submenu div.wp-menu-image:before, #adminmenu li.wp-has-current-submenu div.wp-menu-image svg, #adminmenu li.wp-has-current-submenu div.wp-menu-image svg *, #adminmenu li.wp-has-current-submenu > a.wp-has-current-submenu .wp-menu-name, #adminmenu li.current > a .wp-menu-name { color: var(--iaf-active-text) !important; fill: currentColor !important; stroke: currentColor !important; } #adminmenu li.current div.wp-menu-image img, #adminmenu li.wp-has-current-submenu div.wp-menu-image img { filter: grayscale(1) brightness(0) invert(1) opacity(1) !important; } /* Hover / open submenu - avoids remaining WordPress blue states */ #adminmenu li.menu-top:hover, #adminmenu li.opensub > a.menu-top, #adminmenu li > a.menu-top:focus, #adminmenu li.wp-has-submenu:hover > a.menu-top, #adminmenu li.wp-has-submenu.opensub > a.menu-top, #adminmenu li.wp-not-current-submenu:hover > a, #adminmenu li.wp-not-current-submenu.opensub > a, #adminmenu li:hover > a, #adminmenu li > a:focus, #adminmenu .wp-submenu a:hover, #adminmenu .wp-submenu a:focus { background: var(--iaf-hover-bg) !important; color: var(--iaf-hover-text) !important; } #adminmenu li:hover div.wp-menu-image, #adminmenu li:hover div.wp-menu-image:before, #adminmenu li:hover div.wp-menu-image svg, #adminmenu li:hover div.wp-menu-image svg *, #adminmenu li.opensub div.wp-menu-image, #adminmenu li.opensub div.wp-menu-image:before, #adminmenu li.opensub div.wp-menu-image svg, #adminmenu li.opensub div.wp-menu-image svg *, #adminmenu li.wp-has-submenu:hover div.wp-menu-image, #adminmenu li.wp-has-submenu:hover div.wp-menu-image:before, #adminmenu li.wp-has-submenu:hover div.wp-menu-image svg, #adminmenu li.wp-has-submenu:hover div.wp-menu-image svg *, #adminmenu li.wp-has-submenu.opensub div.wp-menu-image, #adminmenu li.wp-has-submenu.opensub div.wp-menu-image:before, #adminmenu li.wp-has-submenu.opensub div.wp-menu-image svg, #adminmenu li.wp-has-submenu.opensub div.wp-menu-image svg * { color: var(--iaf-hover-icon) !important; fill: currentColor !important; stroke: currentColor !important; } #adminmenu li:hover div.wp-menu-image img, #adminmenu li.opensub div.wp-menu-image img, #adminmenu li.wp-has-submenu:hover div.wp-menu-image img, #adminmenu li.wp-has-submenu.opensub div.wp-menu-image img { filter: grayscale(1) brightness(0) invert(1) opacity(1) !important; } #adminmenu a:focus { box-shadow:none !important; outline:none !important; } /* Content links: plugin list, tables, settings pages, normal admin views */ .wrap a, .wp-list-table a, .subsubsub a, .tablenav a, .plugins a, .plugin-card a, .theme-browser a, .media-frame a, .row-actions a, .notice a, .form-table a, .about-wrap a { color:#2271b1; } .wrap a:hover, .wrap a:focus, .wp-list-table a:hover, .wp-list-table a:focus, .subsubsub a:hover, .subsubsub a:focus, .tablenav a:hover, .tablenav a:focus, .plugins a:hover, .plugins a:focus, .plugin-card a:hover, .plugin-card a:focus, .theme-browser a:hover, .theme-browser a:focus, .media-frame a:hover, .media-frame a:focus, .row-actions a:hover, .row-actions a:focus, .notice a:hover, .notice a:focus, .form-table a:hover, .form-table a:focus, .about-wrap a:hover, .about-wrap a:focus { color:#135e96; } /* Avoid recoloring destructive actions too strongly */ .row-actions .delete a, .row-actions .trash a, .submitdelete { color:#b32d2e !important; } /* Buttons / focus */ .wp-core-ui .button-primary, .wp-core-ui .button-primary.focus, .wp-core-ui .button-primary:focus { background: var(--iaf-button-bg) !important; border-color: var(--iaf-button-bg) !important; color: var(--iaf-button-text) !important; } .wp-core-ui .button-primary:hover, .wp-core-ui .button-primary:active { background: var(--iaf-button-bg-hover) !important; border-color: var(--iaf-button-bg-hover) !important; color: var(--iaf-button-text) !important; } input[type=checkbox]:checked::before { filter: hue-rotate(120deg); } input[type=radio]:checked::before { background-color: var(--iaf-focus) !important; } input[type=text]:focus, input[type=password]:focus, input[type=color]:focus, input[type=date]:focus, input[type=datetime]:focus, input[type=datetime-local]:focus, input[type=email]:focus, input[type=month]:focus, input[type=number]:focus, input[type=search]:focus, input[type=tel]:focus, input[type=time]:focus, input[type=url]:focus, input[type=week]:focus, input[type=checkbox]:focus, input[type=radio]:focus, select:focus, textarea:focus { border-color: var(--iaf-focus) !important; box-shadow: 0 0 0 1px var(--iaf-focus) !important; } /* Admin bar hover text and icons */ #wpadminbar .ab-top-menu > li.hover > .ab-item .ab-icon:before, #wpadminbar .ab-top-menu > li.hover > .ab-item .ab-label, #wpadminbar.nojq .quicklinks .ab-top-menu > li > .ab-item:focus .ab-icon:before, #wpadminbar.nojq .quicklinks .ab-top-menu > li > .ab-item:focus .ab-label, #wpadminbar:not(.mobile) .ab-top-menu > li:hover > .ab-item .ab-icon:before, #wpadminbar:not(.mobile) .ab-top-menu > li:hover > .ab-item .ab-label, #wpadminbar:not(.mobile) .ab-top-menu > li > .ab-item:focus .ab-icon:before, #wpadminbar:not(.mobile) .ab-top-menu > li > .ab-item:focus .ab-label, #wpadminbar .quicklinks .menupop ul li a:hover .ab-label, #wpadminbar .quicklinks .menupop ul li a:focus .ab-label { color: var(--iaf-admin-bar-hover-text) !important; } /* Keep left menu icons centered */ #adminmenu div.wp-menu-image { display:flex !important; align-items:center !important; justify-content:center !important; } #adminmenu div.wp-menu-image:before, #adminmenu div.wp-menu-image svg { line-height:1 !important; vertical-align:middle !important; } #adminmenu div.wp-menu-image.iaf-masked-icon:before { margin:0 auto !important; } #wpadminbar .ab-top-menu > li.hover > .ab-item, #wpadminbar.nojq .quicklinks .ab-top-menu > li > .ab-item:focus, #wpadminbar:not(.mobile) .ab-top-menu > li:hover > .ab-item, #wpadminbar:not(.mobile) .ab-top-menu > li > .ab-item:focus, #wpadminbar .quicklinks .menupop ul li a:hover, #wpadminbar .quicklinks .menupop ul li a:focus, #wpadminbar .quicklinks .menupop ul li a:hover strong, #wpadminbar .quicklinks .menupop ul li a:focus strong, #wpadminbar .quicklinks .menupop.hover ul li a:hover, #wpadminbar .quicklinks .menupop.hover ul li a:focus { background: var(--iaf-admin-bar-hover) !important; color: var(--iaf-admin-bar-hover-text) !important; } #wpadminbar .quicklinks .menupop ul li a:hover .ab-icon:before, #wpadminbar .quicklinks .menupop ul li a:focus .ab-icon:before, #wpadminbar .quicklinks .menupop ul li a:hover:before, #wpadminbar .quicklinks .menupop ul li a:focus:before { color: var(--iaf-admin-bar-hover-text) !important; } CSS; $replacements = array(); foreach ($defaults as $key => $default) { if ('scheme_name' === $key) { continue; } $replacements['{' . $key . '}'] = isset($o[$key]) ? $o[$key] : $default; } return strtr($css, $replacements); } private function field($key, $label, $desc = '') { $o = self::get_options(); $value = isset($o[$key]) ? sanitize_hex_color($o[$key]) : '#000000'; if (!$value) { $value = '#000000'; } echo '
'; echo ''; echo '
'; echo ''; echo ''; echo '
'; if ($desc !== '') { echo '

' . esc_html($desc) . '

'; } echo '
'; } public function render_settings_page() { if (!current_user_can('manage_options')) { return; } $o = self::get_options(); $message = get_transient('acd_admin_designer_import_message_' . get_current_user_id()); if (false !== $message) { delete_transient('acd_admin_designer_import_message_' . get_current_user_id()); $message = sanitize_key($message); } else { $message = ''; } ?>

5.3.4

field('admin_bar', self::t('Hintergrund', 'Background')); ?> field('admin_bar_text', self::t('Text & Icons', 'Text & icons')); ?> field('admin_bar_hover', self::t('Hover-Hintergrund', 'Hover background')); ?> field('admin_bar_hover_text', self::t('Hover-Schriftfarbe', 'Hover text color')); ?>

field('menu_bg', self::t('Hauptmenü Hintergrund', 'Main menu background')); ?> field('submenu_bg', self::t('Untermenü Hintergrund', 'Submenu background')); ?> field('menu_text', self::t('Normale Schriftfarbe', 'Default text color')); ?> field('menu_icon', self::t('Normale Icon-Farbe', 'Default icon color')); ?>

field('active_bg', self::t('Aktiver Menüpunkt', 'Active menu item')); ?> field('active_text', self::t('Text aktiv', 'Active text')); ?> field('hover_bg', self::t('Hover-Hintergrund', 'Hover background')); ?> field('hover_text', self::t('Hover-Schriftfarbe', 'Hover text color')); ?> field('hover_icon', self::t('Hover-Iconfarbe', 'Hover icon color')); ?>

#2271b1 und Hover #135e96.', 'Backend links intentionally keep the WordPress default colors: #2271b1 and hover #135e96.')); ?>

field('button_bg', self::t('Button Primär', 'Primary button')); ?> field('button_bg_hover', self::t('Button Hover', 'Button hover')); ?> field('button_text', self::t('Button Text', 'Button text')); ?> field('focus_color', self::t('Fokus / Markierung', 'Focus / highlight')); ?>