diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php index 816db4cf0..2ec9a4c25 100644 --- a/app/Repos/BookRepo.php +++ b/app/Repos/BookRepo.php @@ -1,31 +1,25 @@ book = $book; $this->pageRepo = $pageRepo; $this->chapterRepo = $chapterRepo; - $this->restrictionService = $restrictionService; + parent::__construct(); } /** @@ -90,7 +84,6 @@ class BookRepo */ public function getRecentlyViewed($count = 10, $page = 0) { - // TODO restrict return Views::getUserRecentlyViewed($count, $page, $this->book); } @@ -102,7 +95,6 @@ class BookRepo */ public function getPopular($count = 10, $page = 0) { - // TODO - Restrict return Views::getPopular($count, $page, $this->book); } @@ -241,16 +233,7 @@ class BookRepo */ public function getBySearch($term, $count = 20, $paginationAppends = []) { - preg_match_all('/"(.*?)"/', $term, $matches); - if (count($matches[1]) > 0) { - $terms = $matches[1]; - $term = trim(preg_replace('/"(.*?)"/', '', $term)); - } else { - $terms = []; - } - if (!empty($term)) { - $terms = array_merge($terms, explode(' ', $term)); - } + $terms = $this->prepareSearchTerms($term); $books = $this->restrictionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms)) ->paginate($count)->appends($paginationAppends); $words = join('|', explode(' ', preg_quote(trim($term), '/'))); @@ -262,27 +245,4 @@ class BookRepo return $books; } - /** - * Updates books restrictions from a request - * @param $request - * @param $book - */ - public function updateRestrictionsFromRequest($request, $book) - { - // TODO - extract into shared repo - $book->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; - $book->restrictions()->delete(); - if ($request->has('restrictions')) { - foreach ($request->get('restrictions') as $roleId => $restrictions) { - foreach ($restrictions as $action => $value) { - $book->restrictions()->create([ - 'role_id' => $roleId, - 'action' => strtolower($action) - ]); - } - } - } - $book->save(); - } - } \ No newline at end of file diff --git a/app/Repos/BookRepo.php.orig b/app/Repos/BookRepo.php.orig deleted file mode 100644 index 4b9709fe6..000000000 --- a/app/Repos/BookRepo.php.orig +++ /dev/null @@ -1,295 +0,0 @@ -book = $book; - $this->pageRepo = $pageRepo; - $this->chapterRepo = $chapterRepo; - $this->restrictionService = $restrictionService; - } - - /** - * Base query for getting books. - * Takes into account any restrictions. - * @return mixed - */ - private function bookQuery() - { - return $this->restrictionService->enforceBookRestrictions($this->book, 'view'); - } - - /** - * Get the book that has the given id. - * @param $id - * @return mixed - */ - public function getById($id) - { - return $this->bookQuery()->findOrFail($id); - } - - /** - * Get all books, Limited by count. - * @param int $count - * @return mixed - */ - public function getAll($count = 10) - { - $bookQuery = $this->bookQuery()->orderBy('name', 'asc'); - if (!$count) return $bookQuery->get(); - return $bookQuery->take($count)->get(); - } - - /** - * Get all books paginated. - * @param int $count - * @return mixed - */ - public function getAllPaginated($count = 10) - { - return $this->bookQuery() - ->orderBy('name', 'asc')->paginate($count); - } - - - /** - * Get the latest books. - * @param int $count - * @return mixed - */ - public function getLatest($count = 10) - { - return $this->bookQuery()->orderBy('created_at', 'desc')->take($count)->get(); - } - - /** - * Gets the most recently viewed for a user. - * @param int $count - * @param int $page - * @return mixed - */ - public function getRecentlyViewed($count = 10, $page = 0) - { - // TODO restrict - return Views::getUserRecentlyViewed($count, $page, $this->book); - } - - /** - * Gets the most viewed books. - * @param int $count - * @param int $page - * @return mixed - */ - public function getPopular($count = 10, $page = 0) - { - // TODO - Restrict - return Views::getPopular($count, $page, $this->book); - } - - /** - * Get a book by slug - * @param $slug - * @return mixed - * @throws NotFoundException - */ - public function getBySlug($slug) - { - $book = $this->bookQuery()->where('slug', '=', $slug)->first(); - if ($book === null) throw new NotFoundException('Book not found'); - return $book; - } - - /** - * Checks if a book exists. - * @param $id - * @return bool - */ - public function exists($id) - { - return $this->bookQuery()->where('id', '=', $id)->exists(); - } - - /** - * Get a new book instance from request input. - * @param $input - * @return Book - */ - public function newFromInput($input) - { - return $this->book->newInstance($input); - } - - /** - * Destroy a book identified by the given slug. - * @param $bookSlug - */ - public function destroyBySlug($bookSlug) - { - $book = $this->getBySlug($bookSlug); - foreach ($book->pages as $page) { - $this->pageRepo->destroy($page); - } - foreach ($book->chapters as $chapter) { - $this->chapterRepo->destroy($chapter); - } - $book->views()->delete(); - $book->restrictions()->delete(); - $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; - } - - /** - * @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) - { - $originalSlug = Str::slug($name); - $slug = $originalSlug; - $count = 2; - while ($this->doesSlugExist($slug, $currentId)) { - $slug = $originalSlug . '-' . $count; - $count++; - } - return $slug; - } - - /** - * Get all child objects of a book. - * Returns a sorted collection of Pages and Chapters. - * Loads the bookslug onto child elements to prevent access database access for getting the slug. - * @param Book $book - * @return mixed - */ - public function getChildren(Book $book) - { - $pageQuery = $book->pages()->where('chapter_id', '=', 0); - $pageQuery = $this->restrictionService->enforcePageRestrictions($pageQuery, 'view'); - $pages = $pageQuery->get(); - - $chapterQuery = $book->chapters()->with(['pages' => function($query) { - $this->restrictionService->enforcePageRestrictions($query, 'view'); - }]); - $chapterQuery = $this->restrictionService->enforceChapterRestrictions($chapterQuery, 'view'); - $chapters = $chapterQuery->get(); - $children = $pages->merge($chapters); - $bookSlug = $book->slug; - $children->each(function ($child) use ($bookSlug) { - $child->setAttribute('bookSlug', $bookSlug); - if ($child->isA('chapter')) { - $child->pages->each(function ($page) use ($bookSlug) { - $page->setAttribute('bookSlug', $bookSlug); - }); - } - }); - return $children->sortBy('priority'); - } - - /** - * Get books by search term. - * @param $term - * @param int $count - * @param array $paginationAppends - * @return mixed - */ - public function getBySearch($term, $count = 20, $paginationAppends = []) - { -<<<<<<< HEAD - preg_match_all('/"(.*?)"/', $term, $matches); - if (count($matches[1]) > 0) { - $terms = $matches[1]; - $term = trim(preg_replace('/"(.*?)"/', '', $term)); - } else { - $terms = []; - } - if (!empty($term)) { - $terms = array_merge($terms, explode(' ', $term)); - } - $books = $this->book->fullTextSearchQuery(['name', 'description'], $terms) -======= - $terms = explode(' ', $term); - $books = $this->restrictionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms)) ->>>>>>> custom_role_system - ->paginate($count)->appends($paginationAppends); - $words = join('|', explode(' ', preg_quote(trim($term), '/'))); - foreach ($books as $book) { - //highlight - $result = preg_replace('#' . $words . '#iu', "\$0", $book->getExcerpt(100)); - $book->searchSnippet = $result; - } - return $books; - } - - /** - * Updates books restrictions from a request - * @param $request - * @param $book - */ - public function updateRestrictionsFromRequest($request, $book) - { - // TODO - extract into shared repo - $book->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; - $book->restrictions()->delete(); - if ($request->has('restrictions')) { - foreach ($request->get('restrictions') as $roleId => $restrictions) { - foreach ($restrictions as $action => $value) { - $book->restrictions()->create([ - 'role_id' => $roleId, - 'action' => strtolower($action) - ]); - } - } - } - $book->save(); - } - -} \ No newline at end of file diff --git a/app/Repos/ChapterRepo.php b/app/Repos/ChapterRepo.php index 6868bbf89..5d1d6437f 100644 --- a/app/Repos/ChapterRepo.php +++ b/app/Repos/ChapterRepo.php @@ -3,27 +3,11 @@ use Activity; use BookStack\Exceptions\NotFoundException; -use BookStack\Services\RestrictionService; use Illuminate\Support\Str; use BookStack\Chapter; -class ChapterRepo +class ChapterRepo extends EntityRepo { - - protected $chapter; - protected $restrictionService; - - /** - * ChapterRepo constructor. - * @param Chapter $chapter - * @param RestrictionService $restrictionService - */ - public function __construct(Chapter $chapter, RestrictionService $restrictionService) - { - $this->chapter = $chapter; - $this->restrictionService = $restrictionService; - } - /** * Base query for getting chapters, Takes restrictions into account. * @return mixed @@ -148,7 +132,7 @@ class ChapterRepo /** * Get chapters by the given search term. - * @param $term + * @param string $term * @param array $whereTerms * @param int $count * @param array $paginationAppends @@ -156,16 +140,7 @@ class ChapterRepo */ public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = []) { - preg_match_all('/"(.*?)"/', $term, $matches); - if (count($matches[1]) > 0) { - $terms = $matches[1]; - $term = trim(preg_replace('/"(.*?)"/', '', $term)); - } else { - $terms = []; - } - if (!empty($term)) { - $terms = array_merge($terms, explode(' ', $term)); - } + $terms = $this->prepareSearchTerms($term); $chapters = $this->restrictionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms)) ->paginate($count)->appends($paginationAppends); $words = join('|', explode(' ', preg_quote(trim($term), '/'))); @@ -195,27 +170,4 @@ class ChapterRepo return $chapter; } - /** - * Updates pages restrictions from a request - * @param $request - * @param $chapter - */ - public function updateRestrictionsFromRequest($request, $chapter) - { - // TODO - extract into shared repo - $chapter->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; - $chapter->restrictions()->delete(); - if ($request->has('restrictions')) { - foreach($request->get('restrictions') as $roleId => $restrictions) { - foreach ($restrictions as $action => $value) { - $chapter->restrictions()->create([ - 'role_id' => $roleId, - 'action' => strtolower($action) - ]); - } - } - } - $chapter->save(); - } - } \ No newline at end of file diff --git a/app/Repos/ChapterRepo.php.orig b/app/Repos/ChapterRepo.php.orig deleted file mode 100644 index be4a4e6b5..000000000 --- a/app/Repos/ChapterRepo.php.orig +++ /dev/null @@ -1,226 +0,0 @@ -chapter = $chapter; - $this->restrictionService = $restrictionService; - } - - /** - * Base query for getting chapters, Takes restrictions into account. - * @return mixed - */ - private function chapterQuery() - { - return $this->restrictionService->enforceChapterRestrictions($this->chapter, 'view'); - } - - /** - * Check if an id exists. - * @param $id - * @return bool - */ - public function idExists($id) - { - return $this->chapterQuery()->where('id', '=', $id)->count() > 0; - } - - /** - * Get a chapter by a specific id. - * @param $id - * @return mixed - */ - public function getById($id) - { - return $this->chapterQuery()->findOrFail($id); - } - - /** - * Get all chapters. - * @return \Illuminate\Database\Eloquent\Collection|static[] - */ - public function getAll() - { - return $this->chapterQuery()->all(); - } - - /** - * Get a chapter that has the given slug within the given book. - * @param $slug - * @param $bookId - * @return mixed - * @throws NotFoundException - */ - public function getBySlug($slug, $bookId) - { - $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first(); - if ($chapter === null) throw new NotFoundException('Chapter not found'); - return $chapter; - } - - /** - * Get the child items for a chapter - * @param Chapter $chapter - */ - public function getChildren(Chapter $chapter) - { - return $this->restrictionService->enforcePageRestrictions($chapter->pages())->get(); - } - - /** - * Create a new chapter from request input. - * @param $input - * @return $this - */ - public function newFromInput($input) - { - return $this->chapter->fill($input); - } - - /** - * 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->restrictions()->delete(); - $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 = Str::slug($name); - while ($this->doesSlugExist($slug, $bookId, $currentId)) { - $slug .= '-' . substr(md5(rand(1, 500)), 0, 3); - } - return $slug; - } - - /** - * Get chapters by the given search term. - * @param $term - * @param array $whereTerms - * @param int $count - * @param array $paginationAppends - * @return mixed - */ - public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = []) - { -<<<<<<< HEAD - preg_match_all('/"(.*?)"/', $term, $matches); - if (count($matches[1]) > 0) { - $terms = $matches[1]; - $term = trim(preg_replace('/"(.*?)"/', '', $term)); - } else { - $terms = []; - } - if (!empty($term)) { - $terms = array_merge($terms, explode(' ', $term)); - } - $chapters = $this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms) -======= - $terms = explode(' ', $term); - $chapters = $this->restrictionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms)) ->>>>>>> custom_role_system - ->paginate($count)->appends($paginationAppends); - $words = join('|', explode(' ', preg_quote(trim($term), '/'))); - foreach ($chapters as $chapter) { - //highlight - $result = preg_replace('#' . $words . '#iu', "\$0", $chapter->getExcerpt(100)); - $chapter->searchSnippet = $result; - } - return $chapters; - } - - /** - * Changes the book relation of this chapter. - * @param $bookId - * @param Chapter $chapter - * @return Chapter - */ - public function changeBook($bookId, Chapter $chapter) - { - $chapter->book_id = $bookId; - foreach ($chapter->activity as $activity) { - $activity->book_id = $bookId; - $activity->save(); - } - $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id); - $chapter->save(); - return $chapter; - } - - /** - * Updates pages restrictions from a request - * @param $request - * @param $chapter - */ - public function updateRestrictionsFromRequest($request, $chapter) - { - // TODO - extract into shared repo - $chapter->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; - $chapter->restrictions()->delete(); - if ($request->has('restrictions')) { - foreach($request->get('restrictions') as $roleId => $restrictions) { - foreach ($restrictions as $action => $value) { - $chapter->restrictions()->create([ - 'role_id' => $roleId, - 'action' => strtolower($action) - ]); - } - } - } - $chapter->save(); - } - -} \ No newline at end of file diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index 46e1d98a5..9c5184e2f 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -1,32 +1,43 @@ book = $book; - $this->chapter = $chapter; - $this->page = $page; - $this->restrictionService = $restrictionService; + $this->book = app(Book::class); + $this->chapter = app(Chapter::class); + $this->page = app(Page::class); + $this->restrictionService = app(RestrictionService::class); } /** @@ -37,7 +48,7 @@ class EntityRepo public function getRecentlyCreatedBooks($count = 20, $page = 0) { return $this->restrictionService->enforceBookRestrictions($this->book) - ->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get(); + ->orderBy('created_at', 'desc')->skip($page * $count)->take($count)->get(); } /** @@ -49,7 +60,7 @@ class EntityRepo public function getRecentlyUpdatedBooks($count = 20, $page = 0) { return $this->restrictionService->enforceBookRestrictions($this->book) - ->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get(); + ->orderBy('updated_at', 'desc')->skip($page * $count)->take($count)->get(); } /** @@ -60,7 +71,7 @@ class EntityRepo public function getRecentlyCreatedPages($count = 20, $page = 0) { return $this->restrictionService->enforcePageRestrictions($this->page) - ->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get(); + ->orderBy('created_at', 'desc')->skip($page * $count)->take($count)->get(); } /** @@ -72,7 +83,49 @@ class EntityRepo public function getRecentlyUpdatedPages($count = 20, $page = 0) { return $this->restrictionService->enforcePageRestrictions($this->page) - ->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get(); + ->orderBy('updated_at', 'desc')->skip($page * $count)->take($count)->get(); + } + + /** + * Updates entity restrictions from a request + * @param $request + * @param Entity $entity + */ + public function updateRestrictionsFromRequest($request, Entity $entity) + { + $entity->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; + $entity->restrictions()->delete(); + if ($request->has('restrictions')) { + foreach ($request->get('restrictions') as $roleId => $restrictions) { + foreach ($restrictions as $action => $value) { + $entity->restrictions()->create([ + 'role_id' => $roleId, + 'action' => strtolower($action) + ]); + } + } + } + $entity->save(); + } + + /** + * Prepare a string of search terms by turning + * it into an array of terms. + * Keeps quoted terms together. + * @param $termString + * @return array + */ + protected function prepareSearchTerms($termString) + { + preg_match_all('/"(.*?)"/', $termString, $matches); + if (count($matches[1]) > 0) { + $terms = $matches[1]; + $termString = trim(preg_replace('/"(.*?)"/', '', $termString)); + } else { + $terms = []; + } + if (!empty($termString)) $terms = array_merge($terms, explode(' ', $termString)); + return $terms; } diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index 3d675183e..4784ad407 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -3,34 +3,23 @@ use Activity; use BookStack\Book; -use BookStack\Chapter; use BookStack\Exceptions\NotFoundException; -use BookStack\Services\RestrictionService; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use BookStack\Page; use BookStack\PageRevision; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -class PageRepo +class PageRepo extends EntityRepo { - protected $page; protected $pageRevision; - protected $restrictionService; /** * PageRepo constructor. - * @param Page $page * @param PageRevision $pageRevision - * @param RestrictionService $restrictionService */ - public function __construct(Page $page, PageRevision $pageRevision, RestrictionService $restrictionService) + public function __construct(PageRevision $pageRevision) { - $this->page = $page; $this->pageRevision = $pageRevision; - $this->restrictionService = $restrictionService; + parent::__construct(); } /** @@ -200,16 +189,7 @@ class PageRepo */ public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = []) { - preg_match_all('/"(.*?)"/', $term, $matches); - if (count($matches[1]) > 0) { - $terms = $matches[1]; - $term = trim(preg_replace('/"(.*?)"/', '', $term)); - } else { - $terms = []; - } - if (!empty($term)) { - $terms = array_merge($terms, explode(' ', $term)); - } + $terms = $this->prepareSearchTerms($term); $pages = $this->restrictionService->enforcePageRestrictions($this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms)) ->paginate($count)->appends($paginationAppends); @@ -416,27 +396,4 @@ class PageRepo return $this->pageQuery()->orderBy('updated_at', 'desc')->paginate($count); } - /** - * Updates pages restrictions from a request - * @param $request - * @param $page - */ - public function updateRestrictionsFromRequest($request, $page) - { - // TODO - extract into shared repo - $page->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; - $page->restrictions()->delete(); - if ($request->has('restrictions')) { - foreach($request->get('restrictions') as $roleId => $restrictions) { - foreach ($restrictions as $action => $value) { - $page->restrictions()->create([ - 'role_id' => $roleId, - 'action' => strtolower($action) - ]); - } - } - } - $page->save(); - } - } diff --git a/app/Repos/PageRepo.php.orig b/app/Repos/PageRepo.php.orig deleted file mode 100644 index c1e02b501..000000000 --- a/app/Repos/PageRepo.php.orig +++ /dev/null @@ -1,437 +0,0 @@ -page = $page; - $this->pageRevision = $pageRevision; - $this->restrictionService = $restrictionService; - } - - /** - * Base query for getting pages, Takes restrictions into account. - * @return mixed - */ - private function pageQuery() - { - return $this->restrictionService->enforcePageRestrictions($this->page, 'view'); - } - - /** - * Get a page via a specific ID. - * @param $id - * @return mixed - */ - public function getById($id) - { - return $this->pageQuery()->findOrFail($id); - } - - /** - * Get a page identified by the given slug. - * @param $slug - * @param $bookId - * @return mixed - * @throws NotFoundException - */ - public function getBySlug($slug, $bookId) - { - $page = $this->pageQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first(); - if ($page === null) throw new NotFoundException('Page not found'); - return $page; - } - - /** - * 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->restrictionService->enforcePageRestrictions($query); - }) - ->where('book_slug', '=', $bookSlug)->orderBy('created_at', 'desc') - ->with('page')->first(); - 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; - } - - - /** - * Save a new page into the system. - * Input validation must be done beforehand. - * @param array $input - * @param Book $book - * @param int $chapterId - * @return Page - */ - public function saveNew(array $input, Book $book, $chapterId = null) - { - $page = $this->newFromInput($input); - $page->slug = $this->findSuitableSlug($page->name, $book->id); - - if ($chapterId) $page->chapter_id = $chapterId; - - $page->html = $this->formatHtml($input['html']); - $page->text = strip_tags($page->html); - $page->created_by = auth()->user()->id; - $page->updated_by = auth()->user()->id; - - $book->pages()->save($page); - return $page; - } - - /** - * 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; - } - - - /** - * 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 = []) - { -<<<<<<< HEAD - preg_match_all('/"(.*?)"/', $term, $matches); - if (count($matches[1]) > 0) { - $terms = $matches[1]; - $term = trim(preg_replace('/"(.*?)"/', '', $term)); - } else { - $terms = []; - } - if (!empty($term)) { - $terms = array_merge($terms, explode(' ', $term)); - } - $pages = $this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms) -======= - $terms = explode(' ', $term); - $pages = $this->restrictionService->enforcePageRestrictions($this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms)) ->>>>>>> custom_role_system - ->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', "\$0", $result); - if (strlen($result) < 5) { - $result = $page->getExcerpt(80); - } - $page->searchSnippet = $result; - } - return $pages; - } - - /** - * 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) - { - // Save a revision before updating - if ($page->html !== $input['html'] || $page->name !== $input['name']) { - $this->saveRevision($page); - } - - // Prevent slug being updated if no name change - if ($page->name !== $input['name']) { - $page->slug = $this->findSuitableSlug($input['name'], $book_id, $page->id); - } - - // Update with new details - $page->fill($input); - $page->html = $this->formatHtml($input['html']); - $page->text = strip_tags($page->html); - $page->updated_by = auth()->user()->id; - $page->save(); - 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->name, $book->id, $page->id); - $page->text = strip_tags($page->html); - $page->updated_by = auth()->user()->id; - $page->save(); - return $page; - } - - /** - * Saves a page revision into the system. - * @param Page $page - * @return $this - */ - public function saveRevision(Page $page) - { - $revision = $this->pageRevision->fill($page->toArray()); - $revision->page_id = $page->id; - $revision->slug = $page->slug; - $revision->book_slug = $page->book->slug; - $revision->created_by = auth()->user()->id; - $revision->created_at = $page->updated_at; - $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; - } - - /** - * Gets a single revision via it's id. - * @param $id - * @return mixed - */ - public function getRevisionById($id) - { - 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. - * @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->name, $bookId, $page->id); - $page->save(); - return $page; - } - - /** - * Gets a suitable slug for the resource - * @param $name - * @param $bookId - * @param bool|false $currentId - * @return string - */ - public function findSuitableSlug($name, $bookId, $currentId = false) - { - $slug = Str::slug($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 - */ - public function destroy($page) - { - Activity::removeEntity($page); - $page->views()->delete(); - $page->revisions()->delete(); - $page->restrictions()->delete(); - $page->delete(); - } - - /** - * Get the latest pages added to the system. - * @param $count - */ - public function getRecentlyCreatedPaginated($count = 20) - { - return $this->pageQuery()->orderBy('created_at', 'desc')->paginate($count); - } - - /** - * Get the latest pages added to the system. - * @param $count - */ - public function getRecentlyUpdatedPaginated($count = 20) - { - return $this->pageQuery()->orderBy('updated_at', 'desc')->paginate($count); - } - - /** - * Updates pages restrictions from a request - * @param $request - * @param $page - */ - public function updateRestrictionsFromRequest($request, $page) - { - // TODO - extract into shared repo - $page->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; - $page->restrictions()->delete(); - if ($request->has('restrictions')) { - foreach($request->get('restrictions') as $roleId => $restrictions) { - foreach ($restrictions as $action => $value) { - $page->restrictions()->create([ - 'role_id' => $roleId, - 'action' => strtolower($action) - ]); - } - } - } - $page->save(); - } - -} diff --git a/app/Services/ActivityService.php b/app/Services/ActivityService.php index a57210b8d..118bd6d9c 100644 --- a/app/Services/ActivityService.php +++ b/app/Services/ActivityService.php @@ -1,6 +1,5 @@