Make WordPress Core

Ticket #21267: 21267.2.diff

File 21267.2.diff, 7.4 KB (added by wonderboymusic, 10 years ago)
  • tests/phpunit/tests/term/getTerms.php

     
    190190                $terms8 = get_terms( 'post_tag', array( 'hide_empty' => false, 'description__like' => '.', 'fields' => 'ids' ) );
    191191                $this->assertEqualSets( array( $term_id1, $term_id2 ), $terms8 );
    192192        }
     193
     194        function test_list_terms_exclusions() {
     195                $term_id1 = $this->factory->tag->create( array( 'slug' => 'woo', 'name' => 'WOO!' ) );
     196
     197                add_filter( 'query', array( $this, 'capture_query' ) );
     198                add_filter( 'list_terms_exclusions', array( $this, 'capture_exclusions_sql' ) );
     199
     200                $filter1 = wp_filter_callbacks_hash( 'list_terms_exclusions' );
     201
     202                $terms1 = get_terms( 'post_tag', array( 'hide_empty' => false, 'exclude' => $term_id1 ) );
     203
     204                $this->assertNotContains( $term_id1, wp_list_pluck( $terms1, 'term_id' ) );
     205                $this->assertNotEquals( false, strpos( $this->sql, 'NOT IN' ) );
     206                $this->assertNotEquals( false, strpos( $this->sql, $this->exclude_sql ) );
     207
     208                add_filter( 'list_terms_exclusions', array( $this, 'filter_list_terms_exclusions' ), 11 );
     209
     210                $filter2 = wp_filter_callbacks_hash( 'list_terms_exclusions' );
     211
     212                $this->assertNotEquals( $filter1, $filter2 );
     213
     214                $terms2 = get_terms( 'post_tag', array( 'hide_empty' => false, 'exclude' => $term_id1 ) );
     215
     216                $this->assertContains( $term_id1, wp_list_pluck( $terms2, 'term_id' ) );
     217                $this->assertFalse( strpos( $this->sql, 'NOT IN' ) );
     218                $this->assertFalse( strpos( $this->sql, $this->exclude_sql ) );
     219
     220                remove_filter( 'query', array( $this, 'capture_query' ) );
     221                remove_filter( 'list_terms_exclusions', array( $this, 'capture_exclusions_sql' ) );
     222                remove_filter( 'list_terms_exclusions', array( $this, 'filter_list_terms_exclusions' ), 11 );
     223        }
     224
     225        function capture_exclusions_sql( $exclude_sql ) {
     226                $this->exclude_sql = $exclude_sql;
     227                return $exclude_sql;
     228        }
     229
     230        function filter_list_terms_exclusions() {
     231                return '';
     232        }
     233
     234        function capture_query( $sql ) {
     235                $this->sql = $sql;
     236                return $sql;
     237        }
    193238}
  • src/wp-includes/plugin.php

     
    744744/**
    745745 * Build Unique ID for storage and retrieval.
    746746 *
    747  * The old way to serialize the callback caused issues and this function is the
    748  * solution. It works by checking for objects and creating an a new property in
    749  * the class to keep track of the object and new objects of the same class that
    750  * need to be added.
    751  *
    752  * It also allows for the removal of actions and filters for objects after they
    753  * change class properties. It is possible to include the property $wp_filter_id
    754  * in your class and set it to "null" or a number to bypass the workaround.
    755  * However this will prevent you from adding new classes and any new classes
    756  * will overwrite the previous hook by the same class.
    757  *
    758747 * Functions and static method callbacks are just returned as strings and
    759748 * shouldn't have any speed penalty.
    760749 *
     
    767756 * @global array $wp_filter Storage for all of the filters and actions
    768757 * @param string $tag Used in counting how many hooks were applied
    769758 * @param callback $function Used for creating unique id
    770  * @param int|bool $priority Used in counting how many hooks were applied. If === false and $function is an object reference, we return the unique id only if it already has one, false otherwise.
    771759 * @return string|bool Unique ID for usage as array key or false if $priority === false and $function is an object reference, and it does not already have a unique id.
    772760 */
    773 function _wp_filter_build_unique_id($tag, $function, $priority) {
    774         global $wp_filter;
    775         static $filter_id_count = 0;
    776 
    777         if ( is_string($function) )
     761function _wp_filter_build_unique_id( $tag, $function ) {
     762        if ( is_string( $function ) )
    778763                return $function;
    779764
    780         if ( is_object($function) ) {
    781                 // Closures are currently implemented as objects
    782                 $function = array( $function, '' );
    783         } else {
    784                 $function = (array) $function;
    785         }
     765        if ( is_object( $function ) && 'Closure' === get_class( $function ) )
     766                return _wp_build_unique_closure_id( $function );
    786767
    787         if (is_object($function[0]) ) {
    788                 // Object Class Calling
    789                 if ( function_exists('spl_object_hash') ) {
    790                         return spl_object_hash($function[0]) . $function[1];
    791                 } else {
    792                         $obj_idx = get_class($function[0]).$function[1];
    793                         if ( !isset($function[0]->wp_filter_id) ) {
    794                                 if ( false === $priority )
    795                                         return false;
    796                                 $obj_idx .= isset($wp_filter[$tag][$priority]) ? count((array)$wp_filter[$tag][$priority]) : $filter_id_count;
    797                                 $function[0]->wp_filter_id = $filter_id_count;
    798                                 ++$filter_id_count;
    799                         } else {
    800                                 $obj_idx .= $function[0]->wp_filter_id;
    801                         }
     768        $function = array_filter( (array) $function );
    802769
    803                         return $obj_idx;
    804                 }
    805         } else if ( is_string($function[0]) ) {
     770        if ( is_object( $function[0] ) ) {
     771                return spl_object_hash( $function[0] ) . '~' . get_class( $function[0] ) . '::' . $function[1];
     772        } else if ( is_string( $function[0] ) ) {
    806773                // Static Calling
    807                 return $function[0] . '::' . $function[1];
     774                return join( '::', $function );
    808775        }
    809776}
     777
     778/**
     779 * Build Unique ID for Closure
     780 *
     781 * @package WordPress
     782 * @subpackage Plugin
     783 * @since 3.7
     784 *
     785 * @param callback $function Used for creating unique id
     786 * @return string Unique ID for usage as array key
     787 */
     788function _wp_build_unique_closure_id( $function ) {
     789        ob_start();
     790        echo new ReflectionFunction( $function );
     791        $source = ob_get_clean();
     792        return md5( $source );
     793}
     794/**
     795 * Build Unique ID for list of callbacks
     796 *
     797 * @package WordPress
     798 * @subpackage Plugin
     799 * @since 3.7
     800 *
     801 * @param string $tag Name of filter
     802 * @return string Unique ID representing hash of filter callback array keys (hashes)
     803 */
     804function wp_filter_callbacks_hash( $tag ) {
     805        global $wp_filter;
     806
     807        if ( ! has_filter( $tag ) )
     808                return '';
     809
     810        $hashes = array();
     811        foreach ( $wp_filter[$tag] as $priority )
     812                $hashes = array_merge( $hashes, array_keys( $priority ) );
     813
     814        return md5( join( '', array_map( '_dehash_filter_callback_object', $hashes ) ) );
     815 }
     816
     817/**
     818 * Remove the spl_object_hash portion of the filter callback key
     819 * This will allow persistence between requests
     820 *
     821 * @package WordPress
     822 * @subpackage Plugin
     823 * @since 3.7
     824 *
     825 * @param string $hash
     826 * @return string
     827 */
     828function _dehash_filter_callback_object( $hash ) {
     829        if ( false !== strpos( $hash, '~' ) ) {
     830                $bits = explode( '~', $hash, 2 );
     831                return $bits[1];
     832        }
     833        return $hash;
     834 }
     835 No newline at end of file
  • src/wp-includes/taxonomy.php

     
    13051305        }
    13061306
    13071307        // $args can be whatever, only use the args defined in defaults to compute the key
    1308         $filter_key = ( has_filter('list_terms_exclusions') ) ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : '';
    1309         $key = md5( serialize( compact(array_keys($defaults)) ) . serialize( $taxonomies ) . $filter_key );
     1308        $filter_key = wp_filter_callbacks_hash( 'list_terms_exclusions' );
     1309        $key = md5( serialize( compact( array_keys( $defaults ) ) ) . serialize( $taxonomies ) . $filter_key );
    13101310        $last_changed = wp_cache_get( 'last_changed', 'terms' );
    13111311        if ( ! $last_changed ) {
    13121312                $last_changed = microtime();