PluginProbe
Accessibility Tool Kit: WP Accessibility checker plugin for WCAG, Section 508, ADA, EAA Compliance / 1.2
Accessibility Tool Kit: WP Accessibility checker plugin for WCAG, Section 508, ADA, EAA Compliance v1.2
2.2.1 2.2.0 2.1.2 1.1.1 1.1.2 1.1.3 1.2 1.2.1 1.2.2 1.2.3 1.2.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 trunk 1.0.0 All 31 releases
accessibility-plus / accessibility.php

accessibility.php in Accessibility Tool Kit: WP Accessibility checker plugin for WCAG, Section 508, ADA, EAA Compliance 1.2, at accessibility.php

323 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: AccessibilityPlus
4 Plugin URI:
5 Description: Improve pagespeed insight or lighthouse accessibility scores by fixing recommended issues.
6 Version: 1.2
7 Author: easywpstuff
8 Author URI: https://easywpstuff.com
9 License: GNU General Public License v2 or later
10 */
11
12
13 require_once('vendor/autoload.php');
14
15 // include option
16
17 include_once('inc/options.php');
18
19
20 // Name: Form elements do not have associated labels
21 function easywpstuff_assesplus_check_input_labels($html) {
22 if (empty($html)) {
23 return $html;
24 }
25
26 $dom = new \DiDom\Document($html);
27 $inputs = $dom->find('input');
28
29 foreach ($inputs as $input) {
30 $parent = $input->parent();
31 if ($parent && $parent->tag !== 'label') {
32 if (!$input->hasAttribute('id') && !$input->hasAttribute('placeholder') && !$input->hasAttribute('aria-label') && !$input->hasAttribute('aria-labelledby')) {
33 $inputType = $input->getAttribute('type');
34 if ($inputType && !in_array($inputType, ['hidden', 'button', 'submit'])) {
35 $input->setAttribute('aria-label', $inputType);
36 }
37 }
38 }
39 }
40
41 return $dom->html();
42 }
43
44 // Links do not have a discernible name
45 function easywpstuff_assesplus_add_aria_labels_to_links($html) {
46 // Remove closing tags for img and source elements to avoid parsing issues
47 $html = str_replace('</img>', '', $html);
48 $html = str_replace('</source>', '', $html);
49
50 $dom = new \DiDom\Document($html);
51 if (empty($dom)) {
52 return $dom;
53 }
54
55 $links = $dom->find('a');
56 $filteredHeaderLinks = array_filter($dom->find('header a'), function ($link) {
57 return $link->has('i') || ($link->has('span') && trim($link->text()));
58 });
59
60 $links = array_merge($links, $filteredHeaderLinks);
61
62 foreach ($links as $link) {
63 $span = $link->first('span');
64 $div = $link->first('div');
65 $spnimg = $link->first('img');
66
67 if ($span && !$div && !$spnimg && !$link->hasAttribute('aria-label')) {
68 $span_text = trim($span->text());
69 if ($span_text) {
70 $link->setAttribute('aria-label', $span_text);
71 }
72 }
73
74 $spanimg = $link->first('span img');
75 if ($spanimg && !$link->hasAttribute('aria-label') && (!$spanimg->hasAttribute('alt') || !$spanimg->hasAttribute('title'))) {
76 $link->setAttribute('aria-label', 'image');
77 }
78
79 if (!trim($link->text()) && !$link->hasAttribute('aria-label')) {
80 $child_elements = $link->find('*');
81 if (empty($child_elements)) {
82 $link->setAttribute('aria-label', 'link');
83 } else {
84 $icon = $link->first('i');
85 if ($icon) {
86 $link->setAttribute('aria-label', 'icon');
87 } else {
88 $img = $link->first('img');
89 if ($img && !$img->hasAttribute('alt')) {
90 $link->setAttribute('aria-label', 'image');
91 } else if ($img && (!$img->hasAttribute('alt') || !$img->hasAttribute('title'))) {
92 $link->setAttribute('aria-label', 'image');
93 }
94 $svg = $link->first('svg');
95 if ($svg) {
96 $link->setAttribute('aria-label', 'svg');
97 }
98 if (!$svg && !$img) {
99 $link->setAttribute('aria-label', 'link');
100 }
101 }
102 }
103 }
104 }
105
106 return $dom->html();
107 }
108
109
110 //Buttons do not have an accessible name
111
112 function easywpstuff_assesplus_add_aria_labels_to_buttons($html) {
113 $dom = new \DiDom\Document($html);
114 $buttons = $dom->find('button');
115
116 foreach ($buttons as $button) {
117 if (!trim($button->text()) && !$button->hasAttribute('aria-label')) {
118 $child_elements = $button->find('*');
119 if (empty($child_elements)) {
120 $button->setAttribute('aria-label', 'button');
121 } else {
122 $button->setAttribute('aria-label', 'button');
123 }
124 }
125 if (!$button->hasAttribute('aria-label')) {
126 $svg = $button->first('svg');
127 $path = $button->first('path');
128 $span = $button->first('span');
129
130 if ($svg && $path) {
131 $button->setAttribute('aria-label', 'button');
132 } elseif ($span) {
133 $span_text = trim($span->text());
134 if ($span_text) {
135 $button->setAttribute('aria-label', $span_text);
136 }
137 }
138 }
139 }
140
141 return $dom->html();
142 }
143
144 //[user-scalable="no"] is used in the <meta name="viewport"> element or the [maximum-scale] attribute is less than 5.
145 function easywpstuff_assesplus_modify_viewport_meta_tag($html) {
146 $dom = new \DiDom\Document($html);
147 $viewport_meta_tag = $dom->first('meta[name=viewport]');
148
149 if ($viewport_meta_tag) {
150 $content = $viewport_meta_tag->getAttribute('content');
151
152 $content = preg_replace('/,\s*user-scalable=(?:no|0)/', '', $content);
153
154 if (preg_match('/maximum-scale=([^,\s]*)/', $content, $matches)) {
155 $maximum_scale = (float) $matches[1];
156 if ($maximum_scale < 2) {
157 $content = preg_replace('/maximum-scale=[^,\s]*/', 'maximum-scale=2', $content);
158 }
159 } else {
160 $content .= ', maximum-scale=2';
161 }
162
163 $viewport_meta_tag->setAttribute('content', $content);
164 }
165
166 return $dom->html();
167 }
168
169 function easywpstuff_assesplus_add_aria_labels_to_headers($html) {
170 $dom = new \DiDom\Document($html);
171 foreach ($dom->find('header div') as $div) {
172 $role = $div->getAttribute('role');
173 if ($role === 'link' && !$div->hasAttribute('aria-label')) {
174 $div->setAttribute('aria-label', 'link');
175 }
176 if ($role === 'button' && !$div->hasAttribute('aria-label')) {
177 $div->setAttribute('aria-label', 'button');
178 }
179 if ($role === 'menuitem' && !$div->hasAttribute('aria-label')) {
180 $div->setAttribute('aria-label', 'menuitem');
181 }
182 }
183
184 return $dom->html();
185 }
186
187 // <frame> or <iframe> elements do not have a title
188 function easywpstuff_assesplus_booster_add_to_iframes($html) {
189 $dom = new \DiDom\Document($html);
190 foreach ($dom->find('iframe') as $iframe) {
191 if (!$iframe->hasAttribute('title')) {
192 $iframe->setAttribute('title', 'iframe');
193 }
194 }
195
196 return $dom->html();
197 }
198
199 //Links are not crawlable
200 function easywpstuff_assesplus_addHashToBlankLinks($html) {
201 $dom = new \DiDom\Document($html);
202 $blankLinks = $dom->find('a');
203 foreach ($blankLinks as $link) {
204 $href = $link->getAttribute('href');
205 if (!$href || $href === '') {
206 $link->setAttribute('href', '#');
207 }
208 if ($href === 'javascript: void(0);' || $href === 'javascript:void(0);') {
209 $link->setAttribute('href', '#');
210 }
211 }
212
213 return $dom->html();
214 }
215
216 //ARIA progressbar elements do not have accessible names.
217 function easywpstuff_assesplus_add_aria_label_to_progressbar($html) {
218 $dom = new \DiDom\Document($html);
219 foreach ($dom->find('[role=progressbar]') as $element) {
220 $has_label = $element->hasAttribute('aria-label') ||
221 $element->hasAttribute('aria-labelledby') ||
222 $element->hasAttribute('title');
223
224 if (!$has_label || (empty($element->getAttribute('aria-label')) && empty($element->getAttribute('aria-labelledby')) && empty($element->getAttribute('title')))) {
225 $element->setAttribute('aria-label', 'progressbar');
226 }
227 }
228
229 return $dom->html();
230 }
231 //Image elements do not have [alt] attributes
232 function easywpstuff_assesplus_addAltToImg($html) {
233 $dom = new \DiDom\Document($html);
234 $imgs = $dom->find('img');
235 foreach ($imgs as $img) {
236 if (!$img->getAttribute('alt')) {
237 $alt = '';
238 if ($img->hasAttribute('title')) {
239 $alt = $img->getAttribute('title');
240 } else {
241 $src = $img->getAttribute('src');
242 $alt = basename($src);
243 $alt = preg_replace('/\d+/', '', $alt);
244 $alt = preg_replace('/\.[^.]+$/', '', $alt);
245 $alt = str_replace('-', ' ', $alt);
246 $alt = str_replace('_', ' ', $alt);
247 }
248 $img->setAttribute('alt', $alt);
249 }
250 }
251 return $dom->html();
252 }
253
254
255 // buffer if option is enabled
256 function easywpstuff_assesplus_bstr_template_redirect( $buffer ) {
257
258 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_booster_field_no_labels'] == 1 ) {
259 $buffer = easywpstuff_assesplus_check_input_labels( $buffer );
260 }
261
262 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_booster_field_no_discernible_name'] == 1 ) {
263
264 $buffer = easywpstuff_assesplus_add_aria_labels_to_links( $buffer );
265 }
266
267 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_booster_field_no_accessible_name'] == 1 ) {
268
269 $buffer = easywpstuff_assesplus_add_aria_labels_to_buttons( $buffer );
270 }
271
272 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_booster_field_viewport_meta_tag'] == 1 ) {
273 $buffer = easywpstuff_assesplus_modify_viewport_meta_tag( $buffer );
274 }
275
276 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_booster_field_menuitem_accessible'] == 1 ) {
277 $buffer = easywpstuff_assesplus_add_aria_labels_to_headers( $buffer );
278 }
279
280 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_booster_field_iframe_title_tag'] == 1 ) {
281 $buffer = easywpstuff_assesplus_booster_add_to_iframes( $buffer );
282 }
283
284 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_add_aria_label_to_progressbar'] == 1 ) {
285 $buffer = easywpstuff_assesplus_add_aria_label_to_progressbar( $buffer );
286 }
287
288 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_links_not_crawlable'] == 1 ) {
289 $buffer = easywpstuff_assesplus_addHashToBlankLinks( $buffer );
290 }
291
292 if ( get_option( 'easywpstuff_assesplus_booster_options' )['easywpstuff_assesplus_img_donot_alt'] == 1 ) {
293 $buffer = easywpstuff_assesplus_addAltToImg( $buffer );
294 }
295
296 return $buffer;
297 }
298
299 //add_action( 'template_redirect', 'easywpstuff_assesplus_bstr_template_redirect', 99 );
300
301 // run the function
302 add_action( 'template_redirect', 'easywpstuff_assesplus_loader', 99 );
303 function easywpstuff_assesplus_loader() {
304
305 ob_start( 'easywpstuff_assesplus_bstr_template_redirect');
306
307 }
308
309 // added settings link
310 function easywpstuff_assesplus_bs_settings_link($links) {
311 $settings_link = '<a href="' . admin_url( 'options-general.php?page=accessibilityplus' ) . '">' . __( 'Settings' ) . '</a>';
312 array_unshift( $links, $settings_link );
313 return $links;
314 }
315 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'easywpstuff_assesplus_bs_settings_link' );
316
317 // enqueue admin styles on option page
318 function easywpstuff_assesplus_admin_enqueue_plugin_styles( $hook ) {
319 if ( 'settings_page_accessibilityplus' === $hook ) {
320 wp_enqueue_style( 'lhbooster-styles', plugin_dir_url( __FILE__ ) . 'assets/style.css' );
321 }
322 }
323 add_action( 'admin_enqueue_scripts', 'easywpstuff_assesplus_admin_enqueue_plugin_styles' );