—';
return;
}
$count = isset( $latest['counts'][ $post_id ] ) ? (int) $latest['counts'][ $post_id ] : 0;
if ( 0 === $count ) {
echo '' . esc_html__( 'None found', 'markproof' ) . '';
return;
}
printf(
'%s',
esc_url( admin_url( 'admin.php?page=markproof-findings&url=' . rawurlencode( get_permalink( $post_id ) ) ) ),
esc_html( sprintf( /* translators: %d: number of findings */ _n( '%d finding', '%d findings', $count, 'markproof' ), $count ) )
);
}
/** One dismissible pointer to the first scan. Not an advert, and it never comes back. */
public function welcome_notice() {
if ( ! current_user_can( self::CAP ) || get_option( 'markproof_welcome_dismissed' ) ) {
return;
}
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( (string) $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- reading which screen we are on, changing nothing.
if ( 0 === strpos( $page, 'markproof' ) ) {
return; // they are already there
}
// One dismissible sentence on the dashboard and the plugin list, not on every screen an
// administrator visits. A notice that follows people around is the behaviour reviewers
// rightly object to, and it is not how we would want to be treated either.
$allowed = array( 'dashboard', 'plugins' );
if ( $screen && ! in_array( $screen->id, $allowed, true ) ) {
return;
}
?>
20, 'user-agent' => 'Markproof – Accessibility Checks/' . STOCHASTIC_SCANNER_VERSION ) );
$ms = (int) round( ( microtime( true ) - $started ) * 1000 );
if ( is_wp_error( $response ) ) {
wp_send_json_success( array( 'ok' => false, 'detail' => $response->get_error_message(), 'ms' => $ms ) );
}
wp_send_json_success(
array(
'ok' => true,
'detail' => 'HTTP ' . (int) wp_remote_retrieve_response_code( $response ) . ', ' . strlen( wp_remote_retrieve_body( $response ) ) . ' bytes',
'ms' => $ms,
)
);
}
public function ajax_batch() {
check_ajax_referer( 'markproof', 'nonce' );
if ( ! current_user_can( self::CAP ) ) {
wp_send_json_error( 'forbidden', 403 );
}
$scan_id = isset( $_POST['scan'] ) ? (int) $_POST['scan'] : 0;
if ( ! $scan_id ) {
wp_send_json_error( 'missing scan' );
}
wp_send_json_success( Markproof_Scanner::process_batch( $scan_id, 5, 20 ) );
}
public function export_csv() {
if ( ! current_user_can( self::CAP ) ) {
wp_die( esc_html__( 'Not allowed.', 'markproof' ) );
}
check_admin_referer( 'markproof_export' );
$scan_id = isset( $_GET['scan'] ) ? (int) $_GET['scan'] : 0;
$meta = Markproof_Rules::metadata();
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=markproof-' . $scan_id . '.csv' );
$out = fopen( 'php://output', 'w' );
fputcsv( $out, array( 'page_url', 'severity', 'problem', 'details', 'html_snippet', 'how_to_fix' ) );
$offset = 0;
do {
$rows = Markproof_Store::issues_for_scan( $scan_id, 500, '', $offset );
foreach ( $rows as $row ) {
$info = isset( $meta[ $row->rule_id ] ) ? $meta[ $row->rule_id ] : null;
fputcsv(
$out,
array(
$row->url,
$row->severity,
$info ? $info['title'] : $row->rule_id,
$row->message,
$row->snippet,
$info ? $info['fix'] : '',
)
);
}
$offset += 500;
} while ( count( $rows ) === 500 );
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- streaming straight to the browser, not a file on disk.
fclose( $out );
exit;
}
/**
* A work list of images with no alt text, with the fix on the same screen.
*
* Reporting a problem is half a tool. The other half is being able to act on it without leaving
* the page, which is why every row here can be filled in and saved in one go.
*/
public function page_alt_text() {
if ( ! current_user_can( self::CAP ) ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- a display filter, it changes nothing.
$show_all = isset( $_GET['show'] ) && 'all' === $_GET['show'];
$images = get_posts(
array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'post_status' => 'inherit',
'posts_per_page' => 200,
'orderby' => 'ID',
'order' => 'DESC',
'fields' => 'ids',
)
);
$missing = array();
foreach ( $images as $id ) {
$alt = (string) get_post_meta( $id, '_wp_attachment_image_alt', true );
if ( '' === trim( $alt ) ) {
$missing[] = $id;
}
}
$list = $show_all ? $images : $missing;
?>