diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-includes/post.php --- a/wp/wp-includes/post.php Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-includes/post.php Fri Sep 05 18:52:52 2025 +0200 @@ -75,7 +75,7 @@ 'labels' => array( 'name' => _x( 'Media', 'post type general name' ), 'name_admin_bar' => _x( 'Media', 'add new from admin bar' ), - 'add_new' => __( 'Add New Media File' ), + 'add_new' => __( 'Add Media File' ), 'edit_item' => __( 'Edit Media' ), 'view_item' => ( '1' === get_option( 'wp_attachment_pages_enabled' ) ) ? __( 'View Attachment Page' ) : __( 'View Media File' ), 'attributes' => __( 'Attachment Attributes' ), @@ -202,8 +202,8 @@ 'labels' => array( 'name' => _x( 'Changesets', 'post type general name' ), 'singular_name' => _x( 'Changeset', 'post type singular name' ), - 'add_new' => __( 'Add New Changeset' ), - 'add_new_item' => __( 'Add New Changeset' ), + 'add_new' => __( 'Add Changeset' ), + 'add_new_item' => __( 'Add Changeset' ), 'new_item' => __( 'New Changeset' ), 'edit_item' => __( 'Edit Changeset' ), 'view_item' => __( 'View Changeset' ), @@ -284,8 +284,8 @@ 'labels' => array( 'name' => _x( 'Patterns', 'post type general name' ), 'singular_name' => _x( 'Pattern', 'post type singular name' ), - 'add_new' => __( 'Add New Pattern' ), - 'add_new_item' => __( 'Add New Pattern' ), + 'add_new' => __( 'Add Pattern' ), + 'add_new_item' => __( 'Add Pattern' ), 'new_item' => __( 'New Pattern' ), 'edit_item' => __( 'Edit Block Pattern' ), 'view_item' => __( 'View Pattern' ), @@ -350,8 +350,8 @@ 'labels' => array( 'name' => _x( 'Templates', 'post type general name' ), 'singular_name' => _x( 'Template', 'post type singular name' ), - 'add_new' => __( 'Add New Template' ), - 'add_new_item' => __( 'Add New Template' ), + 'add_new' => __( 'Add Template' ), + 'add_new_item' => __( 'Add Template' ), 'new_item' => __( 'New Template' ), 'edit_item' => __( 'Edit Template' ), 'view_item' => __( 'View Template' ), @@ -415,8 +415,8 @@ 'labels' => array( 'name' => _x( 'Template Parts', 'post type general name' ), 'singular_name' => _x( 'Template Part', 'post type singular name' ), - 'add_new' => __( 'Add New Template Part' ), - 'add_new_item' => __( 'Add New Template Part' ), + 'add_new' => __( 'Add Template Part' ), + 'add_new_item' => __( 'Add Template Part' ), 'new_item' => __( 'New Template Part' ), 'edit_item' => __( 'Edit Template Part' ), 'view_item' => __( 'View Template Part' ), @@ -489,7 +489,7 @@ 'revisions_rest_controller_class' => 'WP_REST_Global_Styles_Revisions_Controller', 'late_route_registration' => true, 'capabilities' => array( - 'read' => 'edit_theme_options', + 'read' => 'edit_posts', 'create_posts' => 'edit_theme_options', 'edit_posts' => 'edit_theme_options', 'edit_published_posts' => 'edit_theme_options', @@ -522,8 +522,8 @@ 'labels' => array( 'name' => _x( 'Navigation Menus', 'post type general name' ), 'singular_name' => _x( 'Navigation Menu', 'post type singular name' ), - 'add_new' => __( 'Add New Navigation Menu' ), - 'add_new_item' => __( 'Add New Navigation Menu' ), + 'add_new' => __( 'Add Navigation Menu' ), + 'add_new_item' => __( 'Add Navigation Menu' ), 'new_item' => __( 'New Navigation Menu' ), 'edit_item' => __( 'Edit Navigation Menu' ), 'view_item' => __( 'View Navigation Menu' ), @@ -852,13 +852,15 @@ * Updates attachment file path based on attachment ID. * * Used to update the file path of the attachment, which uses post meta name - * '_wp_attached_file' to store the path of the attachment. + * `_wp_attached_file` to store the path of the attachment. * * @since 2.1.0 * * @param int $attachment_id Attachment ID. * @param string $file File path for the attachment. - * @return bool True on success, false on failure. + * @return int|bool Meta ID if the `_wp_attached_file` key didn't exist for the attachment. + * True on successful update, false on failure or if the `$file` value passed + * to the function is the same as the one that is already in the database. */ function update_attached_file( $attachment_id, $file ) { if ( ! get_post( $attachment_id ) ) { @@ -1135,7 +1137,7 @@ function get_post_ancestors( $post ) { $post = get_post( $post ); - if ( ! $post || empty( $post->post_parent ) || $post->post_parent == $post->ID ) { + if ( ! $post || empty( $post->post_parent ) || $post->post_parent === $post->ID ) { return array(); } @@ -1146,7 +1148,9 @@ while ( $ancestor = get_post( $id ) ) { // Loop detection: If the ancestor has been seen before, break. - if ( empty( $ancestor->post_parent ) || ( $ancestor->post_parent == $post->ID ) || in_array( $ancestor->post_parent, $ancestors, true ) ) { + if ( empty( $ancestor->post_parent ) || $ancestor->post_parent === $post->ID + || in_array( $ancestor->post_parent, $ancestors, true ) + ) { break; } @@ -2022,8 +2026,8 @@ * - `name` - General name for the post type, usually plural. The same and overridden * by `$post_type_object->label`. Default is 'Posts' / 'Pages'. * - `singular_name` - Name for one object of this post type. Default is 'Post' / 'Page'. - * - `add_new` - Label for adding a new item. Default is 'Add New Post' / 'Add New Page'. - * - `add_new_item` - Label for adding a new singular item. Default is 'Add New Post' / 'Add New Page'. + * - `add_new` - Label for adding a new item. Default is 'Add Post' / 'Add Page'. + * - `add_new_item` - Label for adding a new singular item. Default is 'Add Post' / 'Add Page'. * - `edit_item` - Label for editing a singular item. Default is 'Edit Post' / 'Edit Page'. * - `new_item` - Label for the new item page title. Default is 'New Post' / 'New Page'. * - `view_item` - Label for viewing a singular item. Default is 'View Post' / 'View Page'. @@ -2084,6 +2088,8 @@ * @since 6.4.0 Changed default values for the `add_new` label to include the type of content. * This matches `add_new_item` and provides more context for better accessibility. * @since 6.6.0 Added the `template_name` label. + * @since 6.7.0 Restored pre-6.4.0 defaults for the `add_new` label and updated documentation. + * Updated core usage to reference `add_new_item`. * * @access private * @@ -2470,6 +2476,40 @@ } /** + * Determines whether a post is embeddable. + * + * @since 6.8.0 + * + * @param int|WP_Post|null $post Optional. Post ID or `WP_Post` object. Defaults to global $post. + * @return bool Whether the post should be considered embeddable. + */ +function is_post_embeddable( $post = null ) { + $post = get_post( $post ); + + if ( ! $post ) { + return false; + } + + $post_type = get_post_type_object( $post->post_type ); + + if ( ! $post_type ) { + return false; + } + + $is_embeddable = $post_type->embeddable; + + /** + * Filter whether a post is embeddable. + * + * @since 6.8.0 + * + * @param bool $is_embeddable Whether the post is embeddable. + * @param WP_Post $post Post object. + */ + return apply_filters( 'is_post_embeddable', $is_embeddable, $post ); +} + +/** * Retrieves an array of the latest posts, or posts matching the given criteria. * * For more information on the accepted arguments, see the @@ -2552,7 +2592,13 @@ * * @param int $post_id Post ID. * @param string $meta_key Metadata name. - * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $meta_value Metadata value. Arrays and objects are stored as serialized data and + * will be returned as the same type when retrieved. Other data types will + * be stored as strings in the database: + * - false is stored and retrieved as an empty string ('') + * - true is stored and retrieved as '1' + * - numbers (both integer and float) are stored and retrieved as strings + * Must be serializable if non-scalar. * @param bool $unique Optional. Whether the same key should not be added. * Default false. * @return int|false Meta ID on success, false on failure. @@ -2607,7 +2653,13 @@ * @return mixed An array of values if `$single` is false. * The value of the meta field if `$single` is true. * False for an invalid `$post_id` (non-numeric, zero, or negative value). - * An empty string if a valid but non-existing post ID is passed. + * An empty array if a valid but non-existing post ID is passed and `$single` is false. + * An empty string if a valid but non-existing post ID is passed and `$single` is true. + * Note: Non-serialized values are returned as strings: + * - false values are returned as empty strings ('') + * - true values are returned as '1' + * - numbers (both integer and float) are returned as strings + * Arrays and objects retain their original type. */ function get_post_meta( $post_id, $key = '', $single = false ) { return get_metadata( 'post', $post_id, $key, $single ); @@ -2820,7 +2872,7 @@ function sanitize_post( $post, $context = 'display' ) { if ( is_object( $post ) ) { // Check if post already filtered for this context. - if ( isset( $post->filter ) && $context == $post->filter ) { + if ( isset( $post->filter ) && $context === $post->filter ) { return $post; } if ( ! isset( $post->ID ) ) { @@ -2832,7 +2884,7 @@ $post->filter = $context; } elseif ( is_array( $post ) ) { // Check if post already filtered for this context. - if ( isset( $post['filter'] ) && $context == $post['filter'] ) { + if ( isset( $post['filter'] ) && $context === $post['filter'] ) { return $post; } if ( ! isset( $post['ID'] ) ) { @@ -2895,7 +2947,23 @@ * Filters the value of a specific post field to edit. * * The dynamic portion of the hook name, `$field`, refers to the post - * field name. + * field name. Possible filter names include: + * + * - `edit_post_author` + * - `edit_post_date` + * - `edit_post_date_gmt` + * - `edit_post_content` + * - `edit_post_title` + * - `edit_post_excerpt` + * - `edit_post_status` + * - `edit_post_password` + * - `edit_post_name` + * - `edit_post_modified` + * - `edit_post_modified_gmt` + * - `edit_post_content_filtered` + * - `edit_post_parent` + * - `edit_post_type` + * - `edit_post_mime_type` * * @since 2.3.0 * @@ -2907,8 +2975,26 @@ /** * Filters the value of a specific post field to edit. * - * The dynamic portion of the hook name, `$field_no_prefix`, refers to - * the post field name. + * Only applied to post fields with a name which is prefixed with `post_`. + * + * The dynamic portion of the hook name, `$field_no_prefix`, refers to the + * post field name minus the `post_` prefix. Possible filter names include: + * + * - `author_edit_pre` + * - `date_edit_pre` + * - `date_gmt_edit_pre` + * - `content_edit_pre` + * - `title_edit_pre` + * - `excerpt_edit_pre` + * - `status_edit_pre` + * - `password_edit_pre` + * - `name_edit_pre` + * - `modified_edit_pre` + * - `modified_gmt_edit_pre` + * - `content_filtered_edit_pre` + * - `parent_edit_pre` + * - `type_edit_pre` + * - `mime_type_edit_pre` * * @since 2.3.0 * @@ -2917,6 +3003,28 @@ */ $value = apply_filters( "{$field_no_prefix}_edit_pre", $value, $post_id ); } else { + /** + * Filters the value of a specific post field to edit. + * + * Only applied to post fields not prefixed with `post_`. + * + * The dynamic portion of the hook name, `$field`, refers to the + * post field name. Possible filter names include: + * + * - `edit_post_ID` + * - `edit_post_ping_status` + * - `edit_post_pinged` + * - `edit_post_to_ping` + * - `edit_post_comment_count` + * - `edit_post_comment_status` + * - `edit_post_guid` + * - `edit_post_menu_order` + * + * @since 2.3.0 + * + * @param mixed $value Value of the post field. + * @param int $post_id Post ID. + */ $value = apply_filters( "edit_post_{$field}", $value, $post_id ); } @@ -2935,8 +3043,26 @@ /** * Filters the value of a specific post field before saving. * + * Only applied to post fields with a name which is prefixed with `post_`. + * * The dynamic portion of the hook name, `$field`, refers to the post - * field name. + * field name. Possible filter names include: + * + * - `pre_post_author` + * - `pre_post_date` + * - `pre_post_date_gmt` + * - `pre_post_content` + * - `pre_post_title` + * - `pre_post_excerpt` + * - `pre_post_status` + * - `pre_post_password` + * - `pre_post_name` + * - `pre_post_modified` + * - `pre_post_modified_gmt` + * - `pre_post_content_filtered` + * - `pre_post_parent` + * - `pre_post_type` + * - `pre_post_mime_type` * * @since 2.3.0 * @@ -2947,8 +3073,26 @@ /** * Filters the value of a specific field before saving. * - * The dynamic portion of the hook name, `$field_no_prefix`, refers - * to the post field name. + * Only applied to post fields with a name which is prefixed with `post_`. + * + * The dynamic portion of the hook name, `$field_no_prefix`, refers to the + * post field name minus the `post_` prefix. Possible filter names include: + * + * - `author_save_pre` + * - `date_save_pre` + * - `date_gmt_save_pre` + * - `content_save_pre` + * - `title_save_pre` + * - `excerpt_save_pre` + * - `status_save_pre` + * - `password_save_pre` + * - `name_save_pre` + * - `modified_save_pre` + * - `modified_gmt_save_pre` + * - `content_filtered_save_pre` + * - `parent_save_pre` + * - `type_save_pre` + * - `mime_type_save_pre` * * @since 2.3.0 * @@ -2956,13 +3100,45 @@ */ $value = apply_filters( "{$field_no_prefix}_save_pre", $value ); } else { + /** + * Filters the value of a specific field before saving. + * + * Only applied to post fields with a name which is prefixed with `post_`. + * + * The dynamic portion of the hook name, `$field_no_prefix`, refers to the + * post field name minus the `post_` prefix. Possible filter names include: + * + * - `pre_post_ID` + * - `pre_post_comment_status` + * - `pre_post_ping_status` + * - `pre_post_to_ping` + * - `pre_post_pinged` + * - `pre_post_guid` + * - `pre_post_menu_order` + * - `pre_post_comment_count` + * + * @since 2.3.0 + * + * @param mixed $value Value of the post field. + */ $value = apply_filters( "pre_post_{$field}", $value ); /** * Filters the value of a specific post field before saving. * + * Only applied to post fields with a name which is *not* prefixed with `post_`. + * * The dynamic portion of the hook name, `$field`, refers to the post - * field name. + * field name. Possible filter names include: + * + * - `ID_pre` + * - `comment_status_pre` + * - `ping_status_pre` + * - `to_ping_pre` + * - `pinged_pre` + * - `guid_pre` + * - `menu_order_pre` + * - `comment_count_pre` * * @since 2.3.0 * @@ -2978,8 +3154,26 @@ /** * Filters the value of a specific post field for display. * + * Only applied to post fields with a name which is prefixed with `post_`. + * * The dynamic portion of the hook name, `$field`, refers to the post - * field name. + * field name. Possible filter names include: + * + * - `post_author` + * - `post_date` + * - `post_date_gmt` + * - `post_content` + * - `post_title` + * - `post_excerpt` + * - `post_status` + * - `post_password` + * - `post_name` + * - `post_modified` + * - `post_modified_gmt` + * - `post_content_filtered` + * - `post_parent` + * - `post_type` + * - `post_mime_type` * * @since 2.3.0 * @@ -2991,6 +3185,31 @@ */ $value = apply_filters( "{$field}", $value, $post_id, $context ); } else { + /** + * Filters the value of a specific post field for display. + * + * Only applied to post fields name which is *not* prefixed with `post_`. + * + * The dynamic portion of the hook name, `$field`, refers to the post + * field name. Possible filter names include: + * + * - `post_ID` + * - `post_comment_status` + * - `post_ping_status` + * - `post_to_ping` + * - `post_pinged` + * - `post_guid` + * - `post_menu_order` + * - `post_comment_count` + * + * @since 2.3.0 + * + * @param mixed $value Value of the unprefixed post field. + * @param int $post_id Post ID + * @param string $context Context for how to sanitize the field. + * Accepts 'raw', 'edit', 'db', 'display', + * 'attribute', or 'js'. Default 'display'. + */ $value = apply_filters( "post_{$field}", $value, $post_id, $context ); } @@ -3005,7 +3224,6 @@ if ( in_array( $field, $int_fields, true ) ) { $value = (int) $value; } - return $value; } @@ -3219,7 +3437,8 @@ ); $counts = wp_cache_get( $cache_key, 'counts' ); - if ( false == $counts ) { + + if ( false === $counts ) { $and = wp_post_mime_type_where( $mime_type ); $count = $wpdb->get_results( "SELECT post_mime_type, COUNT( * ) AS num_posts FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' $and GROUP BY post_mime_type", ARRAY_A ); @@ -3687,11 +3906,11 @@ * If the page is defined in option page_on_front or post_for_posts, * adjust the corresponding options. */ - if ( get_option( 'page_on_front' ) == $post->ID ) { + if ( (int) get_option( 'page_on_front' ) === $post->ID ) { update_option( 'show_on_front', 'posts' ); update_option( 'page_on_front', 0 ); } - if ( get_option( 'page_for_posts' ) == $post->ID ) { + if ( (int) get_option( 'page_for_posts' ) === $post->ID ) { update_option( 'page_for_posts', 0 ); } } @@ -5889,9 +6108,9 @@ $revparts = array_reverse( $parts ); - $foundid = 0; + $found_id = 0; foreach ( (array) $pages as $page ) { - if ( $page->post_name == $revparts[0] ) { + if ( $page->post_name === $revparts[0] ) { $count = 0; $p = $page; @@ -5899,18 +6118,21 @@ * Loop through the given path parts from right to left, * ensuring each matches the post ancestry. */ - while ( 0 != $p->post_parent && isset( $pages[ $p->post_parent ] ) ) { + while ( 0 !== (int) $p->post_parent && isset( $pages[ $p->post_parent ] ) ) { ++$count; $parent = $pages[ $p->post_parent ]; - if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] ) { + if ( ! isset( $revparts[ $count ] ) || $parent->post_name !== $revparts[ $count ] ) { break; } $p = $parent; } - if ( 0 == $p->post_parent && count( $revparts ) === $count + 1 && $p->post_name == $revparts[ $count ] ) { - $foundid = $page->ID; - if ( $page->post_type == $post_type ) { + if ( 0 === (int) $p->post_parent + && count( $revparts ) === $count + 1 + && $p->post_name === $revparts[ $count ] + ) { + $found_id = $page->ID; + if ( $page->post_type === $post_type ) { break; } } @@ -5918,10 +6140,10 @@ } // We cache misses as well as hits. - wp_cache_set( $cache_key, $foundid, 'post-queries' ); - - if ( $foundid ) { - return get_post( $foundid, $output ); + wp_cache_set( $cache_key, $found_id, 'post-queries' ); + + if ( $found_id ) { + return get_post( $found_id, $output ); } return null; @@ -6182,7 +6404,7 @@ $query_args['author__in'] = array(); foreach ( $post_authors as $post_author ) { // Do we have an author id or an author login? - if ( 0 == (int) $post_author ) { + if ( 0 === (int) $post_author ) { $post_author = get_user_by( 'login', $post_author ); if ( empty( $post_author ) ) { continue; @@ -6829,7 +7051,7 @@ switch ( $type ) { case 'image': - $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp', 'avif' ); + $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp', 'avif', 'heic' ); return in_array( $ext, $image_exts, true ); case 'audio': @@ -7035,12 +7257,14 @@ */ function wp_check_for_changed_slugs( $post_id, $post, $post_before ) { // Don't bother if it hasn't changed. - if ( $post->post_name == $post_before->post_name ) { + if ( $post->post_name === $post_before->post_name ) { return; } // We're only concerned with published, non-hierarchical objects. - if ( ! ( 'publish' === $post->post_status || ( 'attachment' === get_post_type( $post ) && 'inherit' === $post->post_status ) ) || is_post_type_hierarchical( $post->post_type ) ) { + if ( ! ( 'publish' === $post->post_status || ( 'attachment' === $post->post_type && 'inherit' === $post->post_status ) ) + || is_post_type_hierarchical( $post->post_type ) + ) { return; } @@ -7081,12 +7305,14 @@ $new_date = gmdate( 'Y-m-d', strtotime( $post->post_date ) ); // Don't bother if it hasn't changed. - if ( $new_date == $previous_date ) { + if ( $new_date === $previous_date ) { return; } // We're only concerned with published, non-hierarchical objects. - if ( ! ( 'publish' === $post->post_status || ( 'attachment' === get_post_type( $post ) && 'inherit' === $post->post_status ) ) || is_post_type_hierarchical( $post->post_type ) ) { + if ( ! ( 'publish' === $post->post_status || ( 'attachment' === $post->post_type && 'inherit' === $post->post_status ) ) + || is_post_type_hierarchical( $post->post_type ) + ) { return; } @@ -7182,7 +7408,7 @@ $id = get_current_user_id(); if ( null === $post_author || ! $full ) { $post_status_sql .= " OR post_status = 'private' AND post_author = $id"; - } elseif ( $id == (int) $post_author ) { + } elseif ( $id === (int) $post_author ) { $post_status_sql .= " OR post_status = 'private'"; } // Else none. } // Else none. @@ -7758,7 +7984,7 @@ } // Can't be its own parent. - if ( $post_parent == $post_id ) { + if ( $post_parent === $post_id ) { return 0; } @@ -7793,7 +8019,10 @@ * * @param int|WP_Post $post Post ID or post object where thumbnail should be attached. * @param int $thumbnail_id Thumbnail to attach. - * @return int|bool True on success, false on failure. + * @return int|bool Post meta ID if the key didn't exist (ie. this is the first time that + * a thumbnail has been saved for the post), true on successful update, + * false on failure or if the value passed is the same as the one that + * is already in the database. */ function set_post_thumbnail( $post, $thumbnail_id ) { $post = get_post( $post );