From a3f420ef7b15008b2d88c6975e66755fb270d095 Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Mon, 8 Jan 2024 00:19:15 +0100 Subject: [PATCH] delete linkto cache replace recursive render - small admin interface improvements --- MANUAL.md | 10 +-- app/class/Config.php | 10 +-- app/class/Controllerhome.php | 3 +- app/class/Controllerpage.php | 157 +++++++++++++++++------------------ app/class/Fs.php | 2 + app/class/Modelpage.php | 39 +++++---- app/class/Page.php | 4 +- app/view/templates/admin.php | 77 +++++++++++++---- assets/css/admin.css | 21 +++++ assets/css/base.css | 2 +- 10 files changed, 200 insertions(+), 125 deletions(-) create mode 100644 assets/css/admin.css diff --git a/MANUAL.md b/MANUAL.md index 773356ae..33c366b0 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -638,7 +638,7 @@ Where `*` is the page ID of the rendered page. %?tag=(0|1)% This will determine if HTML tags will be printed around included element. This may be usefull for advanced users to achieve more precise HTML editing. -The default behavior can be set globaly in the [admin panel](#admin). +The default behavior can be set globaly in the [admin panel](#administration). Example : @@ -698,7 +698,7 @@ This settings is deactivated by default. %?urllinker=(0|1)% -URL Linker is a tool that will transform a plain text URL into a link. This can be enabled or disabled specificly for each elements. The default behavior can be set globaly in the [admin panel](#admin). +URL Linker is a tool that will transform a plain text URL into a link. This can be enabled or disabled specificly for each elements. The default behavior can be set globaly in the [admin panel](#administration). ##### Everylink @@ -860,7 +860,7 @@ CSS properties for weight only use `normal` and `bold` as absolute values. other This contain two files: -- the `global.css` file, that admins can edit in the [admin panel](#admin). +- the `global.css` file, that admins can edit in the [admin panel](#administration). - the `fonts.css` file, that is automatcly generated according to content of [fonts folder](#fonts-folder). @@ -904,7 +904,7 @@ Acces to admin menu is reserved to [admin](#administrator) users. ### Theming -You change the interface theme in the [admin panel](#admin), under *interface*. There is a kit of presets, but you can even add your own themes ! And it is actualy *super easy* 😎. To do so, go to the folder `/assets/css/themes/` and duplicate one of the preset you prefer. Then you can edit the CSS variables to quickly stylise your theme colors. +You change the interface theme in the [admin panel](#administration), under *interface*. There is a kit of presets, but you can even add your own themes ! And it is actualy *super easy* 😎. To do so, go to the folder `/assets/css/themes/` and duplicate one of the preset you prefer. Then you can edit the CSS variables to quickly stylise your theme colors. @@ -1111,7 +1111,7 @@ Invite Editors are the lowest editor status possible. They can only access the [ > level : 10 -- Can access the [admin interface](#admin). +- Can access the [admin interface](#administration). - Can create new users. ### URL based command interface diff --git a/app/class/Config.php b/app/class/Config.php index 7b7f2f3d..c805adba 100644 --- a/app/class/Config.php +++ b/app/class/Config.php @@ -27,7 +27,7 @@ abstract class Config protected static $externallinkblank = true; protected static $internallinkblank = false; protected static $urllinker = true; - protected static $recursiverender = true; + protected static bool $deletelinktocache = true; protected static $defaultprivacy = 0; protected static $homepage = 'default'; protected static $homeredirect = null; @@ -280,9 +280,9 @@ public static function urllinker(): bool return self::$urllinker; } - public static function recursiverender() + public static function deletelinktocache(): bool { - return self::$recursiverender; + return self::$deletelinktocache; } public static function defaultprivacy() @@ -501,9 +501,9 @@ public static function seturllinker($urllinker) self::$urllinker = boolval($urllinker); } - public static function setrecursiverender($recursiverender) + public static function setdeletelinktocache($deletelinktocache) { - self::$recursiverender = boolval($recursiverender); + self::$deletelinktocache = boolval($deletelinktocache); } public static function setdefaultprivacy($defaultprivacy) diff --git a/app/class/Controllerhome.php b/app/class/Controllerhome.php index 92e8a7b6..87d96d57 100644 --- a/app/class/Controllerhome.php +++ b/app/class/Controllerhome.php @@ -238,6 +238,7 @@ public function flushrendercache(): void Model::sendflashmessage('Render cache successfully deleted', Model::FLASH_SUCCESS); } catch (RuntimeException $e) { Model::sendflashmessage($e->getMessage(), Model::FLASH_ERROR); + Logger::errorex($e); } $this->routedirect('home'); } @@ -318,7 +319,7 @@ public function multidelete() $total = count($pagelist); $count = 0; foreach ($pagelist as $id) { - if ($this->pagemanager->delete($id)) { + if ($this->pagemanager->delete(new Pagev2(['id' => $id]))) { $count++; } } diff --git a/app/class/Controllerpage.php b/app/class/Controllerpage.php index 6cdaabb1..7249a463 100644 --- a/app/class/Controllerpage.php +++ b/app/class/Controllerpage.php @@ -73,9 +73,6 @@ public function render($page) $this->setpage($page, 'pageupdate'); if ($this->importpage() && $this->user->iseditor()) { - if (Config::recursiverender()) { - $this->recursiverender($this->page); - } $this->page = $this->pagemanager->renderpage($this->page, $this->router); $this->pagemanager->update($this->page); $this->templaterender($this->page); @@ -85,16 +82,15 @@ public function render($page) } /** - * Render all other pages that are linked from this page + * Delete render cache of all related pages + * + * @param string[] $relatedpages List of page ids */ - public function recursiverender(Page $page): void + public function deletelinktocache(array $relatedpages): void { - $relatedpages = array_diff($page->linkto(), [$page->id()]); foreach ($relatedpages as $pageid) { try { - $page = $this->pagemanager->get($pageid); - $page = $this->pagemanager->renderpage($page, $this->router); - $this->pagemanager->update($page); + $this->pagemanager->unlink($pageid); } catch (RuntimeException $e) { Logger::errorex($e, true); } @@ -102,9 +98,11 @@ public function recursiverender(Page $page): void } /** - * Render all page templates if they need to + * Render page's JS and CSS templates if they need to * * @param Page $page page to check templates + * + * @todo Move this function in Modelpage */ private function templaterender(Page $page) { @@ -138,89 +136,88 @@ private function templaterender(Page $page) public function read($page) { $this->setpage($page, 'pageread'); - - $pageexist = $this->importpage(); - $canread = false; - $needtoberendered = false; $filedir = Model::HTML_RENDER_DIR . $page . '.html'; + $reccursiverender = false; - if ($pageexist) { - $canread = $this->user->level() >= $this->page->secure(); + if (!$this->importpage()) { + http_response_code(404); + $this->showtemplate( + 'alertexistnot', + ['page' => $this->page, 'subtitle' => Config::existnot()] + ); + exit; + } - // Check page password - if (!empty($this->page->password())) { - if (empty($_POST['pagepassword']) || $_POST['pagepassword'] !== $this->page->password()) { - $this->showtemplate('pagepassword', ['pageid' => $this->page->id()]); - exit; - } + // Check page password + if (!empty($this->page->password())) { + if (empty($_POST['pagepassword']) || $_POST['pagepassword'] !== $this->page->password()) { + $this->showtemplate('pagepassword', ['pageid' => $this->page->id()]); + exit; } + } - if ($canread) { - if ($this->pagemanager->needtoberendered($this->page)) { - $this->page = $this->pagemanager->renderpage($this->page, $this->router); - $needtoberendered = true; - } - $this->templaterender($this->page); - - - $this->page->adddisplaycount(); - if ($this->user->isvisitor()) { - $this->page->addvisitcount(); - } - - // redirection using Location and 302 - if (!empty($this->page->redirection()) && $this->page->refresh() === 0 && $this->page->sleep() === 0) { - try { - if (Model::idcheck($this->page->redirection())) { - $this->routedirect('pageread', ['page' => $this->page->redirection()]); - } else { - $url = getfirsturl($this->page->redirection()); - $this->redirect($url); - } - } catch (RuntimeException $e) { - // TODO : send synthax error to editor - } - } - $html = file_get_contents($filedir); + if ($this->user->level() < $this->page->secure()) { + http_response_code(403); + switch ($this->page->secure()) { + case Page::NOT_PUBLISHED: + $this->showtemplate( + 'alertnotpublished', + ['page' => $this->page, 'subtitle' => Config::notpublished()] + ); + break; + + case Page::PRIVATE: + $this->showtemplate( + 'alertprivate', + ['page' => $this->page, 'subtitle' => Config::private()] + ); + break; + } + exit; + } - $postprocessor = new Servicepostprocess($this->page, $this->user); - $html = $postprocessor->process($html); + if ($this->pagemanager->needtoberendered($this->page)) { + if (Config::deletelinktocache() && $this->page->daterender() <= $this->page->datemodif()) { + $oldlinkto = $this->page->linkto(); + } + $this->page = $this->pagemanager->renderpage($this->page, $this->router); + if (isset($oldlinkto)) { + $relatedpages = array_unique(array_merge($oldlinkto, $this->page->linkto())); + $this->deletelinktocache($relatedpages); + } + } - sleep($this->page->sleep()); + $this->templaterender($this->page); - echo $html; - $this->pagemanager->update($this->page); + $this->page->adddisplaycount(); + if ($this->user->isvisitor()) { + $this->page->addvisitcount(); + } - if ($needtoberendered && Config::recursiverender()) { - $this->recursiverender($this->page); - } - } else { - http_response_code(403); - switch ($this->page->secure()) { - case Page::NOT_PUBLISHED: - $this->showtemplate( - 'alertnotpublished', - ['page' => $this->page, 'subtitle' => Config::notpublished()] - ); - break; - - case Page::PRIVATE: - $this->showtemplate( - 'alertprivate', - ['page' => $this->page, 'subtitle' => Config::private()] - ); - break; + // redirection using Location and 302 + if (!empty($this->page->redirection()) && $this->page->refresh() === 0 && $this->page->sleep() === 0) { + try { + if (Model::idcheck($this->page->redirection())) { + $this->routedirect('pageread', ['page' => $this->page->redirection()]); + } else { + $url = getfirsturl($this->page->redirection()); + $this->redirect($url); } - exit; + } catch (RuntimeException $e) { + // TODO : send synthax error to editor } - } else { - http_response_code(404); - $this->showtemplate( - 'alertexistnot', - ['page' => $this->page, 'subtitle' => Config::existnot()] - ); } + $html = file_get_contents($filedir); + + $postprocessor = new Servicepostprocess($this->page, $this->user); + $html = $postprocessor->process($html); + + sleep($this->page->sleep()); + + echo $html; + + $this->pagemanager->update($this->page); } public function edit($page) diff --git a/app/class/Fs.php b/app/class/Fs.php index 7ef9c573..18f75f79 100644 --- a/app/class/Fs.php +++ b/app/class/Fs.php @@ -176,6 +176,8 @@ public static function recursecopy($src, $dst, $perm = Model::FOLDER_PERMISSION) * @throws Notfoundexception If file does not exist * @throws Fileexception If file cannot be deleted * @throws Unlinkexception If PHP unlink function fails for another reason + * + * @todo Maybe do not send Notfoundexception */ public static function deletefile(string $file): void { diff --git a/app/class/Modelpage.php b/app/class/Modelpage.php index d3c5209c..be75f268 100644 --- a/app/class/Modelpage.php +++ b/app/class/Modelpage.php @@ -67,7 +67,7 @@ public function pagelistbyid(array $idlist = []): array $pagelist = []; foreach ($pagedatalist as $id => $pagedata) { try { - $this->pagelist[$id] = $this->parsepage($pagedata); + $pagelist[$id] = $this->parsepage($pagedata); } catch (RuntimeException $e) { Logger::error("Could not load Page with ID \"$id\" : $e"); } @@ -247,38 +247,43 @@ public function getpagethumbnail(Page $page): string /** * Delete a page and it's linked rendered html and css files * - * @param Page|string $page could be an Page object or a id string + * @param Page $page Page to delete * * @return bool true if success otherwise false + * + * @todo use Exception istead of returning boolean */ - public function delete($page): bool + public function delete(Page $page): bool { - if ($page instanceof Page) { - $page = $page->id(); - } - if (is_string($page)) { - $this->unlink($page); - return $this->repo->delete($page); - } else { + try { + $this->unlink($page->id()); + } catch (Filesystemexception $e) { return false; } + return $this->repo->delete($page->id()); } /** - * Delete rendered CSS and HTML files + * Delete rendered CSS, JS and HTML files associated with given Page * * @param string $pageid + * + * @throws Filesystemexception If a file deletion failure occurs */ public function unlink(string $pageid) { $files = ['.css', '.quick.css', '.js']; foreach ($files as $file) { - if (file_exists(Model::RENDER_DIR . $pageid . $file)) { - unlink(Model::RENDER_DIR . $pageid . $file); + try { + Fs::deletefile(Model::RENDER_DIR . $pageid . $file); + } catch (Notfoundexception $e) { + // do nothing, this means file is already deleted } } - if (file_exists(Model::HTML_RENDER_DIR . $pageid . '.html')) { - unlink(Model::HTML_RENDER_DIR . $pageid . '.html'); + try { + Fs::deletefile(Model::HTML_RENDER_DIR . $pageid . '.html'); + } catch (Notfoundexception $e) { + // do nothing, this means file is already deleted } } @@ -400,6 +405,10 @@ public function reset(Page $page, array $reset): Page /** * Check if a page need to be rendered * + * This will compare edit and render dates, + * then if render file exists, + * then if the templatebody is set and has been updated. + * * @param Page $page Page to be checked * * @return bool true if the page need to be rendered otherwise false diff --git a/app/class/Page.php b/app/class/Page.php index 8ff0f65e..99f68ffe 100644 --- a/app/class/Page.php +++ b/app/class/Page.php @@ -287,9 +287,9 @@ public function interface($type = 'string') public function linkto($option = 'array') { if ($option == 'json') { - $linkto = json_encode($this->linkto); + return json_encode($this->linkto); } elseif ($option == 'array') { - $linkto = $this->linkto; + return $this->linkto; } elseif ($option == 'sort') { return count($this->linkto); } elseif ($option == 'string') { diff --git a/app/view/templates/admin.php b/app/view/templates/admin.php index 671bfb9f..2b0d1ac7 100644 --- a/app/view/templates/admin.php +++ b/app/view/templates/admin.php @@ -21,13 +21,16 @@
  • Page creation
  • Alert Pages
  • Render
  • -
  • CSS
  • +
  • Style
  • Interface
  • -
  • Tracking
  • - + +
    @@ -44,7 +47,10 @@

    Home page

    -

    Here you can set the home-page view for visitors.

    +

    + By default, W has no home page for visitors without an account. + But if you wish, you can define a page to which visitors who are not logged in will be redirected. +

    form="admin"> @@ -178,19 +184,36 @@

    Render

    +

    rendering details

    +
    - - form="admin"> - + + form="admin"> + +

    + When a page is modified, this may affect the rendering of other pages linked to it. + The pages to which it points have a strong possibility of needing to be updated too. + This option will invalidate their rendering each time the page pointing to them is updated. + They will therefore be re-rendered the next time they are viewed. +

    +

    base page language

    + +

    + If the page language is not specified in metadatas, then this default will be used. +

    +

    title

    +

    + This add a suffix to the title of all your pages. +

    Links

    @@ -241,11 +264,17 @@

    -

    CSS

    +

    Style

    + +

    Global CSS

    - +

    + Global CSS will be loaded with every pages. +

    +

    Favicon

    + +

    Thumbnail

    + - form="admin"> - -
    - +

    Theme

    -

    Set interface theme

    + +

    + See 📖 manual section for more infos. +

    + +

    Javascript

    + +
    + + form="admin"> + +
    + +

    + Disables javascript in the user interface. + Syntax highlighting, depend on it and will therefore not be displayed. + This also reduces comfort a little, but full functionality is retained. +

    + + diff --git a/assets/css/admin.css b/assets/css/admin.css new file mode 100644 index 00000000..b6ecd87f --- /dev/null +++ b/assets/css/admin.css @@ -0,0 +1,21 @@ +section.admin .scroll { + padding-bottom: 300px; +} + +nav li a { + display: block; +} + +nav li a:hover { + background-color: var(--outline-background-color); + color: var(--outline-color); +} + +section.admin h2 { + margin-top: 100px; + margin-bottom: 25px; +} + +section.admin h4 { + margin-bottom: 15px; +} diff --git a/assets/css/base.css b/assets/css/base.css index ef23b111..893bd030 100644 --- a/assets/css/base.css +++ b/assets/css/base.css @@ -91,7 +91,7 @@ summary { white-space: nowrap; } -summary:hover, input[type="submit"] { +summary:hover, input[type="submit"], button { cursor: pointer; }