PluginProbe ʕ •ᴥ•ʔ
Web Accessibility Toolkit – Accessibility Checker & ARIA for WCAG, Section 508 & ADA Compliance / 1.5.3
Web Accessibility Toolkit – Accessibility Checker & ARIA for WCAG, Section 508 & ADA Compliance v1.5.3
trunk 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6
aria-accessibility-toolkit / includes / class-admin.php
aria-accessibility-toolkit / includes Last commit date
class-admin.php 10 months ago index.php 11 months ago
class-admin.php
788 lines
1 <?php
2
3 // Exit if accessed directly
4 if ( ! defined( 'ABSPATH' ) ) exit;
5
6 class ARIAAT_Admin {
7
8 /**
9 * Constructor to hook the necessary actions.
10 */
11 public function __construct() {
12
13 add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts_styles' ] );
14
15 add_action('admin_menu', [$this, 'register_admin_menu']);
16 add_action('admin_init', [$this, 'register_settings']);
17
18
19 }
20
21 public function admin_scripts_styles( $hook ) {
22 $v = ARIAATVERSION;
23 //$v = time();
24
25 if ( strpos( $hook, 'ariaat' ) !== false ) {
26 wp_enqueue_script(
27 'ariaat-admin',
28 ARIAATURL . 'assets/js/ariaat-admin.js',
29 ['jquery'],
30 $v,
31 true
32 );
33
34 wp_localize_script('ariaat-admin', 'ARIAAT_Data', [
35 'aria_options' => array_map(function($item) {
36 return [
37 'label' => $item['label'],
38 ];
39 }, $this->get_aria_attributes()),
40 'role_options' => array_map(function($item) {
41 return [
42 'label' => $item['label'],
43 ];
44 }, $this->get_role_options()),
45 ]);
46
47 wp_enqueue_style( 'ariaat-style', ARIAATURL .'assets/css/ariaat-admin.css', false, $v );
48 }
49 }
50
51 public function register_admin_menu() {
52 add_options_page('Web Accessibility', 'Web Accessibility', 'manage_options', 'ariaat', [$this, 'render_settings_page']);
53 }
54
55 public function register_settings() {
56
57 register_setting('ariaat_general_group', 'ariaat_general_settings', [$this, 'sanitize_general_settings']);
58
59 register_setting('ariaat_aria_group', 'ariaat_aria_mappings', [$this, 'sanitize_array']);
60 register_setting('ariaat_aria_group', 'ariaat_aria_menus', [$this, 'sanitize_menu_selection']);
61
62 register_setting('ariaat_role_group', 'ariaat_role_mappings', [$this, 'sanitize_array']);
63 register_setting('ariaat_role_group', 'ariaat_role_menus', [$this, 'sanitize_menu_selection']);
64
65 register_setting('ariaat_contrast_group', 'ariaat_contrast_mappings', [$this, 'sanitize_array']);
66
67 register_setting('ariaat_images_group', 'ariaat_image_settings', [$this, 'sanitize_array']);
68
69 }
70
71
72 public function get_all_menus() {
73 $menus = wp_get_nav_menus();
74 $output = [];
75 foreach ($menus as $menu) {
76 $output[$menu->term_id] = $menu->name;
77 }
78 return $output;
79 }
80
81
82 public function render_settings_page() {
83
84 $active_tab = isset($_GET['tab']) ? sanitize_key($_GET['tab']) : 'general';
85 ?>
86 <div class="wrap ariaat">
87
88 <div class="ariaat-header">
89 <h1>Web Accessibility Toolkit <span><?php echo esc_attr(ARIAATVERSION); ?></span></h1>
90
91 <div class="ariaat-header-buttons">
92 <a href="https://wordpress.org/support/plugin/aria-accessibility-toolkit/reviews/#new-post" target="_blank" class="small">Leave a review</a>
93 <a href="https://wcagforwp.com/docs/" target="_blank" class="button-primary small">Docs</a>
94 <a href="https://wcagforwp.com/downloads/pro-plugin" target="_blank" class="button-primary small">PRO Plugin</a>
95 </div>
96 </div>
97
98 <div class="main_content">
99 <h2 class="nav-tab-wrapper">
100 <a href="?page=ariaat&tab=general" class="nav-tab <?php echo $active_tab == 'general' ? 'nav-tab-active' : '' ?>">General</a>
101 <a href="?page=ariaat&tab=aria" class="nav-tab <?php echo $active_tab == 'aria' ? 'nav-tab-active' : '' ?>">ARIA</a>
102 <a href="?page=ariaat&tab=roles" class="nav-tab <?php echo $active_tab == 'roles' ? 'nav-tab-active' : '' ?>">Roles</a>
103 <a href="?page=ariaat&tab=contrast" class="nav-tab <?php echo $active_tab == 'contrast' ? 'nav-tab-active' : '' ?>">Contrast</a>
104 <a href="?page=ariaat&tab=images" class="nav-tab <?php echo $active_tab == 'images' ? 'nav-tab-active' : '' ?>">Images</a>
105 <a href="?page=ariaat&tab=forms" class="nav-tab <?php echo $active_tab == 'forms' ? 'nav-tab-active' : '' ?>">Forms</a>
106 <?php do_action( 'ariaat_after_nav_tab_wrapper', $active_tab ); ?>
107 </h2>
108
109
110 <form method="post" action="options.php">
111 <?php
112 if ($active_tab === 'general') {
113 settings_fields('ariaat_general_group');
114 $settings = get_option('ariaat_general_settings', []);
115
116 ?>
117 <div class="section">
118 <h3><span class="dashicons dashicons-laptop"></span> Frontend Accessibility Checker</h3>
119 <div class="setting-row no-border">
120 <div class="setting-label">
121 <p class="description">
122 Toggle visibility of the accessibility checker on the frontend. The frontend accessibility checker is only visible to logged-in admins - it will never be visible to your users.
123 <?php if (! defined('ARIAAT_PRO_ACTIVE')) { ?>
124 <br>The <a href="https://wcagforwp.com/downloads/pro-plugin/">PRO plugin</a> also includes deep scanning of forms & works with all form plugins.
125 <?php } ?>
126 </p>
127 </div>
128 <div class="setting-control">
129 <label class="toggle-switch">
130 <input type="checkbox" name="ariaat_general_settings[enable_frontend_checker]" value="1" <?php checked($settings['enable_frontend_checker'] ?? '', '1'); ?> />
131 <span class="toggle-slider"></span>
132 </label>
133 </div>
134 </div>
135
136 </div>
137 <div class="section">
138 <h3><span class="dashicons dashicons-universal-access-alt"></span> General Accessibility Enhancements</h3>
139
140 <div class="setting-row">
141 <div class="setting-label">
142 <strong>Language</strong>
143 <p class="description">This sets the default lang attribute in your site’s HTML. It helps screen readers and search engines understand what language your site is written in. For example, use <code>en</code> for English, <code>en-AU</code> for Australian English, <code>fr</code> for French, etc.</p>
144 </div>
145 <div class="setting-control">
146 <input type="text" name="ariaat_general_settings[language]" value="<?php echo esc_attr($settings['language'] ?? ''); ?>" class="regular-text" placeholder="e.g. en, en-AU" />
147 </div>
148 </div>
149
150 <div class="setting-row">
151 <div class="setting-label">
152 <strong>Skip Link Target</strong>
153 <p class="description">
154 If provided, a “Skip to content” link will be added at the top of the page but will only be visible to keyboard and screen reader users. This improves accessibility for keyboard and screen reader users by letting them jump straight to the main content. Enter a CSS selector that matches your main content area, like <code>#primary</code> or <code>.main-content</code>. This should point to the container that wraps your main article or page content.
155 </p>
156 </div>
157 <div class="setting-control">
158 <input type="text" name="ariaat_general_settings[skip_link]" value="<?php echo esc_attr($settings['skip_link'] ?? ''); ?>" class="regular-text" placeholder=".main-content" />
159 </div>
160 </div>
161
162 <div class="setting-row">
163 <div class="setting-label">
164 <strong>Show Focus Outline</strong>
165 <p class="description">
166 Ensures that keyboard users can clearly see which element is currently focused - like buttons, links, or form fields. Some themes hide this outline by default, which can make navigation difficult. This setting forces the outline to remain visible for better usability and compliance with WCAG.
167 </p>
168 </div>
169 <div class="setting-control">
170 <label class="toggle-switch">
171 <input type="checkbox" name="ariaat_general_settings[focus_outline]" value="1" <?php checked($settings['focus_outline'] ?? '', '1'); ?> />
172 <span class="toggle-slider"></span>
173 </label>
174 </div>
175 </div>
176
177 <div class="setting-row">
178 <div class="setting-label">
179 <strong>Fix Tab Order</strong>
180 <p class="description">
181 Remove <code>tabindex</code> values greater than 0 to maintain a logical keyboard focus order.
182 </p>
183 </div>
184 <div class="setting-control">
185 <label class="toggle-switch">
186 <input type="checkbox" name="ariaat_general_settings[fix_tabindex]" value="1" <?php checked($settings['fix_tabindex'] ?? '', '1'); ?> />
187 <span class="toggle-slider"></span>
188 </label>
189 </div>
190 </div>
191
192 <div class="setting-row no-border">
193 <div class="setting-label">
194 <strong>Make Viewport Scalable</strong>
195 <p class="description">Remove <code>user-scalable=no</code> from the viewport meta tag to allow pinch-zooming.</p>
196 </div>
197 <div class="setting-control">
198 <label class="toggle-switch">
199 <input type="checkbox" name="ariaat_general_settings[make_viewport_scalable]" value="1" <?php checked($settings['make_viewport_scalable'] ?? '', '1'); ?> />
200 <span class="toggle-slider"></span>
201 </label>
202 </div>
203 </div>
204
205 </div>
206
207 <div class="section">
208 <h3><span class="dashicons dashicons-star-filled"></span> Like this plugin?</h3>
209 <div class="setting-row no-border">
210 <div class="setting-label">
211 <p class="description">The Web Accessibility Toolkit is a new plugin and we'd love it if you could help out and provide a kind review if you've found this plugin useful. You can <a href="https://wordpress.org/support/plugin/aria-accessibility-toolkit/reviews/#new-post" target="_blank">leave a review here</a>.</p>
212 </div>
213 </div>
214 </div>
215
216 <?php
217 } else if ($active_tab === 'aria') {
218 settings_fields('ariaat_aria_group');
219 $items = get_option('ariaat_aria_mappings', []);
220 ?>
221
222 <div class="section">
223 <h3><span class="dashicons dashicons-menu"></span> Menu ARIA Labels</h3>
224 <p class="desc">
225 Automatically converts <code>title</code> attributes on menu links to <code>aria-label</code> attributes, which is more reliable for screen readers. <br>This is ideal when the link text might be "About" but has a longer title like "Learn more about our company" which is much more descriptive.<br>To set the titles, visit the <a href="<?php echo esc_url( admin_url('/nav-menus.php') ); ?>" target="_blank">Menu editor</a> or go to <strong>Appearance Menus</strong> and use the “Title Attribute field (enable it via “Screen Options” if hidden).
226
227 </p>
228
229 <?php
230 $all_menus = wp_get_nav_menus();
231 $menus = apply_filters('ariaat_allowed_menus', array_slice($all_menus, 0, 2), $all_menus);
232 $selected = get_option('ariaat_aria_menus', []);
233
234 foreach ($menus as $menu) :
235 $checked = in_array($menu->term_id, $selected);
236 ?>
237 <div class="setting-row no-border">
238 <div class="setting-label">
239 <strong><?php echo esc_html($menu->name); ?></strong>
240 </div>
241 <div class="setting-control">
242 <label class="toggle-switch">
243 <input type="checkbox" name="ariaat_aria_menus[]" value="<?php echo esc_attr($menu->term_id); ?>" <?php checked($checked); ?> />
244 <span class="toggle-slider"></span>
245 </label>
246 </div>
247 </div>
248 <?php endforeach; ?>
249 <p class="desc">
250 <?php if (! defined('ARIAAT_PRO_ACTIVE')) { ?>
251 You can select up to 2 menus in the free version.
252 Upgrade to the <a href="https://wcagforwp.com/downloads/pro-plugin/">PRO plugin</a> to add unlimited menus.
253 <?php } ?>
254 </p>
255 </div>
256
257 <div class="section">
258 <h3><span class="dashicons dashicons-editor-code"></span> Custom ARIA Attributes</h3>
259 <p class="desc">
260 Add custom <code>aria-*</code> attributes to elements on your site by targeting them with CSS selectors.
261 This is useful when your theme or plugins don’t include the necessary ARIA markup.
262 For example, you might target a navigation item with a selector like <code>.nav-primary .current</code>. To find the correct selectors, right click on your page and click "Inspect" - some knowledge of CSS and HTML is required.
263 <?php if (! defined('ARIAAT_PRO_ACTIVE')) { ?>
264 <br>The <a href="https://wcagforwp.com/downloads/pro-plugin/">PRO plugin</a> includes a more comprehensive list of ARIA attributes.
265 <?php } ?>
266 </p>
267
268 <table class="form-table" id="aria-table">
269 <thead>
270 <tr>
271 <th>CSS Selector</th>
272 <th>ARIA Attribute</th>
273 <th>Value</th>
274 <th></th>
275 </tr>
276 </thead>
277 <tbody>
278 <?php foreach ($items as $index => $item) : ?>
279 <tr>
280 <td><input type="text" name="ariaat_aria_mappings[<?php echo esc_attr($index); ?>][selector]" value="<?php echo esc_attr($item['selector']); ?>" class="regular-text" /></td>
281 <td>
282 <select name="ariaat_aria_mappings[<?php echo esc_attr($index); ?>][attribute]">
283 <?php foreach ($this->get_aria_attributes() as $attr => $attr_item): ?>
284 <option value="<?php echo esc_attr($attr); ?>" <?php selected($item['attribute'], $attr); ?>>
285 <?php echo esc_html($attr_item['label']); ?>
286 </option>
287 <?php endforeach; ?>
288 </select>
289 </td>
290 <td><input type="text" name="ariaat_aria_mappings[<?php echo esc_attr($index); ?>][value]" value="<?php echo esc_attr($item['value']); ?>" class="regular-text" /></td>
291 <td><button type="button" class="button remove-row">Remove</button></td>
292 </tr>
293 <?php endforeach; ?>
294 </tbody>
295 </table>
296
297 <p><button type="button" class="button" id="add-aria-row">Add ARIA Attribute</button></p>
298 </div>
299
300 <?php
301
302
303 } elseif ($active_tab == 'roles') {
304 settings_fields('ariaat_role_group');
305 $items = get_option('ariaat_role_mappings', []);
306 ?>
307
308 <div class="section">
309 <h3><span class="dashicons dashicons-menu"></span> Menu Roles</h3>
310 <p class="desc">
311 Automatically adds <code>role="navigation"</code> to selected menus for improved screen reader support. Use this only if the menu's container is <code>&lt;div&gt;</code> or another non-semantic element. Do <strong>not</strong> use it on <code>&lt;nav&gt;</code> elements, which are already semantic. Applies only to menus output by WordPress’s <code>wp_nav_menu()</code> function. It won't modify custom HTML added manually by your theme.
312 </p>
313
314 <?php
315 $all_menus = wp_get_nav_menus();
316 $menus = apply_filters('ariaat_allowed_menus', array_slice($all_menus, 0, 2), $all_menus);
317 $selected_roles = get_option('ariaat_role_menus', []);
318
319 foreach ($menus as $menu) :
320 $checked = in_array($menu->term_id, $selected_roles);
321 ?>
322 <div class="setting-row no-border">
323 <div class="setting-label">
324 <strong><?php echo esc_html($menu->name); ?></strong>
325 </div>
326 <div class="setting-control">
327 <label class="toggle-switch">
328 <input type="checkbox" name="ariaat_role_menus[]" value="<?php echo esc_attr($menu->term_id); ?>" <?php checked($checked); ?> />
329 <span class="toggle-slider"></span>
330 </label>
331 </div>
332 </div>
333 <?php endforeach; ?>
334
335 <p class="desc">
336 <?php if (! defined('ARIAAT_PRO_ACTIVE')) { ?>
337 You can select up to 2 menus in the free version.
338 Upgrade to the <a href="https://wcagforwp.com/downloads/pro-plugin/">PRO plugin</a> to add unlimited menus.
339 <?php } ?>
340 </p>
341
342 </div>
343
344 <div class="section">
345 <h3><span class="dashicons dashicons-editor-code"></span> Custom Roles</h3>
346
347 <p class="desc">
348 Assign ARIA landmark <code>role</code> attributes to elements on your site using CSS selectors.
349 This is helpful when your theme doesn’t use semantic HTML or lacks proper roles for key regions like navigation, main content, or banners.
350 To find the right selectors, right-click any element on your site and choose "Inspect." Some familiarity with CSS and HTML is recommended.
351 <?php if (! defined('ARIAAT_PRO_ACTIVE')) { ?>
352 <br>The <a href="https://wcagforwp.com/downloads/pro-plugin/">PRO plugin</a> includes a more comprehensive list of ARIA landmark roles.
353 <?php } ?>
354 </p>
355
356
357 <table class="form-table" id="role-table">
358 <thead>
359 <tr>
360 <th>CSS Selector</th>
361 <th>Role</th>
362 <th></th>
363 </tr>
364 </thead>
365 <tbody>
366 <?php foreach ($items as $index => $item) : ?>
367 <tr>
368 <td><input type="text" name="ariaat_role_mappings[<?php echo esc_attr($index); ?>][selector]" value="<?php echo esc_attr($item['selector']); ?>" class="regular-text" /></td>
369 <td>
370 <select name="ariaat_role_mappings[<?php echo esc_attr($index); ?>][role]">
371 <?php foreach ($this->get_role_options() as $role => $role_item): ?>
372 <option value="<?php echo esc_attr($role); ?>" <?php selected($item['role'], $role); ?>>
373 <?php echo esc_html($role_item['label']); ?>
374 </option>
375 <?php endforeach; ?>
376 </select>
377 </td>
378 <td><button type="button" class="button remove-row">Remove</button></td>
379 </tr>
380 <?php endforeach; ?>
381 </tbody>
382 </table>
383
384 <p><button type="button" class="button" id="add-role-row">Add Role</button></p>
385 </div>
386
387 <?php
388
389
390 } else if( $active_tab == 'contrast' ) {
391 settings_fields('ariaat_contrast_group');
392 $items = get_option('ariaat_contrast_mappings', []);
393 ?>
394
395 <div class="section">
396 <h3><span class="dashicons dashicons-star-half"></span> High Contrast Adjustments</h3>
397 <p class="desc">
398 Apply custom foreground and background colors to specific elements to improve visual contrast and accessibility. This is especially useful for meeting WCAG contrast ratio requirements and making content easier to read for users with visual impairments.
399 </p>
400
401 <table class="form-table" id="contrast-table">
402 <thead>
403 <tr>
404 <th class="selector">HTML Selector</th>
405 <th class="color">Text</th>
406 <th class="color">Background</th>
407 <th>Contrast</th>
408 <th class="remove"></th>
409 </tr>
410 </thead>
411 <tbody>
412 <?php foreach ($items as $index => $item) : ?>
413 <tr>
414 <td class="selector"><input type="text" name="ariaat_contrast_mappings[<?php echo esc_attr( $index ) ?>][selector]" value="<?php echo esc_attr($item['selector']) ?>" class="regular-text" /></td>
415 <td>
416 <input type="color"
417 id="text-color-picker-<?php echo esc_attr($index); ?>"
418 class="text-color"
419 data-index="<?php echo esc_attr($index); ?>"
420 value="<?php echo esc_attr($item['color']); ?>"
421 >
422 <input type="hidden"
423 name="ariaat_contrast_mappings[<?php echo esc_attr($index); ?>][color]"
424 id="real-text-color-<?php echo esc_attr($index); ?>"
425 value="<?php echo esc_attr($item['color']); ?>"
426 >
427 <button type="button" class="button clear-color" data-target="<?php echo esc_attr($index); ?>" data-type="text">Clear</button>
428 </td>
429 <td>
430 <input type="color"
431 id="bg-color-picker-<?php echo esc_attr($index); ?>"
432 class="bg-color"
433 data-index="<?php echo esc_attr($index); ?>"
434 value="<?php echo esc_attr($item['background']); ?>"
435 >
436 <input type="hidden"
437 name="ariaat_contrast_mappings[<?php echo esc_attr($index); ?>][background]"
438 id="real-bg-color-<?php echo esc_attr($index); ?>"
439 value="<?php echo esc_attr($item['background']); ?>"
440 >
441 <button type="button" class="button clear-color" data-target="<?php echo esc_attr($index); ?>" data-type="bg">Clear</button>
442 </td>
443 <td>
444 <div class="contrast-result" id="contrast-result-<?php echo esc_attr( $index ); ?>"></div>
445 </td>
446
447 <td><button type="button" class="button remove-row">Remove</button></td>
448 </tr>
449 <?php endforeach; ?>
450 </tbody>
451 </table>
452 <p><button type="button" class="button" id="add-contrast-row">Add Contrast Item</button></p>
453
454 </div>
455
456 <?php
457
458 } else if ($active_tab === 'images') {
459
460 settings_fields('ariaat_images_group');
461 $settings = get_option('ariaat_image_settings', []);
462
463 $show_all = isset($_POST['ariaat_image_settings']['show_all'])
464 ? boolval($_POST['ariaat_image_settings']['show_all'])
465 : (!empty($settings['show_all']));
466
467 $paged = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
468 $per_page = 50;
469 $offset = ($paged - 1) * $per_page;
470
471 $meta_query = $show_all ? [] : [
472 'relation' => 'OR',
473 [
474 'key' => '_wp_attachment_image_alt',
475 'value' => '',
476 'compare' => '='
477 ],
478 [
479 'key' => '_wp_attachment_image_alt',
480 'value' => ' ',
481 'compare' => '='
482 ],
483 [
484 'key' => '_wp_attachment_image_alt',
485 'compare' => 'NOT EXISTS'
486 ]
487 ];
488
489 $query = new WP_Query([
490 'post_type' => 'attachment',
491 'post_mime_type' => 'image',
492 'post_status' => 'inherit',
493 'posts_per_page' => $per_page,
494 'offset' => $offset,
495 'meta_query' => $meta_query
496 ]);
497
498 $attachments = $query->posts;
499 $total = $query->found_posts;
500 $total_pages = ceil($total / $per_page);
501 ?>
502 <div class="section">
503 <h3><span class="dashicons dashicons-format-gallery"></span> Images Missing Alt Text</h3>
504 <p class="desc">
505 Lists images on your site that are missing alt text. Add the alt text below and click "Save" to update each image. Does not scan images that are within themes or plugins, only images from your WordPress Media Library.
506 </p>
507 <p>
508 <label>
509 <input type="checkbox" name="ariaat_image_settings[show_all]" value="1"
510 <?php checked($settings['show_all'] ?? '', '1'); ?> />
511 Show all images (not just those missing alt text)
512 </label>
513 </p>
514
515 <?php if (empty($attachments)) : ?>
516 <p>No images without alt text were found.</p>
517 <?php else : ?>
518
519 <p style="margin-bottom: 1em;">
520 <button type="button" class="button copy-all-filenames">Copy all Filenames to Alt</button>
521 <button type="button" class="button copy-all-titles">Copy all Titles to Alt Tags</button>
522 </p>
523
524 <table class="form-table widefat fixed striped" id="alt-images" style="margin-bottom: 2em;">
525 <thead>
526 <tr>
527 <th class="id">ID</th>
528 <th class="thumb">Thumb</th>
529 <th>Alt Tag</th>
530 <th>Filename</th>
531 <th>Attached To</th>
532 <th class="save">Save</th>
533 </tr>
534 </thead>
535 <tbody>
536 <?php foreach ($attachments as $attachment) :
537
538 $parent_id = $attachment->post_parent;
539
540 if ($parent_id) {
541 $parent = get_post($parent_id);
542 if (!$parent || $parent->post_status !== 'publish') {
543 continue; // skip this image
544 }
545 }
546 $id = $attachment->ID;
547 $alt = get_post_meta($id, '_wp_attachment_image_alt', true);
548 $thumb = wp_get_attachment_image_url($id, [48, 48]);
549 $nonce = wp_create_nonce("ariaat_update_alt_{$id}");
550 $filename = basename(get_attached_file($id));
551 $parent_id = $attachment->post_parent;
552 $attached_to = $parent_id ? get_post($parent_id) : null;
553 ?>
554
555 <tr data-id="<?php echo esc_attr($id); ?>">
556 <td><?php echo esc_html($id); ?></td>
557 <td><img src="<?php echo esc_url($thumb); ?>" width="48" height="48" /></td>
558 <td><input type="text" class="ariaat-alt" value="<?php echo esc_attr($alt); ?>" placeholder="no alt tag" /></td>
559 <td>
560 <button type="button" class="button button-small copy-filename" data-filename="<?php echo esc_attr($filename); ?>">
561 Copy to Alt
562 </button>
563 <br>
564 <?php echo esc_html($filename); ?>
565
566 </td>
567 <td>
568 <?php if ($attached_to) : ?>
569 <button type="button"
570 class="button button-small copy-title"
571 data-title="<?php echo esc_attr(get_the_title($attached_to->ID)); ?>">
572 Copy to Alt
573 </button>
574 <br>
575 <a href="<?php echo esc_url(get_edit_post_link($attached_to->ID)); ?>">
576 <?php echo esc_html(get_the_title($attached_to->ID)); ?>
577 </a> <small>(<?php echo esc_html( ucfirst(get_post_type($attached_to)) ); ?>)</small>
578
579 <?php else : ?>
580 <em>Not attached</em>
581 <?php endif; ?>
582 </td>
583 <td>
584 <button class="button ariaat-save-alt"
585 data-id="<?php echo esc_attr($id); ?>"
586 data-nonce="<?php echo esc_attr($nonce); ?>">
587 Save
588 </button>
589 </td>
590 </tr>
591 <?php endforeach; ?>
592 </tbody>
593 </table>
594
595 <?php if ($total_pages > 1) : ?>
596 <div class="ariaat-pagination">
597 <?php
598 $base_url = remove_query_arg(['paged']);
599 for ($i = 1; $i <= $total_pages; $i++) :
600 $url = add_query_arg('paged', $i, $base_url);
601 $active_class = ($i == $paged) ? 'active' : '';
602 printf(
603 '<a class="%s" href="%s">%d</a> ',
604 esc_attr($active_class),
605 esc_url($url),
606 $i
607 );
608 endfor;
609 ?>
610 </div>
611 <?php endif; ?>
612
613 <?php endif; ?>
614
615 </div>
616
617
618 <?php } else if ($active_tab === 'forms') {
619
620 $forms_output = '
621 <div class="section">
622 <h3><span class="dashicons dashicons-info"></span> Upgrade to PRO</h3>
623 <p>Get deep form scanning and automatic form fixes when you upgrade to the PRO plugin.<br>Works with all form plugins.</p>
624 <a style="margin-bottom:30px" href="https://wcagforwp.com/downloads/pro-plugin/" class="button button-primary" target="_blank">View PRO Plugin</a>
625 </div>
626 ';
627
628 echo apply_filters( 'ariaat_forms_page_output', $forms_output, $active_tab );
629
630 }
631
632 do_action( 'ariaat_before_admin_submit_button', $active_tab );
633
634 if ($active_tab !== 'forms' || ($active_tab === 'forms' && defined('ARIAAT_PRO_ACTIVE') ) )
635 submit_button();
636
637 ?>
638
639 </form>
640
641 </div>
642
643 </div>
644
645 <?php
646 }
647
648
649 private function get_aria_attributes() {
650 $attributes = [
651 'aria-describedby' => ['label' => 'aria-describedby'],
652 'aria-disabled' => ['label' => 'aria-disabled'],
653 'aria-expanded' => ['label' => 'aria-expanded'],
654 'aria-hidden' => ['label' => 'aria-hidden'],
655 'aria-label' => ['label' => 'aria-label'],
656 'aria-labelledby' => ['label' => 'aria-labelledby'],
657 ];
658
659 /**
660 * Filter the list of ARIA attributes available in the plugin.
661 *
662 * @param array $attributes The default set of ARIA attributes.
663 */
664 return apply_filters('ariaat_aria_attributes_options', $attributes);
665 }
666
667
668 private function get_role_options() {
669 $roles = [
670 'banner' => ['label' => 'banner'],
671 'button' => ['label' => 'button'],
672 'checkbox' => ['label' => 'checkbox'],
673 'complementary' => ['label' => 'complementary'],
674 'contentinfo' => ['label' => 'contentinfo'],
675 'form' => ['label' => 'form'],
676 'grid' => ['label' => 'grid'],
677 'heading' => ['label' => 'heading'],
678 'img' => ['label' => 'img'],
679 'link' => ['label' => 'link'],
680 'list' => ['label' => 'list'],
681 'listitem' => ['label' => 'listitem'],
682 'main' => ['label' => 'main'],
683 'navigation' => ['label' => 'navigation'],
684 'region' => ['label' => 'region'],
685 'row' => ['label' => 'row'],
686 'rowheader' => ['label' => 'rowheader'],
687 'search' => ['label' => 'search'],
688 'table' => ['label' => 'table'],
689 'textbox' => ['label' => 'textbox'],
690 ];
691
692 /**
693 * Filter the list of available roles.
694 *
695 * @param array $roles Array of role definitions.
696 */
697 return apply_filters('ariaat_roles_options', $roles);
698 }
699
700
701 public function sanitize_array($input) {
702 if (!is_array($input)) {
703 return sanitize_text_field($input);
704 }
705
706 foreach ($input as $key => $item) {
707 if (is_array($item)) {
708 foreach ($item as $subkey => $value) {
709 // Sanitize based on known keys
710 if (in_array($subkey, ['selector'], true)) {
711 // Allow basic CSS selectors: letters, numbers, dashes, underscores, dots, #, >, space, :
712 $input[$key][$subkey] = preg_replace('/[^a-zA-Z0-9\s\.\#\>\:\[\]\=\"~\+\-\*(),]/', '', $value);
713 } elseif (in_array($subkey, ['attribute', 'role'], true)) {
714 // Whitelist attribute/role names to be alphanumeric with optional dashes
715 $input[$key][$subkey] = preg_replace('/[^a-zA-Z0-9\-_]/', '', $value);
716 } else {
717 $input[$key][$subkey] = sanitize_text_field($value);
718 }
719 }
720 } else {
721 $input[$key] = sanitize_text_field($item);
722 }
723 }
724
725 return $input;
726 }
727
728
729
730 public function sanitize_menu_selection($input) {
731 $allowed_menus = array_keys($this->get_all_menus());
732
733 if( ! $input || ! array( $allowed_menus ) || ! array( $input ) )
734 return;
735 $selected = array_intersect($input, $allowed_menus);
736
737 return $selected;
738 }
739
740 public function sanitize_general_settings($input) {
741
742 $output = [];
743
744 // Language setting
745 $output['language'] = isset($input['language']) ? sanitize_text_field($input['language']) : '';
746
747 $output['skip_link'] = isset($input['skip_link']) ? sanitize_text_field($input['skip_link']) : '';
748
749 $output['enable_frontend_checker'] = isset($input['enable_frontend_checker']) ? '1' : '';
750 $output['focus_outline'] = isset($input['focus_outline']) ? '1' : '';
751 $output['fix_tabindex'] = isset($input['fix_tabindex']) ? '1' : '';
752 $output['make_viewport_scalable'] = isset($input['make_viewport_scalable']) ? '1' : '';
753
754 return $output;
755
756 }
757
758 public function sanitize_form_settings($input) {
759
760 $sanitized = [];
761
762 $checkboxes = [
763 'auto_generate_labels',
764 'fix_label_for',
765 'generate_aria_labels',
766 'fix_empty_buttons',
767 'remove_positive_tabindex',
768 'group_form_fields',
769 'clean_hidden_labels',
770 'placeholders_to_aria',
771 'fix_select_labels',
772 'fix_submit_labels',
773 ];
774
775 foreach ($checkboxes as $key) {
776 $sanitized[$key] = isset($input[$key]) && $input[$key] === '1' ? '1' : '0';
777 }
778
779 return $sanitized;
780
781 }
782
783
784 }
785
786 // Initialize the class
787 new ARIAAT_Admin();
788