move()->execute([ 'post_id' => 7, 'tree_rev' => $this->treeRev(), 'id' => 's0.r0.c1.m2', 'parent' => 's1.r0.c0', ]); self::assertSame([['id' => 's1.r0.c0.m1', 'type' => 'divi/button', 'action' => 'moved', 'label' => 'Hero – Button']], $moved['changed']); self::assertStringContainsString('Leistungen', (string) $moved['outline'], 'the outline is embedded in the result'); $back = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => Rev::of($this->saved[0]), 'id' => 's1.r0.c0.m1', 'parent' => 's0.r0.c1', ]); self::assertSame([['id' => 's0.r0.c1.m2', 'type' => 'divi/button', 'action' => 'moved', 'label' => 'Hero – Button']], $back['changed']); self::assertSame($this->original, $this->saved[1], 'move there and back restores the exact bytes (S14)'); } /** StructureRules apply on move: a module directly into a section, or into a specialty column. */ public function testMoveRefusedByStructureRules(): void { $mixed = DiviFixtures::markup('synthetic-mixed.html'); $this->post->post_content = $mixed; $treeRev = Rev::of($mixed); // s1 is a regular section: it holds rows, not modules directly. $intoSection = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => $treeRev, 'id' => 's0.c0.m0', 'parent' => 's1', ]); self::assertToolError($intoSection, 'validation_failed'); self::assertStringContainsString('Zeilen (row)', self::clientError($intoSection)['fields']['position']); // s0.c1 is a specialty column (specialtyColumns set, holds a row-inner): refuses every child. $intoSpecialtyColumn = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => $treeRev, 'id' => 's0.c0.m0', 'parent' => 's0.c1', ]); self::assertToolError($intoSpecialtyColumn, 'validation_failed'); self::assertStringContainsString('Spezialspalten', self::clientError($intoSpecialtyColumn)['fields']['position']); self::assertSame([], $this->saved); self::assertSame($mixed, $this->post->post_content); } public function testMoveIntoItsOwnDescendantIsRefused(): void { $result = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => $this->treeRev(), 'id' => 's0', 'parent' => 's0.r0.c1', ]); self::assertToolError($result, 'validation_failed'); self::assertStringContainsString( 'nicht in sich selbst verschoben', self::clientError($result)['fields']['position'] ); self::assertSame([], $this->saved); } public function testMoveRefusesAStaleTreeRev(): void { $result = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => '000000000000', 'id' => 's0.r0.c1.m2', 'parent' => 's1.r0.c0', ]); self::assertToolError($result, 'rev_mismatch'); self::assertSame('rev_mismatch', self::clientError($result)['code'], 'the client sees the code without lit_'); self::assertSame([], $this->saved); } }