• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

equalizedigital / accessibility-checker / 15881592242

25 Jun 2025 04:14PM UTC coverage: 29.05%. First build
15881592242

Pull #1031

github

web-flow
Merge 760ee3421 into a2033844f
Pull Request #1031: Release v1.26.0

3 of 5 new or added lines in 4 files covered. (60.0%)

1501 of 5167 relevant lines covered (29.05%)

1.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.89
/includes/classes/Fixes/FixesManager.php
1
<?php
2
/**
3
 * Manager class for fixes.
4
 *
5
 * @package Accessibility_Checker
6
 */
7

8
namespace EqualizeDigital\AccessibilityChecker\Fixes;
9

10
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\AddFileSizeAndTypeToLinkedFilesFix;
11
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\AddLabelToUnlabelledFormFieldsFix;
12
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\AddMissingOrEmptyPageTitleFix;
13
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\AddNewWindowWarningFix;
14
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\BlockPDFUploadsFix;
15
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\CommentSearchLabelFix;
16
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\HTMLLangAndDirFix;
17
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\RemoveTitleIfPrefferedAccessibleNameFix;
18
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\PreventLinksOpeningNewWindowFix;
19
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\SkipLinkFix;
20
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\TabindexFix;
21
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\LinkUnderline;
22
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\MetaViewportScalableFix;
23
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\FocusOutlineFix;
24
use EqualizeDigital\AccessibilityChecker\Fixes\Fix\ReadMoreAddTitleFix;
25
use EqualizeDigital\AccessibilityChecker\Admin\AdminPage\FixesPage;
26

27
/**
28
 * Manager class for fixes.
29
 *
30
 * @since 1.16.0
31
 */
32
class FixesManager {
33

34
        /**
35
         * The single instance of the class.
36
         *
37
         * @var FixesManager|null
38
         */
39
        private static $instance = null;
40

41
        /**
42
         * Whether the theme has the accessibility-ready tag.
43
         *
44
         * @var bool|null
45
         */
46
        private static $theme_is_accessibility_ready = null;
47

48
        /**
49
         * The fixes.
50
         *
51
         * @var array
52
         */
53
        private $fixes = [];
54

55
        /**
56
         * Private constructor to prevent direct instantiation.
57
         */
58
        private function __construct() {
59
                $this->maybe_enqueue_frontend_scripts();
6✔
60
                $this->maybe_enqueue_thickbox();
6✔
61

62
                self::$theme_is_accessibility_ready = self::is_theme_accessibility_ready();
6✔
63
        }
64

65
        /**
66
         * Maybe enqueue the thickbox script.
67
         *
68
         * This powers the modal that is used to display fix settings in the editor.
69
         */
70
        public function maybe_enqueue_thickbox() {
71
                add_action(
6✔
72
                        'admin_enqueue_scripts',
6✔
73
                        function () {
6✔
74
                                add_thickbox();
×
75
                        }
6✔
76
                );
6✔
77
        }
78

79
        /**
80
         * Get the single instance of the class.
81
         *
82
         * @return FixesManager
83
         */
84
        public static function get_instance() {
85
                if ( null === self::$instance ) {
6✔
86
                        self::$instance = new self();
6✔
87
                }
88
                return self::$instance;
6✔
89
        }
90

91
        /**
92
         * Maybe enqueue the frontend scripts.
93
         */
94
        private function maybe_enqueue_frontend_scripts() {
95

96
                if (
97
                        ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
6✔
98
                        ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
6✔
99
                        ( defined( 'DOING_CRON' ) && DOING_CRON ) ||
6✔
100
                        ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
6✔
101
                ) {
102
                        return;
×
103
                }
104

105
                // Consider adding this only if we can determine at least 1 of the fixes are enabled.
106
                add_action(
6✔
107
                        'wp_enqueue_scripts',
6✔
108
                        function () {
6✔
109
                                wp_enqueue_script( 'edac-frontend-fixes', EDAC_PLUGIN_URL . 'build/frontendFixes.bundle.js', [], EDAC_VERSION, true );
×
NEW
110
                                wp_set_script_translations( 'edac-frontend-fixes', 'accessibility-checker', plugin_dir_path( EDAC_PLUGIN_FILE ) . 'languages' );
×
111
                                wp_localize_script(
×
112
                                        'edac-frontend-fixes',
×
113
                                        'edac_frontend_fixes',
×
114
                                        apply_filters( 'edac_filter_frontend_fixes_data', [] )
×
115
                                );
×
116
                                do_action( 'edac_action_enqueue_frontend_fixes' );
×
117
                        }
6✔
118
                );
6✔
119
        }
120

121
        /**
122
         * Load the fixes.
123
         */
124
        private function load_fixes() {
125
                $fixes = apply_filters(
×
126
                        'edac_filter_fixes',
×
127
                        [
×
128
                                SkipLinkFix::class,
×
129
                                CommentSearchLabelFix::class,
×
130
                                HTMLLangAndDirFix::class,
×
131
                                TabindexFix::class,
×
132
                                RemoveTitleIfPrefferedAccessibleNameFix::class,
×
133
                                LinkUnderline::class,
×
134
                                MetaViewportScalableFix::class,
×
135
                                PreventLinksOpeningNewWindowFix::class,
×
136
                                FocusOutlineFix::class,
×
137
                                BlockPDFUploadsFix::class,
×
138
                                AddFileSizeAndTypeToLinkedFilesFix::class,
×
139
                                AddMissingOrEmptyPageTitleFix::class,
×
140
                                AddLabelToUnlabelledFormFieldsFix::class,
×
141
                                AddNewWindowWarningFix::class,
×
142
                        ]
×
143
                );
×
144
                foreach ( $fixes as $fix ) {
×
145
                        if ( is_subclass_of( $fix, '\EqualizeDigital\AccessibilityChecker\Fixes\FixInterface' ) ) {
×
146
                                if ( ! isset( $this->fixes[ $fix::get_slug() ] ) ) {
×
147
                                        $this->fixes[ $fix::get_slug() ] = ( new $fix() );
×
148
                                }
149
                        }
150
                }
151
        }
152

153
        /**
154
         * Get a fix by its slug.
155
         *
156
         * @param string $slug The fix slug.
157
         *
158
         * @return FixInterface|null
159
         */
160
        public function get_fix( $slug ) {
161
                return isset( $this->fixes[ $slug ] ) ? $this->fixes[ $slug ] : null;
×
162
        }
163

164
        /**
165
         * Get the fixes settings.
166
         *
167
         * Returns an array of all the fix settings and their values along with a pro or not flag.
168
         *
169
         * @return array
170
         */
171
        public function get_fixes_settings() {
172
                $fixes_array = [];
6✔
173
                foreach ( $this->fixes as $fix ) {
6✔
174

175
                        $fields = [];
4✔
176
                        foreach ( $fix->get_fields_array() as $field_slug => $field ) {
4✔
177
                                $fields[ $field_slug ] = get_option( $field_slug, $field['default'] ?? 0 );
4✔
178
                        }
179

180
                        $fixes_array[ $fix::get_slug() ] = [
4✔
181
                                'fields' => $fields,
4✔
182
                                'is_pro' => isset( $fix->is_pro ) ? $fix->is_pro : false,
4✔
183
                        ];
4✔
184
                }
185
                return $fixes_array;
6✔
186
        }
187

188
        /**
189
         * Register the fixes.
190
         */
191
        public function register_fixes() {
192
                $this->load_fixes();
×
193

194
                foreach ( $this->fixes as $fix ) {
×
195
                        $fix->register();
×
196
                        $this->maybe_run_fix( $fix );
×
197
                }
198
        }
199

200
        /**
201
         * Maybe run a fix depending on current context.
202
         *
203
         * @param FixInterface $fix The fix to maybe run.
204
         */
205
        public function maybe_run_fix( $fix ) {
206
                if ( 'backend' === $fix::get_type() && is_admin() ) {
×
207
                        $fix->run();
×
208
                } elseif ( 'frontend' === $fix::get_type() && ! is_admin() ) {
×
209
                        $fix->run();
×
210
                } elseif ( 'everywhere' === $fix::get_type() ) {
×
211
                        $fix->run();
×
212
                }
213
        }
214

215
        /**
216
         * Check if the theme is accessibility ready.
217
         *
218
         * True if the theme has the tag, false otherwise.
219
         *
220
         * @return bool
221
         */
222
        public static function is_theme_accessibility_ready() {
223
                if ( null !== self::$theme_is_accessibility_ready ) {
6✔
224
                        return self::$theme_is_accessibility_ready;
6✔
225
                }
226

227
                $theme = wp_get_theme();
×
228
                $tags  = $theme->get( 'Tags' );
×
229

230
                self::$theme_is_accessibility_ready = is_array( $tags ) && in_array( 'accessibility-ready', $tags, true );
×
231
                return self::$theme_is_accessibility_ready;
×
232
        }
233

234
        /**
235
         * Maybe show a notice if the theme is accessibility-ready.
236
         */
237
        public static function maybe_show_accessibility_ready_conflict_notice() {
238
                if ( self::is_theme_accessibility_ready() ) {
×
239
                        ?>
240
                        <span class="edac-notice--accessibility-ready-conflict">
×
241
                                <?php esc_html_e( 'Note: This setting is not recommended for themes that are already accessibility-ready.', 'accessibility-checker' ); ?>
×
242
                        </span>
×
243
                        <?php
×
244
                }
245
        }
246

247
        /**
248
         * Register the rest routes.
249
         *
250
         * @return void
251
         */
252
        public function register_rest_routes() {
253
                register_rest_route(
×
254
                        'edac/v1',
×
255
                        '/fixes',
×
256
                        [
×
257
                                'methods'             => 'GET',
×
258
                                'callback'            => [ $this, 'get_fixes' ],
×
259
                                'permission_callback' => function () {
×
260
                                        return current_user_can( apply_filters( 'edac_filter_settings_capability', 'manage_options' ) );
×
261
                                },
×
262
                        ]
×
263
                );
×
264

265
                register_rest_route(
×
266
                        'edac/v1',
×
267
                        '/fixes/update',
×
268
                        [
×
269
                                'methods'             => 'POST',
×
270
                                'callback'            => [ $this, 'update_fix_settings' ],
×
271
                                'permission_callback' => function () {
×
272
                                        return current_user_can( apply_filters( 'edac_filter_settings_capability', 'manage_options' ) );
×
273
                                },
×
274
                        ]
×
275
                );
×
276
        }
277

278
        /**
279
         * Handle the request to set a fix.
280
         *
281
         * @param \WP_REST_Request $request The request recieved through a rest call.
282
         *
283
         * @return \WP_Error|\WP_HTTP_Response|\WP_REST_Response
284
         */
285
        public function update_fix_settings( $request ) {
286
                // get body of the request.
287
                $body = $request->get_json_params();
×
288

289
                // loop through body and find fixes for those items.
290
                foreach ( $body as $rule_slug => $settings ) {
×
291
                        $fix        = $this->get_fix( $rule_slug );
×
292
                        $fix_fields = $fix->get_fields_array();
×
293
                        if ( ! $fix ) {
×
294
                                return new \WP_Error( 'edac_fix_not_found', esc_html__( 'Fix not found', 'accessibility-checker' ), [ 'status' => 404 ] );
×
295
                        }
296

297
                        foreach ( $settings as $setting => $value ) {
×
298
                                $sanitizer = isset( $fix_fields[ $setting ]['sanitize_callback'] ) ? $fix_fields[ $setting ]['sanitize_callback'] : [ FixesPage::class, 'sanitize_' . $fix_fields[ $setting ]['type'] ];
×
299
                                if ( ! $sanitizer || ! is_callable( $sanitizer ) ) {
×
300
                                        // no sanitizer, do not save.
301
                                        continue;
×
302
                                }
303
                                update_option( $setting, $sanitizer( $value ) );
×
304
                        }
305
                }
306

307
                return rest_ensure_response( [ 'enabled' => $enabled ] );
×
308
        }
309
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc