Make WordPress Core


Ignore:
Timestamp:
10/14/2010 03:09:04 PM (14 years ago)
Author:
ryan
Message:

Prevent post and term hierarchy loops. Props mdawaffe. fixes #14662

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/functions.php

    r15746 r15806  
    43394339}
    43404340
    4341 ?>
     4341/**
     4342 * Finds hierarchy loops using a callback function that maps objects to parents.
     4343 *
     4344 * @since 3.1
     4345 *
     4346 * @param callback $callback function that accepts ( ID, callback_arg, ... ) and outputs parent_ID
     4347 * @param $start The ID to start the loop check at
     4348 * @param $start_parent the parent_ID of $start to use instead of calling $callback( $start ).  Use null to always use $callback
     4349 * @param array $override an array of ( ID => parent_ID, ... ) to use instead of $callback
     4350 * @param array $callback_arg optional additional arguments to send to $callback
     4351 *
     4352 * @internal
     4353 *
     4354 * @return array IDs of all members of loop
     4355 */
     4356function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_args = array() ) {
     4357    $override = is_null( $start_parent ) ? array() : array( $start => $start_parent );
     4358
     4359    echo "wp_find_hierarchy_loop: $callback, $start, $callback_args\n";
     4360    if ( !$arbitrary_loop_member = wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override, $callback_args ) )
     4361        return array();
     4362
     4363    return wp_find_hierarchy_loop_tortoise_hare( $callback, $arbitrary_loop_member, $override, $callback_args, true );
     4364}
     4365
     4366/**
     4367 * Uses the "The Tortoise and the Hare" algorithm to detect loops.
     4368 *
     4369 * For every step of the algorithm, the hare takes two steps and the tortoise one.
     4370 * If the hare ever laps the tortoise, there must be a loop.
     4371 *
     4372 * @since 3.1
     4373 *
     4374 * @param callback $callback function that accupts ( ID, callback_arg, ... ) and outputs parent_ID
     4375 * @param $start The ID to start the loop check at
     4376 * @param array $override an array of ( ID => parent_ID, ... ) to use instead of $callback
     4377 * @param array $callback_args optional additional arguments to send to $callback
     4378 * @param bool $_return_loop Return loop members or just detect presence of loop?
     4379 *             Only set to true if you already know the given $start is part of a loop
     4380 *             (otherwise the returned array might include branches)
     4381 *
     4382 * @internal
     4383 *
     4384 * @return mixed scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if $_return_loop
     4385 */
     4386function wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override = array(), $callback_args = array(), $_return_loop = false ) {
     4387    $tortoise = $hare = $evanescent_hare = $start;
     4388    $return = array();
     4389
     4390    // Set evanescent_hare to one past hare
     4391    // Increment hare two steps
     4392    while (
     4393        $tortoise
     4394    &&
     4395        ( $evanescent_hare = isset( $override[$hare] ) ? $override[$hare] : call_user_func_array( $callback, array_merge( array( $hare ), $callback_args ) ) )
     4396    &&
     4397        ( $hare = isset( $override[$evanescent_hare] ) ? $override[$evanescent_hare] : call_user_func_array( $callback, array_merge( array( $evanescent_hare ), $callback_args ) ) )
     4398    ) {
     4399        if ( $_return_loop )
     4400            $return[$tortoise] = $return[$evanescent_hare] = $return[$hare] = true;
     4401
     4402        // tortoise got lapped - must be a loop
     4403        if ( $tortoise == $evanescent_hare || $tortoise == $hare )
     4404            return $_return_loop ? $return : $tortoise;
     4405
     4406        // Increment tortoise by one step
     4407        $tortoise = isset( $override[$tortoise] ) ? $override[$tortoise] : call_user_func_array( $callback, array_merge( array( $tortoise ), $callback_args ) );
     4408    }
     4409
     4410    return false;
     4411}
Note: See TracChangeset for help on using the changeset viewer.