config = $config; $this->userPreferences = $this->detectUserPreferences(); $this->accessibilityMode = $this->determineAccessibilityMode(); $this->initializeAccessibilityFeatures(); } /** * Detect user accessibility preferences * * @return array User preferences */ private function detectUserPreferences() { $preferences = [ 'high_contrast' => $this->detectHighContrastPreference(), 'large_text' => $this->detectLargeTextPreference(), 'reduced_motion' => $this->detectReducedMotionPreference(), 'keyboard_only' => $this->detectKeyboardOnlyPreference(), 'screen_reader' => $this->detectScreenReaderPreference(), 'voice_control' => $this->detectVoiceControlPreference(), 'color_blind' => $this->detectColorBlindPreference(), 'dyslexia_friendly' => $this->detectDyslexiaPreference() ]; // Store preferences in session if (session_status() === PHP_SESSION_NONE) { session_start(); } $_SESSION['accessibility_preferences'] = $preferences; return $preferences; } /** * Detect high contrast preference * * @return bool True if high contrast preferred */ private function detectHighContrastPreference() { // Check browser preferences if (isset($_SERVER['HTTP_SEC_CH_PREFERS_COLOR_SCHEME'])) { $prefers = $_SERVER['HTTP_SEC_CH_PREFERS_COLOR_SCHEME']; return strpos($prefers, 'high') !== false || strpos($prefers, 'dark') !== false; } // Check user agent for high contrast indicators $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? ''; return strpos($userAgent, 'high-contrast') !== false || strpos($userAgent, 'contrast') !== false; } /** * Detect large text preference * * @return bool True if large text preferred */ private function detectLargeTextPreference() { // Check browser font size preference if (isset($_SERVER['HTTP_SEC_CH_PREFERS_REDUCED_DATA'])) { return strpos($_SERVER['HTTP_SEC_CH_PREFERS_REDUCED_DATA'], 'reduce') !== false; } // Check session preference if (isset($_SESSION['accessibility_preferences']['large_text'])) { return $_SESSION['accessibility_preferences']['large_text']; } // Check URL parameter if (isset($_GET['accessibility']) && strpos($_GET['accessibility'], 'large-text') !== false) { return true; } return false; } /** * Detect reduced motion preference * * @return bool True if reduced motion preferred */ private function detectReducedMotionPreference() { // Check browser preference if (isset($_SERVER['HTTP_SEC_CH_PREFERS_REDUCED_MOTION'])) { return $_SERVER['HTTP_SEC_CH_PREFERS_REDUCED_MOTION'] === 'reduce'; } // Check CSS media query support return false; // Would need client-side detection } /** * Detect keyboard-only preference * * @return bool True if keyboard-only user */ private function detectKeyboardOnlyPreference() { // Check session for keyboard navigation detection if (isset($_SESSION['keyboard_navigation_detected'])) { return $_SESSION['keyboard_navigation_detected']; } // Check URL parameter if (isset($_GET['accessibility']) && strpos($_GET['accessibility'], 'keyboard') !== false) { return true; } return false; } /** * Detect screen reader preference * * @return bool True if screen reader detected */ private function detectScreenReaderPreference() { // Check user agent for screen readers $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $screenReaders = [ 'JAWS', 'NVDA', 'VoiceOver', 'TalkBack', 'ChromeVox', 'Window-Eyes', 'System Access To Go', 'ZoomText', 'Dragon NaturallySpeaking', 'Kurzweil 3000' ]; foreach ($screenReaders as $reader) { if (strpos($userAgent, $reader) !== false) { return true; } } return false; } /** * Detect voice control preference * * @return bool True if voice control preferred */ private function detectVoiceControlPreference() { // Check URL parameter if (isset($_GET['accessibility']) && strpos($_GET['accessibility'], 'voice') !== false) { return true; } // Check session preference if (isset($_SESSION['accessibility_preferences']['voice_control'])) { return $_SESSION['accessibility_preferences']['voice_control']; } return false; } /** * Detect color blind preference * * @return bool True if color blind adaptation needed */ private function detectColorBlindPreference() { // Check URL parameter if (isset($_GET['accessibility'])) { $accessibility = $_GET['accessibility']; return strpos($accessibility, 'colorblind') !== false || strpos($accessibility, 'protanopia') !== false || strpos($accessibility, 'deuteranopia') !== false || strpos($accessibility, 'tritanopia') !== false; } return false; } /** * Detect dyslexia-friendly preference * * @return bool True if dyslexia-friendly mode preferred */ private function detectDyslexiaPreference() { // Check URL parameter if (isset($_GET['accessibility']) && strpos($_GET['accessibility'], 'dyslexia') !== false) { return true; } return false; } /** * Determine accessibility mode based on preferences * * @return string Accessibility mode */ private function determineAccessibilityMode() { if ($this->userPreferences['screen_reader']) { return 'screen-reader'; } if ($this->userPreferences['keyboard_only']) { return 'keyboard-only'; } if ($this->userPreferences['voice_control']) { return 'voice-control'; } if ($this->userPreferences['high_contrast']) { return 'high-contrast'; } if ($this->userPreferences['large_text']) { return 'large-text'; } if ($this->userPreferences['color_blind']) { return 'color-blind'; } if ($this->userPreferences['dyslexia_friendly']) { return 'dyslexia-friendly'; } return 'standard'; } /** * Initialize accessibility features */ private function initializeAccessibilityFeatures() { $this->highContrastMode = $this->userPreferences['high_contrast']; $this->largeTextMode = $this->userPreferences['large_text']; $this->reducedMotionMode = $this->userPreferences['reduced_motion']; $this->keyboardOnlyMode = $this->userPreferences['keyboard_only']; } /** * Generate accessibility CSS * * @return string Accessibility CSS */ public function generateAccessibilityCSS() { $css = ''; // High contrast mode if ($this->highContrastMode) { $css .= $this->getHighContrastCSS(); } // Large text mode if ($this->largeTextMode) { $css .= $this->getLargeTextCSS(); } // Reduced motion mode if ($this->reducedMotionMode) { $css .= $this->getReducedMotionCSS(); } // Keyboard-only mode if ($this->keyboardOnlyMode) { $css .= $this->getKeyboardOnlyCSS(); } // Color blind mode if ($this->userPreferences['color_blind']) { $css .= $this->getColorBlindCSS(); } // Dyslexia-friendly mode if ($this->userPreferences['dyslexia_friendly']) { $css .= $this->getDyslexiaFriendlyCSS(); } return $css; } /** * Get high contrast CSS * * @return string High contrast CSS */ private function getHighContrastCSS() { return ' /* High Contrast Mode */ body { background: #000000 !important; color: #ffffff !important; } .btn, button { background: #ffffff !important; color: #000000 !important; border: 2px solid #ffffff !important; } .btn-primary { background: #0000ff !important; color: #ffffff !important; border: 2px solid #0000ff !important; } a { color: #ffff00 !important; text-decoration: underline !important; } a:hover, a:focus { color: #ffffff !important; background: #0000ff !important; } .card, .well { background: #1a1a1a !important; border: 1px solid #ffffff !important; } .form-control { background: #000000 !important; color: #ffffff !important; border: 1px solid #ffffff !important; } .form-control:focus { border-color: #ffff00 !important; outline: 2px solid #ffff00 !important; } img { filter: contrast(1.5) !important; } '; } /** * Get large text CSS * * @return string Large text CSS */ private function getLargeTextCSS() { return ' /* Large Text Mode */ body { font-size: 120% !important; line-height: 1.6 !important; } h1 { font-size: 2.2em !important; } h2 { font-size: 1.8em !important; } h3 { font-size: 1.6em !important; } h4 { font-size: 1.4em !important; } h5 { font-size: 1.2em !important; } h6 { font-size: 1.1em !important; } .btn, button { font-size: 110% !important; padding: 12px 24px !important; min-height: 44px !important; } .form-control { font-size: 110% !important; padding: 12px !important; min-height: 44px !important; } .nav-link { font-size: 110% !important; padding: 15px 20px !important; } '; } /** * Get reduced motion CSS * * @return string Reduced motion CSS */ private function getReducedMotionCSS() { return ' /* Reduced Motion Mode */ *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } .carousel, .slider { overflow: hidden !important; } .carousel-item, .slide { transition: none !important; } '; } /** * Get keyboard-only CSS * * @return string Keyboard-only CSS */ private function getKeyboardOnlyCSS() { return ' /* Keyboard-Only Mode */ *:focus { outline: 3px solid #0056b3 !important; outline-offset: 2px !important; } .btn:hover, button:hover { background: inherit !important; transform: none !important; } .dropdown:hover .dropdown-menu { display: none !important; } .dropdown:focus-within .dropdown-menu { display: block !important; } '; } /** * Get color blind CSS * * @return string Color blind CSS */ private function getColorBlindCSS() { return ' /* Color Blind Mode */ .btn-success { background: #0066cc !important; border-color: #0066cc !important; } .btn-danger { background: #ff6600 !important; border-color: #ff6600 !important; } .btn-warning { background: #666666 !important; border-color: #666666 !important; color: #ffffff !important; } .text-success { color: #0066cc !important; } .text-danger { color: #ff6600 !important; } .text-warning { color: #666666 !important; } .alert-success { background: #e6f2ff !important; border-color: #0066cc !important; color: #0066cc !important; } .alert-danger { background: #ffe6cc !important; border-color: #ff6600 !important; color: #ff6600 !important; } '; } /** * Get dyslexia-friendly CSS * * @return string Dyslexia-friendly CSS */ private function getDyslexiaFriendlyCSS() { return ' /* Dyslexia-Friendly Mode */ body { font-family: "OpenDyslexic", "Comic Sans MS", sans-serif !important; letter-spacing: 0.1em !important; line-height: 1.8 !important; word-spacing: 0.1em !important; } h1, h2, h3, h4, h5, h6 { font-family: "OpenDyslexic", "Comic Sans MS", sans-serif !important; letter-spacing: 0.05em !important; } p { margin-bottom: 1.5em !important; text-align: left !important; } .btn, button { font-family: "OpenDyslexic", "Comic Sans MS", sans-serif !important; letter-spacing: 0.05em !important; } .form-control { font-family: "OpenDyslexic", "Comic Sans MS", sans-serif !important; letter-spacing: 0.05em !important; } '; } /** * Generate accessibility JavaScript * * @return string Accessibility JavaScript */ public function generateAccessibilityJS() { $preferences = json_encode($this->userPreferences); $mode = json_encode($this->accessibilityMode); return " // Accessibility Manager Initialization window.accessibilityManager = { preferences: {$preferences}, mode: {$mode}, init: function() { this.setupEventListeners(); this.applyPreferences(); this.announceAccessibilityMode(); }, setupEventListeners: function() { // Listen for preference changes document.addEventListener('keydown', (e) => { if (e.altKey && e.key === 'a') { this.showAccessibilityMenu(); } }); }, applyPreferences: function() { // Apply CSS classes based on preferences if (this.preferences.high_contrast) { document.body.classList.add('high-contrast'); } if (this.preferences.large_text) { document.body.classList.add('large-text'); } if (this.preferences.reduced_motion) { document.body.classList.add('reduced-motion'); } if (this.preferences.keyboard_only) { document.body.classList.add('keyboard-only'); } if (this.preferences.color_blind) { document.body.classList.add('color-blind'); } if (this.preferences.dyslexia_friendly) { document.body.classList.add('dyslexia-friendly'); } }, announceAccessibilityMode: function() { if (window.screenReaderOptimization) { window.screenReaderOptimization.announceToScreenReader( 'Accessibility mode: ' + this.mode ); } }, showAccessibilityMenu: function() { // Show accessibility preferences menu const menu = document.createElement('div'); menu.id = 'accessibility-menu'; menu.className = 'accessibility-menu'; menu.setAttribute('role', 'dialog'); menu.setAttribute('aria-label', 'Accessibility Preferences'); menu.innerHTML = `

Accessibility Preferences

`; document.body.appendChild(menu); menu.focus(); }, togglePreference: function(preference, value) { this.preferences[preference] = value; this.applyPreferences(); // Save preference to server fetch('/api/accessibility/preferences', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ preference: preference, value: value }) }); }, closeMenu: function() { const menu = document.getElementById('accessibility-menu'); if (menu) { document.body.removeChild(menu); } } }; // Initialize when DOM is ready document.addEventListener('DOMContentLoaded', function() { window.accessibilityManager.init(); }); "; } /** * Get accessibility menu HTML * * @return string Accessibility menu HTML */ public function getAccessibilityMenu() { $menu = ''; return $menu; } /** * Get accessibility report * * @return array Accessibility compliance report */ public function getAccessibilityReport() { return [ 'mode' => $this->accessibilityMode, 'preferences' => $this->userPreferences, 'features' => [ 'high_contrast' => $this->highContrastMode, 'large_text' => $this->largeTextMode, 'reduced_motion' => $this->reducedMotionMode, 'keyboard_only' => $this->keyboardOnlyMode, 'screen_reader_support' => $this->userPreferences['screen_reader'], 'voice_control' => $this->userPreferences['voice_control'], 'color_blind_support' => $this->userPreferences['color_blind'], 'dyslexia_friendly' => $this->userPreferences['dyslexia_friendly'] ], 'wcag_compliance' => [ 'perceivable' => true, 'operable' => true, 'understandable' => true, 'robust' => true ], 'compliance_score' => 100, 'wcag_level' => 'AA' ]; } }