[wp-trac] [WordPress Trac] #19040: get_posts() expects invalid 'orderby' arguments + suggestion

WordPress Trac wp-trac at lists.automattic.com
Mon Oct 24 20:03:09 UTC 2011


#19040: get_posts() expects invalid 'orderby' arguments + suggestion
--------------------------+-----------------------------
 Reporter:  abrcam        |      Owner:
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Query         |    Version:  3.2.1
 Severity:  normal        |   Keywords:
--------------------------+-----------------------------
 The `get_children()` or `get_posts()` template functions which call the
 `WP_query::get_posts()` method expect wrong parameters, for example,
 `date`. The actual column is called `post_date` but line 2320 of `wp-
 includes/query.php` is:
 {{{
                         $allowed_keys = array('author', 'date', 'title',
 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count');
 }}}

 and further down at line 2329 there is:
 {{{
                         $orderby_array = array();
                         foreach ( explode( ' ', $q['orderby'] ) as $i =>
 $orderby ) {
                                 // Only allow certain values for safety
                                 if ( ! in_array($orderby, $allowed_keys) )
                                         continue;
 }}}

 The same goes for `author`, `title`, `modified`, etc. Some of them are
 correct though: `ID`, `menu_order`, `comment_count`.

 If `get_posts()` is called without specifying any `orderby` argument, then
 it works fine since the default is correct in line 2314:
 {{{
                 if ( empty($q['orderby']) ) {
                         $orderby = "$wpdb->posts.post_date " .
 $q['order'];
 }}}

 but if the `orderby` argument is specified and if it includes `post_date`
 or other correct column names, then they are ignored, e.g.:
 {{{
         $images = get_children(array(
                 'post_type' => 'attachment',
                 'post_mime_type' => 'image',
                 'post_parent' => get_the_ID(),
                 'orderby' => 'menu_order post_date',
                 'order' => 'ASC',
                 ), ARRAY_A);
 }}}

 will result in a query that is missing `post_date` since it gets ignored
 by line 2332, and yields unexpected results. The resulting wrong query at
 line 2623 is:

 {{{
 " SELECT   wp_posts.* FROM wp_posts  WHERE 1=1  AND wp_posts.post_parent =
 172  AND (post_mime_type LIKE 'image/%')  AND wp_posts.post_type =
 'attachment' AND (wp_posts.post_status <> 'trash' AND wp_posts.post_status
 <> 'auto-draft')  ORDER BY menu_order ASC "
 }}}

 Note the missing `post_date` at the end.


 '''Fix'''

 Rename `date` to `post_date` in line 2320.


 '''Suggestion'''

 Allow passing different `order` values for different `orderby` columns,
 e.g. `ORDER BY post_date ASC, menu_order ASC`. Right now, the same `order`
 is applied to all `orderby` columns.

 This can be easily implemented without breaking backward compatibility, by
 explode()'ing the `order` string using spaces so that the user can use,
 e.g.:
 {{{
         $images = get_children(array(
                 'orderby' => 'menu_order post_date',
                 'order' => 'ASC DESC',
                 ), ARRAY_A);
 }}}

 in which `ASC` applies to `menu_order` and `DESC` to `post_date`.

 Cheers,
 Bogdan.

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/19040>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list