Agevole": checks that help the site owner fix real problems * (content checks, images without alternative text, accessibility statement). * * @package Agevole */ if ( ! defined( 'ABSPATH' ) ) { exit; } define( 'AGEVOLE_A11Y_TOOLS_SLUG', 'agevole-accessibility-tools' ); define( 'AGEVOLE_A11Y_PER_PAGE', 20 ); /** * URL of a tab of the tools page. * * @param string $tab Tab key. * @param array $args Extra query arguments. * @return string */ function agevole_a11y_tools_url( $tab = 'content', $args = array() ) { return add_query_arg( array_merge( array( 'page' => AGEVOLE_A11Y_TOOLS_SLUG, 'tab' => $tab, ), $args ), admin_url( 'tools.php' ) ); } /** * Menu entry. */ function agevole_a11y_tools_menu() { add_management_page( __( 'Accessibility checks', 'agevole-accessibility' ), 'Agevole', 'edit_others_posts', AGEVOLE_A11Y_TOOLS_SLUG, 'agevole_a11y_render_tools' ); } add_action( 'admin_menu', 'agevole_a11y_tools_menu' ); /** * Current tab. * * @return string */ function agevole_a11y_current_tab() { $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'content'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Navigation only. return in_array( $tab, array( 'content', 'images', 'statement' ), true ) ? $tab : 'content'; } /** * Current page number of a list. * * @return int */ function agevole_a11y_current_paged() { return isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Navigation only. } /** * Tools page with tabs. */ function agevole_a11y_render_tools() { if ( ! current_user_can( 'edit_others_posts' ) ) { return; } $tab = agevole_a11y_current_tab(); $tabs = array( 'content' => __( 'Content', 'agevole-accessibility' ), 'images' => __( 'Images', 'agevole-accessibility' ), 'statement' => __( 'Accessibility statement', 'agevole-accessibility' ), ); ?>

'; if ( $paged > 1 ) { echo '' . esc_html__( 'Previous page', 'agevole-accessibility' ) . ' '; } /* translators: 1: current page, 2: number of pages. */ echo esc_html( sprintf( __( 'Page %1$d of %2$d', 'agevole-accessibility' ), $paged, $pages ) ); if ( $paged < $pages ) { echo ' ' . esc_html__( 'Next page', 'agevole-accessibility' ) . ''; } echo '

'; } /* ------------------------------------------------------------------------- * Content * ---------------------------------------------------------------------- */ /** * Published content checked by the content tab. * * @return string[] */ function agevole_a11y_checked_post_types() { $types = get_post_types( array( 'public' => true, 'show_ui' => true, ) ); unset( $types['attachment'] ); return array_values( $types ); } /** * Content tab: published posts and pages with problems. */ function agevole_a11y_render_content_tab() { $paged = agevole_a11y_current_paged(); $query = new WP_Query( array( 'post_type' => agevole_a11y_checked_post_types(), 'post_status' => 'publish', 'posts_per_page' => AGEVOLE_A11Y_PER_PAGE, 'paged' => $paged, 'orderby' => 'modified', 'order' => 'DESC', 'no_found_rows' => false, ) ); $rows = array(); foreach ( $query->posts as $post ) { $issues = agevole_a11y_check_html( $post->post_content ); if ( $issues ) { $rows[] = array( $post, $issues ); } } ?>

posts ), count( $rows ) ) ); ?>


post_type )->labels->singular_name ); ?>
  • :
  • 6 ) : ?>
ID ) ) : ?>
max_num_pages ); } /* ------------------------------------------------------------------------- * Images * ---------------------------------------------------------------------- */ /** * Images in the media library without alternative text. * * @param int $paged Page number. * @return WP_Query */ function agevole_a11y_images_query( $paged ) { return new WP_Query( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_mime_type' => 'image', 'posts_per_page' => AGEVOLE_A11Y_PER_PAGE, 'paged' => $paged, 'orderby' => 'date', 'order' => 'DESC', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Admin-only report, paginated. 'meta_query' => array( 'relation' => 'OR', array( 'key' => '_wp_attachment_image_alt', 'compare' => 'NOT EXISTS', ), array( 'key' => '_wp_attachment_image_alt', 'value' => '', ), ), ) ); } /** * Images tab: alternative text editable in place. */ function agevole_a11y_render_images_tab() { $paged = agevole_a11y_current_paged(); $query = agevole_a11y_images_query( $paged ); $saved = isset( $_GET['saved'] ) ? absint( $_GET['saved'] ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display only. ?>

posts ) : ?>

found_posts, 'agevole-accessibility' ), (int) $query->found_posts ) ); ?>

posts as $image ) : ?> ID; ?>
ID, array( 150, 150 ), false, array( 'alt' => '' ) ); ?>
ID ) ) ); ?>

max_num_pages ); } /** * Saves the alternative texts (only non-empty fields, only images the user can edit). */ function agevole_a11y_save_alts() { check_admin_referer( 'agevole_a11y_save_alts' ); if ( ! current_user_can( 'upload_files' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'agevole-accessibility' ), 403 ); } $count = 0; $alts = isset( $_POST['agevole_alt'] ) && is_array( $_POST['agevole_alt'] ) ? wp_unslash( $_POST['agevole_alt'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Each value is sanitized below. foreach ( $alts as $id => $alt ) { $id = absint( $id ); $alt = sanitize_text_field( (string) $alt ); if ( ! $id || '' === $alt || 'attachment' !== get_post_type( $id ) || ! current_user_can( 'edit_post', $id ) ) { continue; } update_post_meta( $id, '_wp_attachment_image_alt', $alt ); ++$count; } $paged = isset( $_POST['paged'] ) ? max( 1, absint( $_POST['paged'] ) ) : 1; wp_safe_redirect( agevole_a11y_tools_url( 'images', array( 'saved' => $count, 'paged' => $paged, ) ) ); exit; } add_action( 'admin_post_agevole_a11y_save_alts', 'agevole_a11y_save_alts' );