From 60171b3522220e874436f52cc8936f6879e7e60f Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Wed, 28 Sep 2022 14:14:51 +0100
Subject: [PATCH] Updated book copy to copy shelf relations

Where permission to edit the shelf is allowed.
For #3699
---
 app/Entities/Models/Book.php  |  1 +
 app/Entities/Tools/Cloner.php | 11 +++++++++++
 tests/Entity/BookTest.php     | 26 +++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php
index 8217d2cab..bf42f2008 100644
--- a/app/Entities/Models/Book.php
+++ b/app/Entities/Models/Book.php
@@ -19,6 +19,7 @@ use Illuminate\Support\Collection;
  * @property \Illuminate\Database\Eloquent\Collection $chapters
  * @property \Illuminate\Database\Eloquent\Collection $pages
  * @property \Illuminate\Database\Eloquent\Collection $directPages
+ * @property \Illuminate\Database\Eloquent\Collection $shelves
  */
 class Book extends Entity implements HasCoverImage
 {
diff --git a/app/Entities/Tools/Cloner.php b/app/Entities/Tools/Cloner.php
index 92b62a754..86f392e61 100644
--- a/app/Entities/Tools/Cloner.php
+++ b/app/Entities/Tools/Cloner.php
@@ -4,6 +4,7 @@ namespace BookStack\Entities\Tools;
 
 use BookStack\Actions\Tag;
 use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Bookshelf;
 use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Entity;
 use BookStack\Entities\Models\Page;
@@ -71,8 +72,10 @@ class Cloner
         $bookDetails = $this->entityToInputData($original);
         $bookDetails['name'] = $newName;
 
+        // Clone book
         $copyBook = $this->bookRepo->create($bookDetails);
 
+        // Clone contents
         $directChildren = $original->getDirectChildren();
         foreach ($directChildren as $child) {
             if ($child instanceof Chapter && userCan('chapter-create', $copyBook)) {
@@ -84,6 +87,14 @@ class Cloner
             }
         }
 
+        // Clone bookshelf relationships
+        /** @var Bookshelf $shelf */
+        foreach ($original->shelves as $shelf) {
+            if (userCan('bookshelf-update', $shelf)) {
+                $shelf->appendBook($copyBook);
+            }
+        }
+
         return $copyBook;
     }
 
diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php
index 2e6f8e9de..2f04fcf25 100644
--- a/tests/Entity/BookTest.php
+++ b/tests/Entity/BookTest.php
@@ -4,6 +4,7 @@ namespace Tests\Entity;
 
 use BookStack\Entities\Models\Book;
 use BookStack\Entities\Models\BookChild;
+use BookStack\Entities\Models\Bookshelf;
 use BookStack\Entities\Repos\BookRepo;
 use Tests\TestCase;
 use Tests\Uploads\UsesImages;
@@ -344,11 +345,34 @@ class BookTest extends TestCase
         $bookRepo->updateCoverImage($book, $coverImageFile);
 
         $this->asEditor()->post($book->getUrl('/copy'), ['name' => 'My copy book']);
-
         /** @var Book $copy */
         $copy = Book::query()->where('name', '=', 'My copy book')->first();
 
         $this->assertNotNull($copy->cover);
         $this->assertNotEquals($book->cover->id, $copy->cover->id);
     }
+
+    public function test_copy_adds_book_to_shelves_if_edit_permissions_allows()
+    {
+        /** @var Bookshelf $shelfA */
+        /** @var Bookshelf $shelfB */
+        [$shelfA, $shelfB] = Bookshelf::query()->take(2)->get();
+        /** @var Book $book */
+        $book = Book::query()->first();
+
+        $shelfA->appendBook($book);
+        $shelfB->appendBook($book);
+
+        $viewer = $this->getViewer();
+        $this->giveUserPermissions($viewer, ['book-update-all', 'book-create-all', 'bookshelf-update-all']);
+        $this->setEntityRestrictions($shelfB);
+
+
+        $this->asEditor()->post($book->getUrl('/copy'), ['name' => 'My copy book']);
+        /** @var Book $copy */
+        $copy = Book::query()->where('name', '=', 'My copy book')->first();
+
+        $this->assertTrue($copy->shelves()->where('id', '=', $shelfA->id)->exists());
+        $this->assertFalse($copy->shelves()->where('id', '=', $shelfB->id)->exists());
+    }
 }