From 048ecb099a5d722c0b1e5ffd6cfcb50e87e6cd31 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 29 Feb 2016 20:34:33 +0200 Subject: [PATCH] Move BlueprintForm class into toolbox --- composer.lock | 50 +- system/src/Grav/Common/Data/Blueprint.php | 4 +- system/src/Grav/Common/Data/BlueprintForm.php | 483 ------------------ .../src/Grav/Common/Data/BlueprintSchema.php | 4 +- 4 files changed, 28 insertions(+), 513 deletions(-) delete mode 100644 system/src/Grav/Common/Data/BlueprintForm.php diff --git a/composer.lock b/composer.lock index fe3eadfbf..2430230b0 100644 --- a/composer.lock +++ b/composer.lock @@ -637,12 +637,12 @@ "source": { "type": "git", "url": "https://github.com/rockettheme/toolbox.git", - "reference": "cfb20f0396f1dc8e556cdf0e785f311e10742eee" + "reference": "687ca3b95950a07eb0d11f04f0ff0a1a0fab0b49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rockettheme/toolbox/zipball/cfb20f0396f1dc8e556cdf0e785f311e10742eee", - "reference": "cfb20f0396f1dc8e556cdf0e785f311e10742eee", + "url": "https://api.github.com/repos/rockettheme/toolbox/zipball/687ca3b95950a07eb0d11f04f0ff0a1a0fab0b49", + "reference": "687ca3b95950a07eb0d11f04f0ff0a1a0fab0b49", "shasum": "" }, "require": { @@ -652,7 +652,7 @@ "symfony/yaml": ">2.5" }, "require-dev": { - "phpunit/phpunit": "~5.1" + "phpunit/phpunit": "~5.1.5" }, "type": "library", "autoload": { @@ -677,20 +677,20 @@ "php", "rockettheme" ], - "time": "2016-02-25 18:01:13" + "time": "2016-02-29 18:27:06" }, { "name": "symfony/console", - "version": "v2.8.2", + "version": "v2.8.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d" + "reference": "56cc5caf051189720b8de974e4746090aaa10d44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d0239fb42f98dd02e7d342f793c5d2cdee0c478d", - "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d", + "url": "https://api.github.com/repos/symfony/console/zipball/56cc5caf051189720b8de974e4746090aaa10d44", + "reference": "56cc5caf051189720b8de974e4746090aaa10d44", "shasum": "" }, "require": { @@ -737,20 +737,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-01-14 08:33:16" + "time": "2016-02-28 16:20:50" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.2", + "version": "v2.8.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "ee278f7c851533e58ca307f66305ccb9188aceda" + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ee278f7c851533e58ca307f66305ccb9188aceda", - "reference": "ee278f7c851533e58ca307f66305ccb9188aceda", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/78c468665c9568c3faaa9c416a7134308f2d85c3", + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3", "shasum": "" }, "require": { @@ -797,7 +797,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-01-27 05:14:19" }, { "name": "symfony/polyfill-iconv", @@ -919,16 +919,16 @@ }, { "name": "symfony/var-dumper", - "version": "v2.8.2", + "version": "v2.8.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "ab94426d127ad9e95433778a3a451fe9d18f3d6b" + "reference": "19b697abe08833ddf38c3ab0cb1bfad236b13bde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ab94426d127ad9e95433778a3a451fe9d18f3d6b", - "reference": "ab94426d127ad9e95433778a3a451fe9d18f3d6b", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/19b697abe08833ddf38c3ab0cb1bfad236b13bde", + "reference": "19b697abe08833ddf38c3ab0cb1bfad236b13bde", "shasum": "" }, "require": { @@ -978,20 +978,20 @@ "debug", "dump" ], - "time": "2016-01-07 13:38:40" + "time": "2016-02-13 09:21:29" }, { "name": "symfony/yaml", - "version": "v2.8.2", + "version": "v2.8.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8" + "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/34c8a4b51e751e7ea869b8262f883d008a2b81b8", - "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", + "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", "shasum": "" }, "require": { @@ -1027,7 +1027,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-02-23 07:41:20" }, { "name": "twig/twig", diff --git a/system/src/Grav/Common/Data/Blueprint.php b/system/src/Grav/Common/Data/Blueprint.php index 876d0d2b6..c8917e537 100644 --- a/system/src/Grav/Common/Data/Blueprint.php +++ b/system/src/Grav/Common/Data/Blueprint.php @@ -3,9 +3,7 @@ namespace Grav\Common\Data; use Grav\Common\File\CompiledYamlFile; use Grav\Common\Grav; -use RocketTheme\Toolbox\ArrayTraits\Export; -use RocketTheme\Toolbox\ArrayTraits\ExportInterface; -use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters; +use RocketTheme\Toolbox\Blueprints\BlueprintForm; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; /** diff --git a/system/src/Grav/Common/Data/BlueprintForm.php b/system/src/Grav/Common/Data/BlueprintForm.php deleted file mode 100644 index d5b1fc985..000000000 --- a/system/src/Grav/Common/Data/BlueprintForm.php +++ /dev/null @@ -1,483 +0,0 @@ -filename = $filename; - $this->items = $items; - } - - /** - * Set context for import@ and extend@. - * - * @param $context - * @return $this - */ - public function setContext($context) - { - $this->context = $context; - - return $this; - } - - /** - * Set custom overrides for import@ and extend@. - * - * @param array $overrides - * @return $this - */ - public function setOverrides($overrides) - { - $this->overrides = $overrides; - - return $this; - } - - /** - * Load blueprint. - * - * @return $this - */ - public function load() - { - // Only load and extend blueprint if it has not yet been loaded. - if (empty($this->items)) { - // Get list of files. - $files = $this->getFiles($this->filename); - - // Load and extend blueprints. - $data = $this->doLoad($files); - - $this->items = array_shift($data); - - foreach ($data as $content) { - $this->extend($content, true); - } - } - - // Import blueprints. - $this->deepInit($this->items); - - return $this; - } - - /** - * Initialize blueprints with its dynamic fields. - * - * @return $this - */ - public function init() - { - foreach ($this->dynamic as $key => $data) { - // Locate field. - $path = explode('/', $key); - $current = &$this->items; - foreach ($path as $field) { - if (is_object($current)) { - // Handle objects. - if (!isset($current->{$field})) { - $current->{$field} = array(); - } - $current = &$current->{$field}; - } else { - // Handle arrays and scalars. - if (!is_array($current)) { - $current = array($field => array()); - } elseif (!isset($current[$field])) { - $current[$field] = array(); - } - $current = &$current[$field]; - } - } - - // Set dynamic property. - foreach ($data as $property => $call) { - $action = 'dynamic' . ucfirst($call['action']); - - if (method_exists($this, $action)) { - $this->{$action}($current, $property, $call); - } - } - } - - return $this; - } - - - /** - * Get form. - * - * @return array - */ - public function form() - { - return (array) $this->get('form'); - } - - /** - * Get form fields. - * - * @return array - */ - public function fields() - { - return (array) $this->get('form.fields'); - } - - /** - * Extend blueprint with another blueprint. - * - * @param BlueprintForm|array $extends - * @param bool $append - * @return $this - */ - public function extend($extends, $append = false) - { - if ($extends instanceof BlueprintForm) { - $extends = $extends->toArray(); - } - - if ($append) { - $a = $this->items; - $b = $extends; - } else { - $a = $extends; - $b = $this->items; - } - - $this->items = $this->deepMerge($a, $b); - - return $this; - } - - /** - * @param string $name - * @param mixed $value - * @param string $separator - * @param bool $append - * @return $this - */ - public function embed($name, $value, $separator = '/', $append = false) - { - $oldValue = $this->get($name, null, $separator); - - if (is_array($oldValue) && is_array($value)) { - if ($append) { - $a = $oldValue; - $b = $value; - } else { - $a = $value; - $b = $oldValue; - } - - $value = $this->deepMerge($a, $b); - } - - $this->set($name, $value, $separator); - - return $this; - } - - /** - * Get blueprints by using dot notation for nested arrays/objects. - * - * @example $value = $this->resolve('this.is.my.nested.variable'); - * returns ['this.is.my', 'nested.variable'] - * - * @param array $path - * @param string $separator - * @return array - */ - public function resolve(array $path, $separator = '/') - { - $fields = false; - $parts = []; - $current = $this['form.fields']; - $result = [null, null, null]; - - while (($field = current($path)) !== null) { - if (!$fields && isset($current['fields'])) { - if (!empty($current['array'])) { - $result = [$current, $parts, $path ? implode($separator, $path) : null]; - // Skip item offset. - $parts[] = array_shift($path); - } - - $current = $current['fields']; - $fields = true; - - } elseif (isset($current[$field])) { - $parts[] = array_shift($path); - $current = $current[$field]; - $fields = false; - - } elseif (isset($current['.' . $field])) { - $parts[] = array_shift($path); - $current = $current['.' . $field]; - $fields = false; - - } else { - break; - } - } - - return $result; - } - - /** - * Deep merge two arrays together. - * - * @param array $a - * @param array $b - * @return array - */ - protected function deepMerge(array $a, array $b) - { - $bref_stack = array(&$a); - $head_stack = array($b); - - do { - end($bref_stack); - $bref = &$bref_stack[key($bref_stack)]; - $head = array_pop($head_stack); - unset($bref_stack[key($bref_stack)]); - - foreach (array_keys($head) as $key) { - if (isset($key, $bref[$key]) && is_array($bref[$key]) && is_array($head[$key])) { - $bref_stack[] = &$bref[$key]; - $head_stack[] = $head[$key]; - } else { - $bref = array_merge($bref, [$key => $head[$key]]); - } - } - } while (count($head_stack)); - - return $a; - } - - /** - * @param array $items - * @param array $path - * @return string - */ - protected function deepInit(array &$items, $path = []) - { - $ordering = ''; - $order = []; - $field = end($path) === 'fields'; - - foreach ($items as $key => &$item) { - // Set name for nested field. - if ($field && isset($item['type'])) { - $item['name'] = $key; - } - - // Handle special instructions in the form. - if (!empty($key) && ($key[0] === '@' || $key[strlen($key) - 1] === '@')) { - $name = trim($key, '@'); - - switch ($name) { - case 'import': - $this->doImport($item, $path); - unset($items[$key]); - break; - case 'ordering': - $ordering = $item; - unset($items[$key]); - break; - default: - $list = explode('-', trim($name, '@'), 2); - $action = array_shift($list); - $property = array_shift($list); - - $this->dynamic[implode('/', $path)][$property] = ['action' => $action, 'params' => $item]; - } - - } elseif (is_array($item)) { - // Recursively initialize form. - $newPath = array_merge($path, [$key]); - - $location = $this->deepInit($item, $newPath); - if ($location) { - $order[$key] = $location; - } - } - } - - if ($order) { - // Reorder fields if needed. - $items = $this->doReorder($items, $order); - } - - return $ordering; - } - - /** - * @param array $value - * @param array $path - */ - protected function doImport(array &$value, array &$path) - { - $type = !is_string($value) ? !isset($value['type']) ? null : $value['type'] : $value; - - $files = $this->getFiles($type, isset($value['context']) ? $value['context'] : null); - - if (!$files) { - return; - } - - /** @var BlueprintForm $blueprint */ - $blueprint = new static($files); - $blueprint->setContext($this->context)->setOverrides($this->overrides)->load(); - - $name = implode('/', $path); - - $this->embed($name, $blueprint->form(), '/', false); - } - - /** - * Internal function that handles loading extended blueprints. - * - * @param array $files - * @return array - */ - protected function doLoad(array $files) - { - $filename = array_shift($files); - $content = $this->loadFile($filename); - - $extends = isset($content['@extends']) ? (array) $content['@extends'] - : (isset($content['extends@']) ? (array) $content['extends@'] : null); - - $data = isset($extends) ? $this->doExtend($files, $extends) : []; - $data[] = $content; - - return $data; - } - - /** - * Internal function to recursively load extended blueprints. - * - * @param array $parents - * @param array $extends - * @return array - */ - protected function doExtend(array $parents, array $extends) - { - if (is_string(key($extends))) { - $extends = [$extends]; - } - - $data = []; - foreach ($extends as $value) { - // Accept array of type and context or a string. - $type = !is_string($value) - ? !isset($value['type']) ? null : $value['type'] : $value; - - if (!$type) { - continue; - } - - if ($type === '@parent' || $type === 'parent@') { - $files = $parents; - } else { - $files = $this->getFiles($type, isset($value['context']) ? $value['context'] : null); - } - - if ($files) { - $data = array_merge($data, $this->doLoad($files)); - } - } - - return $data; - } - - /** - * Internal function to reorder items. - * - * @param array $items - * @param array $keys - * @return array - */ - protected function doReorder(array $items, array $keys) - { - $reordered = array_keys($items); - - foreach ($keys as $item => $ordering) { - if ((string)(int) $ordering === (string) $ordering) { - $location = array_search($item, $reordered); - $rel = array_splice($reordered, $location, 1); - array_splice($reordered, $ordering, 0, $rel); - - } elseif (isset($items[$ordering])) { - $location = array_search($item, $reordered); - $rel = array_splice($reordered, $location, 1); - $location = array_search($ordering, $reordered); - array_splice($reordered, $location + 1, 0, $rel); - } - } - - return array_merge(array_flip($reordered), $items); - } -} diff --git a/system/src/Grav/Common/Data/BlueprintSchema.php b/system/src/Grav/Common/Data/BlueprintSchema.php index 0e3157447..5e8efeb1c 100644 --- a/system/src/Grav/Common/Data/BlueprintSchema.php +++ b/system/src/Grav/Common/Data/BlueprintSchema.php @@ -4,7 +4,7 @@ namespace Grav\Common\Data; use Grav\Common\Grav; use RocketTheme\Toolbox\ArrayTraits\Export; use RocketTheme\Toolbox\ArrayTraits\ExportInterface; -use RocketTheme\Toolbox\Blueprints\Blueprints as BaseBlueprints; +use RocketTheme\Toolbox\Blueprints\BlueprintSchema as BlueprintSchemaBase; /** * Blueprint schema handles the internal logic of blueprints. @@ -12,7 +12,7 @@ use RocketTheme\Toolbox\Blueprints\Blueprints as BaseBlueprints; * @author RocketTheme * @license MIT */ -class BlueprintSchema extends BaseBlueprints implements ExportInterface +class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface { use Export;