]> BookStack Code Mirror - bookstack/blobdiff - app/Repos/EntityRepo.php
Adds overflow:auto to popup content to allow it to scroll in lower res.
[bookstack] / app / Repos / EntityRepo.php
index 9a572be547f1ea87eb626ef0d29c98269598f39d..24c680234241471caa275462832cd4f977178336 100644 (file)
@@ -4,6 +4,7 @@ use BookStack\Book;
 use BookStack\Chapter;
 use BookStack\Entity;
 use BookStack\Exceptions\NotFoundException;
+use BookStack\Exceptions\NotifyException;
 use BookStack\Page;
 use BookStack\PageRevision;
 use BookStack\Services\AttachmentService;
@@ -137,10 +138,15 @@ class EntityRepo
      * @param string $type
      * @param integer $id
      * @param bool $allowDrafts
+     * @param bool $ignorePermissions
      * @return Entity
      */
-    public function getById($type, $id, $allowDrafts = false)
+    public function getById($type, $id, $allowDrafts = false, $ignorePermissions = false)
     {
+        if ($ignorePermissions) {
+            $entity = $this->getEntity($type);
+            return $entity->newQuery()->find($id);
+        }
         return $this->entityQuery($type, $allowDrafts)->find($id);
     }
 
@@ -436,9 +442,10 @@ class EntityRepo
      */
     public function updateEntityPermissionsFromRequest($request, Entity $entity)
     {
-        $entity->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
+        $entity->restricted = $request->get('restricted', '') === 'true';
         $entity->permissions()->delete();
-        if ($request->has('restrictions')) {
+
+        if ($request->filled('restrictions')) {
             foreach ($request->get('restrictions') as $roleId => $restrictions) {
                 foreach ($restrictions as $action => $value) {
                     $entity->permissions()->create([
@@ -448,6 +455,7 @@ class EntityRepo
                 }
             }
         }
+
         $entity->save();
         $this->permissionService->buildJointPermissionsForEntity($entity);
     }
@@ -533,11 +541,11 @@ class EntityRepo
 
     /**
      * Alias method to update the book jointPermissions in the PermissionService.
-     * @param Collection $collection collection on entities
+     * @param Book $book
      */
-    public function buildJointPermissions(Collection $collection)
+    public function buildJointPermissionsForBook(Book $book)
     {
-        $this->permissionService->buildJointPermissionsForEntities($collection);
+        $this->permissionService->buildJointPermissionsForEntity($book);
     }
 
     /**
@@ -547,8 +555,9 @@ class EntityRepo
      */
     protected function nameToSlug($name)
     {
-        $slug = str_replace(' ', '-', strtolower($name));
-        $slug = preg_replace('/[\+\/\\\?\@\}\{\.\,\=\[\]\#\&\!\*\'\;\:\$\%]/', '', $slug);
+        $slug = preg_replace('/[\+\/\\\?\@\}\{\.\,\=\[\]\#\&\!\*\'\;\:\$\%]/', '', mb_strtolower($name));
+        $slug = preg_replace('/\s{2,}/', ' ', $slug);
+        $slug = str_replace(' ', '-', $slug);
         if ($slug === "") $slug = substr(md5(rand(1, 500)), 0, 5);
         return $slug;
     }
@@ -571,7 +580,7 @@ class EntityRepo
 
         $draftPage->slug = $this->findSuitableSlug('page', $draftPage->name, false, $draftPage->book->id);
         $draftPage->html = $this->formatHtml($input['html']);
-        $draftPage->text = strip_tags($draftPage->html);
+        $draftPage->text = $this->pageToPlainText($draftPage);
         $draftPage->draft = false;
         $draftPage->revision_count = 1;
 
@@ -671,41 +680,48 @@ class EntityRepo
     /**
      * Render the page for viewing, Parsing and performing features such as page transclusion.
      * @param Page $page
+     * @param bool $ignorePermissions
      * @return mixed|string
      */
-    public function renderPage(Page $page)
+    public function renderPage(Page $page, $ignorePermissions = false)
     {
         $content = $page->html;
         $matches = [];
         preg_match_all("/{{@\s?([0-9].*?)}}/", $content, $matches);
         if (count($matches[0]) === 0) return $content;
 
+        $topLevelTags = ['table', 'ul', 'ol'];
         foreach ($matches[1] as $index => $includeId) {
             $splitInclude = explode('#', $includeId, 2);
             $pageId = intval($splitInclude[0]);
             if (is_nan($pageId)) continue;
 
-            $page = $this->getById('page', $pageId);
-            if ($page === null) {
+            $matchedPage = $this->getById('page', $pageId, false, $ignorePermissions);
+            if ($matchedPage === null) {
                 $content = str_replace($matches[0][$index], '', $content);
                 continue;
             }
 
             if (count($splitInclude) === 1) {
-                $content = str_replace($matches[0][$index], $page->html, $content);
+                $content = str_replace($matches[0][$index], $matchedPage->html, $content);
                 continue;
             }
 
             $doc = new DOMDocument();
-            $doc->loadHTML(mb_convert_encoding('<body>'.$page->html.'</body>', 'HTML-ENTITIES', 'UTF-8'));
+            $doc->loadHTML(mb_convert_encoding('<body>'.$matchedPage->html.'</body>', 'HTML-ENTITIES', 'UTF-8'));
             $matchingElem = $doc->getElementById($splitInclude[1]);
             if ($matchingElem === null) {
                 $content = str_replace($matches[0][$index], '', $content);
                 continue;
             }
             $innerContent = '';
-            foreach ($matchingElem->childNodes as $childNode) {
-                $innerContent .= $doc->saveHTML($childNode);
+            $isTopLevel = in_array(strtolower($matchingElem->nodeName), $topLevelTags);
+            if ($isTopLevel) {
+                $innerContent .= $doc->saveHTML($matchingElem);
+            } else {
+                foreach ($matchingElem->childNodes as $childNode) {
+                    $innerContent .= $doc->saveHTML($childNode);
+                }
             }
             $content = str_replace($matches[0][$index], trim($innerContent), $content);
         }
@@ -713,6 +729,17 @@ class EntityRepo
         return $content;
     }
 
+    /**
+     * Get the plain text version of a page's content.
+     * @param Page $page
+     * @return string
+     */
+    public function pageToPlainText(Page $page)
+    {
+        $html = $this->renderPage($page);
+        return strip_tags($html);
+    }
+
     /**
      * Get a new draft page instance.
      * @param Book $book
@@ -730,6 +757,7 @@ class EntityRepo
         if ($chapter) $page->chapter_id = $chapter->id;
 
         $book->pages()->save($page);
+        $page = $this->page->find($page->id);
         $this->permissionService->buildJointPermissionsForEntity($page);
         return $page;
     }
@@ -815,7 +843,7 @@ class EntityRepo
         $userId = user()->id;
         $page->fill($input);
         $page->html = $this->formatHtml($input['html']);
-        $page->text = strip_tags($page->html);
+        $page->text = $this->pageToPlainText($page);
         if (setting('app-editor') !== 'markdown') $page->markdown = '';
         $page->updated_by = $userId;
         $page->revision_count++;
@@ -932,7 +960,7 @@ class EntityRepo
         $revision = $page->revisions()->where('id', '=', $revisionId)->first();
         $page->fill($revision->toArray());
         $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
-        $page->text = strip_tags($page->html);
+        $page->text = $this->pageToPlainText($page);
         $page->updated_by = user()->id;
         $page->save();
         $this->searchService->indexEntity($page);
@@ -952,7 +980,7 @@ class EntityRepo
         if ($page->draft) {
             $page->fill($data);
             if (isset($data['html'])) {
-                $page->text = strip_tags($data['html']);
+                $page->text = $this->pageToPlainText($page);
             }
             $page->save();
             return $page;
@@ -1055,6 +1083,7 @@ class EntityRepo
     /**
      * Destroy a given page along with its dependencies.
      * @param Page $page
+     * @throws NotifyException
      */
     public function destroyPage(Page $page)
     {
@@ -1066,6 +1095,12 @@ class EntityRepo
         $this->permissionService->deleteJointPermissionsForEntity($page);
         $this->searchService->deleteEntityTerms($page);
 
+        // Check if set as custom homepage
+        $customHome = setting('app-homepage', '0:');
+        if (intval($page->id) === intval(explode(':', $customHome)[0])) {
+            throw new NotifyException(trans('errors.page_custom_home_deletion'), $page->getUrl());
+        }
+
         // Delete Attached Files
         $attachmentService = app(AttachmentService::class);
         foreach ($page->attachments as $attachment) {