rs the attachment meta data.
*
* @since 2.1.0
*
* @param array $data Array of meta data for the given attachment.
* @param int $attachment_id Attachment post ID.
*/
return apply_filters( 'wp_get_attachment_metadata', $data, $attachment_id );
}
/**
* Updates metadata for an attachment.
*
* @since 2.1.0
*
* @param int $attachment_id Attachment post ID.
* @param array $data Attachment meta data.
* @return int|false False if $post is invalid.
*/
function wp_update_attachment_metadata( $attachment_id, $data ) {
$attachment_id = (int) $attachment_id;
$post = get_post( $attachment_id );
if ( ! $post ) {
return false;
}
/**
* Filters the updated attachment meta data.
*
* @since 2.1.0
*
* @param array $data Array of updated attachment meta data.
* @param int $attachment_id Attachment post ID.
*/
$data = apply_filters( 'wp_update_attachment_metadata', $data, $post->ID );
if ( $data ) {
return update_post_meta( $post->ID, '_wp_attachment_metadata', $data );
} else {
return delete_post_meta( $post->ID, '_wp_attachment_metadata' );
}
}
/**
* Retrieves the URL for an attachment.
*
* @since 2.1.0
*
* @global string $pagenow The filename of the current screen.
*
* @param int $attachment_id Optional. Attachment post ID. Defaults to global $post.
* @return string|false Attachment URL, otherwise false.
*/
function wp_get_attachment_url( $attachment_id = 0 ) {
global $pagenow;
$attachment_id = (int) $attachment_id;
$post = get_post( $attachment_id );
if ( ! $post ) {
return false;
}
if ( 'attachment' !== $post->post_type ) {
return false;
}
$url = '';
// Get attached file.
$file = get_post_meta( $post->ID, '_wp_attached_file', true );
if ( $file ) {
// Get upload directory.
$uploads = wp_get_upload_dir();
if ( $uploads && false === $uploads['error'] ) {
// Check that the upload base exists in the file location.
if ( str_starts_with( $file, $uploads['basedir'] ) ) {
// Replace file location with url location.
$url = str_replace( $uploads['basedir'], $uploads['baseurl'], $file );
} elseif ( str_contains( $file, 'wp-content/uploads' ) ) {
// Get the directory name relative to the basedir (back compat for pre-2.7 uploads).
$url = trailingslashit( $uploads['baseurl'] . '/' . _wp_get_attachment_relative_path( $file ) ) . wp_basename( $file );
} else {
// It's a newly-uploaded file, therefore $file is relative to the basedir.
$url = $uploads['baseurl'] . "/$file";
}
}
}
/*
* If any of the above options failed, Fallback on the GUID as used pre-2.7,
* not recommended to rely upon this.
*/
if ( ! $url ) {
$url = get_the_guid( $post->ID );
}
// On SSL front end, URLs should be HTTPS.
if ( is_ssl() && ! is_admin() && 'wp-login.php' !== $pagenow ) {
$url = set_url_scheme( $url );
}
/**
* Filters the attachment URL.
*
* @since 2.1.0
*
* @param string $url URL for the given attachment.
* @param int $attachment_id Attachment post ID.
*/
$url = apply_filters( 'wp_get_attachment_url', $url, $post->ID );
if ( ! $url ) {
return false;
}
return $url;
}
/**
* Retrieves the caption for an attachment.
*
* @since 4.6.0
*
* @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`.
* @return string|false Attachment caption on success, false on failure.
*/
function wp_get_attachment_caption( $post_id = 0 ) {
$post_id = (int) $post_id;
$post = get_post( $post_id );
if ( ! $post ) {
return false;
}
if ( 'attachment' !== $post->post_type ) {
return false;
}
$caption = $post->post_excerpt;
/**
* Filters the attachment caption.
*
* @since 4.6.0
*
* @param string $caption Caption for the given attachment.
* @param int $post_id Attachment ID.
*/
return apply_filters( 'wp_get_attachment_caption', $caption, $post->ID );
}
/**
* Retrieves URL for an attachment thumbnail.
*
* @since 2.1.0
* @since 6.1.0 Changed to use wp_get_attachment_image_url().
*
* @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`.
* @return string|false Thumbnail URL on success, false on failure.
*/
function wp_get_attachment_thumb_url( $post_id = 0 ) {
$post_id = (int) $post_id;
/*
* This uses image_downsize() which also looks for the (very) old format $image_meta['thumb']
* when the newer format $image_meta['sizes']['thumbnail'] doesn't exist.
*/
$thumbnail_url = wp_get_attachment_image_url( $post_id, 'thumbnail' );
if ( empty( $thumbnail_url ) ) {
return false;
}
/**
* Filters the attachment thumbnail URL.
*
* @since 2.1.0
*
* @param string $thumbnail_url URL for the attachment thumbnail.
* @param int $post_id Attachment ID.
*/
return apply_filters( 'wp_get_attachment_thumb_url', $thumbnail_url, $post_id );
}
/**
* Verifies an attachment is of a given type.
*
* @since 4.2.0
*
* @param string $type Attachment type. Accepts `image`, `audio`, `video`, or a file extension.
* @param int|WP_Post $post Optional. Attachment ID or object. Default is global $post.
* @return bool True if an accepted type or a matching file extension, false otherwise.
*/
function wp_attachment_is( $type, $post = null ) {
$post = get_post( $post );
if ( ! $post ) {
return false;
}
$file = get_attached_file( $post->ID );
if ( ! $file ) {
return false;
}
if ( str_starts_with( $post->post_mime_type, $type . '/' ) ) {
return true;
}
$check = wp_check_filetype( $file );
if ( empty( $check['ext'] ) ) {
return false;
}
$ext = $check['ext'];
if ( 'import' !== $post->post_mime_type ) {
return $type === $ext;
}
switch ( $type ) {
case 'image':
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp', 'avif' );
return in_array( $ext, $image_exts, true );
case 'audio':
return in_array( $ext, wp_get_audio_extensions(), true );
case 'video':
return in_array( $ext, wp_get_video_extensions(), true );
default:
return $type === $ext;
}
}
/**
* Determines whether an attachment is an image.
*
* For more information on this and similar theme functions, check out
* the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
* Conditional Tags} article in the Theme Developer Handbook.
*
* @since 2.1.0
* @since 4.2.0 Modified into wrapper for wp_attachment_is() and
* allowed WP_Post object to be passed.
*
* @param int|WP_Post $post Optional. Attachment ID or object. Default is global $post.
* @return bool Whether the attachment is an image.
*/
function wp_attachment_is_image( $post = null ) {
return wp_attachment_is( 'image', $post );
}
/**
* Retrieves the icon for a MIME type or attachment.
*
* @since 2.1.0
* @since 6.5.0 Added the `$preferred_ext` parameter.
*
* @param string|int $mime MIME type or attachment ID.
* @param string $preferred_ext File format to prefer in return. Default '.png'.
* @return string|false Icon, false otherwise.
*/
function wp_mime_type_icon( $mime = 0, $preferred_ext = '.png' ) {
if ( ! is_numeric( $mime ) ) {
$icon = wp_cache_get( "mime_type_icon_$mime" );
}
// Check if preferred file format variable is present and is a validly formatted file extension.
if ( ! empty( $preferred_ext ) && is_string( $preferred_ext ) && ! str_starts_with( $preferred_ext, '.' ) ) {
$preferred_ext = '.' . strtolower( $preferred_ext );
}
$post_id = 0;
if ( empty( $icon ) ) {
$post_mimes = array();
if ( is_numeric( $mime ) ) {
$mime = (int) $mime;
$post = get_post( $mime );
if ( $post ) {
$post_id = (int) $post->ID;
$file = get_attached_file( $post_id );
$ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $file );
if ( ! empty( $ext ) ) {
$post_mimes[] = $ext;
$ext_type = wp_ext2type( $ext );
if ( $ext_type ) {
$post_mimes[] = $ext_type;
}
}
$mime = $post->post_mime_type;
} else {
$mime = 0;
}
} else {
$post_mimes[] = $mime;
}
$icon_files = wp_cache_get( 'icon_files' );
if ( ! is_array( $icon_files ) ) {
/**
* Filters the icon directory path.
*
* @since 2.0.0
*
* @param string $path Icon directory absolute path.
*/
$icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
/**
* Filters the icon directory URI.
*
* @since 2.0.0
*
* @param string $uri Icon directory URI.
*/
$icon_dir_uri = apply_filters( 'icon_dir_uri', includes_url( 'images/media' ) );
/**
* Filters the array of icon directory URIs.
*
* @since 2.5.0
*
* @param string[] $uris Array of icon directory URIs keyed by directory absolute path.
*/
$dirs = apply_filters( 'icon_dirs', array( $icon_dir => $icon_dir_uri ) );
$icon_files = array();
$all_icons = array();
while ( $dirs ) {
$keys = array_keys( $dirs );
$dir = array_shift( $keys );
$uri = array_shift( $dirs );
$dh = opendir( $dir );
if ( $dh ) {
while ( false !== $file = readdir( $dh ) ) {
$file = wp_basename( $file );
if ( str_starts_with( $file, '.' ) ) {
continue;
}
$ext = strtolower( substr( $file, -4 ) );
if ( ! in_array( $ext, array( '.svg', '.png', '.gif', '.jpg' ), true ) ) {
if ( is_dir( "$dir/$file" ) ) {
$dirs[ "$dir/$file" ] = "$uri/$file";
}
continue;
}
$all_icons[ "$dir/$file" ] = "$uri/$file";
if ( $ext === $preferred_ext ) {
$icon_files[ "$dir/$file" ] = "$uri/$file";
}
}
closedir( $dh );
}
}
// If directory only contained icons of a non-preferred format, return those.
if ( empty( $icon_files ) ) {
$icon_files = $all_icons;
}
wp_cache_add( 'icon_files', $icon_files, 'default', 600 );
}
$types = array();
// Icon wp_basename - extension = MIME wildcard.
foreach ( $icon_files as $file => $uri ) {
$types[ preg_replace( '/^([^.]*).*$/', '$1', wp_basename( $file ) ) ] =& $icon_files[ $file ];
}
if ( ! empty( $mime ) ) {
$post_mimes[] = substr( $mime, 0, strpos( $mime, '/' ) );
$post_mimes[] = substr( $mime, strpos( $mime, '/' ) + 1 );
$post_mimes[] = str_replace( '/', '_', $mime );
}
$matches = wp_match_mime_types( array_keys( $types ), $post_mimes );
$matches['default'] = array( 'default' );
foreach ( $matches as $match => $wilds ) {
foreach ( $wilds as $wild ) {
if ( ! isset( $types[ $wild ] ) ) {
continue;
}
$icon = $types[ $wild ];
if ( ! is_numeric( $mime ) ) {
wp_cache_add( "mime_type_icon_$mime", $icon );
}
break 2;
}
}
}
/**
* Filters the mime type icon.
*
* @since 2.1.0
*
* @param string $icon Path to the mime type icon.
* @param string $mime Mime type.
* @param int $post_id Attachment ID. Will equal 0 if the function passed
* the mime type.
*/
return apply_filters( 'wp_mime_type_icon', $icon, $mime, $post_id );
}
/**
* Checks for changed slugs for published post objects and save the old slug.
*
* The function is used when a post object of any type is updated,
* by comparing the current and previous post objects.
*
* If the slug was changed and not already part of the old slugs then it will be
* added to the post meta field ('_wp_old_slug') for storing old slugs for that
* post.
*
* The most logically usage of this function is redirecting changed post objects, so
* that those that linked to an changed post will be redirected to the new post.
*
* @since 2.1.0
*
* @param int $post_id Post ID.
* @param WP_Post $post The post object.
* @param WP_Post $post_before The previous post object.
*/
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 ) {
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 ) ) {
return;
}
$old_slugs = (array) get_post_meta( $post_id, '_wp_old_slug' );
// If we haven't added this old slug before, add it now.
if ( ! empty( $post_before->post_name ) && ! in_array( $post_before->post_name, $old_slugs, true ) ) {
add_post_meta( $post_id, '_wp_old_slug', $post_before->post_name );
}
// If the new slug was used previously, delete it from the list.
if ( in_array( $post->post_name, $old_slugs, true ) ) {
delete_post_meta( $post_id, '_wp_old_slug', $post->post_name );
}
}
/**
* Checks for changed dates for published post objects and save the old date.
*
* The function is used when a post object of any type is updated,
* by comparing the current and previous post objects.
*
* If the date was changed and not already part of the old dates then it will be
* added to the post meta field ('_wp_old_date') for storing old dates for that
* post.
*
* The most logically usage of this function is redirecting changed post objects, so
* that those that linked to an changed post will be redirected to the new post.
*
* @since 4.9.3
*
* @param int $post_id Post ID.
* @param WP_Post $post The post object.
* @param WP_Post $post_before The previous post object.
*/
function wp_check_for_changed_dates( $post_id, $post, $post_before ) {
$previous_date = gmdate( 'Y-m-d', strtotime( $post_before->post_date ) );
$new_date = gmdate( 'Y-m-d', strtotime( $post->post_date ) );
// Don't bother if it hasn't changed.
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 ) ) {
return;
}
$old_dates = (array) get_post_meta( $post_id, '_wp_old_date' );
// If we haven't added this old date before, add it now.
if ( ! empty( $previous_date ) && ! in_array( $previous_date, $old_dates, true ) ) {
add_post_meta( $post_id, '_wp_old_date', $previous_date );
}
// If the new slug was used previously, delete it from the list.
if ( in_array( $new_date, $old_dates, true ) ) {
delete_post_meta( $post_id, '_wp_old_date', $new_date );
}
}
/**
* Retrieves the private post SQL based on capability.
*
* This function provides a standardized way to appropriately select on the
* post_status of a post type. The function will return a piece of SQL code
* that can be added to a WHERE clause; this SQL is constructed to allow all
* published posts, and all private posts to which the user has access.
*
* @since 2.2.0
* @since 4.3.0 Added the ability to pass an array to `$post_type`.
*
* @param string|array $post_type Single post type or an array of post types. Currently only supports 'post' or 'page'.
* @return string SQL code that can be added to a where clause.
*/
function get_private_posts_cap_sql( $post_type ) {
return get_posts_by_author_sql( $post_type, false );
}
/**
* Retrieves the post SQL based on capability, author, and type.
*
* @since 3.0.0
* @since 4.3.0 Introduced the ability to pass an array of post types to `$post_type`.
*
* @see get_private_posts_cap_sql()
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string|string[] $post_type Single post type or an array of post types.
* @param bool $full Optional. Returns a full WHERE statement instead of just
* an 'andalso' term. Default true.
* @param int $post_author Optional. Query posts having a single author ID. Default null.
* @param bool $public_only Optional. Only return public posts. Skips cap checks for
* $current_user. Default false.
* @return string SQL WHERE code that can be added to a query.
*/
function get_posts_by_author_sql( $post_type, $full = true, $post_author = null, $public_only = false ) {
global $wpdb;
if ( is_array( $post_type ) ) {
$post_types = $post_type;
} else {
$post_types = array( $post_type );
}
$post_type_clauses = array();
foreach ( $post_types as $post_type ) {
$post_type_obj = get_post_type_object( $post_type );
if ( ! $post_type_obj ) {
continue;
}
/**
* Filters the capability to read private posts for a custom post type
* when generating SQL for getting posts by author.
*
* @since 2.2.0
* @deprecated 3.2.0 The hook transitioned from "somewhat useless" to "totally useless".
*
* @param string $cap Capability.
*/
$cap = apply_filters_deprecated( 'pub_priv_sql_capability', array( '' ), '3.2.0' );
if ( ! $cap ) {
$cap = current_user_can( $post_type_obj->cap->read_private_posts );
}
// Only need to check the cap if $public_only is false.
$post_status_sql = "post_status = 'publish'";
if ( false === $public_only ) {
if ( $cap ) {
// Does the user have the capability to view private posts? Guess so.
$post_status_sql .= " OR post_status = 'private'";
} elseif ( is_user_logged_in() ) {
// Users can view their own private posts.
$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 ) {
$post_status_sql .= " OR post_status = 'private'";
} // Else none.
} // Else none.
}
$post_type_clauses[] = "( post_type = '" . $post_type . "' AND ( $post_status_sql ) )";
}
if ( empty( $post_type_clauses ) ) {
return $full ? 'WHERE 1 = 0' : '1 = 0';
}
$sql = '( ' . implode( ' OR ', $post_type_clauses ) . ' )';
if ( null !== $post_author ) {
$sql .= $wpdb->prepare( ' AND post_author = %d', $post_author );
}
if ( $full ) {
$sql = 'WHERE ' . $sql;
}
return $sql;
}
/**
* Retrieves the most recent time that a post on the site was published.
*
* The server timezone is the default and is the difference between GMT and
* server time. The 'blog' value is the date when the last post was posted.
* The 'gmt' is when the last post was posted in GMT formatted date.
*
* @since 0.71
* @since 4.4.0 The `$post_type` argument was added.
*
* @param string $timezone Optional. The timezone for the timestamp. Accepts 'server', 'blog', or 'gmt'.
* 'server' uses the server's internal timezone.
* 'blog' uses the `post_date` field, which proxies to the timezone set for the site.
* 'gmt' uses the `post_date_gmt` field.
* Default 'server'.
* @param string $post_type Optional. The post type to check. Default 'any'.
* @return string The date of the last post, or false on failure.
*/
function get_lastpostdate( $timezone = 'server', $post_type = 'any' ) {
$lastpostdate = _get_last_post_time( $timezone, 'date', $post_type );
/**
* Filters the most recent time that a post on the site was published.
*
* @since 2.3.0
* @since 5.5.0 Added the `$post_type` parameter.
*
* @param string|false $lastpostdate The most recent time that a post was published,
* in 'Y-m-d H:i:s' format. False on failure.
* @param string $timezone Location to use for getting the post published date.
* See get_lastpostdate() for accepted `$timezone` values.
* @param string $post_type The post type to check.
*/
return apply_filters( 'get_lastpostdate', $lastpostdate, $timezone, $post_type );
}
/**
* Gets the most recent time that a post on the site was modified.
*
* The server timezone is the default and is the difference between GMT and
* server time. The 'blog' value is just when the last post was modified.
* The 'gmt' is when the last post was modified in GMT time.
*
* @since 1.2.0
* @since 4.4.0 The `$post_type` argument was added.
*
* @param string $timezone Optional. The timezone for the timestamp. See get_lastpostdate()
* for information on accepted values.
* Default 'server'.
* @param string $post_type Optional. The post type to check. Default 'any'.
* @return string The timestamp in 'Y-m-d H:i:s' format, or false on failure.
*/
function get_lastpostmodified( $timezone = 'server', $post_type = 'any' ) {
/**
* Pre-filter the return value of get_lastpostmodified() before the query is run.
*
* @since 4.4.0
*
* @param string|false $lastpostmodified The most recent time that a post was modified,
* in 'Y-m-d H:i:s' format, or false. Returning anything
* other than false will short-circuit the function.
* @param string $timezone Location to use for getting the post modified date.
* See get_lastpostdate() for accepted `$timezone` values.
* @param string $post_type The post type to check.
*/
$lastpostmodified = apply_filters( 'pre_get_lastpostmodified', false, $timezone, $post_type );
if ( false !== $lastpostmodified ) {
return $lastpostmodified;
}
$lastpostmodified = _get_last_post_time( $timezone, 'modified', $post_type );
$lastpostdate = get_lastpostdate( $timezone, $post_type );
if ( $lastpostdate > $lastpostmodified ) {
$lastpostmodified = $lastpostdate;
}
/**
* Filters the most recent time that a post on the site was modified.
*
* @since 2.3.0
* @since 5.5.0 Added the `$post_type` parameter.
*
* @param string|false $lastpostmodified The most recent time that a post was modified,
* in 'Y-m-d H:i:s' format. False on failure.
* @param string $timezone Location to use for getting the post modified date.
* See get_lastpostdate() for accepted `$timezone` values.
* @param string $post_type The post type to check.
*/
return apply_filters( 'get_lastpostmodified', $lastpostmodified, $timezone, $post_type );
}
/**
* Gets the timestamp of the last time any post was modified or published.
*
* @since 3.1.0
* @since 4.4.0 The `$post_type` argument was added.
* @access private
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $timezone The timezone for the timestamp. See get_lastpostdate().
* for information on accepted values.
* @param string $field Post field to check. Accepts 'date' or 'modified'.
* @param string $post_type Optional. The post type to check. Default 'any'.
* @return string|false The timestamp in 'Y-m-d H:i:s' format, or false on failure.
*/
function _get_last_post_time( $timezone, $field, $post_type = 'any' ) {
global $wpdb;
if ( ! in_array( $field, array( 'date', 'modified' ), true ) ) {
return false;
}
$timezone = strtolower( $timezone );
$key = "lastpost{$field}:$timezone";
if ( 'any' !== $post_type ) {
$key .= ':' . sanitize_key( $post_type );
}
$date = wp_cache_get( $key, 'timeinfo' );
if ( false !== $date ) {
return $date;
}
if ( 'any' === $post_type ) {
$post_types = get_post_types( array( 'public' => true ) );
array_walk( $post_types, array( $wpdb, 'escape_by_ref' ) );
$post_types = "'" . implode( "', '", $post_types ) . "'";
} else {
$post_types = "'" . sanitize_key( $post_type ) . "'";
}
switch ( $timezone ) {
case 'gmt':
$date = $wpdb->get_var( "SELECT post_{$field}_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
break;
case 'blog':
$date = $wpdb->get_var( "SELECT post_{$field} FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
break;
case 'server':
$add_seconds_server = gmdate( 'Z' );
$date = $wpdb->get_var( "SELECT DATE_ADD(post_{$field}_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
break;
}
if ( $date ) {
wp_cache_set( $key, $date, 'timeinfo' );
return $date;
}
return false;
}
/**
* Updates posts in cache.
*
* @since 1.5.1
*
* @param WP_Post[] $posts Array of post objects (passed by reference).
*/
function update_post_cache( &$posts ) {
if ( ! $posts ) {
return;
}
$data = array();
foreach ( $posts as $post ) {
if ( empty( $post->filter ) || 'raw' !== $post->filter ) {
$post = sanitize_post( $post, 'raw' );
}
$data[ $post->ID ] = $post;
}
wp_cache_add_multiple( $data, 'posts' );
}
/**
* Will clean the post in the cache.
*
* Cleaning means delete from the cache of the post. Will call to clean the term
* object cache associated with the post ID.
*
* This function not run if $_wp_suspend_cache_invalidation is not empty. See
* wp_suspend_cache_invalidation().
*
* @since 2.0.0
*
* @global bool $_wp_suspend_cache_invalidation
*
* @param int|WP_Post $post Post ID or post object to remove from the cache.
*/
function clean_post_cache( $post ) {
global $_wp_suspend_cache_invalidation;
if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
return;
}
$post = get_post( $post );
if ( ! $post ) {
return;
}
wp_cache_delete( $post->ID, 'posts' );
wp_cache_delete( 'post_parent:' . (string) $post->ID, 'posts' );
wp_cache_delete( $post->ID, 'post_meta' );
clean_object_term_cache( $post->ID, $post->post_type );
wp_cache_delete( 'wp_get_archives', 'general' );
/**
* Fires immediately after the given post's cache is cleaned.
*
* @since 2.5.0
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
do_action( 'clean_post_cache', $post->ID, $post );
if ( 'page' === $post->post_type ) {
wp_cache_delete( 'all_page_ids', 'posts' );
/**
* Fires immediately after the given page's cache is cleaned.
*
* @since 2.5.0
*
* @param int $post_id Post ID.
*/
do_action( 'clean_page_cache', $post->ID );
}
wp_cache_set_posts_last_changed();
}
/**
* Updates post, term, and metadata caches for a list of post objects.
*
* @since 1.5.0
*
* @param WP_Post[] $posts Array of post objects (passed by reference).
* @param string $post_type Optional. Post type. Default 'post'.
* @param bool $update_term_cache Optional. Whether to update the term cache. Default true.
* @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true.
*/
function update_post_caches( &$posts, $post_type = 'post', $update_term_cache = true, $update_meta_cache = true ) {
// No point in doing all this work if we didn't match any posts.
if ( ! $posts ) {
return;
}
update_post_cache( $posts );
$post_ids = array();
foreach ( $posts as $post ) {
$post_ids[] = $post->ID;
}
if ( ! $post_type ) {
$post_type = 'any';
}
if ( $update_term_cache ) {
if ( is_array( $post_type ) ) {
$ptypes = $post_type;
} elseif ( 'any' === $post_type ) {
$ptypes = array();
// Just use the post_types in the supplied posts.
foreach ( $posts as $post ) {
$ptypes[] = $post->post_type;
}
$ptypes = array_unique( $ptypes );
} else {
$ptypes = array( $post_type );
}
if ( ! empty( $ptypes ) ) {
update_object_term_cache( $post_ids, $ptypes );
}
}
if ( $update_meta_cache ) {
update_postmeta_cache( $post_ids );
}
}
/**
* Updates post author user caches for a list of post objects.
*
* @since 6.1.0
*
* @param WP_Post[] $posts Array of post objects.
*/
function update_post_author_caches( $posts ) {
/*
* cache_users() is a pluggable function so is not available prior
* to the `plugins_loaded` hook firing. This is to ensure against
* fatal errors when the function is not available.
*/
if ( ! function_exists( 'cache_users' ) ) {
return;
}
$author_ids = wp_list_pluck( $posts, 'post_author' );
$author_ids = array_map( 'absint', $author_ids );
$author_ids = array_unique( array_filter( $author_ids ) );
cache_users( $author_ids );
}
/**
* Updates parent post caches for a list of post objects.
*
* @since 6.1.0
*
* @param WP_Post[] $posts Array of post objects.
*/
function update_post_parent_caches( $posts ) {
$parent_ids = wp_list_pluck( $posts, 'post_parent' );
$parent_ids = array_map( 'absint', $parent_ids );
$parent_ids = array_unique( array_filter( $parent_ids ) );
if ( ! empty( $parent_ids ) ) {
_prime_post_caches( $parent_ids, false );
}
}
/**
* Updates metadata cache for a list of post IDs.
*
* Performs SQL query to retrieve the metadata for the post IDs and updates the
* metadata cache for the posts. Therefore, the functions, which call this
* function, do not need to perform SQL queries on their own.
*
* @since 2.1.0
*
* @param int[] $post_ids Array of post IDs.
* @return array|false An array of metadata on success, false if there is nothing to update.
*/
function update_postmeta_cache( $post_ids ) {
return update_meta_cache( 'post', $post_ids );
}
/**
* Will clean the attachment in the cache.
*
* Cleaning means delete from the cache. Optionally will clean the term
* object cache associated with the attachment ID.
*
* This function will not run if $_wp_suspend_cache_invalidation is not empty.
*
* @since 3.0.0
*
* @global bool $_wp_suspend_cache_invalidation
*
* @param int $id The attachment ID in the cache to clean.
* @param bool $clean_terms Optional. Whether to clean terms cache. Default false.
*/
function clean_attachment_cache( $id, $clean_terms = false ) {
global $_wp_suspend_cache_invalidation;
if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
return;
}
$id = (int) $id;
wp_cache_delete( $id, 'posts' );
wp_cache_delete( $id, 'post_meta' );
if ( $clean_terms ) {
clean_object_term_cache( $id, 'attachment' );
}
/**
* Fires after the given attachment's cache is cleaned.
*
* @since 3.0.0
*
* @param int $id Attachment ID.
*/
do_action( 'clean_attachment_cache', $id );
}
//
// Hooks.
//
/**
* Hook for managing future post transitions to published.
*
* @since 2.3.0
* @access private
*
* @see wp_clear_scheduled_hook()
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $new_status New post status.
* @param string $old_status Previous post status.
* @param WP_Post $post Post object.
*/
function _transition_post_status( $new_status, $old_status, $post ) {
global $wpdb;
if ( 'publish' !== $old_status && 'publish' === $new_status ) {
// Reset GUID if transitioning to publish and it is empty.
if ( '' === get_the_guid( $post->ID ) ) {
$wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post->ID ) ), array( 'ID' => $post->ID ) );
}
/**
* Fires when a post's status is transitioned from private to published.
*
* @since 1.5.0
* @deprecated 2.3.0 Use {@see 'private_to_publish'} instead.
*
* @param int $post_id Post ID.
*/
do_action_deprecated( 'private_to_published', array( $post->ID ), '2.3.0', 'private_to_publish' );
}
// If published posts changed clear the lastpostmodified cache.
if ( 'publish' === $new_status || 'publish' === $old_status ) {
foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
wp_cache_delete( "lastpostmodified:$timezone", 'timeinfo' );
wp_cache_delete( "lastpostdate:$timezone", 'timeinfo' );
wp_cache_delete( "lastpostdate:$timezone:{$post->post_type}", 'timeinfo' );
}
}
if ( $new_status !== $old_status ) {
wp_cache_delete( _count_posts_cache_key( $post->post_type ), 'counts' );
wp_cache_delete( _count_posts_cache_key( $post->post_type, 'readable' ), 'counts' );
}
// Always clears the hook in case the post status bounced from future to draft.
wp_clear_scheduled_hook( 'publish_future_post', array( $post->ID ) );
}
/**
* Hook used to schedule publication for a post marked for the future.
*
* The $post properties used and must exist are 'ID' and 'post_date_gmt'.
*
* @since 2.3.0
* @access private
*
* @param int $deprecated Not used. Can be set to null. Never implemented. Not marked
* as deprecated with _deprecated_argument() as it conflicts with
* wp_transition_post_status() and the default filter for _future_post_hook().
* @param WP_Post $post Post object.
*/
function _future_post_hook( $deprecated, $post ) {
wp_clear_scheduled_hook( 'publish_future_post', array( $post->ID ) );
wp_schedule_single_event( strtotime( get_gmt_from_date( $post->post_date ) . ' GMT' ), 'publish_future_post', array( $post->ID ) );
}
/**
* Hook to schedule pings and enclosures when a post is published.
*
* Uses XMLRPC_REQUEST and WP_IMPORTING constants.
*
* @since 2.3.0
* @access private
*
* @param int $post_id The ID of the post being published.
*/
function _publish_post_hook( $post_id ) {
if ( defined( 'XMLRPC_REQUEST' ) ) {
/**
* Fires when _publish_post_hook() is called during an XML-RPC request.
*
* @since 2.1.0
*
* @param int $post_id Post ID.
*/
do_action( 'xmlrpc_publish_post', $post_id );
}
if ( defined( 'WP_IMPORTING' ) ) {
return;
}
if ( get_option( 'default_pingback_flag' ) ) {
add_post_meta( $post_id, '_pingme', '1', true );
}
add_post_meta( $post_id, '_encloseme', '1', true );
$to_ping = get_to_ping( $post_id );
if ( ! empty( $to_ping ) ) {
add_post_meta( $post_id, '_trackbackme', '1' );
}
if ( ! wp_next_scheduled( 'do_pings' ) ) {
wp_schedule_single_event( time(), 'do_pings' );
}
}
/**
* Returns the ID of the post's parent.
*
* @since 3.1.0
* @since 5.9.0 The `$post` parameter was made optional.
*
* @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post.
* @return int|false Post parent ID (which can be 0 if there is no parent),
* or false if the post does not exist.
*/
function wp_get_post_parent_id( $post = null ) {
$post = get_post( $post );
if ( ! $post || is_wp_error( $post ) ) {
return false;
}
return (int) $post->post_parent;
}
/**
* Checks the given subset of the post hierarchy for hierarchy loops.
*
* Prevents loops from forming and breaks those that it finds. Attached
* to the {@see 'wp_insert_post_parent'} filter.
*
* @since 3.1.0
*
* @see wp_find_hierarchy_loop()
*
* @param int $post_parent ID of the parent for the post we're checking.
* @param int $post_id ID of the post we're checking.
* @return int The new post_parent for the post, 0 otherwise.
*/
function wp_check_post_hierarchy_for_loops( $post_parent, $post_id ) {
// Nothing fancy here - bail.
if ( ! $post_parent ) {
return 0;
}
// New post can't cause a loop.
if ( ! $post_id ) {
return $post_parent;
}
// Can't be its own parent.
if ( $post_parent == $post_id ) {
return 0;
}
// Now look for larger loops.
$loop = wp_find_hierarchy_loop( 'wp_get_post_parent_id', $post_id, $post_parent );
if ( ! $loop ) {
return $post_parent; // No loop.
}
// Setting $post_parent to the given value causes a loop.
if ( isset( $loop[ $post_id ] ) ) {
return 0;
}
// There's a loop, but it doesn't contain $post_id. Break the loop.
foreach ( array_keys( $loop ) as $loop_member ) {
wp_update_post(
array(
'ID' => $loop_member,
'post_parent' => 0,
)
);
}
return $post_parent;
}
/**
* Sets the post thumbnail (featured image) for the given post.
*
* @since 3.1.0
*
* @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.
*/
function set_post_thumbnail( $post, $thumbnail_id ) {
$post = get_post( $post );
$thumbnail_id = absint( $thumbnail_id );
if ( $post && $thumbnail_id && get_post( $thumbnail_id ) ) {
if ( wp_get_attachment_image( $thumbnail_id, 'thumbnail' ) ) {
return update_post_meta( $post->ID, '_thumbnail_id', $thumbnail_id );
} else {
return delete_post_meta( $post->ID, '_thumbnail_id' );
}
}
return false;
}
/**
* Removes the thumbnail (featured image) from the given post.
*
* @since 3.3.0
*
* @param int|WP_Post $post Post ID or post object from which the thumbnail should be removed.
* @return bool True on success, false on failure.
*/
function delete_post_thumbnail( $post ) {
$post = get_post( $post );
if ( $post ) {
return delete_post_meta( $post->ID, '_thumbnail_id' );
}
return false;
}
/**
* Deletes auto-drafts for new posts that are > 7 days old.
*
* @since 3.4.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*/
function wp_delete_auto_drafts() {
global $wpdb;
// Cleanup old auto-drafts more than 7 days old.
$old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
foreach ( (array) $old_posts as $delete ) {
// Force delete.
wp_delete_post( $delete, true );
}
}
/**
* Queues posts for lazy-loading of term meta.
*
* @since 4.5.0
*
* @param WP_Post[] $posts Array of WP_Post objects.
*/
function wp_queue_posts_for_term_meta_lazyload( $posts ) {
$post_type_taxonomies = array();
$prime_post_terms = array();
foreach ( $posts as $post ) {
if ( ! ( $post instanceof WP_Post ) ) {
continue;
}
if ( ! isset( $post_type_taxonomies[ $post->post_type ] ) ) {
$post_type_taxonomies[ $post->post_type ] = get_object_taxonomies( $post->post_type );
}
foreach ( $post_type_taxonomies[ $post->post_type ] as $taxonomy ) {
$prime_post_terms[ $taxonomy ][] = $post->ID;
}
}
$term_ids = array();
if ( $prime_post_terms ) {
foreach ( $prime_post_terms as $taxonomy => $post_ids ) {
$cached_term_ids = wp_cache_get_multiple( $post_ids, "{$taxonomy}_relationships" );
if ( is_array( $cached_term_ids ) ) {
$cached_term_ids = array_filter( $cached_term_ids );
foreach ( $cached_term_ids as $_term_ids ) {
// Backward compatibility for if a plugin is putting objects into the cache, rather than IDs.
foreach ( $_term_ids as $term_id ) {
if ( is_numeric( $term_id ) ) {
$term_ids[] = (int) $term_id;
} elseif ( isset( $term_id->term_id ) ) {
$term_ids[] = (int) $term_id->term_id;
}
}
}
}
}
$term_ids = array_unique( $term_ids );
}
wp_lazyload_term_meta( $term_ids );
}
/**
* Updates the custom taxonomies' term counts when a post's status is changed.
*
* For example, default posts term counts (for custom taxonomies) don't include
* private / draft posts.
*
* @since 3.3.0
* @access private
*
* @param string $new_status New post status.
* @param string $old_status Old post status.
* @param WP_Post $post Post object.
*/
function _update_term_count_on_transition_post_status( $new_status, $old_status, $post ) {
// Update counts for the post's terms.
foreach ( (array) get_object_taxonomies( $post->post_type ) as $taxonomy ) {
$tt_ids = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'tt_ids' ) );
wp_update_term_count( $tt_ids, $taxonomy );
}
}
/**
* Adds any posts from the given IDs to the cache that do not already exist in cache.
*
* @since 3.4.0
* @since 6.1.0 This function is no longer marked as "private".
*
* @see update_post_cache()
* @see update_postmeta_cache()
* @see update_object_term_cache()
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param int[] $ids ID list.
* @param bool $update_term_cache Optional. Whether to update the term cache. Default true.
* @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true.
*/
function _prime_post_caches( $ids, $update_term_cache = true, $update_meta_cache = true ) {
global $wpdb;
$non_cached_ids = _get_non_cached_ids( $ids, 'posts' );
if ( ! empty( $non_cached_ids ) ) {
$fresh_posts = $wpdb->get_results( sprintf( "SELECT $wpdb->posts.* FROM $wpdb->posts WHERE ID IN (%s)", implode( ',', $non_cached_ids ) ) );
if ( $fresh_posts ) {
// Despite the name, update_post_cache() expects an array rather than a single post.
update_post_cache( $fresh_posts );
}
}
if ( $update_meta_cache ) {
update_postmeta_cache( $ids );
}
if ( $update_term_cache ) {
$post_types = array_map( 'get_post_type', $ids );
$post_types = array_unique( $post_types );
update_object_term_cache( $ids, $post_types );
}
}
/**
* Prime the cache containing the parent ID of various post objects.
*
* @since 6.4.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param int[] $ids ID list.
*/
function _prime_post_parent_id_caches( array $ids ) {
global $wpdb;
$ids = array_filter( $ids, '_validate_cache_id' );
$ids = array_unique( array_map( 'intval', $ids ), SORT_NUMERIC );
if ( empty( $ids ) ) {
return;
}
$cache_keys = array();
foreach ( $ids as $id ) {
$cache_keys[ $id ] = 'post_parent:' . (string) $id;
}
$cached_data = wp_cache_get_multiple( array_values( $cache_keys ), 'posts' );
$non_cached_ids = array();
foreach ( $cache_keys as $id => $cache_key ) {
if ( false === $cached_data[ $cache_key ] ) {
$non_cached_ids[] = $id;
}
}
if ( ! empty( $non_cached_ids ) ) {
$fresh_posts = $wpdb->get_results( sprintf( "SELECT $wpdb->posts.ID, $wpdb->posts.post_parent FROM $wpdb->posts WHERE ID IN (%s)", implode( ',', $non_cached_ids ) ) );
if ( $fresh_posts ) {
$post_parent_data = array();
foreach ( $fresh_posts as $fresh_post ) {
$post_parent_data[ 'post_parent:' . (string) $fresh_post->ID ] = (int) $fresh_post->post_parent;
}
wp_cache_add_multiple( $post_parent_data, 'posts' );
}
}
}
/**
* Adds a suffix if any trashed posts have a given slug.
*
* Store its desired (i.e. current) slug so it can try to reclaim it
* if the post is untrashed.
*
* For internal use.
*
* @since 4.5.0
* @access private
*
* @param string $post_name Post slug.
* @param int $post_id Optional. Post ID that should be ignored. Default 0.
*/
function wp_add_trashed_suffix_to_post_name_for_trashed_posts( $post_name, $post_id = 0 ) {
$trashed_posts_with_desired_slug = get_posts(
array(
'name' => $post_name,
'post_status' => 'trash',
'post_type' => 'any',
'nopaging' => true,
'post__not_in' => array( $post_id ),
)
);
if ( ! empty( $trashed_posts_with_desired_slug ) ) {
foreach ( $trashed_posts_with_desired_slug as $_post ) {
wp_add_trashed_suffix_to_post_name_for_post( $_post );
}
}
}
/**
* Adds a trashed suffix for a given post.
*
* Store its desired (i.e. current) slug so it can try to reclaim it
* if the post is untrashed.
*
* For internal use.
*
* @since 4.5.0
* @access private
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param WP_Post $post The post.
* @return string New slug for the post.
*/
function wp_add_trashed_suffix_to_post_name_for_post( $post ) {
global $wpdb;
$post = get_post( $post );
if ( str_ends_with( $post->post_name, '__trashed' ) ) {
return $post->post_name;
}
add_post_meta( $post->ID, '_wp_desired_post_slug', $post->post_name );
$post_name = _truncate_post_slug( $post->post_name, 191 ) . '__trashed';
$wpdb->update( $wpdb->posts, array( 'post_name' => $post_name ), array( 'ID' => $post->ID ) );
clean_post_cache( $post->ID );
return $post_name;
}
/**
* Sets the last changed time for the 'posts' cache group.
*
* @since 5.0.0
*/
function wp_cache_set_posts_last_changed() {
wp_cache_set_last_changed( 'posts' );
}
/**
* Gets all available post MIME types for a given post type.
*
* @since 2.5.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $type
* @return string[] An array of MIME types.
*/
function get_available_post_mime_types( $type = 'attachment' ) {
global $wpdb;
/**
* Filters the list of available post MIME types for the given post type.
*
* @since 6.4.0
*
* @param string[]|null $mime_types An array of MIME types. Default null.
* @param string $type The post type name. Usually 'attachment' but can be any post type.
*/
$mime_types = apply_filters( 'pre_get_available_post_mime_types', null, $type );
if ( ! is_array( $mime_types ) ) {
$mime_types = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s AND post_mime_type != ''", $type ) );
}
// Remove nulls from returned $mime_types.
return array_values( array_filter( $mime_types ) );
}
/**
* Retrieves the path to an uploaded image file.
*
* Similar to `get_attached_file()` however some images may have been processed after uploading
* to make them suitable for web use. In this case the attached "full" size file is usually replaced
* with a scaled down version of the original image. This function always returns the path
* to the originally uploaded image file.
*
* @since 5.3.0
* @since 5.4.0 Added the `$unfiltered` parameter.
*
* @param int $attachment_id Attachment ID.
* @param bool $unfiltered Optional. Passed through to `get_attached_file()`. Default false.
* @return string|false Path to the original image file or false if the attachment is not an image.
*/
function wp_get_original_image_path( $attachment_id, $unfiltered = false ) {
if ( ! wp_attachment_is_image( $attachment_id ) ) {
return false;
}
$image_meta = wp_get_attachment_metadata( $attachment_id );
$image_file = get_attached_file( $attachment_id, $unfiltered );
if ( empty( $image_meta['original_image'] ) ) {
$original_image = $image_file;
} else {
$original_image = path_join( dirname( $image_file ), $image_meta['original_image'] );
}
/**
* Filters the path to the original image.
*
* @since 5.3.0
*
* @param string $original_image Path to original image file.
* @param int $attachment_id Attachment ID.
*/
return apply_filters( 'wp_get_original_image_path', $original_image, $attachment_id );
}
/**
* Retrieves the URL to an original attachment image.
*
* Similar to `wp_get_attachment_url()` however some images may have been
* processed after uploading. In this case this function returns the URL
* to the originally uploaded image file.
*
* @since 5.3.0
*
* @param int $attachment_id Attachment post ID.
* @return string|false Attachment image URL, false on error or if the attachment is not an image.
*/
function wp_get_original_image_url( $attachment_id ) {
if ( ! wp_attachment_is_image( $attachment_id ) ) {
return false;
}
$image_url = wp_get_attachment_url( $attachment_id );
if ( ! $image_url ) {
return false;
}
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( empty( $image_meta['original_image'] ) ) {
$original_image_url = $image_url;
} else {
$original_image_url = path_join( dirname( $image_url ), $image_meta['original_image'] );
}
/**
* Filters the URL to the original attachment image.
*
* @since 5.3.0
*
* @param string $original_image_url URL to original image.
* @param int $attachment_id Attachment ID.
*/
return apply_filters( 'wp_get_original_image_url', $original_image_url, $attachment_id );
}
/**
* Filters callback which sets the status of an untrashed post to its previous status.
*
* This can be used as a callback on the `wp_untrash_post_status` filter.
*
* @since 5.6.0
*
* @param string $new_status The new status of the post being restored.
* @param int $post_id The ID of the post being restored.
* @param string $previous_status The status of the post at the point where it was trashed.
* @return string The new status of the post.
*/
function wp_untrash_post_set_previous_status( $new_status, $post_id, $previous_status ) {
return $previous_status;
}
/**
* Returns whether the post can be edited in the block editor.
*
* @since 5.0.0
* @since 6.1.0 Moved to wp-includes from wp-admin.
*
* @param int|WP_Post $post Post ID or WP_Post object.
* @return bool Whether the post can be edited in the block editor.
*/
function use_block_editor_for_post( $post ) {
$post = get_post( $post );
if ( ! $post ) {
return false;
}
// We're in the meta box loader, so don't use the block editor.
if ( is_admin() && isset( $_GET['meta-box-loader'] ) ) {
check_admin_referer( 'meta-box-loader', 'meta-box-loader-nonce' );
return false;
}
$use_block_editor = use_block_editor_for_post_type( $post->post_type );
/**
* Filters whether a post is able to be edited in the block editor.
*
* @since 5.0.0
*
* @param bool $use_block_editor Whether the post can be edited or not.
* @param WP_Post $post The post being checked.
*/
return apply_filters( 'use_block_editor_for_post', $use_block_editor, $post );
}
/**
* Returns whether a post type is compatible with the block editor.
*
* The block editor depends on the REST API, and if the post type is not shown in the
* REST API, then it won't work with the block editor.
*
* @since 5.0.0
* @since 6.1.0 Moved to wp-includes from wp-admin.
*
* @param string $post_type The post type.
* @return bool Whether the post type can be edited with the block editor.
*/
function use_block_editor_for_post_type( $post_type ) {
if ( ! post_type_exists( $post_type ) ) {
return false;
}
if ( ! post_type_supports( $post_type, 'editor' ) ) {
return false;
}
$post_type_object = get_post_type_object( $post_type );
if ( $post_type_object && ! $post_type_object->show_in_rest ) {
return false;
}
/**
* Filters whether a post is able to be edited in the block editor.
*
* @since 5.0.0
*
* @param bool $use_block_editor Whether the post type can be edited or not. Default true.
* @param string $post_type The post type being checked.
*/
return apply_filters( 'use_block_editor_for_post_type', true, $post_type );
}
/**
* Registers any additional post meta fields.
*
* @since 6.3.0 Adds `wp_pattern_sync_status` meta field to the wp_block post type so an unsynced option can be added.
*
* @link https://github.com/WordPress/gutenberg/pull/51144
*/
function wp_create_initial_post_meta() {
register_post_meta(
'wp_block',
'wp_pattern_sync_status',
array(
'sanitize_callback' => 'sanitize_text_field',
'single' => true,
'type' => 'string',
'show_in_rest' => array(
'schema' => array(
'type' => 'string',
'enum' => array( 'partial', 'unsynced' ),
),
),
)
);
}
Fatal error: Uncaught Error: Call to undefined function _get_custom_object_labels() in /home/candoodesigncom/public_html/wp-includes/taxonomy.php:722
Stack trace:
#0 /home/candoodesigncom/public_html/wp-includes/class-wp-taxonomy.php(486): get_taxonomy_labels(Object(WP_Taxonomy))
#1 /home/candoodesigncom/public_html/wp-includes/class-wp-taxonomy.php(290): WP_Taxonomy->set_props('post', Array)
#2 /home/candoodesigncom/public_html/wp-includes/taxonomy.php(532): WP_Taxonomy->__construct('category', 'post', Array)
#3 /home/candoodesigncom/public_html/wp-includes/taxonomy.php(82): register_taxonomy('category', 'post', Array)
#4 /home/candoodesigncom/public_html/wp-settings.php(504): create_initial_taxonomies()
#5 /home/candoodesigncom/public_html/wp-config.php(100): require_once('/home/candoodes...')
#6 /home/candoodesigncom/public_html/wp-load.php(50): require_once('/home/candoodes...')
#7 /home/candoodesigncom/public_html/wp-blog-header.php(13): require_once('/home/candoodes...')
#8 /home/candoodesigncom/public_html/index.ph in /home/candoodesigncom/public_html/wp-includes/taxonomy.php on line 722