WordPress Version: 6.2
/**
* Checks the given subset of the post hierarchy for hierarchy loops.
*
* Prevents loops from forming and breaks those that it finds. Attached
* to the {@see 'wp_insert_post_parent'} filter.
*
* @since 3.1.0
*
* @see wp_find_hierarchy_loop()
*
* @param int $post_parent ID of the parent for the post we're checking.
* @param int $post_id ID of the post we're checking.
* @return int The new post_parent for the post, 0 otherwise.
*/
function wp_check_post_hierarchy_for_loops($post_parent, $post_id)
{
// Nothing fancy here - bail.
if (!$post_parent) {
return 0;
}
// New post can't cause a loop.
if (!$post_id) {
return $post_parent;
}
// Can't be its own parent.
if ($post_parent == $post_id) {
return 0;
}
// Now look for larger loops.
$loop = wp_find_hierarchy_loop('wp_get_post_parent_id', $post_id, $post_parent);
if (!$loop) {
return $post_parent;
// No loop.
}
// Setting $post_parent to the given value causes a loop.
if (isset($loop[$post_id])) {
return 0;
}
// There's a loop, but it doesn't contain $post_id. Break the loop.
foreach (array_keys($loop) as $loop_member) {
wp_update_post(array('ID' => $loop_member, 'post_parent' => 0));
}
return $post_parent;
}