Ticket #14662: 14662.diff
| File 14662.diff, 9.5 KB (added by , 16 years ago) |
|---|
-
wp-includes/default-filters.php
109 109 add_filter( $filter, 'convert_chars' ); 110 110 } 111 111 112 // Pre save hierarchy 113 add_filter( 'wp_insert_post_parent', 'wp_check_post_hierarchy_for_loops', 10, 2 ); 114 add_filter( 'wp_update_term_parent', 'wp_check_term_hierarchy_for_loops', 10, 3 ); 115 112 116 // Display filters 113 117 add_filter( 'the_title', 'wptexturize' ); 114 118 add_filter( 'the_title', 'convert_chars' ); -
wp-includes/taxonomy.php
1936 1936 } 1937 1937 } 1938 1938 1939 // Check $parent to see if it will cause a hierarchy loop 1940 $parent = apply_filters( 'wp_update_term_parent', $parent, $term_id, $taxonomy, compact( array_keys( $args ) ), $args ); 1941 1939 1942 // Check for duplicate slug 1940 1943 $id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE slug = %s", $slug ) ); 1941 1944 if ( $id && ($id != $term_id) ) { … … 2682 2685 2683 2686 return false; 2684 2687 } 2688 2689 /** 2690 * Checks the given subset of the term hierarchy for hierarchy loops. 2691 * Prevents loops from forming and breaks those that it finds. 2692 * 2693 * Attached to the wp_update_term_parent filter. 2694 * 2695 * @since 3.1 2696 * @uses WP_Term_Parent_Map 2697 * @uses wp_find_hierarchy_loop() 2698 * 2699 * @param int $parent term_id of the parent for the term we're checking. 2700 * @parem int $term_id The term we're checking. 2701 * 2702 * @return int The new parent for the term. 2703 */ 2704 function wp_check_term_hierarchy_for_loops( $parent, $term_id, $taxonomy ) { 2705 // Nothing fancy here - bail 2706 if ( !$parent ) 2707 return 0; 2708 2709 // Can't be its own parent 2710 if ( $parent == $term_id ) 2711 return 0; 2712 2713 // Now look for larger loops 2714 2715 $term_parent_map = new WP_Term_Parent_Map( $taxonomy, array( $term_id => $parent ) ); 2716 2717 if ( !$loop = wp_find_hierarchy_loop( $term_parent_map, $term_id ) ) 2718 return $parent; // No loop 2719 2720 // Setting $parent to the given value causes a loop 2721 if ( isset( $loop[$term_id] ) ) 2722 return 0; 2723 2724 // There's a loop, but it doesn't contain $term_id. Break the loop. 2725 foreach ( array_keys( $loop ) as $loop_member ) 2726 $term_parent_map[$loop_member] = 0; 2727 return $parent; 2728 } 2729 2730 /** 2731 * Simulates array( $term_id => $parent, ... ) without having to load all terms. 2732 * 2733 * @link http://php.net/manual/class.arrayaccess.php 2734 * 2735 * @since 3.1 2736 */ 2737 class WP_Term_Parent_Map implements ArrayAccess { 2738 public $taxonomy = ''; 2739 public $override = array(); 2740 2741 /** 2742 * @param string $taxonomy 2743 * @param array $override A list of term_id => parent mappings used to override the results of get_term()->parent. 2744 * Useful when checking for loops in hierarchies that are not yet stored in the DB. 2745 */ 2746 public function __construct( $taxonomy, $override = array() ) { 2747 $this->taxonomy = $taxonomy; 2748 $this->override = $override; 2749 } 2750 2751 /* ArrayAccess */ 2752 public function offsetExists( $offset ) { 2753 if ( isset( $this->override[$offset] ) ) 2754 return true; 2755 $term = get_term( $offset, $this->taxonomy ); 2756 return $term && !is_wp_error( $term ); 2757 } 2758 public function offsetGet( $offset ) { 2759 if ( isset( $this->override[$offset] ) ) 2760 return $this->override[$offset]; 2761 2762 $term = get_term( $offset, $this->taxonomy ); 2763 if ( !$term || is_wp_error( $term ) ) 2764 return; 2765 return (int) $term->parent; 2766 } 2767 public function offsetSet( $offset, $value ) { 2768 if ( isset( $this->override[$offset] ) ) 2769 $this->override[$offset] = $value; 2770 else 2771 wp_update_term( $offset, $this->taxonomy, array( 'parent' => $value ) ); 2772 } 2773 public function offsetUnset( $offset ) { 2774 if ( isset( $this->override[$offset] ) ) 2775 unset( $this->override[$offset] ); 2776 // else noop 2777 } 2778 } -
wp-includes/post.php
2273 2273 else 2274 2274 $post_parent = 0; 2275 2275 2276 if ( !empty($post_ID) ) { 2277 if ( $post_parent == $post_ID ) { 2278 // Post can't be its own parent 2279 $post_parent = 0; 2280 } elseif ( !empty($post_parent) ) { 2281 $parent_post = get_post($post_parent); 2282 // Check for circular dependency 2283 if ( isset( $parent_post->post_parent ) && $parent_post->post_parent == $post_ID ) 2284 $post_parent = 0; 2285 } 2286 } 2276 // Check the post_parent to see if it will cause a hierarchy loop 2277 $post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr ) ), $postarr ); 2287 2278 2288 2279 if ( isset($menu_order) ) 2289 2280 $menu_order = (int) $menu_order; … … 4724 4715 add_filter('the_preview', '_set_preview'); 4725 4716 } 4726 4717 } 4718 4719 /** 4720 * Checks the given subset of the post hierarchy for hierarchy loops. 4721 * Prevents loops from forming and breaks those that it finds. 4722 * 4723 * Attached to the wp_insert_post_parent filter. 4724 * 4725 * @since 3.1 4726 * @uses WP_Post_Parent_Map 4727 * @uses wp_find_hierarchy_loop() 4728 * 4729 * @param int $post_parent ID of the parent for the post we're checking. 4730 * @parem int $post_ID ID of the post we're checking. 4731 * 4732 * @return int The new post_parent for the post. 4733 */ 4734 function wp_check_post_hierarchy_for_loops( $post_parent, $post_ID ) { 4735 // Nothing fancy here - bail 4736 if ( !$post_parent ) 4737 return 0; 4738 4739 // New post can't cause a loop 4740 if ( empty( $post_ID ) ) 4741 return $post_parent; 4742 4743 // Can't be its own parent 4744 if ( $post_parent == $post_ID ) 4745 return 0; 4746 4747 // Now look for larger loops 4748 4749 $post_parent_map = new WP_Post_Parent_Map( array( $post_ID => $post_parent ) ); 4750 4751 if ( !$loop = wp_find_hierarchy_loop( $post_parent_map, $post_ID ) ) 4752 return $post_parent; // No loop 4753 4754 // Setting $post_parent to the given value causes a loop 4755 if ( isset( $loop[$post_ID] ) ) 4756 return 0; 4757 4758 // There's a loop, but it doesn't contain $post_ID. Break the loop. 4759 foreach ( array_keys( $loop ) as $loop_member ) 4760 $post_parent_map[$loop_member] = 0; 4761 return $post_parent; 4762 } 4763 4764 /** 4765 * Simulates array( $post_id => $post_parent, ... ) without having to load all posts. 4766 * 4767 * @link http://php.net/manual/class.arrayaccess.php 4768 * 4769 * @since 3.1 4770 */ 4771 class WP_Post_Parent_Map implements ArrayAccess { 4772 public $override = array(); 4773 4774 /** 4775 * @param array $override A list of post_ID => post_parent mappings used to override the results of get_post()->post_parent. 4776 * Useful when checking for loops in hierarchies that are not yet stored in the DB. 4777 */ 4778 public function __construct( $override = array() ) { 4779 $this->override = $override; 4780 } 4781 4782 /* ArrayAccess */ 4783 public function offsetExists( $offset ) { 4784 if ( isset( $this->override[$offset] ) ) 4785 return true; 4786 return (bool) get_post( $offset ); 4787 } 4788 public function offsetGet( $offset ) { 4789 if ( isset( $this->override[$offset] ) ) 4790 return $this->override[$offset]; 4791 4792 if ( !$post = get_post( $offset ) ) 4793 return; 4794 return (int) $post->post_parent; 4795 } 4796 public function offsetSet( $offset, $value ) { 4797 if ( isset( $this->override[$offset] ) ) 4798 $this->override[$offset] = $value; 4799 else 4800 wp_update_post( array( 'ID' => $offset, 'post_parent' => $value ) ); 4801 } 4802 public function offsetUnset( $offset ) { 4803 if ( isset( $this->override[$offset] ) ) 4804 unset( $this->override[$offset] ); 4805 // else noop 4806 } 4807 } -
wp-includes/functions.php
4297 4297 } 4298 4298 } 4299 4299 4300 ?> 4300 /** 4301 * Finds hierarchy loops in an array that maps objects to parents. 4302 * 4303 * @since 3.1 4304 * 4305 * @param array $map array( ID => parent_ID, ... ) 4306 * @param $start The ID to start the loop check at 4307 * 4308 * @return array IDs of all members of loop 4309 */ 4310 function wp_find_hierarchy_loop( $map, $start ) { 4311 if ( !$arbitrary_loop_member = wp_find_hierarchy_loop_tortoise_hare( $map, $start ) ) 4312 return array(); 4313 4314 return wp_find_hierarchy_loop_tortoise_hare( $map, $arbitrary_loop_member, true ); 4315 } 4316 4317 /** 4318 * Uses the "The Tortoise and the Hare" algorithm to detect loops. 4319 * 4320 * For every step of the algorithm, the hare takes two steps and the tortoise one. 4321 * If the hare ever laps the tortoise, there must be a loop. 4322 * 4323 * @since 3.1 4324 * 4325 * @param array $map array( ID => parent_ID, ... ) 4326 * @param $start The ID to start the loop check at 4327 * @param bool $_return_loop Return loop members or just detect presence of loop? 4328 * Only set to true if you already know the given $start is part of a loop 4329 * (otherwise the returned array might include branches) 4330 * 4331 * @return mixed scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if $_return_loop 4332 */ 4333 function wp_find_hierarchy_loop_tortoise_hare( $map, $start, $_return_loop = false ) { 4334 $tortoise = $hare = $evanescent_hare = $start; 4335 $return = array(); 4336 4337 // Set evanescent_hare to one past hare 4338 // Increment hare two steps 4339 while ( $tortoise && ( $evanescent_hare = $map[$hare] ) && ( $hare = $map[$evanescent_hare] ) ) { 4340 if ( $_return_loop ) 4341 $return[$tortoise] = $return[$evanescent_hare] = $return[$hare] = true; 4342 4343 // tortoise got lapped - must be a loop 4344 if ( $tortoise == $evanescent_hare ) { 4345 unset( $return[$hare] ); // $hare is not actually in the loop 4346 return $_return_loop ? $return : $tortoise; 4347 } else if ( $tortoise == $hare ) { 4348 return $_return_loop ? $return : $tortoise; 4349 } 4350 4351 $tortoise = $map[$tortoise]; // Increment tortoise by one step 4352 } 4353 4354 return false; 4355 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)