]> BookStack Code Mirror - bookstack/blobdiff - app/Entities/Tools/Cloner.php
Customization: Added parent tag classes
[bookstack] / app / Entities / Tools / Cloner.php
index c76f224b4f9130402301e5967078cc7a8d079d92..2be6083e3ddcb810871ab42ad973070d1f41fd8e 100644 (file)
@@ -2,10 +2,12 @@
 
 namespace BookStack\Entities\Tools;
 
-use BookStack\Actions\Tag;
+use BookStack\Activity\Models\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\HasCoverImage;
 use BookStack\Entities\Models\Page;
 use BookStack\Entities\Repos\BookRepo;
 use BookStack\Entities\Repos\ChapterRepo;
@@ -16,17 +18,12 @@ use Illuminate\Http\UploadedFile;
 
 class Cloner
 {
-    protected PageRepo $pageRepo;
-    protected ChapterRepo $chapterRepo;
-    protected BookRepo $bookRepo;
-    protected ImageService $imageService;
-
-    public function __construct(PageRepo $pageRepo, ChapterRepo $chapterRepo, BookRepo $bookRepo, ImageService $imageService)
-    {
-        $this->pageRepo = $pageRepo;
-        $this->chapterRepo = $chapterRepo;
-        $this->bookRepo = $bookRepo;
-        $this->imageService = $imageService;
+    public function __construct(
+        protected PageRepo $pageRepo,
+        protected ChapterRepo $chapterRepo,
+        protected BookRepo $bookRepo,
+        protected ImageService $imageService,
+    ) {
     }
 
     /**
@@ -71,9 +68,11 @@ class Cloner
         $bookDetails = $this->entityToInputData($original);
         $bookDetails['name'] = $newName;
 
+        // Clone book
         $copyBook = $this->bookRepo->create($bookDetails);
 
-        $directChildren = $original->getDirectChildren();
+        // Clone contents
+        $directChildren = $original->getDirectVisibleChildren();
         foreach ($directChildren as $child) {
             if ($child instanceof Chapter && userCan('chapter-create', $copyBook)) {
                 $this->cloneChapter($child, $copyBook, $child->name);
@@ -84,11 +83,20 @@ class Cloner
             }
         }
 
+        // Clone bookshelf relationships
+        /** @var Bookshelf $shelf */
+        foreach ($original->shelves as $shelf) {
+            if (userCan('bookshelf-update', $shelf)) {
+                $shelf->appendBook($copyBook);
+            }
+        }
+
         return $copyBook;
     }
 
     /**
      * Convert an entity to a raw data array of input data.
+     *
      * @return array<string, mixed>
      */
     public function entityToInputData(Entity $entity): array
@@ -97,10 +105,11 @@ class Cloner
         $inputData['tags'] = $this->entityTagsToInputArray($entity);
 
         // Add a cover to the data if existing on the original entity
-        if ($entity->cover instanceof Image) {
-            $tmpImgFile = tmpfile();
-            $uploadedFile = $this->imageToUploadedFile($entity->cover, $tmpImgFile);
-            $inputData['image'] = $uploadedFile;
+        if ($entity instanceof HasCoverImage) {
+            $cover = $entity->cover()->first();
+            if ($cover) {
+                $inputData['image'] = $this->imageToUploadedFile($cover);
+            }
         }
 
         return $inputData;
@@ -111,8 +120,7 @@ class Cloner
      */
     public function copyEntityPermissions(Entity $sourceEntity, Entity $targetEntity): void
     {
-        $targetEntity->restricted = $sourceEntity->restricted;
-        $permissions = $sourceEntity->permissions()->get(['role_id', 'action'])->toArray();
+        $permissions = $sourceEntity->permissions()->get(['role_id', 'view', 'create', 'update', 'delete'])->toArray();
         $targetEntity->permissions()->delete();
         $targetEntity->permissions()->createMany($permissions);
         $targetEntity->rebuildPermissions();
@@ -122,10 +130,10 @@ class Cloner
      * Convert an image instance to an UploadedFile instance to mimic
      * a file being uploaded.
      */
-    protected function imageToUploadedFile(Image $image, &$tmpFile): ?UploadedFile
+    protected function imageToUploadedFile(Image $image): ?UploadedFile
     {
         $imgData = $this->imageService->getImageData($image);
-        $tmpImgFilePath = stream_get_meta_data($tmpFile)['uri'];
+        $tmpImgFilePath = tempnam(sys_get_temp_dir(), 'bs_cover_clone_');
         file_put_contents($tmpImgFilePath, $imgData);
 
         return new UploadedFile($tmpImgFilePath, basename($image->path));