[wp-trac] [WordPress Trac] #12731: Add a callback to get_posts() in /wp-includes/post.php to enable more robust plugins
WordPress Trac
wp-trac at lists.automattic.com
Sat Mar 27 09:34:31 UTC 2010
#12731: Add a callback to get_posts() in /wp-includes/post.php to enable more
robust plugins
--------------------------+-------------------------------------------------
Reporter: mikeschinkel | Owner: ryan
Type: enhancement | Status: new
Priority: normal | Milestone: Unassigned
Component: Query | Version: 3.0
Severity: normal | Keywords: posts, get_posts, query
--------------------------+-------------------------------------------------
----
'''Suggestion:'''
Add callback functionality to get_posts() in /wp-includes/post.php to
enable more robust plugins. Allow a developer to specify a hook that when
defined will process all hooks used by get_posts() and thus can allow a
developer to avoid all side-effects from other plugins and fully control
get_posts for specific use-cases like Widgets or other things.
With the advent of custom post types in the admin user interface there is
likely to be a lot greater need for custom queries and so this will become
an increasing problem.
----
'''Background:'''
One of the things I struggle with frequently is trying to perform a
WP_Query() in a plugin or a theme only to find that some other plugin has
added hooks (like a 'post_join') that cause my code to break. Of course
the plugin developer didn't test against my code, and as I can't test
against all other plugins my code gets trampled and my client gets upset.
I really want the ability to call a query and make certain that no other
plugin will create a global "side-effect" condition that can cause my
plugin to fail.
----
'''Implementation:'''
The attached patch is but one proposed implementation to solve the
problem. Addressing the issue is more important than this implementation
but the following explains why the implementation was chosen:
-- Adds a $_get_post_callback instance variable to WP_Query() to hold the
name of the callback.
-- Tests for "callback" in the query and if found looks for a hook that
matches "get_posts_callback_$_get_posts_callback"
-- Adds the "internal" functions _do_action_ref_array_or_callback($tag),
_do_action_or_callback($tag,$value) and
_apply_filters_ref_array_or_callback($tag,$args) to be called as proxy for
do_action_ref_array(), do_action() and apply_filters_ref_array().
-- If a valid callback exists it will be used to process all hooks within
get_posts(), actions and filters, by passing a 3rd "$tag" parameter that
allows the developer to decide which filters to wake on and which to
ignore (this required the first parameter be echoed as the return value,
unless it needs to be modified, of course.)
-- This callback will bypass all existing hooks but the plugin/theme
developer can delegate back to said hooks if need be.
-- This approach was chosen instead of adding for 35 additional callback
specific hooks to minimize the overhead added by this patch. As is there
this patch contributes only a negligible overhead, overhead which could be
recovered by a few simply optimizations of the existing get_posts()
function.
----
'''Benefits:'''
The primary benefits are to make it much easier to get a plugin or theme
that uses a custom query to work and to ensure it will continue to work no
matter what other plugins are added.
----
'''Example Use Case:'''
Here is an example use case that adds taxonomy terms string to the query
in the form, i.e. "tax1/term1,tax2/term2,...taxN/termN" (this use case and
the exact code came from functionality I needed for building a website
using custom post types. It is a "real world" and "in the wild" need, not
a hypothetical):
{{{
add_filter('get_posts_callback_add_tax_terms','my_add_tax_terms',10,3);
$q = new
WP_Query('post_type=session&posts_per_page=9999&callback=add_taxonomy_terms');
foreach($q->posts as $post) {
echo "{$post->post_title}: {$post->taxonomy_terms}\n";
}
function my_add_tax_terms( $value,$query,$tag ) {
global $wpdb;
switch($tag) {
case 'posts_fields':
$value .= ',taxonomy_terms.taxonomy_terms';
break;
case 'posts_join':
$value .= " LEFT OUTER JOIN (SELECT $wpdb->posts.ID AS post_ID,
GROUP_CONCAT(CONCAT_WS('/',$wpdb->term_taxonomy.taxonomy,$wpdb->terms.slug)
ORDER BY $wpdb->terms.name SEPARATOR ',')
AS taxonomy_terms FROM $wpdb->posts
LEFT OUTER JOIN $wpdb->term_relationships ON
$wpdb->term_relationships.object_id=$wpdb->posts.ID
LEFT OUTER JOIN $wpdb->term_taxonomy ON
$wpdb->term_taxonomy.term_taxonomy_id=$wpdb->term_relationships.term_taxonomy_id
LEFT OUTER JOIN $wpdb->terms ON
$wpdb->terms.term_id=$wpdb->term_taxonomy.term_id
WHERE 1=1 GROUP BY $wpdb->posts.ID) taxonomy_terms
ON $wpdb->posts.ID=taxonomy_terms.post_ID ";
break;
}
return $value;
}
}}}
--
Ticket URL: <http://core.trac.wordpress.org/ticket/12731>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list