Skip to content
This repository was archived by the owner on Feb 6, 2020. It is now read-only.

Commit 3e9cf1e

Browse files
committed
Fixed delegator de-duple
1 parent 3a9f472 commit 3e9cf1e

File tree

2 files changed

+69
-12
lines changed

2 files changed

+69
-12
lines changed

src/ServiceManager.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,8 @@ public function configure(array $config)
361361
$this->factories = $config['factories'] + $this->factories;
362362
}
363363

364-
if (isset($config['delegators'])) {
365-
$this->delegators = ArrayUtils::merge($this->delegators, $config['delegators']);
364+
if (isset($config['delegators']) && ! empty($config['delegators'])) {
365+
$this->mergeDelegators($config['delegators']);
366366
}
367367

368368
if (isset($config['shared'])) {
@@ -736,6 +736,32 @@ private function createLazyServiceDelegatorFactory()
736736
return $this->lazyServicesDelegator;
737737
}
738738

739+
/**
740+
* Merge delegators avoiding multiple same delegators for the same service.
741+
* It works with strings and class instances.
742+
* It's not possibile to de-duple anonymous functions
743+
*
744+
* @param string[][]|Factory\DelegatorFactoryInterface[][] $config
745+
* @return string[][]|Factory\DelegatorFactoryInterface[][]
746+
*/
747+
private function mergeDelegators(array $config): array
748+
{
749+
foreach($config as $key => $delegators) {
750+
if (! isset($this->delegators[$key])) {
751+
$this->delegators[$key] = $delegators;
752+
continue;
753+
}
754+
755+
foreach ($delegators as $delegator) {
756+
if (! in_array($delegator, $this->delegators[$key], true)) {
757+
$this->delegators[$key][] = $delegator;
758+
}
759+
}
760+
}
761+
762+
return $this->delegators;
763+
}
764+
739765
/**
740766
* Create aliases and factories for invokable classes.
741767
*

test/ServiceManagerTest.php

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,27 @@
1212
use Psr\Container\ContainerInterface;
1313
use ReflectionObject;
1414
use stdClass;
15+
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
16+
use Zend\ServiceManager\Exception\ServiceNotFoundException;
1517
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
18+
use Zend\ServiceManager\Factory\ContainerException;
19+
use Zend\ServiceManager\Factory\DelegatorFactoryInterface;
1620
use Zend\ServiceManager\Factory\FactoryInterface;
1721
use Zend\ServiceManager\Factory\InvokableFactory;
22+
use Zend\ServiceManager\Proxy\LazyServiceFactory;
1823
use Zend\ServiceManager\ServiceManager;
1924
use ZendTest\ServiceManager\TestAsset\InvokableObject;
2025
use ZendTest\ServiceManager\TestAsset\SimpleServiceManager;
2126

2227
use function get_class;
2328

29+
interface DecorableInterface
30+
{}
31+
class DecorableClass implements DecorableInterface
32+
{
33+
34+
}
35+
2436
/**
2537
* @covers \Zend\ServiceManager\ServiceManager
2638
*/
@@ -371,27 +383,46 @@ public function testResolvedAliasNoMatchingAbstractFactoryReturnsFalse()
371383
*/
372384
public function testConfigureMultipleTimes()
373385
{
386+
$delegatorFactory = new class {
387+
public function __invoke(
388+
ContainerInterface $container,
389+
$name,
390+
callable $callback
391+
) {
392+
/** @var InvokableObject $instance */
393+
$instance = $callback();
394+
$inc = $instance->getOptions()['inc'] ?? 0;
395+
396+
return new InvokableObject(['inc' => ++$inc]);
397+
}
398+
};
399+
374400
$config = [
401+
'factories' => [
402+
'Foo' => function () {
403+
return new InvokableObject();
404+
},
405+
],
375406
'delegators' => [
376-
'Foo' => 'FooDelegator',
407+
'Foo' => [
408+
$delegatorFactory,
409+
LazyServiceFactory::class,
410+
],
377411
],
378412
'lazy_services' => [
379413
'class_map' => [
380-
'Foo' => 'Foo',
414+
'Foo' => InvokableObject::class,
381415
],
382-
]
416+
],
383417
];
384418

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

388-
$ref = new ReflectionObject($serviceManager);
389-
$delegatorsProperty = $ref->getProperty('delegators');
390-
$delegatorsProperty->setAccessible(true);
391-
$lazyServicesProperty = $ref->getProperty('lazyServices');
392-
$lazyServicesProperty->setAccessible(true);
422+
/** @var InvokableObject $instance */
423+
$instance = $serviceManager->get('Foo');
393424

394-
self::assertSame($config['delegators'], $delegatorsProperty->getValue($serviceManager));
395-
self::assertSame($config['lazy_services'], $lazyServicesProperty->getValue($serviceManager));
425+
self::assertInstanceOf(InvokableObject::class, $instance);
426+
self::assertSame(1, $instance->getOptions()['inc']);
396427
}
397428
}

0 commit comments

Comments
 (0)