Opened 17 years ago
Closed 16 years ago
#12731 closed enhancement (wontfix)
Add a callback to get_posts() in /wp-includes/query.php to enable more robust plugins
| Reported by: | mikeschinkel | Owned by: | ryan |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | Query | Version: | 3.0 |
| Severity: | normal | Keywords: | 2nd-opinion |
| Cc: | Focuses: |
Description
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;
}
Attachments (1)
Change History (9)
#1
@
17 years ago
DAMN, that title should be:
Add a callback to get_posts() in /wp-includes/query.php to enable more robust plugins
#2
follow-up:
↓ 3
@
17 years ago
- Keywords posts get_posts query removed
- Summary Add a callback to get_posts() in /wp-includes/post.php to enable more robust plugins → Add a callback to get_posts() in /wp-includes/query.php to enable more robust plugins
Well, then just change the title, I guess :-) (It's called "Summary" here.)
#3
in reply to: ↑ 2
@
17 years ago
- Cc added
Replying to TobiasBg:
Well, then just change the title, I guess :-) (It's called "Summary" here.)
Ah, thanks. It's very late and I just didn't see that I could edit it. Too bleary eyed from getting it all working. :)
Question: why did you remove the keywords I used?
#4
@
17 years ago
No problem :-)
Keywords here in Trac have special meanings to the devs (see this list), as they describe necessary actions to be taken in the lifecycle of the ticket. They are not search keywords as they are unrelated to the actual content of a ticket.
#6
@
17 years ago
I just noticed a bug in my example use-case:
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_tax_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;
}
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
Patch for /wp-includes/query.php to add callback functionality as an alternate to existing hooks for get_posts().