Skip to content

Commit b83dc20

Browse files
authored
Merge pull request #1066 from equalizedigital/william/integration/merge-recent-frontend-highlighter-and-scanner-change-branches
Integration - merge recent frontend highlighter and scanner change branches
2 parents a7933b4 + f364662 commit b83dc20

7 files changed

Lines changed: 257 additions & 93 deletions

File tree

admin/class-insert-rule-data.php

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@ class Insert_Rule_Data {
2121
*
2222
* @since 1.10.0
2323
*
24-
* @param object $post The post object. Must have a valid ID.
25-
* @param string $rule The rule.
26-
* @param string $ruletype The rule type.
27-
* @param string $rule_obj The object.
28-
* @param string|null $landmark The landmark type (main, header, footer, nav), optional.
24+
* @param object $post The post object. Must have a valid ID.
25+
* @param string $rule The rule.
26+
* @param string $ruletype The rule type.
27+
* @param string $rule_obj The object.
28+
* @param string|null $landmark The landmark type (main, header, footer, nav), optional.
2929
* @param string|null $landmark_selector The landmark selector, optional.
30+
* @param array $selectors An array of selectors that point to the object, optional.
3031
*
3132
* @return void|int|\WP_Error The ID of the inserted record, void if no
3233
* record was inserted or a WP_Error if the insert failed.
3334
*/
34-
public function insert( object $post, string $rule, string $ruletype, string $rule_obj, ?string $landmark = null, ?string $landmark_selector = null ) {
35+
public function insert( object $post, string $rule, string $ruletype, string $rule_obj, ?string $landmark = null, ?string $landmark_selector = null, array $selectors = [] ) {
3536

3637
if ( ! isset( $post->ID, $post->post_type )
3738
|| empty( $rule )
@@ -51,6 +52,9 @@ public function insert( object $post, string $rule, string $ruletype, string $ru
5152
'type' => $post->post_type,
5253
'landmark' => $landmark,
5354
'landmark_selector' => $landmark_selector,
55+
'selector' => $selectors['selector'][0] ?? null,
56+
'ancestry' => $selectors['ancestry'][0] ?? null,
57+
'xpath' => $selectors['xpath'][0] ?? null,
5458
'rule' => $rule,
5559
'ruletype' => $ruletype,
5660
'object' => esc_attr( $rule_obj ),
@@ -96,9 +100,14 @@ public function insert( object $post, string $rule, string $ruletype, string $ru
96100
// 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.
97101
$wpdb->query(
98102
$wpdb->prepare(
99-
'UPDATE %i SET recordcheck = %d, ignre = %d WHERE siteid = %d and postid = %d and rule = %s and object = %s and type = %s',
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',
100104
$table_name,
101105
1,
106+
$rule_data['landmark'],
107+
$rule_data['landmark_selector'],
108+
$rule_data['selector'],
109+
$rule_data['ancestry'],
110+
$rule_data['xpath'],
102111
$rule_data['ignre'],
103112
$rule_data['siteid'],
104113
$rule_data['postid'],
@@ -134,6 +143,9 @@ public function insert( object $post, string $rule, string $ruletype, string $ru
134143
'type' => sanitize_text_field( $rule_data['type'] ),
135144
'landmark' => isset( $rule_data['landmark'] ) ? sanitize_text_field( $rule_data['landmark'] ) : null,
136145
'landmark_selector' => isset( $rule_data['landmark_selector'] ) ? sanitize_text_field( $rule_data['landmark_selector'] ) : null,
146+
'selector' => sanitize_text_field( $rule_data['selector'] ?? '' ),
147+
'ancestry' => sanitize_text_field( $rule_data['ancestry'] ?? '' ),
148+
'xpath' => sanitize_text_field( $rule_data['xpath'] ?? '' ),
137149
'rule' => sanitize_text_field( $rule_data['rule'] ),
138150
'ruletype' => sanitize_text_field( $rule_data['ruletype'] ),
139151
'object' => esc_attr( $rule_data['object'] ),

admin/class-update-database.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public function edac_update_database() {
5050
type text NOT NULL,
5151
landmark varchar(20) NULL,
5252
landmark_selector text NULL,
53+
selector text NULL,
54+
ancestry text NULL,
55+
xpath text NULL,
5356
rule text NOT NULL,
5457
ruletype text NOT NULL,
5558
object mediumtext NOT NULL,

includes/classes/class-enqueue-frontend.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,17 @@ public static function maybe_enqueue_frontend_highlighter() {
9797
'edac-frontend-highlighter-app',
9898
'edacFrontendHighlighterApp',
9999
[
100-
'postID' => $post_id,
101-
'nonce' => wp_create_nonce( 'ajax-nonce' ),
102-
'restNonce' => wp_create_nonce( 'wp_rest' ),
103-
'userCanFix' => current_user_can( apply_filters( 'edac_filter_settings_capability', 'manage_options' ) ),
104-
'edacUrl' => esc_url_raw( get_site_url() ),
105-
'ajaxurl' => admin_url( 'admin-ajax.php' ),
106-
'loggedIn' => is_user_logged_in(),
107-
'appCssUrl' => EDAC_PLUGIN_URL . 'build/css/frontendHighlighterApp.css?ver=' . EDAC_VERSION,
108-
'widgetPosition' => get_option( 'edac_frontend_highlighter_position', 'right' ),
109-
'editorLink' => get_edit_post_link( $post_id ),
100+
'postID' => $post_id,
101+
'nonce' => wp_create_nonce( 'ajax-nonce' ),
102+
'restNonce' => wp_create_nonce( 'wp_rest' ),
103+
'userCanFix' => current_user_can( apply_filters( 'edac_filter_settings_capability', 'manage_options' ) ),
104+
'edacUrl' => esc_url_raw( get_site_url() ),
105+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
106+
'loggedIn' => is_user_logged_in(),
107+
'appCssUrl' => EDAC_PLUGIN_URL . 'build/css/frontendHighlighterApp.css?ver=' . EDAC_VERSION,
108+
'widgetPosition' => get_option( 'edac_frontend_highlighter_position', 'right' ),
109+
'editorLink' => get_edit_post_link( $post_id ),
110+
'scannerBundleUrl' => plugin_dir_url( EDAC_PLUGIN_FILE ) . 'build/pageScanner.bundle.js',
110111
]
111112
);
112113

includes/classes/class-rest-api.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,12 @@ public function set_post_scan_results( $request ) {
383383
$landmark = $violation['landmark'] ?? null;
384384
$landmark_selector = $violation['landmarkSelector'] ?? null;
385385

386-
( new Insert_Rule_Data() )->insert( $post, $actual_rule_id, $impact, $html, $landmark, $landmark_selector );
386+
$selectors = [
387+
'selector' => $violation['selector'] ?? [],
388+
'ancestry' => $violation['ancestry'] ?? [],
389+
'xpath' => $violation['xpath'] ?? [],
390+
];
391+
( new Insert_Rule_Data() )->insert( $post, $actual_rule_id, $impact, $html, $landmark, $landmark_selector, $selectors );
387392

388393
/**
389394
* Fires after a rule is run against the content.

src/frontendHighlighterApp/index.js

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class AccessibilityCheckerHighlight {
1919
};
2020

2121
this.settings = { ...defaultSettings, ...settings };
22+
this._scanAttempted = false;
2223

2324
this.highlightPanel = this.addHighlightPanel();
2425
this.nextButton = document.querySelector( '#edac-highlight-next' );
@@ -188,15 +189,21 @@ class AccessibilityCheckerHighlight {
188189
},
189190
);
190191
}
192+
} else if ( ! self._scanAttempted && response.data?.[ 0 ]?.code === -3 ) {
193+
// Only try kickoffScan once per highlightAjax call
194+
self._scanAttempted = true;
195+
self.kickoffScan();
196+
// After kickoffScan, try highlightAjax again, but only once
197+
setTimeout( () => {
198+
self.highlightAjax().then( resolve ).catch( reject );
199+
}, 5000 ); // Wait 5s for scan to complete.
191200
} else {
192-
resolve( [] );
193-
//console.log(response);
201+
// Default: resolve with empty issues/fixes
202+
resolve( { issues: [], fixes: [] } );
194203
}
195204
} else {
196205
self.showWait( false );
197206

198-
//console.log( 'Request failed. Returned status of ' + xhr.status );
199-
200207
reject( {
201208
status: xhr.status,
202209
statusText: xhr.statusText,
@@ -541,7 +548,11 @@ class AccessibilityCheckerHighlight {
541548
}
542549
}
543550
).catch( ( err ) => {
544-
//TODO:
551+
// Output a message that says that there are no issues or that the issues could not be loaded.
552+
const summary = document.querySelector( '.edac-highlight-panel-controls-summary' );
553+
if ( summary ) {
554+
summary.textContent = __( 'An error occurred when loading the issues.', 'accessibility-checker' );
555+
}
545556
} );
546557
}
547558

@@ -1088,6 +1099,115 @@ class AccessibilityCheckerHighlight {
10881099
element.removeAttribute( 'data-edac-landmark-label-id' );
10891100
} );
10901101
}
1102+
1103+
/**
1104+
* Kick off the accessibility scan.
1105+
*/
1106+
kickoffScan() {
1107+
const getPageDensity = () => {
1108+
const elementCount = document.body.getElementsByTagName( '*' ).length;
1109+
const contentLength = document.body.innerText.length;
1110+
return { elementCount, contentLength };
1111+
};
1112+
const densityMetrics = getPageDensity();
1113+
const self = this;
1114+
const scriptId = 'edac-accessibility-checker-scanner-script';
1115+
if ( ! document.getElementById( scriptId ) ) {
1116+
const script = document.createElement( 'script' );
1117+
script.src = window.edacFrontendHighlighterApp?.scannerBundleUrl || '/wp-content/plugins/accessibility-checker/build/pageScanner.bundle.js';
1118+
script.id = scriptId;
1119+
script.onload = function() {
1120+
setTimeout( () => {
1121+
self._runScanOrShowError( densityMetrics );
1122+
}, 100 );
1123+
};
1124+
script.onerror = function() {
1125+
self.showWait( false );
1126+
self.showScanError( 'Failed to load scanner script.' );
1127+
};
1128+
document.head.appendChild( script );
1129+
} else {
1130+
self._runScanOrShowError( densityMetrics );
1131+
}
1132+
}
1133+
1134+
_runScanOrShowError( densityMetrics ) {
1135+
if ( window.runAccessibilityScan ) {
1136+
this.runAccessibilityScanAndSave( densityMetrics );
1137+
} else {
1138+
this.showWait( false );
1139+
this.showScanError( __( 'Scanner function not found.', 'accessibility-checker' ) );
1140+
}
1141+
}
1142+
1143+
runAccessibilityScanAndSave( densityMetrics ) {
1144+
const self = this;
1145+
const summary = document.querySelector( '.edac-highlight-panel-controls-summary' );
1146+
if ( summary ) {
1147+
summary.textContent = __( 'Scanning...', 'accessibility-checker' );
1148+
summary.classList.remove( 'edac-error' );
1149+
}
1150+
window.runAccessibilityScan().then( ( result ) => {
1151+
const postId = window.edacFrontendHighlighterApp && window.edacFrontendHighlighterApp.postID;
1152+
const nonce = window.edacFrontendHighlighterApp && window.edacFrontendHighlighterApp.restNonce;
1153+
if ( ! postId || ! nonce ) {
1154+
self.showWait( false );
1155+
self.showScanError( __( 'Missing postId or nonce.', 'accessibility-checker' ) );
1156+
return;
1157+
}
1158+
if ( ! result || ! result.violations || result.violations.length === 0 ) {
1159+
self.showWait( false );
1160+
self.showScanError( __( 'No violations found, skipping save.', 'accessibility-checker' ) );
1161+
return;
1162+
}
1163+
self.saveScanResults( postId, nonce, result.violations, densityMetrics );
1164+
} ).catch( () => {
1165+
self.showWait( false );
1166+
self.showScanError( __( 'Accessibility scan error.', 'accessibility-checker' ) );
1167+
} );
1168+
}
1169+
1170+
saveScanResults( postId, nonce, violations, densityMetrics ) {
1171+
const self = this;
1172+
fetch( '/wp-json/accessibility-checker/v1/post-scan-results/' + postId, {
1173+
method: 'POST',
1174+
headers: {
1175+
'Content-Type': 'application/json',
1176+
'X-WP-Nonce': nonce,
1177+
},
1178+
body: JSON.stringify( {
1179+
violations,
1180+
isSkipped: false,
1181+
isFailure: false,
1182+
densityMetrics,
1183+
} ),
1184+
} )
1185+
.then( ( response ) => response.json() )
1186+
.then( ( data ) => {
1187+
self.showWait( false );
1188+
if ( data && data.success ) {
1189+
// Optionally show a success message or update UI
1190+
} else {
1191+
self.showScanError( __( 'Saving failed.', 'accessibility-checker' ) );
1192+
}
1193+
} )
1194+
.catch( () => {
1195+
self.showWait( false );
1196+
self.showScanError( __( 'Error saving scan results.', 'accessibility-checker' ) );
1197+
} );
1198+
}
1199+
1200+
/**
1201+
* Show an error message in the scan panel or as an alert fallback.
1202+
* @param {string} message
1203+
*/
1204+
showScanError( message ) {
1205+
const summary = document.querySelector( '.edac-highlight-panel-controls-summary' );
1206+
if ( summary ) {
1207+
summary.textContent = message;
1208+
summary.classList.add( 'edac-error' );
1209+
}
1210+
}
10911211
}
10921212

10931213
// Some systems (Cloudflare Rocket Loader) defers scripts for performance but that can

0 commit comments

Comments
 (0)