Skip to content

Commit d5c04c5

Browse files
backported zendframework/zend-config-aggregator to php 5.3 so it's usable us
1 parent 6db5c7f commit d5c04c5

18 files changed

+621
-0
lines changed

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "zend-pattern/ZendServerDeploymentHelper",
33
"require": {
4+
"php": "^5.3.23 || ^7.0",
45
"zendframework/zend-db": "2.4.8",
56
"zendframework/zend-eventmanager": "2.4.8",
67
"zendframework/zend-i18n": "2.4.8",
@@ -10,6 +11,8 @@
1011
"require-dev": {
1112
"mockery/mockery": "0.9.4",
1213
"phpunit/phpunit": "4.8.36",
14+
"mikey179/vfsStream": "^1.6",
15+
"zendframework/zend-config": "2.4.8",
1316
"zendframework/zend-loader": "2.4.8"
1417
},
1518
"autoload": {

phpunit.xml.dist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
verbose="true"
1515
colors="false">
1616
<testsuites>
17+
<testsuite name="Zend Server DepH ConfigAggregator Suite">
18+
<directory>./tests/ConfigAggregator</directory>
19+
</testsuite>
1720
<testsuite name="Zend Server DepH Deployment Suite">
1821
<directory>./tests/Deployment</directory>
1922
</testsuite>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-config-aggregator for the canonical source repository
4+
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @copyright Copyright (c) 2015-2016 Mateusz Tymek (http://mateusztymek.pl)
6+
* @license https://github.com/zendframework/zend-config-aggregator/blob/master/LICENSE.md New BSD License
7+
*/
8+
namespace ZendServer\DepH\ConfigAggregator;
9+
/**
10+
* Provider that returns the array seeded to itself.
11+
*
12+
* Primary use case is configuration cache-related settings.
13+
*/
14+
class ArrayProvider
15+
{
16+
/**
17+
* @var array
18+
*/
19+
private $config;
20+
/**
21+
* @param array $config
22+
*/
23+
public function __construct(array $config)
24+
{
25+
$this->config = $config;
26+
}
27+
/**
28+
* @return array
29+
*/
30+
public function __invoke()
31+
{
32+
return $this->config;
33+
}
34+
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-config-aggregator for the canonical source repository
4+
* @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @copyright Copyright (c) 2015-2016 Mateusz Tymek (http://mateusztymek.pl)
6+
* @license https://github.com/zendframework/zend-config-aggregator/blob/master/LICENSE.md New BSD License
7+
*/
8+
namespace ZendServer\DepH\ConfigAggregator;
9+
10+
use Closure;
11+
use Generator;
12+
use Zend\Stdlib\ArrayUtils\MergeRemoveKey;
13+
use Zend\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
14+
use ZendServer\DepH\ConfigAggregator\Exception\InvalidConfigProviderException;
15+
16+
/**
17+
* Aggregate configuration generated by configuration providers.
18+
*/
19+
class ConfigAggregator
20+
{
21+
const ENABLE_CACHE = 'config_cache_enabled';
22+
const CACHE_TEMPLATE = <<< 'EOT'
23+
<?php
24+
/**
25+
* This configuration cache file was generated by %s
26+
* at %s
27+
*/
28+
return %s;
29+
EOT;
30+
/**
31+
* @var array
32+
*/
33+
private $config;
34+
/**
35+
* @param array $providers Array of providers. These may be callables, or
36+
* string values representing classes that act as providers. If the
37+
* latter, they must be instantiable without constructor arguments.
38+
* @param null|string $cachedConfigFile Configuration cache file; config is
39+
* loaded from this file if present, and written to it if not. null
40+
* disables caching.
41+
*/
42+
public function __construct(
43+
array $providers = array(),
44+
$cachedConfigFile = null
45+
) {
46+
if ($this->loadConfigFromCache($cachedConfigFile)) {
47+
return;
48+
}
49+
$this->config = $this->loadConfigFromProviders($providers);
50+
$this->cacheConfig($this->config, $cachedConfigFile);
51+
}
52+
/**
53+
* @return array
54+
*/
55+
public function getMergedConfig()
56+
{
57+
return $this->config;
58+
}
59+
/**
60+
* Resolve a provider.
61+
*
62+
* If the provider is a string class name, instantiates that class and
63+
* tests if it is callable, returning it if true.
64+
*
65+
* If the provider is a callable, returns it verbatim.
66+
*
67+
* Raises an exception for any other condition.
68+
*
69+
* @param string|callable $provider
70+
* @return callable
71+
* @throws InvalidConfigProviderException
72+
*/
73+
private function resolveProvider($provider)
74+
{
75+
if (is_string($provider)) {
76+
if (! class_exists($provider)) {
77+
throw new InvalidConfigProviderException("Cannot read config from $provider - class cannot be loaded.");
78+
}
79+
$provider = new $provider();
80+
}
81+
if (! is_callable($provider)) {
82+
throw new InvalidConfigProviderException(
83+
sprintf("Cannot read config from %s - config provider must be callable.", get_class($provider))
84+
);
85+
}
86+
return $provider;
87+
}
88+
/**
89+
* Perform a recursive merge of two multi-dimensional arrays.
90+
*
91+
* Copied from https://github.com/zendframework/zend-stdlib/blob/980ce463c29c1a66c33e0eb67961bba895d0e19e/src/ArrayUtils.php#L269
92+
*
93+
* @param array $a
94+
* @param array $b
95+
* @return $a
96+
*/
97+
private function mergeArray(array $a, array $b)
98+
{
99+
foreach ($b as $key => $value) {
100+
if ($value instanceof MergeReplaceKeyInterface) {
101+
$a[$key] = $value->getData();
102+
} elseif (isset($a[$key]) || array_key_exists($key, $a)) {
103+
if ($value instanceof MergeRemoveKey) {
104+
unset($a[$key]);
105+
} elseif (is_int($key)) {
106+
$a[] = $value;
107+
} elseif (is_array($value) && is_array($a[$key])) {
108+
$a[$key] = $this->mergeArray($a[$key], $value);
109+
} else {
110+
$a[$key] = $value;
111+
}
112+
} else {
113+
if (! $value instanceof MergeRemoveKey) {
114+
$a[$key] = $value;
115+
}
116+
}
117+
}
118+
return $a;
119+
}
120+
/**
121+
* Merge configuration from a provider with existing configuration.
122+
*
123+
* @param array $mergedConfig Passed by reference as a performance/resource
124+
* optimization.
125+
* @param mixed|array $config Configuration generated by the $provider.
126+
* @param callable $provider Provider responsible for generating $config;
127+
* used for exception messages only.
128+
* @return void
129+
* @throws InvalidConfigProviderException
130+
*/
131+
private function mergeConfig(&$mergedConfig, $config, $provider)
132+
{
133+
if (!is_callable($provider)) {
134+
throw new InvalidProviderException('Callable provider expected.');
135+
}
136+
137+
if (! is_array($config)) {
138+
$type = '';
139+
if (is_object($provider) && ! $provider instanceof Closure) {
140+
$type = get_class($provider);
141+
}
142+
if ($provider instanceof Closure) {
143+
$type = 'Closure';
144+
}
145+
if (is_callable($provider) && ! $provider instanceof Closure) {
146+
$type = is_string($provider) ? $provider : gettype($provider);
147+
}
148+
throw new InvalidConfigProviderException(sprintf(
149+
'Cannot read config from %s; does not return array',
150+
$type
151+
));
152+
}
153+
$mergedConfig = $this->mergeArray($mergedConfig, $config);
154+
}
155+
/**
156+
* Iterate providers, merging config from each with the previous.
157+
*
158+
* @param array $providers
159+
* @return array
160+
*/
161+
private function loadConfigFromProviders(array $providers)
162+
{
163+
$mergedConfig = array();
164+
foreach ($providers as $provider) {
165+
$provider = $this->resolveProvider($provider);
166+
$config = $provider();
167+
if (! $config instanceof Generator) {
168+
$this->mergeConfig($mergedConfig, $config, $provider);
169+
continue;
170+
}
171+
// Handle generators
172+
foreach ($config as $cfg) {
173+
$this->mergeConfig($mergedConfig, $cfg, $provider);
174+
}
175+
}
176+
return $mergedConfig;
177+
}
178+
/**
179+
* Attempt to load the configuration from a cache file.
180+
*
181+
* @param null|string $cachedConfigFile
182+
* @return bool
183+
*/
184+
private function loadConfigFromCache($cachedConfigFile)
185+
{
186+
if (null === $cachedConfigFile) {
187+
return false;
188+
}
189+
if (! file_exists($cachedConfigFile)) {
190+
return false;
191+
}
192+
$this->config = require $cachedConfigFile;
193+
return true;
194+
}
195+
/**
196+
* Attempt to cache discovered configuration.
197+
*
198+
* @param array $config
199+
* @param null|string $cachedConfigFile
200+
*/
201+
private function cacheConfig(array $config, $cachedConfigFile)
202+
{
203+
if (null === $cachedConfigFile) {
204+
return;
205+
}
206+
if (empty($config[static::ENABLE_CACHE])) {
207+
return;
208+
}
209+
file_put_contents($cachedConfigFile, sprintf(
210+
self::CACHE_TEMPLATE,
211+
get_class($this),
212+
date('c'),
213+
var_export($config, true)
214+
));
215+
}
216+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-config-aggregator for the canonical source repository
4+
* @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @copyright Copyright (c) 2015-2016 Mateusz Tymek (http://mateusztymek.pl)
6+
* @license https://github.com/zendframework/zend-config-aggregator/blob/master/LICENSE.md New BSD License
7+
*/
8+
namespace ZendServer\DepH\ConfigAggregator\Exception;
9+
10+
use RuntimeException;
11+
12+
class InvalidConfigProviderException extends RuntimeException
13+
{
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-config-aggregator for the canonical source repository
4+
* @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @copyright Copyright (c) 2015-2016 Mateusz Tymek (http://mateusztymek.pl)
6+
* @license https://github.com/zendframework/zend-config-aggregator/blob/master/LICENSE.md New BSD License
7+
*/
8+
namespace ZendServer\DepH\ConfigAggregator;
9+
10+
use InvalidArgumentException;
11+
12+
class InvalidProviderException extends InvalidArgumentException
13+
{
14+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-config-aggregator for the canonical source repository
4+
* @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @copyright Copyright (c) 2015-2016 Mateusz Tymek (http://mateusztymek.pl)
6+
* @license https://github.com/zendframework/zend-config-aggregator/blob/master/LICENSE.md New BSD License
7+
*/
8+
namespace ZendServer\DepH\ConfigAggregator;
9+
10+
use Zend\Stdlib\Glob;
11+
12+
/**
13+
* Provide a collection of PHP files returning config arrays.
14+
*/
15+
class PhpFileProvider
16+
{
17+
/** @var string */
18+
private $pattern;
19+
/**
20+
* @param string $pattern A glob pattern by which to look up config files.
21+
*/
22+
public function __construct($pattern)
23+
{
24+
$this->pattern = $pattern;
25+
}
26+
/**
27+
* @return array
28+
*/
29+
public function __invoke()
30+
{
31+
$result = array();
32+
foreach ($this->glob($this->pattern) as $file) {
33+
$result[] = include $file;
34+
}
35+
return $result;
36+
}
37+
38+
/**
39+
* Return a set of filesystem items based on a glob pattern.
40+
*
41+
* Uses the zend-stdlib Glob class for cross-platform globbing, when
42+
* present, falling back to glob() otherwise.
43+
*
44+
* @param string $pattern
45+
* @return array
46+
*/
47+
private function glob($pattern)
48+
{
49+
if (class_exists('Zend\Stdlib\Glob')) {
50+
return Glob::glob($pattern, Glob::GLOB_BRACE);
51+
}
52+
return glob($pattern, GLOB_BRACE);
53+
}
54+
}

0 commit comments

Comments
 (0)