WordPress.org

Make WordPress Core

Changeset 27635


Ignore:
Timestamp:
03/20/14 02:58:48 (4 years ago)
Author:
nacin
Message:

Fix various issues with WP_Adjacent_Post:

  • Performance / number of queries.
  • Incorrect results caused by sticky posts.
  • Back compat for filters, which had used "WHERE" while WP_Query does not; and fixing table references.

props ethitter.
fixes #26937.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/link-template.php

    r27409 r27635  
    12441244 
    12451245    /** 
    1246      * Allow direct access to adjacent post from the class instance itself 
     1246     * Allow direct access to adjacent post from the class instance itself. 
    12471247     * 
    12481248     * @param string $property Property to get. 
     
    12741274     */ 
    12751275    protected function get_post( $args ) { 
    1276         $this->current_post = get_post( $args['post'] ); 
     1276        $this->current_post   = get_post( $args['post'] ); 
    12771277        $this->excluded_terms = array_map( 'intval', $args['excluded_terms'] ); 
    12781278        $this->adjacent       = $args['previous'] ? 'previous' : 'next'; 
     
    12921292        // Build our arguments for WP_Query. 
    12931293        $query_args = array( 
    1294             'posts_per_page'   => 1, 
    1295             'post_status'      => 'publish', 
    1296             'post_type'        => 'post', 
    1297             'orderby'          => 'date', 
    1298             'order'            => 'previous' === $this->adjacent ? 'DESC' : 'ASC', 
    1299             'no_found_rows'    => true, 
    1300             'cache_results'    => true, 
    1301             'date_query'       => array(), 
     1294            'posts_per_page'      => 1, 
     1295            'post_status'         => 'publish', 
     1296            'post_type'           => 'post', 
     1297            'orderby'             => 'date', 
     1298            'order'               => 'previous' === $this->adjacent ? 'DESC' : 'ASC', 
     1299            'ignore_sticky_posts' => true, 
     1300            'date_query'          => array(), 
     1301 
     1302            // Performance considerations: 
     1303            'no_found_rows'          => true, 
     1304            'cache_results'          => true, 
     1305            'update_post_term_cache' => false, 
     1306            'update_post_meta_cache' => false, 
     1307            'split_the_query'        => wp_using_ext_object_cache(), 
    13021308        ); 
    13031309 
     
    13891395        remove_filter( 'posts_clauses', array( $this, 'filter' ) ); 
    13901396 
    1391         /* 
    1392          * The `join` and `where` filters are identical in their parameters, 
    1393          * so we can use the same approach for both. 
     1397        /** 
     1398         * If no legacy filter callbacks are registered, proceed no further. 
    13941399         */ 
    1395         foreach ( array( 'join', 'where' ) as $clause ) { 
    1396             if ( has_filter( 'get_' . $this->adjacent . '_post_' . $clause ) ) { 
    1397                 $clauses[ $clause ] = $this->filter_join_and_where( $clauses[ $clause ], $clause ); 
    1398             } 
     1400        if ( ! has_filter( 'get_' . $this->adjacent . '_post_join' ) && ! has_filter( 'get_' . $this->adjacent . '_post_where' ) && ! has_filter( 'get_' . $this->adjacent . '_post_sort' ) ) { 
     1401            return $clauses; 
     1402        } 
     1403 
     1404        /** 
     1405         * Posts table must be aliased as `p` for backwards compatibility with query previously generated by `get_adjacent_post()`. 
     1406         */ 
     1407        $clauses = array_map( array( $this, 'alias_posts_table' ), $clauses ); 
     1408 
     1409        /** 
     1410         * Apply the legacy `join` filter. 
     1411         */ 
     1412        if ( has_filter( 'get_' . $this->adjacent . '_post_join' ) ) { 
     1413            $clauses['join'] = $this->filter_join( $clauses['join'] ); 
     1414        } 
     1415 
     1416        /** 
     1417         * Posts table must be aliased as `p` for backwards compatibility with query previously generated by `get_adjacent_post()`. 
     1418         * No filter on the table name exists, so we have to leverage the next applied filter, that for the `join` clause. 
     1419         * We wait to apply this until after the legacy filter is applied so that the legacy filter doesn't remove the alias. 
     1420         */ 
     1421        $clauses['join'] = 'AS p ' . $clauses['join']; 
     1422 
     1423        /** 
     1424         * Apply the legacy `where` filter. 
     1425         */ 
     1426        if ( has_filter( 'get_' . $this->adjacent . '_post_where' ) ) { 
     1427            $clauses['where'] = $this->filter_where( $clauses['where'] ); 
    13991428        } 
    14001429 
     
    14121441 
    14131442    /** 
    1414      * Apply the deprecated `join` or `where` clause filter to the clauses built by WP_Query. 
     1443     * Alias posts table as `p` to match query previously built by `get_adjacent_post()`. 
    14151444     * 
    1416      * @param string $value 
    1417      * @param string $clause 
     1445     * @global $wpdb 
     1446     * @param string  Clause to alias 
    14181447     * @return string 
    14191448     */ 
    1420     protected function filter_join_and_where( $value, $clause ) { 
     1449    protected function alias_posts_table( $clause ) { 
     1450        global $wpdb; 
     1451 
     1452        return str_replace( $wpdb->posts, 'p', $clause ); 
     1453    } 
     1454 
     1455    /** 
     1456     * Apply the deprecated `join` clause filter to the clause built by WP_Query. 
     1457     * 
     1458     * @param string $join 
     1459     * @return string 
     1460     */ 
     1461    protected function filter_join( $join ) { 
    14211462        /** 
    1422          * @todo Minimal hook docs 
    14231463         * @deprecated 3.9.0 
    14241464         */ 
    1425         return apply_filters( 'get_' . $this->adjacent . '_post_' . $clause, $value, $this->in_same_term, $this->excluded_terms ); 
     1465        return apply_filters( 'get_' . $this->adjacent . '_post_join', $join, $this->in_same_term, $this->excluded_terms ); 
     1466    } 
     1467 
     1468    /** 
     1469     * Apply the deprecated `where` clause filter to the clause built by WP_Query. 
     1470     * 
     1471     * @param string $join 
     1472     * @return string 
     1473     */ 
     1474    protected function filter_where( $where ) { 
     1475        $where = trim( $where ); 
     1476 
     1477        // The legacy filter passed the entire clause, including the `WHERE`, while WP_Query's filter does not. 
     1478        // We prepend the `WHERE` for the benefit of legacy callbacks that look for it. 
     1479        if ( 0 !== stripos( $where, 'where' ) ) { 
     1480            $where = 'WHERE 1=1 ' . $where; 
     1481        } 
     1482 
     1483        /** 
     1484         * @deprecated 3.9.0 
     1485         */ 
     1486        $where = apply_filters( 'get_' . $this->adjacent . '_post_where', $where, $this->in_same_term, $this->excluded_terms ); 
     1487 
     1488        $where = trim( $where ); 
     1489 
     1490        // The legacy filter passed the entire clause, including the `WHERE`, while WP_Query's filter does not. 
     1491        // Removing the `WHERE` is necessary as we've added it above, and the legacy filter could include it in the returned string. 
     1492        if ( 0 === stripos( $where, 'where 1=1' ) ) { 
     1493            $where = substr( $where, 9 ); 
     1494        } elseif ( 0 === stripos( $where, 'where' ) ) { 
     1495            $where = substr( $where, 5 ); 
     1496        } 
     1497 
     1498        $where = trim( $where ); 
     1499 
     1500        // WP_Query expects that the string returned begins with `AND`, as it is prepended with "1=1" when the clauses are joined 
     1501        if ( 0 !== stripos( $where, 'and' ) ) { 
     1502            $where = 'AND ' . $where; 
     1503        } 
     1504 
     1505        return $where; 
    14261506    } 
    14271507 
  • trunk/tests/phpunit/tests/link.php

    r27285 r27635  
    209209        remove_filter( 'get_next_post_where', array( $this, 'filter_next_post_where' ) ); 
    210210 
     211        // Test "where" filter that writes its own query 
     212        add_filter( 'get_previous_post_where', array( $this, 'override_previous_post_where_clause' ) ); 
     213        $this->go_to( get_permalink( $post_four->ID ) ); 
     214        $this->assertEquals( $post_two, get_adjacent_post( false, null, true ) ); 
     215        remove_filter( 'get_previous_post_where', array( $this, 'override_previous_post_where_clause' ) ); 
     216 
    211217        // Test "join" filter by joining the postmeta table and restricting by meta key 
    212218        add_filter( 'get_next_post_join', array( $this, 'filter_next_post_join' ) ); 
     
    249255     * Filter callback for `test_legacy_get_adjacent_post_filters()` 
    250256     */ 
     257    function override_previous_post_where_clause( $where ) { 
     258        $where = "WHERE p.post_date < '2012-02-28'"; 
     259        return $where; 
     260    } 
     261 
     262    /** 
     263     * Filter callback for `test_legacy_get_adjacent_post_filters()` 
     264     */ 
    251265    function filter_next_post_join( $join ) { 
    252266        global $wpdb; 
    253267 
    254         $join .= " INNER JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id"; 
     268        $join .= " INNER JOIN {$wpdb->postmeta} ON p.ID = {$wpdb->postmeta}.post_id"; 
    255269        return $join; 
    256270    } 
     
    270284     */ 
    271285    function filter_next_post_sort( $sort ) { 
    272         global $wpdb; 
    273  
    274         $sort = str_replace( $wpdb->posts . '.post_date', $wpdb->posts . '.post_title', $sort ); 
    275         return $sort; 
     286        return str_replace( 'p.post_date', 'p.post_title', $sort ); 
    276287    } 
    277288 
Note: See TracChangeset for help on using the changeset viewer.