X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/e211f313704d3a0a00d8d358bd49eb310f9531c5..refs/pull/358/head:/app/Repos/EntityRepo.php diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index 83e79ac9b..8f4b533ff 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -86,8 +86,7 @@ class EntityRepo $this->entities = [ 'page' => $this->page, 'chapter' => $this->chapter, - 'book' => $this->book, - 'page_revision' => $this->pageRevision + 'book' => $this->book ]; $this->viewService = $viewService; $this->permissionService = $permissionService; @@ -139,7 +138,7 @@ class EntityRepo */ public function getById($type, $id, $allowDrafts = false) { - return $this->entityQuery($type, $allowDrafts)->findOrFail($id); + return $this->entityQuery($type, $allowDrafts)->find($id); } /** @@ -314,31 +313,36 @@ class EntityRepo * Loads the book slug onto child elements to prevent access database access for getting the slug. * @param Book $book * @param bool $filterDrafts + * @param bool $renderPages * @return mixed */ - public function getBookChildren(Book $book, $filterDrafts = false) + public function getBookChildren(Book $book, $filterDrafts = false, $renderPages = false) { - $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts); + $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts, $renderPages)->get(); $entities = []; $parents = []; $tree = []; foreach ($q as $index => $rawEntity) { - if ($rawEntity->entity_type === 'Bookstack\\Page') { + if ($rawEntity->entity_type === 'BookStack\\Page') { $entities[$index] = $this->page->newFromBuilder($rawEntity); - } else if ($rawEntity->entity_type === 'Bookstack\\Chapter') { + if ($renderPages) { + $entities[$index]->html = $rawEntity->description; + $entities[$index]->html = $this->renderPage($entities[$index]); + }; + } 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]; + if ($entities[$index]->chapter_id === 0 || $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; + if ($entity->chapter_id === 0 || $entity->chapter_id === '0') continue; + $parentKey = 'BookStack\\Chapter:' . $entity->chapter_id; $chapter = $parents[$parentKey]; $chapter->pages->push($entity); } @@ -796,6 +800,52 @@ class EntityRepo return $html; } + + /** + * Render the page for viewing, Parsing and performing features such as page transclusion. + * @param Page $page + * @return mixed|string + */ + public function renderPage(Page $page) + { + $content = $page->html; + $matches = []; + preg_match_all("/{{@\s?([0-9].*?)}}/", $content, $matches); + if (count($matches[0]) === 0) return $content; + + 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) { + $content = str_replace($matches[0][$index], '', $content); + continue; + } + + if (count($splitInclude) === 1) { + $content = str_replace($matches[0][$index], $page->html, $content); + continue; + } + + $doc = new DOMDocument(); + $doc->loadHTML(mb_convert_encoding(''.$page->html.'', '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); + } + $content = str_replace($matches[0][$index], trim($innerContent), $content); + } + + return $content; + } + /** * Get a new draft page instance. * @param Book $book @@ -835,15 +885,15 @@ class EntityRepo /** * Parse the headers on the page to get a navigation menu - * @param Page $page + * @param String $pageContent * @return array */ - public function getPageNav(Page $page) + public function getPageNav($pageContent) { - if ($page->html == '') return []; + if ($pageContent == '') return []; libxml_use_internal_errors(true); $doc = new DOMDocument(); - $doc->loadHTML(mb_convert_encoding($page->html, 'HTML-ENTITIES', 'UTF-8')); + $doc->loadHTML(mb_convert_encoding($pageContent, 'HTML-ENTITIES', 'UTF-8')); $xPath = new DOMXPath($doc); $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6"); @@ -1008,7 +1058,7 @@ class EntityRepo public function restorePageRevision(Page $page, Book $book, $revisionId) { $this->savePageRevision($page); - $revision = $this->getById('page_revision', $revisionId); + $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);