10, 'serious' => 6, 'moderate' => 3, 'minor' => 1, ); } /** * Penalty of one grouped issue. * * @param string $severity Severity. * @param int $pages Pages affected. * @return float */ public static function issue_penalty( $severity, $pages ) { $w = self::weights(); $w = isset( $w[ $severity ] ) ? $w[ $severity ] : 1; return $w * ( 1 + 0.5 * log( max( 1, (int) $pages ) ) ); } /** * Turn a penalty into 0-100. * * @param float $penalty Penalty. * @param float $scale Scale. * @return int */ public static function to_score( $penalty, $scale = self::SITE_SCALE ) { if ( $penalty <= 0 ) { return 100; } $s = (int) round( 100 * exp( -$penalty / $scale ) ); return max( 0, min( 99, $s ) ); } /** * Current site score and breakdown from the open, automated issues. * * @return array{score:int,categories:array,penalty:float,counts:array} */ public static function site() { global $wpdb; $t = Schema::table( 'issues' ); $rows = $wpdb->get_results( $wpdb->prepare( "SELECT severity, category, page_count FROM %i WHERE state = 'open' AND mode = 'automated'", $t ), ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery $total = 0.0; $cats = array(); foreach ( (array) $rows as $r ) { $p = self::issue_penalty( $r['severity'], $r['page_count'] ); $total += $p; $cats[ $r['category'] ] = ( isset( $cats[ $r['category'] ] ) ? $cats[ $r['category'] ] : 0 ) + $p; } $cat_scores = array(); foreach ( \A11yMate\Rules\Registry::categories() as $c ) { $pen = isset( $cats[ $c['id'] ] ) ? $cats[ $c['id'] ] : 0; $cat_scores[ $c['id'] ] = self::to_score( $pen, self::SITE_SCALE / 2 ); } return array( 'score' => self::to_score( $total ), 'categories' => $cat_scores, 'penalty' => round( $total, 2 ), ); } /** * Score a page from its list of [rule, severity, count] entries. * * @param array $entries Entries with severity and n keys. * @return int */ public static function page( array $entries ) { $w = self::weights(); $pen = 0; foreach ( $entries as $e ) { $weight = isset( $w[ $e['severity'] ] ) ? $w[ $e['severity'] ] : 1; $pen += $weight * ( 1 + 0.5 * log( max( 1, (int) $e['n'] ) ) ); } return self::to_score( $pen, self::PAGE_SCALE ); } /** * Per-post editor score (used by the block editor assistant, mirrored in JS). * * @param array $severities List of severities. * @return int */ public static function editor( array $severities ) { $w = self::weights(); $pen = 0; foreach ( $severities as $s ) { $pen += isset( $w[ $s ] ) ? $w[ $s ] : 1; } return self::to_score( $pen, 20 ); } }