WordPress.org

Make WordPress Core

Opened 6 years ago

Last modified 4 weeks ago

#12955 new feature request

Add get_post filter

Reported by: JohnLamansky Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Posts, Post Types Keywords: has-patch dev-feedback
Focuses: Cc:

Description

This patch filters the return value of the get_post() function. I would find this very helpful for a plugin I'm developing.

Attachments (6)

post.php.diff (687 bytes) - added by JohnLamansky 6 years ago.
12955.2.diff (397 bytes) - added by Mte90 4 months ago.
patch refreshed
12955.3.diff (968 bytes) - added by MikeSchinkel 4 months ago.
Added PHPDoc for filter and $post, $output and $filter as $args.
12726-3.patch (992 bytes) - added by MikeSchinkel 4 months ago.
Updated PHPDoc for $post
12955.4.diff (4.8 KB) - added by MikeSchinkel 4 months ago.
Another approach: 'make_post_instance' and 'get_virtual_post_instance hooks' because some people at 10up were worried about calling the hook after caching (I don't think it would have any significant effect but I'm trying to provide an alternate solution.)
12955.5.diff (4.8 KB) - added by MikeSchinkel 4 months ago.
Added in correct first parameter for 'get_virtual_post_instance' hook

Download all attachments as: .zip

Change History (34)

#1 @scribu
6 years ago

  • Keywords has-patch added

#2 follow-up: @dd32
6 years ago

Out of interest, What is the use-case for this exactly?

#3 @mikeschinkel
6 years ago

  • Cc mikeschinkel@… added

#4 in reply to: ↑ 2 @JohnLamansky
6 years ago

Replying to dd32:

Out of interest, What is the use-case for this exactly?

I'd like to filter posts retrieved via XMLRPC/APP. Currently, the function chain goes like this: XMLRPC/APP method -> wp_get_single_post() -> get_post() -- None of these functions are filtered. Right now I have to manually override every single XMLRPC/APP method that retrieves posts, which is a pain. I'd love to be able to filter get_post() like this:

if ( defined('XMLRPC_REQUEST') || defined('APP_REQUEST') )
	add_filter( 'get_post', 'my_plugin_function' );

#5 @JohnLamansky
6 years ago

  • Cc JohnLamansky added
  • Keywords filter added

#6 @nacin
6 years ago

  • Milestone changed from 3.0 to Future Release

#7 @JohnLamansky
6 years ago

  • Milestone changed from Future Release to 3.0
  • Summary changed from Filter request for get_post to Add get_post filter

Since this filter would really help me with a plugin I'm developing, I'd really like to have it for 3.0 so I don't have to wait several more months for 3.1, if at all possible.

#8 @nacin
6 years ago

  • Milestone changed from 3.0 to Future Release

There is technically a workaround available. It's a pain as you say, but I don't want to change this so late in the development cycle.

#9 @meqia
4 years ago

  • Cc meqia added
  • Type changed from enhancement to feature request

Hello,
I apologize for my bad english but why you have abandoned the idea of ​​a filter to the function get_post(); ? Because it would be interesting to provide change the values ​​returned. For example when using the function wp_nav_menu() who call get_post();


Bonjour,
veuillez m'excuser pour mon mauvais anglais mais pourquoi vous avez abandonné l'idée de mettre un filtre sur la fonction get_post(); ? Car il serait intéressant de pourvoir modifier les valeurs retournées notamment lorsque l'on utilise la fonction wp_nav_menu(); qui appel get_post();

#10 @nacin
2 years ago

  • Component changed from General to Post Types

#11 @MikeSchinkel
2 years ago

I could really use this. Any chance this will get considered soon?

#12 @nikolov.tmw
17 months ago

I second the idea for a filter on get_post(), but I just ran into a possible side effect of the suggested patch.

Having the following super-simple code:

function my_post_filter( $post ) {
	$post->post_title .= ' | Filters are awesome';

	return $post;
}
add_filter( 'get_post', 'my_post_filter', 10 );

Results in the main post being displayed having it's title become something like this: "Hello world! | Filters are awesome | Filters are awesome | ...".
Now my question is the following - should we leave it up to the developers to make sure they're not filtering the same object multiple times, or should we come-up with an idea of how to avoid having to do that in the first place?

WP_Post::filter() seemed like a good place, but it never seems to run under normal circumstances, since the passed $filter is always the same as $this->filter.

#13 @sundquistm
11 months ago

I'm also interested in this filter.

Use-case: being able to properly support revisions complete with versioned post-meta and arbitrary data. Unless I'm mistaken, there's no way to fully and properly implement this without being able to filter get_post. The required workaround(s) are very ugly.

Last edited 11 months ago by sundquistm (previous) (diff)

#14 @danieliser
8 months ago

I support this as well. Use case, attaching extra fields into the post object.

Currently got a working concept for something like a partner table for posts, such as location information. This is useful in itself since querying post meta for radius location searches is very taxing if you have say 50k listings(CPT). A second table to manage these means easily querying using built in MySQL methods for these types of searches.

This patch applies simply because say I have address info in a partner table, I can then join that row to the post object so that $post->city, $post->state etc are available. Currently I am using a wrapper function that simply calls get_post() and then appends the extra keys. But being able to filter these on the initial get_post call would mean one less step. I'm sure there are many other uses for this as well.

#15 @Mte90
5 months ago

I would love this filter because this function is used in the menu editor in wordpress and i need to alter for inject virtual page.

#16 @sc0ttkclark
4 months ago

  • Keywords dev-feedback added

Following up on this, can we get dev eyes on this for 4.4 or 4.5-early?

#17 @sc0ttkclark
4 months ago

  • Keywords needs-refresh added

Patch needs refresh

@Mte90
4 months ago

patch refreshed

#18 @Mte90
4 months ago

  • Keywords needs-refresh removed

Patch Updated :-)

#19 @sc0ttkclark
4 months ago

  • Keywords needs-refresh added

Core code has changed since the original patch, I'm wondering whether the filter belongs before the filter, or before the check if $_post was found. This could allow a plugin to return a post, if it wasn't found.

#20 @MikeSchinkel
4 months ago

Per discussion with @sc0ttkclark I've added in $post, $output, $filter to the filter and also added PHPDoc for the filter to patch 12955.3.diff.

@MikeSchinkel
4 months ago

Added PHPDoc for filter and $post, $output and $filter as $args.

#21 @sc0ttkclark
4 months ago

  • Keywords filter needs-refresh removed

@MikeSchinkel
4 months ago

Updated PHPDoc for $post

#22 @sc0ttkclark
4 months ago

If we moved the filter to run only if $post wasn't an instanceof, that could greatly reduce the number of times this filter has to get called.

So that'd be from the current patch:

	if ( $post instanceof WP_Post ) {
		$_post = $post;
	} elseif ( is_object( $post ) ) {
		if ( empty( $post->filter ) ) {
			$_post = sanitize_post( $post, 'raw' );
			$_post = new WP_Post( $_post );
		} elseif ( 'raw' == $post->filter ) {
			$_post = new WP_Post( $post );
		} else {
			$_post = WP_Post::get_instance( $post->ID );
		}
	} else {
		$_post = WP_Post::get_instance( $post );
	}

	/**
	 * Filter that allows a post object to be further sanitized, virtualized and/or have properties annotated.
	 *
	 * @since 4.4.0
	 *
	 * @param WP_Post       $_post    Post object to saitize/virtualize/annotate/etc.
	 * @param WP_Post|int   $post     Original post object passed in.
	 * @param string        $output   Format of data to return, potentially 'OBJECT', 'ARRAY_A' or 'ARRAY_N'.
	 * @param string        $filter   Type of filter to apply, potentially 'raw', 'edit', 'db' or 'display'.
	 */
	$_post = apply_filters( 'get_post', $_post, $post, $output, $filter );

to

	if ( $post instanceof WP_Post ) {
		$_post = $post;
	} else {
		if ( is_object( $post ) ) {
			if ( empty( $post->filter ) ) {
				$_post = sanitize_post( $post, 'raw' );
				$_post = new WP_Post( $_post );
			} elseif ( 'raw' == $post->filter ) {
				$_post = new WP_Post( $post );
			} else {
				$_post = WP_Post::get_instance( $post->ID );
			}
		} else {
			$_post = WP_Post::get_instance( $post );
		}

		/**
		 * Filter that allows a post object to be further sanitized, virtualized and/or have properties annotated.
		 *
		 * @since 4.4.0
		 *
		 * @param WP_Post       $_post    Post object to saitize/virtualize/annotate/etc.
		 * @param WP_Post|int   $post     Original post object passed in.
		 * @param string        $output   Format of data to return, potentially 'OBJECT', 'ARRAY_A' or 'ARRAY_N'.
		 * @param string        $filter   Type of filter to apply, potentially 'raw', 'edit', 'db' or 'display'.
		 */
		$_post = apply_filters( 'get_post', $_post, $post, $output, $filter );
	}

This

#23 @MikeSchinkel
4 months ago

@sc0ttkclark That change would unfortunately result in not filtering all $post instances so it makes it a non-starter.

I'm going to look at WP_Post::get_instance() to see if I can instead add a filter there to achieve the same w/o running the filter more often than needed.

@MikeSchinkel
4 months ago

Another approach: 'make_post_instance' and 'get_virtual_post_instance hooks' because some people at 10up were worried about calling the hook after caching (I don't think it would have any significant effect but I'm trying to provide an alternate solution.)

#24 @MikeSchinkel
4 months ago

So attached is another way to skin this cat.

  1. Added a WP_Post::make_instance() method that is to be called instead of new WP_Post() except inside core. 2. Added deprecation warning if new WP_Post() is called in a theme or plugin directly.
  2. Added a 'make_post_instance' to filter instances when new WP_Post() is called.
  3. Added a 'get_virtual_post_instance' for when the SQL query in WP_Post::get_instance() fails to find a post in the database. This will allow code to retrieve the post via API and then return a valid post.

This approach is in advance of caching.

@MikeSchinkel
4 months ago

Added in correct first parameter for 'get_virtual_post_instance' hook

#25 @MikeSchinkel
4 months ago

In order to illustrate how beneficial this hook can be ,I've implemented a plugin as a proof-of-concept in the following Gist that virtualizes the results of the API found at http://apps.usa.gov/apps-gallery/api/registrations.json :

The plugin does not fully handle all aspects that a robust solution would handle, but it works well enough to show why this hook would be beneficial.

To see how it works just drop in any WordPress site and navigate to the URL:

  • /wp-admin/edit.php?post_type=vp_fed_mob_apps

From there click forward through the next pages and notice how it loads the results from the API into the database as if a post type. If you click back to earlier pages you notice it doesn't need to reload. Also notice that if it has been 15 minutes since a post has been updated it uses the 'make_post_instance' hook to reload the data from the API when you view a specific post.

Now imagine how much easier it would be for a themer who is not a strong PHP developer to access an API by treating it like a post type assuming someone has developed a plugin that presents the API as a post type.

If we get this functionality we'd like to implement the APIs that are found here: http://www.cdata.com/cloud/ which include Salesforce, Gmail, Facebook, QuickBooks, Google AdWords, Xero Accounting, Hubspot, Marketo, MailChimp and more.

But we can't without this hook.

Last edited 4 months ago by MikeSchinkel (previous) (diff)

#26 @Mte90
3 months ago

any news for that patch?

This ticket was mentioned in Slack in #core by mte90. View the logs.


3 months ago

This ticket was mentioned in Slack in #core by chriscct7. View the logs.


4 weeks ago

Note: See TracTickets for help on using tickets.