get_post_status( int|WP_Post $post = null ): string|false

Retrieves the post status based on the post ID.

Description

If the post ID is of an attachment, then the parent post status will be given instead.

Parameters

$postint|WP_Postoptional
Post ID or post object. Defaults to global $post.

Default:null

Return

string|false Post status on success, false on failure.

Source

function get_post_status( $post = null ) {
	$post = get_post( $post );

	if ( ! is_object( $post ) ) {
		return false;
	}

	$post_status = $post->post_status;

	if (
		'attachment' === $post->post_type &&
		'inherit' === $post_status
	) {
		if (
			0 === $post->post_parent ||
			! get_post( $post->post_parent ) ||
			$post->ID === $post->post_parent
		) {
			// Unattached attachments with inherit status are assumed to be published.
			$post_status = 'publish';
		} elseif ( 'trash' === get_post_status( $post->post_parent ) ) {
			// Get parent status prior to trashing.
			$post_status = get_post_meta( $post->post_parent, '_wp_trash_meta_status', true );

			if ( ! $post_status ) {
				// Assume publish as above.
				$post_status = 'publish';
			}
		} else {
			$post_status = get_post_status( $post->post_parent );
		}
	} elseif (
		'attachment' === $post->post_type &&
		! in_array( $post_status, array( 'private', 'trash', 'auto-draft' ), true )
	) {
		/*
		 * Ensure uninherited attachments have a permitted status either 'private', 'trash', 'auto-draft'.
		 * This is to match the logic in wp_insert_post().
		 *
		 * Note: 'inherit' is excluded from this check as it is resolved to the parent post's
		 * status in the logic block above.
		 */
		$post_status = 'publish';
	}

	/**
	 * Filters the post status.
	 *
	 * @since 4.4.0
	 * @since 5.7.0 The attachment post type is now passed through this filter.
	 *
	 * @param string  $post_status The post status.
	 * @param WP_Post $post        The post object.
	 */
	return apply_filters( 'get_post_status', $post_status, $post );
}

Hooks

apply_filters( ‘get_post_status’, string $post_status, WP_Post $post )

Filters the post status.

Changelog

VersionDescription
2.0.0Introduced.

User Contributed Notes

  1. Skip to note 6 content

    will return one of: publish, future, draft, pending, private

  2. Skip to note 9 content

    Basic example:

    <?php 
    $current_status = get_post_status ( $postID );
    
    if ( false !== $current_status ) {
        if ( 'publish' === $current_status == 'publish' ) {
            $err_msg = esc_html__( 'Post status is set to: Publish.', 'textdomain' ) );
        } elseif ( 'draft' === $current_status ) 
            $err_msg = esc_html__( 'Your post is in Draft mode.', 'textdomain' );
        }
    } else {
        $err_msg = esc_html__( 'Sorry, the post status is not available at this time.', 'textdomain' );
    }
    ?>

    Default post status includes: publish, future, draft, pending, private.

  3. Skip to note 10 content

    Documentation above says both that, if no ID or $post is passed then it will default to both the global $post AND null.

    In my testing it does NOT default to the global $post, so if used in the Loop you must still pass either the ID or the $post, eg:

    get_post_status ( get_the_ID() )

You must log in before being able to contribute a note or feedback.