Skip to content

Commit

Permalink
Merge pull request #43 from GeeH/geeh/#3-hotfix-from-old-repo
Browse files Browse the repository at this point in the history
#3 Ported 279 from ZF repository - fixes merging of duplicate delegator factory definitions
  • Loading branch information
Ocramius authored Jun 12, 2020
2 parents 7c42b69 + 316fa33 commit cc4c218
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 3 deletions.
32 changes: 29 additions & 3 deletions src/ServiceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
use Psr\Container\ContainerInterface;
use Laminas\Stdlib\ArrayUtils;

use function array_intersect;
use function array_merge_recursive;
use function class_exists;
use function get_class;
use function gettype;
Expand Down Expand Up @@ -363,7 +363,7 @@ public function configure(array $config)
}

if (isset($config['delegators'])) {
$this->delegators = array_merge_recursive($this->delegators, $config['delegators']);
$this->mergeDelegators($config['delegators']);
}

if (isset($config['shared'])) {
Expand All @@ -384,7 +384,7 @@ public function configure(array $config)
// If lazy service configuration was provided, reset the lazy services
// delegator factory.
if (isset($config['lazy_services']) && ! empty($config['lazy_services'])) {
$this->lazyServices = array_merge_recursive($this->lazyServices, $config['lazy_services']);
$this->lazyServices = ArrayUtils::merge($this->lazyServices, $config['lazy_services']);
$this->lazyServicesDelegator = null;
}

Expand Down Expand Up @@ -737,6 +737,32 @@ private function createLazyServiceDelegatorFactory()
return $this->lazyServicesDelegator;
}

/**
* Merge delegators avoiding multiple same delegators for the same service.
* It works with strings and class instances.
* It's not possible to de-duple anonymous functions
*
* @param string[][]|Factory\DelegatorFactoryInterface[][] $config
* @return string[][]|Factory\DelegatorFactoryInterface[][]
*/
private function mergeDelegators(array $config)
{
foreach ($config as $key => $delegators) {
if (! array_key_exists($key, $this->delegators)) {
$this->delegators[$key] = $delegators;
continue;
}

foreach ($delegators as $delegator) {
if (! in_array($delegator, $this->delegators[$key], true)) {
$this->delegators[$key][] = $delegator;
}
}
}

return $this->delegators;
}

/**
* Create aliases and factories for invokable classes.
*
Expand Down
48 changes: 48 additions & 0 deletions test/ServiceManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Laminas\ServiceManager\ServiceManager;
use LaminasTest\ServiceManager\TestAsset\InvokableObject;
use LaminasTest\ServiceManager\TestAsset\SimpleServiceManager;
use Laminas\ServiceManager\Proxy\LazyServiceFactory;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use stdClass;
Expand Down Expand Up @@ -364,4 +365,51 @@ public function testResolvedAliasNoMatchingAbstractFactoryReturnsFalse()

self::assertFalse($serviceManager->has('Alias'));
}

/**
* @group #3
* @see https://github.com/laminas/laminas-servicemanager/issues/3
*/
public function testConfiguringADelegatorMultipleTimesDoesNotLeadToDuplicateDelegatorCalls()
{
$delegatorFactory = function (
ContainerInterface $container,
$name,
callable $callback
) {
/** @var InvokableObject $instance */
$instance = $callback();
$options = $instance->getOptions();
$inc = $options['inc'] ?? 0;
return new InvokableObject(['inc' => ++$inc]);
};

$config = [
'factories' => [
'Foo' => function () {
return new InvokableObject();
},
],
'delegators' => [
'Foo' => [
$delegatorFactory,
LazyServiceFactory::class,
],
],
'lazy_services' => [
'class_map' => [
'Foo' => InvokableObject::class,
],
],
];

$serviceManager = new ServiceManager($config);
$serviceManager->configure($config);

/** @var InvokableObject $instance */
$instance = $serviceManager->get('Foo');

self::assertInstanceOf(InvokableObject::class, $instance);
self::assertSame(1, $instance->getOptions()['inc']);
}
}

0 comments on commit cc4c218

Please sign in to comment.