Opened 4 months ago
Last modified 4 months ago
#61773 new enhancement
get_posts() returns posts of removed custom post type
Reported by: | rajanit2000 | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | |
Component: | Posts, Post Types | Keywords: | |
Focuses: | Cc: |
Description
I’ve encountered an issue with the get_posts() function related to custom post types. Here’s the detailed process to reproduce the problem:
- Register a Custom Post Type:
- Register a custom post type, for example, movie.
- Use the register_post_type() function to create the custom post type.
- Add Posts:
- Add several posts to the movie custom post type.
- Ensure these posts are correctly saved and retrievable using get_posts().
- Remove the Custom Post Type:
- Remove or unregister the movie custom post type.
- This can be done by not calling the register_post_type() function for movie in your theme or plugin.
- Retrieve Posts:
- Use the get_posts() function to retrieve posts.
- Notice that posts belonging to the movie custom post type are still being returned by get_posts().
Expected Behavior:
After the custom post type has been removed/unregistered, the get_posts() function should not return posts associated with the removed custom post type. These posts should be excluded from the query results, as their post type is no longer registered.
Actual Behavior:
The get_posts() function continues to return posts of the removed custom post type. This can lead to unexpected behavior and confusion, especially in dynamic environments where custom post types may be added and removed frequently.
Proposed Solution:
Introduce a new argument in the get_posts() function to control whether to include posts from unregistered post types. For example:
$args = array(
'unregistered_post' => true // This will return all posts including unregistered posts, default is false
);
$latest_posts = get_posts($args);
By default, unregistered_post should be false, ensuring that posts from unregistered custom post types are excluded from the query results. When explicitly set to true, it will include posts from unregistered custom post types.
Change History (5)
#2
follow-up:
↓ 3
@
4 months ago
What is the prolem with the current behaviour?
I would expect it to return what's in the database, and if I wanted to exclude unregistered posts, even when I explicitly specify a possibly unregsitered post type, to check that before calling get_posts. This very edge case, I think.
#3
in reply to:
↑ 2
@
4 months ago
The current behavior of the get_posts() function and WP_Query class, where posts from an unregistered custom post type are still returned, can be seen as consistent with the expectation that these functions should return what is in the database. However, there are several potential issues with this behavior.
Firstly, it can lead to inconsistencies and unpredictability for developers, who typically expect functions to behave consistently. When a custom post type is unregistered, it no longer appears to be part of the site’s structure, and continuing to return posts from such a type can lead to confusion and unexpected results.
Secondly, unregistered post types may indicate that the data is no longer intended to be used or displayed, and returning posts from these types can complicate data management and content strategies by potentially displaying outdated or irrelevant content.
Thirdly, requiring developers to manually check for unregistered post types before calling get_posts() adds extra complexity to their code, making it less robust and harder to maintain.
Fourthly, there are security implications, as unregistered post types might be used to store sensitive or restricted content, and automatically returning such posts without verification can lead to unintended data exposure.
Lastly, while handling unregistered post types might seem like an edge case, it can occur more frequently in larger, dynamic sites or during development and testing phases.
Addressing this within the core function makes the WordPress ecosystem more resilient and user-friendly. To resolve these issues while maintaining flexibility, an enhancement is proposed that introduces a new argument, unregistered_post, to the get_posts() function and WP_Query class. This argument defaults to false, ensuring unregistered post types are excluded by default, but allows developers to include posts from unregistered types by setting this argument to true.
This approach balances returning all data by default with providing an easy mechanism to exclude unregistered post types when needed, enhancing the predictability, security, and usability of the get_posts() function.
Replying to knutsp:
What is the prolem with the current behaviour?
I would expect it to return what's in the database, and if I wanted to exclude unregistered posts, even when I explicitly specify a possibly unregsitered post type, to check that before calling get_posts. This very edge case, I think.
This ticket was mentioned in PR #7102 on WordPress/wordpress-develop by @rajanit2000.
4 months ago
#4
- Keywords has-patch added
This PR introduces enhancements to the get_posts() function to handle scenarios involving unregistered post types.
- New Argument: Added a new argument, unregistered_post, which allows users to specify whether to include posts of unregistered post types.
- Unregistered Post Type Handling: Implemented a check to determine if the post type is registered when unregistered_post is set to false. If unregistered_post is false and the post type is not found among the registered post types, the function returns an empty array.
- Default Argument Handling: Updated the default arguments to include unregistered_post with a default value of false.
- Query Execution: The function now proceeds to execute the query using WP_Query if the post type is valid or if unregistered_post is true.
### Benefits:
- Improved Data Validation: Ensures that only registered post types are queried unless explicitly stated otherwise.
- Enhanced Flexibility: Allows developers to include unregistered post types if needed, providing greater control over query behavior.
### Usage:
The new unregistered_post argument can be used as follows:
$args = array( 'post_type' => 'custom_post_type', 'unregistered_post' => true, // Include unregistered post types ); $posts = get_posts( $args );}}}
function get_posts( $args = null ) { $defaults = array( 'numberposts' => 5, 'category' => 0, 'orderby' => 'date', 'order' => 'DESC', 'include' => array(), 'exclude' => array(), 'meta_key' => '', 'meta_value' => '', 'post_type' => 'post', 'suppress_filters' => true, 'unregistered_post'=> false, // New argument to include unregistered posts ); $parsed_args = wp_parse_args( $args, $defaults ); // Handle the unregistered_post argument if ( ! $parsed_args['unregistered_post'] ) { $registered_post_types = get_post_types( array(), 'names' ); if ( ! in_array( $parsed_args['post_type'], $registered_post_types ) ) { // If the post type is unregistered, return an empty array return array(); } } if ( empty( $parsed_args['post_status'] ) ) { $parsed_args['post_status'] = ( 'attachment' === $parsed_args['post_type'] ) ? 'inherit' : 'publish'; } if ( ! empty( $parsed_args['numberposts'] ) && empty( $parsed_args['posts_per_page'] ) ) { $parsed_args['posts_per_page'] = $parsed_args['numberposts']; } if ( ! empty( $parsed_args['category'] ) ) { $parsed_args['cat'] = $parsed_args['category']; } if ( ! empty( $parsed_args['include'] ) ) { $incposts = wp_parse_id_list( $parsed_args['include'] ); $parsed_args['posts_per_page'] = count( $incposts ); // Only the number of posts included. $parsed_args['post__in'] = $incposts; } elseif ( ! empty( $parsed_args['exclude'] ) ) { $parsed_args['post__not_in'] = wp_parse_id_list( $parsed_args['exclude'] ); } $parsed_args['ignore_sticky_posts'] = true; $parsed_args['no_found_rows'] = true; $get_posts = new WP_Query(); return $get_posts->query( $parsed_args ); }
We can improve this function by adding a new argument to include unregistered post types. This will allow developers to include unregistered post types in the query. The new argument is called
unregistered_post
and is set tofalse
by default. If set totrue
, the function will return an empty array if the post type is unregistered.