settings_capability = $settings_capability; } /** * Register hooks. * * @return void */ public function add_page() { add_filter( 'edac_filter_settings_tab_items', [ $this, 'add_reports_tab' ] ); add_action( 'edac_settings_tab_content', [ $this, 'maybe_render_tab_content' ] ); } /** * Add the Accessibility Reports tab. * * @param array $tabs Existing tabs. * @return array */ public function add_reports_tab( $tabs ) { $tabs[] = [ 'slug' => 'accessibility-reports', 'label' => esc_html__( 'Accessibility Reports', 'accessibility-checker' ), 'badge' => esc_html__( 'New', 'accessibility-checker' ), 'order' => defined( 'EDACP_VERSION' ) ? 4 : 3, 'capability' => $this->settings_capability, ]; return $tabs; } /** * Render content for the active tab. * * @param string|null $settings_tab Active tab slug. * @return void */ public function maybe_render_tab_content( $settings_tab ) { if ( 'accessibility-reports' === $settings_tab ) { $this->render_page(); } } /** * Render the page. * * @return void */ public function render_page() { $license_context = $this->get_license_context(); $is_pro = $license_context['is_pro']; $license_key = (string) get_option( 'edacp_license_key', '' ); $is_connected = $license_context['is_connected']; $is_registered = $license_context['is_registered']; $status = $license_context['status']; $next_send_date = $this->get_next_send_estimate_date(); $scans_stats = new Scans_Stats(); $summary = $scans_stats->summary(); $preview_data = is_array( $summary ) ? $this->get_preview_data( $summary, $is_pro ) : []; $upgrade_url = edac_generate_link_type( [ 'utm_campaign' => 'settings-page', 'utm_content' => 'accessibility-reports-upgrade', ] ); $dashboard_url = edac_link_wrapper( 'https://my.equalizedigital.com/license-keys/', 'accessibility-reports', 'account', false ); $signup_url = edac_link_wrapper( 'https://my.equalizedigital.com/sign-up/', 'accessibility-reports', 'signup', false ); $privacy_url = edac_link_wrapper( 'https://equalizedigital.com/privacy-policy/', 'accessibility-reports', 'privacy', false ); $data_processing_url = edac_link_wrapper( 'https://equalizedigital.com/data-terms/', 'accessibility-reports', 'dpa', false ); $allowed_icon_html = [ 'span' => [ 'class' => true, 'aria-hidden' => true, 'aria-label' => true, ], 'svg' => [ 'width' => true, 'height' => true, 'viewbox' => true, 'fill' => true, 'xmlns' => true, ], 'path' => [ 'd' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, ], 'rect' => [ 'x' => true, 'y' => true, 'width' => true, 'height' => true, 'rx' => true, 'stroke' => true, 'stroke-width' => true, ], ]; ?>

dashboard.', 'accessibility-checker' ) ), esc_url( $dashboard_url ) ); ?>

Create a free account to get one.', 'accessibility-checker' ) ), esc_url( $signup_url ) ); ?>

create a free account. It only takes a minute.', 'accessibility-checker' ) ), esc_url( $signup_url ) ); ?>

mask_license_key( $license_key ) ); ?>
$has_pro_plugin, 'is_pro' => $is_pro, 'status' => $status, 'is_connected' => $is_connected, 'is_registered' => $is_registered, 'fallback_active' => $fallback_active, ]; } /** * Gets the next estimated send date, assuming each send will be on * Mondays. * * @return string */ private function get_next_send_estimate_date(): string { try { // If today is Monday, use today. Otherwise, use next Monday. $today = new \DateTime( 'now', wp_timezone() ); if ( '1' === $today->format( 'N' ) ) { return $today->format( 'Y-m-d' ); } $next_monday = new \DateTime( 'next monday', wp_timezone() ); return $next_monday->format( 'Y-m-d' ); } catch ( \Exception $exception ) { return ''; } } /** * Build preview data from current site stats. * * @param array $summary Current site summary. * @param bool $is_pro Whether the effective active license is Pro. * @return array */ private function get_preview_data( array $summary, bool $is_pro ): array { $problems = (int) ( $summary['errors'] ?? 0 ); $needs_review = (int) ( $summary['warnings'] ?? 0 ); $total_issues = $problems + $needs_review; $urls_scanned = (int) ( $summary['posts_scanned'] ?? 0 ); $post_types_checked = (int) ( $summary['scannable_post_types_count'] ?? 0 ); $public_post_types = (int) ( $summary['public_post_types_count'] ?? 0 ); $taxonomies_checked = $this->get_taxonomy_coverage_counts( $is_pro ); $rules = $this->get_rule_index(); return [ 'total_issues' => $total_issues, 'problems' => $problems, 'needs_review' => $needs_review, 'passed_checks' => (string) ( $summary['passed_percentage_formatted'] ?? __( 'N/A', 'accessibility-checker' ) ), 'urls_scanned' => $urls_scanned, 'post_types_checked' => sprintf( '%1$d/%2$d', $post_types_checked, max( $public_post_types, $post_types_checked ) ), 'taxonomies_checked' => sprintf( '%1$d/%2$d', $taxonomies_checked['checked'], max( $taxonomies_checked['total'], $taxonomies_checked['checked'] ) ), 'top_pages' => array_slice( $summary['top_pages_with_issues'] ?? [], 0, 5 ), 'top_issues' => $this->format_top_issues( $summary['top_issues_found_on_site'] ?? [], $rules ), ]; } /** * Map rules by slug for display. * * @return array */ private function get_rule_index(): array { $rules = edac_register_rules(); $index = []; foreach ( $rules as $rule ) { if ( empty( $rule['slug'] ) ) { continue; } $index[ $rule['slug'] ] = $rule; } return $index; } /** * Get a resized status icon using the shared helper output. * * @param string $icon_name Icon name for edac_icon(). * @return string */ private function get_status_icon( string $icon_name ): string { return edac_icon( $icon_name, '', true, '', 'edac-reports-card__status-icon' ); } /** * Format top issue rows for the preview table. * * @param array $issues Raw issue counts. * @param array $rules Indexed rules. * @return array */ private function format_top_issues( array $issues, array $rules ): array { $formatted = []; foreach ( array_slice( $issues, 0, 10 ) as $issue ) { $rule = $rules[ $issue['rule_slug'] ] ?? []; $severity = isset( $rule['severity'] ) ? (int) $rule['severity'] : 99; $formatted[] = [ 'title' => $rule['title'] ?? $issue['rule_slug'], 'severity' => $this->format_severity( $severity ), 'rank' => $severity, 'count' => (int) $issue['issue_count'], ]; } usort( $formatted, function ( $a, $b ) { if ( $a['rank'] === $b['rank'] ) { return $b['count'] <=> $a['count']; } return $a['rank'] <=> $b['rank']; } ); return array_map( function ( $issue ) { unset( $issue['rank'] ); return $issue; }, array_slice( $formatted, 0, 5 ) ); } /** * Convert a numeric severity to a human-readable label. * * @param int $severity Severity number. * @return string */ private function format_severity( int $severity ): string { switch ( $severity ) { case 1: return __( 'Critical', 'accessibility-checker' ); case 2: return __( 'High', 'accessibility-checker' ); case 3: return __( 'Medium', 'accessibility-checker' ); case 4: return __( 'Low', 'accessibility-checker' ); default: return __( 'Unknown', 'accessibility-checker' ); } } /** * Get taxonomy coverage counts for the preview panel. * * @param bool $is_pro Whether the effective active license is Pro. * @return array */ private function get_taxonomy_coverage_counts( bool $is_pro ): array { $taxonomies = get_taxonomies( [ 'public' => true, ], 'names' ); unset( $taxonomies['post_format'] ); $total = count( $taxonomies ); $checked = 0; if ( $is_pro && get_option( 'edacp_enable_archive_scanning' ) ) { $checked = $total; } return [ 'checked' => $checked, 'total' => $total, ]; } /** * Mask a license key for display. * * @param string $license_key License key. * @return string */ private function mask_license_key( string $license_key ): string { if ( strlen( $license_key ) <= 8 ) { return $license_key; } return substr( $license_key, 0, 4 ) . str_repeat( '*', max( strlen( $license_key ) - 8, 4 ) ) . substr( $license_key, -4 ); } }