| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Tests\Helpers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | use BookStack\Entities\Repos\BookRepo; | 
					
						
							|  |  |  | use BookStack\Entities\Repos\BookshelfRepo; | 
					
						
							|  |  |  | use BookStack\Entities\Repos\ChapterRepo; | 
					
						
							|  |  |  | use BookStack\Entities\Repos\PageRepo; | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Users\Models\User; | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  | use Illuminate\Database\Eloquent\Builder; | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Class to provider and action entity models for common test case | 
					
						
							|  |  |  |  * operations. Tracks handled models and only returns fresh models. | 
					
						
							|  |  |  |  * Does not dedupe against nested/child/parent models. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  | class EntityProvider | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @var array<string, int[]> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected array $fetchCache = [ | 
					
						
							|  |  |  |         'book' => [], | 
					
						
							|  |  |  |         'page' => [], | 
					
						
							|  |  |  |         'bookshelf' => [], | 
					
						
							|  |  |  |         'chapter' => [], | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get an un-fetched page from the system. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function page(callable $queryFilter = null): Page | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var Page $page */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |         $page = Page::query()->when($queryFilter, $queryFilter)->whereNotIn('id', $this->fetchCache['page'])->first(); | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |         $this->addToCache($page); | 
					
						
							|  |  |  |         return $page; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function pageWithinChapter(): Page | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->page(fn(Builder $query) => $query->whereHas('chapter')->with('chapter')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function pageNotWithinChapter(): Page | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->page(fn(Builder $query) => $query->where('chapter_id', '=', 0)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get an un-fetched chapter from the system. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function chapter(callable $queryFilter = null): Chapter | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var Chapter $chapter */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |         $chapter = Chapter::query()->when($queryFilter, $queryFilter)->whereNotIn('id', $this->fetchCache['chapter'])->first(); | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |         $this->addToCache($chapter); | 
					
						
							|  |  |  |         return $chapter; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function chapterHasPages(): Chapter | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->chapter(fn(Builder $query) => $query->whereHas('pages')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get an un-fetched book from the system. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function book(callable $queryFilter = null): Book | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var Book $book */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |         $book = Book::query()->when($queryFilter, $queryFilter)->whereNotIn('id', $this->fetchCache['book'])->first(); | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |         $this->addToCache($book); | 
					
						
							|  |  |  |         return $book; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get a book that has chapters and pages assigned. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function bookHasChaptersAndPages(): Book | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->book(function (Builder $query) { | 
					
						
							|  |  |  |             $query->has('chapters')->has('pages')->with(['chapters', 'pages']); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get an un-fetched shelf from the system. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function shelf(callable $queryFilter = null): Bookshelf | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var Bookshelf $shelf */ | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |         $shelf = Bookshelf::query()->when($queryFilter, $queryFilter)->whereNotIn('id', $this->fetchCache['bookshelf'])->first(); | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |         $this->addToCache($shelf); | 
					
						
							|  |  |  |         return $shelf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get all entity types from the system. | 
					
						
							|  |  |  |      * @return array{page: Page, chapter: Chapter, book: Book, bookshelf: Bookshelf} | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function all(): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             'page'      => $this->page(), | 
					
						
							|  |  |  |             'chapter'   => $this->chapter(), | 
					
						
							|  |  |  |             'book'      => $this->book(), | 
					
						
							|  |  |  |             'bookshelf' => $this->shelf(), | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 05:11:16 +08:00
										 |  |  |     public function updatePage(Page $page, array $data): Page | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->addToCache($page); | 
					
						
							|  |  |  |         return app()->make(PageRepo::class)->update($page, $data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Create a book to page chain of entities that belong to a specific user. | 
					
						
							|  |  |  |      * @return array{book: Book, chapter: Chapter, page: Page} | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function createChainBelongingToUser(User $creatorUser, ?User $updaterUser = null): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($updaterUser)) { | 
					
						
							|  |  |  |             $updaterUser = $creatorUser; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $userAttrs = ['created_by' => $creatorUser->id, 'owned_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]; | 
					
						
							|  |  |  |         /** @var Book $book */ | 
					
						
							|  |  |  |         $book = Book::factory()->create($userAttrs); | 
					
						
							|  |  |  |         $chapter = Chapter::factory()->create(array_merge(['book_id' => $book->id], $userAttrs)); | 
					
						
							|  |  |  |         $page = Page::factory()->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $book->rebuildPermissions(); | 
					
						
							|  |  |  |         $this->addToCache([$page, $chapter, $book]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return compact('book', 'chapter', 'page'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create and return a new bookshelf. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function newShelf(array $input = ['name' => 'test shelf', 'description' => 'My new test shelf']): Bookshelf | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $shelf = app(BookshelfRepo::class)->create($input, []); | 
					
						
							|  |  |  |         $this->addToCache($shelf); | 
					
						
							|  |  |  |         return $shelf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create and return a new book. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function newBook(array $input = ['name' => 'test book', 'description' => 'My new test book']): Book | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $book = app(BookRepo::class)->create($input); | 
					
						
							|  |  |  |         $this->addToCache($book); | 
					
						
							|  |  |  |         return $book; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create and return a new test chapter. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function newChapter(array $input, Book $book): Chapter | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $chapter = app(ChapterRepo::class)->create($input, $book); | 
					
						
							|  |  |  |         $this->addToCache($chapter); | 
					
						
							|  |  |  |         return $chapter; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create and return a new test page. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function newPage(array $input = ['name' => 'test page', 'html' => 'My new test page']): Page | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $book = $this->book(); | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |         $pageRepo = app(PageRepo::class); | 
					
						
							|  |  |  |         $draftPage = $pageRepo->getNewDraftPage($book); | 
					
						
							|  |  |  |         $this->addToCache($draftPage); | 
					
						
							|  |  |  |         return $pageRepo->publishDraft($draftPage, $input); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 01:57:34 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Create and return a new test draft page. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function newDraftPage(array $input = ['name' => 'test page', 'html' => 'My new test page']): Page | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $book = $this->book(); | 
					
						
							|  |  |  |         $pageRepo = app(PageRepo::class); | 
					
						
							|  |  |  |         $draftPage = $pageRepo->getNewDraftPage($book); | 
					
						
							|  |  |  |         $pageRepo->updatePageDraft($draftPage, $input); | 
					
						
							|  |  |  |         $this->addToCache($draftPage); | 
					
						
							|  |  |  |         return $draftPage; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 23:49:25 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Entity|Entity[] $entities | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function addToCache($entities): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($entities)) { | 
					
						
							|  |  |  |             $entities = [$entities]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($entities as $entity) { | 
					
						
							|  |  |  |             $this->fetchCache[$entity->getType()][] = $entity->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |