From b6bd7f7ec561c643b17072161dfae46e6190da1c Mon Sep 17 00:00:00 2001 From: Florian Thoma Date: Wed, 18 Dec 2019 09:51:58 +1100 Subject: [PATCH 1/2] move registration of classes to dev/build using cache --- _config/config.yml | 6 ++ src/Extensions/ListedPageExtension.php | 5 -- src/Extensions/ListingsRootPageExtension.php | 5 -- src/ListedPages.php | 90 +++++++++++++++----- src/ListingsRoots.php | 87 +++++++++++++++---- 5 files changed, 146 insertions(+), 47 deletions(-) diff --git a/_config/config.yml b/_config/config.yml index 024f5ca..1fd449a 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -1,3 +1,9 @@ --- Name: fromholdio-listings --- + +SilverStripe\Core\Injector\Injector: + Psr\SimpleCache\CacheInterface.ListingsCache: + factory: SilverStripe\Core\Cache\CacheFactory + constructor: + namespace: "ListingsCache" diff --git a/src/Extensions/ListedPageExtension.php b/src/Extensions/ListedPageExtension.php index 56910c6..31b869c 100644 --- a/src/Extensions/ListedPageExtension.php +++ b/src/Extensions/ListedPageExtension.php @@ -13,11 +13,6 @@ class ListedPageExtension extends SiteTreeExtension { - public static function add_to_class($class, $extensionClass, $args = null) - { - ListedPages::register_class($class); - } - public function updateCMSFields(FieldList $fields) { // Remove ParentID dropdown (if mode != cmstree) diff --git a/src/Extensions/ListingsRootPageExtension.php b/src/Extensions/ListingsRootPageExtension.php index e58c970..28f74ec 100644 --- a/src/Extensions/ListingsRootPageExtension.php +++ b/src/Extensions/ListingsRootPageExtension.php @@ -77,11 +77,6 @@ class ListingsRootPageExtension extends ListingsSiteTreeExtension */ private static $administration_mode = 'cmstree'; - public static function add_to_class($class, $extensionClass, $args = null) - { - ListingsRoots::register_class($class); - } - public function getListedPagesParentIDs() { return [$this->owner->ID]; diff --git a/src/ListedPages.php b/src/ListedPages.php index deecdf8..abaa4de 100644 --- a/src/ListedPages.php +++ b/src/ListedPages.php @@ -4,33 +4,36 @@ use Fromholdio\CommonAncestor\CommonAncestor; use Fromholdio\Listings\Extensions\ListedPageExtension; +use Psr\SimpleCache\CacheInterface; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Core\ClassInfo; -use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Extensible; +use SilverStripe\Core\Flushable; +use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Injector\Injectable; +use SilverStripe\Core\Injector\Injector; use SilverStripe\ORM\DataList; -class ListedPages +class ListedPages implements Flushable { use Injectable; use Extensible; use Configurable; - protected static $classes = []; - - public static function register_class($class) - { - self::validate_class($class); - self::$classes[$class] = $class; - } - public static function get_classes($includeSubclasses = true) { - $classes = self::$classes; + $classes = []; + $cache = self::get_cache(); + + // retrieve classes from cache + if ($cache->has(self::get_cache_key('Classes'))) { + $classes = $cache->get(self::get_cache_key('Classes')); + } + if ($includeSubclasses) { $classes = self::add_subclasses($classes); } + return $classes; } @@ -51,7 +54,7 @@ public static function get_classes_dropdown_source($includeSubclasses = true, $u public static function get_index_classes() { - $classes = self::$classes; + $classes = self::get_classes(); foreach ($classes as $class) { if (!$class::singleton()->config()->get('can_be_root')) { unset($classes[$class]); @@ -133,15 +136,28 @@ public static function get_common_class($classes = null) protected static function add_subclasses($classes) { - $classes = array_combine($classes, $classes); - - foreach ($classes as $class) { - $subclasses = ClassInfo::subclassesFor($class); - foreach ($subclasses as $subclass) { - $classes[$subclass] = $subclass; + $cache = self::get_cache(); + + // retrieve classes from cache + $cacheKey = self::get_cache_key('IncludeSubclasses', $classes); + if ($cache->has($cacheKey)) { + + $classes = $cache->get($cacheKey); + + } else { + + $classes = array_combine($classes, $classes); + + foreach ($classes as $class) { + $subclasses = ClassInfo::subclassesFor($class); + foreach ($subclasses as $subclass) { + $classes[$subclass] = $subclass; + } } + + $cache->set($cacheKey, $classes); } - + return $classes; } @@ -203,4 +219,40 @@ public static function validate_classes($classes) return true; } + + /** + * This function is triggered early in the request if the "flush" query + * parameter has been set. Each class that implements Flushable implements + * this function which looks after it's own specific flushing functionality. + * + * @see FlushMiddleware + */ + public static function flush() + { + self::get_cache()->clear(); + + // build pages cache + $pages = []; + $classes = ClassInfo::subclassesFor(SiteTree::class); + foreach ($classes as $class) { + if ($class::has_extension(ListedPageExtension::class)) { + self::validate_class($class); + $pages[$class] = $class; + } + } + $cache = self::get_cache(); + $cacheKey = self::get_cache_key('Classes'); + $cache->set($cacheKey, $pages); + self::add_subclasses($pages); + + } + + private static function get_cache() { + return Injector::inst()->get(CacheInterface::class . '.ListingsCache'); + } + + private static function get_cache_key($suffix, $classes=null) { + return 'ListedPagesClasses-'.$suffix.($classes ? md5(implode('-', $classes)) : ''); + } + } diff --git a/src/ListingsRoots.php b/src/ListingsRoots.php index 581079e..cc9b35e 100644 --- a/src/ListingsRoots.php +++ b/src/ListingsRoots.php @@ -2,33 +2,37 @@ namespace Fromholdio\Listings; +use Fromholdio\CommonAncestor\CommonAncestor; use Fromholdio\Listings\Extensions\ListingsRootPageExtension; +use Psr\SimpleCache\CacheInterface; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Core\ClassInfo; -use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Extensible; +use SilverStripe\Core\Flushable; +use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Injector\Injectable; +use SilverStripe\Core\Injector\Injector; -class ListingsRoots +class ListingsRoots implements Flushable { use Injectable; use Extensible; use Configurable; - protected static $classes = []; - - public static function register_class($class) - { - self::validate_class($class); - self::$classes[$class] = $class; - } - public static function get_classes($includeSubclasses = true) { - $classes = self::$classes; + $classes = []; + $cache = self::get_cache(); + + // retrieve classes from cache + if ($cache->has(self::get_cache_key('Classes'))) { + $classes = $cache->get(self::get_cache_key('Classes')); + } + if ($includeSubclasses) { $classes = self::add_subclasses($classes); } + return $classes; } @@ -120,15 +124,28 @@ public static function get_common_plural_name($classes) protected static function add_subclasses($classes) { - $classes = array_combine($classes, $classes); - - foreach ($classes as $class) { - $subclasses = ClassInfo::subclassesFor($class); - foreach ($subclasses as $subclass) { - $classes[$subclass] = $subclass; + $cache = self::get_cache(); + + // retrieve classes from cache + $cacheKey = self::get_cache_key('IncludeSubclasses', $classes); + if ($cache->has($cacheKey)) { + + $classes = $cache->get($cacheKey); + + } else { + + $classes = array_combine($classes, $classes); + + foreach ($classes as $class) { + $subclasses = ClassInfo::subclassesFor($class); + foreach ($subclasses as $subclass) { + $classes[$subclass] = $subclass; + } } + + $cache->set($cacheKey, $classes); } - + return $classes; } @@ -190,4 +207,38 @@ public static function validate_classes($classes) return true; } + + /** + * This function is triggered early in the request if the "flush" query + * parameter has been set. Each class that implements Flushable implements + * this function which looks after it's own specific flushing functionality. + * + * @see FlushMiddleware + */ + public static function flush() + { + self::get_cache()->clear(); + + // build pages cache + $pages = []; + $classes = ClassInfo::subclassesFor(SiteTree::class); + foreach ($classes as $class) { + if ($class::has_extension(ListingsRootPageExtension::class)) { + self::validate_class($class); + $pages[$class] = $class; + } + } + $cache = self::get_cache(); + $cacheKey = self::get_cache_key('Classes'); + $cache->set($cacheKey, $pages); + self::add_subclasses($pages); + } + + private static function get_cache() { + return Injector::inst()->get(CacheInterface::class . '.ListingsCache'); + } + + private static function get_cache_key($suffix, $classes=null) { + return 'ListingsRootClasses-'.$suffix.($classes ? md5(implode('-', $classes)) : ''); + } } From 0b6a07f1545579f6b9c14ff43d7855664db8ac4d Mon Sep 17 00:00:00 2001 From: Florian Thoma Date: Thu, 19 Dec 2019 09:11:20 +1100 Subject: [PATCH 2/2] add fallback for building of cache --- src/ListedPages.php | 20 +++++++++++++------- src/ListingsRoots.php | 16 ++++++++++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/ListedPages.php b/src/ListedPages.php index abaa4de..8b66e48 100644 --- a/src/ListedPages.php +++ b/src/ListedPages.php @@ -6,6 +6,7 @@ use Fromholdio\Listings\Extensions\ListedPageExtension; use Psr\SimpleCache\CacheInterface; use SilverStripe\CMS\Model\SiteTree; +use SilverStripe\Control\Middleware\FlushMiddleware; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Extensible; use SilverStripe\Core\Flushable; @@ -23,11 +24,15 @@ class ListedPages implements Flushable public static function get_classes($includeSubclasses = true) { $classes = []; - $cache = self::get_cache(); // retrieve classes from cache - if ($cache->has(self::get_cache_key('Classes'))) { - $classes = $cache->get(self::get_cache_key('Classes')); + $cache = self::get_cache(); + $cacheKey = self::get_cache_key('Classes'); + if (!$cache->has($cacheKey)) { + self::build_cache(); + } + if ($cache->has($cacheKey)) { + $classes = $cache->get($cacheKey); } if ($includeSubclasses) { @@ -136,9 +141,8 @@ public static function get_common_class($classes = null) protected static function add_subclasses($classes) { - $cache = self::get_cache(); - // retrieve classes from cache + $cache = self::get_cache(); $cacheKey = self::get_cache_key('IncludeSubclasses', $classes); if ($cache->has($cacheKey)) { @@ -230,7 +234,10 @@ public static function validate_classes($classes) public static function flush() { self::get_cache()->clear(); - + self::build_cache(); + } + + private static function build_cache() { // build pages cache $pages = []; $classes = ClassInfo::subclassesFor(SiteTree::class); @@ -244,7 +251,6 @@ public static function flush() $cacheKey = self::get_cache_key('Classes'); $cache->set($cacheKey, $pages); self::add_subclasses($pages); - } private static function get_cache() { diff --git a/src/ListingsRoots.php b/src/ListingsRoots.php index cc9b35e..8c7062e 100644 --- a/src/ListingsRoots.php +++ b/src/ListingsRoots.php @@ -6,6 +6,7 @@ use Fromholdio\Listings\Extensions\ListingsRootPageExtension; use Psr\SimpleCache\CacheInterface; use SilverStripe\CMS\Model\SiteTree; +use SilverStripe\Control\Middleware\FlushMiddleware; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Extensible; use SilverStripe\Core\Flushable; @@ -22,11 +23,15 @@ class ListingsRoots implements Flushable public static function get_classes($includeSubclasses = true) { $classes = []; - $cache = self::get_cache(); // retrieve classes from cache - if ($cache->has(self::get_cache_key('Classes'))) { - $classes = $cache->get(self::get_cache_key('Classes')); + $cache = self::get_cache(); + $cacheKey = self::get_cache_key('Classes'); + if (!$cache->has($cacheKey)) { + self::build_cache(); + } + if ($cache->has($cacheKey)) { + $classes = $cache->get($cacheKey); } if ($includeSubclasses) { @@ -218,7 +223,10 @@ public static function validate_classes($classes) public static function flush() { self::get_cache()->clear(); - + self::build_cache(); + } + + private static function build_cache() { // build pages cache $pages = []; $classes = ClassInfo::subclassesFor(SiteTree::class);