]> BookStack Code Mirror - bookstack/commitdiff
Refactored search and slug repo components
authorDan Brown <redacted>
Sun, 1 Jan 2017 16:57:47 +0000 (16:57 +0000)
committerDan Brown <redacted>
Sun, 1 Jan 2017 16:57:47 +0000 (16:57 +0000)
app/Entity.php
app/Http/Controllers/ChapterController.php
app/Http/Controllers/PageController.php
app/Http/Controllers/SearchController.php
app/Page.php
app/Repos/BookRepo.php
app/Repos/ChapterRepo.php
app/Repos/EntityRepo.php
app/Repos/PageRepo.php

index 186059f00e13848d88d5db6dd82b932366bbb7f3..e8deddf0a56f6f861e31ee83523ccac9c47c1bdc 100644 (file)
@@ -4,6 +4,8 @@
 class Entity extends Ownable
 {
 
+    protected $fieldsToSearch = ['name', 'description'];
+
     /**
      * Compares this entity to another given entity.
      * Matches by comparing class and id.
@@ -157,7 +159,7 @@ class Entity extends Ownable
      * @param string[] array $wheres
      * @return mixed
      */
-    public function fullTextSearchQuery($fieldsToSearch, $terms, $wheres = [])
+    public function fullTextSearchQuery($terms, $wheres = [])
     {
         $exactTerms = [];
         $fuzzyTerms = [];
@@ -181,16 +183,16 @@ class Entity extends Ownable
         // Perform fulltext search if relevant terms exist.
         if ($isFuzzy) {
             $termString = implode(' ', $fuzzyTerms);
-            $fields = implode(',', $fieldsToSearch);
+            $fields = implode(',', $this->fieldsToSearch);
             $search = $search->selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]);
             $search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]);
         }
 
         // Ensure at least one exact term matches if in search
         if (count($exactTerms) > 0) {
-            $search = $search->where(function ($query) use ($exactTerms, $fieldsToSearch) {
+            $search = $search->where(function ($query) use ($exactTerms) {
                 foreach ($exactTerms as $exactTerm) {
-                    foreach ($fieldsToSearch as $field) {
+                    foreach ($this->fieldsToSearch as $field) {
                         $query->orWhere($field, 'like', $exactTerm);
                     }
                 }
index e71ed4d98661064adb75a2f3a9a56986d71d3f14..d239b08cc01d88bea6b3f424f5ad646e9f020916 100644 (file)
@@ -118,7 +118,7 @@ class ChapterController extends Controller
         $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
         $this->checkOwnablePermission('chapter-update', $chapter);
         if ($chapter->name !== $request->get('name')) {
-            $chapter->slug = $this->chapterRepo->findSuitableSlug($request->get('name'), $chapter->book->id, $chapter->id);
+            $chapter->slug = $this->entityRepo->findSuitableSlug('chapter', $request->get('name'), $chapter->id, $chapter->book->id);
         }
         $chapter->fill($request->all());
         $chapter->updated_by = user()->id;
index 0d6678e048d422e47acafcbabf7b52bd3e0d4c0c..5a33ecb37d2c5465cafad62625649c5bff14b307 100644 (file)
@@ -26,6 +26,7 @@ class PageController extends Controller
 
     /**
      * PageController constructor.
+     * @param EntityRepo $entityRepo
      * @param PageRepo $pageRepo
      * @param BookRepo $bookRepo
      * @param ChapterRepo $chapterRepo
index bb70b0f88cbc9e6ad07141cd49c51127af70c080..37aaccece64bbc5514c8ac8d55487ed16187ed2b 100644 (file)
@@ -1,30 +1,22 @@
 <?php namespace BookStack\Http\Controllers;
 
+use BookStack\Repos\EntityRepo;
 use BookStack\Services\ViewService;
 use Illuminate\Http\Request;
-use BookStack\Repos\BookRepo;
-use BookStack\Repos\ChapterRepo;
-use BookStack\Repos\PageRepo;
 
 class SearchController extends Controller
 {
-    protected $pageRepo;
-    protected $bookRepo;
-    protected $chapterRepo;
+    protected $entityRepo;
     protected $viewService;
 
     /**
      * SearchController constructor.
-     * @param PageRepo $pageRepo
-     * @param BookRepo $bookRepo
-     * @param ChapterRepo $chapterRepo
+     * @param EntityRepo $entityRepo
      * @param ViewService $viewService
      */
-    public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ViewService $viewService)
+    public function __construct(EntityRepo $entityRepo, ViewService $viewService)
     {
-        $this->pageRepo = $pageRepo;
-        $this->bookRepo = $bookRepo;
-        $this->chapterRepo = $chapterRepo;
+        $this->entityRepo = $entityRepo;
         $this->viewService = $viewService;
         parent::__construct();
     }
@@ -42,9 +34,9 @@ class SearchController extends Controller
         }
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
-        $pages = $this->pageRepo->getBySearch($searchTerm, [], 20, $paginationAppends);
-        $books = $this->bookRepo->getBySearch($searchTerm, 10, $paginationAppends);
-        $chapters = $this->chapterRepo->getBySearch($searchTerm, [], 10, $paginationAppends);
+        $pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
+        $books = $this->entityRepo->getBySearch('book', $searchTerm, [], 10, $paginationAppends);
+        $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 10, $paginationAppends);
         $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm]));
         return view('search/all', [
             'pages'      => $pages,
@@ -65,7 +57,7 @@ class SearchController extends Controller
 
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
-        $pages = $this->pageRepo->getBySearch($searchTerm, [], 20, $paginationAppends);
+        $pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
         $this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm]));
         return view('search/entity-search-list', [
             'entities'   => $pages,
@@ -85,7 +77,7 @@ class SearchController extends Controller
 
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
-        $chapters = $this->chapterRepo->getBySearch($searchTerm, [], 20, $paginationAppends);
+        $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 20, $paginationAppends);
         $this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm]));
         return view('search/entity-search-list', [
             'entities'   => $chapters,
@@ -105,7 +97,7 @@ class SearchController extends Controller
 
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
-        $books = $this->bookRepo->getBySearch($searchTerm, 20, $paginationAppends);
+        $books = $this->entityRepo->getBySearch('book', $searchTerm, [], 20, $paginationAppends);
         $this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm]));
         return view('search/entity-search-list', [
             'entities'   => $books,
@@ -128,8 +120,8 @@ class SearchController extends Controller
         }
         $searchTerm = $request->get('term');
         $searchWhereTerms = [['book_id', '=', $bookId]];
-        $pages = $this->pageRepo->getBySearch($searchTerm, $searchWhereTerms);
-        $chapters = $this->chapterRepo->getBySearch($searchTerm, $searchWhereTerms);
+        $pages = $this->entityRepo->getBySearch('page', $searchTerm, $searchWhereTerms);
+        $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, $searchWhereTerms);
         return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]);
     }
 
@@ -148,9 +140,11 @@ class SearchController extends Controller
 
         // Search for entities otherwise show most popular
         if ($searchTerm !== false) {
-            if ($entityTypes->contains('page')) $entities = $entities->merge($this->pageRepo->getBySearch($searchTerm)->items());
-            if ($entityTypes->contains('chapter')) $entities = $entities->merge($this->chapterRepo->getBySearch($searchTerm)->items());
-            if ($entityTypes->contains('book')) $entities = $entities->merge($this->bookRepo->getBySearch($searchTerm)->items());
+            foreach (['page', 'chapter', 'book'] as $entityType) {
+                if ($entityTypes->contains($entityType)) {
+                    $entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items());
+                }
+            }
             $entities = $entities->sortByDesc('title_relevance');
         } else {
             $entityNames = $entityTypes->map(function ($type) {
index 38f95a3b1d8d703c110932ba147936bbdc1e8c33..b24e7778aead87706b0b736d8ddaa625be5812ec 100644 (file)
@@ -9,6 +9,8 @@ class Page extends Entity
 
     protected $with = ['book'];
 
+    protected $fieldsToSearch = ['name', 'text'];
+
     /**
      * Converts this page into a simplified array.
      * @return mixed
index ebfda3fa44dd0829455c34d66ab31cb60e2434f6..3043d2916576398028f20e6dff1ce3519e534acd 100644 (file)
@@ -27,7 +27,7 @@ class BookRepo extends EntityRepo
     public function createFromInput($input)
     {
         $book = $this->book->newInstance($input);
-        $book->slug = $this->findSuitableSlug($book->name);
+        $book->slug = $this->findSuitableSlug('book', $book->name);
         $book->created_by = user()->id;
         $book->updated_by = user()->id;
         $book->save();
@@ -44,7 +44,7 @@ class BookRepo extends EntityRepo
     public function updateFromInput(Book $book, $input)
     {
         if ($book->name !== $input['name']) {
-            $book->slug = $this->findSuitableSlug($input['name'], $book->id);
+            $book->slug = $this->findSuitableSlug('book', $input['name'], $book->id);
         }
         $book->fill($input);
         $book->updated_by = user()->id;
@@ -83,36 +83,6 @@ class BookRepo extends EntityRepo
         return $lastElem ? $lastElem->priority + 1 : 0;
     }
 
-    /**
-     * @param string $slug
-     * @param bool|false $currentId
-     * @return bool
-     */
-    public function doesSlugExist($slug, $currentId = false)
-    {
-        $query = $this->book->where('slug', '=', $slug);
-        if ($currentId) {
-            $query = $query->where('id', '!=', $currentId);
-        }
-        return $query->count() > 0;
-    }
-
-    /**
-     * Provides a suitable slug for the given book name.
-     * Ensures the returned slug is unique in the system.
-     * @param string $name
-     * @param bool|false $currentId
-     * @return string
-     */
-    public function findSuitableSlug($name, $currentId = false)
-    {
-        $slug = $this->nameToSlug($name);
-        while ($this->doesSlugExist($slug, $currentId)) {
-            $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
-        }
-        return $slug;
-    }
-
     /**
      * Get all child objects of a book.
      * Returns a sorted collection of Pages and Chapters.
@@ -166,26 +136,4 @@ class BookRepo extends EntityRepo
         });
     }
 
-    /**
-     * Get books by search term.
-     * @param $term
-     * @param int $count
-     * @param array $paginationAppends
-     * @return mixed
-     */
-    public function getBySearch($term, $count = 20, $paginationAppends = [])
-    {
-        $terms = $this->prepareSearchTerms($term);
-        $bookQuery = $this->permissionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms));
-        $bookQuery = $this->addAdvancedSearchQueries($bookQuery, $term);
-        $books = $bookQuery->paginate($count)->appends($paginationAppends);
-        $words = join('|', explode(' ', preg_quote(trim($term), '/')));
-        foreach ($books as $book) {
-            //highlight
-            $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $book->getExcerpt(100));
-            $book->searchSnippet = $result;
-        }
-        return $books;
-    }
-
 }
\ No newline at end of file
index 861bb72fcc6f6b50731177ebd2de09a326f6661a..afbf312da9327cfdf3c8aa4f2daf400f02731877 100644 (file)
@@ -45,7 +45,7 @@ class ChapterRepo extends EntityRepo
     public function createFromInput($input, Book $book)
     {
         $chapter = $this->chapter->newInstance($input);
-        $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id);
+        $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);
@@ -72,38 +72,6 @@ class ChapterRepo extends EntityRepo
         $chapter->delete();
     }
 
-    /**
-     * Check if a chapter's slug exists.
-     * @param            $slug
-     * @param            $bookId
-     * @param bool|false $currentId
-     * @return bool
-     */
-    public function doesSlugExist($slug, $bookId, $currentId = false)
-    {
-        $query = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId);
-        if ($currentId) {
-            $query = $query->where('id', '!=', $currentId);
-        }
-        return $query->count() > 0;
-    }
-
-    /**
-     * Finds a suitable slug for the provided name.
-     * Checks database to prevent duplicate slugs.
-     * @param            $name
-     * @param            $bookId
-     * @param bool|false $currentId
-     * @return string
-     */
-    public function findSuitableSlug($name, $bookId, $currentId = false)
-    {
-        $slug = $this->nameToSlug($name);
-        while ($this->doesSlugExist($slug, $bookId, $currentId)) {
-            $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
-        }
-        return $slug;
-    }
 
     /**
      * Get a new priority value for a new page to be added
@@ -117,29 +85,6 @@ class ChapterRepo extends EntityRepo
         return $lastPage !== null ? $lastPage->priority + 1 : 0;
     }
 
-    /**
-     * Get chapters by the given search term.
-     * @param string $term
-     * @param array $whereTerms
-     * @param int $count
-     * @param array $paginationAppends
-     * @return mixed
-     */
-    public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
-    {
-        $terms = $this->prepareSearchTerms($term);
-        $chapterQuery = $this->permissionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms));
-        $chapterQuery = $this->addAdvancedSearchQueries($chapterQuery, $term);
-        $chapters = $chapterQuery->paginate($count)->appends($paginationAppends);
-        $words = join('|', explode(' ', preg_quote(trim($term), '/')));
-        foreach ($chapters as $chapter) {
-            //highlight
-            $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $chapter->getExcerpt(100));
-            $chapter->searchSnippet = $result;
-        }
-        return $chapters;
-    }
-
     /**
      * Changes the book relation of this chapter.
      * @param $bookId
@@ -155,7 +100,7 @@ class ChapterRepo extends EntityRepo
             $activity->book_id = $bookId;
             $activity->save();
         }
-        $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id);
+        $chapter->slug = $this->findSuitableSlug('chapter', $chapter->name, $chapter->id, $bookId);
         $chapter->save();
         // Update all child pages
         foreach ($chapter->pages as $page) {
index 19beebc77f829d85b2ea6f723f413e65298b50ea..40fdea54ee9be1bf636a4a728a517ec44cc1cf4d 100644 (file)
@@ -238,6 +238,83 @@ class EntityRepo
             ->skip($count * $page)->take($count)->get();
     }
 
+    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->addAdvancedSearchQueries($q, $term);
+        $entities = $q->paginate($count)->appends($paginationAppends);
+        $words = join('|', explode(' ', preg_quote(trim($term), '/')));
+
+        // Highlight page content
+        if ($type === 'page') {
+            //lookahead/behind assertions ensures cut between words
+            $s = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
+
+            foreach ($entities as $page) {
+                preg_match_all('#(?<=[' . $s . ']).{1,30}((' . $words . ').{1,30})+(?=[' . $s . '])#uis', $page->text, $matches, PREG_SET_ORDER);
+                //delimiter between occurrences
+                $results = [];
+                foreach ($matches as $line) {
+                    $results[] = htmlspecialchars($line[0], 0, 'UTF-8');
+                }
+                $matchLimit = 6;
+                if (count($results) > $matchLimit) $results = array_slice($results, 0, $matchLimit);
+                $result = join('... ', $results);
+
+                //highlight
+                $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $result);
+                if (strlen($result) < 5) $result = $page->getExcerpt(80);
+
+                $page->searchSnippet = $result;
+            }
+            return $entities;
+        }
+
+        // Highlight chapter/book content
+        foreach ($entities as $entity) {
+            //highlight
+            $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $entity->getExcerpt(100));
+            $entity->searchSnippet = $result;
+        }
+        return $entities;
+    }
+
+    /**
+     * Find a suitable slug for an entity.
+     * @param string $type
+     * @param string $name
+     * @param bool|integer $currentId
+     * @param bool|integer $bookId Only pass if type is not a book
+     * @return string
+     */
+    public function findSuitableSlug($type, $name, $currentId = false, $bookId = false)
+    {
+        $slug = $this->nameToSlug($name);
+        while ($this->slugExists($type, $slug, $currentId, $bookId)) {
+            $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
+        }
+        return $slug;
+    }
+
+    /**
+     * Check if a slug already exists in the database.
+     * @param string $type
+     * @param string $slug
+     * @param bool|integer $currentId
+     * @param bool|integer $bookId
+     * @return bool
+     */
+    protected function slugExists($type, $slug, $currentId = false, $bookId = false)
+    {
+        $query = $this->getEntity($type)->where('slug', '=', $slug);
+        if (strtolower($type) === 'page' || strtolower($type) === 'chapter') {
+            $query = $query->where('book_id', '=', $bookId);
+        }
+        if ($currentId) $query = $query->where('id', '!=', $currentId);
+        return $query->count() > 0;
+    }
+
     /**
      * Updates entity restrictions from a request
      * @param $request
index f16ea6b6d5ff69c67771ac93cd4c804f869c6b5a..699e6ecc564e50d3c59527f7557e0130891f2eb9 100644 (file)
@@ -65,17 +65,6 @@ class PageRepo extends EntityRepo
         return $revision !== null ? $revision->page : null;
     }
 
-    /**
-     * Get a new Page instance from the given input.
-     * @param $input
-     * @return Page
-     */
-    public function newFromInput($input)
-    {
-        $page = $this->page->fill($input);
-        return $page;
-    }
-
     /**
      * Count the pages with a particular slug within a book.
      * @param $slug
@@ -103,7 +92,7 @@ class PageRepo extends EntityRepo
             $this->tagRepo->saveTagsToEntity($draftPage, $input['tags']);
         }
 
-        $draftPage->slug = $this->findSuitableSlug($draftPage->name, $draftPage->book->id);
+        $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;
@@ -222,50 +211,6 @@ class PageRepo extends EntityRepo
     }
 
 
-    /**
-     * Gets pages by a search term.
-     * Highlights page content for showing in results.
-     * @param string $term
-     * @param array $whereTerms
-     * @param int $count
-     * @param array $paginationAppends
-     * @return mixed
-     */
-    public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
-    {
-        $terms = $this->prepareSearchTerms($term);
-        $pageQuery = $this->permissionService->enforcePageRestrictions($this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms));
-        $pageQuery = $this->addAdvancedSearchQueries($pageQuery, $term);
-        $pages = $pageQuery->paginate($count)->appends($paginationAppends);
-
-        // Add highlights to page text.
-        $words = join('|', explode(' ', preg_quote(trim($term), '/')));
-        //lookahead/behind assertions ensures cut between words
-        $s = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
-
-        foreach ($pages as $page) {
-            preg_match_all('#(?<=[' . $s . ']).{1,30}((' . $words . ').{1,30})+(?=[' . $s . '])#uis', $page->text, $matches, PREG_SET_ORDER);
-            //delimiter between occurrences
-            $results = [];
-            foreach ($matches as $line) {
-                $results[] = htmlspecialchars($line[0], 0, 'UTF-8');
-            }
-            $matchLimit = 6;
-            if (count($results) > $matchLimit) {
-                $results = array_slice($results, 0, $matchLimit);
-            }
-            $result = join('... ', $results);
-
-            //highlight
-            $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $result);
-            if (strlen($result) < 5) {
-                $result = $page->getExcerpt(80);
-            }
-            $page->searchSnippet = $result;
-        }
-        return $pages;
-    }
-
     /**
      * Search for image usage.
      * @param $imageString
@@ -297,7 +242,7 @@ class PageRepo extends EntityRepo
 
         // Prevent slug being updated if no name change
         if ($page->name !== $input['name']) {
-            $page->slug = $this->findSuitableSlug($input['name'], $book_id, $page->id);
+            $page->slug = $this->findSuitableSlug('page', $input['name'], $page->id, $book_id);
         }
 
         // Save page tags if present
@@ -337,7 +282,7 @@ class PageRepo extends EntityRepo
         $this->saveRevision($page);
         $revision = $this->getRevisionById($revisionId);
         $page->fill($revision->toArray());
-        $page->slug = $this->findSuitableSlug($page->name, $book->id, $page->id);
+        $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
         $page->text = strip_tags($page->html);
         $page->updated_by = user()->id;
         $page->save();
@@ -529,20 +474,6 @@ class PageRepo extends EntityRepo
         return $this->pageRevision->findOrFail($id);
     }
 
-    /**
-     * Checks if a slug exists within a book already.
-     * @param            $slug
-     * @param            $bookId
-     * @param bool|false $currentId
-     * @return bool
-     */
-    public function doesSlugExist($slug, $bookId, $currentId = false)
-    {
-        $query = $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId);
-        if ($currentId) $query = $query->where('id', '!=', $currentId);
-        return $query->count() > 0;
-    }
-
     /**
      * Changes the related book for the specified page.
      * Changes the book id of any relations to the page that store the book id.
@@ -557,7 +488,7 @@ class PageRepo extends EntityRepo
             $activity->book_id = $bookId;
             $activity->save();
         }
-        $page->slug = $this->findSuitableSlug($page->name, $bookId, $page->id);
+        $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $bookId);
         $page->save();
         return $page;
     }
@@ -578,22 +509,6 @@ class PageRepo extends EntityRepo
         $this->permissionService->buildJointPermissionsForEntity($book);
     }
 
-    /**
-     * Gets a suitable slug for the resource
-     * @param string $name
-     * @param int $bookId
-     * @param bool|false $currentId
-     * @return string
-     */
-    public function findSuitableSlug($name, $bookId, $currentId = false)
-    {
-        $slug = $this->nameToSlug($name);
-        while ($this->doesSlugExist($slug, $bookId, $currentId)) {
-            $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
-        }
-        return $slug;
-    }
-
     /**
      * Destroy a given page along with its dependencies.
      * @param $page