diff --git a/admin/class-insert-rule-data.php b/admin/class-insert-rule-data.php index 51901827a..bccc97703 100644 --- a/admin/class-insert-rule-data.php +++ b/admin/class-insert-rule-data.php @@ -21,17 +21,18 @@ class Insert_Rule_Data { * * @since 1.10.0 * - * @param object $post The post object. Must have a valid ID. - * @param string $rule The rule. - * @param string $ruletype The rule type. - * @param string $rule_obj The object. - * @param string|null $landmark The landmark type (main, header, footer, nav), optional. + * @param object $post The post object. Must have a valid ID. + * @param string $rule The rule. + * @param string $ruletype The rule type. + * @param string $rule_obj The object. + * @param string|null $landmark The landmark type (main, header, footer, nav), optional. * @param string|null $landmark_selector The landmark selector, optional. + * @param array $selectors An array of selectors that point to the object, optional. * * @return void|int|\WP_Error The ID of the inserted record, void if no * record was inserted or a WP_Error if the insert failed. */ - public function insert( object $post, string $rule, string $ruletype, string $rule_obj, ?string $landmark = null, ?string $landmark_selector = null ) { + public function insert( object $post, string $rule, string $ruletype, string $rule_obj, ?string $landmark = null, ?string $landmark_selector = null, array $selectors = [] ) { if ( ! isset( $post->ID, $post->post_type ) || empty( $rule ) @@ -51,6 +52,9 @@ public function insert( object $post, string $rule, string $ruletype, string $ru 'type' => $post->post_type, 'landmark' => $landmark, 'landmark_selector' => $landmark_selector, + 'selector' => $selectors['selector'][0] ?? null, + 'ancestry' => $selectors['ancestry'][0] ?? null, + 'xpath' => $selectors['xpath'][0] ?? null, 'rule' => $rule, 'ruletype' => $ruletype, 'object' => esc_attr( $rule_obj ), @@ -96,9 +100,14 @@ public function insert( object $post, string $rule, string $ruletype, string $ru // 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. $wpdb->query( $wpdb->prepare( - 'UPDATE %i SET recordcheck = %d, ignre = %d WHERE siteid = %d and postid = %d and rule = %s and object = %s and type = %s', + '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', $table_name, 1, + $rule_data['landmark'], + $rule_data['landmark_selector'], + $rule_data['selector'], + $rule_data['ancestry'], + $rule_data['xpath'], $rule_data['ignre'], $rule_data['siteid'], $rule_data['postid'], @@ -134,6 +143,9 @@ public function insert( object $post, string $rule, string $ruletype, string $ru 'type' => sanitize_text_field( $rule_data['type'] ), 'landmark' => isset( $rule_data['landmark'] ) ? sanitize_text_field( $rule_data['landmark'] ) : null, 'landmark_selector' => isset( $rule_data['landmark_selector'] ) ? sanitize_text_field( $rule_data['landmark_selector'] ) : null, + 'selector' => sanitize_text_field( $rule_data['selector'] ?? '' ), + 'ancestry' => sanitize_text_field( $rule_data['ancestry'] ?? '' ), + 'xpath' => sanitize_text_field( $rule_data['xpath'] ?? '' ), 'rule' => sanitize_text_field( $rule_data['rule'] ), 'ruletype' => sanitize_text_field( $rule_data['ruletype'] ), 'object' => esc_attr( $rule_data['object'] ), diff --git a/admin/class-update-database.php b/admin/class-update-database.php index 10bd6f30d..3149b3bf0 100644 --- a/admin/class-update-database.php +++ b/admin/class-update-database.php @@ -50,6 +50,9 @@ public function edac_update_database() { type text NOT NULL, landmark varchar(20) NULL, landmark_selector text NULL, + selector text NULL, + ancestry text NULL, + xpath text NULL, rule text NOT NULL, ruletype text NOT NULL, object mediumtext NOT NULL, diff --git a/includes/classes/class-rest-api.php b/includes/classes/class-rest-api.php index ea6fa2ce0..cbc2394ff 100644 --- a/includes/classes/class-rest-api.php +++ b/includes/classes/class-rest-api.php @@ -383,7 +383,12 @@ public function set_post_scan_results( $request ) { $landmark = $violation['landmark'] ?? null; $landmark_selector = $violation['landmarkSelector'] ?? null; - ( new Insert_Rule_Data() )->insert( $post, $actual_rule_id, $impact, $html, $landmark, $landmark_selector ); + $selectors = [ + 'selector' => $violation['selector'] ?? [], + 'ancestry' => $violation['ancestry'] ?? [], + 'xpath' => $violation['xpath'] ?? [], + ]; + ( new Insert_Rule_Data() )->insert( $post, $actual_rule_id, $impact, $html, $landmark, $landmark_selector, $selectors ); /** * Fires after a rule is run against the content. diff --git a/src/pageScanner/index.js b/src/pageScanner/index.js index 5d306305b..b83de91b9 100644 --- a/src/pageScanner/index.js +++ b/src/pageScanner/index.js @@ -210,36 +210,14 @@ const scan = async ( //Build an array of the dom selectors and ruleIDs for violations/failed tests item.violations.forEach( ( violation ) => { if ( violation.result === 'failed' ) { - const selector = violation.node.selector; - const html = document.querySelector( selector )?.outerHTML; - const landmark = getLandmarkForSelector( selector ); - violations.push( { - selector, - html, - ruleId: item.id, - impact: item.impact, - tags: item.tags, - landmark: landmark.type, - landmarkSelector: landmark.selector, - } ); + violations.push( processViolation( violation, item ) ); } } ); // Handle incomplete results for form-field-multiple-labels only. if ( item.id === 'form-field-multiple-labels' ) { // Allow incomplete results for this rule. item.incomplete.forEach( ( incompleteItem ) => { - const selector = incompleteItem.node.selector; - const html = document.querySelector( selector )?.outerHTML; - const landmark = getLandmarkForSelector( selector ); - violations.push( { - selector, - html, - ruleId: item.id, - impact: item.impact, - tags: item.tags, - landmark: landmark.type, - landmarkSelector: landmark.selector, - } ); + violations.push( processViolation( incompleteItem, item ) ); } ); } } ); @@ -350,3 +328,24 @@ scan().then( ( results ) => { } ).catch( ( err ) => { onDone( [], [ err.message ], true ); } ); + +// Helper to process a violation and return the formatted object +function processViolation( violation, item ) { + // Note that this is an array, generally with one item, but can be more. + const selector = violation.node.selector; + const landmark = getLandmarkForSelector( selector ); + const ancestry = violation.node.ancestry || []; + const xpath = violation.node.xpath || []; + const html = document.querySelector( selector )?.outerHTML; + return { + selector, + ancestry, + xpath, + html, + ruleId: item.id, + impact: item.impact, + tags: item.tags, + landmark: landmark.type, + landmarkSelector: landmark.selector, + }; +} diff --git a/tests/phpunit/Admin/InsertRuleDataTest.php b/tests/phpunit/Admin/InsertRuleDataTest.php index 3e3d7ead2..628dafbf7 100644 --- a/tests/phpunit/Admin/InsertRuleDataTest.php +++ b/tests/phpunit/Admin/InsertRuleDataTest.php @@ -20,31 +20,11 @@ class InsertRuleDataTest extends WP_UnitTestCase { public function setUp(): void { global $wpdb; $this->table_name = $wpdb->prefix . 'accessibility_checker'; - $charset_collate = $wpdb->get_charset_collate(); - $sql = "CREATE TABLE $this->table_name ( - id bigint(20) NOT NULL AUTO_INCREMENT, - postid bigint(20) NOT NULL, - siteid text NOT NULL, - type text NOT NULL, - rule text NOT NULL, - ruletype text NOT NULL, - object mediumtext NOT NULL, - recordcheck mediumint(9) NOT NULL, - created timestamp NOT NULL default CURRENT_TIMESTAMP, - user bigint(20) NOT NULL, - ignre mediumint(9) NOT NULL, - ignre_global mediumint(9) NOT NULL, - ignre_user bigint(20) NULL, - ignre_date timestamp NULL, - ignre_comment mediumtext NULL, - landmark varchar(20) NULL, - landmark_selector text NULL, - UNIQUE KEY id (id), - KEY postid_index (postid) - ) $charset_collate;"; - require_once ABSPATH . 'wp-admin/includes/upgrade.php'; - dbDelta( $sql ); + // Use the Update_Database class to create/update the table schema. + require_once dirname( __DIR__, 3 ) . '/admin/class-update-database.php'; + $update_db = new \EDAC\Admin\Update_Database(); + $update_db->edac_update_database(); } /**