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

equalizedigital / accessibility-checker / 17471903338

04 Sep 2025 05:29PM UTC coverage: 59.267% (+0.01%) from 59.256%
17471903338

push

github

web-flow
Merge pull request #1220 from equalizedigital/william/tweak/some-request-handlers-and-callbacks

Use a specifically named ajax request for frontend highlighter

4 of 68 new or added lines in 4 files covered. (5.88%)

4 existing lines in 2 files now uncovered.

4122 of 6955 relevant lines covered (59.27%)

3.52 hits per line

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

0.0
/admin/class-frontend-highlight.php
1
<?php
2
/**
3
 * Accessibility Checker plugin file.
4
 *
5
 * @package Accessibility_Checker
6
 */
7

8
namespace EDAC\Admin;
9

10
use EqualizeDigital\AccessibilityChecker\Admin\AdminPage\FixesPage;
11
use EqualizeDigital\AccessibilityChecker\Fixes\FixesManager;
12

13
/**
14
 * Class Frontend_Highlight
15
 *
16
 * A class that handles AJAX requests for frontend highlighting of accessibility issues.
17
 */
18
class Frontend_Highlight {
19

20
        /**
21
         * Constructor function for the class.
22
         */
23
        public function __construct() {
24
        }
×
25

26
        /**
27
         * Initialize hooks.
28
         *
29
         * @return void
30
         */
31
        public function init_hooks() {
32
                add_action( 'wp_ajax_edac_frontend_highlight_ajax', [ $this, 'ajax' ] );
×
33

34
                /**
35
                 * Filter the visibility of the frontend highlighter.
36
                 *
37
                 * 'edac_filter_frontend_highlighter_visibility' is a filter that can be used
38
                 * to allow users without edit permissions on the post to see the frontend
39
                 * highlighter. You can use the filter to perform additional permission checks
40
                 * on who can see it.
41
                 *
42
                 * @since 1.14.0
43
                 *
44
                 * @param bool $visibility The visibility of the frontend highlighter. Default is false, return true to show the frontend highlighter.
45
                 */
46
                if ( apply_filters( 'edac_filter_frontend_highlighter_visibility', false ) ) {
×
47
                        // A nopriv endpoint allows logged-out users to access the endpoint.
48
                        add_action( 'wp_ajax_nopriv_edac_frontend_highlight_ajax', [ $this, 'ajax' ] );
×
49
                }
50
        }
51

52
        /**
53
         * Retrieves accessibility issues for a specific post.
54
         *
55
         * @param int $post_id The ID of the post.
56
         *
57
         * @return array|null The array of issues or null if no issues found.
58
         */
59
        public function get_issues( $post_id ) {
60
                global $wpdb;
×
61
                $table_name = $wpdb->prefix . 'accessibility_checker';
×
62
                $post_id    = (int) $post_id;
×
63
                $siteid     = get_current_blog_id();
×
64
                $results    = $wpdb->get_results( $wpdb->prepare( 'SELECT id, rule, ignre, object, ruletype FROM %i where postid = %d and siteid = %d', $table_name, $post_id, $siteid ), ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Safe variable used for table name.
×
65
                if ( ! $results ) {
×
66
                        return null;
×
67
                }
68

69
                return Helpers::filter_results_to_only_active_rules( $results );
×
70
        }
71

72
        /**
73
         * AJAX handler function for frontend highlighting requests.
74
         */
75
        public function ajax() {
76

NEW
77
                if ( ! check_ajax_referer( 'frontend-highlighter', 'nonce', false ) ) {
×
NEW
78
                        wp_send_json_error( new \WP_Error( '-1', __( 'Permission Denied', 'accessibility-checker' ) ) );
×
79
                }
80

81
                if ( ! isset( $_REQUEST['post_id'] ) ) {
×
82
                        $error = new \WP_Error( '-2', __( 'The id value was not set', 'accessibility-checker' ) );
×
83
                        wp_send_json_error( $error );
×
84
                }
85

86
                $post_id = isset( $_REQUEST['post_id'] ) ? (int) $_REQUEST['post_id'] : 0;
×
NEW
87
                $post    = get_post( $post_id );
×
NEW
88
                if ( ! $post ) {
×
NEW
89
                        wp_send_json_error( new \WP_Error( '-4', __( 'Post not found', 'accessibility-checker' ) ) );
×
90
                }
91

92
                // Check if the user has permission to view this post.
NEW
93
                if ( is_user_logged_in() ) {
×
94
                        // For authenticated users, use read_post capability.
NEW
95
                        if ( ! current_user_can( 'read_post', $post_id ) ) {
×
NEW
96
                                wp_send_json_error( new \WP_Error( '-1', __( 'Permission Denied', 'accessibility-checker' ) ) );
×
97
                        }
NEW
98
                } elseif ( apply_filters( 'edac_filter_frontend_highlighter_visibility', false ) ) {
×
99
                        // For unauthenticated users, only allow access to publicly viewable posts.
NEW
100
                        if ( ! is_post_publicly_viewable( $post ) ) {
×
NEW
101
                                wp_send_json_error( new \WP_Error( '-1', __( 'Permission Denied', 'accessibility-checker' ) ) );
×
102
                        }
103
                } else {
104
                        // Shouldn't ever reach this point but error just in case.
NEW
105
                        wp_send_json_error( new \WP_Error( '-1', __( 'Permission Denied', 'accessibility-checker' ) ) );
×
106
                }
107

UNCOV
108
                $results = $this->get_issues( $post_id );
×
109

110
                if ( ! $results ) {
×
NEW
111
                        wp_send_json_error( new \WP_Error( '-3', __( 'Issue query returned no results', 'accessibility-checker' ) ) );
×
112
                }
113

114
                $rules = edac_register_rules();
×
115

116
                $issues = [];
×
117
                $fixes  = [];
×
118
                foreach ( $results as $result ) {
×
119
                        $array = [];
×
120
                        $rule  = edac_filter_by_value( $rules, 'slug', $result['rule'] );
×
121

122
                        // When rules are filtered out, they are not in the rules array and this can be empty. Skip when the rule
123
                        // is empty to avoid php warnings and passing null values to the frontend highlighter.
124
                        if ( ! $rule ) {
×
125
                                continue;
×
126
                        }
127

128
                        $rule_type = ( true === (bool) $result['ignre'] ) ? 'ignored' : $rule[0]['rule_type'];
×
129

130
                        $array['rule_type']  = $rule_type;
×
131
                        $array['slug']       = $rule[0]['slug'];
×
132
                        $array['rule_title'] = $rule[0]['title'];
×
133
                        $array['summary']    = $rule[0]['summary'];
×
134
                        $array['how_to_fix'] = wp_kses_post( $rule[0]['how_to_fix'] ?? '' );
×
135
                        $array['link']       = edac_link_wrapper( $rule[0]['info_url'], 'frontend-highlighter', $rule[0]['slug'], false );
×
136
                        $array['object']     = html_entity_decode( $result['object'], ENT_QUOTES | ENT_HTML5 );
×
137
                        $array['id']         = $result['id'];
×
138
                        $array['ignored']    = $result['ignre'];
×
139

140
                        $issues[] = $array;
×
141

142
                        if ( ! isset( $fixes[ $rule[0]['slug'] ] ) ) {
×
143
                                $fixes_for_rule = $rule[0]['fixes'] ?? [];
×
144

145
                                foreach ( $fixes_for_rule as $fix_for_rule ) {
×
146
                                        $fix = FixesManager::get_instance()->get_fix( $fix_for_rule );
×
147
                                        if ( $fix && method_exists( $fix, 'get_fields_array' ) ) {
×
148
                                                $fixes[ $rule[0]['slug'] ] = isset( $fixes[ $rule[0]['slug'] ] ) ? array_merge( $fixes[ $rule[0]['slug'] ], $fix->get_fields_array() ) : $fix->get_fields_array();
×
149
                                        }
150
                                }
151
                        }
152
                }
153

154
                if ( ! $issues ) {
×
NEW
155
                        wp_send_json_error( new \WP_Error( '-5', __( 'Object query returned no results', 'accessibility-checker' ) ) );
×
156
                }
157

158
                // if we have fixes then create fields for each of the groups.
159
                if ( ! empty( $fixes ) ) {
×
160
                        foreach ( $fixes as $key => $fix ) {
×
161
                                // count the number of fields in the fix.
162
                                $fields_count      = count( $fix );
×
163
                                $itteration        = 0;
×
164
                                $fix_fields_markup = '';
×
165
                                foreach ( $fix as $index => $field ) {
×
166
                                        ++$itteration;
×
167
                                        $field_type = $field['type'] ?? 'checkbox';
×
168
                                        ob_start();
×
169
                                        if ( isset( $field['group_name'] ) ) {
×
170
                                                // if this is anything other than the first field in the group then close the fieldset.
171
                                                if ( 1 !== $itteration ) {
×
172
                                                        ?>
173
                                                        </fieldset>
×
174
                                                        <?php
×
175
                                                }
176
                                                ?>
177
                                                <fieldset>
×
178
                                                <legend><h3 class="title"><?php echo esc_html( $field['group_name'] ); ?></h3></legend>
×
179
                                                <?php
180
                                        }
181
                                        FixesPage::{$field_type}(
×
182
                                                array_merge(
×
183
                                                        [
×
184
                                                                'name'     => $index,
×
185
                                                                'location' => 'frontend-highlighter',
×
186
                                                        ],
×
187
                                                        $field
×
188
                                                )
×
189
                                        );
×
190
                                        if ( $fields_count === $itteration ) {
×
191
                                                ?>
192
                                                </fieldset>
×
193
                                                <?php
×
194
                                        }
195
                                        $fix_fields_markup .= ob_get_clean();
×
196
                                }
197
                                $fixes[ $key ]['fields'] = $fix_fields_markup . PHP_EOL . '</fieldset>';
×
198
                        }
199
                }
200

201
                wp_send_json_success(
×
202
                        wp_json_encode(
×
203
                                [
×
204
                                        'issues' => $issues,
×
205
                                        'fixes'  => $fixes,
×
206
                                ]
×
207
                        )
×
208
                );
×
209
        }
210
}
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