array( 'label' => __( 'Scanner', 'acceguru' ), 'group' => 'acceguru_settings_scanner', 'kind' => 'form' ), 'fixers' => array( 'label' => __( 'Fixers', 'acceguru' ), 'group' => 'acceguru_settings_fixers', 'kind' => 'form' ), 'ai' => array( 'label' => __( 'AI Alt Text', 'acceguru' ), 'group' => 'acceguru_settings_ai', 'kind' => 'form' ), 'statement' => array( 'label' => __( 'Statement', 'acceguru' ), 'kind' => 'view', 'view' => 'statement-page.php' ), 'advanced' => array( 'label' => __( 'Rules', 'acceguru' ), 'group' => 'acceguru_settings_advanced', 'kind' => 'form' ), ); /** * Filters the Settings page tab list. * * Each tab descriptor must have at least: label, kind ('form' | 'view' | 'callback'). * For 'form' add 'group' (option-group registered via register_setting). * For 'view' add 'view' (filename in admin/views/). * For 'callback' add 'render' (callable that prints the tab body). * * @param array $tabs Existing tab descriptors keyed by slug. */ $filtered_tabs = apply_filters( 'acceguru_settings_tabs', $default_tabs ); $tabs = array(); if ( is_array( $filtered_tabs ) ) { foreach ( $filtered_tabs as $slug => $tab ) { if ( ! is_string( $slug ) || '' === $slug || sanitize_key( $slug ) !== $slug || ! is_array( $tab ) || ! isset( $tab['label'], $tab['kind'] ) || ! is_string( $tab['label'] ) || '' === trim( $tab['label'] ) || ! is_string( $tab['kind'] ) ) { continue; } $kind = $tab['kind']; if ( 'form' === $kind ) { // The page has dedicated markup for its four built-in form tabs. if ( ! isset( $default_tabs[ $slug ] ) || 'form' !== $default_tabs[ $slug ]['kind'] || ! isset( $tab['group'] ) || ! is_string( $tab['group'] ) || '' === trim( $tab['group'] ) ) { continue; } } elseif ( 'view' === $kind ) { if ( ! isset( $tab['view'] ) || ! is_string( $tab['view'] ) || '' === $tab['view'] || basename( $tab['view'] ) !== $tab['view'] || ! str_ends_with( $tab['view'], '.php' ) || ! is_file( ACCEGURU_PATH . 'admin/views/' . $tab['view'] ) ) { continue; } } elseif ( 'callback' === $kind ) { if ( ! isset( $tab['render'] ) || ! is_callable( $tab['render'] ) ) { continue; } } else { continue; } $tabs[ $slug ] = $tab; } } // A broken extension must not leave the Settings page empty. if ( array() === $tabs ) { $tabs = $default_tabs; } $active = isset( $_GET['tab'] ) ? sanitize_key( (string) $_GET['tab'] ) : 'scanner'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only tab selector for display, sanitised and validated against the known tab list below; no state change. if ( ! isset( $tabs[ $active ] ) ) { $active = isset( $tabs['scanner'] ) ? 'scanner' : (string) array_key_first( $tabs ); } $current = $tabs[ $active ]; /** * Reads scalar settings without converting damaged arrays or objects. * Stored values are not changed; the normal default is used for this view. */ $option_scalar = static function ( string $name, mixed $default ): mixed { $value = get_option( $name, $default ); return is_scalar( $value ) ? $value : $default; }; /** * Render a label cell for a form-row. * * @param string $title Field title. * @param string $tip Optional help-tip text. Renders as a help-dot tooltip. * @param string $hint Optional inline hint shown under the title. * @param string $badge Optional pre-escaped HTML appended after the title. */ $render_label = static function ( string $title, string $tip = '', string $hint = '', string $badge = '' ): void { echo '
'; echo esc_html( $title ); if ( '' !== $badge ) { echo wp_kses( ' ' . $badge, acceguru_admin_allowed_html() ); } echo ''; if ( '' !== $hint ) { echo '' . wp_kses( $hint, array( 'strong' => array(), 'em' => array() ) ) . ''; } echo '
'; if ( '' !== $tip ) { echo wp_kses( ' ' . Acceguru_Admin::help_tip( $tip ), acceguru_admin_allowed_html() ); } echo '
'; }; /** * Render a toggle (checkbox styled as iOS-style switch). */ $render_toggle = static function ( string $option, int $default = 0 ) use ( $option_scalar ): void { $checked = (int) $option_scalar( $option, $default ); printf( '', esc_attr( $option ), checked( 1, $checked, false ) ); }; /** * Render a select. * * @param array $choices value => label. */ $render_select = static function ( string $option, array $choices, string $default = '' ) use ( $option_scalar ): void { $current = (string) $option_scalar( $option, '' === $default ? array_key_first( $choices ) : $default ); printf( ''; }; ?>

v

'A', 'AA' => 'AA', 'AAA' => 'AAA' ), 'AA' ); ?>
name; $label = (string) $type->label; $checked = in_array( $slug, $selected, true ); // How many items of this type the site holds. A scan can // still walk fewer of them - a page without a permalink or // one an add-on filters out never enters the queue. $counts = wp_count_posts( $slug ); $total = 0; foreach ( array( 'publish', 'draft', 'pending', 'private', 'future' ) as $status ) { $total += isset( $counts->$status ) ? (int) $counts->$status : 0; } ?>
__( 'Right (default)', 'acceguru' ), 'left' => __( 'Left', 'acceguru' ) ), 'right' ); ?>
__( 'Bottom right (default)', 'acceguru' ), 'bottom-left' => __( 'Bottom left', 'acceguru' ), 'top-right' => __( 'Top right', 'acceguru' ), 'top-left' => __( 'Top left', 'acceguru' ), 'off' => __( 'Off (hide button)', 'acceguru' ), ), 'bottom-right' ); ?>
__( 'Page structure', 'acceguru' ), 'first' => true, 'fields' => array( 'acceguru_fix_skip_links' => array( __( 'Enable skip links', 'acceguru' ), __( 'Adds a "Skip to main content" link as the first focusable element on every page. Helps keyboard users bypass the navigation. WCAG 2.4.1.', 'acceguru' ) ), 'acceguru_fix_focus_outlines' => array( __( 'Enable focus outlines', 'acceguru' ), __( 'Adds a visible focus indicator to every interactive element. Required so keyboard users can see what they have selected. WCAG 2.4.7.', 'acceguru' ) ), 'acceguru_fix_html_lang' => array( __( 'Add lang and dir to ', 'acceguru' ), __( 'Adds from the site language and text direction, so screen readers pronounce correctly and right-to-left languages render the right way. WCAG 3.1.1.', 'acceguru' ) ), ), ), array( 'title' => __( 'Forms & search', 'acceguru' ), 'fields' => array( 'acceguru_fix_search_form_label' => array( __( 'Add an accessible name to the search field', 'acceguru' ), __( 'Adds an aria-label to the WP search field when it has no accessible name of its own, so screen readers can announce it. Skipped when the field already has a name.', 'acceguru' ) ), 'acceguru_fix_label_comment_form' => array( __( 'Add labels to the comment form', 'acceguru' ), __( 'Adds an accessible name to the comment fields (Name, Email, Website, Comment) when the theme leaves them unlabelled. WCAG 1.3.1 / 4.1.2.', 'acceguru' ) ), 'acceguru_fix_empty_search_results' => array( __( 'Show search results page on empty search', 'acceguru' ), __( 'Forces WordPress to render the search results template when the query is empty.', 'acceguru' ) ), ), ), array( 'title' => __( 'Links & buttons', 'acceguru' ), 'fields' => array( 'acceguru_fix_label_new_window' => array( __( 'Label links opening a new window', 'acceguru' ), __( 'Adds an "(opens in new tab)" screen-reader label and a small icon to every . WCAG 3.2.5.', 'acceguru' ) ), 'acceguru_fix_label_document_links' => array( __( 'Flag links to documents (PDF, Word...)', 'acceguru' ), __( 'Appends a short "(PDF)", "(Word)", "(Excel)" marker - plus the file size for files on this site - to links pointing at non-HTML files. Skips links that already say so. WCAG 3.2.4 best practice.', 'acceguru' ) ), 'acceguru_fix_force_link_underline' => array( __( 'Underline non-navigation links', 'acceguru' ), __( 'Underlines content links (skipping menus and button-styled links) so colour-blind users can tell links from text. WCAG 1.4.1.', 'acceguru' ) ), 'acceguru_fix_autoplay_video_controls' => array( __( 'Add controls to autoplay videos', 'acceguru' ), __( 'Forces controls onto every