diff --git a/system/typemill/Controllers/Controller.php b/system/typemill/Controllers/Controller.php index d32f92a..b79ce8a 100644 --- a/system/typemill/Controllers/Controller.php +++ b/system/typemill/Controllers/Controller.php @@ -28,18 +28,6 @@ abstract class Controller $this->c->get('dispatcher')->dispatch(new OnTwigLoaded(false), 'onTwigLoaded'); } -/* - public function getCsrfData($request) - { - $nameKey = $this->csrf->getTokenNameKey(); - $valueKey = $this->csrf->getTokenValueKey(); - - return [ - $nameKey => $request->getAttribute($nameKey), - $valueKey => $request->getAttribute($valueKey) - ]; - } -*/ protected function settingActive($setting) { if(isset($this->settings[$setting]) && $this->settings[$setting]) @@ -65,16 +53,23 @@ abstract class Controller protected function getItem($navigation, $url, $urlinfo) { + die('getItem in controller'); + $url = $this->removeEditorFromUrl($url); - $langattr = $this->settings['langattr']; if($url == '/') { - $keyPathArray = ['']; + return $navigation->getHomepageItem($urlinfo['baseurl']); } else { + $langattr = $this->settings['langattr']; + + # get the first level navigation + $firstLevel = $navigation->getExtendedNavigation($urlinfo, $langattr, '/'); + + $extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr); $pageinfo = $extendedNavigation[$url] ?? false; @@ -88,15 +83,46 @@ abstract class Controller } - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); $item = $navigation->getItemWithKeyPath($draftNavigation, $keyPathArray, $urlinfo['basepath']); return $item; - } + } + +/* + protected function getFolderForItem($item) + { + if(count($item->keyPathArray) > 1) + { + $segments = explode('/', $item->path); + + return $segments[1]; + } + + # it is a base-item + return '/'; + } +*/ + + protected function getFolderForItem($item) + { + die('moved getFolderForItem from controller to navigation'); + $segments = explode('/', $item->path); + + # we always return base (parent) folder, so for base folder /myfolder the parent is '/'. Makes sure that base-level navigation in navigation cache is deleted + if(isset($segments[2])) + { + return $segments[1]; + } + + return 'navi-draft'; + } protected function removeEditorFromUrl($url) { + die('moved removeEditorFromUrl from controller to navigation'); + $url = trim($url, '/'); $url = str_replace('tm/content/visual', '', $url); @@ -107,6 +133,8 @@ abstract class Controller return '/' . $url; } + + protected function addDatasets(array $formDefinitions) { foreach($formDefinitions as $fieldname => $field) diff --git a/system/typemill/Controllers/ControllerApiAuthorArticle.php b/system/typemill/Controllers/ControllerApiAuthorArticle.php index 9412c1d..08f404d 100644 --- a/system/typemill/Controllers/ControllerApiAuthorArticle.php +++ b/system/typemill/Controllers/ControllerApiAuthorArticle.php @@ -37,9 +37,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -78,14 +79,18 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(500); } - # refresh navigation and item - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); + + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); - $sitemap = new Sitemap(); - $sitemap->updateSitemap($draftNavigation, $urlinfo); + if(!isset($this->settings['disableSitemap']) OR !$this->settings['disableSitemap']) + { + $sitemap = new Sitemap(); + $sitemap->updateSitemap($draftNavigation, $urlinfo); + } # META is important e.g. for newsletter, so send it, too $meta = new Meta(); @@ -130,9 +135,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -163,14 +169,18 @@ class ControllerApiAuthorArticle extends Controller $draftMarkdown = $content->getDraftMarkdown($item); $content->unpublishMarkdown($item, $draftMarkdown); - # refresh navigation and item - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); + + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); - - $sitemap = new Sitemap(); - $sitemap->updateSitemap($draftNavigation, $urlinfo); + + if(!isset($this->settings['disableSitemap']) OR !$this->settings['disableSitemap']) + { + $sitemap = new Sitemap(); + $sitemap->updateSitemap($draftNavigation, $urlinfo); + } # check if it is a folder and if the folder has published pages. $message = false; @@ -213,9 +223,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -247,12 +258,13 @@ class ControllerApiAuthorArticle extends Controller $markdownArray = $content->markdownTextToArray($markdown); $content->saveDraftMarkdown($item, $markdownArray); - # refresh navigation and item - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); + + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); - + # refresh content $draftMarkdown = $content->getDraftMarkdown($item); $draftMarkdownHtml = $content->addDraftHtml($draftMarkdown); @@ -282,9 +294,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -316,14 +329,18 @@ class ControllerApiAuthorArticle extends Controller $markdownArray = $content->markdownTextToArray($markdown); $content->publishMarkdown($item, $markdownArray); - # refresh navigation and item - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); + + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); - $sitemap = new Sitemap(); - $sitemap->updateSitemap($draftNavigation, $urlinfo); + if(!isset($this->settings['disableSitemap']) OR !$this->settings['disableSitemap']) + { + $sitemap = new Sitemap(); + $sitemap->updateSitemap($draftNavigation, $urlinfo); + } # refresh content $draftMarkdown = $content->getDraftMarkdown($item); @@ -368,9 +385,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -400,9 +418,10 @@ class ControllerApiAuthorArticle extends Controller $content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher')); $content->deleteDraft($item); - # refresh navigation and item - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); + + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); @@ -441,7 +460,7 @@ class ControllerApiAuthorArticle extends Controller # get navigation $navigation = new Navigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); if($params['folder_id'] == 'root') { if($params['item_name'] == 'tm') @@ -557,10 +576,15 @@ class ControllerApiAuthorArticle extends Controller # $url = $urlinfo['baseurl'] . '/tm/content/' . $this->settings['editor'] . $folder->urlRelWoF . '/' . $slug; } - $navigation->clearNavigation(); + + $itempath = $folderPath . DIRECTORY_SEPARATOR . $namePath; + $naviFileName = $navigation->getNaviFileNameForPath($itempath); + + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $response->getBody()->write(json_encode([ - 'navigation' => $navigation->getDraftNavigation($urlinfo, $langattr), + 'navigation' => $draftNavigation, 'message' => '', 'url' => false ])); @@ -590,7 +614,7 @@ class ControllerApiAuthorArticle extends Controller # get navigation $navigation = new Navigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); if($params['folder_id'] == 'root') { $folderContent = $draftNavigation; @@ -669,9 +693,13 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(402); } - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); - $item = $navigation->getItemWithKeyPath($draftNavigation, $folderKeyPath); + $itempath = $folderPath . DIRECTORY_SEPARATOR . $namePath; + $naviFileName = $navigation->getNaviFileNameForPath($itempath); + + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); + $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); $response->getBody()->write(json_encode([ 'navigation' => $draftNavigation, @@ -697,9 +725,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -730,11 +759,11 @@ class ControllerApiAuthorArticle extends Controller if($parentUrl == '/') { $parentItem = new \stdClass; - $parentItem->folderContent = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $parentItem->folderContent = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr'], '/'); } else { - $parentItem = $this->getItem($navigation, $parentUrl, $urlinfo); + $parentItem = $navigation->getItemForUrl($parentUrl, $urlinfo, $langattr); } foreach($parentItem->folderContent as $sibling) @@ -750,11 +779,19 @@ class ControllerApiAuthorArticle extends Controller } $navigation->renameItem($item, $params['slug']); - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); - $sitemap = new Sitemap(); - $sitemap->updateSitemap($draftNavigation, $urlinfo); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); + + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); + $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); + + if(!isset($this->settings['disableSitemap']) OR !$this->settings['disableSitemap']) + { + $sitemap = new Sitemap(); + $sitemap->updateSitemap($draftNavigation, $urlinfo); + } # create the new url for redirects $newUrlRel = str_replace($item->slug, $params['slug'], $item->urlRelWoF); @@ -791,18 +828,15 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - # set variables - $urlinfo = $this->c->get('urlinfo'); - $langattr = $this->settings['langattr'] ?? 'en'; - $itemKeyPath = explode('.', $params['item_id']); $parentKeyFrom = explode('.', $params['parent_id_from']); $parentKeyTo = explode('.', $params['parent_id_to']); # get navigation - $navigation = new Navigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); - $item = $navigation->getItemWithKeyPath($draftNavigation, $itemKeyPath); + $urlinfo = $this->c->get('urlinfo'); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -826,8 +860,9 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(403); } - } + } +/* $extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr); $pageinfo = $extendedNavigation[$params['url']] ?? false; if(!$pageinfo) @@ -838,6 +873,9 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(404); } +*/ + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); + $clearFullNavi = true; # if an item is moved to the first level if($params['parent_id_to'] == '') @@ -859,6 +897,10 @@ class ControllerApiAuthorArticle extends Controller # if the item has been moved within the same folder if($params['parent_id_from'] == $params['parent_id_to']) { + # we do not have to generate the full navigation, only this part + $clearFullNavi = false; + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + # get key of item $itemKey = end($itemKeyPath); reset($itemKeyPath); @@ -902,11 +944,22 @@ class ControllerApiAuthorArticle extends Controller } # refresh navigation and item - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + if($clearFullNavi) + { + $navigation->clearNavigation(); + } + else + { + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); + } + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); - $sitemap = new Sitemap(); - $sitemap->updateSitemap($draftNavigation, $urlinfo); + # update the sitemap + if(!isset($this->settings['disableSitemap']) OR !$this->settings['disableSitemap']) + { + $sitemap = new Sitemap(); + $sitemap->updateSitemap($draftNavigation, $urlinfo); + } $this->c->get('dispatcher')->dispatch(new OnPageSorted($params), 'onPageSorted'); @@ -935,9 +988,10 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -992,12 +1046,16 @@ class ControllerApiAuthorArticle extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(500); } - # refresh navigation - $navigation->clearNavigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); - $sitemap = new Sitemap(); - $sitemap->updateSitemap($draftNavigation, $urlinfo); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); + + if(!isset($this->settings['disableSitemap']) OR !$this->settings['disableSitemap']) + { + $sitemap = new Sitemap(); + $sitemap->updateSitemap($draftNavigation, $urlinfo); + } # check if it is a subfile or subfolder and set the redirect-url to the parent item $url = $urlinfo['baseurl'] . '/tm/content/' . $this->settings['editor']; diff --git a/system/typemill/Controllers/ControllerApiAuthorBlock.php b/system/typemill/Controllers/ControllerApiAuthorBlock.php index b6774cb..17f1500 100644 --- a/system/typemill/Controllers/ControllerApiAuthorBlock.php +++ b/system/typemill/Controllers/ControllerApiAuthorBlock.php @@ -30,9 +30,10 @@ class ControllerApiAuthorBlock extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -100,12 +101,13 @@ class ControllerApiAuthorBlock extends Controller # if it was published before, then we need to refresh the navigation if($item->status == 'published') { - $navigation->clearNavigation(); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); - + $response->getBody()->write(json_encode([ 'content' => $draftMarkdownHtml, 'navigation' => $draftNavigation, @@ -140,9 +142,10 @@ class ControllerApiAuthorBlock extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -199,9 +202,10 @@ class ControllerApiAuthorBlock extends Controller # if it was published before, then we need to refresh the navigation if($item->status == 'published') { - $navigation->clearNavigation(); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); @@ -239,9 +243,10 @@ class ControllerApiAuthorBlock extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -311,9 +316,10 @@ class ControllerApiAuthorBlock extends Controller # if it was published before, then we need to refresh the navigation if($item->status == 'published') { - $navigation->clearNavigation(); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); @@ -351,9 +357,10 @@ class ControllerApiAuthorBlock extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -414,9 +421,10 @@ class ControllerApiAuthorBlock extends Controller # if it was published before, then we need to refresh the navigation if($item->status == 'published') { - $navigation->clearNavigation(); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $navigation->clearNavigation([$naviFileName]); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); diff --git a/system/typemill/Controllers/ControllerApiAuthorMeta.php b/system/typemill/Controllers/ControllerApiAuthorMeta.php index b128754..a838939 100644 --- a/system/typemill/Controllers/ControllerApiAuthorMeta.php +++ b/system/typemill/Controllers/ControllerApiAuthorMeta.php @@ -17,9 +17,10 @@ class ControllerApiAuthorMeta extends Controller { $url = $request->getQueryParams()['url'] ?? false; - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $url, $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($url, $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -125,9 +126,10 @@ class ControllerApiAuthorMeta extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } - $navigation = new Navigation(); $urlinfo = $this->c->get('urlinfo'); - $item = $this->getItem($navigation, $params['url'], $urlinfo); + $langattr = $this->settings['langattr']; + $navigation = new Navigation(); + $item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr); if(!$item) { $response->getBody()->write(json_encode([ @@ -193,47 +195,11 @@ class ControllerApiAuthorMeta extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } -/* - $errors = []; - - # take the user input data and iterate over all fields and values - foreach($params['data'] as $fieldname => $fieldvalue) - { - # get the corresponding field definition from original plugin settings - $fielddefinition = $tabdefinitions[$fieldname] ?? false; - - if(!$fielddefinition) - { - $errors[$tab][$fieldname] = Translations::translate('This field is not defined'); - } - else - { - # validate user input for this field - $result = $validate->field($fieldname, $fieldvalue, $fielddefinition); - - if($result !== true) - { - $errors[$params['tab']][$fieldname] = $result[$fieldname][0]; - } - } - } - - # return validation errors - if(!empty($errors)) - { - $response->getBody()->write(json_encode([ - 'message' => Translations::translate('Please correct your input.'), - 'errors' => $errors - ])); - - return $response->withHeader('Content-Type', 'application/json')->withStatus(400); - } -*/ - - # extended - $navigation = new Navigation(); - - $extended = $navigation->getExtendedNavigation($urlinfo, $this->settings['langattr']); + $navigation = new Navigation(); + $naviFileName = $navigation->getNaviFileNameForPath($item->path); + $extended = $navigation->getExtendedNavigation($urlinfo, $this->settings['langattr'], $naviFileName); + $draftNavigation = false; + $updateDraftNavi = false; if($params['tab'] == 'meta') { @@ -262,11 +228,13 @@ class ControllerApiAuthorMeta extends Controller $renameresults = $meta->renamePost($item->pathWithoutType, $newPathWithoutType); - $navigation->clearNavigation(); + # make sure the whole navigation with base-navigation and folder-navigation is updated. Bad for performance but rare case + $navigation->clearNavigation(); - # WE HAVE TO REGENERATE ITEM AND NAVIGATION - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); - $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); + # RECREATE ITEM AND NAVIGATION, because we rename filename first and later update the meta-content + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); + $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); } } @@ -300,7 +268,17 @@ class ControllerApiAuthorMeta extends Controller return $response->withHeader('Content-Type', 'application/json')->withStatus(500); } - $navigation->clearNavigation(); + # this will only update the basic draft navigation but we also have to update the folder navigation + # $navigation->clearNavigation([$naviFileName, $naviFileName. "-extened"]); + # other solution: + # $fakeFolderpath = $item->getPath; + # $fakeFolderpath .= '/getMyParent'; + # $naviFolderName = $navigation->getNaviFileNameForPath($fakeFolderPath); + # $navigation->clearNavigation([$naviFolderName, $naviFolderName. "-extened"]); + + # clear the whole navigation to make sure that folder navigation is recreated correctly + $navigation->clearNavigation(); + $updateDraftNavi = true; } # normalize the meta-input @@ -315,7 +293,8 @@ class ControllerApiAuthorMeta extends Controller && isset($extended[$item->urlRelWoF]) ) { - $navigation->clearNavigation(); + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); + $updateDraftNavi = true; } elseif( # check if navtitle or hide-value has been changed @@ -326,10 +305,11 @@ class ControllerApiAuthorMeta extends Controller ($this->hasChanged($params['data'], $metadata['meta'], 'noindex')) ) { - $navigation->clearNavigation(); + $navigation->clearNavigation([$naviFileName, $naviFileName . '-extended']); + $updateDraftNavi = true; } } - + # add the new/edited metadata $metadata[$params['tab']] = $validated['data']; @@ -338,9 +318,12 @@ class ControllerApiAuthorMeta extends Controller if($store === true) { - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $this->settings['langattr']); - $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); - $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); + if($updateDraftNavi) + { + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $this->settings['langattr']); + $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $item->keyPathArray); + $item = $navigation->getItemWithKeyPath($draftNavigation, $item->keyPathArray); + } $response->getBody()->write(json_encode([ 'navigation' => $draftNavigation, diff --git a/system/typemill/Controllers/ControllerWebAuthor.php b/system/typemill/Controllers/ControllerWebAuthor.php index 1fc1e32..c72a54e 100644 --- a/system/typemill/Controllers/ControllerWebAuthor.php +++ b/system/typemill/Controllers/ControllerWebAuthor.php @@ -24,7 +24,7 @@ class ControllerWebAuthor extends Controller $langattr = $this->settings['langattr']; $navigation = new Navigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); $home = $navigation->getHomepageItem($urlinfo['baseurl']); if($url == '/') @@ -34,9 +34,7 @@ class ControllerWebAuthor extends Controller } else { - $extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr); - - $pageinfo = $extendedNavigation[$url] ?? false; + $pageinfo = $navigation->getPageInfoForUrl($url, $urlinfo, $langattr); if(!$pageinfo) { return $this->c->get('view')->render($response->withStatus(404), '404.twig', [ @@ -47,9 +45,6 @@ class ControllerWebAuthor extends Controller $keyPathArray = explode(".", $pageinfo['keyPath']); - # extend : $request->getAttribute('c_userrole') -# $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); - $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $keyPathArray); $draftNavigation = $this->c->get('dispatcher')->dispatch(new OnPagetreeLoaded($draftNavigation), 'onPagetreeLoaded')->getData(); @@ -95,7 +90,7 @@ class ControllerWebAuthor extends Controller $langattr = $this->settings['langattr']; $navigation = new Navigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); $home = $navigation->getHomepageItem($urlinfo['baseurl']); if($url == '/') @@ -105,9 +100,7 @@ class ControllerWebAuthor extends Controller } else { - $extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr); - - $pageinfo = $extendedNavigation[$url] ?? false; + $pageinfo = $navigation->getPageInfoForUrl($url, $urlinfo, $langattr); if(!$pageinfo) { return $this->c->get('view')->render($response->withStatus(404), '404.twig', [ @@ -119,7 +112,6 @@ class ControllerWebAuthor extends Controller $keyPathArray = explode(".", $pageinfo['keyPath']); # extend : $request->getAttribute('c_userrole') - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); $draftNavigation = $navigation->setActiveNaviItemsWithKeyPath($draftNavigation, $keyPathArray); $draftNavigation = $this->c->get('dispatcher')->dispatch(new OnPagetreeLoaded($draftNavigation), 'onPagetreeLoaded')->getData(); diff --git a/system/typemill/Controllers/ControllerWebFrontend.php b/system/typemill/Controllers/ControllerWebFrontend.php index 9164e3e..2d72ffc 100644 --- a/system/typemill/Controllers/ControllerWebFrontend.php +++ b/system/typemill/Controllers/ControllerWebFrontend.php @@ -31,7 +31,7 @@ class ControllerWebFrontend extends Controller # GET THE NAVIGATION $navigation = new Navigation(); - $draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr); + $draftNavigation = $navigation->getFullDraftNavigation($urlinfo, $langattr); $home = false; # GET THE PAGINATION @@ -52,9 +52,8 @@ class ControllerWebFrontend extends Controller } else { - $extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr); - $pageinfo = $extendedNavigation[$url] ?? false; + $pageinfo = $navigation->getPageInfoForUrl($url, $urlinfo, $langattr); if(!$pageinfo) { @@ -96,14 +95,12 @@ class ControllerWebFrontend extends Controller } } - # GET THE LIVE NAVIGATION (keyPathArray does not match here!!!) - $liveNavigation = $navigation->getLiveNavigation($urlinfo, $langattr); + $liveNavigation = $navigation->generateLiveNavigationFromDraft($draftNavigation); # STRIP OUT HIDDEN PAGES $liveNavigation = $navigation->removeHiddenPages($liveNavigation); # SET PAGEs ACTIVE -# $liveNavigation = $navigation->setActiveNaviItems($liveNavigation, $breadcrumb); $liveNavigation = $navigation->setActiveNaviItemsWithKeyPath($liveNavigation, $item->keyPathArray); # DISPATCH LIVE NAVIGATION diff --git a/system/typemill/Models/Folder.php b/system/typemill/Models/Folder.php index 094442d..8c09287 100644 --- a/system/typemill/Models/Folder.php +++ b/system/typemill/Models/Folder.php @@ -6,40 +6,13 @@ use \URLify; class Folder { - - /* - * scans content of a folder (without recursion) - * vars: folder path as string - * returns: one-dimensional array with names of folders and files - */ - public function scanFolderFlat($folderPath) - { - $folderItems = scandir($folderPath); - $folderContent = array(); - - foreach ($folderItems as $key => $item) - { - if (!in_array($item, array(".",".."))) - { - $nameParts = $this->getStringParts($item); - $fileType = array_pop($nameParts); - - if($fileType == 'md' OR $fileType == 'txt' ) - { - $folderContent[] = $item; - } - } - } - return $folderContent; - } - - /* * scans content of a folder recursively - * vars: folder path as string + * $folderPath as string + * $flat true scans no subfolder or string scans only subfolder with that string * returns: multi-dimensional array with names of folders and files */ - public function scanFolder($folderPath) + public function scanFolder($folderPath, $flat = NULL) { $folderItems = scandir($folderPath); $folderContent = array(); @@ -50,11 +23,32 @@ class Folder { if (is_dir($folderPath . DIRECTORY_SEPARATOR . $item)) { + if($flat) + { + if($flat === $item) + { + $folderContent[$item] = $this->scanFolder($folderPath . DIRECTORY_SEPARATOR . $item); + } + else + { + # We need to include the index.txt or index.md for the folder + $index = 'index.'; + if( file_exists($folderPath . DIRECTORY_SEPARATOR . $item . DIRECTORY_SEPARATOR . 'index.txt') ) + { + $index .= 'txt'; + } + if( file_exists($folderPath . DIRECTORY_SEPARATOR . $item . DIRECTORY_SEPARATOR . 'index.md') ) + { + $index .= 'md'; + } - $subFolder = $item; - $folderPublished = file_exists($folderPath . DIRECTORY_SEPARATOR . $item . DIRECTORY_SEPARATOR . 'index.md'); - - $folderContent[$subFolder] = $this->scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder); + $folderContent[$item] = [$index]; + } + } + else + { + $folderContent[$item] = $this->scanFolder($folderPath . DIRECTORY_SEPARATOR . $item); + } } else { @@ -105,6 +99,7 @@ class Folder $nameParts = $this->getStringParts($key); $fileType = ''; + $status = 'undefined'; if(in_array('index.md', $name)) { $fileType = 'md'; @@ -150,7 +145,12 @@ class Folder rsort($name); } - $item->folderContent = $this->getFolderContentDetails($name, $language, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter); + $item->folderContent = []; + + if(!empty($name)) + { + $item->folderContent = $this->getFolderContentDetails($name, $language, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter); + } } elseif($name) { @@ -209,7 +209,7 @@ class Folder public function getFolderContentType($folder, $yamlpath) { # check if folder is empty or has only index.yaml-file. This is a rare case so make it quick and dirty - if(count($folder) == 1) + if(count($folder) <= 1) { # check if in folder yaml file contains "posts", then return posts $folderyamlpath = getcwd() . DIRECTORY_SEPARATOR . 'content' . DIRECTORY_SEPARATOR . $yamlpath; diff --git a/system/typemill/Models/Navigation.php b/system/typemill/Models/Navigation.php index 83b3d3b..ca4e49c 100644 --- a/system/typemill/Models/Navigation.php +++ b/system/typemill/Models/Navigation.php @@ -12,23 +12,9 @@ class Navigation extends Folder private $naviFolder; - private $liveNaviName; - private $draftNaviName; - private $extendedNaviName; - - private $extendedNavigation = false; - - private $draftNavigation = false; - - private $basicDraftNavigation = false; - - private $liveNavigation = false; - - private $basicLiveNavigation = false; - - public $activeNavigation = false; + private $DS; public function __construct() { @@ -36,42 +22,9 @@ class Navigation extends Folder $this->naviFolder = 'navigation'; - $this->liveNaviName = 'navi-live.txt'; + $this->draftNaviName = 'draft-navi'; - $this->draftNaviName = 'navi-draft.txt'; - - $this->extendedNaviName = 'navi-extended.txt'; - } - - # use array ['extended' => true, 'draft' => true, 'live' => true] to clear files - public function clearNavigation(array $deleteitems = NULL ) - { - $result = false; - - # clear cache - $this->extendedNavigation = false; - $this->draftNavigation = false; - $this->basicDraftNavigation = false; - $this->liveNavigation = false; - $this->basicLiveNavigation = false; - - $navifiles = [ - 'extended' => $this->extendedNaviName, - 'draft' => $this->draftNaviName, - 'live' => $this->liveNaviName - ]; - - if($deleteitems) - { - $navifiles = array_intersect_key($navifiles, $deleteitems); - } - - foreach($navifiles as $navifile) - { - $result = $this->storage->deleteFile('dataFolder', $this->naviFolder, $navifile); - } - - return $result; + $this->DS = DIRECTORY_SEPARATOR; } public function getMainNavigation($userrole, $acl, $urlinfo, $editor) @@ -148,85 +101,278 @@ class Navigation extends Folder return $allowedsystemnavi; } - # get the navigation with draft files for author environment - public function getDraftNavigation($urlinfo, $language, $userrole = null, $username = null) + + # use array ['extended' => true, 'draft' => true, 'live' => true] to clear files + public function clearNavigation($deleteItems = NULL) { - # todo: filter for userrole or username + $result = false; - $this->draftNavigation = $this->storage->getFile('dataFolder', $this->naviFolder, $this->draftNaviName, 'unserialize'); + $dataPath = $this->storage->getFolderPath('dataFolder'); + $naviPath = $dataPath . DIRECTORY_SEPARATOR . $this->naviFolder; + $naviFiles = scandir($naviPath); - if($this->draftNavigation) + if($deleteItems) { - return $this->draftNavigation; + # replace the placeholder '/' for a base-item with the cached base navigation + foreach ($deleteItems as &$value) + { + if ($value === '/') + { + $value = $this->draftNaviName; + } + else + { + $value .= '.txt'; + } + } + + $naviFiles = array_intersect($naviFiles, $deleteItems); } - # if there is no cached navi, create a basic new draft navi - $basicDraftNavigation = $this->getBasicDraftNavigation($urlinfo, $language); + foreach($naviFiles as $naviFile) + { + if (!in_array($naviFile, array(".","..")) && substr($naviFile, 0, 1) != '.') + { + $result = $this->storage->deleteFile('dataFolder', $this->naviFolder, $naviFile); + } + } - # get the extended navigation with additional infos from the meta-files like title or hidden pages - $extendedNavigation = $this->getExtendedNavigation($urlinfo, $language); + return $result; + } - # merge the basic draft navi with the extended infos from meta-files - $draftNavigation = $this->mergeNavigationWithExtended($basicDraftNavigation, $extendedNavigation); - # cache it - $this->storage->writeFile('dataFolder', $this->naviFolder, $this->draftNaviName, $draftNavigation, 'serialize'); + public function getItemForUrl($url, $urlinfo, $langattr) + { + $url = $this->removeEditorFromUrl($url); + + if($url == '/') + { + return $this->getHomepageItem($urlinfo['baseurl']); + } + + $pageinfo = $this->getPageInfoForUrl($url, $urlinfo, $langattr); + + if(!$pageinfo) + { + return false; + } + + $foldername = $this->getFirstUrlSegment($pageinfo['path']); + + $draftNavigation = $this->getDraftNavigation($urlinfo, $langattr, $foldername); + if(!$draftNavigation) + { + return false; + } + + $keyPathArray = explode(".", $pageinfo['keyPath']); + $item = $this->getItemWithKeyPath($draftNavigation, $keyPathArray); + + return $item; + } + + public function getPageInfoForUrl($url, $urlinfo, $langattr) + { + # get the first level navigation + $firstLevelExtended = $this->getExtendedNavigation($urlinfo, $langattr, '/'); + + $firstUrlSegment = $this->getFirstUrlSegment($url); + $firstUrlSegment = '/' . $firstUrlSegment; + + $pageinfo = $firstLevelExtended[$firstUrlSegment] ?? false; + + # first level does not exist + if(!$pageinfo) + { + return false; + } + + # url is first level + if($url == $firstUrlSegment) + { + return $pageinfo; + } + + $foldername = trim($pageinfo['path'], $this->DS); + + $extendedNavigation = $this->getExtendedNavigation($urlinfo, $langattr, $foldername); + + $pageinfo = $extendedNavigation[$url] ?? false; + if(!$pageinfo) + { + return false; + } + + return $pageinfo; + } + + private function removeEditorFromUrl($url) + { + $url = trim($url, '/'); + + $url = str_replace('tm/content/visual', '', $url); + $url = str_replace('tm/content/raw', '', $url); + + $url = trim($url, '/'); + + return '/' . $url; + } + + public function getFirstUrlSegment($url) + { + $segments = explode('/', $url); + + if(isset($segments[1])) + { + return $segments[1]; + } + + return ''; + } + + public function getNaviFileNameForPath($path) + { + $segments = explode($this->DS, $path); + + # navi-file-name for a base-folder is draftNaviName where first level items are cached. + if(isset($segments[2])) + { + return $segments[1]; + } + + return $this->draftNaviName; + } + + + + public function getLiveNavigation($urlinfo, $langattr) + { + $draftNavigation = $this->getFullDraftNavigation($urlinfo, $langattr); + + $liveNavigation = $this->generateLiveNavigationFromDraft($draftNavigation); + + $liveNavigation = $this->removeHiddenPages($liveNavigation); + + return $liveNavigation; + } + + # ASK FOR THE FULL DRAFT NAVIGATION AND MERGE ALL SEPARATED NAVIGATIONS + public function getFullDraftNavigation($urlinfo, $language, $userrole = null, $username = null) + { + # get first level + $draftNavigation = $this->getDraftNavigation($urlinfo, $language, '/'); + + foreach($draftNavigation as $key => $item) + { + if($item->elementType == 'folder') + { + $subfolder = $this->getDraftNavigation($urlinfo, $language, $item->originalName); + + $draftNavigation[$key]->folderContent = $subfolder[$key]->folderContent; + } + } return $draftNavigation; } - public function getBasicDraftNavigation($urlinfo, $language) + # ASK FOR A STATIC DRAFT NAVIGATION AND CREATE ONE IF NOT THERE + public function getDraftNavigation($urlinfo, $language, $foldername) { - if(!$this->basicDraftNavigation) - { - $this->basicDraftNavigation = $this->createBasicDraftNavigation($urlinfo, $language); - } - return $this->basicDraftNavigation; - } + $draftFileName = $this->getDraftFileName($foldername); + $extendedFileName = $this->getExtendedFileName($foldername); - # creates a fresh structure with published and non-published pages for the author - public function createBasicDraftNavigation($urlinfo, $language) - { - # scan the content of the folder - $draftContentTree = $this->scanFolder($this->storage->getFolderPath('contentFolder'), $draft = true); + $draftNavigation = $this->getDraftNavigationFile($draftFileName); - # if there is content, then get the content details - if(count($draftContentTree) > 0) + if($draftNavigation) { - $draftNavigation = $this->getFolderContentDetails($draftContentTree, $language, $urlinfo['baseurl'], $urlinfo['basepath']); - return $draftNavigation; } - return false; - } - - # get the navigation with draft files for author environment - public function getLiveNavigation($urlinfo, $language, $userrole = null, $username = null) - { - # todo: filter for userrole or username - - $this->liveNavigation = $this->storage->getFile('dataFolder', $this->naviFolder, $this->liveNaviName, 'unserialize'); - - if($this->liveNavigation) + $rawDraftNavigation = $this->generateRawDraftNavigation($urlinfo, $language, $foldername); + if(!$rawDraftNavigation) { - return $this->liveNavigation; + return false; } - $draftNavigation = $this->getDraftNavigation($urlinfo, $language); + $extendedNavigation = $this->getExtendedNavigationFile($extendedFileName); + if(!$extendedNavigation) + { + $extendedNavigation = $this->generateExtendedFromDraft($rawDraftNavigation); - $basicLiveNavigation = $this->generateLiveNavigationFromDraft($draftNavigation); + if(!$extendedNavigation) + { + return false; + } + + $this->storeStaticNavigation($extendedFileName, $extendedNavigation); + } - # get the extended navigation with additional infos from the meta-files like title or hidden pages - $extendedNavigation = $this->getExtendedNavigation($urlinfo, $language); + $draftNavigation = $this->mergeExtendedWithDraft($rawDraftNavigation, $extendedNavigation); + if(!$draftNavigation) + { + return false; + } + + $this->storeStaticNavigation($draftFileName, $draftNavigation); - # merge the basic draft navi with the extended infos from meta-files - $liveNavigation = $this->mergeNavigationWithExtended($basicLiveNavigation, $extendedNavigation); + return $draftNavigation; + } - # cache it - $this->storage->writeFile('dataFolder', $this->naviFolder, $this->liveNaviName, $liveNavigation, 'serialize'); + public function getExtendedNavigation($urlinfo, $language, $foldername) + { + $draftFileName = $this->getDraftFileName($foldername); + $extendedFileName = $this->getExtendedFileName($foldername); - return $liveNavigation; + $extendedNavigation = $this->getExtendedNavigationFile($extendedFileName); + if($extendedNavigation) + { + return $extendedNavigation; + } + + $draftNavigation = $this->getDraftNavigationFile($draftFileName); + if(!$draftNavigation) + { + # we have to create and store extended and draft in this case + + $rawDraftNavigation = $this->generateRawDraftNavigation($urlinfo, $language, $foldername); + + if(!$rawDraftNavigation) + { + return false; + } + + $extendedNavigation = $this->generateExtendedFromDraft($rawDraftNavigation); + + if(!$extendedNavigation) + { + return false; + } + + $this->storeStaticNavigation($extendedFileName, $extendedNavigation); + + $draftNavigation = $this->mergeExtendedWithDraft($rawDraftNavigation, $extendedNavigation); + if(!$draftNavigation) + { + return false; + } + + $this->storeStaticNavigation($draftFileName, $draftNavigation); + + return $extendedNavigation; + } + + # we only have to create and store extended in this case + + $extendedNavigation = $this->generateExtendedFromDraft($draftNavigation); + + if(!$extendedNavigation) + { + return false; + } + + $this->storeStaticNavigation($extendedFileName, $extendedNavigation); + + return $extendedNavigation; } public function generateLiveNavigationFromDraft($draftNavigation) @@ -255,57 +401,69 @@ class Navigation extends Folder return $draftNavigation; } -/* - public function getBasicLiveNavigation($urlinfo, $language) + private function storeStaticNavigation($filename, $data) { - if(!$this->basicLiveNavigation) + if($filename == '.txt' OR $filename == '-extended.txt') { - $this->basicLiveNavigation = $this->createBasicLiveNavigation($urlinfo, $language); + return false; } - return $this->basicLiveNavigation; - } - public function createBasicLiveNavigation($urlinfo, $language) - { - # scan the content of the folder - $liveContentTree = $this->scanFolder($this->storage->getFolderPath('contentFolder'), $draft = false); - - # if there is content, then get the content details - if(count($liveContentTree) > 0) + if($this->storage->writeFile('dataFolder', $this->naviFolder, $filename, $data, 'serialize')) { - $liveNavigation = $this->getFolderContentDetails($liveContentTree, $language, $urlinfo['baseurl'], $urlinfo['basepath']); - - return $liveNavigation; + return true; } return false; } -*/ - - # get the extended navigation with additional infos from the meta-files like title or hidden pages - public function getExtendedNavigation($urlinfo, $language) + + # gets the cached draft navigation of a folder or of the first level + private function getDraftNavigationFile($filename) { - if(!$this->extendedNavigation) + $draftNavigation = $this->storage->getFile('dataFolder', $this->naviFolder, $filename, 'unserialize'); + + if($draftNavigation) { - # read the extended navi file - $this->extendedNavigation = $this->storage->getYaml('dataFolder', $this->naviFolder, $this->extendedNaviName); + return $draftNavigation; } - if(!$this->extendedNavigation) - { - $basicDraftNavigation = $this->getBasicDraftNavigation($urlinfo, $language); + return false; + } - $this->extendedNavigation = $this->createExtendedNavigation($basicDraftNavigation, $extended = NULL); - - # cache it - $this->storage->updateYaml('dataFolder', $this->naviFolder, $this->extendedNaviName, $this->extendedNavigation); + # generates a raw draft navigation + private function generateRawDraftNavigation($urlinfo, $language, $foldername = false) + { + # convert basefolder '/' to true + $flat = ($foldername == '/') ? true : $foldername; + + # scan the content of the folder + $draftContentTree = $this->scanFolder($this->storage->getFolderPath('contentFolder'), $flat); + + # if there is content, then get the content details + if(count($draftContentTree) > 0) + { + $draftNavigation = $this->getFolderContentDetails($draftContentTree, $language, $urlinfo['baseurl'], $urlinfo['basepath']); + + return $draftNavigation; } - return $this->extendedNavigation; + return false; + } + + # get the extended Navigation file for a folder or base + private function getExtendedNavigationFile($filename) + { + $extendedNavigation = $this->storage->getFile('dataFolder', $this->naviFolder, $filename, 'unserialize'); + + if($extendedNavigation) + { + return $extendedNavigation; + } + + return false; } # reads all meta-files and creates an array with url => ['hide' => bool, 'navtitle' => 'bla'] - public function createExtendedNavigation($navigation, $extended = NULL) + private function generateExtendedFromDraft($navigation, $extended = NULL) { if(!$extended) { @@ -337,30 +495,30 @@ class Navigation extends Folder if ($item->elementType == 'folder') { - $extended = $this->createExtendedNavigation($item->folderContent, $extended); + $extended = $this->generateExtendedFromDraft($item->folderContent, $extended); } } return $extended; } - # merge a basic navigation (live or draft) with extended information from meta - public function mergeNavigationWithExtended($navigation, $extended) + # takes a draft navigation and extended navigation and merges both + private function mergeExtendedWithDraft($draftNavigation, $extendedNavigation) { $mergedNavigation = []; - foreach($navigation as $key => $item) + foreach($draftNavigation as $key => $item) { - if($extended && isset($extended[$item->urlRelWoF])) + if($extendedNavigation && isset($extendedNavigation[$item->urlRelWoF])) { - $item->name = ($extended[$item->urlRelWoF]['navtitle'] != '') ? $extended[$item->urlRelWoF]['navtitle'] : $item->name; - $item->hide = ($extended[$item->urlRelWoF]['hide'] === true) ? true : false; - $item->noindex = (isset($extended[$item->urlRelWoF]['noindex']) && $extended[$item->urlRelWoF]['noindex'] === true) ? true : false; + $item->name = ($extendedNavigation[$item->urlRelWoF]['navtitle'] != '') ? $extendedNavigation[$item->urlRelWoF]['navtitle'] : $item->name; + $item->hide = ($extendedNavigation[$item->urlRelWoF]['hide'] === true) ? true : false; + $item->noindex = (isset($extendedNavigation[$item->urlRelWoF]['noindex']) && $extendedNavigation[$item->urlRelWoF]['noindex'] === true) ? true : false; } if($item->elementType == 'folder') { - $item->folderContent = $this->mergeNavigationWithExtended($item->folderContent, $extended); + $item->folderContent = $this->mergeExtendedWithDraft($item->folderContent, $extendedNavigation); } $mergedNavigation[$key] = $item; @@ -369,6 +527,30 @@ class Navigation extends Folder return $mergedNavigation; } + protected function getDraftFileName($foldername) + { + $draftFileName = $foldername; + + if($draftFileName == '/') + { + $draftFileName = $this->draftNaviName; + } + + return $draftFileName . '.txt'; + } + + protected function getExtendedFileName($foldername) + { + $draftFileName = $foldername; + + if($draftFileName == '/') + { + $draftFileName = $this->draftNaviName; + } + + return $draftFileName . '-extended.txt'; + } + public function getItemWithKeyPath($navigation, array $searchArray, $baseUrl = null) { $item = false; @@ -393,64 +575,6 @@ class Navigation extends Folder return $item; } - # NOT IN USE ANYMORE BUT KEEP IT - public function getItemWithUrl($navigation, $url, $result = NULL) - { - foreach($navigation as $key => $item) - { - # set item active, needed to move item in navigation - if($item->urlRelWoF === $url) - { - $result = $item; - break; - } - elseif($item->elementType === "folder") - { - $result = self::getItemWithUrl($item->folderContent, $url, $result); - - if($result) - { - break; - } - } - } - - return $result; - } - - - # NOT IN USE ANYMORE BUT KEEP IT - public function setActiveNaviItems($navigation, $breadcrumb) - { - if($breadcrumb) - { - foreach($breadcrumb as $crumbkey => $page) - { - foreach($navigation as $itemkey => $item) - { - if($page->urlRelWoF == $item->urlRelWoF) - { - unset($breadcrumb[$crumbkey]); - - if(empty($breadcrumb)) - { - $navigation[$itemkey]->active = true; - } - elseif(isset($navigation[$itemkey]->folderContent)) - { - $navigation[$itemkey]->activeParent = true; - $navigation[$itemkey]->folderContent = $this->setActiveNaviItems($navigation[$itemkey]->folderContent, $breadcrumb); - } - - break; - } - } - } - } - - return $navigation; - } - # used with scan folder that keeps index from draft version public function setActiveNaviItemsWithKeyPath($navigation, array $searchArray) { @@ -681,8 +805,73 @@ class Navigation extends Folder return $flat; } + # NOT IN USE ANYMORE BUT KEEP IT + public function getItemWithUrl($navigation, $url, $result = NULL) + { + die('getItemWithURL in navigation model not in use.'); + + foreach($navigation as $key => $item) + { + # set item active, needed to move item in navigation + if($item->urlRelWoF === $url) + { + $result = $item; + break; + } + elseif($item->elementType === "folder") + { + $result = self::getItemWithUrl($item->folderContent, $url, $result); + + if($result) + { + break; + } + } + } + + return $result; + } + + + # NOT IN USE ANYMORE BUT KEEP IT + public function setActiveNaviItems($navigation, $breadcrumb) + { + die('setActiveNaviItems in navigation model not in use.'); + + if($breadcrumb) + { + foreach($breadcrumb as $crumbkey => $page) + { + foreach($navigation as $itemkey => $item) + { + if($page->urlRelWoF == $item->urlRelWoF) + { + unset($breadcrumb[$crumbkey]); + + if(empty($breadcrumb)) + { + $navigation[$itemkey]->active = true; + } + elseif(isset($navigation[$itemkey]->folderContent)) + { + $navigation[$itemkey]->activeParent = true; + $navigation[$itemkey]->folderContent = $this->setActiveNaviItems($navigation[$itemkey]->folderContent, $breadcrumb); + } + + break; + } + } + } + } + + return $navigation; + } + + # NOT IN USE ANYMORE public function getLastItemOfFolder($folder) { + die('getLastItemOfFolder in navimodel not in use.'); + $lastItem = end($folder->folderContent); if(is_object($lastItem) && $lastItem->elementType == 'folder' && !empty($lastItem->folderContent)) { diff --git a/system/typemill/author/js/vue-blox.js b/system/typemill/author/js/vue-blox.js index 93696f3..1f16b8f 100644 --- a/system/typemill/author/js/vue-blox.js +++ b/system/typemill/author/js/vue-blox.js @@ -66,6 +66,8 @@ const bloxeditor = Vue.createApp({ }, onEnd(evt) { + self = this; + tmaxios.put('/api/v1/block/move',{ 'url': data.urlinfo.route, 'index_old': evt.oldIndex, @@ -74,12 +76,24 @@ const bloxeditor = Vue.createApp({ .then(function (response) { self.content = response.data.content; + if(response.data.navigation) + { + eventBus.$emit('navigation', response.data.navigation); + } + if(response.data.item) + { + eventBus.$emit('item', response.data.item); + } }) .catch(function (error) { if(error.response) { - eventBus.$emit('publishermessage', error.response.data.message); + let message = handleErrorMessage(error); + if(message) + { + eventBus.$emit('publishermessage', message); + } } }); }, diff --git a/system/typemill/settings/system.yaml b/system/typemill/settings/system.yaml index 938260d..19faf7c 100644 --- a/system/typemill/settings/system.yaml +++ b/system/typemill/settings/system.yaml @@ -57,6 +57,11 @@ fieldsetsystem: css: lg:w-half disabled: true description: 'Submit the url above in google search console to support indexing.' + disableSitemap: + type: checkbox + css: lg:w-half + label: 'Disable Sitemap Generation' + checkboxlabel: 'Disable Sitemap generation to improve the performance for publish action.' fieldsetmedia: type: fieldset legend: Media