From 9bb1d99ae4b87962b2bf728a93f5224ea62eba77 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 24 Nov 2020 14:48:12 +0200 Subject: [PATCH] Added `FlexObject::refresh()` method to make sure object is up to date --- CHANGELOG.md | 3 +- .../src/Grav/Framework/Flex/FlexDirectory.php | 94 +++++++++++-------- system/src/Grav/Framework/Flex/FlexObject.php | 34 +++++++ 3 files changed, 91 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8292e1ef6..d9378a3e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 1. [](#new) * Set minimum requirements to **PHP 7.3.6** + * Updated Clockwork to v5.0 * Added `FlexDirectoryInterface` interface * Renamed `PageCollectionInterface::nonModular()` into `PageCollectionInterface::pages()` and deprecated the old method * Renamed `PageCollectionInterface::modular()` into `PageCollectionInterface::modules()` and deprecated the old method' @@ -10,7 +11,6 @@ * Added search option `same_as` to Flex Objects * Added PHP 8 compatible `function_exists()`: `Utils::functionExists()` * New sites have `compatibility` features turned off by default, upgrading from older versions will keep the settings on - * Updated Clockwork to v5.0 1. [](#improved) * Updated bundled JQuery to latest version `3.5.1` * Forward a `sid` to GPM when downloading a premium package via CLI @@ -20,6 +20,7 @@ * Added XSS detection to all forms. See [documentation](http://learn.grav.local/17/forms/forms/form-options#xss-checks) * Better handling of missing repository index [grav-plugin-admin#1916](https://github.com/getgrav/grav-plugin-admin/issues/1916) * Added support for having all sites / environments under `user/env` folder [#3072](https://github.com/getgrav/grav/issues/3072) + * Added `FlexObject::refresh()` method to make sure object is up to date 1. [](#bugfix) * *Menu Visibility Requires Access* Security option setting wrong frontmatter [login#265](https://github.com/getgrav/grav-plugin-login/issues/265) * Accessing page with unsupported file extension (jpg, pdf, xsl) will use wrong mime type [#3031](https://github.com/getgrav/grav/issues/3031) diff --git a/system/src/Grav/Framework/Flex/FlexDirectory.php b/system/src/Grav/Framework/Flex/FlexDirectory.php index 0f5a712d1..4d8ed2fd3 100644 --- a/system/src/Grav/Framework/Flex/FlexDirectory.php +++ b/system/src/Grav/Framework/Flex/FlexDirectory.php @@ -35,6 +35,7 @@ use RocketTheme\Toolbox\File\YamlFile; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use RuntimeException; use function call_user_func_array; +use function count; use function is_array; use Grav\Common\Flex\Types\Generic\GenericObject; use Grav\Common\Flex\Types\Generic\GenericCollection; @@ -563,8 +564,6 @@ class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface /** @var Debugger $debugger */ $debugger = Grav::instance()['debugger']; - $cache = $this->getCache('object'); - $keys = []; $rows = []; $fetch = []; @@ -583,48 +582,14 @@ class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface } } - $loading = \count($fetch); - // Attempt to fetch missing rows from the cache. if ($fetch) { - try { - $debugger->startTimer('flex-objects', sprintf('Flex: Loading %d %s', $loading, $this->type)); - - $fetched = (array)$cache->getMultiple($fetch); - if ($fetched) { - $index = $this->loadIndex('storage_key'); - - // Make sure cached objects are up to date: compare against index checksum/timestamp. - /** - * @var string $key - * @var mixed $value - */ - foreach ($fetched as $key => $value) { - if ($value instanceof FlexObjectInterface) { - $objectMeta = $value->getMetaData(); - } else { - $objectMeta = $value['__META'] ?? []; - } - $indexMeta = $index->getMetaData($key); - - $indexChecksum = $indexMeta['checksum'] ?? $indexMeta['storage_timestamp'] ?? null; - $objectChecksum = $objectMeta['checksum'] ?? $objectMeta['storage_timestamp'] ?? null; - if ($indexChecksum !== $objectChecksum) { - unset($fetched[$key]); - } - } - } - - // Update cached rows. - $rows = (array)array_replace($rows, $fetched); - } catch (InvalidArgumentException $e) { - $debugger->addException($e); - } + $rows = (array)array_replace($rows, $this->loadCachedObjects($fetch)); } // Read missing rows from the storage. - $storage = $this->getStorage(); $updated = []; + $storage = $this->getStorage(); $rows = $storage->readRows($rows, $updated); // Create objects from the rows. @@ -669,6 +634,7 @@ class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface // Store updated rows to the cache. if ($updated) { + $cache = $this->getCache('object'); if (!$cache instanceof MemoryCache) { ///** @var Debugger $debugger */ //$debugger = Grav::instance()['debugger']; @@ -689,6 +655,56 @@ class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface return $list; } + protected function loadCachedObjects(array $fetch): array + { + if (!$fetch) { + return []; + } + + /** @var Debugger $debugger */ + $debugger = Grav::instance()['debugger']; + + $cache = $this->getCache('object'); + + // Attempt to fetch missing rows from the cache. + $fetched = []; + try { + $loading = count($fetch); + + $debugger->startTimer('flex-objects', sprintf('Flex: Loading %d %s', $loading, $this->type)); + + $fetched = (array)$cache->getMultiple($fetch); + if ($fetched) { + $index = $this->loadIndex('storage_key'); + + // Make sure cached objects are up to date: compare against index checksum/timestamp. + /** + * @var string $key + * @var mixed $value + */ + foreach ($fetched as $key => $value) { + if ($value instanceof FlexObjectInterface) { + $objectMeta = $value->getMetaData(); + } else { + $objectMeta = $value['__META'] ?? []; + } + $indexMeta = $index->getMetaData($key); + + $indexChecksum = $indexMeta['checksum'] ?? $indexMeta['storage_timestamp'] ?? null; + $objectChecksum = $objectMeta['checksum'] ?? $objectMeta['storage_timestamp'] ?? null; + if ($indexChecksum !== $objectChecksum) { + unset($fetched[$key]); + } + } + } + + } catch (InvalidArgumentException $e) { + $debugger->addException($e); + } + + return $fetched; + } + /** * @return void */ @@ -875,7 +891,7 @@ class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface $keys = $className::loadEntriesFromStorage($storage); if (!$cache instanceof MemoryCache) { $debugger->addMessage( - sprintf('Flex: Caching %s index of %d objects', $this->type, \count($keys)), + sprintf('Flex: Caching %s index of %d objects', $this->type, count($keys)), 'debug' ); } diff --git a/system/src/Grav/Framework/Flex/FlexObject.php b/system/src/Grav/Framework/Flex/FlexObject.php index 171a4571f..12e119e41 100644 --- a/system/src/Grav/Framework/Flex/FlexObject.php +++ b/system/src/Grav/Framework/Flex/FlexObject.php @@ -191,6 +191,40 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return $this->_flexDirectory; } + public function refresh(): void + { + $key = $this->getStorageKey(); + if ('' === $key) { + return; + } + + $storage = $this->getFlexDirectory()->getStorage(); + $meta = $storage->getMetaData([$key])[$key] ?? null; + + $newChecksum = $meta['checksum'] ?? $meta['storage_timestamp'] ?? null; + $curChecksum = $this->_meta['checksum'] ?? $this->_meta['storage_timestamp'] ?? null; + + // Check if object is up to date with the storage. + if (null === $newChecksum || $newChecksum === $curChecksum) { + return; + } + + $elements = $storage->readRows([$key => null])[$key] ?? null; + if (null !== $elements || isset($elements['__ERROR'])) { + $meta = $elements['_META'] ?? $meta; + $this->filterElements($elements); + $newKey = $meta['key'] ?? $this->getKey(); + if ($meta) { + $this->setMetaData($meta); + } + $this->objectConstruct($elements, $newKey); + } + + /** @var Debugger $debugger */ + $debugger = Grav::instance()['debugger']; + $debugger->addMessage("Refreshed {$this->getFlexType()} object {$this->getKey()}", 'debug'); + } + /** * {@inheritdoc} * @see FlexObjectInterface::getTimestamp()