]> BookStack Code Mirror - bookstack/commitdiff
Finished refactor of entity repos 262/head
authorDan Brown <redacted>
Mon, 2 Jan 2017 11:07:27 +0000 (11:07 +0000)
committerDan Brown <redacted>
Mon, 2 Jan 2017 11:07:27 +0000 (11:07 +0000)
Removed entity-specific repos and standardised
the majority of repo calls to be applicable to
all entity types

16 files changed:
app/Chapter.php
app/Http/Controllers/AttachmentController.php
app/Http/Controllers/BookController.php
app/Http/Controllers/ChapterController.php
app/Http/Controllers/ImageController.php
app/Http/Controllers/PageController.php
app/Repos/BookRepo.php [deleted file]
app/Repos/ChapterRepo.php [deleted file]
app/Repos/EntityRepo.php
app/Repos/PageRepo.php [deleted file]
app/Repos/TagRepo.php
app/Services/PermissionService.php
tests/Entity/EntityTest.php
tests/Entity/PageDraftTest.php
tests/Entity/SortTest.php
tests/ImageTest.php

index 586ce3fe37e6b97a1d3721c96c9aab9bdf903aeb..dc23f5ebdbd015fbab800084baf3066ab66d1a59 100644 (file)
@@ -18,11 +18,12 @@ class Chapter extends Entity
 
     /**
      * Get the pages that this chapter contains.
+     * @param string $dir
      * @return mixed
      */
-    public function pages()
+    public function pages($dir = 'ASC')
     {
-        return $this->hasMany(Page::class)->orderBy('priority', 'ASC');
+        return $this->hasMany(Page::class)->orderBy('priority', $dir);
     }
 
     /**
index 715cd2bd8af66565c1c700fe8ffe458b8a0c85c3..3c325d0fe8d4652d02e96bf0c393f040599417ec 100644 (file)
@@ -3,7 +3,6 @@
 use BookStack\Exceptions\FileUploadException;
 use BookStack\Attachment;
 use BookStack\Repos\EntityRepo;
-use BookStack\Repos\PageRepo;
 use BookStack\Services\AttachmentService;
 use Illuminate\Http\Request;
 
@@ -11,21 +10,18 @@ class AttachmentController extends Controller
 {
     protected $attachmentService;
     protected $attachment;
-    protected $pageRepo;
     protected $entityRepo;
 
     /**
      * AttachmentController constructor.
      * @param AttachmentService $attachmentService
      * @param Attachment $attachment
-     * @param PageRepo $pageRepo
+     * @param EntityRepo $entityRepo
      */
-    public function __construct(AttachmentService $attachmentService, Attachment $attachment, EntityRepo $entityRepo, PageRepo $pageRepo)
+    public function __construct(AttachmentService $attachmentService, Attachment $attachment, EntityRepo $entityRepo)
     {
         $this->attachmentService = $attachmentService;
         $this->attachment = $attachment;
-        // TODO - Remove this
-        $this->pageRepo = $pageRepo;
         $this->entityRepo = $entityRepo;
         parent::__construct();
     }
index b6856f273603726335e0ee7800b8408ff3c88469..57ac486d5e71122b49b057b9fc7dc25dd36ef3ed 100644 (file)
@@ -4,10 +4,6 @@ use Activity;
 use BookStack\Repos\EntityRepo;
 use BookStack\Repos\UserRepo;
 use Illuminate\Http\Request;
-use BookStack\Http\Requests;
-use BookStack\Repos\BookRepo;
-use BookStack\Repos\ChapterRepo;
-use BookStack\Repos\PageRepo;
 use Illuminate\Http\Response;
 use Views;
 
@@ -15,26 +11,16 @@ class BookController extends Controller
 {
 
     protected $entityRepo;
-    protected $bookRepo;
-    protected $pageRepo;
-    protected $chapterRepo;
     protected $userRepo;
 
     /**
      * BookController constructor.
      * @param EntityRepo $entityRepo
-     * @param BookRepo $bookRepo
-     * @param PageRepo $pageRepo
-     * @param ChapterRepo $chapterRepo
      * @param UserRepo $userRepo
      */
-    public function __construct(EntityRepo $entityRepo, BookRepo $bookRepo, PageRepo $pageRepo, ChapterRepo $chapterRepo, UserRepo $userRepo)
+    public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
     {
         $this->entityRepo = $entityRepo;
-        // TODO - Remove below
-        $this->bookRepo = $bookRepo;
-        $this->pageRepo = $pageRepo;
-        $this->chapterRepo = $chapterRepo;
         $this->userRepo = $userRepo;
         parent::__construct();
     }
@@ -76,7 +62,7 @@ class BookController extends Controller
             'name' => 'required|string|max:255',
             'description' => 'string|max:1000'
         ]);
-        $book = $this->bookRepo->createFromInput($request->all());
+        $book = $this->entityRepo->createFromInput('book', $request->all());
         Activity::add($book, 'book_create', $book->id);
         return redirect($book->getUrl());
     }
@@ -90,7 +76,7 @@ class BookController extends Controller
     {
         $book = $this->entityRepo->getBySlug('book', $slug);
         $this->checkOwnablePermission('book-view', $book);
-        $bookChildren = $this->bookRepo->getChildren($book);
+        $bookChildren = $this->entityRepo->getBookChildren($book);
         Views::add($book);
         $this->setPageTitle($book->getShortName());
         return view('books/show', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]);
@@ -123,7 +109,7 @@ class BookController extends Controller
             'name' => 'required|string|max:255',
             'description' => 'string|max:1000'
         ]);
-        $book = $this->bookRepo->updateFromInput($book, $request->all());
+        $book = $this->entityRepo->updateFromInput('book', $book, $request->all());
         Activity::add($book, 'book_update', $book->id);
         return redirect($book->getUrl());
     }
@@ -150,7 +136,7 @@ class BookController extends Controller
     {
         $book = $this->entityRepo->getBySlug('book', $bookSlug);
         $this->checkOwnablePermission('book-update', $book);
-        $bookChildren = $this->bookRepo->getChildren($book, true);
+        $bookChildren = $this->entityRepo->getBookChildren($book, true);
         $books = $this->entityRepo->getAll('book', false);
         $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()]));
         return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]);
@@ -165,7 +151,7 @@ class BookController extends Controller
     public function getSortItem($bookSlug)
     {
         $book = $this->entityRepo->getBySlug('book', $bookSlug);
-        $bookChildren = $this->bookRepo->getChildren($book);
+        $bookChildren = $this->entityRepo->getBookChildren($book);
         return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]);
     }
 
@@ -202,7 +188,7 @@ class BookController extends Controller
 
             // Update models only if there's a change in parent chain or ordering.
             if ($model->priority !== $priority || $model->book_id !== $bookId || ($isPage && $model->chapter_id !== $chapterId)) {
-                $isPage ? $this->pageRepo->changeBook($bookId, $model) : $this->chapterRepo->changeBook($bookId, $model);
+                $this->entityRepo->changeBook($isPage?'page':'chapter', $bookId, $model);
                 $model->priority = $priority;
                 if ($isPage) $model->chapter_id = $chapterId;
                 $model->save();
@@ -222,7 +208,7 @@ class BookController extends Controller
         }
 
         // Update permissions on changed models
-        $this->bookRepo->buildJointPermissions($updatedModels);
+        $this->entityRepo->buildJointPermissions($updatedModels);
 
         return redirect($book->getUrl());
     }
@@ -237,8 +223,7 @@ class BookController extends Controller
         $book = $this->entityRepo->getBySlug('book', $bookSlug);
         $this->checkOwnablePermission('book-delete', $book);
         Activity::addMessage('book_delete', 0, $book->name);
-        Activity::removeEntity($book);
-        $this->bookRepo->destroy($book);
+        $this->entityRepo->destroyBook($book);
         return redirect('/books');
     }
 
@@ -269,7 +254,7 @@ class BookController extends Controller
     {
         $book = $this->entityRepo->getBySlug('book', $bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $book);
-        $this->bookRepo->updateEntityPermissionsFromRequest($request, $book);
+        $this->entityRepo->updateEntityPermissionsFromRequest($request, $book);
         session()->flash('success', trans('entities.books_permissions_updated'));
         return redirect($book->getUrl());
     }
index d239b08cc01d88bea6b3f424f5ad646e9f020916..1760ee5c6a3ee0502c6b69e1202ea0c4c742d48c 100644 (file)
@@ -4,32 +4,23 @@ use Activity;
 use BookStack\Repos\EntityRepo;
 use BookStack\Repos\UserRepo;
 use Illuminate\Http\Request;
-use BookStack\Repos\BookRepo;
-use BookStack\Repos\ChapterRepo;
 use Illuminate\Http\Response;
 use Views;
 
 class ChapterController extends Controller
 {
 
-    protected $bookRepo;
-    protected $chapterRepo;
     protected $userRepo;
     protected $entityRepo;
 
     /**
      * ChapterController constructor.
      * @param EntityRepo $entityRepo
-     * @param BookRepo $bookRepo
-     * @param ChapterRepo $chapterRepo
      * @param UserRepo $userRepo
      */
-    public function __construct(EntityRepo $entityRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, UserRepo $userRepo)
+    public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
     {
         $this->entityRepo = $entityRepo;
-        // TODO - Remove below
-        $this->bookRepo = $bookRepo;
-        $this->chapterRepo = $chapterRepo;
         $this->userRepo = $userRepo;
         parent::__construct();
     }
@@ -63,8 +54,8 @@ class ChapterController extends Controller
         $this->checkOwnablePermission('chapter-create', $book);
 
         $input = $request->all();
-        $input['priority'] = $this->bookRepo->getNewPriority($book);
-        $chapter = $this->chapterRepo->createFromInput($input, $book);
+        $input['priority'] = $this->entityRepo->getNewBookPriority($book);
+        $chapter = $this->entityRepo->createFromInput('chapter', $input, $book);
         Activity::add($chapter, 'chapter_create', $book->id);
         return redirect($chapter->getUrl());
     }
@@ -79,10 +70,10 @@ class ChapterController extends Controller
     {
         $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
         $this->checkOwnablePermission('chapter-view', $chapter);
-        $sidebarTree = $this->bookRepo->getChildren($chapter->book);
+        $sidebarTree = $this->entityRepo->getBookChildren($chapter->book);
         Views::add($chapter);
         $this->setPageTitle($chapter->getShortName());
-        $pages = $this->chapterRepo->getChildren($chapter);
+        $pages = $this->entityRepo->getChapterChildren($chapter);
         return view('chapters/show', [
             'book' => $chapter->book,
             'chapter' => $chapter,
@@ -153,7 +144,7 @@ class ChapterController extends Controller
         $book = $chapter->book;
         $this->checkOwnablePermission('chapter-delete', $chapter);
         Activity::addMessage('chapter_delete', $book->id, $chapter->name);
-        $this->chapterRepo->destroy($chapter);
+        $this->entityRepo->destroyChapter($chapter);
         return redirect($book->getUrl());
     }
 
@@ -206,7 +197,7 @@ class ChapterController extends Controller
             return redirect()->back();
         }
 
-        $this->chapterRepo->changeBook($parent->id, $chapter, true);
+        $this->entityRepo->changeBook('chapter', $parent->id, $chapter, true);
         Activity::add($chapter, 'chapter_move', $chapter->book->id);
         session()->flash('success', trans('entities.chapter_move_success', ['bookName' => $parent->name]));
 
@@ -241,7 +232,7 @@ class ChapterController extends Controller
     {
         $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $chapter);
-        $this->chapterRepo->updateEntityPermissionsFromRequest($request, $chapter);
+        $this->entityRepo->updateEntityPermissionsFromRequest($request, $chapter);
         session()->flash('success', trans('entities.chapters_permissions_success'));
         return redirect($chapter->getUrl());
     }
index f073bea0afbd7ea890fbaaee899e7597409cf669..77c320e07db7989203f87284914ba39e68803672 100644 (file)
@@ -1,6 +1,7 @@
 <?php namespace BookStack\Http\Controllers;
 
 use BookStack\Exceptions\ImageUploadException;
+use BookStack\Repos\EntityRepo;
 use BookStack\Repos\ImageRepo;
 use Illuminate\Filesystem\Filesystem as File;
 use Illuminate\Http\Request;
@@ -150,12 +151,12 @@ class ImageController extends Controller
 
     /**
      * Deletes an image and all thumbnail/image files
-     * @param PageRepo $pageRepo
+     * @param EntityRepo $entityRepo
      * @param Request $request
      * @param int $id
      * @return \Illuminate\Http\JsonResponse
      */
-    public function destroy(PageRepo $pageRepo, Request $request, $id)
+    public function destroy(EntityRepo $entityRepo, Request $request, $id)
     {
         $image = $this->imageRepo->getById($id);
         $this->checkOwnablePermission('image-delete', $image);
@@ -163,7 +164,7 @@ class ImageController extends Controller
         // Check if this image is used on any pages
         $isForced = ($request->has('force') && ($request->get('force') === 'true') || $request->get('force') === true);
         if (!$isForced) {
-            $pageSearch = $pageRepo->searchForImage($image->url);
+            $pageSearch = $entityRepo->searchForImage($image->url);
             if ($pageSearch !== false) {
                 return response()->json($pageSearch, 400);
             }
index 5a33ecb37d2c5465cafad62625649c5bff14b307..6ed9fc30c79c8e6d037d06c1ca727448152ff0b9 100644 (file)
@@ -7,9 +7,6 @@ use BookStack\Repos\UserRepo;
 use BookStack\Services\ExportService;
 use Carbon\Carbon;
 use Illuminate\Http\Request;
-use BookStack\Repos\BookRepo;
-use BookStack\Repos\ChapterRepo;
-use BookStack\Repos\PageRepo;
 use Illuminate\Http\Response;
 use Views;
 use GatherContent\Htmldiff\Htmldiff;
@@ -18,28 +15,18 @@ class PageController extends Controller
 {
 
     protected $entityRepo;
-    protected $pageRepo;
-    protected $bookRepo;
-    protected $chapterRepo;
     protected $exportService;
     protected $userRepo;
 
     /**
      * PageController constructor.
      * @param EntityRepo $entityRepo
-     * @param PageRepo $pageRepo
-     * @param BookRepo $bookRepo
-     * @param ChapterRepo $chapterRepo
      * @param ExportService $exportService
      * @param UserRepo $userRepo
      */
-    public function __construct(EntityRepo $entityRepo, PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService, UserRepo $userRepo)
+    public function __construct(EntityRepo $entityRepo, ExportService $exportService, UserRepo $userRepo)
     {
         $this->entityRepo = $entityRepo;
-        // TODO - remove below;
-        $this->pageRepo = $pageRepo;
-        $this->bookRepo = $bookRepo;
-        $this->chapterRepo = $chapterRepo;
         $this->exportService = $exportService;
         $this->userRepo = $userRepo;
         parent::__construct();
@@ -61,7 +48,7 @@ class PageController extends Controller
 
         // Redirect to draft edit screen if signed in
         if ($this->signedIn) {
-            $draft = $this->pageRepo->getDraftPage($book, $chapter);
+            $draft = $this->entityRepo->getDraftPage($book, $chapter);
             return redirect($draft->getUrl());
         }
 
@@ -89,8 +76,8 @@ class PageController extends Controller
         $parent = $chapter ? $chapter : $book;
         $this->checkOwnablePermission('page-create', $parent);
 
-        $page = $this->pageRepo->getDraftPage($book, $chapter);
-        $this->pageRepo->publishDraft($page, [
+        $page = $this->entityRepo->getDraftPage($book, $chapter);
+        $this->entityRepo->publishPageDraft($page, [
             'name' => $request->get('name'),
             'html' => ''
         ]);
@@ -141,12 +128,12 @@ class PageController extends Controller
         $this->checkOwnablePermission('page-create', $parent);
 
         if ($parent->isA('chapter')) {
-            $input['priority'] = $this->chapterRepo->getNewPriority($parent);
+            $input['priority'] = $this->entityRepo->getNewChapterPriority($parent);
         } else {
-            $input['priority'] = $this->bookRepo->getNewPriority($parent);
+            $input['priority'] = $this->entityRepo->getNewBookPriority($parent);
         }
 
-        $page = $this->pageRepo->publishDraft($draftPage, $input);
+        $page = $this->entityRepo->publishPageDraft($draftPage, $input);
 
         Activity::add($page, 'page_create', $book->id);
         return redirect($page->getUrl());
@@ -164,15 +151,15 @@ class PageController extends Controller
         try {
             $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
         } catch (NotFoundException $e) {
-            $page = $this->pageRepo->findPageUsingOldSlug($pageSlug, $bookSlug);
+            $page = $this->entityRepo->getPageByOldSlug($pageSlug, $bookSlug);
             if ($page === null) abort(404);
             return redirect($page->getUrl());
         }
 
         $this->checkOwnablePermission('page-view', $page);
 
-        $sidebarTree = $this->bookRepo->getChildren($page->book);
-        $pageNav = $this->pageRepo->getPageNav($page);
+        $sidebarTree = $this->entityRepo->getBookChildren($page->book);
+        $pageNav = $this->entityRepo->getPageNav($page);
         
         Views::add($page);
         $this->setPageTitle($page->getShortName());
@@ -206,18 +193,18 @@ class PageController extends Controller
 
         // Check for active editing
         $warnings = [];
-        if ($this->pageRepo->isPageEditingActive($page, 60)) {
-            $warnings[] = $this->pageRepo->getPageEditingActiveMessage($page, 60);
+        if ($this->entityRepo->isPageEditingActive($page, 60)) {
+            $warnings[] = $this->entityRepo->getPageEditingActiveMessage($page, 60);
         }
 
         // Check for a current draft version for this user
-        if ($this->pageRepo->hasUserGotPageDraft($page, $this->currentUser->id)) {
-            $draft = $this->pageRepo->getUserPageDraft($page, $this->currentUser->id);
+        if ($this->entityRepo->hasUserGotPageDraft($page, $this->currentUser->id)) {
+            $draft = $this->entityRepo->getUserPageDraft($page, $this->currentUser->id);
             $page->name = $draft->name;
             $page->html = $draft->html;
             $page->markdown = $draft->markdown;
             $page->isDraft = true;
-            $warnings [] = $this->pageRepo->getUserPageDraftMessage($draft);
+            $warnings [] = $this->entityRepo->getUserPageDraftMessage($draft);
         }
 
         if (count($warnings) > 0) session()->flash('warning', implode("\n", $warnings));
@@ -245,7 +232,7 @@ class PageController extends Controller
         ]);
         $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
         $this->checkOwnablePermission('page-update', $page);
-        $this->pageRepo->updatePage($page, $page->book->id, $request->all());
+        $this->entityRepo->updatePage($page, $page->book->id, $request->all());
         Activity::add($page, 'page_update', $page->book->id);
         return redirect($page->getUrl());
     }
@@ -268,11 +255,7 @@ class PageController extends Controller
             ], 500);
         }
 
-        if ($page->draft) {
-            $draft = $this->pageRepo->updateDraftPage($page, $request->only(['name', 'html', 'markdown']));
-        } else {
-            $draft = $this->pageRepo->saveUpdateDraft($page, $request->only(['name', 'html', 'markdown']));
-        }
+        $draft = $this->entityRepo->updatePageDraft($page, $request->only(['name', 'html', 'markdown']));
 
         $updateTime = $draft->updated_at->timestamp;
         $utcUpdateTimestamp = $updateTime + Carbon::createFromTimestamp(0)->offset;
@@ -339,7 +322,7 @@ class PageController extends Controller
         $this->checkOwnablePermission('page-delete', $page);
         Activity::addMessage('page_delete', $book->id, $page->name);
         session()->flash('success', trans('entities.pages_delete_success'));
-        $this->pageRepo->destroy($page);
+        $this->entityRepo->destroyPage($page);
         return redirect($book->getUrl());
     }
 
@@ -356,7 +339,7 @@ class PageController extends Controller
         $book = $page->book;
         $this->checkOwnablePermission('page-update', $page);
         session()->flash('success', trans('entities.pages_delete_draft_success'));
-        $this->pageRepo->destroy($page);
+        $this->entityRepo->destroyPage($page);
         return redirect($book->getUrl());
     }
 
@@ -383,7 +366,7 @@ class PageController extends Controller
     public function showRevision($bookSlug, $pageSlug, $revisionId)
     {
         $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
-        $revision = $this->pageRepo->getRevisionById($revisionId);
+        $revision = $this->entityRepo->getById('page_revision', $revisionId, false);
 
         $page->fill($revision->toArray());
         $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()]));
@@ -404,7 +387,7 @@ class PageController extends Controller
     public function showRevisionChanges($bookSlug, $pageSlug, $revisionId)
     {
         $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
-        $revision = $this->pageRepo->getRevisionById($revisionId);
+        $revision = $this->entityRepo->getById('page_revision', $revisionId);
 
         $prev = $revision->getPrevious();
         $prevContent = ($prev === null) ? '' : $prev->html;
@@ -431,7 +414,7 @@ class PageController extends Controller
     {
         $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
         $this->checkOwnablePermission('page-update', $page);
-        $page = $this->pageRepo->restoreRevision($page, $page->book, $revisionId);
+        $page = $this->entityRepo->restorePageRevision($page, $page->book, $revisionId);
         Activity::add($page, 'page_restore', $page->book->id);
         return redirect($page->getUrl());
     }
@@ -491,7 +474,7 @@ class PageController extends Controller
      */
     public function showRecentlyCreated()
     {
-        $pages = $this->pageRepo->getRecentlyCreatedPaginated(20)->setPath(baseUrl('/pages/recently-created'));
+        $pages = $this->entityRepo->getRecentlyCreatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-created'));
         return view('pages/detailed-listing', [
             'title' => trans('entities.recently_created_pages'),
             'pages' => $pages
@@ -504,7 +487,7 @@ class PageController extends Controller
      */
     public function showRecentlyUpdated()
     {
-        $pages = $this->pageRepo->getRecentlyUpdatedPaginated(20)->setPath(baseUrl('/pages/recently-updated'));
+        $pages = $this->entityRepo->getRecentlyUpdatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-updated'));
         return view('pages/detailed-listing', [
             'title' => trans('entities.recently_updated_pages'),
             'pages' => $pages
@@ -575,7 +558,7 @@ class PageController extends Controller
             return redirect()->back();
         }
 
-        $this->pageRepo->changePageParent($page, $parent);
+        $this->entityRepo->changePageParent($page, $parent);
         Activity::add($page, 'page_move', $page->book->id);
         session()->flash('success', trans('entities.pages_move_success', ['parentName' => $parent->name]));
 
@@ -593,7 +576,7 @@ class PageController extends Controller
     {
         $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $page);
-        $this->pageRepo->updateEntityPermissionsFromRequest($request, $page);
+        $this->entityRepo->updateEntityPermissionsFromRequest($request, $page);
         session()->flash('success', trans('entities.pages_permissions_success'));
         return redirect($page->getUrl());
     }
diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php
deleted file mode 100644 (file)
index f5d19bc..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php namespace BookStack\Repos;
-
-use BookStack\Book;
-
-class BookRepo extends EntityRepo
-{
-    protected $pageRepo;
-    protected $chapterRepo;
-
-    /**
-     * BookRepo constructor.
-     * @param PageRepo $pageRepo
-     * @param ChapterRepo $chapterRepo
-     */
-    public function __construct(PageRepo $pageRepo, ChapterRepo $chapterRepo)
-    {
-        $this->pageRepo = $pageRepo;
-        $this->chapterRepo = $chapterRepo;
-        parent::__construct();
-    }
-
-    /**
-     * Get a new book instance from request input.
-     * @param array $input
-     * @return Book
-     */
-    public function createFromInput($input)
-    {
-        $book = $this->book->newInstance($input);
-        $book->slug = $this->findSuitableSlug('book', $book->name);
-        $book->created_by = user()->id;
-        $book->updated_by = user()->id;
-        $book->save();
-        $this->permissionService->buildJointPermissionsForEntity($book);
-        return $book;
-    }
-
-    /**
-     * Update the given book from user input.
-     * @param Book $book
-     * @param $input
-     * @return Book
-     */
-    public function updateFromInput(Book $book, $input)
-    {
-        if ($book->name !== $input['name']) {
-            $book->slug = $this->findSuitableSlug('book', $input['name'], $book->id);
-        }
-        $book->fill($input);
-        $book->updated_by = user()->id;
-        $book->save();
-        $this->permissionService->buildJointPermissionsForEntity($book);
-        return $book;
-    }
-
-    /**
-     * Destroy the given book.
-     * @param Book $book
-     * @throws \Exception
-     */
-    public function destroy(Book $book)
-    {
-        foreach ($book->pages as $page) {
-            $this->pageRepo->destroy($page);
-        }
-        foreach ($book->chapters as $chapter) {
-            $this->chapterRepo->destroy($chapter);
-        }
-        $book->views()->delete();
-        $book->permissions()->delete();
-        $this->permissionService->deleteJointPermissionsForEntity($book);
-        $book->delete();
-    }
-
-    /**
-     * Get the next child element priority.
-     * @param Book $book
-     * @return int
-     */
-    public function getNewPriority($book)
-    {
-        $lastElem = $this->getChildren($book)->pop();
-        return $lastElem ? $lastElem->priority + 1 : 0;
-    }
-
-    /**
-     * Get all child objects of a book.
-     * Returns a sorted collection of Pages and Chapters.
-     * Loads the book slug onto child elements to prevent access database access for getting the slug.
-     * @param Book $book
-     * @param bool $filterDrafts
-     * @return mixed
-     */
-    public function getChildren(Book $book, $filterDrafts = false)
-    {
-        $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts);
-        $entities = [];
-        $parents = [];
-        $tree = [];
-
-        foreach ($q as $index => $rawEntity) {
-            if ($rawEntity->entity_type === 'Bookstack\\Page') {
-                $entities[$index] = $this->page->newFromBuilder($rawEntity);
-            } else if ($rawEntity->entity_type === 'Bookstack\\Chapter') {
-                $entities[$index] = $this->chapter->newFromBuilder($rawEntity);
-                $key = $entities[$index]->entity_type . ':' . $entities[$index]->id;
-                $parents[$key] = $entities[$index];
-                $parents[$key]->setAttribute('pages', collect());
-            }
-            if ($entities[$index]->chapter_id === 0) $tree[] = $entities[$index];
-            $entities[$index]->book = $book;
-        }
-
-        foreach ($entities as $entity) {
-            if ($entity->chapter_id === 0) continue;
-            $parentKey = 'Bookstack\\Chapter:' . $entity->chapter_id;
-            $chapter = $parents[$parentKey];
-            $chapter->pages->push($entity);
-        }
-
-        return collect($tree);
-    }
-
-}
\ No newline at end of file
diff --git a/app/Repos/ChapterRepo.php b/app/Repos/ChapterRepo.php
deleted file mode 100644 (file)
index afbf312..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php namespace BookStack\Repos;
-
-
-use Activity;
-use BookStack\Book;
-use BookStack\Exceptions\NotFoundException;
-use Illuminate\Support\Str;
-use BookStack\Chapter;
-
-class ChapterRepo extends EntityRepo
-{
-    protected $pageRepo;
-
-    /**
-     * ChapterRepo constructor.
-     * @param $pageRepo
-     */
-    public function __construct(PageRepo $pageRepo)
-    {
-        $this->pageRepo = $pageRepo;
-        parent::__construct();
-    }
-
-    /**
-     * Get the child items for a chapter
-     * @param Chapter $chapter
-     */
-    public function getChildren(Chapter $chapter)
-    {
-        $pages = $this->permissionService->enforcePageRestrictions($chapter->pages())->get();
-        // Sort items with drafts first then by priority.
-        return $pages->sortBy(function ($child, $key) {
-            $score = $child->priority;
-            if ($child->draft) $score -= 100;
-            return $score;
-        });
-    }
-
-    /**
-     * Create a new chapter from request input.
-     * @param $input
-     * @param Book $book
-     * @return Chapter
-     */
-    public function createFromInput($input, Book $book)
-    {
-        $chapter = $this->chapter->newInstance($input);
-        $chapter->slug = $this->findSuitableSlug('chapter', $chapter->name, false, $book->id);
-        $chapter->created_by = user()->id;
-        $chapter->updated_by = user()->id;
-        $chapter = $book->chapters()->save($chapter);
-        $this->permissionService->buildJointPermissionsForEntity($chapter);
-        return $chapter;
-    }
-
-    /**
-     * Destroy a chapter and its relations by providing its slug.
-     * @param Chapter $chapter
-     */
-    public function destroy(Chapter $chapter)
-    {
-        if (count($chapter->pages) > 0) {
-            foreach ($chapter->pages as $page) {
-                $page->chapter_id = 0;
-                $page->save();
-            }
-        }
-        Activity::removeEntity($chapter);
-        $chapter->views()->delete();
-        $chapter->permissions()->delete();
-        $this->permissionService->deleteJointPermissionsForEntity($chapter);
-        $chapter->delete();
-    }
-
-
-    /**
-     * Get a new priority value for a new page to be added
-     * to the given chapter.
-     * @param Chapter $chapter
-     * @return int
-     */
-    public function getNewPriority(Chapter $chapter)
-    {
-        $lastPage = $chapter->pages->last();
-        return $lastPage !== null ? $lastPage->priority + 1 : 0;
-    }
-
-    /**
-     * Changes the book relation of this chapter.
-     * @param $bookId
-     * @param Chapter $chapter
-     * @param bool $rebuildPermissions
-     * @return Chapter
-     */
-    public function changeBook($bookId, Chapter $chapter, $rebuildPermissions = false)
-    {
-        $chapter->book_id = $bookId;
-        // Update related activity
-        foreach ($chapter->activity as $activity) {
-            $activity->book_id = $bookId;
-            $activity->save();
-        }
-        $chapter->slug = $this->findSuitableSlug('chapter', $chapter->name, $chapter->id, $bookId);
-        $chapter->save();
-        // Update all child pages
-        foreach ($chapter->pages as $page) {
-            $this->pageRepo->changeBook($bookId, $page);
-        }
-
-        // Update permissions if applicable
-        if ($rebuildPermissions) {
-            $chapter->load('book');
-            $this->permissionService->buildJointPermissionsForEntity($chapter->book);
-        }
-
-        return $chapter;
-    }
-
-}
\ No newline at end of file
index dd3016c6c75262d27d504f5d0e06d78cbba68db1..95666a66a6ce36bdb5f69dfb30cb9099ac16b9d1 100644 (file)
@@ -5,8 +5,13 @@ use BookStack\Chapter;
 use BookStack\Entity;
 use BookStack\Exceptions\NotFoundException;
 use BookStack\Page;
+use BookStack\PageRevision;
+use BookStack\Services\AttachmentService;
 use BookStack\Services\PermissionService;
 use BookStack\Services\ViewService;
+use Carbon\Carbon;
+use DOMDocument;
+use DOMXPath;
 use Illuminate\Support\Collection;
 
 class EntityRepo
@@ -27,6 +32,11 @@ class EntityRepo
      */
     public $page;
 
+    /**
+     * @var PageRevision
+     */
+    protected $pageRevision;
+
     /**
      * Base entity instances keyed by type
      * @var []Entity
@@ -43,6 +53,11 @@ class EntityRepo
      */
     protected $viewService;
 
+    /**
+     * @var TagRepo
+     */
+    protected $tagRepo;
+
     /**
      * Acceptable operators to be used in a query
      * @var array
@@ -51,20 +66,32 @@ class EntityRepo
 
     /**
      * EntityService constructor.
+     * @param Book $book
+     * @param Chapter $chapter
+     * @param Page $page
+     * @param PageRevision $pageRevision
+     * @param ViewService $viewService
+     * @param PermissionService $permissionService
+     * @param TagRepo $tagRepo
      */
-    public function __construct()
+    public function __construct(
+        Book $book, Chapter $chapter, Page $page, PageRevision $pageRevision,
+        ViewService $viewService, PermissionService $permissionService, TagRepo $tagRepo
+    )
     {
-        // TODO - Redo this to come via injection
-        $this->book = app(Book::class);
-        $this->chapter = app(Chapter::class);
-        $this->page = app(Page::class);
+        $this->book = $book;
+        $this->chapter = $chapter;
+        $this->page = $page;
+        $this->pageRevision = $pageRevision;
         $this->entities = [
             'page' => $this->page,
             'chapter' => $this->chapter,
-            'book' => $this->book
+            'book' => $this->book,
+            'page_revision' => $this->pageRevision
         ];
-        $this->viewService = app(ViewService::class);
-        $this->permissionService = app(PermissionService::class);
+        $this->viewService = $viewService;
+        $this->permissionService = $permissionService;
+        $this->tagRepo = $tagRepo;
     }
 
     /**
@@ -139,6 +166,27 @@ class EntityRepo
         return $entity;
     }
 
+
+    /**
+     * Search through page revisions and retrieve the last page in the
+     * current book that has a slug equal to the one given.
+     * @param string $pageSlug
+     * @param string $bookSlug
+     * @return null|Page
+     */
+    public function getPageByOldSlug($pageSlug, $bookSlug)
+    {
+        $revision = $this->pageRevision->where('slug', '=', $pageSlug)
+            ->whereHas('page', function ($query) {
+                $this->permissionService->enforceEntityRestrictions('page', $query);
+            })
+            ->where('type', '=', 'version')
+            ->where('book_slug', '=', $bookSlug)
+            ->orderBy('created_at', 'desc')
+            ->with('page')->first();
+        return $revision !== null ? $revision->page : null;
+    }
+
     /**
      * Get all entities of a type limited by count unless count if false.
      * @param string $type
@@ -212,6 +260,28 @@ class EntityRepo
         return $this->viewService->getUserRecentlyViewed($count, $page, $filter);
     }
 
+    /**
+     * Get the latest pages added to the system with pagination.
+     * @param string $type
+     * @param int $count
+     * @return mixed
+     */
+    public function getRecentlyCreatedPaginated($type, $count = 20)
+    {
+        return $this->entityQuery($type)->orderBy('created_at', 'desc')->paginate($count);
+    }
+
+    /**
+     * Get the latest pages added to the system with pagination.
+     * @param string $type
+     * @param int $count
+     * @return mixed
+     */
+    public function getRecentlyUpdatedPaginated($type, $count = 20)
+    {
+        return $this->entityQuery($type)->orderBy('updated_at', 'desc')->paginate($count);
+    }
+
     /**
      * Get the most popular entities base on all views.
      * @param string|bool $type
@@ -238,10 +308,68 @@ class EntityRepo
             ->skip($count * $page)->take($count)->get();
     }
 
+    /**
+     * Get all child objects of a book.
+     * Returns a sorted collection of Pages and Chapters.
+     * Loads the book slug onto child elements to prevent access database access for getting the slug.
+     * @param Book $book
+     * @param bool $filterDrafts
+     * @return mixed
+     */
+    public function getBookChildren(Book $book, $filterDrafts = false)
+    {
+        $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts);
+        $entities = [];
+        $parents = [];
+        $tree = [];
+
+        foreach ($q as $index => $rawEntity) {
+            if ($rawEntity->entity_type === 'Bookstack\\Page') {
+                $entities[$index] = $this->page->newFromBuilder($rawEntity);
+            } else if ($rawEntity->entity_type === 'Bookstack\\Chapter') {
+                $entities[$index] = $this->chapter->newFromBuilder($rawEntity);
+                $key = $entities[$index]->entity_type . ':' . $entities[$index]->id;
+                $parents[$key] = $entities[$index];
+                $parents[$key]->setAttribute('pages', collect());
+            }
+            if ($entities[$index]->chapter_id === 0) $tree[] = $entities[$index];
+            $entities[$index]->book = $book;
+        }
+
+        foreach ($entities as $entity) {
+            if ($entity->chapter_id === 0) continue;
+            $parentKey = 'Bookstack\\Chapter:' . $entity->chapter_id;
+            $chapter = $parents[$parentKey];
+            $chapter->pages->push($entity);
+        }
+
+        return collect($tree);
+    }
+
+    /**
+     * Get the child items for a chapter sorted by priority but
+     * with draft items floated to the top.
+     * @param Chapter $chapter
+     */
+    public function getChapterChildren(Chapter $chapter)
+    {
+        return $this->permissionService->enforceEntityRestrictions('page', $chapter->pages())
+            ->orderBy('draft', 'DESC')->orderBy('priority', 'ASC')->get();
+    }
+
+    /**
+     * Search entities of a type via a given query.
+     * @param string $type
+     * @param string $term
+     * @param array $whereTerms
+     * @param int $count
+     * @param array $paginationAppends
+     * @return mixed
+     */
     public function getBySearch($type, $term, $whereTerms = [], $count = 20, $paginationAppends = [])
     {
         $terms = $this->prepareSearchTerms($term);
-        $q = $this->permissionService->enforceChapterRestrictions($this->getEntity($type)->fullTextSearchQuery($terms, $whereTerms));
+        $q = $this->permissionService->enforceEntityRestrictions($type, $this->getEntity($type)->fullTextSearchQuery($terms, $whereTerms));
         $q = $this->addAdvancedSearchQueries($q, $term);
         $entities = $q->paginate($count)->appends($paginationAppends);
         $words = join('|', explode(' ', preg_quote(trim($term), '/')));
@@ -280,6 +408,28 @@ class EntityRepo
         return $entities;
     }
 
+    /**
+     * Get the next sequential priority for a new child element in the given book.
+     * @param Book $book
+     * @return int
+     */
+    public function getNewBookPriority(Book $book)
+    {
+        $lastElem = $this->getBookChildren($book)->pop();
+        return $lastElem ? $lastElem->priority + 1 : 0;
+    }
+
+    /**
+     * Get a new priority for a new page to be added to the given chapter.
+     * @param Chapter $chapter
+     * @return int
+     */
+    public function getNewChapterPriority(Chapter $chapter)
+    {
+        $lastPage = $chapter->pages('DESC')->first();
+        return $lastPage !== null ? $lastPage->priority + 1 : 0;
+    }
+
     /**
      * Find a suitable slug for an entity.
      * @param string $type
@@ -437,6 +587,81 @@ class EntityRepo
         return $query;
     }
 
+    /**
+     * Create a new entity from request input.
+     * Used for books and chapters.
+     * @param string $type
+     * @param array $input
+     * @param bool|Book $book
+     * @return Entity
+     */
+    public function createFromInput($type, $input = [], $book = false)
+    {
+        $isChapter = strtolower($type) === 'chapter';
+        $entity = $this->getEntity($type)->newInstance($input);
+        $entity->slug = $this->findSuitableSlug($type, $entity->name, false, $isChapter ? $book->id : false);
+        $entity->created_by = user()->id;
+        $entity->updated_by = user()->id;
+        $isChapter ? $book->chapters()->save($entity) : $entity->save();
+        $this->permissionService->buildJointPermissionsForEntity($entity);
+        return $entity;
+    }
+
+    /**
+     * Update entity details from request input.
+     * Use for books and chapters
+     * @param string $type
+     * @param Entity $entityModel
+     * @param array $input
+     * @return Entity
+     */
+    public function updateFromInput($type, Entity $entityModel, $input = [])
+    {
+        if ($entityModel->name !== $input['name']) {
+            $entityModel->slug = $this->findSuitableSlug($type, $input['name'], $entityModel->id);
+        }
+        $entityModel->fill($input);
+        $entityModel->updated_by = user()->id;
+        $entityModel->save();
+        $this->permissionService->buildJointPermissionsForEntity($entityModel);
+        return $entityModel;
+    }
+
+    /**
+     * Change the book that an entity belongs to.
+     * @param string $type
+     * @param integer $newBookId
+     * @param Entity $entity
+     * @param bool $rebuildPermissions
+     * @return Entity
+     */
+    public function changeBook($type, $newBookId, Entity $entity, $rebuildPermissions = false)
+    {
+        $entity->book_id = $newBookId;
+        // Update related activity
+        foreach ($entity->activity as $activity) {
+            $activity->book_id = $newBookId;
+            $activity->save();
+        }
+        $entity->slug = $this->findSuitableSlug($type, $entity->name, $entity->id, $newBookId);
+        $entity->save();
+
+        // Update all child pages if a chapter
+        if (strtolower($type) === 'chapter') {
+            foreach ($entity->pages as $page) {
+                $this->changeBook('page', $newBookId, $page, false);
+            }
+        }
+
+        // Update permissions if applicable
+        if ($rebuildPermissions) {
+            $entity->load('book');
+            $this->permissionService->buildJointPermissionsForEntity($entity->book);
+        }
+
+        return $entity;
+    }
+
     /**
      * Alias method to update the book jointPermissions in the PermissionService.
      * @param Collection $collection collection on entities
@@ -459,6 +684,463 @@ class EntityRepo
         return $slug;
     }
 
+    /**
+     * Publish a draft page to make it a normal page.
+     * Sets the slug and updates the content.
+     * @param Page $draftPage
+     * @param array $input
+     * @return Page
+     */
+    public function publishPageDraft(Page $draftPage, array $input)
+    {
+        $draftPage->fill($input);
+
+        // Save page tags if present
+        if (isset($input['tags'])) {
+            $this->tagRepo->saveTagsToEntity($draftPage, $input['tags']);
+        }
+
+        $draftPage->slug = $this->findSuitableSlug('page', $draftPage->name, false, $draftPage->book->id);
+        $draftPage->html = $this->formatHtml($input['html']);
+        $draftPage->text = strip_tags($draftPage->html);
+        $draftPage->draft = false;
+
+        $draftPage->save();
+        $this->savePageRevision($draftPage, trans('entities.pages_initial_revision'));
+
+        return $draftPage;
+    }
+
+    /**
+     * Saves a page revision into the system.
+     * @param Page $page
+     * @param null|string $summary
+     * @return PageRevision
+     */
+    public function savePageRevision(Page $page, $summary = null)
+    {
+        $revision = $this->pageRevision->newInstance($page->toArray());
+        if (setting('app-editor') !== 'markdown') $revision->markdown = '';
+        $revision->page_id = $page->id;
+        $revision->slug = $page->slug;
+        $revision->book_slug = $page->book->slug;
+        $revision->created_by = user()->id;
+        $revision->created_at = $page->updated_at;
+        $revision->type = 'version';
+        $revision->summary = $summary;
+        $revision->save();
+
+        // Clear old revisions
+        if ($this->pageRevision->where('page_id', '=', $page->id)->count() > 50) {
+            $this->pageRevision->where('page_id', '=', $page->id)
+                ->orderBy('created_at', 'desc')->skip(50)->take(5)->delete();
+        }
+
+        return $revision;
+    }
+
+    /**
+     * Formats a page's html to be tagged correctly
+     * within the system.
+     * @param string $htmlText
+     * @return string
+     */
+    protected function formatHtml($htmlText)
+    {
+        if ($htmlText == '') return $htmlText;
+        libxml_use_internal_errors(true);
+        $doc = new DOMDocument();
+        $doc->loadHTML(mb_convert_encoding($htmlText, 'HTML-ENTITIES', 'UTF-8'));
+
+        $container = $doc->documentElement;
+        $body = $container->childNodes->item(0);
+        $childNodes = $body->childNodes;
+
+        // Ensure no duplicate ids are used
+        $idArray = [];
+
+        foreach ($childNodes as $index => $childNode) {
+            /** @var \DOMElement $childNode */
+            if (get_class($childNode) !== 'DOMElement') continue;
+
+            // Overwrite id if not a BookStack custom id
+            if ($childNode->hasAttribute('id')) {
+                $id = $childNode->getAttribute('id');
+                if (strpos($id, 'bkmrk') === 0 && array_search($id, $idArray) === false) {
+                    $idArray[] = $id;
+                    continue;
+                };
+            }
+
+            // Create an unique id for the element
+            // Uses the content as a basis to ensure output is the same every time
+            // the same content is passed through.
+            $contentId = 'bkmrk-' . substr(strtolower(preg_replace('/\s+/', '-', trim($childNode->nodeValue))), 0, 20);
+            $newId = urlencode($contentId);
+            $loopIndex = 0;
+            while (in_array($newId, $idArray)) {
+                $newId = urlencode($contentId . '-' . $loopIndex);
+                $loopIndex++;
+            }
+
+            $childNode->setAttribute('id', $newId);
+            $idArray[] = $newId;
+        }
+
+        // Generate inner html as a string
+        $html = '';
+        foreach ($childNodes as $childNode) {
+            $html .= $doc->saveHTML($childNode);
+        }
+
+        return $html;
+    }
+
+    /**
+     * Get a new draft page instance.
+     * @param Book $book
+     * @param Chapter|bool $chapter
+     * @return Page
+     */
+    public function getDraftPage(Book $book, $chapter = false)
+    {
+        $page = $this->page->newInstance();
+        $page->name = trans('entities.pages_initial_name');
+        $page->created_by = user()->id;
+        $page->updated_by = user()->id;
+        $page->draft = true;
+
+        if ($chapter) $page->chapter_id = $chapter->id;
+
+        $book->pages()->save($page);
+        $this->permissionService->buildJointPermissionsForEntity($page);
+        return $page;
+    }
+
+    /**
+     * Search for image usage within page content.
+     * @param $imageString
+     * @return mixed
+     */
+    public function searchForImage($imageString)
+    {
+        $pages = $this->entityQuery('page')->where('html', 'like', '%' . $imageString . '%')->get();
+        foreach ($pages as $page) {
+            $page->url = $page->getUrl();
+            $page->html = '';
+            $page->text = '';
+        }
+        return count($pages) > 0 ? $pages : false;
+    }
+
+    /**
+     * Parse the headers on the page to get a navigation menu
+     * @param Page $page
+     * @return array
+     */
+    public function getPageNav(Page $page)
+    {
+        if ($page->html == '') return null;
+        libxml_use_internal_errors(true);
+        $doc = new DOMDocument();
+        $doc->loadHTML(mb_convert_encoding($page->html, 'HTML-ENTITIES', 'UTF-8'));
+        $xPath = new DOMXPath($doc);
+        $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6");
+
+        if (is_null($headers)) return null;
+
+        $tree = [];
+        foreach ($headers as $header) {
+            $text = $header->nodeValue;
+            $tree[] = [
+                'nodeName' => strtolower($header->nodeName),
+                'level' => intval(str_replace('h', '', $header->nodeName)),
+                'link' => '#' . $header->getAttribute('id'),
+                'text' => strlen($text) > 30 ? substr($text, 0, 27) . '...' : $text
+            ];
+        }
+        return $tree;
+    }
+
+    /**
+     * Updates a page with any fillable data and saves it into the database.
+     * @param Page $page
+     * @param int $book_id
+     * @param array $input
+     * @return Page
+     */
+    public function updatePage(Page $page, $book_id, $input)
+    {
+        // Hold the old details to compare later
+        $oldHtml = $page->html;
+        $oldName = $page->name;
+
+        // Prevent slug being updated if no name change
+        if ($page->name !== $input['name']) {
+            $page->slug = $this->findSuitableSlug('page', $input['name'], $page->id, $book_id);
+        }
+
+        // Save page tags if present
+        if (isset($input['tags'])) {
+            $this->tagRepo->saveTagsToEntity($page, $input['tags']);
+        }
+
+        // Update with new details
+        $userId = user()->id;
+        $page->fill($input);
+        $page->html = $this->formatHtml($input['html']);
+        $page->text = strip_tags($page->html);
+        if (setting('app-editor') !== 'markdown') $page->markdown = '';
+        $page->updated_by = $userId;
+        $page->save();
+
+        // Remove all update drafts for this user & page.
+        $this->userUpdatePageDraftsQuery($page, $userId)->delete();
+
+        // Save a revision after updating
+        if ($oldHtml !== $input['html'] || $oldName !== $input['name'] || $input['summary'] !== null) {
+            $this->savePageRevision($page, $input['summary']);
+        }
+
+        return $page;
+    }
+
+    /**
+     * The base query for getting user update drafts.
+     * @param Page $page
+     * @param $userId
+     * @return mixed
+     */
+    protected function userUpdatePageDraftsQuery(Page $page, $userId)
+    {
+        return $this->pageRevision->where('created_by', '=', $userId)
+            ->where('type', 'update_draft')
+            ->where('page_id', '=', $page->id)
+            ->orderBy('created_at', 'desc');
+    }
+
+    /**
+     * Checks whether a user has a draft version of a particular page or not.
+     * @param Page $page
+     * @param $userId
+     * @return bool
+     */
+    public function hasUserGotPageDraft(Page $page, $userId)
+    {
+        return $this->userUpdatePageDraftsQuery($page, $userId)->count() > 0;
+    }
+
+    /**
+     * Get the latest updated draft revision for a particular page and user.
+     * @param Page $page
+     * @param $userId
+     * @return mixed
+     */
+    public function getUserPageDraft(Page $page, $userId)
+    {
+        return $this->userUpdatePageDraftsQuery($page, $userId)->first();
+    }
+
+    /**
+     * Get the notification message that informs the user that they are editing a draft page.
+     * @param PageRevision $draft
+     * @return string
+     */
+    public function getUserPageDraftMessage(PageRevision $draft)
+    {
+        $message = trans('entities.pages_editing_draft_notification', ['timeDiff' => $draft->updated_at->diffForHumans()]);
+        if ($draft->page->updated_at->timestamp <= $draft->updated_at->timestamp) return $message;
+        return $message . "\n" . trans('entities.pages_draft_edited_notification');
+    }
+
+    /**
+     * Check if a page is being actively editing.
+     * Checks for edits since last page updated.
+     * Passing in a minuted range will check for edits
+     * within the last x minutes.
+     * @param Page $page
+     * @param null $minRange
+     * @return bool
+     */
+    public function isPageEditingActive(Page $page, $minRange = null)
+    {
+        $draftSearch = $this->activePageEditingQuery($page, $minRange);
+        return $draftSearch->count() > 0;
+    }
+
+    /**
+     * A query to check for active update drafts on a particular page.
+     * @param Page $page
+     * @param null $minRange
+     * @return mixed
+     */
+    protected function activePageEditingQuery(Page $page, $minRange = null)
+    {
+        $query = $this->pageRevision->where('type', '=', 'update_draft')
+            ->where('page_id', '=', $page->id)
+            ->where('updated_at', '>', $page->updated_at)
+            ->where('created_by', '!=', user()->id)
+            ->with('createdBy');
+
+        if ($minRange !== null) {
+            $query = $query->where('updated_at', '>=', Carbon::now()->subMinutes($minRange));
+        }
+
+        return $query;
+    }
+
+    /**
+     * Restores a revision's content back into a page.
+     * @param Page $page
+     * @param Book $book
+     * @param  int $revisionId
+     * @return Page
+     */
+    public function restorePageRevision(Page $page, Book $book, $revisionId)
+    {
+        $this->savePageRevision($page);
+        $revision = $this->getById('page_revision', $revisionId);
+        $page->fill($revision->toArray());
+        $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
+        $page->text = strip_tags($page->html);
+        $page->updated_by = user()->id;
+        $page->save();
+        return $page;
+    }
+
+
+    /**
+     * Save a page update draft.
+     * @param Page $page
+     * @param array $data
+     * @return PageRevision|Page
+     */
+    public function updatePageDraft(Page $page, $data = [])
+    {
+        // If the page itself is a draft simply update that
+        if ($page->draft) {
+            $page->fill($data);
+            if (isset($data['html'])) {
+                $page->text = strip_tags($data['html']);
+            }
+            $page->save();
+            return $page;
+        }
+
+        // Otherwise save the data to a revision
+        $userId = user()->id;
+        $drafts = $this->userUpdatePageDraftsQuery($page, $userId)->get();
+
+        if ($drafts->count() > 0) {
+            $draft = $drafts->first();
+        } else {
+            $draft = $this->pageRevision->newInstance();
+            $draft->page_id = $page->id;
+            $draft->slug = $page->slug;
+            $draft->book_slug = $page->book->slug;
+            $draft->created_by = $userId;
+            $draft->type = 'update_draft';
+        }
+
+        $draft->fill($data);
+        if (setting('app-editor') !== 'markdown') $draft->markdown = '';
+
+        $draft->save();
+        return $draft;
+    }
+
+    /**
+     * Get a notification message concerning the editing activity on a particular page.
+     * @param Page $page
+     * @param null $minRange
+     * @return string
+     */
+    public function getPageEditingActiveMessage(Page $page, $minRange = null)
+    {
+        $pageDraftEdits = $this->activePageEditingQuery($page, $minRange)->get();
+
+        $userMessage = $pageDraftEdits->count() > 1 ? trans('entities.pages_draft_edit_active.start_a', ['count' => $pageDraftEdits->count()]): trans('entities.pages_draft_edit_active.start_b', ['userName' => $pageDraftEdits->first()->createdBy->name]);
+        $timeMessage = $minRange === null ? trans('entities.pages_draft_edit_active.time_a') : trans('entities.pages_draft_edit_active.time_b', ['minCount'=>$minRange]);
+        return trans('entities.pages_draft_edit_active.message', ['start' => $userMessage, 'time' => $timeMessage]);
+    }
+
+    /**
+     * Change the page's parent to the given entity.
+     * @param Page $page
+     * @param Entity $parent
+     */
+    public function changePageParent(Page $page, Entity $parent)
+    {
+        $book = $parent->isA('book') ? $parent : $parent->book;
+        $page->chapter_id = $parent->isA('chapter') ? $parent->id : 0;
+        $page->save();
+        if ($page->book->id !== $book->id) {
+            $page = $this->changeBook('page', $book->id, $page);
+        }
+        $page->load('book');
+        $this->permissionService->buildJointPermissionsForEntity($book);
+    }
+
+    /**
+     * Destroy the provided book and all its child entities.
+     * @param Book $book
+     */
+    public function destroyBook(Book $book)
+    {
+        foreach ($book->pages as $page) {
+            $this->destroyPage($page);
+        }
+        foreach ($book->chapters as $chapter) {
+            $this->destroyChapter($chapter);
+        }
+        \Activity::removeEntity($book);
+        $book->views()->delete();
+        $book->permissions()->delete();
+        $this->permissionService->deleteJointPermissionsForEntity($book);
+        $book->delete();
+    }
+
+    /**
+     * Destroy a chapter and its relations.
+     * @param Chapter $chapter
+     */
+    public function destroyChapter(Chapter $chapter)
+    {
+        if (count($chapter->pages) > 0) {
+            foreach ($chapter->pages as $page) {
+                $page->chapter_id = 0;
+                $page->save();
+            }
+        }
+        \Activity::removeEntity($chapter);
+        $chapter->views()->delete();
+        $chapter->permissions()->delete();
+        $this->permissionService->deleteJointPermissionsForEntity($chapter);
+        $chapter->delete();
+    }
+
+    /**
+     * Destroy a given page along with its dependencies.
+     * @param Page $page
+     */
+    public function destroyPage(Page $page)
+    {
+        \Activity::removeEntity($page);
+        $page->views()->delete();
+        $page->tags()->delete();
+        $page->revisions()->delete();
+        $page->permissions()->delete();
+        $this->permissionService->deleteJointPermissionsForEntity($page);
+
+        // Delete Attached Files
+        $attachmentService = app(AttachmentService::class);
+        foreach ($page->attachments as $attachment) {
+            $attachmentService->deleteFile($attachment);
+        }
+
+        $page->delete();
+    }
+
 }
 
 
diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php
deleted file mode 100644 (file)
index 699e6ec..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-<?php namespace BookStack\Repos;
-
-use Activity;
-use BookStack\Book;
-use BookStack\Chapter;
-use BookStack\Entity;
-use BookStack\Exceptions\NotFoundException;
-use BookStack\Services\AttachmentService;
-use Carbon\Carbon;
-use DOMDocument;
-use DOMXPath;
-use Illuminate\Support\Str;
-use BookStack\Page;
-use BookStack\PageRevision;
-
-class PageRepo extends EntityRepo
-{
-
-    protected $pageRevision;
-    protected $tagRepo;
-
-    /**
-     * PageRepo constructor.
-     * @param PageRevision $pageRevision
-     * @param TagRepo $tagRepo
-     */
-    public function __construct(PageRevision $pageRevision, TagRepo $tagRepo)
-    {
-        $this->pageRevision = $pageRevision;
-        $this->tagRepo = $tagRepo;
-        parent::__construct();
-    }
-
-    /**
-     * Base query for getting pages, Takes restrictions into account.
-     * @param bool $allowDrafts
-     * @return mixed
-     */
-    private function pageQuery($allowDrafts = false)
-    {
-        $query = $this->permissionService->enforcePageRestrictions($this->page, 'view');
-        if (!$allowDrafts) {
-            $query = $query->where('draft', '=', false);
-        }
-        return $query;
-    }
-
-    /**
-     * Search through page revisions and retrieve
-     * the last page in the current book that
-     * has a slug equal to the one given.
-     * @param $pageSlug
-     * @param $bookSlug
-     * @return null | Page
-     */
-    public function findPageUsingOldSlug($pageSlug, $bookSlug)
-    {
-        $revision = $this->pageRevision->where('slug', '=', $pageSlug)
-            ->whereHas('page', function ($query) {
-                $this->permissionService->enforcePageRestrictions($query);
-            })
-            ->where('type', '=', 'version')
-            ->where('book_slug', '=', $bookSlug)->orderBy('created_at', 'desc')
-            ->with('page')->first();
-        return $revision !== null ? $revision->page : null;
-    }
-
-    /**
-     * Count the pages with a particular slug within a book.
-     * @param $slug
-     * @param $bookId
-     * @return mixed
-     */
-    public function countBySlug($slug, $bookId)
-    {
-        return $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->count();
-    }
-
-    /**
-     * Publish a draft page to make it a normal page.
-     * Sets the slug and updates the content.
-     * @param Page $draftPage
-     * @param array $input
-     * @return Page
-     */
-    public function publishDraft(Page $draftPage, array $input)
-    {
-        $draftPage->fill($input);
-
-        // Save page tags if present
-        if (isset($input['tags'])) {
-            $this->tagRepo->saveTagsToEntity($draftPage, $input['tags']);
-        }
-
-        $draftPage->slug = $this->findSuitableSlug('page', $draftPage->name, false, $draftPage->book->id);
-        $draftPage->html = $this->formatHtml($input['html']);
-        $draftPage->text = strip_tags($draftPage->html);
-        $draftPage->draft = false;
-
-        $draftPage->save();
-        $this->saveRevision($draftPage, trans('entities.pages_initial_revision'));
-        
-        return $draftPage;
-    }
-
-    /**
-     * Get a new draft page instance.
-     * @param Book $book
-     * @param Chapter|bool $chapter
-     * @return Page
-     */
-    public function getDraftPage(Book $book, $chapter = false)
-    {
-        $page = $this->page->newInstance();
-        $page->name = trans('entities.pages_initial_name');
-        $page->created_by = user()->id;
-        $page->updated_by = user()->id;
-        $page->draft = true;
-
-        if ($chapter) $page->chapter_id = $chapter->id;
-
-        $book->pages()->save($page);
-        $this->permissionService->buildJointPermissionsForEntity($page);
-        return $page;
-    }
-
-    /**
-     * Parse te headers on the page to get a navigation menu
-     * @param Page $page
-     * @return array
-     */
-    public function getPageNav(Page $page)
-    {
-        if ($page->html == '') return null;
-        libxml_use_internal_errors(true);
-        $doc = new DOMDocument();
-        $doc->loadHTML(mb_convert_encoding($page->html, 'HTML-ENTITIES', 'UTF-8'));
-        $xPath = new DOMXPath($doc);
-        $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6");
-
-        if (is_null($headers)) return null;
-
-        $tree = [];
-        foreach ($headers as $header) {
-            $text = $header->nodeValue;
-            $tree[] = [
-                'nodeName' => strtolower($header->nodeName),
-                'level' => intval(str_replace('h', '', $header->nodeName)),
-                'link' => '#' . $header->getAttribute('id'),
-                'text' => strlen($text) > 30 ? substr($text, 0, 27) . '...' : $text
-            ];
-        }
-        return $tree;
-    }
-
-    /**
-     * Formats a page's html to be tagged correctly
-     * within the system.
-     * @param string $htmlText
-     * @return string
-     */
-    protected function formatHtml($htmlText)
-    {
-        if ($htmlText == '') return $htmlText;
-        libxml_use_internal_errors(true);
-        $doc = new DOMDocument();
-        $doc->loadHTML(mb_convert_encoding($htmlText, 'HTML-ENTITIES', 'UTF-8'));
-
-        $container = $doc->documentElement;
-        $body = $container->childNodes->item(0);
-        $childNodes = $body->childNodes;
-
-        // Ensure no duplicate ids are used
-        $idArray = [];
-
-        foreach ($childNodes as $index => $childNode) {
-            /** @var \DOMElement $childNode */
-            if (get_class($childNode) !== 'DOMElement') continue;
-
-            // Overwrite id if not a BookStack custom id
-            if ($childNode->hasAttribute('id')) {
-                $id = $childNode->getAttribute('id');
-                if (strpos($id, 'bkmrk') === 0 && array_search($id, $idArray) === false) {
-                    $idArray[] = $id;
-                    continue;
-                };
-            }
-
-            // Create an unique id for the element
-            // Uses the content as a basis to ensure output is the same every time
-            // the same content is passed through.
-            $contentId = 'bkmrk-' . substr(strtolower(preg_replace('/\s+/', '-', trim($childNode->nodeValue))), 0, 20);
-            $newId = urlencode($contentId);
-            $loopIndex = 0;
-            while (in_array($newId, $idArray)) {
-                $newId = urlencode($contentId . '-' . $loopIndex);
-                $loopIndex++;
-            }
-
-            $childNode->setAttribute('id', $newId);
-            $idArray[] = $newId;
-        }
-
-        // Generate inner html as a string
-        $html = '';
-        foreach ($childNodes as $childNode) {
-            $html .= $doc->saveHTML($childNode);
-        }
-
-        return $html;
-    }
-
-
-    /**
-     * Search for image usage.
-     * @param $imageString
-     * @return mixed
-     */
-    public function searchForImage($imageString)
-    {
-        $pages = $this->pageQuery()->where('html', 'like', '%' . $imageString . '%')->get();
-        foreach ($pages as $page) {
-            $page->url = $page->getUrl();
-            $page->html = '';
-            $page->text = '';
-        }
-        return count($pages) > 0 ? $pages : false;
-    }
-
-    /**
-     * Updates a page with any fillable data and saves it into the database.
-     * @param Page $page
-     * @param int $book_id
-     * @param string $input
-     * @return Page
-     */
-    public function updatePage(Page $page, $book_id, $input)
-    {
-        // Hold the old details to compare later
-        $oldHtml = $page->html;
-        $oldName = $page->name;
-
-        // Prevent slug being updated if no name change
-        if ($page->name !== $input['name']) {
-            $page->slug = $this->findSuitableSlug('page', $input['name'], $page->id, $book_id);
-        }
-
-        // Save page tags if present
-        if (isset($input['tags'])) {
-            $this->tagRepo->saveTagsToEntity($page, $input['tags']);
-        }
-
-        // Update with new details
-        $userId = user()->id;
-        $page->fill($input);
-        $page->html = $this->formatHtml($input['html']);
-        $page->text = strip_tags($page->html);
-        if (setting('app-editor') !== 'markdown') $page->markdown = '';
-        $page->updated_by = $userId;
-        $page->save();
-
-        // Remove all update drafts for this user & page.
-        $this->userUpdateDraftsQuery($page, $userId)->delete();
-
-        // Save a revision after updating
-        if ($oldHtml !== $input['html'] || $oldName !== $input['name'] || $input['summary'] !== null) {
-            $this->saveRevision($page, $input['summary']);
-        }
-
-        return $page;
-    }
-
-    /**
-     * Restores a revision's content back into a page.
-     * @param Page $page
-     * @param Book $book
-     * @param  int $revisionId
-     * @return Page
-     */
-    public function restoreRevision(Page $page, Book $book, $revisionId)
-    {
-        $this->saveRevision($page);
-        $revision = $this->getRevisionById($revisionId);
-        $page->fill($revision->toArray());
-        $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
-        $page->text = strip_tags($page->html);
-        $page->updated_by = user()->id;
-        $page->save();
-        return $page;
-    }
-
-    /**
-     * Saves a page revision into the system.
-     * @param Page $page
-     * @param null|string $summary
-     * @return $this
-     */
-    public function saveRevision(Page $page, $summary = null)
-    {
-        $revision = $this->pageRevision->newInstance($page->toArray());
-        if (setting('app-editor') !== 'markdown') $revision->markdown = '';
-        $revision->page_id = $page->id;
-        $revision->slug = $page->slug;
-        $revision->book_slug = $page->book->slug;
-        $revision->created_by = user()->id;
-        $revision->created_at = $page->updated_at;
-        $revision->type = 'version';
-        $revision->summary = $summary;
-        $revision->save();
-
-        // Clear old revisions
-        if ($this->pageRevision->where('page_id', '=', $page->id)->count() > 50) {
-            $this->pageRevision->where('page_id', '=', $page->id)
-                ->orderBy('created_at', 'desc')->skip(50)->take(5)->delete();
-        }
-
-        return $revision;
-    }
-
-    /**
-     * Save a page update draft.
-     * @param Page $page
-     * @param array $data
-     * @return PageRevision
-     */
-    public function saveUpdateDraft(Page $page, $data = [])
-    {
-        $userId = user()->id;
-        $drafts = $this->userUpdateDraftsQuery($page, $userId)->get();
-
-        if ($drafts->count() > 0) {
-            $draft = $drafts->first();
-        } else {
-            $draft = $this->pageRevision->newInstance();
-            $draft->page_id = $page->id;
-            $draft->slug = $page->slug;
-            $draft->book_slug = $page->book->slug;
-            $draft->created_by = $userId;
-            $draft->type = 'update_draft';
-        }
-
-        $draft->fill($data);
-        if (setting('app-editor') !== 'markdown') $draft->markdown = '';
-
-        $draft->save();
-        return $draft;
-    }
-
-    /**
-     * Update a draft page.
-     * @param Page $page
-     * @param array $data
-     * @return Page
-     */
-    public function updateDraftPage(Page $page, $data = [])
-    {
-        $page->fill($data);
-
-        if (isset($data['html'])) {
-            $page->text = strip_tags($data['html']);
-        }
-
-        $page->save();
-        return $page;
-    }
-
-    /**
-     * The base query for getting user update drafts.
-     * @param Page $page
-     * @param $userId
-     * @return mixed
-     */
-    private function userUpdateDraftsQuery(Page $page, $userId)
-    {
-        return $this->pageRevision->where('created_by', '=', $userId)
-            ->where('type', 'update_draft')
-            ->where('page_id', '=', $page->id)
-            ->orderBy('created_at', 'desc');
-    }
-
-    /**
-     * Checks whether a user has a draft version of a particular page or not.
-     * @param Page $page
-     * @param $userId
-     * @return bool
-     */
-    public function hasUserGotPageDraft(Page $page, $userId)
-    {
-        return $this->userUpdateDraftsQuery($page, $userId)->count() > 0;
-    }
-
-    /**
-     * Get the latest updated draft revision for a particular page and user.
-     * @param Page $page
-     * @param $userId
-     * @return mixed
-     */
-    public function getUserPageDraft(Page $page, $userId)
-    {
-        return $this->userUpdateDraftsQuery($page, $userId)->first();
-    }
-
-    /**
-     * Get the notification message that informs the user that they are editing a draft page.
-     * @param PageRevision $draft
-     * @return string
-     */
-    public function getUserPageDraftMessage(PageRevision $draft)
-    {
-        $message = trans('entities.pages_editing_draft_notification', ['timeDiff' => $draft->updated_at->diffForHumans()]);
-        if ($draft->page->updated_at->timestamp <= $draft->updated_at->timestamp) return $message;
-        return $message . "\n" . trans('entities.pages_draft_edited_notification');
-    }
-
-    /**
-     * Check if a page is being actively editing.
-     * Checks for edits since last page updated.
-     * Passing in a minuted range will check for edits
-     * within the last x minutes.
-     * @param Page $page
-     * @param null $minRange
-     * @return bool
-     */
-    public function isPageEditingActive(Page $page, $minRange = null)
-    {
-        $draftSearch = $this->activePageEditingQuery($page, $minRange);
-        return $draftSearch->count() > 0;
-    }
-
-    /**
-     * Get a notification message concerning the editing activity on
-     * a particular page.
-     * @param Page $page
-     * @param null $minRange
-     * @return string
-     */
-    public function getPageEditingActiveMessage(Page $page, $minRange = null)
-    {
-        $pageDraftEdits = $this->activePageEditingQuery($page, $minRange)->get();
-
-        $userMessage = $pageDraftEdits->count() > 1 ? trans('entities.pages_draft_edit_active.start_a', ['count' => $pageDraftEdits->count()]): trans('entities.pages_draft_edit_active.start_b', ['userName' => $pageDraftEdits->first()->createdBy->name]);
-        $timeMessage = $minRange === null ? trans('entities.pages_draft_edit_active.time_a') : trans('entities.pages_draft_edit_active.time_b', ['minCount'=>$minRange]);
-        return trans('entities.pages_draft_edit_active.message', ['start' => $userMessage, 'time' => $timeMessage]);
-    }
-
-    /**
-     * A query to check for active update drafts on a particular page.
-     * @param Page $page
-     * @param null $minRange
-     * @return mixed
-     */
-    private function activePageEditingQuery(Page $page, $minRange = null)
-    {
-        $query = $this->pageRevision->where('type', '=', 'update_draft')
-            ->where('page_id', '=', $page->id)
-            ->where('updated_at', '>', $page->updated_at)
-            ->where('created_by', '!=', user()->id)
-            ->with('createdBy');
-
-        if ($minRange !== null) {
-            $query = $query->where('updated_at', '>=', Carbon::now()->subMinutes($minRange));
-        }
-
-        return $query;
-    }
-
-    /**
-     * Gets a single revision via it's id.
-     * @param $id
-     * @return PageRevision
-     */
-    public function getRevisionById($id)
-    {
-        return $this->pageRevision->findOrFail($id);
-    }
-
-    /**
-     * Changes the related book for the specified page.
-     * Changes the book id of any relations to the page that store the book id.
-     * @param int $bookId
-     * @param Page $page
-     * @return Page
-     */
-    public function changeBook($bookId, Page $page)
-    {
-        $page->book_id = $bookId;
-        foreach ($page->activity as $activity) {
-            $activity->book_id = $bookId;
-            $activity->save();
-        }
-        $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $bookId);
-        $page->save();
-        return $page;
-    }
-
-
-    /**
-     * Change the page's parent to the given entity.
-     * @param Page $page
-     * @param Entity $parent
-     */
-    public function changePageParent(Page $page, Entity $parent)
-    {
-        $book = $parent->isA('book') ? $parent : $parent->book;
-        $page->chapter_id = $parent->isA('chapter') ? $parent->id : 0;
-        $page->save();
-        $page = $this->changeBook($book->id, $page);
-        $page->load('book');
-        $this->permissionService->buildJointPermissionsForEntity($book);
-    }
-
-    /**
-     * Destroy a given page along with its dependencies.
-     * @param $page
-     */
-    public function destroy(Page $page)
-    {
-        Activity::removeEntity($page);
-        $page->views()->delete();
-        $page->tags()->delete();
-        $page->revisions()->delete();
-        $page->permissions()->delete();
-        $this->permissionService->deleteJointPermissionsForEntity($page);
-
-        // Delete AttachedFiles
-        $attachmentService = app(AttachmentService::class);
-        foreach ($page->attachments as $attachment) {
-            $attachmentService->deleteFile($attachment);
-        }
-
-        $page->delete();
-    }
-
-    /**
-     * Get the latest pages added to the system.
-     * @param $count
-     * @return mixed
-     */
-    public function getRecentlyCreatedPaginated($count = 20)
-    {
-        return $this->pageQuery()->orderBy('created_at', 'desc')->paginate($count);
-    }
-
-    /**
-     * Get the latest pages added to the system.
-     * @param $count
-     * @return mixed
-     */
-    public function getRecentlyUpdatedPaginated($count = 20)
-    {
-        return $this->pageQuery()->orderBy('updated_at', 'desc')->paginate($count);
-    }
-
-}
index 6e422c4f476ae1de9601357d6f4a496528514d1f..c6350db1ae8a80b8ede8b499227bcb962eb02d1c 100644 (file)
@@ -38,7 +38,7 @@ class TagRepo
     {
         $entityInstance = $this->entity->getEntityInstance($entityType);
         $searchQuery = $entityInstance->where('id', '=', $entityId)->with('tags');
-        $searchQuery = $this->permissionService->enforceEntityRestrictions($searchQuery, $action);
+        $searchQuery = $this->permissionService->enforceEntityRestrictions($entityType, $searchQuery, $action);
         return $searchQuery->first();
     }
 
index 0db2d1b5e94d7f16fd7973c765331bcf3c925fc7..467bf95da69f7f6dbe35361a2a595669cb977bc0 100644 (file)
@@ -516,42 +516,6 @@ ORDER BY draft desc, priority asc";
         return $this->db->select($query, array_replace($roleValues, $params));
     }
 
-    /**
-     * Add restrictions for a page query
-     * @param $query
-     * @param string $action
-     * @return mixed
-     */
-    public function enforcePageRestrictions($query, $action = 'view')
-    {
-        // TODO - remove this
-        return $this->enforceEntityRestrictions('page', $query, $action);
-    }
-
-    /**
-     * Add on permission restrictions to a chapter query.
-     * @param $query
-     * @param string $action
-     * @return mixed
-     */
-    public function enforceChapterRestrictions($query, $action = 'view')
-    {
-        // TODO - remove this
-        return $this->enforceEntityRestrictions('chapter', $query, $action);
-    }
-
-    /**
-     * Add restrictions to a book query.
-     * @param $query
-     * @param string $action
-     * @return mixed
-     */
-    public function enforceBookRestrictions($query, $action = 'view')
-    {
-        // TODO - remove this
-        return $this->enforceEntityRestrictions('book', $query, $action);
-    }
-
     /**
      * Add restrictions for a generic entity
      * @param string $entityType
index 79e574cbd48d444670ccbd1dda90f84e71e44ee6..9fd4eb9ad299bcee4528cbf97e9e581744fd14fe 100644 (file)
@@ -168,7 +168,7 @@ class EntityTest extends TestCase
         $entities = $this->createEntityChainBelongingToUser($creator, $updater);
         $this->actingAs($creator);
         app('BookStack\Repos\UserRepo')->destroy($creator);
-        app('BookStack\Repos\PageRepo')->saveRevision($entities['page']);
+        app('BookStack\Repos\EntityRepo')->savePageRevision($entities['page']);
 
         $this->checkEntitiesViewable($entities);
     }
@@ -181,7 +181,7 @@ class EntityTest extends TestCase
         $entities = $this->createEntityChainBelongingToUser($creator, $updater);
         $this->actingAs($updater);
         app('BookStack\Repos\UserRepo')->destroy($updater);
-        app('BookStack\Repos\PageRepo')->saveRevision($entities['page']);
+        app('BookStack\Repos\EntityRepo')->savePageRevision($entities['page']);
 
         $this->checkEntitiesViewable($entities);
     }
index 1a46e30bc6b03c2e26361b9563b33b6a16a1ba1f..233f300ee339a7fed34fb6eeb64c587c2006ee65 100644 (file)
@@ -4,13 +4,13 @@
 class PageDraftTest extends TestCase
 {
     protected $page;
-    protected $pageRepo;
+    protected $entityRepo;
 
     public function setUp()
     {
         parent::setUp();
         $this->page = \BookStack\Page::first();
-        $this->pageRepo = app('\BookStack\Repos\PageRepo');
+        $this->entityRepo = app('\BookStack\Repos\EntityRepo');
     }
 
     public function test_draft_content_shows_if_available()
@@ -20,7 +20,7 @@ class PageDraftTest extends TestCase
             ->dontSeeInField('html', $addedContent);
 
         $newContent = $this->page->html . $addedContent;
-        $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]);
+        $this->entityRepo->updatePageDraft($this->page, ['html' => $newContent]);
         $this->asAdmin()->visit($this->page->getUrl() . '/edit')
             ->seeInField('html', $newContent);
     }
@@ -33,7 +33,7 @@ class PageDraftTest extends TestCase
 
         $newContent = $this->page->html . $addedContent;
         $newUser = $this->getEditor();
-        $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]);
+        $this->entityRepo->updatePageDraft($this->page, ['html' => $newContent]);
         $this->actingAs($newUser)->visit($this->page->getUrl() . '/edit')
             ->dontSeeInField('html', $newContent);
     }
@@ -41,7 +41,7 @@ class PageDraftTest extends TestCase
     public function test_alert_message_shows_if_editing_draft()
     {
         $this->asAdmin();
-        $this->pageRepo->saveUpdateDraft($this->page, ['html' => 'test content']);
+        $this->entityRepo->updatePageDraft($this->page, ['html' => 'test content']);
         $this->asAdmin()->visit($this->page->getUrl() . '/edit')
             ->see('You are currently editing a draft');
     }
@@ -55,7 +55,7 @@ class PageDraftTest extends TestCase
 
         $newContent = $this->page->html . $addedContent;
         $newUser = $this->getEditor();
-        $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]);
+        $this->entityRepo->updatePageDraft($this->page, ['html' => $newContent]);
 
         $this->actingAs($newUser)
             ->visit($this->page->getUrl() . '/edit')
index d78b9447973751103fdf659b9149ea8693a1655e..4784297a2e804d7f0e2f74c91ddf60314670d4ae 100644 (file)
@@ -13,8 +13,8 @@ class SortTest extends TestCase
     public function test_drafts_do_not_show_up()
     {
         $this->asAdmin();
-        $pageRepo = app('\BookStack\Repos\PageRepo');
-        $draft = $pageRepo->getDraftPage($this->book);
+        $entityRepo = app('\BookStack\Repos\EntityRepo');
+        $draft = $entityRepo->getDraftPage($this->book);
 
         $this->visit($this->book->getUrl())
             ->see($draft->name)
index 031517cdb019d1d9380cf4161fc4dd44346d4399..9da12d36bb049531f88dbc2665ad951f3812db74 100644 (file)
@@ -90,7 +90,7 @@ class ImageTest extends TestCase
             'type' => 'gallery'
         ]);
 
-        $this->assertFalse(file_exists(public_path($relPath)), 'Uploaded image has been deleted');
+        $this->assertFalse(file_exists(public_path($relPath)), 'Uploaded image has not been deleted as expected');
     }
 
 }
\ No newline at end of file