From a4c32dd4d79de30af2bf2c7e5310a6415141eabe Mon Sep 17 00:00:00 2001 From: trendschau Date: Sun, 14 Apr 2024 21:25:36 +0200 Subject: [PATCH 1/2] V2.4.0 Refactor cached navigation to improve performance --- content/00-welcome/00-setup-your-website.md | 2 +- content/00-welcome/00-setup-your-website.yaml | 4 +- content/00-welcome/04-markdown-test.md | 57 ++ content/00-welcome/index.md | 2 +- ...ent-elements.md => 04-content-elements.md} | 0 .../01-cyanine-theme/04-content-elements.yaml | 9 + content/01-cyanine-theme/index.md | 2 +- data/navigation/navi-draft.txt | 1 - data/navigation/navi-extended.txt | 66 -- system/typemill/Controllers/Controller.php | 60 +- .../ControllerApiAuthorArticle.php | 192 ++++-- .../Controllers/ControllerApiAuthorBlock.php | 42 +- .../Controllers/ControllerApiAuthorMeta.php | 95 ++- .../Controllers/ControllerWebAuthor.php | 16 +- .../Controllers/ControllerWebFrontend.php | 9 +- system/typemill/Models/Folder.php | 72 +-- system/typemill/Models/Navigation.php | 589 ++++++++++++------ system/typemill/author/js/vue-blox.js | 16 +- system/typemill/settings/system.yaml | 5 + 19 files changed, 756 insertions(+), 483 deletions(-) rename content/01-cyanine-theme/{03-content-elements.md => 04-content-elements.md} (100%) create mode 100644 content/01-cyanine-theme/04-content-elements.yaml delete mode 100644 data/navigation/navi-draft.txt delete mode 100644 data/navigation/navi-extended.txt diff --git a/content/00-welcome/00-setup-your-website.md b/content/00-welcome/00-setup-your-website.md index 4ec3aa8..13a3396 100644 --- a/content/00-welcome/00-setup-your-website.md +++ b/content/00-welcome/00-setup-your-website.md @@ -1,6 +1,6 @@ # Setup Your Website -Typemill provides detailed settings, and you have access to nearly all settings in the author panel. Learn the basics in this short video: mod +Typemill provides detailed settings, and you have access to nearly all settings in the author panel. Learn the basics in this short video: ![youtube-video](media/live/youtube-7yvlwxjl9dc.jpeg "click to load video"){#7yvlwXJL9dc .youtube} diff --git a/content/00-welcome/00-setup-your-website.yaml b/content/00-welcome/00-setup-your-website.yaml index 8940a3d..285f21e 100644 --- a/content/00-welcome/00-setup-your-website.yaml +++ b/content/00-welcome/00-setup-your-website.yaml @@ -3,10 +3,10 @@ meta: title: 'Setup your website' description: ' You will find all configurations and settings under the main navigation point settings with the following sub-navigation:' owner: Sebastian - manualdate: '2023-11-22' + author: Sebastian + manualdate: '2024-11-04' modified: '2023-10-23' created: '2023-06-12' time: 15-18-48 hide: false noindex: false - author: Sebastian diff --git a/content/00-welcome/04-markdown-test.md b/content/00-welcome/04-markdown-test.md index 359ca52..fbdfcbc 100644 --- a/content/00-welcome/04-markdown-test.md +++ b/content/00-welcome/04-markdown-test.md @@ -29,6 +29,9 @@ Headlines are simply done with hash chars like this: + + + ### Third Level Headline A third headline is more decent and lower prioritized than a second level headline. @@ -57,6 +60,9 @@ A paragraph is a simple text-block separated with a new line above and below. + + + A paragraph is a simple text-block separated with a new line above and below. ## Soft Linebreak @@ -73,6 +79,9 @@ He said: "again" + + + For a soft linebreak (eg. for dialoges in literature), add two spaces at the end of a line and use a simple return. She said: "Hello" @@ -91,6 +100,9 @@ For bold text use two **asterix** or two __underscores__. + + + For italic text use one *asterix* or one _underscore_. For bold text use two **asterix** or two __underscores__. @@ -115,6 +127,9 @@ For an ordered list use whatever number you want and add a dot: + + + For an unordered list use a dash * like @@ -143,6 +158,9 @@ Easily created for example with three dashes like this: + + + Easily created for example with three dashes like this: --- @@ -163,6 +181,9 @@ You can even use a download-link like []() + + + This is an ordinary [Link](http://typemill.net). Links can also be [relative](/info). @@ -194,6 +215,9 @@ The same rules as with links, but with a ! + + + The same rules as with links, but with a ! ![](media/tmp/kai-dahms-v0nbnxlwjzk-3unsp-1.webp) @@ -216,6 +240,9 @@ You can link an image with a nested syntax like this: + + + You can link an image with a nested syntax like this: [![alt-text](media/files/markdown.png){.imgClass}](https://typemill.net) @@ -238,6 +265,9 @@ You can controll the image position with the classes .left, .right and .middle l + + + ![](media/tmp/kai-dahms-v0nbnxlwjzk-3unsp-1.webp) The first image should float on the left side of this paragraph. This might not work with all themes. If you are a theme developer, please ensure that you support the image classes "left", "right" and "center". You can add these classes manually in the raw mode or you can assign them in the visual mode when you edit a picture (double click on it to open the dialog). Images in a separate line are rendered with the html5 elements `figure` and `figcapture`. @@ -265,6 +295,9 @@ There are always some women and men with wise words + + + There always some women and men with wise words > But I usually don't read them, to be honest. @@ -285,6 +318,9 @@ Add the footnote text at the bottom of the page like this: + + + You can write footnotes[^1] with markdown. Scroll down to the end of the page[^2] and look for the footnotes. @@ -304,6 +340,9 @@ Footnotes won't work with the visual editor right now, so please use the raw mod + + + You won't see the abbreviation directly, but if you write HTML or W3C somewhere, then you can see the tooltip with the explanation. *[HTML]: Hyper Text Markup Language @@ -325,6 +364,9 @@ Orange + + + Apple : Pomaceous fruit of plants of the genus Malus in the family Rosaceae. @@ -363,6 +405,9 @@ You can create different notices if you add a '!', '!!', '!!!', '!!!!' before a + + + | Name | Usage | |---|---| | My Name | For Me | @@ -380,6 +425,9 @@ Let us create some `` like this + + + Let us create some `` and now let us check, if a codeblock works: ```` @@ -398,6 +446,9 @@ Use four apostroph like this: + + + ## Math Please activate the math-plugin to use mathematical expressions with LaTeX syntax. You can choose between MathJax or the newer KaTeX library. MathJax is included from a CDN, KaTeX is included in the plugin. So if you don't want to fetch code from a CDN, use KaTeX instead. The markdown syntax in TYPEMILL is the same for both libraries. @@ -414,6 +465,9 @@ inline \(x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)\) math + + + inline $x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)$ math inline \(x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)\) math @@ -434,6 +488,9 @@ x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a) + + + $$ x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a) $$ diff --git a/content/00-welcome/index.md b/content/00-welcome/index.md index eca2d6f..dcca197 100644 --- a/content/00-welcome/index.md +++ b/content/00-welcome/index.md @@ -1,4 +1,4 @@ # Welcome -Great that you give Typemill a try!! Typemill is a simple Flat File Content Management System (CMS). We (the community) work hard to provide the best author experience with easy and intuitive authoring tools. But Typemill is still in early development and it is likely that not everything will work perfectly out of the box. If you miss something or if you have ideas for improvements, then post a new issue on [GitHub](https://github.com/typemill/typemill/issues).mb +Great that you give Typemill a try!! Typemill is a simple Flat File Content Management System (CMS). We (the community) work hard to provide the best author experience with easy and intuitive authoring tools. But Typemill is still in early development and it is likely that not everything will work perfectly out of the box. If you miss something or if you have ideas for improvements, then post a new issue on [GitHub](https://github.com/typemill/typemill/issues). diff --git a/content/01-cyanine-theme/03-content-elements.md b/content/01-cyanine-theme/04-content-elements.md similarity index 100% rename from content/01-cyanine-theme/03-content-elements.md rename to content/01-cyanine-theme/04-content-elements.md diff --git a/content/01-cyanine-theme/04-content-elements.yaml b/content/01-cyanine-theme/04-content-elements.yaml new file mode 100644 index 0000000..55940f3 --- /dev/null +++ b/content/01-cyanine-theme/04-content-elements.yaml @@ -0,0 +1,9 @@ +meta: + navtitle: 'content elements' + owner: Sebastian + created: '2023-06-12' + time: 22-36-50 + modified: '2021-11-24' + title: 'Cyanine provides a lot of other settings for your content area. For example:' + description: "\nAdd an edit-button for github, gitlab or other plattforms.\nShow the author.\nShow the publish date.\nShow the chapter numbers in the navigation.\n" + author: Sebastian diff --git a/content/01-cyanine-theme/index.md b/content/01-cyanine-theme/index.md index dcd9d6c..b4f5b98 100644 --- a/content/01-cyanine-theme/index.md +++ b/content/01-cyanine-theme/index.md @@ -1,6 +1,6 @@ # The Cyanine Theme -Cyanine is the modern, lightweight and flexible standard theme for Typemill. You can activate a landingpage, setup different content sections for the landingpage and order them like you want. You can also change the colors, fonts and other details. To configure the theme, login to the system (/tm/login), go to the theme settings (/tm/themes) and choose the theme "Cyanine". +Cyanine is the modern, lightweight and flexible standard theme for Typemill. You can activate a landingpage, setup different content sections for the landingpage and order them like you want. You can also change the colors, fonts and other details. To configure the theme, login to the system (/tm/login), go to the theme settings (/tm/themes) and choose the theme "Cyanine" If Cyanine does not fit to your needs, then you can also choose another theme in the [theme store](https://themes.typemill.net) of Typemill. diff --git a/data/navigation/navi-draft.txt b/data/navigation/navi-draft.txt deleted file mode 100644 index 84fcabc..0000000 --- a/data/navigation/navi-draft.txt +++ /dev/null @@ -1 +0,0 @@ -a:2:{i:0;O:8:"stdClass":22:{s:12:"originalName";s:10:"00-welcome";s:11:"elementType";s:6:"folder";s:8:"contains";s:5:"pages";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"00";s:4:"name";s:7:"welcome";s:4:"slug";s:7:"welcome";s:4:"path";s:11:"/00-welcome";s:15:"pathWithoutType";s:17:"/00-welcome/index";s:9:"urlRelWoF";s:8:"/welcome";s:6:"urlRel";s:17:"/typemill/welcome";s:6:"urlAbs";s:33:"http://localhost/typemill/welcome";s:3:"key";i:0;s:7:"keyPath";i:0;s:12:"keyPathArray";a:1:{i:0;s:1:"0";}s:7:"chapter";i:1;s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:13:"folderContent";a:5:{i:0;O:8:"stdClass":20:{s:12:"originalName";s:24:"00-setup-your-website.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"00";s:4:"name";s:18:"setup your website";s:4:"slug";s:18:"setup-your-website";s:4:"path";s:36:"/00-welcome/00-setup-your-website.md";s:15:"pathWithoutType";s:33:"/00-welcome/00-setup-your-website";s:3:"key";i:0;s:7:"keyPath";s:3:"0.0";s:12:"keyPathArray";a:2:{i:0;s:1:"0";i:1;s:1:"0";}s:7:"chapter";s:3:"1.1";s:9:"urlRelWoF";s:27:"/welcome/setup-your-website";s:6:"urlRel";s:36:"/typemill/welcome/setup-your-website";s:6:"urlAbs";s:52:"http://localhost/typemill/welcome/setup-your-website";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}i:1;O:8:"stdClass":20:{s:12:"originalName";s:19:"01-write-content.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"01";s:4:"name";s:13:"write content";s:4:"slug";s:13:"write-content";s:4:"path";s:31:"/00-welcome/01-write-content.md";s:15:"pathWithoutType";s:28:"/00-welcome/01-write-content";s:3:"key";i:1;s:7:"keyPath";s:3:"0.1";s:12:"keyPathArray";a:2:{i:0;s:1:"0";i:1;s:1:"1";}s:7:"chapter";s:3:"1.2";s:9:"urlRelWoF";s:22:"/welcome/write-content";s:6:"urlRel";s:31:"/typemill/welcome/write-content";s:6:"urlAbs";s:47:"http://localhost/typemill/welcome/write-content";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}i:2;O:8:"stdClass":20:{s:12:"originalName";s:19:"02-manage-access.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"02";s:4:"name";s:13:"manage access";s:4:"slug";s:13:"manage-access";s:4:"path";s:31:"/00-welcome/02-manage-access.md";s:15:"pathWithoutType";s:28:"/00-welcome/02-manage-access";s:3:"key";i:2;s:7:"keyPath";s:3:"0.2";s:12:"keyPathArray";a:2:{i:0;s:1:"0";i:1;s:1:"2";}s:7:"chapter";s:3:"1.3";s:9:"urlRelWoF";s:22:"/welcome/manage-access";s:6:"urlRel";s:31:"/typemill/welcome/manage-access";s:6:"urlAbs";s:47:"http://localhost/typemill/welcome/manage-access";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}i:3;O:8:"stdClass":20:{s:12:"originalName";s:14:"03-get-help.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"03";s:4:"name";s:8:"get help";s:4:"slug";s:8:"get-help";s:4:"path";s:26:"/00-welcome/03-get-help.md";s:15:"pathWithoutType";s:23:"/00-welcome/03-get-help";s:3:"key";i:3;s:7:"keyPath";s:3:"0.3";s:12:"keyPathArray";a:2:{i:0;s:1:"0";i:1;s:1:"3";}s:7:"chapter";s:3:"1.4";s:9:"urlRelWoF";s:17:"/welcome/get-help";s:6:"urlRel";s:26:"/typemill/welcome/get-help";s:6:"urlAbs";s:42:"http://localhost/typemill/welcome/get-help";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}i:4;O:8:"stdClass":20:{s:12:"originalName";s:19:"04-markdown-test.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"04";s:4:"name";s:13:"markdown test";s:4:"slug";s:13:"markdown-test";s:4:"path";s:31:"/00-welcome/04-markdown-test.md";s:15:"pathWithoutType";s:28:"/00-welcome/04-markdown-test";s:3:"key";i:4;s:7:"keyPath";s:3:"0.4";s:12:"keyPathArray";a:2:{i:0;s:1:"0";i:1;s:1:"4";}s:7:"chapter";s:3:"1.5";s:9:"urlRelWoF";s:22:"/welcome/markdown-test";s:6:"urlRel";s:31:"/typemill/welcome/markdown-test";s:6:"urlAbs";s:47:"http://localhost/typemill/welcome/markdown-test";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}}s:7:"noindex";b:0;}i:1;O:8:"stdClass":22:{s:12:"originalName";s:16:"01-cyanine-theme";s:11:"elementType";s:6:"folder";s:8:"contains";s:5:"pages";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"01";s:4:"name";s:13:"cyanine theme";s:4:"slug";s:13:"cyanine-theme";s:4:"path";s:17:"/01-cyanine-theme";s:15:"pathWithoutType";s:23:"/01-cyanine-theme/index";s:9:"urlRelWoF";s:14:"/cyanine-theme";s:6:"urlRel";s:23:"/typemill/cyanine-theme";s:6:"urlAbs";s:39:"http://localhost/typemill/cyanine-theme";s:3:"key";i:1;s:7:"keyPath";i:1;s:12:"keyPathArray";a:1:{i:0;s:1:"1";}s:7:"chapter";i:2;s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:13:"folderContent";a:4:{i:0;O:8:"stdClass":20:{s:12:"originalName";s:17:"00-landingpage.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"00";s:4:"name";s:11:"landingpage";s:4:"slug";s:11:"landingpage";s:4:"path";s:35:"/01-cyanine-theme/00-landingpage.md";s:15:"pathWithoutType";s:32:"/01-cyanine-theme/00-landingpage";s:3:"key";i:0;s:7:"keyPath";s:3:"1.0";s:12:"keyPathArray";a:2:{i:0;s:1:"1";i:1;s:1:"0";}s:7:"chapter";s:3:"2.1";s:9:"urlRelWoF";s:26:"/cyanine-theme/landingpage";s:6:"urlRel";s:35:"/typemill/cyanine-theme/landingpage";s:6:"urlAbs";s:51:"http://localhost/typemill/cyanine-theme/landingpage";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:1;}i:1;O:8:"stdClass":20:{s:12:"originalName";s:22:"01-colors-and-fonts.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"01";s:4:"name";s:16:"colors and fonts";s:4:"slug";s:16:"colors-and-fonts";s:4:"path";s:40:"/01-cyanine-theme/01-colors-and-fonts.md";s:15:"pathWithoutType";s:37:"/01-cyanine-theme/01-colors-and-fonts";s:3:"key";i:1;s:7:"keyPath";s:3:"1.1";s:12:"keyPathArray";a:2:{i:0;s:1:"1";i:1;s:1:"1";}s:7:"chapter";s:3:"2.2";s:9:"urlRelWoF";s:31:"/cyanine-theme/colors-and-fonts";s:6:"urlRel";s:40:"/typemill/cyanine-theme/colors-and-fonts";s:6:"urlAbs";s:56:"http://localhost/typemill/cyanine-theme/colors-and-fonts";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}i:2;O:8:"stdClass":20:{s:12:"originalName";s:12:"02-footer.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"02";s:4:"name";s:6:"footer";s:4:"slug";s:6:"footer";s:4:"path";s:30:"/01-cyanine-theme/02-footer.md";s:15:"pathWithoutType";s:27:"/01-cyanine-theme/02-footer";s:3:"key";i:2;s:7:"keyPath";s:3:"1.2";s:12:"keyPathArray";a:2:{i:0;s:1:"1";i:1;s:1:"2";}s:7:"chapter";s:3:"2.3";s:9:"urlRelWoF";s:21:"/cyanine-theme/footer";s:6:"urlRel";s:30:"/typemill/cyanine-theme/footer";s:6:"urlAbs";s:46:"http://localhost/typemill/cyanine-theme/footer";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}i:3;O:8:"stdClass":20:{s:12:"originalName";s:22:"03-content-elements.md";s:11:"elementType";s:4:"file";s:6:"status";s:9:"published";s:8:"fileType";s:2:"md";s:5:"order";s:2:"03";s:4:"name";s:16:"content elements";s:4:"slug";s:16:"content-elements";s:4:"path";s:40:"/01-cyanine-theme/03-content-elements.md";s:15:"pathWithoutType";s:37:"/01-cyanine-theme/03-content-elements";s:3:"key";i:3;s:7:"keyPath";s:3:"1.3";s:12:"keyPathArray";a:2:{i:0;s:1:"1";i:1;s:1:"3";}s:7:"chapter";s:3:"2.4";s:9:"urlRelWoF";s:31:"/cyanine-theme/content-elements";s:6:"urlRel";s:40:"/typemill/cyanine-theme/content-elements";s:6:"urlAbs";s:56:"http://localhost/typemill/cyanine-theme/content-elements";s:6:"active";b:0;s:12:"activeParent";b:0;s:4:"hide";b:0;s:7:"noindex";b:0;}}s:7:"noindex";b:0;}} \ No newline at end of file diff --git a/data/navigation/navi-extended.txt b/data/navigation/navi-extended.txt deleted file mode 100644 index 69087af..0000000 --- a/data/navigation/navi-extended.txt +++ /dev/null @@ -1,66 +0,0 @@ -/welcome: - navtitle: welcome - hide: false - noindex: false - path: /00-welcome - keyPath: 0 -/welcome/setup-your-website: - navtitle: 'setup your website' - hide: false - noindex: false - path: /00-welcome/00-setup-your-website.md - keyPath: '0.0' -/welcome/write-content: - navtitle: 'write content' - hide: false - noindex: false - path: /00-welcome/01-write-content.md - keyPath: '0.1' -/welcome/manage-access: - navtitle: 'manage access' - hide: false - noindex: false - path: /00-welcome/02-manage-access.md - keyPath: '0.2' -/welcome/get-help: - navtitle: 'get help' - hide: false - noindex: false - path: /00-welcome/03-get-help.md - keyPath: '0.3' -/welcome/markdown-test: - navtitle: 'markdown test' - hide: false - noindex: false - path: /00-welcome/04-markdown-test.md - keyPath: '0.4' -/cyanine-theme: - navtitle: 'cyanine theme' - hide: false - noindex: false - path: /01-cyanine-theme - keyPath: 1 -/cyanine-theme/landingpage: - navtitle: landingpage - hide: false - noindex: true - path: /01-cyanine-theme/00-landingpage.md - keyPath: '1.0' -/cyanine-theme/colors-and-fonts: - navtitle: 'colors and fonts' - hide: false - noindex: false - path: /01-cyanine-theme/01-colors-and-fonts.md - keyPath: '1.1' -/cyanine-theme/footer: - navtitle: footer - hide: false - noindex: false - path: /01-cyanine-theme/02-footer.md - keyPath: '1.2' -/cyanine-theme/content-elements: - navtitle: 'content elements' - hide: false - noindex: false - path: /01-cyanine-theme/03-content-elements.md - keyPath: '1.3' 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 From e37b1772dd8dd524e10c698e5bf6b6693cbcb9d4 Mon Sep 17 00:00:00 2001 From: trendschau Date: Sun, 14 Apr 2024 21:26:49 +0200 Subject: [PATCH 2/2] Reorder pages --- .../{04-content-elements.md => 02-content-elements.md} | 0 ...04-content-elements.yaml => 02-content-elements.yaml} | 0 content/01-cyanine-theme/{02-footer.md => 03-footer.md} | 0 content/01-cyanine-theme/03-footer.yaml | 9 +++++++++ 4 files changed, 9 insertions(+) rename content/01-cyanine-theme/{04-content-elements.md => 02-content-elements.md} (100%) rename content/01-cyanine-theme/{04-content-elements.yaml => 02-content-elements.yaml} (100%) rename content/01-cyanine-theme/{02-footer.md => 03-footer.md} (100%) create mode 100644 content/01-cyanine-theme/03-footer.yaml diff --git a/content/01-cyanine-theme/04-content-elements.md b/content/01-cyanine-theme/02-content-elements.md similarity index 100% rename from content/01-cyanine-theme/04-content-elements.md rename to content/01-cyanine-theme/02-content-elements.md diff --git a/content/01-cyanine-theme/04-content-elements.yaml b/content/01-cyanine-theme/02-content-elements.yaml similarity index 100% rename from content/01-cyanine-theme/04-content-elements.yaml rename to content/01-cyanine-theme/02-content-elements.yaml diff --git a/content/01-cyanine-theme/02-footer.md b/content/01-cyanine-theme/03-footer.md similarity index 100% rename from content/01-cyanine-theme/02-footer.md rename to content/01-cyanine-theme/03-footer.md diff --git a/content/01-cyanine-theme/03-footer.yaml b/content/01-cyanine-theme/03-footer.yaml new file mode 100644 index 0000000..650a993 --- /dev/null +++ b/content/01-cyanine-theme/03-footer.yaml @@ -0,0 +1,9 @@ +meta: + navtitle: footer + owner: Sebastian + created: '2023-06-12' + time: 21-41-25 + modified: '2021-05-18' + description: 'Cyanine provides a three column footer at the bottom of each page. You can use markdown for each column. Make sure that you use the correct headline-level (we' + title: '3-Column Footer' + author: Sebastian