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

Commit 9f6051c

Browse files
committed
Merge branch 'feature/16' into develop
Close #16
2 parents 966ff89 + 685d41e commit 9f6051c

File tree

4 files changed

+211
-37
lines changed

4 files changed

+211
-37
lines changed

src/Proxy/LazyServiceFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $
4747
/**
4848
* {@inheritDoc}
4949
*
50-
* @return object|\ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface
50+
* @return \ProxyManager\Proxy\VirtualProxyInterface
5151
*/
5252
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null)
5353
{

src/ServiceManager.php

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -241,23 +241,34 @@ public function has($name, $checkAbstractFactories = false)
241241
*/
242242
protected function configure(array $config)
243243
{
244-
$this->services = (isset($config['services']) ? $config['services'] : []) + $this->services;
245-
$this->factories = (isset($config['factories']) ? $config['factories'] : []) + $this->factories;
246-
$this->delegators = array_merge_recursive($this->delegators, isset($config['delegators'])
247-
? $config['delegators']
248-
: []);
249-
$this->shared = (isset($config['shared']) ? $config['shared'] : []) + $this->shared;
250-
$this->aliases = (isset($config['aliases']) ? $config['aliases'] : []) + $this->aliases;
251-
$this->lazyServices = array_merge_recursive($this->lazyServices, isset($config['lazy_services'])
252-
? $config['lazy_services']
253-
: []);
254-
$this->sharedByDefault = isset($config['shared_by_default'])
255-
? $config['shared_by_default']
256-
: $this->sharedByDefault;
244+
if (isset($config['services'])) {
245+
$this->services = $config['services'] + $this->services;
246+
}
247+
248+
if (isset($config['factories'])) {
249+
$this->factories = $config['factories'] + $this->factories;
250+
}
251+
252+
if (isset($config['delegators'])) {
253+
$this->delegators = array_merge_recursive($this->delegators, $config['delegators']);
254+
}
255+
256+
if (isset($config['shared'])) {
257+
$this->shared = $config['shared'] + $this->shared;
258+
}
259+
260+
if (isset($config['aliases'])) {
261+
$this->aliases = $config['aliases'] + $this->aliases;
262+
}
263+
264+
if (isset($config['shared_by_default'])) {
265+
$this->sharedByDefault = $config['shared_by_default'];
266+
}
257267

258268
// If lazy service configuration was provided, reset the lazy services
259269
// delegator factory.
260270
if (isset($config['lazy_services']) && ! empty($config['lazy_services'])) {
271+
$this->lazyServices = array_merge_recursive($this->lazyServices, $config['lazy_services']);
261272
$this->lazyServicesDelegator = null;
262273
}
263274

@@ -435,8 +446,7 @@ private function createDelegatorFromName($name, array $options = null)
435446
}
436447

437448
throw new ServiceNotCreatedException(sprintf(
438-
'A non-callable delegator, "%s", was provided; expected a callable or '
439-
. 'instance of "%s"',
449+
'A non-callable delegator, "%s", was provided; expected a callable or instance of "%s"',
440450
is_object($delegatorFactory) ? get_class($delegatorFactory) : gettype($delegatorFactory),
441451
DelegatorFactoryInterface::class
442452
));

test/LazyServiceIntegrationTest.php

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
namespace ZendTest\ServiceManager;
1111

1212
use PHPUnit_Framework_TestCase as TestCase;
13+
use ProxyManager\Autoloader\AutoloaderInterface;
1314
use RecursiveDirectoryIterator;
1415
use RecursiveIteratorIterator;
1516
use RecursiveRegexIterator;
1617
use RegexIterator;
18+
use stdClass;
1719
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
1820
use Zend\ServiceManager\Exception\ServiceNotFoundException;
1921
use Zend\ServiceManager\Factory\InvokableFactory;
@@ -22,7 +24,7 @@
2224
use ZendTest\ServiceManager\TestAsset\InvokableObject;
2325

2426
/**
25-
* @covers \Zend\ServiceManager\Proxy\LazyServiceFactory
27+
* @covers \Zend\ServiceManager\ServiceManager
2628
*/
2729
class LazyServiceIntegrationTest extends TestCase
2830
{
@@ -43,6 +45,9 @@ public function tearDown()
4345
}
4446

4547
$this->removeDir($this->proxyDir);
48+
foreach ($this->getRegisteredProxyAutoloadFunctions() as $autoloader) {
49+
spl_autoload_unregister($autoloader);
50+
}
4651
}
4752

4853
public function removeDir($directory)
@@ -77,22 +82,15 @@ public function listProxyFiles()
7782
public function assertProxyDirEmpty($message = '')
7883
{
7984
$message = $message ?: 'Expected empty proxy directory; found files';
80-
$count = 0;
81-
foreach ($this->listProxyFiles() as $file) {
82-
$this->assertFail($message);
83-
}
84-
$this->assertEquals(0, $count);
85+
// AssertEquals instead AssertEmpty because the first one prints the list of files.
86+
$this->assertEquals([], iterator_to_array($this->listProxyFiles()), $message);
8587
}
8688

8789
public function assertProxyFileWritten($message = '')
8890
{
8991
$message = $message ?: 'Expected ProxyManager to write at least one class file; none found';
90-
$count = 0;
91-
foreach ($this->listProxyFiles() as $file) {
92-
$count += 1;
93-
break;
94-
}
95-
$this->assertNotEquals(0, $count, $message);
92+
// AssertNotEquals instead AssertNotEmpty because the first one prints the list of files.
93+
$this->assertNotEquals([], iterator_to_array($this->listProxyFiles()), $message);
9694
}
9795

9896
/**
@@ -141,12 +139,12 @@ public function testCanUseLazyServiceFactoryFactoryToCreateLazyServiceFactoryToA
141139
$this->assertInternalType(
142140
'array',
143141
$options,
144-
sprintf(
145-
'Expected an array of options; %s received',
146-
(is_object($options) ? get_class($options) : gettype($options))
147-
)
142+
'Expected an array of options'
148143
);
149144
$this->assertEquals(['foo' => 'bar'], $options, 'Options returned do not match configuration');
145+
146+
$proxyAutoloadFunctions = $this->getRegisteredProxyAutoloadFunctions();
147+
$this->assertCount(1, $proxyAutoloadFunctions, 'Only 1 proxy autoloader should be registered');
150148
}
151149

152150
/**
@@ -215,12 +213,49 @@ public function testWillNotGenerateProxyClassFilesByDefault()
215213
$this->assertInternalType(
216214
'array',
217215
$options,
218-
sprintf(
219-
'Expected an array of options; %s received',
220-
(is_object($options) ? get_class($options) : gettype($options))
221-
)
216+
'Expected an array of options'
222217
);
223218
$this->assertEquals(['foo' => 'bar'], $options, 'Options returned do not match configuration');
219+
220+
$proxyAutoloadFunctions = $this->getRegisteredProxyAutoloadFunctions();
221+
$this->assertCount(1, $proxyAutoloadFunctions, 'Only 1 proxy autoloader should be registered');
222+
}
223+
224+
public function testOnlyOneProxyAutoloaderItsRegisteredOnSubsequentCalls()
225+
{
226+
$config = [
227+
'lazy_services' => [
228+
'class_map' => [
229+
InvokableObject::class => InvokableObject::class,
230+
stdClass::class => stdClass::class,
231+
],
232+
'proxies_namespace' => 'TestAssetProxy',
233+
],
234+
'factories' => [
235+
InvokableObject::class => InvokableFactory::class,
236+
],
237+
'delegators' => [
238+
InvokableObject::class => [LazyServiceFactory::class],
239+
stdClass::class => [LazyServiceFactory::class],
240+
],
241+
];
242+
243+
$container = new ServiceManager($config);
244+
$instance = $container->build(InvokableObject::class, ['foo' => 'bar']);
245+
$this->assertInstanceOf(
246+
InvokableObject::class,
247+
$instance,
248+
'Service returned does not extend ' . InvokableObject::class
249+
);
250+
$instance = $container->build(stdClass::class, ['foo' => 'bar']);
251+
$this->assertInstanceOf(
252+
stdClass::class,
253+
$instance,
254+
'Service returned does not extend ' . stdClass::class
255+
);
256+
257+
$proxyAutoloadFunctions = $this->getRegisteredProxyAutoloadFunctions();
258+
$this->assertCount(1, $proxyAutoloadFunctions, 'Only 1 proxy autoloader should be registered');
224259
}
225260

226261
public function testRaisesServiceNotFoundExceptionIfRequestedLazyServiceIsNotInClassMap()
@@ -243,7 +278,20 @@ public function testRaisesServiceNotFoundExceptionIfRequestedLazyServiceIsNotInC
243278
$this->assertProxyDirEmpty();
244279

245280
$container = new ServiceManager($config);
281+
246282
$this->setExpectedException(ServiceNotFoundException::class, 'not found in the provided services map');
247-
$instance = $container->build(InvokableObject::class, ['foo' => 'bar']);
283+
$container->build(InvokableObject::class, ['foo' => 'bar']);
284+
}
285+
286+
/**
287+
* @return AutoloaderInterface[]
288+
*/
289+
protected function getRegisteredProxyAutoloadFunctions()
290+
{
291+
$filter = function ($autoload) {
292+
return ($autoload instanceof AutoloaderInterface);
293+
};
294+
295+
return array_filter(spl_autoload_functions(), $filter);
248296
}
249297
}

test/Proxy/LazyServiceFactoryTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace ZendTest\ServiceManager\Proxy;
11+
12+
use Interop\Container\ContainerInterface;
13+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
14+
use PHPUnit_Framework_TestCase as TestCase;
15+
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
16+
use ProxyManager\Proxy\LazyLoadingInterface;
17+
use ProxyManager\Proxy\VirtualProxyInterface;
18+
use Zend\ServiceManager\Exception\ServiceNotFoundException;
19+
use Zend\ServiceManager\Factory\DelegatorFactoryInterface;
20+
use Zend\ServiceManager\Proxy\LazyServiceFactory;
21+
22+
/**
23+
* @covers \Zend\ServiceManager\Proxy\LazyServiceFactory
24+
*/
25+
class LazyServiceFactoryTest extends TestCase
26+
{
27+
/**
28+
* @var LazyServiceFactory
29+
*/
30+
private $factory;
31+
32+
/**
33+
* @var LazyLoadingValueHolderFactory|MockObject
34+
*/
35+
private $proxyFactory;
36+
37+
/**
38+
* {@inheritDoc}
39+
*/
40+
protected function setUp()
41+
{
42+
$this->proxyFactory = $this->getMock(LazyLoadingValueHolderFactory::class);
43+
$servicesMap = [
44+
'fooService' => 'FooClass',
45+
];
46+
47+
$this->factory = new LazyServiceFactory($this->proxyFactory, $servicesMap);
48+
}
49+
50+
public function testImplementsDelegatorFactoryInterface()
51+
{
52+
$this->assertInstanceOf(DelegatorFactoryInterface::class, $this->factory);
53+
}
54+
55+
public function testThrowExceptionWhenServiceNotExists()
56+
{
57+
$callback = $this->getMock('stdClass', ['callback']);
58+
$callback->expects($this->never())
59+
->method('callback')
60+
;
61+
$container = $this->createContainerMock();
62+
63+
$this->proxyFactory->expects($this->never())
64+
->method('createProxy')
65+
;
66+
$this->setExpectedException(
67+
ServiceNotFoundException::class,
68+
'The requested service "not_exists" was not found in the provided services map'
69+
);
70+
71+
$this->factory->__invoke($container, 'not_exists', [$callback, 'callback']);
72+
}
73+
74+
public function testCreates()
75+
{
76+
$callback = $this->getMock('stdClass', ['callback']);
77+
$callback->expects($this->once())
78+
->method('callback')
79+
->willReturn('fooValue')
80+
;
81+
$container = $this->createContainerMock();
82+
$expectedService = $this->getMock(VirtualProxyInterface::class);
83+
84+
$this->proxyFactory->expects($this->once())
85+
->method('createProxy')
86+
->willReturnCallback(
87+
function ($className, $initializer) use ($expectedService) {
88+
$this->assertEquals('FooClass', $className, 'class name not match');
89+
90+
$wrappedInstance = null;
91+
$result = $initializer($wrappedInstance, $this->getMock(LazyLoadingInterface::class));
92+
93+
$this->assertEquals('fooValue', $wrappedInstance, 'expected callback return value');
94+
$this->assertTrue($result, 'initializer should return true');
95+
96+
return $expectedService;
97+
}
98+
)
99+
;
100+
101+
$result = $this->factory->__invoke($container, 'fooService', [$callback, 'callback']);
102+
103+
$this->assertSame($expectedService, $result, 'service created not match the expected');
104+
}
105+
106+
/**
107+
* @return ContainerInterface|MockObject
108+
*/
109+
private function createContainerMock()
110+
{
111+
/** @var ContainerInterface|MockObject $container */
112+
$container = $this->getMock(ContainerInterface::class);
113+
114+
return $container;
115+
}
116+
}

0 commit comments

Comments
 (0)