From 01264ef70d1ecd04f6954c034bc69eee7de63e11 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 22 Sep 2022 12:36:36 -0600 Subject: [PATCH] initial commit --- CHANGELOG.md | 1 + composer.json | 3 +- system/config/system.yaml | 1 + system/src/Grav/Common/Filesystem/Folder.php | 110 ++++++++++--------- system/src/Grav/Common/Page/Pages.php | 45 +++++--- 5 files changed, 94 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13f1abc6a..99e0049eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 1. [](#new) * Added new `onPageHeaders()` event to allow for header modification as needed + * Added a `system.pages.dirs` configuration option to allow for configurable paths, and multiple page paths # v1.7.36 ## 09/08/2022 diff --git a/composer.json b/composer.json index d1696285a..8e220f89c 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "ext-zip": "*", "ext-dom": "*", "ext-libxml": "*", + "ext-gd": "*", "symfony/polyfill-mbstring": "~1.23", "symfony/polyfill-iconv": "^1.23", "symfony/polyfill-php74": "^1.23", @@ -60,7 +61,7 @@ "symfony/http-client": "^4.4", "composer/semver": "^1.4", "rhukster/dom-sanitizer": "^1.0", - "multiavatar/multiavatar-php": "^1.0" + "multiavatar/multiavatar-php": "^1.0", }, "require-dev": { "codeception/codeception": "^4.1", diff --git a/system/config/system.yaml b/system/config/system.yaml index 3be86d7d3..2c9eaa040 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -35,6 +35,7 @@ home: pages: type: regular # EXPERIMENTAL: Page type: regular or flex + dirs: ['pages://'] # Advanced functionality, allows for multiple page paths theme: quark # Default theme (defaults to "quark" theme) order: by: default # Order pages by "default", "alpha" or "date" diff --git a/system/src/Grav/Common/Filesystem/Folder.php b/system/src/Grav/Common/Filesystem/Folder.php index 8dac2e578..ad49869a8 100644 --- a/system/src/Grav/Common/Filesystem/Folder.php +++ b/system/src/Grav/Common/Filesystem/Folder.php @@ -31,32 +31,34 @@ abstract class Folder /** * Recursively find the last modified time under given path. * - * @param string $path + * @param array $paths * @return int */ - public static function lastModifiedFolder($path) + public static function lastModifiedFolder(array $paths): int { - if (!file_exists($path)) { - return 0; - } - $last_modified = 0; /** @var UniformResourceLocator $locator */ $locator = Grav::instance()['locator']; $flags = RecursiveDirectoryIterator::SKIP_DOTS; - if ($locator->isStream($path)) { - $directory = $locator->getRecursiveIterator($path, $flags); - } else { - $directory = new RecursiveDirectoryIterator($path, $flags); - } - $filter = new RecursiveFolderFilterIterator($directory); - $iterator = new RecursiveIteratorIterator($filter, RecursiveIteratorIterator::SELF_FIRST); - foreach ($iterator as $dir) { - $dir_modified = $dir->getMTime(); - if ($dir_modified > $last_modified) { - $last_modified = $dir_modified; + foreach ($paths as $path) { + if (!file_exists($path)) { + return 0; + } + if ($locator->isStream($path)) { + $directory = $locator->getRecursiveIterator($path, $flags); + } else { + $directory = new RecursiveDirectoryIterator($path, $flags); + } + $filter = new RecursiveFolderFilterIterator($directory); + $iterator = new RecursiveIteratorIterator($filter, RecursiveIteratorIterator::SELF_FIRST); + + foreach ($iterator as $dir) { + $dir_modified = $dir->getMTime(); + if ($dir_modified > $last_modified) { + $last_modified = $dir_modified; + } } } @@ -66,38 +68,40 @@ abstract class Folder /** * Recursively find the last modified time under given path by file. * - * @param string $path + * @param array $paths * @param string $extensions which files to search for specifically * @return int */ - public static function lastModifiedFile($path, $extensions = 'md|yaml') + public static function lastModifiedFile(array $paths, $extensions = 'md|yaml'): int { - if (!file_exists($path)) { - return 0; - } - $last_modified = 0; /** @var UniformResourceLocator $locator */ $locator = Grav::instance()['locator']; $flags = RecursiveDirectoryIterator::SKIP_DOTS; - if ($locator->isStream($path)) { - $directory = $locator->getRecursiveIterator($path, $flags); - } else { - $directory = new RecursiveDirectoryIterator($path, $flags); - } - $recursive = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); - $iterator = new RegexIterator($recursive, '/^.+\.'.$extensions.'$/i'); - /** @var RecursiveDirectoryIterator $file */ - foreach ($iterator as $filepath => $file) { - try { - $file_modified = $file->getMTime(); - if ($file_modified > $last_modified) { - $last_modified = $file_modified; + foreach($paths as $path) { + if (!file_exists($path)) { + return 0; + } + if ($locator->isStream($path)) { + $directory = $locator->getRecursiveIterator($path, $flags); + } else { + $directory = new RecursiveDirectoryIterator($path, $flags); + } + $recursive = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); + $iterator = new RegexIterator($recursive, '/^.+\.'.$extensions.'$/i'); + + /** @var RecursiveDirectoryIterator $file */ + foreach ($iterator as $file) { + try { + $file_modified = $file->getMTime(); + if ($file_modified > $last_modified) { + $last_modified = $file_modified; + } + } catch (Exception $e) { + Grav::instance()['log']->error('Could not process file: ' . $e->getMessage()); } - } catch (Exception $e) { - Grav::instance()['log']->error('Could not process file: ' . $e->getMessage()); } } @@ -107,28 +111,30 @@ abstract class Folder /** * Recursively md5 hash all files in a path * - * @param string $path + * @param array $paths * @return string */ - public static function hashAllFiles($path) + public static function hashAllFiles(array $paths): string { $files = []; - if (file_exists($path)) { - $flags = RecursiveDirectoryIterator::SKIP_DOTS; + foreach ($paths as $path) { + if (file_exists($path)) { + $flags = RecursiveDirectoryIterator::SKIP_DOTS; - /** @var UniformResourceLocator $locator */ - $locator = Grav::instance()['locator']; - if ($locator->isStream($path)) { - $directory = $locator->getRecursiveIterator($path, $flags); - } else { - $directory = new RecursiveDirectoryIterator($path, $flags); - } + /** @var UniformResourceLocator $locator */ + $locator = Grav::instance()['locator']; + if ($locator->isStream($path)) { + $directory = $locator->getRecursiveIterator($path, $flags); + } else { + $directory = new RecursiveDirectoryIterator($path, $flags); + } - $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); + $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); - foreach ($iterator as $file) { - $files[] = $file->getPathname() . '?'. $file->getMTime(); + foreach ($iterator as $file) { + $files[] = $file->getPathname() . '?'. $file->getMTime(); + } } } diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index ec48b5173..1862b0cf7 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -100,6 +100,7 @@ class Pages /** @var string|null */ protected static $home_route; + /** * Constructor * @@ -1712,10 +1713,7 @@ class Pages /** @var Language $language */ $language = $this->grav['language']; - $pages_dir = $locator->findResource('page://'); - if (!is_string($pages_dir)) { - throw new RuntimeException('Internal Error'); - } + $pages_dirs = $this->getPagesPaths(); // Set active language $this->active_lang = $language->getActive(); @@ -1731,16 +1729,16 @@ class Pages $hash = 0; break; case 'folder': - $hash = Folder::lastModifiedFolder($pages_dir); + $hash = Folder::lastModifiedFolder($pages_dirs); break; case 'hash': - $hash = Folder::hashAllFiles($pages_dir); + $hash = Folder::hashAllFiles($pages_dirs); break; default: - $hash = Folder::lastModifiedFile($pages_dir); + $hash = Folder::lastModifiedFile($pages_dirs); } - $this->pages_cache_id = md5($pages_dir . $hash . $language->getActive() . $config->checksum()); + $this->pages_cache_id = md5(json_encode($pages_dirs) . $hash . $language->getActive() . $config->checksum()); /** @var Cache $cache */ $cache = $this->grav['cache']; @@ -1760,18 +1758,39 @@ class Pages $this->grav['debugger']->addMessage('Page cache disabled, rebuilding pages..'); } - $this->resetPages($pages_dir); + $this->resetPages($pages_dirs); + } + + protected function getPagesPaths(): array + { + $grav = Grav::instance(); + $locator = $grav['locator']; + $paths = []; + + $dirs = (array) $grav['config']->get('system.pages.dirs', ['page://']); + foreach ($dirs as $dir) { + $path = $locator->findResource($dir); + if (file_exists($path)) { + $paths[] = $path; + } + } + + return $paths; } /** * Accessible method to manually reset the pages cache * - * @param string $pages_dir + * @param array $pages_dirs */ - public function resetPages($pages_dir): void + public function resetPages(array $pages_dirs): void { $this->sort = []; - $this->recurse($pages_dir); + + foreach ($pages_dirs as $dir) { + $this->recurse($dir); + } + $this->buildRoutes(); // cache if needed @@ -1795,7 +1814,7 @@ class Pages * @throws RuntimeException * @internal */ - protected function recurse($directory, PageInterface $parent = null) + protected function recurse(string $directory, PageInterface $parent = null) { $directory = rtrim($directory, DS); $page = new Page;