true ), 'names' ), 'ayudawp_aiss_too_short', array( 'get_callback' => static function ( $data ) { $post_id = isset( $data['id'] ) ? (int) $data['id'] : 0; return $post_id && ayudawp_aiss_should_apply_summary( $post_id ) && AyudaWP_AISS_AI_Summary::is_below_minimum( $post_id ); }, 'schema' => array( 'description' => __( 'Whether the post is too short for an automatic summary.', 'ai-share-summarize' ), 'type' => 'boolean', 'context' => array( 'edit' ), 'readonly' => true, ), ) ); } /** * The notice both editors show on a post too short for a summary (v2.7.0) * * @since 2.7.0 * @return string Translated notice with the current minimum. */ public static function ayudawp_too_short_notice() { $min = ayudawp_aiss_get_summary_min_words(); $by_chars = function_exists( 'wp_get_word_count_type' ) && 0 === strpos( wp_get_word_count_type(), 'characters' ); return $by_chars ? sprintf( /* translators: %s: minimum number of characters of text a post needs for an automatic summary. */ _n( 'This post is too short for an automatic summary (it needs at least %s character of text). The site only shows a summary you write here.', 'This post is too short for an automatic summary (it needs at least %s characters of text). The site only shows a summary you write here.', $min, 'ai-share-summarize' ), number_format_i18n( $min ) ) : sprintf( /* translators: %s: minimum number of words of text a post needs for an automatic summary. */ _n( 'This post is too short for an automatic summary (it needs at least %s word of text). The site only shows a summary you write here.', 'This post is too short for an automatic summary (it needs at least %s words of text). The site only shows a summary you write here.', $min, 'ai-share-summarize' ), number_format_i18n( $min ) ); } /** * Register meta for REST API (block editor support) */ public function ayudawp_register_meta() { $post_types = get_post_types( array( 'public' => true ), 'names' ); /* * Permission is checked over the post being written, not over the * "can this user edit posts at all" generic capability (v2.5.0). * Until 2.4.4 these two callbacks took no arguments and asked for * `edit_posts`, so any contributor could flip the exclusion flags on * somebody else's published post through the REST meta endpoint. * `edit_post` runs through map_meta_cap, which resolves ownership and * post status, and matches what the summary meta keys already did in * class-ai-summary.php. */ $auth_callback = function ( $allowed, $meta_key, $post_id ) { return current_user_can( 'edit_post', $post_id ); }; foreach ( $post_types as $post_type ) { register_post_meta( $post_type, self::META_KEY, array( 'show_in_rest' => true, 'single' => true, 'type' => 'boolean', 'default' => false, 'auth_callback' => $auth_callback, 'sanitize_callback' => 'rest_sanitize_boolean', ) ); register_post_meta( $post_type, self::META_KEY_SUMMARY, array( 'show_in_rest' => true, 'single' => true, 'type' => 'boolean', 'default' => false, 'auth_callback' => $auth_callback, 'sanitize_callback' => 'rest_sanitize_boolean', ) ); } } /** * Add meta box to post types * * In the block editor, the sidebar panel (editor-sidebar.js) replaces * this meta box. Registering a classic meta box in the block editor * disables WordPress 7.0 real-time collaboration for the post. * * Fallback: if the sidebar JS file is missing, the classic meta box * is registered even in the block editor so the user is never left * without the exclusion control. */ public function ayudawp_add_meta_box() { $screen = get_current_screen(); if ( $screen && method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) { $js_file = AYUDAWP_AISS_PLUGIN_DIR . 'assets/js/editor-sidebar.js'; if ( file_exists( $js_file ) ) { // Sidebar JS handles the UI in the block editor. return; } } // Classic editor (or block editor fallback if JS is missing). $post_types = get_post_types( array( 'public' => true ), 'names' ); foreach ( $post_types as $post_type ) { add_meta_box( 'ayudawp_aiss_exclude_metabox', __( 'AI Summaries & Share Buttons', 'ai-share-summarize' ), array( $this, 'ayudawp_render_meta_box' ), $post_type, 'side', 'default' ); } } /** * Render meta box content (classic editor only) * * @param WP_Post $post Current post object. */ public function ayudawp_render_meta_box( $post ) { // Add nonce for security. wp_nonce_field( 'ayudawp_aiss_meta_box', 'ayudawp_aiss_meta_box_nonce' ); // Get current value. $excluded = get_post_meta( $post->ID, self::META_KEY, true ); ?>
ID, AyudaWP_AISS_AI_Summary::META_SUMMARY, true ); $provider = get_post_meta( $post->ID, AyudaWP_AISS_AI_Summary::META_PROVIDER, true ); $provider_label = ''; if ( 'wp_ai_client' === $provider ) { $provider_label = __( 'Generated by WP AI Client', 'ai-share-summarize' ); } elseif ( 'extractive' === $provider ) { $provider_label = __( 'Basic summary (extractive)', 'ai-share-summarize' ); } elseif ( 'manual' === $provider ) { $provider_label = __( 'Manually edited', 'ai-share-summarize' ); } ?>
ID ) && AyudaWP_AISS_AI_Summary::is_below_minimum( $post ) ) : ?>
__( 'AI Summaries & Share Buttons', 'ai-share-summarize' ), 'label' => __( 'Hide share buttons on this content', 'ai-share-summarize' ), 'help' => __( 'Check this box to prevent the share and AI buttons from appearing on this specific content.', 'ai-share-summarize' ), 'excludeSummaryLabel' => __( 'Hide AI summary on this content', 'ai-share-summarize' ), 'excludeSummaryHelp' => __( 'Prevents the summary from being generated and displayed for this specific content. Independent from the share buttons toggle.', 'ai-share-summarize' ), 'summaryPanelTitle' => __( 'AI Summary', 'ai-share-summarize' ), 'summaryEditLabel' => __( 'Summary', 'ai-share-summarize' ), 'regenerateLabel' => __( 'Regenerate now', 'ai-share-summarize' ), 'regenerating' => __( 'Regenerating…', 'ai-share-summarize' ), 'regenerateSuccess' => __( 'Summary regenerated.', 'ai-share-summarize' ), 'regenerateError' => __( 'Regeneration failed.', 'ai-share-summarize' ), 'waitingForGen' => __( 'Generating summary in background…', 'ai-share-summarize' ), 'noSummaryYet' => __( 'Summary will be generated when this post is published.', 'ai-share-summarize' ), 'providerWpAi' => __( 'Generated by WP AI Client', 'ai-share-summarize' ), 'providerExtractive' => __( 'Basic summary (extractive)', 'ai-share-summarize' ), 'providerManual' => __( 'Manually edited', 'ai-share-summarize' ), 'manualOverrideHelp' => __( 'Editing this text marks the summary as manual — it will not be regenerated automatically.', 'ai-share-summarize' ), 'tooShort' => self::ayudawp_too_short_notice(), ) ); } /** * Check if a post is excluded via meta box * * Works with both classic editor (stores '1' as string) and * block editor (stores true as boolean via REST API). * * @param int $post_id Post ID to check. * @return bool True if excluded, false otherwise. */ public static function ayudawp_is_post_excluded( $post_id ) { return (bool) get_post_meta( $post_id, self::META_KEY, true ); } /** * Check if a post has the AI summary excluded via meta box (v2.3.0) * * Same value semantics as ayudawp_is_post_excluded(): '1' from the * classic editor, boolean true through the REST meta. * * @since 2.3.0 * @param int $post_id Post ID to check. * @return bool True if the summary is excluded, false otherwise. */ public static function ayudawp_is_summary_excluded( $post_id ) { return (bool) get_post_meta( $post_id, self::META_KEY_SUMMARY, true ); } }