Blueprints: Move duplicated extends@ logic into BlueprintForm class

This commit is contained in:
Matias Griese
2016-02-22 19:57:42 +02:00
parent 30b7aaf2b1
commit 024ae68782
3 changed files with 203 additions and 204 deletions

View File

@@ -3,9 +3,7 @@ namespace Grav\Common\Config;
use Grav\Common\Data\Blueprint;
use Grav\Common\Data\BlueprintForm;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* The Compiled Blueprints class.
@@ -73,91 +71,10 @@ class CompiledBlueprints extends CompiledBase
*/
protected function loadFile($name, $files)
{
$data = $this->loadBlueprints($files);
// Load blueprint file.
$blueprintForm = new BlueprintForm($files);
// Merge all extends into a single blueprint.
$blueprintForm = new BlueprintForm(array_shift($data));
foreach ($data as $content) {
$blueprintForm->extend($content, true);
}
$blueprintForm->init();
$this->object->embed($name, $blueprintForm->toArray(), '/', true);
}
/**
* Internal function that handles loading extended blueprints.
*
* @param array $files
* @return array
*/
protected function loadBlueprints(array $files)
{
$filename = array_shift($files);
$file = CompiledYamlFile::instance($filename);
$content = $file->content();
$file->free();
$extends = isset($content['@extends']) ? (array) $content['@extends']
: (isset($content['extends@']) ? (array) $content['extends@'] : null);
$data = isset($extends) ? $this->extendBlueprint($files, $extends) : [];
$data[] = $content;
return $data;
}
/**
* Internal function to recursively load extended blueprints.
*
* @param array $parents
* @param array $extends
* @return array
*/
protected function extendBlueprint(array $parents, array $extends)
{
if (is_string(key($extends))) {
$extends = [$extends];
}
$data = [];
foreach ($extends as $extendConfig) {
// Accept array of type and context or a string.
$extendType = !is_string($extendConfig)
? !isset($extendConfig['type']) ? null : $extendConfig['type'] : $extendConfig;
if (!$extendType) {
continue;
}
if ($extendType === '@parent' || $extendType === 'parent@') {
$files = $parents;
} else {
if (strpos($extendType, '://')) {
$path = $extendType;
} elseif (empty($extendConfig['context'])) {
$path = "blueprints://{$extendType}";
} else {
$separator = $extendConfig['context'][strlen($extendConfig['context'])-1] === '/' ? '' : '/';
$path = $extendConfig['context'] . $separator . $extendType;
}
if (!preg_match('/\.yaml$/', $path)) {
$path .= '.yaml';
}
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$files = $locator->findResources($path);
}
if ($files) {
$data = array_merge($data, $this->loadBlueprints($files));
}
}
return $data;
$this->object->embed($name, $blueprintForm->load()->toArray(), '/', true);
}
/**

View File

@@ -2,10 +2,11 @@
namespace Grav\Common\Data;
use Grav\Common\File\CompiledYamlFile;
use RocketTheme\Toolbox\ArrayTraits\Constructor;
use Grav\Common\Grav;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* The Config class contains configuration information.
@@ -14,15 +15,116 @@ use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
*/
class BlueprintForm implements \ArrayAccess, ExportInterface
{
use Constructor, NestedArrayAccessWithGetters, Export;
use NestedArrayAccessWithGetters, Export;
/**
* @var array
*/
protected $items;
/**
* @var string
*/
protected $filename;
/**
* @var string
*/
protected $context = 'blueprints://';
/**
* @var array
*/
protected $overrides = [];
/**
* Constructor.
*
* @param string|array $filename
* @param array $items
*/
public function __construct($filename, array $items = [])
{
$this->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(array $overrides)
{
$this->overrides = $overrides;
return $this;
}
/**
* Load blueprint.
*
* @return $this
*/
public function load()
{
$path = $this->filename;
if (is_string($path) && !strpos($path, '://')) {
// Resolve filename.
$path = isset($this->overrides[$path]) ? $this->overrides[$path] : "{$this->context}{$path}";
if (!preg_match('/\.yaml$/', $path)) {
$path .= YAML_EXT;
}
}
// Only load and extend blueprint if it has not yet been loaded.
if (empty($this->items)) {
// Get list of parent files.
if (is_string($path) && strpos($path, '://')) {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$files = $locator->findResources($path);
} else {
$files = (array) $path;
}
// Load and extend blueprints.
$data = $this->doLoad($files);
$this->items = array_shift($data);
foreach ($data as $content) {
$this->extend($content, true);
}
}
// Finally initialize blueprint.
return $this->init();
}
/**
* Initialize blueprint.
*
* @return $this
*/
public function init()
{
// Import blueprints.
$this->deepInit($this->items);
return $this;
@@ -209,7 +311,7 @@ class BlueprintForm implements \ArrayAccess, ExportInterface
if (strpos($type, '://')) {
$filename = $type;
} elseif (empty($value['context'])) {
$filename = "blueprints://{$type}";
$filename = isset($this->overrides[$type]) ? $this->overrides[$type] : "{$this->context}{$type}";
} else {
$separator = $value['context'][strlen($value['context'])-1] === '/' ? '' : '/';
$filename = $value['context'] . $separator . $type;
@@ -218,15 +320,94 @@ class BlueprintForm implements \ArrayAccess, ExportInterface
$filename .= YAML_EXT;
}
if (!is_file($filename)) {
return;
}
$file = CompiledYamlFile::instance($filename);
$blueprint = (new BlueprintForm($file->content()))->init();
$blueprint = (new BlueprintForm($filename))->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);
$file = CompiledYamlFile::instance($filename);
$content = $file->content();
$file->free();
$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 {
if (strpos($type, '://')) {
$path = $type;
} elseif (empty($value['context'])) {
$path = isset($this->overrides[$type]) ? $this->overrides[$type] : "{$this->context}{$type}";
} else {
$separator = $value['context'][strlen($value['context'])-1] === '/' ? '' : '/';
$path = $value['context'] . $separator . $type;
}
if (!preg_match('/\.yaml$/', $path)) {
$path .= YAML_EXT;
}
if (strpos($path, '://')) {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$files = $locator->findResources($path);
} else {
$files = (array) $path;
}
}
if ($files) {
$data = array_merge($data, $this->doLoad($files));
}
}
return $data;
}
}

View File

@@ -1,7 +1,6 @@
<?php
namespace Grav\Common\Data;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
@@ -15,7 +14,7 @@ class Blueprints
{
protected $search;
protected $types;
protected $instances = array();
protected $instances = [];
/**
* @param string|array $search Search path.
@@ -35,25 +34,7 @@ class Blueprints
public function get($type)
{
if (!isset($this->instances[$type])) {
if (!is_string($this->search)) {
$filename = isset($this->search[$type]) ? $this->search[$type] : null;
} else {
$filename = $this->search . $type . YAML_EXT;
}
// Check if search is a stream and resolve the path.
if ($filename && strpos($filename, '://')) {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$files = $locator->findResources($filename);
} else {
$files = (array) $filename;
}
$blueprint = $this->loadFile($type, $files);
$this->instances[$type] = $blueprint->init();
$this->instances[$type] = $this->loadFile($type);
}
return $this->instances[$type];
@@ -90,109 +71,29 @@ class Blueprints
$this->types[$name] = ucfirst(strtr($name, '_', ' '));
}
}
return $this->types;
}
/**
* Load single configuration file and make a blueprint.
* Load blueprint file.
*
* @param string $name Name of the position.
* @param array $files Files to be loaded.
* @param string $name Name of the blueprint.
* @return Blueprint
*/
protected function loadFile($name, $files)
protected function loadFile($name)
{
$data = $this->loadBlueprints($files);
// Merge all extends into a single blueprint.
$blueprintForm = new BlueprintForm(array_shift($data));
foreach ($data as $content) {
$blueprintForm->extend($content, true);
$blueprintForm = new BlueprintForm($name);
if (is_array($this->search)) {
$blueprintForm->setOverrides($this->search);
} else {
$blueprintForm->setContext($this->search);
}
$blueprintForm->init();
$blueprintForm->load();
$blueprint = new Blueprint($name, $blueprintForm->toArray(), $this);
$blueprint = new Blueprint($name, $blueprintForm->toArray());
return $blueprint;
}
/**
* Internal function that handles loading extended blueprints.
*
* @param array $files
* @return array
*/
protected function loadBlueprints(array $files)
{
$filename = array_shift($files);
$file = CompiledYamlFile::instance($filename);
$content = $file->content();
$file->free();
$extends = isset($content['@extends']) ? (array) $content['@extends']
: (isset($content['extends@']) ? (array) $content['extends@'] : null);
$data = isset($extends) ? $this->extendBlueprint($files, $extends) : [];
$data[] = $content;
return $data;
}
/**
* Internal function to recursively load extended blueprints.
*
* @param array $parents
* @param array $extends
* @return array
*/
protected function extendBlueprint(array $parents, array $extends)
{
if (is_string(key($extends))) {
$extends = [$extends];
}
$data = [];
foreach ($extends as $extendConfig) {
// Accept array of type and context or a string.
$extendType = !is_string($extendConfig)
? !isset($extendConfig['type']) ? null : $extendConfig['type'] : $extendConfig;
if (!$extendType) {
continue;
}
if ($extendType === '@parent' || $extendType === 'parent@') {
$files = $parents;
} else {
if (strpos($extendType, '://')) {
$path = $extendType;
} elseif (empty($extendConfig['context'])) {
$path = isset($this->search[$extendType]) ? $this->search[$extendType] : "blueprints://{$extendType}";
} else {
$separator = $extendConfig['context'][strlen($extendConfig['context'])-1] === '/' ? '' : '/';
$path = $extendConfig['context'] . $separator . $extendType;
}
if (!preg_match('/\.yaml$/', $path)) {
$path .= '.yaml';
}
if (strpos($path, '://')) {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$files = $locator->findResources($path);
} else {
$files = (array) $path;
}
}
if ($files) {
$data = array_merge($data, $this->loadBlueprints($files));
}
}
return $data;
return $blueprint->init();
}
}