diff --git a/src/Controllers/LinkFieldController.php b/src/Controllers/LinkFieldController.php index 9e0f263a..a3e1e9a9 100644 --- a/src/Controllers/LinkFieldController.php +++ b/src/Controllers/LinkFieldController.php @@ -22,6 +22,8 @@ use SilverStripe\ORM\DataObject; use SilverStripe\LinkField\Form\LinkField; use SilverStripe\LinkField\Form\MultiLinkField; +use SilverStripe\ORM\Queries\SQLUpdate; +use SilverStripe\Versioned\Versioned; class LinkFieldController extends LeftAndMain { @@ -136,15 +138,30 @@ public function linkDelete(): HTTPResponse if (!SecurityToken::inst()->checkRequest($this->getRequest())) { $this->jsonError(400); } - // delete() will also delete any published version immediately - $link->delete(); + if ($link->hasExtension(Versioned::class)) { + $link->doArchive(); + } else { + $link->delete(); + } // Update owner object if this Link is on a has_one relation on the owner $owner = $this->getOwnerFromRequest(); $ownerRelation = $this->getOwnerRelationFromRequest(); $hasOne = Injector::inst()->get($owner->ClassName)->hasOne(); if (array_key_exists($ownerRelation, $hasOne) && $owner->canEdit()) { + // Update draft owner table $owner->$ownerRelation = null; $owner->write(); + // Update live owner table if owner is versioned + if ($owner->hasExtension(Versioned::class)) { + $schema = $owner->getSchema(); + $draftTable = $schema->tableForField($owner::class, $ownerRelation . 'ID'); + $liveTable = $draftTable . '_Live'; + SQLUpdate::create() + ->setTable($liveTable) + ->assign('"'.$ownerRelation . 'ID"', 0) + ->addWhere(['ID' => $owner->ID]) + ->execute(); + } } // Send response return $this->jsonSuccess(204); diff --git a/tests/php/Controllers/LinkFieldControllerTest.php b/tests/php/Controllers/LinkFieldControllerTest.php index 5c679507..58cb7e8a 100644 --- a/tests/php/Controllers/LinkFieldControllerTest.php +++ b/tests/php/Controllers/LinkFieldControllerTest.php @@ -9,6 +9,7 @@ use SilverStripe\Security\SecurityToken; use SilverStripe\Control\HTTPRequest; use SilverStripe\LinkField\Tests\Models\LinkTest\LinkOwner; +use SilverStripe\Versioned\Versioned; class LinkFieldControllerTest extends FunctionalTest { @@ -24,6 +25,15 @@ class LinkFieldControllerTest extends FunctionalTest protected function setUp(): void { parent::setUp(); + // The Versioned extension is added to LinkOwner, though it's only used for the + // unit tests speicifically to test Versioned functionality. It interferes with + // other units tests that were written before the Versioned extension was added + // The extenion needs to be added on the class rather than dynmically so that the + // relevant database tables are created. The extension is added back in on unit + // tests that requrie it. There's a call to add the extension back in the + // tearDown method + LinkOwner::remove_extension(Versioned::class); + $this->logInWithPermission('ADMIN'); // CSRF token check is normally disabled for unit-tests $this->securityTokenWasEnabled = SecurityToken::is_enabled(); @@ -45,6 +55,8 @@ protected function tearDown(): void if (!$this->securityTokenWasEnabled) { SecurityToken::disable(); } + // Reset the extension that was removed in the setUp() method + LinkOwner::add_extension(Versioned::class); } /** @@ -500,7 +512,6 @@ public function testLinkDelete( $owner = $this->getFixtureLinkOwner(); $this->assertSame(0, $owner->LinkID); } - $this->assertTrue(true); } public function provideLinkDelete(): array @@ -544,6 +555,38 @@ public function provideLinkDelete(): array ]; } + public function testLinkDeleteVersions(): void + { + LinkOwner::add_extension(Versioned::class); + // Need to re-link rejoin $link to $owner as the fixture data for whatever reason + // because doing weird stuff with versioning and adding extensions + $link = $this->getFixtureLink(); + $owner = $this->getFixtureLinkOwner(); + $owner->Link = $link; + $link->publishSingle(); + $owner->publishSingle(); + $linkID = $link->ID; + $ownerID = $owner->ID; + $ownerClass = urlencode($owner->ClassName); + $ownerRelation = 'Link'; + $url = "/admin/linkfield/delete/$linkID?ownerID=$ownerID&ownerClass=$ownerClass&ownerRelation=$ownerRelation"; + $headers = $this->csrfTokenheader(); + $this->assertNotSame(0, $owner->LinkID); + $liveOwner = Versioned::get_by_stage($owner::class, Versioned::LIVE)->byID($ownerID); + $this->assertSame($owner->LinkID, $liveOwner->LinkID); + $liveLink = Versioned::get_by_stage($link::class, Versioned::LIVE)->byID($linkID); + $this->assertNotNull($liveLink); + $this->mainSession->sendRequest('DELETE', $url, [], $headers); + $draftOwner = Versioned::get_by_stage($owner::class, Versioned::DRAFT)->byID($ownerID); + $this->assertSame(0, $draftOwner->LinkID); + $draftLink = Versioned::get_by_stage($link::class, Versioned::DRAFT)->byID($linkID); + $this->assertNull($draftLink); + $liveOwner = Versioned::get_by_stage($owner::class, Versioned::LIVE)->byID($ownerID); + $this->assertSame(0, $liveOwner->LinkID); + $liveLink = Versioned::get_by_stage($link::class, Versioned::LIVE)->byID($linkID); + $this->assertNull($liveLink); + } + /** * @dataProvider provideLinkSort */ diff --git a/tests/php/Models/LinkTest/LinkOwner.php b/tests/php/Models/LinkTest/LinkOwner.php index bd61af73..08dd7996 100644 --- a/tests/php/Models/LinkTest/LinkOwner.php +++ b/tests/php/Models/LinkTest/LinkOwner.php @@ -5,6 +5,7 @@ use SilverStripe\Dev\TestOnly; use SilverStripe\LinkField\Models\Link; use SilverStripe\ORM\DataObject; +use SilverStripe\Versioned\Versioned; class LinkOwner extends DataObject implements TestOnly { @@ -17,6 +18,10 @@ class LinkOwner extends DataObject implements TestOnly 'LinkList2' => Link::class . '.Owner', ]; + private static array $extensions = [ + Versioned::class, + ]; + // Allows us to toggle permissions easily within a unit test public bool $canView = true; public bool $canEdit = true;