]> BookStack Code Mirror - bookstack/commitdiff
References: Fixed references count/list recycle bin interaction
authorDan Brown <redacted>
Mon, 1 Apr 2024 16:08:53 +0000 (17:08 +0100)
committerDan Brown <redacted>
Mon, 1 Apr 2024 16:08:53 +0000 (17:08 +0100)
Count and reference list would get references then attempt to load
entities, which could fail to load if in the recycle bin.
This updates the queries to effectively ignore references for items we
can't see (in recycle bin).
Added test to cover.

For #4918

app/References/ReferenceFetcher.php
tests/References/ReferencesTest.php

index 655ea7c09eb2bf8b0c21b7c30f0345b7ab0e3ea7..1c9664f45a9979d8c5e88627b4bb6eaa7547dd1a 100644 (file)
@@ -41,7 +41,8 @@ class ReferenceFetcher
     {
         $baseQuery = Reference::query()
             ->where('to_type', '=', $entity->getMorphClass())
-            ->where('to_id', '=', $entity->id);
+            ->where('to_id', '=', $entity->id)
+            ->whereHas('from');
 
         return $this->permissions->restrictEntityRelationQuery(
             $baseQuery,
index 715f7143534b09ddcf179bd2517c5a11c6461462..f8698d028858145deba511a35784839d5d7de9df 100644 (file)
@@ -271,7 +271,31 @@ class ReferencesTest extends TestCase
         }
     }
 
-    protected function createReference(Model $from, Model $to)
+    public function test_reference_from_deleted_item_does_not_count_or_show_in_references_page()
+    {
+        $page = $this->entities->page();
+        $referencingPageA = $this->entities->page();
+        $referencingPageB = $this->entities->page();
+
+        $this->asEditor();
+        $this->createReference($referencingPageA, $page);
+        $this->createReference($referencingPageB, $page);
+
+        $resp = $this->get($page->getUrl());
+        $resp->assertSee('Referenced by 2 items');
+
+        $this->delete($referencingPageA->getUrl());
+
+        $resp = $this->get($page->getUrl());
+        $resp->assertSee('Referenced by 1 item');
+
+        $resp = $this->get($page->getUrl('/references'));
+        $resp->assertOk();
+        $resp->assertSee($referencingPageB->getUrl());
+        $resp->assertDontSee($referencingPageA->getUrl());
+    }
+
+    protected function createReference(Model $from, Model $to): void
     {
         (new Reference())->forceFill([
             'from_type' => $from->getMorphClass(),