X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/cd6572b61af2165133468d2562d04dffdca8fca8..refs/pull/691/head:/app/Repos/EntityRepo.php diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index 0515a4cd4..64f7a0810 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -4,10 +4,12 @@ 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; use BookStack\Services\PermissionService; +use BookStack\Services\SearchService; use BookStack\Services\ViewService; use Carbon\Carbon; use DOMDocument; @@ -59,13 +61,12 @@ class EntityRepo protected $tagRepo; /** - * Acceptable operators to be used in a query - * @var array + * @var SearchService */ - protected $queryOperators = ['<=', '>=', '=', '<', '>', 'like', '!=']; + protected $searchService; /** - * EntityService constructor. + * EntityRepo constructor. * @param Book $book * @param Chapter $chapter * @param Page $page @@ -73,12 +74,18 @@ class EntityRepo * @param ViewService $viewService * @param PermissionService $permissionService * @param TagRepo $tagRepo + * @param SearchService $searchService */ public function __construct( - Book $book, Chapter $chapter, Page $page, PageRevision $pageRevision, - ViewService $viewService, PermissionService $permissionService, TagRepo $tagRepo - ) - { + Book $book, + Chapter $chapter, + Page $page, + PageRevision $pageRevision, + ViewService $viewService, + PermissionService $permissionService, + TagRepo $tagRepo, + SearchService $searchService + ) { $this->book = $book; $this->chapter = $chapter; $this->page = $page; @@ -86,12 +93,12 @@ 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; $this->tagRepo = $tagRepo; + $this->searchService = $searchService; } /** @@ -110,9 +117,9 @@ class EntityRepo * @param bool $allowDrafts * @return \Illuminate\Database\Query\Builder */ - protected function entityQuery($type, $allowDrafts = false) + protected function entityQuery($type, $allowDrafts = false, $permission = 'view') { - $q = $this->permissionService->enforceEntityRestrictions($type, $this->getEntity($type), 'view'); + $q = $this->permissionService->enforceEntityRestrictions($type, $this->getEntity($type), $permission); if (strtolower($type) === 'page' && !$allowDrafts) { $q = $q->where('draft', '=', false); } @@ -135,11 +142,16 @@ 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) { - return $this->entityQuery($type, $allowDrafts)->findOrFail($id); + if ($ignorePermissions) { + $entity = $this->getEntity($type); + return $entity->newQuery()->find($id); + } + return $this->entityQuery($type, $allowDrafts)->find($id); } /** @@ -155,14 +167,16 @@ class EntityRepo $q = $this->entityQuery($type)->where('slug', '=', $slug); if (strtolower($type) === 'chapter' || strtolower($type) === 'page') { - $q = $q->where('book_id', '=', function($query) use ($bookSlug) { + $q = $q->where('book_id', '=', function ($query) use ($bookSlug) { $query->select('id') ->from($this->book->getTable()) ->where('slug', '=', $bookSlug)->limit(1); }); } $entity = $q->first(); - if ($entity === null) throw new NotFoundException(trans('errors.' . strtolower($type) . '_not_found')); + if ($entity === null) { + throw new NotFoundException(trans('errors.' . strtolower($type) . '_not_found')); + } return $entity; } @@ -188,15 +202,18 @@ class EntityRepo } /** - * Get all entities of a type limited by count unless count if false. + * Get all entities of a type with the given permission, limited by count unless count is false. * @param string $type * @param integer|bool $count + * @param string $permission * @return Collection */ - public function getAll($type, $count = 20) + public function getAll($type, $count = 20, $permission = 'view') { - $q = $this->entityQuery($type)->orderBy('name', 'asc'); - if ($count !== false) $q = $q->take($count); + $q = $this->entityQuery($type, false, $permission)->orderBy('name', 'asc'); + if ($count !== false) { + $q = $q->take($count); + } return $q->get(); } @@ -217,12 +234,15 @@ class EntityRepo * @param int $count * @param int $page * @param bool|callable $additionalQuery + * @return Collection */ public function getRecentlyCreated($type, $count = 20, $page = 0, $additionalQuery = false) { $query = $this->permissionService->enforceEntityRestrictions($type, $this->getEntity($type)) ->orderBy('created_at', 'desc'); - if (strtolower($type) === 'page') $query = $query->where('draft', '=', false); + if (strtolower($type) === 'page') { + $query = $query->where('draft', '=', false); + } if ($additionalQuery !== false && is_callable($additionalQuery)) { $additionalQuery($query); } @@ -235,12 +255,15 @@ class EntityRepo * @param int $count * @param int $page * @param bool|callable $additionalQuery + * @return Collection */ public function getRecentlyUpdated($type, $count = 20, $page = 0, $additionalQuery = false) { $query = $this->permissionService->enforceEntityRestrictions($type, $this->getEntity($type)) ->orderBy('updated_at', 'desc'); - if (strtolower($type) === 'page') $query = $query->where('draft', '=', false); + if (strtolower($type) === 'page') { + $query = $query->where('draft', '=', false); + } if ($additionalQuery !== false && is_callable($additionalQuery)) { $additionalQuery($query); } @@ -314,31 +337,44 @@ 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->html; + $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; + if (!isset($parents[$parentKey])) { + $tree[] = $entity; + continue; + } $chapter = $parents[$parentKey]; $chapter->pages->push($entity); } @@ -350,6 +386,7 @@ class EntityRepo * Get the child items for a chapter sorted by priority but * with draft items floated to the top. * @param Chapter $chapter + * @return \Illuminate\Database\Eloquent\Collection|static[] */ public function getChapterChildren(Chapter $chapter) { @@ -357,56 +394,6 @@ class EntityRepo ->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->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), '/'))); - - // 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', "\$0", $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', "\$0", $entity->getExcerpt(100)); - $entity->searchSnippet = $result; - } - return $entities; - } /** * Get the next sequential priority for a new child element in the given book. @@ -461,7 +448,9 @@ class EntityRepo if (strtolower($type) === 'page' || strtolower($type) === 'chapter') { $query = $query->where('book_id', '=', $bookId); } - if ($currentId) $query = $query->where('id', '!=', $currentId); + if ($currentId) { + $query = $query->where('id', '!=', $currentId); + } return $query->count() > 0; } @@ -472,9 +461,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([ @@ -484,108 +474,12 @@ class EntityRepo } } } + $entity->save(); $this->permissionService->buildJointPermissionsForEntity($entity); } - /** - * Prepare a string of search terms by turning - * it into an array of terms. - * Keeps quoted terms together. - * @param $termString - * @return array - */ - public function prepareSearchTerms($termString) - { - $termString = $this->cleanSearchTermString($termString); - preg_match_all('/(".*?")/', $termString, $matches); - $terms = []; - if (count($matches[1]) > 0) { - foreach ($matches[1] as $match) { - $terms[] = $match; - } - $termString = trim(preg_replace('/"(.*?)"/', '', $termString)); - } - if (!empty($termString)) $terms = array_merge($terms, explode(' ', $termString)); - return $terms; - } - - /** - * Removes any special search notation that should not - * be used in a full-text search. - * @param $termString - * @return mixed - */ - protected function cleanSearchTermString($termString) - { - // Strip tag searches - $termString = preg_replace('/\[.*?\]/', '', $termString); - // Reduced multiple spacing into single spacing - $termString = preg_replace("/\s{2,}/", " ", $termString); - return $termString; - } - /** - * Get the available query operators as a regex escaped list. - * @return mixed - */ - protected function getRegexEscapedOperators() - { - $escapedOperators = []; - foreach ($this->queryOperators as $operator) { - $escapedOperators[] = preg_quote($operator); - } - return join('|', $escapedOperators); - } - - /** - * Parses advanced search notations and adds them to the db query. - * @param $query - * @param $termString - * @return mixed - */ - protected function addAdvancedSearchQueries($query, $termString) - { - $escapedOperators = $this->getRegexEscapedOperators(); - // Look for tag searches - preg_match_all("/\[(.*?)((${escapedOperators})(.*?))?\]/", $termString, $tags); - if (count($tags[0]) > 0) { - $this->applyTagSearches($query, $tags); - } - - return $query; - } - - /** - * Apply extracted tag search terms onto a entity query. - * @param $query - * @param $tags - * @return mixed - */ - protected function applyTagSearches($query, $tags) { - $query->where(function($query) use ($tags) { - foreach ($tags[1] as $index => $tagName) { - $query->whereHas('tags', function($query) use ($tags, $index, $tagName) { - $tagOperator = $tags[3][$index]; - $tagValue = $tags[4][$index]; - if (!empty($tagOperator) && !empty($tagValue) && in_array($tagOperator, $this->queryOperators)) { - if (is_numeric($tagValue) && $tagOperator !== 'like') { - // We have to do a raw sql query for this since otherwise PDO will quote the value and MySQL will - // search the value as a string which prevents being able to do number-based operations - // on the tag values. We ensure it has a numeric value and then cast it just to be sure. - $tagValue = (float) trim($query->getConnection()->getPdo()->quote($tagValue), "'"); - $query->where('name', '=', $tagName)->whereRaw("value ${tagOperator} ${tagValue}"); - } else { - $query->where('name', '=', $tagName)->where('value', $tagOperator, $tagValue); - } - } else { - $query->where('name', '=', $tagName); - } - }); - } - }); - return $query; - } /** * Create a new entity from request input. @@ -604,12 +498,13 @@ class EntityRepo $entity->updated_by = user()->id; $isChapter ? $book->chapters()->save($entity) : $entity->save(); $this->permissionService->buildJointPermissionsForEntity($entity); + $this->searchService->indexEntity($entity); return $entity; } /** * Update entity details from request input. - * Use for books and chapters + * Used for books and chapters * @param string $type * @param Entity $entityModel * @param array $input @@ -624,6 +519,7 @@ class EntityRepo $entityModel->updated_by = user()->id; $entityModel->save(); $this->permissionService->buildJointPermissionsForEntity($entityModel); + $this->searchService->indexEntity($entityModel); return $entityModel; } @@ -664,11 +560,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); } /** @@ -678,9 +574,12 @@ class EntityRepo */ protected function nameToSlug($name) { - $slug = str_replace(' ', '-', strtolower($name)); - $slug = preg_replace('/[\+\/\\\?\@\}\{\.\,\=\[\]\#\&\!\*\'\;\:\$\%]/', '', $slug); - if ($slug === "") $slug = substr(md5(rand(1, 500)), 0, 5); + $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; } @@ -702,12 +601,13 @@ 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; $draftPage->save(); $this->savePageRevision($draftPage, trans('entities.pages_initial_revision')); - + $this->searchService->indexEntity($draftPage); return $draftPage; } @@ -720,7 +620,9 @@ class EntityRepo public function savePageRevision(Page $page, $summary = null) { $revision = $this->pageRevision->newInstance($page->toArray()); - if (setting('app-editor') !== 'markdown') $revision->markdown = ''; + if (setting('app-editor') !== 'markdown') { + $revision->markdown = ''; + } $revision->page_id = $page->id; $revision->slug = $page->slug; $revision->book_slug = $page->book->slug; @@ -728,6 +630,7 @@ class EntityRepo $revision->created_at = $page->updated_at; $revision->type = 'version'; $revision->summary = $summary; + $revision->revision_number = $page->revision_count; $revision->save(); // Clear old revisions @@ -747,7 +650,9 @@ class EntityRepo */ protected function formatHtml($htmlText) { - if ($htmlText == '') return $htmlText; + if ($htmlText == '') { + return $htmlText; + } libxml_use_internal_errors(true); $doc = new DOMDocument(); $doc->loadHTML(mb_convert_encoding($htmlText, 'HTML-ENTITIES', 'UTF-8')); @@ -761,7 +666,9 @@ class EntityRepo foreach ($childNodes as $index => $childNode) { /** @var \DOMElement $childNode */ - if (get_class($childNode) !== 'DOMElement') continue; + if (get_class($childNode) !== 'DOMElement') { + continue; + } // Overwrite id if not a BookStack custom id if ($childNode->hasAttribute('id')) { @@ -796,6 +703,74 @@ class EntityRepo return $html; } + + /** + * 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, $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; + } + + $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], $matchedPage->html, $content); + continue; + } + + $doc = new DOMDocument(); + $doc->loadHTML(mb_convert_encoding(''.$matchedPage->html.'', 'HTML-ENTITIES', 'UTF-8')); + $matchingElem = $doc->getElementById($splitInclude[1]); + if ($matchingElem === null) { + $content = str_replace($matches[0][$index], '', $content); + continue; + } + $innerContent = ''; + $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); + } + + 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 @@ -810,9 +785,12 @@ class EntityRepo $page->updated_by = user()->id; $page->draft = true; - if ($chapter) $page->chapter_id = $chapter->id; + if ($chapter) { + $page->chapter_id = $chapter->id; + } $book->pages()->save($page); + $page = $this->page->find($page->id); $this->permissionService->buildJointPermissionsForEntity($page); return $page; } @@ -835,19 +813,23 @@ class EntityRepo /** * Parse the headers on the page to get a navigation menu - * @param Page $page - * @return Collection + * @param String $pageContent + * @return array */ - public function getPageNav(Page $page) + public function getPageNav($pageContent) { - if ($page->html == '') return null; + 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"); - if (is_null($headers)) return null; + if (is_null($headers)) { + return []; + } $tree = collect([]); foreach ($headers as $header) { @@ -863,12 +845,12 @@ class EntityRepo // Normalise headers if only smaller headers have been used if (count($tree) > 0) { $minLevel = $tree->pluck('level')->min(); - $tree = $tree->map(function($header) use ($minLevel) { + $tree = $tree->map(function ($header) use ($minLevel) { $header['level'] -= ($minLevel - 2); return $header; }); } - return $tree; + return $tree->toArray(); } /** @@ -898,9 +880,12 @@ class EntityRepo $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->text = $this->pageToPlainText($page); + if (setting('app-editor') !== 'markdown') { + $page->markdown = ''; + } $page->updated_by = $userId; + $page->revision_count++; $page->save(); // Remove all update drafts for this user & page. @@ -911,6 +896,8 @@ class EntityRepo $this->savePageRevision($page, $input['summary']); } + $this->searchService->indexEntity($page); + return $page; } @@ -958,7 +945,9 @@ class EntityRepo 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; + if ($draft->page->updated_at->timestamp <= $draft->updated_at->timestamp) { + return $message; + } return $message . "\n" . trans('entities.pages_draft_edited_notification'); } @@ -1007,13 +996,15 @@ class EntityRepo */ public function restorePageRevision(Page $page, Book $book, $revisionId) { + $page->revision_count++; $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); + $page->text = $this->pageToPlainText($page); $page->updated_by = user()->id; $page->save(); + $this->searchService->indexEntity($page); return $page; } @@ -1030,7 +1021,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; @@ -1052,7 +1043,9 @@ class EntityRepo } $draft->fill($data); - if (setting('app-editor') !== 'markdown') $draft->markdown = ''; + if (setting('app-editor') !== 'markdown') { + $draft->markdown = ''; + } $draft->save(); return $draft; @@ -1106,6 +1099,7 @@ class EntityRepo $book->views()->delete(); $book->permissions()->delete(); $this->permissionService->deleteJointPermissionsForEntity($book); + $this->searchService->deleteEntityTerms($book); $book->delete(); } @@ -1125,12 +1119,14 @@ class EntityRepo $chapter->views()->delete(); $chapter->permissions()->delete(); $this->permissionService->deleteJointPermissionsForEntity($chapter); + $this->searchService->deleteEntityTerms($chapter); $chapter->delete(); } /** * Destroy a given page along with its dependencies. * @param Page $page + * @throws NotifyException */ public function destroyPage(Page $page) { @@ -1140,6 +1136,13 @@ class EntityRepo $page->revisions()->delete(); $page->permissions()->delete(); $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); @@ -1149,17 +1152,4 @@ class EntityRepo $page->delete(); } - } - - - - - - - - - - - -