'string', 'single' => true, 'show_in_rest' => true, 'sanitize_callback' => array( __CLASS__, 'sanitize_question' ), 'auth_callback' => function ( $allowed, $meta_key, $post_id ) { return current_user_can( 'edit_post', $post_id ); }, ) ); } } /** * A question: plain text, one line, at most 200 characters. * * @param string $q Question. */ public static function sanitize_question( $q ) { return mb_substr( sanitize_text_field( (string) $q ), 0, 200 ); } /** Whether the current screen edits a post type the plugin covers. */ private static function covered_screen() { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; return $screen && in_array( $screen->post_type, GetReport_Plugin::post_types(), true ) && current_user_can( 'edit_posts' ); } /** The sidebar script and what it needs (enqueue_block_editor_assets). */ public static function enqueue() { if ( ! self::covered_screen() ) { return; } $base = plugins_url( 'assets/', GETREPORT_FILE ); wp_enqueue_script( 'getreport-analyzer', $base . 'analyzer.js', array(), GETREPORT_VERSION, true ); wp_enqueue_script( 'getreport-editor', $base . 'editor.js', array( 'getreport-analyzer', 'wp-plugins', 'wp-element', 'wp-components', 'wp-data', 'wp-hooks', 'wp-compose', 'wp-i18n', 'wp-edit-post' ), GETREPORT_VERSION, true ); wp_set_script_translations( 'getreport-editor', 'getreport' ); wp_add_inline_script( 'getreport-editor', 'window.getreportEditor = ' . wp_json_encode( self::editor_data() ) . ';', 'before' ); } /** The dots in the editor canvas (loaded into the editor iframe; enqueue_block_assets). */ public static function enqueue_canvas_css() { if ( is_admin() && self::covered_screen() ) { wp_enqueue_style( 'getreport-editor-canvas', plugins_url( 'assets/editor-canvas.css', GETREPORT_FILE ), array(), GETREPORT_VERSION ); } } /** Data for the sidebar: the check catalogue, the site facts and this post's context. */ private static function editor_data() { $post = get_post(); $facts = get_option( GetReport_Audit::FACTS ); $site = array(); if ( is_array( $facts ) ) { $site = $facts; unset( $site['robots'], $site['checked_at'] ); if ( $post && ! in_array( $post->post_type, (array) GetReport_Plugin::setting( 'author_types' ), true ) ) { unset( $site['shows_author'] ); } if ( $post ) { $path = (string) wp_parse_url( get_permalink( $post ), PHP_URL_PATH ); $blocked = GetReport_Audit::robots_blocked( (string) ( $facts['robots'] ?? '' ), '' === $path ? '/' : $path ); $site['robots_blocked'] = (bool) $blocked; $site['robots_detail'] = implode( ', ', $blocked ); } } return array( 'catalogue' => GetReport_Registry::data( 'checks-ai.json' ), 'site' => $site, 'audited' => (bool) $facts, 'lang' => $post ? GetReport_Audit::post_locale( $post->ID ) : get_locale(), 'noindex' => $post ? GetReport_Audit::post_noindex( $post->ID ) : false, 'stale' => (int) GetReport_Plugin::setting( 'stale_months' ), 'fixes' => array( 'no-visible-date' => GetReport_Fixes::is_on( 'show-modified-date' ), 'no-author' => GetReport_Fixes::is_on( 'author-box' ), ), 'fixesUrl' => current_user_can( 'manage_options' ) ? admin_url( 'admin.php?page=getreport-fixes' ) : '', 'i18n' => array( /* translators: %d: percent of the post. */ 'answerAt' => __( 'The best answer starts at %d %% of the post.', 'getreport' ), /* translators: 1: question headings, 2: all headings. */ 'questionHeadings' => __( '%1$d of %2$d headings are questions.', 'getreport' ), /* translators: %d: number of words. */ 'words' => __( '%d words.', 'getreport' ), /* translators: %d: months. */ 'monthsAgo' => __( 'Last changed %d months ago.', 'getreport' ), /* translators: %d: percent of the words. */ 'nojsMissing' => __( '%d %% of the text is missing from the HTML crawlers get.', 'getreport' ), ), ); } /** * The Classic editor metabox (the block editor has the sidebar instead). * * @param string $post_type Post type. * @param WP_Post $post Post. */ public static function classic_metabox( $post_type, $post ) { if ( ! in_array( $post_type, GetReport_Plugin::post_types(), true ) ) { return; } if ( function_exists( 'use_block_editor_for_post' ) && use_block_editor_for_post( $post ) ) { return; } add_meta_box( 'getreport-ai', __( 'getReport: AI visibility', 'getreport' ), array( __CLASS__, 'render_metabox' ), $post_type, 'side' ); } /** * The metabox body. * * @param WP_Post $post Post. */ public static function render_metabox( $post ) { wp_nonce_field( 'getreport_question', 'getreport_question_nonce' ); echo '

'; echo '

'; $row = GetReport_Audit::row( $post->ID ); if ( ! $row ) { echo '

' . esc_html__( 'The score appears here after you publish or update, and on Tools → getReport → AI audit.', 'getreport' ) . '

'; return; } /* translators: 1: AI readiness score, 2: quotability. */ echo '

' . esc_html( (string) $row['score'] ) . ' / 100 · ' . esc_html( sprintf( __( 'quotability %d', 'getreport' ), $row['quote'] ) ) . '

'; } /** * Saves the question from the Classic editor. * * @param int $post_id Post id. */ public static function save_classic_question( $post_id ) { if ( ! isset( $_POST['getreport_question_nonce'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['getreport_question_nonce'] ) ), 'getreport_question' ) ) { return; } if ( ! current_user_can( 'edit_post', $post_id ) || wp_is_post_revision( $post_id ) ) { return; } $q = isset( $_POST['getreport_question'] ) ? self::sanitize_question( sanitize_text_field( wp_unslash( $_POST['getreport_question'] ) ) ) : ''; if ( '' === $q ) { delete_post_meta( $post_id, self::META ); } else { update_post_meta( $post_id, self::META, $q ); } } // ---- "AI score" column in the post lists ---- /** Adds the column to every covered post type. */ public static function columns() { foreach ( GetReport_Plugin::post_types() as $type ) { add_filter( "manage_{$type}_posts_columns", array( __CLASS__, 'add_column' ) ); add_action( "manage_{$type}_posts_custom_column", array( __CLASS__, 'column' ), 10, 2 ); } } /** * The column header. * * @param array $cols Columns. */ public static function add_column( $cols ) { $cols['getreport_ai'] = esc_html__( 'AI score', 'getreport' ); return $cols; } /** * A cell: the score, coloured, with the main issue as a tooltip. * * @param string $col Column. * @param int $post_id Post id. */ public static function column( $col, $post_id ) { if ( 'getreport_ai' !== $col ) { return; } $row = GetReport_Audit::row( $post_id ); if ( ! $row ) { echo ''; return; } $main = $row['fails'] ? GetReport_Registry::check( $row['fails'][0] ) : null; echo '' . esc_html( (string) $row['score'] ) . ''; } }