Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Commit

Permalink
Merge fdef4cd into ea4d9f3
Browse files Browse the repository at this point in the history
  • Loading branch information
michalbundyra committed Apr 10, 2018
2 parents ea4d9f3 + fdef4cd commit 4770567
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 328 deletions.
19 changes: 13 additions & 6 deletions README.md
Expand Up @@ -32,12 +32,14 @@ $factory = new ContainerFactory();
$container = $factory(
new Config([
'dependencies' => [
'services' => [],
'invokables' => [],
'factories' => [],
'aliases' => [],
'delegators' => [],
'extensions' => [],
'services' => [],
'invokables' => [],
'factories' => [],
'aliases' => [],
'delegators' => [],
'extensions' => [],
'shared' => [],
'shared_by_default' => true,
],
// ... other configuration
])
Expand All @@ -62,6 +64,11 @@ The `dependencies` sub associative array can contain the following keys:
for more details.
- `extensions`: an associative array that maps service names to lists of
extension factory names, see the [the section below](#extensions).
- `shared`: associative array that map a service name to a boolean, in order to
indicate the service manager if it should cache or not a service created
through the get method, independant of the shared_by_default setting.
- `shared_by_default`: boolean that indicates whether services created through
the `get` method should be cached. This is `true` by default.

> Please note, that the whole configuration is available in the `$container`
> on `config` key:
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -23,7 +23,8 @@
},
"require-dev": {
"phpunit/phpunit": "^7.0.2",
"zendframework/zend-coding-standard": "~1.0.0"
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-container-config-test": "^0.1.0"
},
"autoload": {
"psr-4": {
Expand Down
57 changes: 56 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

121 changes: 92 additions & 29 deletions src/Config.php
@@ -1,7 +1,7 @@
<?php
/**
* @see https://github.com/zendframework/zend-pimple-config for the canonical source repository
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (https://www.zend.com)
* @copyright Copyright (c) 2017-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-pimple-config/blob/master/LICENSE.md New BSD License
*/

Expand All @@ -10,9 +10,14 @@
namespace Zend\Pimple\Config;

use Pimple\Container;
use Pimple\Exception\ExpectedInvokableException;
use Pimple\Psr11\Container as PsrContainer;

use function class_exists;
use function is_array;
use function is_callable;
use function is_int;
use function is_string;

class Config implements ConfigInterface
{
Expand All @@ -33,13 +38,15 @@ public function configureContainer(Container $container) : void
) {
$dependencies = $this->config['dependencies'];
}
$dependencies['shared_by_default'] = isset($dependencies['shared_by_default'])
? (bool) $dependencies['shared_by_default']
: true;

$this->injectServices($container, $dependencies);
$this->injectFactories($container, $dependencies);
$this->injectInvokables($container, $dependencies);
$this->injectAliases($container, $dependencies);
$this->injectExtensions($container, $dependencies);
$this->injectDelegators($container, $dependencies);
}

private function injectServices(Container $container, array $dependencies) : void
Expand All @@ -66,15 +73,39 @@ private function injectFactories(Container $container, array $dependencies) : vo
}

foreach ($dependencies['factories'] as $name => $object) {
$container[$name] = function (Container $c) use ($object, $name) {
if ($c->offsetExists($object)) {
$factory = $c->offsetGet($object);
$callback = function () use ($container, $object, $name) {
if (is_callable($object)) {
$factory = $object;
} elseif (is_string($object) && ! class_exists($object)) {
throw new ExpectedInvokableException(sprintf(
'Factory provided to initialize service %s does not exist',
$name
));
} else {
$factory = new $object();
$c[$object] = $c->protect($factory);
}
return $factory(new PsrContainer($c), $name);

if (! is_callable($factory)) {
throw new ExpectedInvokableException(sprintf(
'Factory provided to initialize service %s is not invokable',
$name
));
}

return $factory(new PsrContainer($container), $name);
};

if (isset($dependencies['delegators'][$name])) {
$this->injectDelegator(
$container,
$callback,
$name,
$dependencies['delegators'][$name]
);
continue;
}

$this->setService($container, $dependencies, $name, $callback);
}
}

Expand All @@ -86,16 +117,34 @@ private function injectInvokables(Container $container, array $dependencies) : v
return;
}

foreach ($dependencies['invokables'] as $name => $object) {
if ($name !== $object) {
$container[$name] = function (Container $c) use ($object) {
return $c->offsetGet($object);
};
}
foreach ($dependencies['invokables'] as $alias => $object) {
$callback = function () use ($object) {
if (! class_exists($object)) {
throw new ExpectedInvokableException(sprintf(
'Class %s does not exist',
$object
));
}

$container[$object] = function (Container $c) use ($object) {
return new $object();
};

if (isset($dependencies['delegators'][$object])) {
$this->injectDelegator(
$container,
$callback,
$object,
$dependencies['delegators'][$object]
);
} else {
$this->setService($container, $dependencies, $object, $callback);
}

if (! is_int($alias) && $alias !== $object) {
$container[$alias] = function (Container $c) use ($object) {
return $c->offsetGet($object);
};
}
}
}

Expand Down Expand Up @@ -132,24 +181,38 @@ private function injectExtensions(Container $container, array $dependencies) : v
}
}

private function injectDelegators(Container $container, array $dependencies) : void
private function injectDelegator(Container $container, callable $callback, string $name, array $delegators)
{
if (empty($dependencies['delegators'])
|| ! is_array($dependencies['delegators'])
) {
return;
}
$container[$name] = function (Container $c) use ($callback, $name, $delegators) {
foreach ($delegators as $delegatorClass) {
if (! class_exists($delegatorClass)) {
throw new ExpectedInvokableException();
}

foreach ($dependencies['delegators'] as $name => $delegators) {
foreach ($delegators as $delegator) {
$container->extend($name, function ($service, Container $c) use ($delegator, $name) {
$factory = new $delegator();
$callback = function () use ($service) {
return $service;
};
return $factory(new PsrContainer($c), $name, $callback);
});
$delegator = new $delegatorClass();

if (! is_callable($delegator)) {
throw new ExpectedInvokableException();
}

$instance = $delegator(new PsrContainer($c), $name, $callback);
$callback = function () use ($instance) {
return $instance;
};
}

return $instance ?? $callback();
};
}

private function setService(Container $container, array $dependencies, string $name, callable $callback)
{
if (($dependencies['shared_by_default'] === true && ! isset($dependencies['shared'][$name]))
|| (isset($dependencies['shared'][$name]) && $dependencies['shared'][$name] === true)
) {
$container[$name] = $callback;
} else {
$container[$name] = $container->factory($callback);
}
}
}

0 comments on commit 4770567

Please sign in to comment.