[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