plugin_name = $plugin_name; $this->version = $version; add_action('admin_menu', [$this,'menu']); add_action('admin_enqueue_scripts', [$this,'assets']); add_action('admin_head', [$this,'adjust_menu_icon_markup']); add_action('in_admin_header', [$this, 'capture_notices_before_header'], 1); // AJAX handled by dedicated \ABILITY\Ajax class (includes/class-ability-ajax.php) } /** * Prevent WP and third-party notices from being injected inside .ability-header. * Moves all .notice elements above .ability-header via JS on ABILITY pages. */ public function capture_notices_before_header() { $screen = get_current_screen(); if (!$screen || strpos($screen->id, 'ability-') === false) return; add_action('admin_footer', function() { ?> version . '.' . (file_exists(ABILITY_PATH . 'assets/css/admin.css') ? filemtime(ABILITY_PATH . 'assets/css/admin.css') : time()); wp_enqueue_style('ability-admin', ABILITY_URL.'assets/css/admin.css', [], $css_version); wp_enqueue_script('ability-admin', ABILITY_URL.'assets/js/admin.js', ['jquery'], $this->version, true); wp_localize_script('ability-admin', 'ABILITY_ADMIN', [ 'ajaxurl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('ability_admin'), 'tier' => function_exists('ability_get_tier') ? ability_get_tier() : 'basic', 'isPro' => function_exists('ability_is_pro') ? ability_is_pro() : false, 'adminUrl' => admin_url(), ]); } /** * Adjust top-level admin menu icon HTML to match requested markup. * Uses early CSS to prevent FOUC (flash of unstyled content) where the * default dashicon momentarily appears before being replaced by the SVG. */ public function adjust_menu_icon_markup() { ?>

0

0

0

0%
prefix . $table_name; $status = 'pending'; $total_issues = (int) $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM `{$table}` WHERE status = %s", $status )); } ?>

prefix . $table_name; $pages_scanned = (int) $wpdb->get_var("SELECT COUNT(DISTINCT file_path) FROM `{$table}`"); $errors_count = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM `{$table}` WHERE UPPER(severity) = %s", 'ERROR')); $warnings_count = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM `{$table}` WHERE UPPER(severity) = %s", 'WARNING')); // Heuristic review score only; this is not a WCAG conformance or legal-compliance score. $compliance_score = max(0, 100 - ($errors_count * 2) - ($warnings_count * 1)); // Get last scan date $last_scan = $wpdb->get_var("SELECT MAX(created_at) FROM `{$table}`"); if ($last_scan) { $last_scan_date = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($last_scan)); } } ?>

' . esc_html($last_scan_date) . ''); ?>

  • ' . esc_html($last_scan_date) . ''); ?>

0 && preg_match('/^[a-zA-Z0-9_]+$/', $table_name)): ?> prefix . $table_name; $status = 'pending'; $limit = 50; $issues = $wpdb->get_results( $wpdb->prepare("SELECT * FROM `{$table}` WHERE status = %s ORDER BY created_at DESC LIMIT %d", $status, $limit), ARRAY_A ); ?>