ProShell v2.0
Dashboard
Server Info
Server: 158.106.128.192
PHP: 8.2.33
home
planet5
public_html
bansibaba.com
wp-includes
2026-09-12 20:00:27
Editing: blogging-prompts.php
Cancel
Save Changes
<?php /** * Used by the blogging prompt feature. * * @package automattic/jetpack */ if ( ! defined( 'ABSPATH' ) ) { exit( 0 ); } /** * Hooked functions. */ /** * Adds the blogging prompt key post meta to the list of allowed post meta to be updated by rest api. * * @param array $keys Array of post meta keys that are allowed public metadata. * * @return array */ function jetpack_blogging_prompts_add_meta_data( $keys ) { $keys[] = '_jetpack_blogging_prompt_key'; return $keys; } add_filter( 'rest_api_allowed_public_metadata', 'jetpack_blogging_prompts_add_meta_data' ); /** * Sets up a new post as an answer to a blogging prompt (classic new-post screen). * * When we know a user is explicitly answering a prompt, pre-populate the post meta to mark the post as a prompt response, * in case they decide to remove the block from the post content, preventing they meta from being added later. * * REST creations (e.g. the Write editor's POST /wp/v2/posts?answer_prompt=…) are * handled by jetpack_setup_blogging_prompt_response_rest() on rest_after_insert_post * instead — that hook runs after the REST controller sets the request's tags, so the * prompt tags we add aren't overwritten. * * Called on `wp_insert_post` hook. * * @param int $post_id ID of post being inserted. * @return void */ function jetpack_setup_blogging_prompt_response( $post_id ) { if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return; } if ( ! jetpack_is_new_post_screen() ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Clicking a prompt response link can happen from notifications, Calypso, wp-admin, email, etc and only sets up a response post (tag, meta, prompt text); the user must take action to actually publish the post. $prompt_id = isset( $_GET['answer_prompt'] ) ? absint( $_GET['answer_prompt'] ) : 0; if ( $prompt_id ) { jetpack_apply_blogging_prompt_response( $post_id, $prompt_id ); } } add_action( 'wp_insert_post', 'jetpack_setup_blogging_prompt_response' ); /** * Sets up a REST-created post (e.g. the Write editor) as an answer to a prompt. * * Runs on `rest_after_insert_post`, which fires after the REST controller has set * the request's tags — so the prompt tags added here survive. * * @param WP_Post $post Inserted post object. * @param WP_REST_Request $request Request object. * @param bool $creating True when creating, false when updating. * @return void */ function jetpack_setup_blogging_prompt_response_rest( $post, $request, $creating ) { if ( ! $creating || ! $post instanceof WP_Post || 'post' !== $post->post_type ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only GET param forwarded by the Write editor on the create request; only sets up a response post (tag, meta). $prompt_id = isset( $_GET['answer_prompt'] ) ? absint( $_GET['answer_prompt'] ) : 0; if ( $prompt_id ) { jetpack_apply_blogging_prompt_response( $post->ID, $prompt_id ); } } add_action( 'rest_after_insert_post', 'jetpack_setup_blogging_prompt_response_rest', 10, 3 ); /** * Stamp a post as a blogging-prompt answer: prompt-key meta + prompt tags. * * Shared by the classic (wp_insert_post) and REST (rest_after_insert_post) entry * points so both mark the answer identically. * * @param int $post_id Post ID. * @param int $prompt_id Prompt ID. * @return void */ function jetpack_apply_blogging_prompt_response( $post_id, $prompt_id ) { // Make sure the prompt exists. $prompt = jetpack_get_blogging_prompt_by_id( $prompt_id ); if ( ! $prompt ) { return; } update_post_meta( $post_id, '_jetpack_blogging_prompt_key', $prompt_id ); wp_add_post_tags( $post_id, array( 'dailyprompt', "dailyprompt-$prompt_id" ) ); if ( is_array( $prompt ) && array_key_exists( 'bloganuary_id', $prompt ) ) { wp_add_post_tags( $post_id, array( 'bloganuary', $prompt['bloganuary_id'] ) ); } } /** * When a published posts answers a blogging prompt, store the prompt id in the post meta. * * @param int $post_id Post ID. * @param WP_Post $post Post object. * @param bool $update Whether this is an existing post being updated. * @param null|WP_Post $post_before Null for new posts, the WP_Post object prior * to the update for updated posts. */ function jetpack_mark_if_post_answers_blogging_prompt( $post_id, $post, $update, $post_before ) { if ( ! $post instanceof WP_Post ) { return; } $post_type = $post->post_type ?? null; $post_content = $post->post_content ?? null; if ( 'post' !== $post_type || ! $post_content ) { return; } $new_status = $post->post_status ?? null; $old_status = $post_before && isset( $post_before->post_status ) ? $post_before->post_status : null; // Make sure we are publishing a post, and it's not already published. if ( 'publish' !== $new_status || 'publish' === $old_status ) { return; } $scanner = \Automattic\Block_Scanner::create( $post->post_content ); if ( ! $scanner ) { return; } $prompt_id = null; $total_blocks = 0; $found_prompt_block = false; while ( $scanner->next_delimiter() ) { if ( $scanner->opens_block() ) { ++$total_blocks; if ( ! $found_prompt_block && $scanner->is_block_type( 'jetpack/blogging-prompt' ) ) { $attributes = $scanner->allocate_and_return_parsed_attributes(); if ( $attributes && isset( $attributes['promptId'] ) ) { $prompt_id = absint( $attributes['promptId'] ); } $found_prompt_block = true; } // Early exit: if we found the prompt and have >1 blocks, we have all info needed if ( $found_prompt_block && $total_blocks > 1 ) { break; } } } if ( ! $found_prompt_block || ! $prompt_id || $total_blocks <= 1 ) { return; } $has_prompt_tag = has_tag( 'dailyprompt', $post ) || has_tag( "dailyprompt-{$prompt_id}", $post ); if ( ! $has_prompt_tag ) { return; } update_post_meta( $post->ID, '_jetpack_blogging_prompt_key', $prompt_id ); } add_action( 'wp_after_insert_post', 'jetpack_mark_if_post_answers_blogging_prompt', 10, 4 ); /** * Utility functions. */ /** * Build the blogging-prompts route for the REST context we're running in. * * The endpoint sets `wpcom_is_site_specific_endpoint`, so WordPress.com's * centralized REST API registers it site-scoped, as * `/wpcom/v3/sites/<blog_id>/blogging-prompts/<id>`. Everywhere else — Atomic, * self-hosted, and ordinary wp-admin requests on Simple — it registers at * `/wpcom/v3/blogging-prompts/<id>`. Which shape is live depends on the request * we happen to be running inside, and asking for the wrong one just 404s and * silently loses the prompt, so resolve it against the route table each time. * * Call this only after the endpoint file is required, so its routes are in * place by the time `rest_get_server()` fires `rest_api_init`. * * @since 16.2 * * @param int $prompt_id ID of the prompt to fetch. * @return string REST route for that prompt. */ function jetpack_get_blogging_prompt_route( $prompt_id ) { foreach ( array_keys( rest_get_server()->get_routes() ) as $route ) { if ( str_starts_with( $route, '/wpcom/v3/blogging-prompts/' ) ) { return sprintf( '/wpcom/v3/blogging-prompts/%d', $prompt_id ); } } return sprintf( '/wpcom/v3/sites/%d/blogging-prompts/%d', get_current_blog_id(), $prompt_id ); } /** * Retrieve a blogging prompt by prompt ID. * * @param int $prompt_id ID of the prompt fetch. * @return array|null Prompt object or null. */ function jetpack_get_blogging_prompt_by_id( $prompt_id ) { // Ensure the REST API endpoint we need is loaded. require_once __DIR__ . '/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v3-endpoint-blogging-prompts.php'; $locale = get_locale(); $route = jetpack_get_blogging_prompt_route( $prompt_id ); $request = new WP_REST_Request( 'GET', $route ); $request->set_param( '_locale', $locale ); $request->set_param( 'force_year', gmdate( 'Y' ) ); $response = rest_do_request( $request ); if ( $response->is_error() || WP_Http::OK !== $response->get_status() ) { return null; } $prompt = $response->get_data(); return $prompt; } /** * Retrieve daily blogging prompts from the wpcom API and cache them. * * @param int $time Unix timestamp representing the day for which to get blogging prompts. * @return stdClass[]|null Array of blogging prompt objects or null. */ function jetpack_get_daily_blogging_prompts( $time = 0 ) { $timestamp = $time ? $time : time(); // Include prompts from the previous day, just in case someone has an outdated prompt id. $day_before = wp_date( 'Y-m-d', $timestamp - DAY_IN_SECONDS ); $locale = get_locale(); $transient_key = 'jetpack_blogging_prompt_' . $day_before . '_' . $locale; $daily_prompts = get_transient( $transient_key ); // Return the cached prompt, if we have it. Otherwise fetch it from the API. if ( false !== $daily_prompts ) { return $daily_prompts; } $blog_id = \Jetpack_Options::get_option( 'id' ); $path = '/sites/' . rawurldecode( $blog_id ) . '/blogging-prompts?from=' . rawurldecode( $day_before ) . '&number=10&_locale=' . rawurldecode( $locale ); $args = array( 'headers' => array( 'Content-Type' => 'application/json', 'X-Forwarded-For' => ( new \Automattic\Jetpack\Status\Visitor() )->get_ip( true ), ), // `method` and `url` are needed for using `WPCOM_API_Direct::do_request` // `wpcom_json_api_request_as_user` will generate and overwrite these. 'method' => \WP_REST_Server::READABLE, 'url' => JETPACK__WPCOM_JSON_API_BASE . '/wpcom/v2' . $path, ); if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { // This will load the library, but it may be too late to automatically load any endpoints using WPCOM_API_Direct::register_endpoints. // In that case, call `wpcom_rest_api_v2_load_plugin_files( 'wp-content/rest-api-plugins/endpoints/blogging-prompts.php' )` // on the `init` hook to load the blogging-prompts endpoint before calling this function. require_once WP_CONTENT_DIR . '/lib/wpcom-api-direct/wpcom-api-direct.php'; $response = \WPCOM_API_Direct::do_request( $args ); } else { $response = \Automattic\Jetpack\Connection\Client::wpcom_json_api_request_as_user( $path, 'v2', $args, null, 'wpcom' ); } $response_status = wp_remote_retrieve_response_code( $response ); if ( is_wp_error( $response ) || $response_status !== \WP_Http::OK ) { return null; } $body = json_decode( wp_remote_retrieve_body( $response ) ); if ( ! $body || ! isset( $body->prompts ) ) { return null; } $prompts = $body->prompts; set_transient( $transient_key, $prompts, DAY_IN_SECONDS ); return $prompts; } /** * Determines if the site has publish posts or plans to publish posts. * * @return bool */ function jetpack_has_or_will_publish_posts() { // Lets count the posts. $count_posts_object = wp_count_posts( 'post' ); $count_posts = (int) $count_posts_object->publish + (int) $count_posts_object->future + (int) $count_posts_object->draft; return $count_posts_object->publish >= 2 || $count_posts >= 100; } /** * Determines if the site has a posts page or shows posts on the front page. * * @return bool */ function jetpack_has_posts_page() { // The site is set up to be a blog. if ( 'posts' === get_option( 'show_on_front' ) ) { return true; } // There is a page set to show posts. $is_posts_page_set = (int) get_option( 'page_for_posts' ) > 0; if ( $is_posts_page_set ) { return true; } return false; } /** * Determines if site had the "Write" intent set when created. * * @return bool */ function jetpack_has_write_intent() { return 'write' === get_option( 'site_intent', '' ); } /** * Determines if the current screen (in wp-admin) is creating a new post. * * /wp-admin/post-new.php * * @return bool */ function jetpack_is_new_post_screen() { global $current_screen; if ( $current_screen instanceof \WP_Screen && 'add' === $current_screen->action && 'post' === $current_screen->post_type ) { return true; } return false; } /** * Determines if the site might have a blog. * * @return bool */ function jetpack_is_potential_blogging_site() { return jetpack_has_write_intent() || jetpack_has_posts_page() || jetpack_has_or_will_publish_posts(); }
Upload Files
Cancel
Upload
Create New
Cancel
Create
Change Permissions
Cancel
Save
Change Date
Cancel
Save
Rename Item
Cancel
Save
Confirm Delete
Are you sure you want to delete the selected items?
Cancel
Delete