From 29880bbb25b491ef1deb2e80f72ad6ebe746161c Mon Sep 17 00:00:00 2001 From: Mrshahidali420 Date: Wed, 8 Jul 2026 22:23:52 +0500 Subject: [PATCH] fix: move-block loses or misplaces the block when removal shifts the target path (#69) Co-authored-by: Mrshahidali420 <175938180+Mrshahidali420@users.noreply.github.com> --- includes/class-block-tree.php | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/includes/class-block-tree.php b/includes/class-block-tree.php index 371faa2..1962b26 100644 --- a/includes/class-block-tree.php +++ b/includes/class-block-tree.php @@ -194,14 +194,24 @@ class EMCP_Tools_Block_Tree { return $blocks; } - // Adjust the target index when source and target share the same parent and - // the source sits before the insertion point (removal shifts it left by 1). - if ( in_array( $mode, array( 'before', 'after' ), true ) - && count( $from ) === count( $to ) - && array_slice( $from, 0, -1 ) === array_slice( $to, 0, -1 ) - && (int) end( $from ) < (int) end( $to ) ) { - $to[ count( $to ) - 1 ] = (int) $to[ count( $to ) - 1 ] - 1; - $position['path'] = $to; + // A move whose target lies inside the moved node's own subtree would remove the + // node and then fail to re-insert it (its path no longer resolves), losing the + // block. Reject it as a no-op. + $depth = count( $from ); + if ( count( $to ) >= $depth && array_slice( $to, 0, $depth ) === $from ) { + return $blocks; + } + + // remove() shifts every later sibling under $from's parent left by one. When the + // target path passes through that parent at a position after $from, the index there + // is now stale — decrement it so insert() still lands correctly. Applies to every + // mode (before/after siblings AND inside a later container) at any depth. + $shift = $depth - 1; + if ( count( $to ) > $shift + && array_slice( $from, 0, $shift ) === array_slice( $to, 0, $shift ) + && (int) $to[ $shift ] > (int) $from[ $shift ] ) { + $to[ $shift ] = (int) $to[ $shift ] - 1; + $position['path'] = $to; } $without = self::remove( $blocks, $from );