Skip to content

Commit 1cbcfbf

Browse files
authored
Merge pull request #1345 from equalizedigital/release/1.37.0
Release v1.37.0
2 parents 0a04f4a + 6a52ebf commit 1cbcfbf

18 files changed

Lines changed: 17288 additions & 36064 deletions

.github/workflows/lint-php.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,10 @@ jobs:
7373
github-token: ${{ secrets.PUBLIC_REPO_ACCESS }}
7474

7575
- name: Lint against parse errors
76+
id: lint_with_cs2pr
7677
run: composer lint -- --checkstyle | cs2pr
78+
continue-on-error: true
79+
80+
- name: Lint against parse errors (fallback without cs2pr)
81+
if: steps.lint_with_cs2pr.outcome == 'failure'
82+
run: composer lint

accessibility-checker.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Plugin Name: Accessibility Checker
1111
* Plugin URI: https://a11ychecker.com
1212
* Description: Audit and check your website for accessibility before you hit publish. In-post accessibility scanner and guidance.
13-
* Version: 1.36.0
13+
* Version: 1.37.0
1414
* Requires PHP: 7.4
1515
* Author: Equalize Digital
1616
* Author URI: https://equalizedigital.com
@@ -36,12 +36,12 @@
3636

3737
// Current plugin version.
3838
if ( ! defined( 'EDAC_VERSION' ) ) {
39-
define( 'EDAC_VERSION', '1.36.0' );
39+
define( 'EDAC_VERSION', '1.37.0' );
4040
}
4141

4242
// Current database version.
4343
if ( ! defined( 'EDAC_DB_VERSION' ) ) {
44-
define( 'EDAC_DB_VERSION', '1.0.4' );
44+
define( 'EDAC_DB_VERSION', '1.0.5' );
4545
}
4646

4747
// Plugin Folder Path.

admin/class-ajax.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,10 @@ function ( $a, $b ) {
540540
$html .= ( true === $ignore_permission || ! empty( $ignore_comment ) ) ? '<label for="edac-details-rule-records-record-ignore-comment-' . $id . '">Comment</label><br>' : '';
541541
$html .= ( true === $ignore_permission || ! empty( $ignore_comment ) ) ? '<textarea rows="4" class="edac-details-rule-records-record-ignore-comment" id="edac-details-rule-records-record-ignore-comment-' . $id . '" ' . $ignore_comment_disabled . '>' . $ignore_comment . '</textarea>' : '';
542542

543-
if ( $ignore_global ) {
544-
$html .= ( true === $ignore_permission ) ? '<a href="' . admin_url( 'admin.php?page=accessibility_checker_ignored&tab=global' ) . '" class="edac-details-rule-records-record-ignore-global">Manage Globally Ignored</a>' : '';
543+
if ( $ignore_global && edac_is_pro() ) {
544+
$html .= ( true === $ignore_permission ) ? '<a href="' . admin_url( 'admin.php?page=accessibility_checker_ignored&tab=global' ) . '" class="edac-details-rule-records-record-ignore-global">' . __( 'Manage Globally Ignored', 'accessibility-checker' ) . '</a>' : '';
545545
} else {
546-
$html .= ( true === $ignore_permission ) ? '<button class="edac-details-rule-records-record-ignore-submit" data-id=' . $id . ' data-action=' . $ignore_action . ' data-type=' . $ignore_type . '>' . EDAC_SVG_IGNORE_ICON . ' <span class="edac-details-rule-records-record-ignore-submit-label">' . $ignore_submit_label . '<span></button>' : '';
546+
$html .= ( true === $ignore_permission ) ? '<button class="edac-details-rule-records-record-ignore-submit" data-id="' . $id . '" data-action="' . $ignore_action . '" data-type="' . $ignore_type . '">' . EDAC_SVG_IGNORE_ICON . ' <span class="edac-details-rule-records-record-ignore-submit-label">' . $ignore_submit_label . '</span></button>' : '';
547547
}
548548

549549
$html .= ( false === $ignore_permission && false === $ignore ) ? __( 'Your user account doesn\'t have permission to ignore this issue.', 'accessibility-checker' ) : '';

admin/class-frontend-highlight.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function get_issues( $post_id ) {
6161
$table_name = $wpdb->prefix . 'accessibility_checker';
6262
$post_id = (int) $post_id;
6363
$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.
64+
$results = $wpdb->get_results( $wpdb->prepare( 'SELECT id, rule, ignre, object, ruletype, selector, ancestry, xpath 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.
6565
if ( ! $results ) {
6666
return null;
6767
}
@@ -136,6 +136,9 @@ public function ajax() {
136136
$array['object'] = html_entity_decode( $result['object'], ENT_QUOTES | ENT_HTML5 );
137137
$array['id'] = $result['id'];
138138
$array['ignored'] = $result['ignre'];
139+
$array['selector'] = $result['selector'] ?? '';
140+
$array['ancestry'] = $result['ancestry'] ?? '';
141+
$array['xpath'] = $result['xpath'] ?? '';
139142

140143
$issues[] = $array;
141144

admin/class-insert-rule-data.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
/**
1313
* Class for inserting rule data into the database
1414
*
15+
* The unique identifier for issues changed in version 1.0.5 of the database schema.
16+
* Previously, issues were identified by: postid + rule + object + type + siteid
17+
* Now, issues are identified by: postid + rule + selector + type + siteid
18+
*
19+
* This change allows duplicate code objects (e.g., two empty paragraphs) to be
20+
* stored as separate issues when they appear in different locations on the page.
21+
* The selector field provides the unique location identifier for each issue.
22+
*
1523
* @since 1.10.0
1624
*/
1725
class Insert_Rule_Data {
@@ -73,15 +81,17 @@ public function insert( object $post, string $rule, string $ruletype, string $ru
7381
}
7482

7583
// Check if exists.
84+
// Use selector as the unique identifier instead of object to allow duplicate code objects
85+
// with different selectors (e.g., two empty paragraphs in different locations).
7686
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Using direct query for adding data to database, caching not required for one time operation.
7787
$results = $wpdb->get_results(
7888
$wpdb->prepare(
79-
'SELECT postid, ignre FROM %i where type = %s and postid = %d and rule = %s and object = %s and siteid = %d',
89+
'SELECT postid, ignre FROM %i where type = %s and postid = %d and rule = %s and selector = %s and siteid = %d',
8090
$table_name,
8191
$rule_data['type'],
8292
$rule_data['postid'],
8393
$rule_data['rule'],
84-
$rule_data['object'],
94+
$rule_data['selector'],
8595
$rule_data['siteid']
8696
),
8797
ARRAY_A
@@ -97,22 +107,23 @@ public function insert( object $post, string $rule, string $ruletype, string $ru
97107
}
98108

99109
// update existing record.
110+
// Use selector for WHERE clause instead of object to match on unique identifier.
100111
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Using direct query for adding data to database, caching not required for one time operation.
101112
$wpdb->query(
102113
$wpdb->prepare(
103-
'UPDATE %i SET recordcheck = %d, landmark = %s, landmark_selector = %s, selector = %s, ancestry = %s, xpath = %s, ignre = %d WHERE siteid = %d and postid = %d and rule = %s and object = %s and type = %s',
114+
'UPDATE %i SET recordcheck = %d, landmark = %s, landmark_selector = %s, object = %s, ancestry = %s, xpath = %s, ignre = %d WHERE siteid = %d and postid = %d and rule = %s and selector = %s and type = %s',
104115
$table_name,
105116
1,
106117
$rule_data['landmark'],
107118
$rule_data['landmark_selector'],
108-
$rule_data['selector'],
119+
$rule_data['object'],
109120
$rule_data['ancestry'],
110121
$rule_data['xpath'],
111122
$rule_data['ignre'],
112123
$rule_data['siteid'],
113124
$rule_data['postid'],
114125
$rule_data['rule'],
115-
$rule_data['object'],
126+
$rule_data['selector'],
116127
$rule_data['type']
117128
)
118129
);

admin/class-update-database.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,38 @@ public function edac_update_database() {
7474
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
7575
dbDelta( $sql );
7676

77+
// Run migration for selector-based unique identifiers if upgrading from older versions.
78+
if ( version_compare( $db_version, '1.0.5', '<' ) ) {
79+
$this->migrate_to_selector_based_unique_id();
80+
}
7781
}
7882

7983
// Update database version option.
8084
update_option( 'edac_db_version', sanitize_text_field( EDAC_DB_VERSION ) );
8185
}
86+
87+
/**
88+
* Migrate existing records to use selector-based unique identifiers.
89+
*
90+
* This migration handles records that were created before the selector field
91+
* was used as the unique identifier. Records with NULL selectors will have
92+
* a fallback identifier generated based on their ID to ensure uniqueness.
93+
*
94+
* @since 1.0.5
95+
* @return void
96+
*/
97+
private function migrate_to_selector_based_unique_id() {
98+
global $wpdb;
99+
$table_name = $wpdb->prefix . 'accessibility_checker';
100+
101+
// Find records with NULL or empty selectors and update them with a fallback value.
102+
// Using the record ID ensures each record has a unique selector for backward compatibility.
103+
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- One-time migration query.
104+
$wpdb->query(
105+
$wpdb->prepare(
106+
"UPDATE %i SET selector = CONCAT('legacy-id-', id) WHERE selector IS NULL OR selector = ''",
107+
$table_name
108+
)
109+
);
110+
}
82111
}

changelog.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
*** Accessibility Checker ***
22

3-
2025-15-22 - version 1.36.0
3+
2026-01-23 - version 1.37.0
4+
* Fix - Duplicate markup on the page can now be properly identified as an issue.
5+
* Fix - Restrict global ignore management link and fix button label span closure.
6+
* Fix - Update database schema to use selector as unique identifier for issues.
7+
* Enhanced - Frontend issue matching with stable selectors and DOM ordering.
8+
* Enhanced - Better handling of frontend highlighter positioning.
9+
* Improved - More accurate restoration of styles after deactivating them in frontend highlighter.
10+
* Improved - When closing frontend highlighter it won't re-render unless needed.
11+
12+
2025-12-15 - version 1.36.0
413
* Fix - passed tests percentage logic now accounts times no posts are scanned
514
* Fix - don't prevent scan speed saving when pro plugin is enabled.
615
* Add - new trigger for invalid alt text - "an image".

includes/classes/class-rest-api.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,7 @@ public function clear_issues_for_post( $request ) {
264264
*
265265
* @return string
266266
*/
267-
public function filter_js_validation_html( string $html, string $rule_id, array $violation ): string {
268-
// Add the selector to the violation message as empty paragraphs are almost always
269-
// duplicate html fragments. Adding the selector makes it unique, so it can be saved.
270-
if ( 'empty_paragraph_tag' === $rule_id ) {
271-
$html .= $violation['selector'][0]
272-
? '// {{ ' . $violation['selector'][0] . ' }}'
273-
: '';
274-
}
275-
267+
public function filter_js_validation_html( string $html, string $rule_id, array $violation ): string { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- the variable was used previously and will be used in future most likely.
276268
// Use just the opening <html> and closing </html> tag, prevents storing entire page as the affected code.
277269
if ( 'html-has-lang' === $rule_id || 'document-title' === $rule_id ) {
278270
$html = preg_replace( '/^.*(<html.*?>).*(<\/html>).*$/s', '$1...$2', $html );

0 commit comments

Comments
 (0)