From b353ec12e1cafa399a224f1d5cb86b79e8b94975 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 20 Nov 2018 12:01:32 +0200 Subject: [PATCH] Flex: Fixes for indexing with different keys --- .../Grav/Framework/Flex/FlexCollection.php | 13 +++-- .../src/Grav/Framework/Flex/FlexDirectory.php | 50 +++++++++---------- system/src/Grav/Framework/Flex/FlexIndex.php | 39 +++++++-------- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/system/src/Grav/Framework/Flex/FlexCollection.php b/system/src/Grav/Framework/Flex/FlexCollection.php index 59b1a018a..378a95d36 100644 --- a/system/src/Grav/Framework/Flex/FlexCollection.php +++ b/system/src/Grav/Framework/Flex/FlexCollection.php @@ -84,7 +84,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface * instance should be created when constructor semantics have changed. * * @param array $elements Elements. - * @package string|null $keyField + * @param string|null $keyField * * @return static * @throws \InvalidArgumentException @@ -92,7 +92,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface protected function createFrom(array $elements, $keyField = null) { $collection = new static($elements, $this->_flexDirectory); - $collection->setKeyField($keyField); + $collection->setKeyField($keyField ?: $this->_keyField); return $collection; } @@ -273,8 +273,13 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface * @param string $keyField * @return FlexIndex */ - public function withKeyField(string $keyField = 'key') : self + public function withKeyField(string $keyField = null) : self { + $keyField = $keyField ?: 'key'; + if ($keyField === $this->getKeyField()) { + return $this; + } + $entries = []; foreach ($this as $key => $object) { // TODO: remove hardcoded logic @@ -295,7 +300,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface */ public function getKeyField() : string { - return $this->_keyField ?? 'key'; + return $this->_keyField ?? 'storage_key'; } /** diff --git a/system/src/Grav/Framework/Flex/FlexDirectory.php b/system/src/Grav/Framework/Flex/FlexDirectory.php index d61413d21..1ee59e003 100644 --- a/system/src/Grav/Framework/Flex/FlexDirectory.php +++ b/system/src/Grav/Framework/Flex/FlexDirectory.php @@ -173,9 +173,11 @@ class FlexDirectory implements FlexAuthorizeInterface */ public function getCollection(array $keys = null, string $keyField = null) : CollectionInterface { + // Get all selected entries. $index = $this->getIndex($keys, $keyField); if (!Utils::isAdminPlugin()) { + // If not in admin, filter the list by using default filters. $filters = (array)$this->getConfig('site.filter', []); foreach ($filters as $filter) { @@ -186,6 +188,28 @@ class FlexDirectory implements FlexAuthorizeInterface return $index; } + /** + * Get the full collection of all stored objects. + * + * Use $directory->getCollection() if you want a filtered collection. + * + * @param array|null $keys Array of keys. + * @param string|null $keyField Field to be used as the key. + * @return FlexIndex|FlexCollection + * @internal + */ + public function getIndex(array $keys = null, string $keyField = null) : CollectionInterface + { + $index = clone $this->loadIndex(); + $index = $index->withKeyField($keyField); + + if (null !== $keys) { + $index = $index->select($keys); + } + + return $index; + } + /** * @param string $key * @param string|null $keyField Field to be used as the key. @@ -360,31 +384,6 @@ class FlexDirectory implements FlexAuthorizeInterface return $this->storage; } - /** - * Get the full collection of all stored objects. - * - * Use $directory->getCollection() if you want a filtered collection. - * - * @param array|null $keys Array of keys. - * @param string|null $keyField Field to be used as the key. - * @return FlexIndex|FlexCollection - * @internal - */ - public function getIndex(array $keys = null, string $keyField = null) : CollectionInterface - { - $index = clone $this->loadIndex(); - - if (null !== $keyField) { - $index = $index->withKeyField($keyField); - } - - if (null !== $keys) { - $index = $index->select($keys); - } - - return $index; - } - /** * @param array $data * @param string $key @@ -524,7 +523,6 @@ class FlexDirectory implements FlexAuthorizeInterface continue; } $usedKey = $keys[$storageKey]; - // TODO: add method to get a single storage index field $row += [ 'storage_key' => $storageKey, 'storage_timestamp' => $entries[$usedKey]['storage_timestamp'], diff --git a/system/src/Grav/Framework/Flex/FlexIndex.php b/system/src/Grav/Framework/Flex/FlexIndex.php index 1dddb1785..96af57507 100644 --- a/system/src/Grav/Framework/Flex/FlexIndex.php +++ b/system/src/Grav/Framework/Flex/FlexIndex.php @@ -152,21 +152,18 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde * @param string $keyField * @return FlexIndex */ - public function withKeyField(string $keyField = 'key') : self + public function withKeyField(string $keyField = null) : self { - // Get storage keys for the objects. - $type = $this->_flexDirectory->getType() . '.obj:'; + $keyField = $keyField ?: 'key'; + if ($keyField === $this->getKeyField()) { + return $this; + } $entries = []; foreach ($this->getEntries() as $key => $value) { - $storageKey = $value['storage_key']; - if (!isset($value['key'])) { $value['key'] = $key; } - if (!isset($value['flex_key'])) { - $value['flex_key'] = $type . $storageKey; - } if (isset($value[$keyField])) { $entries[$value[$keyField]] = $value; @@ -181,7 +178,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde */ public function getKeyField() : string { - return $this->_keyField ?? 'key'; + return $this->_keyField ?? 'storage_key'; } /** @@ -218,16 +215,13 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde // Ordering can be done by using index only. $previous = null; foreach (array_reverse($orderings) as $field => $ordering) { - switch ($field) { - case 'key': - $keys = $this->getKeys(); - $search = array_combine($keys, $keys); - break; - case 'flex_key': - $search = $this->getFlexKeys(); - break; - default: - $search = $this->getIndex($field); + if ($this->getKeyField() === $field) { + $keys = $this->getKeys(); + $search = array_combine($keys, $keys); + } elseif ($field === 'flex_key') { + $search = $this->getFlexKeys(); + } else { + $search = $this->getIndex($field); } // Update current search to match the previous ordering. @@ -266,7 +260,8 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde $cachedMethods = $className::getCachedMethods(); if (!empty($cachedMethods[$name])) { - $key = $this->getType(true) . '.' . sha1($name . '.' . json_encode($arguments) . $this->getCacheKey()); + // TODO: We can optimize this by removing key field from the key and creating collection with proper key. + $key = $this->getType(true) . '.' . sha1($name . '.' . json_encode($arguments) . $this->getCacheKey(), $this->getKeyField()); $cache = $this->_flexDirectory->getCache('object'); @@ -336,7 +331,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde protected function createFrom(array $entries, string $keyField = null) { $index = new static($entries, $this->_flexDirectory); - $index->setKeyField($keyField); + $index->setKeyField($keyField ?? $this->_keyField); return $index; } @@ -346,7 +341,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde */ protected function setKeyField(string $keyField = null) { - $this->_keyField = $keyField ?? 'key'; + $this->_keyField = $keyField ?? 'storage_key'; } protected function getIndexKeys()