From 8c1c813acd30ec0445f6350de1e494336f5c7aaa Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 19 Mar 2019 13:36:12 +0200 Subject: [PATCH] Greatly improved Flex interfaces and docblocks --- CHANGELOG.md | 1 + system/src/Grav/Common/User/FlexUser/User.php | 14 +- system/src/Grav/Framework/Flex/Flex.php | 2 +- .../Grav/Framework/Flex/FlexCollection.php | 364 ++++++++------- .../src/Grav/Framework/Flex/FlexDirectory.php | 8 +- system/src/Grav/Framework/Flex/FlexForm.php | 7 +- system/src/Grav/Framework/Flex/FlexIndex.php | 234 ++++++---- system/src/Grav/Framework/Flex/FlexObject.php | 421 +++++++++--------- .../Interfaces/FlexAuthorizeInterface.php | 17 +- .../Interfaces/FlexCollectionInterface.php | 101 ++++- .../Flex/Interfaces/FlexCommonInterface.php | 85 ++++ .../Flex/Interfaces/FlexFormInterface.php | 39 +- .../Flex/Interfaces/FlexIndexInterface.php | 45 +- .../Flex/Interfaces/FlexObjectInterface.php | 182 ++++---- .../Flex/Interfaces/FlexStorageInterface.php | 86 ++-- .../Storage/AbstractFilesystemStorage.php | 2 +- .../Framework/Flex/Storage/FileStorage.php | 10 +- .../Framework/Flex/Storage/FolderStorage.php | 49 +- .../Framework/Flex/Storage/SimpleStorage.php | 37 +- .../Framework/Flex/Traits/FlexMediaTrait.php | 8 +- .../Grav/Framework/Form/Traits/FormTrait.php | 8 +- .../Interfaces/MediaCollectionInterface.php | 2 +- 22 files changed, 1025 insertions(+), 697 deletions(-) create mode 100644 system/src/Grav/Framework/Flex/Interfaces/FlexCommonInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ecb3b0b1..223bc8931 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * Twig `nicenumber`: do not use 0 + string casting hack * Converted Twig tags to use namespaced Twig classes * Site shows error on page rather than hard-crash when page has invalid frontmatter [#2343](https://github.com/getgrav/grav/issues/2343) + * Grav 1.6: Greatly improved Flex interfaces 1. [](#bugfix) * Grav 1.6: Fixed `FlexUser` loosing ACL information * Grav 1.6: Fixed `FlexUser::find()` breaking when nothing is found diff --git a/system/src/Grav/Common/User/FlexUser/User.php b/system/src/Grav/Common/User/FlexUser/User.php index ef19849f3..f97adfdb9 100644 --- a/system/src/Grav/Common/User/FlexUser/User.php +++ b/system/src/Grav/Common/User/FlexUser/User.php @@ -9,7 +9,6 @@ namespace Grav\Common\User\FlexUser; -use Grav\Common\Data\ValidationException; use Grav\Common\Grav; use Grav\Common\Media\Interfaces\MediaCollectionInterface; use Grav\Common\Page\Media; @@ -18,7 +17,6 @@ use Grav\Common\Page\Medium\Medium; use Grav\Common\User\Authentication; use Grav\Common\User\Interfaces\UserInterface; use Grav\Common\User\Traits\UserTrait; -use Grav\Common\Utils; use Grav\Framework\File\Formatter\JsonFormatter; use Grav\Framework\File\Formatter\YamlFormatter; use Grav\Framework\Flex\FlexDirectory; @@ -65,7 +63,7 @@ class User extends FlexObject implements UserInterface, MediaManipulationInterfa /** * @return array */ - public static function getCachedMethods() + public static function getCachedMethods(): array { return [ 'load' => false, @@ -78,12 +76,12 @@ class User extends FlexObject implements UserInterface, MediaManipulationInterfa ] + parent::getCachedMethods(); } - public function __construct(array $elements, $key, FlexDirectory $flexDirectory, bool $validate = false) + public function __construct(array $elements, $key, FlexDirectory $directory, bool $validate = false) { // User can only be authenticated via login. unset($elements['authenticated'], $elements['authorized']); - parent::__construct($elements, $key, $flexDirectory, $validate); + parent::__construct($elements, $key, $directory, $validate); // Define username and state if they aren't set. $this->defProperty('username', $key); @@ -435,7 +433,7 @@ class User extends FlexObject implements UserInterface, MediaManipulationInterfa /** * @return array */ - public function prepareStorage() + public function prepareStorage(): array { $elements = parent::prepareStorage(); @@ -628,7 +626,7 @@ class User extends FlexObject implements UserInterface, MediaManipulationInterfa /** * @return array */ - protected function doSerialize() + protected function doSerialize(): array { return [ 'type' => 'accounts', @@ -641,7 +639,7 @@ class User extends FlexObject implements UserInterface, MediaManipulationInterfa /** * @param array $serialized */ - protected function doUnserialize(array $serialized) + protected function doUnserialize(array $serialized): void { $grav = Grav::instance(); diff --git a/system/src/Grav/Framework/Flex/Flex.php b/system/src/Grav/Framework/Flex/Flex.php index 36f112063..de5ddcd26 100644 --- a/system/src/Grav/Framework/Flex/Flex.php +++ b/system/src/Grav/Framework/Flex/Flex.php @@ -48,7 +48,7 @@ class Flex implements \Countable * @param array $config * @return $this */ - public function addDirectoryType(string $type, string $blueprint, array $config = []): self + public function addDirectoryType(string $type, string $blueprint, array $config = []) { $config = array_merge_recursive(['enabled' => true], $this->config['object'] ?? [], $config); diff --git a/system/src/Grav/Framework/Flex/FlexCollection.php b/system/src/Grav/Framework/Flex/FlexCollection.php index 9faf5bcab..a71ff604e 100644 --- a/system/src/Grav/Framework/Flex/FlexCollection.php +++ b/system/src/Grav/Framework/Flex/FlexCollection.php @@ -40,9 +40,11 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface private $_keyField; /** - * @return array + * Get list of cached methods. + * + * @return array Returns a list of methods with their caching information. */ - public static function getCachedMethods() + public static function getCachedMethods(): array { return [ 'getTypePrefix' => true, @@ -65,12 +67,10 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface } /** - * @param array $entries - * @param FlexDirectory $directory - * @param string $keyField - * @return static + * {@inheritdoc} + * @see FlexCollectionInterface::createFromArray() */ - public static function createFromArray(array $entries, FlexDirectory $directory, string $keyField = null): FlexCollectionInterface + public static function createFromArray(array $entries, FlexDirectory $directory, string $keyField = null) { $instance = new static($entries, $directory); $instance->setKeyField($keyField); @@ -79,66 +79,23 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface } /** - * @param array $elements - * @param FlexDirectory|null $flexDirectory - * @throws \InvalidArgumentException + * {@inheritdoc} + * @see FlexCollectionInterface::__construct() */ - public function __construct(array $elements = [], FlexDirectory $flexDirectory = null) + public function __construct(array $entries = [], FlexDirectory $directory = null) { - parent::__construct($elements); + parent::__construct($entries); - if ($flexDirectory) { - $this->setFlexDirectory($flexDirectory)->setKey($flexDirectory->getType()); + if ($directory) { + $this->setFlexDirectory($directory)->setKey($directory->getType()); } } /** - * Creates a new instance from the specified elements. - * - * This method is provided for derived classes to specify how a new - * instance should be created when constructor semantics have changed. - * - * @param array $elements Elements. - * @param string|null $keyField - * - * @return static - * @throws \InvalidArgumentException + * {@inheritdoc} + * @see FlexCollectionInterface::search() */ - protected function createFrom(array $elements, $keyField = null) - { - $collection = new static($elements, $this->_flexDirectory); - $collection->setKeyField($keyField ?: $this->_keyField); - - return $collection; - } - - /** - * @return string - */ - protected function getTypePrefix() - { - return 'c.'; - } - - /** - * @param bool $prefix - * @return string - */ - public function getType($prefix = false) - { - $type = $prefix ? $this->getTypePrefix() : ''; - - return $type . $this->_flexDirectory->getType(); - } - - - /** - * @param string $search - * @param string|string[]|null $properties - * @param array|null $options - * @return FlexCollectionInterface - */ - public function search(string $search, $properties = null, array $options = null) // : FlexCollectionInterface + public function search(string $search, $properties = null, array $options = null) { $matching = $this->call('search', [$search, $properties, $options]); $matching = array_filter($matching); @@ -152,35 +109,154 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface return $this->select(array_keys($matching)); } - public function sort(array $order) // : FlexCollectionInterface + /** + * {@inheritdoc} + * @see FlexCollectionInterface::sort() + */ + public function sort(array $order) { $criteria = Criteria::create()->orderBy($order); - return $this->matching($criteria); + /** @var FlexCollectionInterface $matching */ + $matching = $this->matching($criteria); + + return $matching; } /** - * Twig example: {% render collection layout 'edit' with {my_check: true} %} - * - * @param string $layout - * @param array $context - * @return ContentBlockInterface|HtmlBlock - * @throws \Exception - * @throws \Throwable - * @throws LoaderError - * @throws SyntaxError + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexType() + */ + public function getFlexType(): string + { + return $this->_flexDirectory->getType(); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getFlexDirectory(): FlexDirectory + { + return $this->_flexDirectory; + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getTimestamp() + */ + public function getTimestamp(): int + { + $timestamps = $this->getTimestamps(); + + return $timestamps ? max($timestamps) : time(); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getCacheKey(): string + { + return $this->getTypePrefix() . $this->getFlexType() . '.' . sha1(json_encode($this->call('getKey'))); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getCacheChecksum(): string + { + return sha1(json_encode($this->getTimestamps())); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getTimestamps(): array + { + /** @var int[] $timestamps */ + $timestamps = $this->call('getTimestamp'); + + return $timestamps; + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getStorageKeys(): array + { + /** @var string[] $keys */ + $keys = $this->call('getStorageKey'); + + return $keys; + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getFlexKeys(): array + { + /** @var string[] $keys */ + $keys = $this->call('getFlexKey'); + + return $keys; + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::withKeyField() + */ + public function withKeyField(string $keyField = null) + { + $keyField = $keyField ?: 'key'; + if ($keyField === $this->getKeyField()) { + return $this; + } + + $entries = []; + foreach ($this as $key => $object) { + // TODO: remove hardcoded logic + if ($keyField === 'storage_key') { + $entries[$object->getStorageKey()] = $object; + } elseif ($keyField === 'flex_key') { + $entries[$object->getFlexKey()] = $object; + } elseif ($keyField === 'key') { + $entries[$object->getKey()] = $object; + } + } + + return $this->createFrom($entries, $keyField); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getIndex() + */ + public function getIndex() + { + return $this->getFlexDirectory()->getIndex($this->getKeys(), $this->getKeyField()); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::render() */ public function render($layout = null, array $context = []) { if (null === $layout) { $layout = 'default'; } + $type = $this->getFlexType(); $grav = Grav::instance(); /** @var Debugger $debugger */ $debugger = $grav['debugger']; - $debugger->startTimer('flex-collection-' . ($debugKey = uniqid($this->getType(false), false)), 'Render Collection ' . $this->getType(false) . ' (' . $layout . ')'); + $debugger->startTimer('flex-collection-' . ($debugKey = uniqid($type, false)), 'Render Collection ' . $type . ' (' . $layout . ')'); $cache = $key = null; foreach ($context as $value) { @@ -229,8 +305,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface ); if ($debugger->enabled()) { - $name = $this->getType(false); - $output = "\n\n{$output}\n\n"; + $output = "\n\n{$output}\n\n"; } $block->setContent($output); @@ -247,6 +322,20 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface return $block; } + /** + * @param bool $prefix + * @return string + * @deprecated 1.6 Use `->getFlexType()` instead. + */ + public function getType($prefix = false) + { + user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getFlexType() method instead', E_USER_DEPRECATED); + + $type = $prefix ? $this->getTypePrefix() : ''; + + return $type . $this->getFlexType(); + } + /** * @param FlexDirectory $type * @return $this @@ -258,14 +347,6 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface return $this; } - /** - * @return FlexDirectory - */ - public function getFlexDirectory() //: FlexDirectory - { - return $this->_flexDirectory; - } - /** * @return array */ @@ -280,94 +361,11 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface * @param string|null $namespace * @return CacheInterface */ - public function getCache(string $namespace = null): CacheInterface + public function getCache(string $namespace = null) { return $this->_flexDirectory->getCache($namespace); } - /** - * @return string - */ - public function getCacheKey() - { - return $this->getType(true) . '.' . sha1(json_encode($this->call('getKey'))); - } - - /** - * @return string - */ - public function getCacheChecksum() - { - return sha1(json_encode($this->getTimestamps())); - } - - /** - * @return int[] - */ - public function getTimestamps() - { - /** @var int[] $timestamps */ - $timestamps = $this->call('getTimestamp'); - - return $timestamps; - } - - /** - * @return string[] - */ - public function getStorageKeys() - { - /** @var string[] $keys */ - $keys = $this->call('getStorageKey'); - - return $keys; - } - - /** - * @return string[] - */ - public function getFlexKeys() - { - /** @var string[] $keys */ - $keys = $this->call('getFlexKey'); - - return $keys; - } - - /** - * @return FlexIndexInterface - */ - public function getIndex(): FlexIndexInterface - { - return $this->getFlexDirectory()->getIndex($this->getKeys(), $this->getKeyField()); - } - - /** - * @param string|null $keyField - * @return FlexCollectionInterface - */ - public function withKeyField(string $keyField = null): FlexCollectionInterface - { - $keyField = $keyField ?: 'key'; - if ($keyField === $this->getKeyField()) { - return $this; - } - - $entries = []; - foreach ($this as $key => $object) { - // TODO: remove hardcoded logic - if ($keyField === 'storage_key') { - $entries[$object->getStorageKey()] = $object; - } elseif ($keyField === 'flex_key') { - $entries[$object->getFlexKey()] = $object; - } elseif ($keyField === 'key') { - $entries[$object->getKey()] = $object; - } - } - - return $this->createFrom($entries, $keyField); - } - /** * @return string */ @@ -427,20 +425,48 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface public function __debugInfo() { return [ - 'type:private' => $this->getType(false), + 'type:private' => $this->getFlexType(), 'key:private' => $this->getKey(), 'objects_key:private' => $this->getKeyField(), 'objects:private' => $this->getElements() ]; } + /** + * Creates a new instance from the specified elements. + * + * This method is provided for derived classes to specify how a new + * instance should be created when constructor semantics have changed. + * + * @param array $elements Elements. + * @param string|null $keyField + * + * @return static + * @throws \InvalidArgumentException + */ + protected function createFrom(array $elements, $keyField = null) + { + $collection = new static($elements, $this->_flexDirectory); + $collection->setKeyField($keyField ?: $this->_keyField); + + return $collection; + } + + /** + * @return string + */ + protected function getTypePrefix(): string + { + return 'c.'; + } + /** * @param string $layout * @return TemplateWrapper * @throws LoaderError * @throws SyntaxError */ - protected function getTemplate($layout) //: \Twig_Template + protected function getTemplate($layout) { $grav = Grav::instance(); @@ -448,7 +474,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface $twig = $grav['twig']; try { - return $twig->twig()->resolveTemplate(["flex-objects/layouts/{$this->getType(false)}/collection/{$layout}.html.twig"]); + return $twig->twig()->resolveTemplate(["flex-objects/layouts/{$this->getFlexType()}/collection/{$layout}.html.twig"]); } catch (LoaderError $e) { /** @var Debugger $debugger */ $debugger = Grav::instance()['debugger']; @@ -470,7 +496,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface return $flex->getDirectory($type); } - protected function setKeyField($keyField = null) + protected function setKeyField($keyField = null): void { $this->_keyField = $keyField ?? 'storage_key'; } diff --git a/system/src/Grav/Framework/Flex/FlexDirectory.php b/system/src/Grav/Framework/Flex/FlexDirectory.php index 824b8d190..d91b5564b 100644 --- a/system/src/Grav/Framework/Flex/FlexDirectory.php +++ b/system/src/Grav/Framework/Flex/FlexDirectory.php @@ -132,7 +132,7 @@ class FlexDirectory implements FlexAuthorizeInterface * @param string $context * @return Blueprint */ - public function getBlueprint(string $type = '', string $context = ''): Blueprint + public function getBlueprint(string $type = '', string $context = '') { $blueprint = $this->getBlueprintInternal($type, $context); @@ -291,7 +291,7 @@ class FlexDirectory implements FlexAuthorizeInterface * @param string|null $namespace * @return CacheInterface */ - public function getCache(string $namespace = null): CacheInterface + public function getCache(string $namespace = null) { $namespace = $namespace ?: 'index'; $cache = $this->cache[$namespace] ?? null; @@ -332,7 +332,7 @@ class FlexDirectory implements FlexAuthorizeInterface /** * @return $this */ - public function clearCache(): self + public function clearCache() { $grav = Grav::instance(); @@ -553,7 +553,7 @@ class FlexDirectory implements FlexAuthorizeInterface * @param string $context * @return Blueprint */ - protected function getBlueprintInternal(string $type_view = '', string $context = ''): Blueprint + protected function getBlueprintInternal(string $type_view = '', string $context = '') { if (!isset($this->blueprints[$type_view])) { if (!file_exists($this->blueprint_file)) { diff --git a/system/src/Grav/Framework/Flex/FlexForm.php b/system/src/Grav/Framework/Flex/FlexForm.php index 31d7d02d6..3e4d8265b 100644 --- a/system/src/Grav/Framework/Flex/FlexForm.php +++ b/system/src/Grav/Framework/Flex/FlexForm.php @@ -79,7 +79,7 @@ class FlexForm implements FlexFormInterface /** * @return Data|FlexObjectInterface */ - public function getData(): \ArrayAccess + public function getData() { return $this->data ?? $this->getObject(); } @@ -189,11 +189,6 @@ class FlexForm implements FlexFormInterface return ''; } - public function getMediaRoute(): string - { - return '/' . $this->getObject()->getKey(); - } - /** * Implements \Serializable::unserialize(). * diff --git a/system/src/Grav/Framework/Flex/FlexIndex.php b/system/src/Grav/Framework/Flex/FlexIndex.php index 5678dbdb6..77a2d85ac 100644 --- a/system/src/Grav/Framework/Flex/FlexIndex.php +++ b/system/src/Grav/Framework/Flex/FlexIndex.php @@ -40,18 +40,16 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde * @param FlexDirectory $directory * @return static */ - public static function createFromStorage(FlexDirectory $directory) : FlexCollectionInterface + public static function createFromStorage(FlexDirectory $directory) { return static::createFromArray(static::loadEntriesFromStorage($directory->getStorage()), $directory); } /** - * @param array[] $entries - * @param FlexDirectory $directory - * @param string $keyField - * @return static + * {@inheritdoc} + * @see FlexCollectionInterface::createFromArray() */ - public static function createFromArray(array $entries, FlexDirectory $directory, string $keyField = null) : FlexCollectionInterface + public static function createFromArray(array $entries, FlexDirectory $directory, string $keyField = null) { $instance = new static($entries, $directory); $instance->setKeyField($keyField); @@ -63,7 +61,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde * @param FlexStorageInterface $storage * @return array */ - public static function loadEntriesFromStorage(FlexStorageInterface $storage) : array + public static function loadEntriesFromStorage(FlexStorageInterface $storage): array { return $storage->getExistingKeys(); } @@ -72,58 +70,104 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde * Initializes a new FlexIndex. * * @param array $entries - * @param FlexDirectory $flexDirectory + * @param FlexDirectory|null $directory */ - public function __construct(array $entries, FlexDirectory $flexDirectory) + public function __construct(array $entries = [], FlexDirectory $directory = null) { parent::__construct($entries); - $this->_flexDirectory = $flexDirectory; + $this->_flexDirectory = $directory; $this->setKeyField(null); } /** - * @param string $search - * @param string|string[]|null $properties - * @param array|null $options - * @return FlexCollectionInterface + * {@inheritdoc} + * @see FlexCollectionInterface::search() */ - public function search(string $search, $properties = null, array $options = null) // : FlexCollectionInterface + public function search(string $search, $properties = null, array $options = null) { return $this->__call('search', [$search, $properties, $options]); } /** - * @return FlexDirectory + * {@inheritdoc} + * @see FlexCollectionInterface::sort() */ - public function getFlexDirectory() : FlexDirectory + public function sort(array $orderings) + { + return $this->orderBy($orderings); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexType() + */ + public function getFlexType(): string + { + return $this->_flexDirectory->getType(); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexDirectory() + */ + public function getFlexDirectory(): FlexDirectory { return $this->_flexDirectory; } /** - * @param bool $prefix - * @return string + * {@inheritdoc} + * @see FlexCollectionInterface::getTimestamp() */ - public function getType($prefix = false) + public function getTimestamp(): int { - $type = $prefix ? $this->getTypePrefix() : ''; + $timestamps = $this->getTimestamps(); - return $type . $this->_flexDirectory->getType(); + return $timestamps ? max($timestamps) : time(); } /** - * @return string[] + * {@inheritdoc} + * @see FlexCollectionInterface::getCacheKey() */ - public function getStorageKeys() + public function getCacheKey(): string + { + return $this->getTypePrefix() . $this->getFlexType() . '.' . sha1(json_encode($this->getKeys()) . $this->_keyField); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getCacheChecksum() + */ + public function getCacheChecksum(): string + { + return sha1($this->getCacheKey() . json_encode($this->getTimestamps())); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getTimestamps() + */ + public function getTimestamps(): array + { + return $this->getIndexMap('storage_timestamp'); + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getStorageKeys() + */ + public function getStorageKeys(): array { return $this->getIndexMap('storage_key'); } /** - * @return string[] + * {@inheritdoc} + * @see FlexCollectionInterface::getFlexKeys() */ - public function getFlexKeys() + public function getFlexKeys(): array { // Get storage keys for the objects. $keys = []; @@ -137,53 +181,10 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde } /** - * @return int[] + * {@inheritdoc} + * @see FlexIndexInterface::withKeyField() */ - public function getTimestamps() - { - return $this->getIndexMap('storage_timestamp'); - } - - /** - * @return $this - */ - public function getIndex(): FlexIndexInterface - { - return $this; - } - - /** - * @param string $indexKey - * @return array - */ - public function getIndexMap(string $indexKey = null) - { - if (null === $indexKey) { - return $this->getEntries(); - } - - // Get storage keys for the objects. - $index = []; - foreach ($this->getEntries() as $key => $value) { - $index[$key] = $value[$indexKey] ?? null; - } - - return $index; - } - - /** - * @return array - */ - public function getMetaData(string $key) : array - { - return $this->getEntries()[$key] ?? []; - } - - /** - * @param string $keyField - * @return FlexCollectionInterface - */ - public function withKeyField(string $keyField = null): FlexCollectionInterface + public function withKeyField(string $keyField = null) { $keyField = $keyField ?: 'key'; if ($keyField === $this->getKeyField()) { @@ -207,6 +208,65 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde return $this->createFrom($entries, $keyField); } + /** + * {@inheritdoc} + * @see FlexCollectionInterface::getIndex() + */ + public function getIndex() + { + return $this; + } + + /** + * {@inheritdoc} + * @see FlexCollectionInterface::render() + */ + public function render($layout = null, array $context = []) + { + return $this->__call('render', [$layout, $context]); + } + + /** + * @param bool $prefix + * @return string + * @deprecated 1.6 Use `->getFlexType()` instead. + */ + public function getType($prefix = false) + { + user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getFlexType() method instead', E_USER_DEPRECATED); + + $type = $prefix ? $this->getTypePrefix() : ''; + + return $type . $this->getFlexType(); + } + + /** + * {@inheritdoc} + * @see FlexIndexInterface::getFlexKeys() + */ + public function getIndexMap(string $indexKey = null) + { + if (null === $indexKey) { + return $this->getEntries(); + } + + // Get storage keys for the objects. + $index = []; + foreach ($this->getEntries() as $key => $value) { + $index[$key] = $value[$indexKey] ?? null; + } + + return $index; + } + + /** + * @return array + */ + public function getMetaData(string $key): array + { + return $this->getEntries()[$key] ?? []; + } + /** * @return string */ @@ -219,27 +279,11 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde * @param string|null $namespace * @return CacheInterface */ - public function getCache(string $namespace = null): CacheInterface + public function getCache(string $namespace = null) { return $this->_flexDirectory->getCache($namespace); } - /** - * @return string - */ - public function getCacheKey() - { - return $this->getType(true) . '.' . sha1(json_encode($this->getKeys()) . $this->_keyField); - } - - /** - * @return string - */ - public function getCacheChecksum() - { - return sha1($this->getCacheKey() . json_encode($this->getTimestamps())); - } - /** * @param array $orderings * @return FlexIndex|FlexCollection @@ -302,6 +346,8 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde $className = $this->_flexDirectory->getCollectionClass(); $cachedMethods = $className::getCachedMethods(); + $flexType = $this->getFlexType(); + if (!empty($cachedMethods[$name])) { $type = $cachedMethods[$name]; if ($type === 'session') { @@ -311,7 +357,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde } else { $cacheKey = ''; } - $key = $this->getType(true) . '.' . sha1($name . '.' . $cacheKey . json_encode($arguments) . $this->getCacheKey()); + $key = "{$flexType}.idx." . sha1($name . '.' . $cacheKey . json_encode($arguments) . $this->getCacheKey()); $cache = $this->getCache('object'); @@ -319,7 +365,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde $result = $cache->get($key); // Make sure the keys aren't changed if the returned type is the same index type. - if ($result instanceof self && $this->getType(true) === $result->getType(true)) { + if ($result instanceof self && $flexType === $result->getFlexType()) { $result = $result->withKeyField($this->getKeyField()); } } catch (InvalidArgumentException $e) { @@ -368,7 +414,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde */ public function serialize() { - return serialize(['type' => $this->getType(false), 'entries' => $this->getEntries()]); + return serialize(['type' => $this->getFlexType(), 'entries' => $this->getEntries()]); } /** @@ -376,7 +422,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde */ public function unserialize($serialized) { - $data = unserialize($serialized); + $data = unserialize($serialized, ['allowed_classes' => false]); $this->_flexDirectory = Grav::instance()['flex_objects']->getDirectory($data['type']); $this->setEntries($data['entries']); @@ -637,7 +683,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde public function __debugInfo() { return [ - 'type:private' => $this->getType(false), + 'type:private' => $this->getFlexType(), 'key:private' => $this->getKey(), 'entries_key:private' => $this->getKeyField(), 'entries:private' => $this->getEntries() diff --git a/system/src/Grav/Framework/Flex/FlexObject.php b/system/src/Grav/Framework/Flex/FlexObject.php index 5e03b9e98..4c8882187 100644 --- a/system/src/Grav/Framework/Flex/FlexObject.php +++ b/system/src/Grav/Framework/Flex/FlexObject.php @@ -10,15 +10,14 @@ namespace Grav\Framework\Flex; use Grav\Common\Data\Blueprint; -use Grav\Common\Data\ValidationException; use Grav\Common\Debugger; use Grav\Common\Grav; use Grav\Common\Twig\Twig; use Grav\Common\Utils; use Grav\Framework\Cache\CacheInterface; -use Grav\Framework\ContentBlock\ContentBlockInterface; use Grav\Framework\ContentBlock\HtmlBlock; use Grav\Framework\Flex\Interfaces\FlexAuthorizeInterface; +use Grav\Framework\Flex\Interfaces\FlexCollectionInterface; use Grav\Framework\Flex\Interfaces\FlexFormInterface; use Grav\Framework\Flex\Traits\FlexAuthorizeTrait; use Grav\Framework\Object\Access\NestedArrayAccessTrait; @@ -26,6 +25,7 @@ use Grav\Framework\Object\Access\NestedPropertyTrait; use Grav\Framework\Object\Access\OverloadedPropertyTrait; use Grav\Framework\Object\Base\ObjectTrait; use Grav\Framework\Flex\Interfaces\FlexObjectInterface; +use Grav\Framework\Object\Interfaces\ObjectInterface; use Grav\Framework\Object\Property\LazyPropertyTrait; use Psr\SimpleCache\InvalidArgumentException; use RocketTheme\Toolbox\Event\Event; @@ -60,11 +60,12 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @return array */ - public static function getCachedMethods() + public static function getCachedMethods(): array { return [ 'getTypePrefix' => true, 'getType' => true, + 'getFlexType' => true, 'getFlexDirectory' => true, 'getCacheKey' => true, 'getCacheChecksum' => true, @@ -79,25 +80,21 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface ]; } - public static function createFromStorage(array $elements, array $storage, FlexDirectory $flexDirectory, $validate = false) + public static function createFromStorage(array $elements, array $storage, FlexDirectory $directory, bool $validate = false) { - $instance = new static($elements, $storage['key'], $flexDirectory, $validate); + $instance = new static($elements, $storage['key'], $directory, $validate); $instance->setStorage($storage); return $instance; } /** - * @param array $elements - * @param string $key - * @param FlexDirectory $flexDirectory - * @param bool $validate - * @throws \InvalidArgumentException - * @throws ValidationException + * {@inheritdoc} + * @see FlexObjectInterface::__construct() */ - public function __construct(array $elements, $key, FlexDirectory $flexDirectory, $validate = false) + public function __construct(array $elements, $key, FlexDirectory $directory, bool $validate = false) { - $this->_flexDirectory = $flexDirectory; + $this->_flexDirectory = $directory; if ($validate) { $blueprint = $this->getFlexDirectory()->getBlueprint(); @@ -113,10 +110,53 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface } /** - * @param string $search - * @param string|string[]|null $properties - * @param array|null $options - * @return float + * {@inheritdoc} + * @see FlexObjectInterface::getFlexType() + */ + public function getFlexType(): string + { + return $this->_flexDirectory->getType(); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getFlexDirectory() + */ + public function getFlexDirectory(): FlexDirectory + { + return $this->_flexDirectory; + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getTimestamp() + */ + public function getTimestamp(): int + { + return $this->_storage['storage_timestamp'] ?? 0; + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getCacheKey() + */ + public function getCacheKey(): string + { + return $this->getTypePrefix() . $this->getFlexType() . '.' . $this->getStorageKey(); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getCacheChecksum() + */ + public function getCacheChecksum(): string + { + return (string)$this->getTimestamp(); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::search() */ public function search(string $search, $properties = null, array $options = null): float { @@ -131,6 +171,53 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return $weight > 0 ? min($weight, 1) : 0; } + /** + * {@inheritdoc} + * @see ObjectInterface::getFlexKey() + */ + public function getKey() + { + return $this->_key ?: $this->getFlexType() . '@@' . spl_object_hash($this); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getFlexKey() + */ + public function getFlexKey(): string + { + return $this->_storage['flex_key'] ?? $this->_flexDirectory->getType() . '.obj:' . $this->getStorageKey(); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getStorageKey() + */ + public function getStorageKey(): string + { + return $this->_storage['storage_key'] ?? $this->getTypePrefix() . $this->getFlexType() . '@@' . spl_object_hash($this); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getMetaData() + */ + public function getMetaData(): array + { + return $this->getStorage(); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::exists() + */ + public function exists(): bool + { + $key = $this->getStorageKey(); + + return $key && $this->getFlexDirectory()->getStorage()->hasKey($key); + } + /** * @param string $property * @param string $search @@ -192,56 +279,12 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return 0; } - /** - * @param array $data - * @param array $files - * @return $this - * @throws ValidationException - */ - public function update(array $data, array $files = []) - { - if ($data) { - $blueprint = $this->getBlueprint(); - - // Process updated data through the object filters. - $this->filterElements($data); - - // Get currently stored data. - $elements = $this->getElements(); - - // Merge existing object to the test data to be validated. - $test = $blueprint->mergeData($elements, $data); - - // Validate and filter elements and throw an error if any issues were found. - $blueprint->validate($test + ['storage_key' => $this->getStorageKey(), 'timestamp' => $this->getTimestamp()]); - $data = $blueprint->filter($data, false, true); - - // Finally update the object. - foreach ($blueprint->flattenData($data) as $key => $value) { - if ($value === null) { - $this->unsetNestedProperty($key); - } else { - $this->setNestedProperty($key, $value); - } - } - - // Store the changes - $this->_changes = Utils::arrayDiffMultidimensional($this->getElements(), $elements); - } - - if ($files && method_exists($this, 'setUpdatedMedia')) { - $this->setUpdatedMedia($files); - } - - return $this; - } - /** * Get any changes based on data sent to update * * @return array */ - public function getChanges() + public function getChanges(): array { return $this->_changes ?? []; } @@ -249,7 +292,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @return string */ - protected function getTypePrefix() + protected function getTypePrefix(): string { return 'o.'; } @@ -257,43 +300,15 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @param bool $prefix * @return string + * @deprecated 1.6 Use `->getFlexType()` instead. */ public function getType($prefix = false) { + user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getFlexType() method instead', E_USER_DEPRECATED); + $type = $prefix ? $this->getTypePrefix() : ''; - return $type . $this->_flexDirectory->getType(); - } - - /** - * @return FlexDirectory - */ - public function getFlexDirectory() : FlexDirectory - { - return $this->_flexDirectory; - } - - /** - * @param string $name - * @param array|null $form - * @return FlexFormInterface - */ - public function getForm(string $name = '', array $form = null): FlexFormInterface - { - if (!isset($this->_forms[$name])) { - $this->_forms[$name] = $this->createFormObject($name, $form); - } - - return $this->_forms[$name]; - } - - /** - * @param string $name - * @return Blueprint - */ - public function getBlueprint(string $name = '') - { - return $this->_flexDirectory->getBlueprint($name ? '.' . $name : $name); + return $type . $this->getFlexType(); } /** @@ -307,57 +322,15 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return $this->getBlueprint(); } - /** - * Returns a string representation of this object. - * - * @return string - */ - public function getFlexKey() - { - return $this->_storage['flex_key'] ?? $this->_flexDirectory->getType() . '.obj:' . $this->getStorageKey(); - } - /** * @param string|null $namespace * @return CacheInterface */ - public function getCache(string $namespace = null): CacheInterface + public function getCache(string $namespace = null) { return $this->_flexDirectory->getCache($namespace); } - /** - * @return string - */ - public function getCacheKey() - { - return $this->getType(true) . '.' . $this->getStorageKey(); - } - - /** - * @return string - */ - public function getCacheChecksum() - { - return (string)$this->getTimestamp(); - } - - /** - * @return array - */ - public function getMetaData() - { - return $this->getStorage(); - } - - /** - * @return string - */ - public function getStorageKey() - { - return $this->_storage['storage_key'] ?? $this->getType(true) . '@@' . spl_object_hash($this); - } - /** * @param string|null $key * @return $this @@ -369,14 +342,6 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return $this; } - /** - * @return int - */ - public function getTimestamp() : int - { - return $this->_storage['storage_timestamp'] ?? 0; - } - /** * @param int $timestamp * @return $this @@ -389,15 +354,8 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface } /** - * Twig example: {% render object layout 'edit' with {my_check: true} %} - * - * @param string $layout - * @param array $context - * @return ContentBlockInterface|HtmlBlock - * @throws \Exception - * @throws \Throwable - * @throws LoaderError - * @throws SyntaxError + * {@inheritdoc} + * @see FlexObjectInterface::render() */ public function render($layout = null, array $context = []) { @@ -405,11 +363,13 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface $layout = 'default'; } + $type = $this->getFlexType(); + $grav = Grav::instance(); /** @var Debugger $debugger */ $debugger = $grav['debugger']; - $debugger->startTimer('flex-object-' . ($debugKey = uniqid($this->getType(false), false)), 'Render Object ' . $this->getType(false) . ' (' . $layout . ')'); + $debugger->startTimer('flex-object-' . ($debugKey = uniqid($type, false)), 'Render Object ' . $type . ' (' . $layout . ')'); $cache = $key = null; foreach ($context as $value) { @@ -460,7 +420,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface ); if ($debugger->enabled()) { - $name = $this->getKey() . ' (' . $this->getType(false) . ')'; + $name = $this->getKey() . ' (' . $type . ')'; $output = "\n\n{$output}\n\n"; } @@ -478,36 +438,6 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return $block; } - /** - * Form field compatibility. - * - * @param string $name - * @param mixed $default - * @param string $separator - * @return mixed - */ - public function value($name, $default = null, $separator = null) - { - if ($name === 'storage_key') { - return $this->getStorageKey(); - } - if ($name === 'storage_timestamp') { - return $this->getTimestamp(); - } - - return $this->getNestedProperty($name, $default, $separator); - } - - /** - * @return bool - */ - public function exists() - { - $key = $this->getStorageKey(); - - return $key && $this->getFlexDirectory()->getStorage()->hasKey($key); - } - /** * @return array */ @@ -517,9 +447,10 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface } /** - * @return array + * {@inheritdoc} + * @see FlexObjectInterface::prepareStorage() */ - public function prepareStorage() + public function prepareStorage(): array { return $this->getElements(); } @@ -534,10 +465,50 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface } /** - * Create new object into storage. - * - * @param string|null $key Optional new key. - * @return $this + * {@inheritdoc} + * @see FlexObjectInterface::update() + */ + public function update(array $data, array $files = []) + { + if ($data) { + $blueprint = $this->getBlueprint(); + + // Process updated data through the object filters. + $this->filterElements($data); + + // Get currently stored data. + $elements = $this->getElements(); + + // Merge existing object to the test data to be validated. + $test = $blueprint->mergeData($elements, $data); + + // Validate and filter elements and throw an error if any issues were found. + $blueprint->validate($test + ['storage_key' => $this->getStorageKey(), 'timestamp' => $this->getTimestamp()]); + $data = $blueprint->filter($data, false, true); + + // Finally update the object. + foreach ($blueprint->flattenData($data) as $key => $value) { + if ($value === null) { + $this->unsetNestedProperty($key); + } else { + $this->setNestedProperty($key, $value); + } + } + + // Store the changes + $this->_changes = Utils::arrayDiffMultidimensional($this->getElements(), $elements); + } + + if ($files && method_exists($this, 'setUpdatedMedia')) { + $this->setUpdatedMedia($files); + } + + return $this; + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::create() */ public function create($key = null) { @@ -553,7 +524,8 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface } /** - * @return $this + * {@inheritdoc} + * @see FlexObjectInterface::save() */ public function save() { @@ -593,7 +565,8 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface } /** - * @return $this + * {@inheritdoc} + * @see FlexObjectInterface::delete() */ public function delete() { @@ -619,6 +592,44 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return $this; } + /** + * {@inheritdoc} + * @see FlexObjectInterface::getBlueprint() + */ + public function getBlueprint(string $name = '') + { + return $this->_flexDirectory->getBlueprint($name ? '.' . $name : $name); + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::getForm() + */ + public function getForm(string $name = '', array $form = null) + { + if (!isset($this->_forms[$name])) { + $this->_forms[$name] = $this->createFormObject($name, $form); + } + + return $this->_forms[$name]; + } + + /** + * {@inheritdoc} + * @see FlexObjectInterface::value() + */ + public function value($name, $default = null, $separator = null) + { + if ($name === 'storage_key') { + return $this->getStorageKey(); + } + if ($name === 'storage_timestamp') { + return $this->getTimestamp(); + } + + return $this->getNestedProperty($name, $default, $separator); + } + /** * Returns a string representation of this object. * @@ -632,7 +643,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface public function __debugInfo() { return [ - 'type:private' => $this->getType(false), + 'type:private' => $this->getFlexType(), 'key:private' => $this->getKey(), 'elements:private' => $this->getElements(), 'storage:private' => $this->getStorage() @@ -642,10 +653,10 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @return array */ - protected function doSerialize() + protected function doSerialize(): array { return [ - 'type' => $this->getType(false), + 'type' => $this->getFlexType(), 'key' => $this->getKey(), 'elements' => $this->getElements(), 'storage' => $this->getStorage() @@ -655,7 +666,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @param array $serialized */ - protected function doUnserialize(array $serialized) + protected function doUnserialize(array $serialized): void { $type = $serialized['type'] ?? 'unknown'; @@ -679,7 +690,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @param FlexDirectory $directory */ - public function setFlexDirectory(FlexDirectory $directory) + public function setFlexDirectory(FlexDirectory $directory): void { $this->_flexDirectory = $directory; } @@ -702,7 +713,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface /** * @param string $type * @param string $property - * @return FlexCollection + * @return FlexCollectionInterface */ protected function getCollectionByProperty($type, $property) { @@ -721,7 +732,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface * @return FlexDirectory * @throws \RuntimeException */ - protected function getRelatedDirectory($type) + protected function getRelatedDirectory($type): FlexDirectory { /** @var Flex $flex */ $flex = Grav::instance()['flex_objects']; @@ -747,7 +758,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface $twig = $grav['twig']; try { - return $twig->twig()->resolveTemplate(["flex-objects/layouts/{$this->getType(false)}/object/{$layout}.html.twig"]); + return $twig->twig()->resolveTemplate(["flex-objects/layouts/{$this->getFlexType()}/object/{$layout}.html.twig"]); } catch (LoaderError $e) { /** @var Debugger $debugger */ $debugger = Grav::instance()['debugger']; @@ -764,7 +775,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface * * @param array $elements */ - protected function filterElements(array &$elements) + protected function filterElements(array &$elements): void { if (!empty($elements['storage_key'])) { $this->_storage['storage_key'] = trim($elements['storage_key']); @@ -783,7 +794,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface * @param array|null $form Form fields * @return FlexFormInterface */ - protected function createFormObject(string $name, array $form = null): FlexFormInterface + protected function createFormObject(string $name, array $form = null) { return new FlexForm($name, $this, $form); } diff --git a/system/src/Grav/Framework/Flex/Interfaces/FlexAuthorizeInterface.php b/system/src/Grav/Framework/Flex/Interfaces/FlexAuthorizeInterface.php index 622ebadba..cfcb8a98e 100644 --- a/system/src/Grav/Framework/Flex/Interfaces/FlexAuthorizeInterface.php +++ b/system/src/Grav/Framework/Flex/Interfaces/FlexAuthorizeInterface.php @@ -14,16 +14,19 @@ namespace Grav\Framework\Flex\Interfaces; use Grav\Common\User\Interfaces\UserInterface; /** - * Interface FlexAuthorizeInterface - * @package Grav\Framework\User\Interfaces + * Defines authorization checks for Flex Objects. */ interface FlexAuthorizeInterface { /** - * @param string $action One of: create, read, update, delete, save, list - * @param string|null $scope One of: admin, site - * @param UserInterface|null $user - * @return bool + * Check if user is authorized to perform an action for the object. + * + * @param string $action One of: `create`, `read`, `update`, `delete`, `save`, `list` + * @param string|null $scope One of: `admin`, `site` + * @param UserInterface|null $user Optional user. Defaults to the current user. + * + * @return bool Returns `true` if user is authorized to perform action, `false` otherwise. + * @api */ - public function isAuthorized(string $action, string $scope = null, UserInterface $user = null) : bool; + public function isAuthorized(string $action, string $scope = null, UserInterface $user = null): bool; } diff --git a/system/src/Grav/Framework/Flex/Interfaces/FlexCollectionInterface.php b/system/src/Grav/Framework/Flex/Interfaces/FlexCollectionInterface.php index 90a947b2e..efadcacba 100644 --- a/system/src/Grav/Framework/Flex/Interfaces/FlexCollectionInterface.php +++ b/system/src/Grav/Framework/Flex/Interfaces/FlexCollectionInterface.php @@ -11,53 +11,106 @@ declare(strict_types=1); namespace Grav\Framework\Flex\Interfaces; +use Grav\Framework\Flex\Flex; use Grav\Framework\Object\Interfaces\NestedObjectInterface; use Grav\Framework\Object\Interfaces\ObjectCollectionInterface; use Grav\Framework\Flex\FlexDirectory; /** - * Interface FlexCollectionInterface - * @package Grav\Framework\Flex\Interfaces + * Defines a collection of Flex Objects. + * + * @used-by \Grav\Framework\Flex\FlexCollection + * @since 1.6 */ -interface FlexCollectionInterface extends ObjectCollectionInterface, NestedObjectInterface +interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionInterface, NestedObjectInterface { - /** - * @param array $entries - * @param FlexDirectory $directory - * @param string $keyField - * @return static + * Creates a Flex Collection from an array. + * + * @used-by FlexDirectory::createCollection() Official method to create a Flex Collection. + * + * @param FlexObjectInterface[] $entries Associated array of Flex Objects to be included in the collection. + * @param FlexDirectory $directory Flex Directory where all the objects belong into. + * @param string $keyField Key field used to index the collection. + * + * @return static Returns a new Flex Collection. */ - public static function createFromArray(array $entries, FlexDirectory $directory, string $keyField = null) : FlexCollectionInterface; + public static function createFromArray(array $entries, FlexDirectory $directory, string $keyField = null); /** - * @param array $elements - * @param FlexDirectory $type + * Creates a new Flex Collection. + * + * @used-by FlexDirectory::createCollection() Official method to create Flex Collection. + * + * @param FlexObjectInterface[] $entries Associated array of Flex Objects to be included in the collection. + * @param FlexDirectory $directory Flex Directory where all the objects belong into. + * * @throws \InvalidArgumentException */ - public function __construct(array $elements, FlexDirectory $type); + public function __construct(array $entries = [], FlexDirectory $directory = null); /** - * @param string $search - * @param string|string[]|null $properties - * @param array|null $options - * @return FlexCollectionInterface + * Search a string from the collection. + * + * @param string $search Search string. + * @param string|string[]|null $properties Properties to search for, defaults to configured properties. + * @param array|null $options Search options, defaults to configured options. + * + * @return FlexCollectionInterface Returns a Flex Collection with only matching objects. + * @api */ - public function search(string $search, $properties = null, array $options = null); // : FlexCollection + public function search(string $search, $properties = null, array $options = null); /** - * @return FlexDirectory + * Sort the collection. + * + * @param array $orderings Pair of [property => 'ASC'|'DESC', ...]. + * + * @return FlexCollectionInterface Returns a sorted version from the collection. */ - public function getFlexDirectory(); //: FlexDirectory; + public function sort(array $orderings); /** - * @param string|null $keyField - * @return FlexCollectionInterface + * Get timestamps from all the objects in the collection. + * + * This method can be used for example in caching. + * + * @return int[] Returns [key => timestamp, ...] pairs. */ - public function withKeyField(string $keyField = null): FlexCollectionInterface; + public function getTimestamps(): array; /** - * @return FlexIndexInterface + * Get storage keys from all the objects in the collection. + * + * @see FlexDirectory::getObject() If you want to get Flex Object from the Flex Directory. + * + * @return string[] Returns [key => storage_key, ...] pairs. */ - public function getIndex(): FlexIndexInterface; + public function getStorageKeys(): array; + + /** + * Get Flex keys from all the objects in the collection. + * + * @see Flex::getObjects() If you want to get list of Flex Objects from any Flex Directory. + * + * @return string[] Returns[key => flex_key, ...] pairs. + */ + public function getFlexKeys(): array; + + /** + * Return new collection with a different key. + * + * @param string|null $keyField Switch key field of the collection. + * + * @return FlexCollectionInterface Returns a new Flex Collection with new key field. + * @api + */ + public function withKeyField(string $keyField = null); + + /** + * Get Flex Index from the Flex Collection. + * + * @return FlexIndexInterface Returns a Flex Index from the current collection. + */ + public function getIndex(); } diff --git a/system/src/Grav/Framework/Flex/Interfaces/FlexCommonInterface.php b/system/src/Grav/Framework/Flex/Interfaces/FlexCommonInterface.php new file mode 100644 index 000000000..89f12100f --- /dev/null +++ b/system/src/Grav/Framework/Flex/Interfaces/FlexCommonInterface.php @@ -0,0 +1,85 @@ + [storage_key => xxx, storage_timestamp => 123456, ...]] + */ + public static function loadEntriesFromStorage(FlexStorageInterface $storage): array; + + /** + * Return new collection with a different key. + * + * @param string|null $keyField Switch key field of the collection. + * + * @return FlexIndexInterface Returns a new Flex Collection with new key field. + * @api + */ + public function withKeyField(string $keyField = null); + + /** + * @param string $indexKey * @return array */ - public static function loadEntriesFromStorage(FlexStorageInterface $storage) : array; + public function getIndexMap(string $indexKey = null); } diff --git a/system/src/Grav/Framework/Flex/Interfaces/FlexObjectInterface.php b/system/src/Grav/Framework/Flex/Interfaces/FlexObjectInterface.php index 50351d866..d0f11f6e9 100644 --- a/system/src/Grav/Framework/Flex/Interfaces/FlexObjectInterface.php +++ b/system/src/Grav/Framework/Flex/Interfaces/FlexObjectInterface.php @@ -12,141 +12,173 @@ declare(strict_types=1); namespace Grav\Framework\Flex\Interfaces; use Grav\Common\Data\Blueprint; -use Grav\Framework\ContentBlock\HtmlBlock; -use Grav\Framework\Flex\FlexForm; +use Grav\Framework\Flex\Flex; use Grav\Framework\Object\Interfaces\NestedObjectInterface; use Grav\Framework\Flex\FlexDirectory; +use Psr\Http\Message\UploadedFileInterface; /** - * Interface FlexObjectInterface - * @package Grav\Framework\Flex\Interfaces + * Defines Flex Objects. + * + * @used-by \Grav\Framework\Flex\FlexObject + * @since 1.6 */ -interface FlexObjectInterface extends NestedObjectInterface, \ArrayAccess +interface FlexObjectInterface extends FlexCommonInterface, NestedObjectInterface, \ArrayAccess { /** - * @param array $elements - * @param string $key - * @param FlexDirectory $type + * Construct a new Flex Object instance. + * + * @used-by FlexDirectory::createObject() Method to create Flex Object. + * + * @param array $elements Array of object properties. + * @param string $key Identifier key for the new object. + * @param FlexDirectory $directory Flex Directory the object belongs into. + * @param bool $validate True if the object should be validated against blueprint. + * * @throws \InvalidArgumentException */ - public function __construct(array $elements, $key, FlexDirectory $type); + public function __construct(array $elements, $key, FlexDirectory $directory, bool $validate = false); /** - * Search object, returns weight between 0 and 1. + * Search a string from the object, returns weight between 0 and 1. * * Note: If you override this function, make sure you return value in range 0...1! * - * @param string $search - * @param string|string[]|null $properties - * @param array|null $options - * @return float Weight between 0...1 + * @used-by FlexCollectionInterface::search() If you want to search a string from a Flex Collection. + * + * @param string $search Search string. + * @param string|string[]|null $properties Properties to search for, defaults to configured properties. + * @param array|null $options Search options, defaults to configured options. + * + * @return float Returns a weight between 0 and 1. + * @api */ public function search(string $search, $properties = null, array $options = null): float; /** - * Returns the directory where the object belongs into. + * Get a unique key for the object. * - * @return FlexDirectory - */ - public function getFlexDirectory() : FlexDirectory; - - /** - * Returns a unique key for this object. + * Flex Keys can be used without knowing the Directory the Object belongs into. + * + * @see Flex::getObject() If you want to get Flex Object from any Flex Directory. + * @see Flex::getObjects() If you want to get list of Flex Objects from any Flex Directory. * * NOTE: Please do not override the method! * - * @return string + * @return string Returns Flex Key of the object. + * @api */ - public function getFlexKey(); + public function getFlexKey(): string; /** - * Returns a storage key which is used for figuring out the filename or database id. + * Get an unique storage key (within the directory) which is used for figuring out the filename or database id. * - * @return string - */ - public function getStorageKey(); - - /** - * Returns a cache key which is used for caching the object. + * @see FlexDirectory::getObject() If you want to get Flex Object from the Flex Directory. + * @see FlexDirectory::getCollection() If you want to get Flex Collection with selected keys from the Flex Directory. * - * @return string + * @return string Returns storage key of the Object. + * @api */ - public function getCacheKey(); + public function getStorageKey(): string; /** - * Returns cache checksum for the object. If checksum changes, cache gets invalided. + * Get index data associated to the object. * - * @return string + * @return array Returns metadata of the object. */ - public function getCacheChecksum(); - - /** - * Returns a last updated timestamp for the object. - * - * @return int - */ - public function getTimestamp() : int; - - /** - * @return array - */ - public function getMetaData(); + public function getMetaData(): array; /** * Returns true if the object exists in the storage. * - * @return bool + * @return bool Returns `true` if the object exists, `false` otherwise. + * @api */ - public function exists(); + public function exists(): bool; /** - * @return array + * Prepare object for saving into the storage. + * + * @return array Returns an array of object properties containing only scalars and arrays. */ - public function prepareStorage(); + public function prepareStorage(): array; /** - * @param array $data - * @param array $files - * @return $this + * Updates object in the memory. + * + * @see FlexObjectInterface::save() You need to save the object after calling this method. + * + * @param array $data Data containing updated properties with their values. To unset a value, use `null`. + * @param array|UploadedFileInterface[] $files List of uploaded files to be saved within the object. + * + * @return FlexObjectInterface * @throws \RuntimeException + * @api */ public function update(array $data, array $files = []); /** - * Returns the blueprint for the object. + * Create new object into the storage. * - * @param string $name - * @return Blueprint + * @see FlexDirectory::createObject() If you want to create a new object instance. + * @see FlexObjectInterface::update() If you want to update properties of the object. + * + * @param string|null $key Optional new key. If key isn't given, random key will be associated to the object. + * + * @return FlexObjectInterface + * @throws \RuntimeException if object already exists. + * @api + */ + public function create($key = null); + + /** + * Save object into the storage. + * + * @see FlexObjectInterface::update() If you want to update properties of the object. + * + * @return FlexObjectInterface + * @api + */ + public function save(); + + /** + * Delete object from the storage. + * + * @return FlexObjectInterface + * @api + */ + public function delete(); + + /** + * Returns the blueprint of the object. + * + * @see FlexObjectInterface::getForm() + * @used-by FlexForm::getBlueprint() + * + * @param string $name Name of the Blueprint form. Used to create customized forms for different use cases. + * + * @return Blueprint Returns a Blueprint. */ public function getBlueprint(string $name = ''); /** * Returns a form instance for the object. * - * @param string $name - * @param array|null $form - * @return FlexForm + * @param string $name Name of the form. Can be used to create customized forms for different use cases. + * @param array|null $form Can be used to further customize the form. + * + * @return FlexFormInterface Returns a Form. + * @api */ public function getForm(string $name = '', array $form = null); - /** - * @param string $layout - * @param array $context - * @return HtmlBlock - * @throws \Exception - * @throws \Throwable - * @throws \Twig_Error_Loader - * @throws \Twig_Error_Syntax - */ - public function render($layout = null, array $context = []); - /** * Form field compatibility. * - * @param string $name - * @param mixed $default - * @param string $separator - * @return mixed + * @param string $name Property name. + * @param mixed $default Default value. + * @param string $separator Optional nested property separator. + * @return mixed Returns value of the field. */ public function value($name, $default = null, $separator = null); } diff --git a/system/src/Grav/Framework/Flex/Interfaces/FlexStorageInterface.php b/system/src/Grav/Framework/Flex/Interfaces/FlexStorageInterface.php index 49cb43ab9..1ccb81d00 100644 --- a/system/src/Grav/Framework/Flex/Interfaces/FlexStorageInterface.php +++ b/system/src/Grav/Framework/Flex/Interfaces/FlexStorageInterface.php @@ -12,8 +12,9 @@ declare(strict_types=1); namespace Grav\Framework\Flex\Interfaces; /** - * Interface FlexStorageInterface - * @package Grav\Framework\Flex\Interfaces + * Defines Flex Storage layer. + * + * @since 1.6 */ interface FlexStorageInterface { @@ -24,83 +25,96 @@ interface FlexStorageInterface public function __construct(array $options); /** - * Returns list of all stored keys in [key => timestamp] pairs. + * Returns associated array of all existing storage keys with a timestamp. * - * @return array + * @return array Returns all existing keys as `[key => [storage_key => key, storage_timestamp => timestamp], ...]`. */ - public function getExistingKeys() : array; + public function getExistingKeys(): array; /** - * Check if storage has a row for the key. + * Check if the key exists in the storage. * - * @param string $key - * @return bool + * @param string $key Storage key of an object. + * + * @return bool Returns `true` if the key exists in the storage, `false` otherwise. */ - public function hasKey(string $key) : bool; + public function hasKey(string $key): bool; /** - * Create new rows. New keys will be assigned when the objects are created. + * Create new rows into the storage. * - * @param array $rows Array of rows. - * @return array Returns created rows. Note that existing rows will fail to save and have null value. + * New keys will be assigned when the objects are created. + * + * @param array $rows List of rows as `[row, ...]`. + * + * @return array Returns created rows as `[key => row, ...] pairs. */ - public function createRows(array $rows) : array; + public function createRows(array $rows): array; /** - * Read rows. If you pass object or array as value, that value will be used to save I/O. + * Read rows from the storage. * - * @param array $rows Array of [key => row] pairs. - * @param array $fetched Optional variable for storing only fetched items. - * @return array Returns rows. Note that non-existing rows have null value. + * If you pass object or array as value, that value will be used to save I/O. + * + * @param array $rows Array of `[key => row, ...]` pairs. + * @param array $fetched Optional reference to store only fetched items. + * + * @return array Returns rows. Note that non-existing rows will have `null` as their value. */ - public function readRows(array $rows, array &$fetched = null) : array; + public function readRows(array $rows, array &$fetched = null): array; /** - * Update existing rows. + * Update existing rows in the storage. * - * @param array $rows Array of [key => row] pairs. - * @return array Returns updated rows. Note that non-existing rows will fail to save and have null value. + * @param array $rows Array of `[key => row, ...]` pairs. + * + * @return array Returns updated rows. Note that non-existing rows will not be saved and have `null` as their value. */ - public function updateRows(array $rows) : array; + public function updateRows(array $rows): array; /** - * Delete rows. + * Delete rows from the storage. * - * @param array $rows Array of [key => row] pairs. - * @return array Returns deleted rows. Note that non-existing rows have null value. + * @param array $rows Array of `[key => row, ...]` pairs. + * + * @return array Returns deleted rows. Note that non-existing rows have `null` as their value. */ - public function deleteRows(array $rows) : array; + public function deleteRows(array $rows): array; /** * Replace rows regardless if they exist or not. * - * All rows should have a specified key for this to work. + * All rows should have a specified key for replace to work properly. + * + * @param array $rows Array of `[key => row, ...]` pairs. * - * @param array $rows Array of [key => row] pairs. * @return array Returns both created and updated rows. */ - public function replaceRows(array $rows) : array; + public function replaceRows(array $rows): array; /** * @param string $src * @param string $dst + * * @return bool */ - public function renameRow(string $src, string $dst) : bool; + public function renameRow(string $src, string $dst): bool; /** * Get filesystem path for the collection or object storage. * - * @param string|null $key - * @return string + * @param string|null $key Optional storage key. + * + * @return string Path in the filesystem. Can be URI. */ - public function getStoragePath(string $key = null) : string; + public function getStoragePath(string $key = null): string; /** * Get filesystem path for the collection or object media. * - * @param string|null $key - * @return string + * @param string|null $key Optional storage key. + * + * @return string Path in the filesystem. Can be URI. */ - public function getMediaPath(string $key = null) : string; + public function getMediaPath(string $key = null): string; } diff --git a/system/src/Grav/Framework/Flex/Storage/AbstractFilesystemStorage.php b/system/src/Grav/Framework/Flex/Storage/AbstractFilesystemStorage.php index 689694f8f..f8dfdf1dc 100644 --- a/system/src/Grav/Framework/Flex/Storage/AbstractFilesystemStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/AbstractFilesystemStorage.php @@ -69,7 +69,7 @@ abstract class AbstractFilesystemStorage implements FlexStorageInterface * @param string $filename * @return File */ - protected function getFile(string $filename): File + protected function getFile(string $filename) { $filename = $this->resolvePath($filename); diff --git a/system/src/Grav/Framework/Flex/Storage/FileStorage.php b/system/src/Grav/Framework/Flex/Storage/FileStorage.php index f9f31cc28..e263e6c9f 100644 --- a/system/src/Grav/Framework/Flex/Storage/FileStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/FileStorage.php @@ -11,6 +11,8 @@ declare(strict_types=1); namespace Grav\Framework\Flex\Storage; +use Grav\Framework\Flex\Interfaces\FlexStorageInterface; + /** * Class FileStorage * @package Grav\Framework\Flex\Storage @@ -19,6 +21,7 @@ class FileStorage extends FolderStorage { /** * {@inheritdoc} + * @see FlexStorageInterface::__construct() */ public function __construct(array $options) { @@ -33,8 +36,9 @@ class FileStorage extends FolderStorage /** * {@inheritdoc} + * @see FlexStorageInterface::getMediaPath() */ - public function getMediaPath(string $key = null) : string + public function getMediaPath(string $key = null): string { return $key ? \dirname($this->getStoragePath($key)) . '/' . $key : $this->getStoragePath(); } @@ -42,7 +46,7 @@ class FileStorage extends FolderStorage /** * {@inheritdoc} */ - protected function getKeyFromPath(string $path) : string + protected function getKeyFromPath(string $path): string { return basename($path, $this->dataFormatter->getDefaultFileExtension()); } @@ -50,7 +54,7 @@ class FileStorage extends FolderStorage /** * {@inheritdoc} */ - protected function buildIndex() : array + protected function buildIndex(): array { if (!file_exists($this->getStoragePath())) { return []; diff --git a/system/src/Grav/Framework/Flex/Storage/FolderStorage.php b/system/src/Grav/Framework/Flex/Storage/FolderStorage.php index 9208ba878..603beda57 100644 --- a/system/src/Grav/Framework/Flex/Storage/FolderStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/FolderStorage.php @@ -13,6 +13,7 @@ namespace Grav\Framework\Flex\Storage; use Grav\Common\Filesystem\Folder; use Grav\Common\Grav; +use Grav\Framework\Flex\Interfaces\FlexStorageInterface; use RocketTheme\Toolbox\File\File; use InvalidArgumentException; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; @@ -57,24 +58,27 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::getExistingKeys() */ - public function getExistingKeys() : array + public function getExistingKeys(): array { return $this->buildIndex(); } /** * {@inheritdoc} + * @see FlexStorageInterface::hasKey() */ - public function hasKey(string $key) : bool + public function hasKey(string $key): bool { return $key && !strpos($key, '@@') && file_exists($this->getPathFromKey($key)); } /** * {@inheritdoc} + * @see FlexStorageInterface::createRows() */ - public function createRows(array $rows) : array + public function createRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -90,8 +94,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::readRows() */ - public function readRows(array $rows, array &$fetched = null) : array + public function readRows(array $rows, array &$fetched = null): array { $list = []; foreach ($rows as $key => $row) { @@ -118,8 +123,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::updateRows() */ - public function updateRows(array $rows) : array + public function updateRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -137,8 +143,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::deleteRows() */ - public function deleteRows(array $rows) : array + public function deleteRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -162,8 +169,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::replaceRows() */ - public function replaceRows(array $rows) : array + public function replaceRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -180,8 +188,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::renameRow() */ - public function renameRow(string $src, string $dst) : bool + public function renameRow(string $src, string $dst): bool { if ($this->hasKey($dst)) { throw new \RuntimeException("Cannot rename object: key '{$dst}' is already taken"); @@ -196,8 +205,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::getStoragePath() */ - public function getStoragePath(string $key = null) : string + public function getStoragePath(string $key = null): string { if (null === $key) { $path = $this->dataFolder; @@ -210,8 +220,9 @@ class FolderStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::getMediaPath() */ - public function getMediaPath(string $key = null) : string + public function getMediaPath(string $key = null): string { return null !== $key ? \dirname($this->getStoragePath($key)) : $this->getStoragePath(); } @@ -222,7 +233,7 @@ class FolderStorage extends AbstractFilesystemStorage * @param string $key * @return string */ - public function getPathFromKey(string $key) : string + public function getPathFromKey(string $key): string { return sprintf($this->dataPattern, $this->dataFolder, $key, substr($key, 0, 2)); } @@ -231,7 +242,7 @@ class FolderStorage extends AbstractFilesystemStorage * @param File $file * @return array|null */ - protected function loadFile(File $file) : ?array + protected function loadFile(File $file): ?array { if (!$file->exists()) { return null; @@ -254,7 +265,7 @@ class FolderStorage extends AbstractFilesystemStorage * @param array $data * @return array */ - protected function saveFile(File $file, array $data) : array + protected function saveFile(File $file, array $data): array { try { $file->save($data); @@ -298,7 +309,7 @@ class FolderStorage extends AbstractFilesystemStorage * @param string $dst * @return bool */ - protected function moveFolder(string $src, string $dst) : bool + protected function moveFolder(string $src, string $dst): bool { try { Folder::move($this->resolvePath($src), $this->resolvePath($dst)); @@ -320,7 +331,7 @@ class FolderStorage extends AbstractFilesystemStorage * @param bool $include_target * @return bool */ - protected function deleteFolder(string $path, bool $include_target = false) : bool + protected function deleteFolder(string $path, bool $include_target = false): bool { try { $success = Folder::delete($this->resolvePath($path), $include_target); @@ -343,7 +354,7 @@ class FolderStorage extends AbstractFilesystemStorage * @param string $path * @return string */ - protected function getKeyFromPath(string $path) : string + protected function getKeyFromPath(string $path): string { return basename($path); } @@ -353,7 +364,7 @@ class FolderStorage extends AbstractFilesystemStorage * * @return array */ - protected function buildIndex() : array + protected function buildIndex(): array { $path = $this->getStoragePath(); if (!file_exists($path)) { @@ -424,7 +435,7 @@ class FolderStorage extends AbstractFilesystemStorage /** * @return string */ - protected function getNewKey() : string + protected function getNewKey(): string { // Make sure that the file doesn't exist. do { @@ -437,7 +448,7 @@ class FolderStorage extends AbstractFilesystemStorage /** * @param array $options */ - protected function initOptions(array $options) : void + protected function initOptions(array $options): void { $extension = $this->dataFormatter->getDefaultFileExtension(); $pattern = !empty($options['pattern']) ? $options['pattern'] : $this->dataPattern; diff --git a/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php b/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php index abe1ca486..b33b4ecef 100644 --- a/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php @@ -29,6 +29,7 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::__construct() */ public function __construct(array $options) { @@ -57,24 +58,27 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::getExistingKeys() */ - public function getExistingKeys() : array + public function getExistingKeys(): array { return $this->buildIndex(); } /** * {@inheritdoc} + * @see FlexStorageInterface::hasKey() */ - public function hasKey(string $key) : bool + public function hasKey(string $key): bool { return $key && !strpos($key, '@@') && isset($this->data[$key]); } /** * {@inheritdoc} + * @see FlexStorageInterface::createRows() */ - public function createRows(array $rows) : array + public function createRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -91,8 +95,9 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::readRows() */ - public function readRows(array $rows, array &$fetched = null) : array + public function readRows(array $rows, array &$fetched = null): array { $list = []; foreach ($rows as $key => $row) { @@ -113,8 +118,9 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::updateRows() */ - public function updateRows(array $rows) : array + public function updateRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -132,8 +138,9 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::deleteRows() */ - public function deleteRows(array $rows) : array + public function deleteRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -152,8 +159,9 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::replaceRows() */ - public function replaceRows(array $rows) : array + public function replaceRows(array $rows): array { $list = []; foreach ($rows as $key => $row) { @@ -169,8 +177,9 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::renameRow() */ - public function renameRow(string $src, string $dst) : bool + public function renameRow(string $src, string $dst): bool { if ($this->hasKey($dst)) { throw new \RuntimeException("Cannot rename object: key '{$dst}' is already taken"); @@ -191,16 +200,18 @@ class SimpleStorage extends AbstractFilesystemStorage /** * {@inheritdoc} + * @see FlexStorageInterface::getStoragePath() */ - public function getStoragePath(string $key = null) : string + public function getStoragePath(string $key = null): string { return $this->dataFolder . '/' . $this->dataPattern; } /** * {@inheritdoc} + * @see FlexStorageInterface::getMediaPath() */ - public function getMediaPath(string $key = null) : string + public function getMediaPath(string $key = null): string { return sprintf('%s/%s/%s', $this->dataFolder, basename($this->dataPattern, $this->dataFormatter->getDefaultFileExtension()), $key); } @@ -222,7 +233,7 @@ class SimpleStorage extends AbstractFilesystemStorage * @param string $path * @return string */ - protected function getKeyFromPath(string $path) : string + protected function getKeyFromPath(string $path): string { return basename($path); } @@ -232,7 +243,7 @@ class SimpleStorage extends AbstractFilesystemStorage * * @return array */ - protected function buildIndex() : array + protected function buildIndex(): array { $file = $this->getFile($this->getStoragePath()); $modified = $file->modified(); @@ -253,7 +264,7 @@ class SimpleStorage extends AbstractFilesystemStorage /** * @return string */ - protected function getNewKey() : string + protected function getNewKey(): string { if (null === $this->data) { $this->buildIndex(); diff --git a/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php b/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php index 9d7090df2..236474480 100644 --- a/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php +++ b/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php @@ -31,7 +31,7 @@ use RuntimeException; trait FlexMediaTrait { use MediaTrait { - MediaTrait::getMedia as private getTraitMedia; + MediaTrait::getMedia as protected getExistingMedia; } protected $_uploads; @@ -66,7 +66,7 @@ trait FlexMediaTrait { if ($this->media === null) { /** @var AbstractMedia $media */ - $media = $this->getTraitMedia(); + $media = $this->getExistingMedia(); // Include uploaded media to the object media. /** @var FormFlashFile $upload */ @@ -136,7 +136,7 @@ trait FlexMediaTrait } } - public function uploadMediaFile(UploadedFileInterface $uploadedFile, string $filename = null) : void + public function uploadMediaFile(UploadedFileInterface $uploadedFile, string $filename = null): void { $this->checkUploadedMediaFile($uploadedFile); @@ -187,7 +187,7 @@ trait FlexMediaTrait $this->clearMediaCache(); } - public function deleteMediaFile(string $filename) : void + public function deleteMediaFile(string $filename): void { $grav = Grav::instance(); $language = $grav['language']; diff --git a/system/src/Grav/Framework/Form/Traits/FormTrait.php b/system/src/Grav/Framework/Form/Traits/FormTrait.php index ead301852..24d6a4b54 100644 --- a/system/src/Grav/Framework/Form/Traits/FormTrait.php +++ b/system/src/Grav/Framework/Form/Traits/FormTrait.php @@ -36,7 +36,7 @@ trait FormTrait private $submitted; /** @var string[] */ private $errors; - /** @var \ArrayAccess|null */ + /** @var Data|object|null */ private $data; /** @var array|UploadedFileInterface[] */ private $files; @@ -115,7 +115,7 @@ trait FormTrait /** * @param ServerRequestInterface $request - * @return $this + * @return FormInterface|$this */ public function handleRequest(ServerRequestInterface $request): FormInterface { @@ -132,7 +132,7 @@ trait FormTrait /** * @param ServerRequestInterface $request - * @return $this + * @return FormInterface|$this */ public function setRequest(ServerRequestInterface $request): FormInterface { @@ -187,7 +187,7 @@ trait FormTrait /** * @param array $data * @param UploadedFileInterface[] $files - * @return $this + * @return FormInterface|$this */ public function submit(array $data, array $files = null): FormInterface { diff --git a/system/src/Grav/Framework/Media/Interfaces/MediaCollectionInterface.php b/system/src/Grav/Framework/Media/Interfaces/MediaCollectionInterface.php index 0183e9e9c..e834bc852 100644 --- a/system/src/Grav/Framework/Media/Interfaces/MediaCollectionInterface.php +++ b/system/src/Grav/Framework/Media/Interfaces/MediaCollectionInterface.php @@ -12,6 +12,6 @@ namespace Grav\Framework\Media\Interfaces; /** * Class implements media collection interface. */ -interface MediaCollectionInterface +interface MediaCollectionInterface extends \ArrayAccess, \Countable, \Iterator { }