ABILITY: ' . esc_html($msg) . '
'; } } add_action('admin_notices', 'ability_admin_bootstrap_notices'); /** * Verify requirements early. */ function ability_requirements_ok(): bool { if (version_compare(PHP_VERSION, ABILITY_MIN_PHP, '<')) { $GLOBALS['ability_bootstrap_errors'][] = sprintf( 'Requires PHP %s or higher. Current: %s.', ABILITY_MIN_PHP, PHP_VERSION ); return false; } global $wp_version; if (version_compare($wp_version, ABILITY_MIN_WP, '<')) { $GLOBALS['ability_bootstrap_errors'][] = sprintf( 'Requires WordPress %s or higher. Current: %s.', ABILITY_MIN_WP, $wp_version ); return false; } $files = [ ABILITY_PATH . 'includes/class-ability-db.php', ABILITY_PATH . 'includes/class-ability-ajax.php', ABILITY_PATH . 'includes/class-ability-wizard.php', ABILITY_PATH . 'includes/class-ability-config.php', ABILITY_PATH . 'includes/class-ability-scanner.php', ABILITY_PATH . 'admin/class-ability-admin.php', ABILITY_PATH . 'frontend/class-ability-frontend.php', ]; foreach ($files as $f) { if (!file_exists($f)) { $GLOBALS['ability_bootstrap_errors'][] = sprintf( 'Missing required file: %s', str_replace(WP_PLUGIN_DIR . '/', '', $f) ); return false; } } return true; } /** * Safe loader with guards. */ function ability_safe_load_files() { try { require_once ABILITY_PATH . 'includes/class-ability-db.php'; require_once ABILITY_PATH . 'includes/class-ability-ajax.php'; require_once ABILITY_PATH . 'includes/class-ability-wizard.php'; require_once ABILITY_PATH . 'includes/class-ability-config.php'; require_once ABILITY_PATH . 'includes/class-ability-scanner.php'; require_once ABILITY_PATH . 'admin/class-ability-admin.php'; require_once ABILITY_PATH . 'frontend/class-ability-frontend.php'; require_once ABILITY_PATH . 'includes/shortcode-accessibility-statement.php'; require_once ABILITY_PATH . 'includes/admin-settings.php'; require_once ABILITY_PATH . 'includes/class-ability-mini-toolbar.php'; } catch (Throwable $e) { $GLOBALS['ability_bootstrap_errors'][] = 'Failed to load plugin files: ' . $e->getMessage(); return false; } return true; } /** * Activation hook. */ function ability_activation() { if (!ability_requirements_ok()) { deactivate_plugins(plugin_basename(__FILE__)); wp_die( __('ABILITY requires PHP 7.4+ and WordPress 5.8+.', 'ability'), __('Plugin Activation Error', 'ability'), ['back_link' => true] ); } set_transient('ability_activation_redirect', true, 30); // Ensure DB class is loaded so tables can be created on first activation. if (!class_exists('ABILITY\\DB') && file_exists(ABILITY_PATH . 'includes/class-ability-db.php')) { require_once ABILITY_PATH . 'includes/class-ability-db.php'; } if (class_exists('ABILITY\\DB')) { \ABILITY\DB::create_tables(); } if (false === get_option('ability_a11y_settings', false)) { $adv_defaults = array( 'show_controls' => array( 'high-contrast-toggle' => 1, 'line-spacing-toggle' => 1, 'focus-indicators-toggle' => 1, 'screen-reader-mode-toggle' => 1, 'voice-navigation-toggle' => 1, 'dyslexia-font-toggle' => 1, 'reduce-motion-toggle' => 1, 'adhd-mode-toggle' => 1, 'font-size-controls' => 1, ), 'default_states' => array( 'high-contrast-toggle' => 0, 'line-spacing-toggle' => 0, 'focus-indicators-toggle' => 0, 'screen-reader-mode-toggle' => 0, 'voice-navigation-toggle' => 0, 'dyslexia-font-toggle' => 0, 'reduce-motion-toggle' => 0, 'adhd-mode-toggle' => 0, ), 'skip_links_position' => 'body_open', 'hide_footer_skip_links' => 1, 'enable_structured_data' => 0, 'initial_font_scale' => '1.0', 'enable_legacy_toolbar' => 0, // NEW configurable skip link targets 'skip_link_main_id' => 'main-content', 'skip_link_nav_id' => 'navigation', 'skip_link_footer_id' => 'footer', ); update_option('ability_a11y_settings', $adv_defaults); } // Create a review-required Accessibility Statement draft. The plugin must not // automatically publish site-wide accessibility or legal representations. $existing_id = (int) get_option('ability_a11y_statement_page_id', 0); if ($existing_id && get_post_status($existing_id)) { return; } $existing = get_page_by_path('accessibility-statement', OBJECT, 'page'); if ($existing) { update_option('ability_a11y_statement_page_id', $existing->ID); return; } $page_id = wp_insert_post( array( 'post_title' => __('Accessibility Statement', 'ability'), 'post_name' => 'accessibility-statement', 'post_status' => 'draft', 'post_type' => 'page', 'post_content' => '[access-statement]', ), true ); if (!is_wp_error($page_id)) { update_post_meta($page_id, '_wp_page_template', 'accessibility-statement.php'); update_post_meta($page_id, '_ability_generated_statement', 1); update_post_meta($page_id, '_ability_statement_review_required', 1); update_option('ability_a11y_statement_page_id', $page_id); } } /** * Deactivation hook. */ function ability_deactivation() { delete_transient('ability_activation_redirect'); } /** * Initialize plugin. */ function ability_init() { if (!ability_requirements_ok()) { return; } if (!ability_safe_load_files()) { return; } if (class_exists('ABILITY\Admin\Ability_Admin')) { new \ABILITY\Admin\Ability_Admin('ability', ABILITY_VERSION); } if (class_exists('ABILITY\Wizard')) { new \ABILITY\Wizard(); } if (class_exists('ABILITY\Frontend\Ability_Frontend')) { new \ABILITY\Frontend\Ability_Frontend('ability', ABILITY_VERSION); } if (class_exists('Ability_A11y_Admin_Settings')) { new Ability_A11y_Admin_Settings(); } if (class_exists('Ability_Mini_Toolbar')) { new Ability_Mini_Toolbar(); } // Instantiate AJAX handlers (previously missing) if (class_exists('ABILITY\Ajax')) { new \ABILITY\Ajax(); } } function ability_get_tier(): string { if (ABILITY_ENTERPRISE) return ABILITY_TIER_ENTERPRISE; if (ABILITY_PRO) return ABILITY_TIER_PRO; return ABILITY_TIER_BASIC; } function ability_is_pro(): bool { return ABILITY_PRO || ABILITY_ENTERPRISE; } function ability_is_enterprise(): bool { return ABILITY_ENTERPRISE; } // Register hooks at file scope for reliability register_activation_hook(__FILE__, 'ability_activation'); register_deactivation_hook(__FILE__, 'ability_deactivation'); /** * Load plugin textdomain for translations. */ add_action('init', function(){ load_plugin_textdomain('ability', false, dirname(plugin_basename(__FILE__)) . '/languages'); }); /** * Plugin links (Plugins list row) */ add_filter('plugin_action_links_' . plugin_basename(__FILE__), function($links){ $settings_link = '' . esc_html__('Settings','ability') . ''; array_unshift($links, $settings_link); return $links; }); // Initialize add_action('plugins_loaded', 'ability_init', 10);