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

Commit 640ec2c

Browse files
committed
Merge branch 'feature/275'
Close #257
2 parents 0aea76f + 4367dc0 commit 640ec2c

File tree

5 files changed

+193
-27
lines changed

5 files changed

+193
-27
lines changed

CHANGELOG.md

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,28 @@
22

33
All notable changes to this project will be documented in this file, in reverse chronological order by release.
44

5+
## 3.4.0 - TBD
6+
7+
### Added
8+
9+
- [#275](https://github.com/zendframework/zend-servicemanager/pull/275) Enables plugin managers to accept as a creation context PSR Containers not implementing Interop interface
10+
11+
### Changed
12+
13+
- Nothing.
14+
15+
### Deprecated
16+
17+
- Nothing.
18+
19+
### Removed
20+
21+
- Nothing.
22+
23+
### Fixed
24+
25+
- Nothing.
26+
527
## 3.3.2 - 2018-01-29
628

729
### Added
@@ -61,7 +83,7 @@ All notable changes to this project will be documented in this file, in reverse
6183
container-interop at a minimum version of 1.2.0, and adding a requirement on
6284
psr/container 1.0. `Zend\ServiceManager\ServiceLocatorInterface` now
6385
explicitly extends the `ContainerInterface` from both projects.
64-
86+
6587
Factory interfaces still typehint against the container-interop variant, as
6688
changing the typehint would break backwards compatibility. Users can
6789
duck-type most of these interfaces, however, by creating callables or
@@ -339,7 +361,7 @@ Documentation is now available at http://zend-servicemanager.rtfd.org
339361
(previously, it was the third).
340362

341363
Example:
342-
364+
343365
```php
344366
$sm = new \Zend\ServiceManager\ServiceManager([
345367
'factories' => [
@@ -348,7 +370,7 @@ Documentation is now available at http://zend-servicemanager.rtfd.org
348370
'MyClassC' => 'MyFactory' // This is equivalent as using ::class
349371
],
350372
]);
351-
373+
352374
$sm->get(MyClassA::class); // MyFactory will receive MyClassA::class as second parameter
353375
```
354376

@@ -367,7 +389,7 @@ Documentation is now available at http://zend-servicemanager.rtfd.org
367389
if ($instance instanceof \Zend\Validator\ValidatorInterface) {
368390
return;
369391
}
370-
392+
371393
throw new InvalidServiceException(sprintf(
372394
'Plugin manager "%s" expected an instance of type "%s", but "%s" was received',
373395
__CLASS__,
@@ -377,19 +399,19 @@ Documentation is now available at http://zend-servicemanager.rtfd.org
377399
}
378400
}
379401
```
380-
402+
381403
In version 3, this becomes:
382-
404+
383405
```php
384406
use Zend\ServiceManager\AbstractPluginManager;
385407
use Zend\Validator\ValidatorInterface;
386-
408+
387409
class MyPluginManager extends AbstractPluginManager
388410
{
389411
protected $instanceOf = ValidatorInterface::class;
390412
}
391413
```
392-
414+
393415
Of course, you can still override the `validate` method if your logic is more
394416
complex.
395417

@@ -433,17 +455,17 @@ changes, outlined in this section.
433455
service manager; you can pass the configuration array directly instead.
434456

435457
In version 2.x:
436-
458+
437459
```php
438460
$config = new \Zend\ServiceManager\Config([
439461
'factories' => [...]
440462
]);
441-
463+
442464
$sm = new \Zend\ServiceManager\ServiceManager($config);
443465
```
444-
466+
445467
In ZF 3.x:
446-
468+
447469
```php
448470
$sm = new \Zend\ServiceManager\ServiceManager([
449471
'factories' => [...]
@@ -472,7 +494,7 @@ changes, outlined in this section.
472494
argument if present.
473495

474496
For instance, here is a simple version 2.x factory:
475-
497+
476498
```php
477499
class MyFactory implements FactoryInterface
478500
{
@@ -482,9 +504,9 @@ changes, outlined in this section.
482504
}
483505
}
484506
```
485-
507+
486508
The equivalent version 3 factory:
487-
509+
488510
```php
489511
class MyFactory implements FactoryInterface
490512
{
@@ -514,23 +536,23 @@ changes, outlined in this section.
514536
through the interface.
515537

516538
In version 2.x, if a factory was set to a service name defined in a plugin manager:
517-
539+
518540
```php
519541
class MyFactory implements FactoryInterface
520542
{
521543
function createService(ServiceLocatorInterface $sl)
522544
{
523545
// $sl is actually a plugin manager
524-
546+
525547
$parentLocator = $sl->getServiceLocator();
526-
548+
527549
// ...
528550
}
529551
}
530552
```
531-
553+
532554
In version 3:
533-
555+
534556
```php
535557
class MyFactory implements FactoryInterface
536558
{

src/AbstractPluginManager.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
<?php
22
/**
3-
* @link http://github.com/zendframework/zend-servicemanager for the canonical source repository
4-
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
5-
* @license http://framework.zend.com/license/new-bsd New BSD License
3+
* @see https://github.com/zendframework/zend-servicemanager for the canonical source repository
4+
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-servicemanager/blob/master/LICENSE.md New BSD License
66
*/
77

88
namespace Zend\ServiceManager;
99

1010
use Interop\Container\ContainerInterface;
11+
use Psr\Container\ContainerInterface as PsrContainerInterface;
1112
use Zend\ServiceManager\Exception\InvalidServiceException;
1213

1314
/**
@@ -47,11 +48,21 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
4748
* factories; for $config, {@see \Zend\ServiceManager\ServiceManager::configure()}
4849
* for details on its accepted structure.
4950
*
50-
* @param null|ConfigInterface|ContainerInterface $configInstanceOrParentLocator
51+
* @param null|ConfigInterface|ContainerInterface|PsrContainerInterface $configInstanceOrParentLocator
5152
* @param array $config
5253
*/
5354
public function __construct($configInstanceOrParentLocator = null, array $config = [])
5455
{
56+
if ($configInstanceOrParentLocator instanceof PsrContainerInterface
57+
&& ! $configInstanceOrParentLocator instanceof ContainerInterface
58+
) {
59+
/**
60+
* {@see \Zend\ServiceManager\Factory\FactoryInterface} typehints
61+
* against interop container and as such cannot accept non-interop
62+
* psr container. Decorate it as interop.
63+
*/
64+
$configInstanceOrParentLocator = new PsrContainerDecorator($configInstanceOrParentLocator);
65+
}
5566
if (null !== $configInstanceOrParentLocator
5667
&& ! $configInstanceOrParentLocator instanceof ConfigInterface
5768
&& ! $configInstanceOrParentLocator instanceof ContainerInterface

src/PsrContainerDecorator.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-servicemanager for the canonical source repository
4+
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-servicemanager/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace Zend\ServiceManager;
9+
10+
use Interop\Container\ContainerInterface;
11+
use Psr\Container\ContainerInterface as PsrContainerInterface;
12+
13+
/**
14+
* @internal for use in abstract plugin manager
15+
*/
16+
final class PsrContainerDecorator implements ContainerInterface
17+
{
18+
/**
19+
* @var PsrContainerInterface
20+
*/
21+
private $container;
22+
23+
public function __construct(PsrContainerInterface $container)
24+
{
25+
$this->container = $container;
26+
}
27+
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function get($id)
32+
{
33+
return $this->container->get($id);
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function has($id)
40+
{
41+
return $this->container->has($id);
42+
}
43+
44+
/**
45+
* @return PsrContainerInterface
46+
*/
47+
public function getContainer()
48+
{
49+
return $this->container;
50+
}
51+
}

test/AbstractPluginManagerTest.php

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
<?php
22
/**
3-
* @link http://github.com/zendframework/zend-servicemanager for the canonical source repository
4-
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
5-
* @license http://framework.zend.com/license/new-bsd New BSD License
3+
* @see https://github.com/zendframework/zend-servicemanager for the canonical source repository
4+
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-servicemanager/blob/master/LICENSE.md New BSD License
66
*/
77

88
namespace ZendTest\ServiceManager;
99

1010
use Interop\Container\ContainerInterface;
1111
use PHPUnit\Framework\TestCase;
12+
use Psr\Container\ContainerInterface as PsrContainerInterface;
1213
use stdClass;
14+
use Zend\ServiceManager\AbstractPluginManager;
1315
use Zend\ServiceManager\ConfigInterface;
1416
use Zend\ServiceManager\Exception\InvalidArgumentException;
1517
use Zend\ServiceManager\Exception\InvalidServiceException;
1618
use Zend\ServiceManager\Exception\ServiceNotFoundException;
1719
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
1820
use Zend\ServiceManager\Factory\FactoryInterface;
1921
use Zend\ServiceManager\Factory\InvokableFactory;
22+
use Zend\ServiceManager\PsrContainerDecorator;
2023
use Zend\ServiceManager\ServiceManager;
2124
use ZendTest\ServiceManager\TestAsset\InvokableObject;
2225
use ZendTest\ServiceManager\TestAsset\SimplePluginManager;
@@ -60,6 +63,32 @@ public function testInjectCreationContextInFactories()
6063
$this->assertInstanceOf(InvokableObject::class, $object);
6164
}
6265

66+
public function testTransparentlyDecoratesNonInteropPsrContainerAsInteropContainer()
67+
{
68+
$invokableFactory = $this->getMockBuilder(FactoryInterface::class)
69+
->getMock();
70+
$invokableFactory->method('__invoke')
71+
->will($this->returnArgument(0));
72+
73+
$config = [
74+
'factories' => [
75+
'creation context container' => $invokableFactory,
76+
],
77+
];
78+
79+
$container = $this->getMockBuilder(PsrContainerInterface::class)
80+
->getMock();
81+
$pluginManager = $this->getMockForAbstractClass(
82+
AbstractPluginManager::class,
83+
[$container, $config]
84+
);
85+
86+
$object = $pluginManager->get('creation context container');
87+
88+
$this->assertInstanceOf(PsrContainerDecorator::class, $object);
89+
$this->assertSame($container, $object->getContainer());
90+
}
91+
6392
public function testValidateInstance()
6493
{
6594
$config = [

test/PsrContainerDecoratorTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-servicemanager for the canonical source repository
4+
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-servicemanager/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace ZendTest\ServiceManager;
9+
10+
use Psr\Container\ContainerInterface;
11+
use stdClass;
12+
use Zend\ServiceManager\PsrContainerDecorator;
13+
use PHPUnit\Framework\TestCase;
14+
15+
/**
16+
* @covers \Zend\ServiceManager\PsrContainerDecorator
17+
*/
18+
class PsrContainerDecoratorTest extends TestCase
19+
{
20+
public function testProxiesHasToDecoratedContainer()
21+
{
22+
$psrContainer = $this->getMockBuilder(ContainerInterface::class)
23+
->getMock();
24+
$psrContainer->expects($this->exactly(2))
25+
->method('has')
26+
->with('string key')
27+
->willReturnOnConsecutiveCalls(true, false);
28+
$decorator = new PsrContainerDecorator($psrContainer);
29+
$this->assertTrue($decorator->has('string key'));
30+
$this->assertFalse($decorator->has('string key'));
31+
}
32+
33+
public function testProxiesGetToDecoratedContainer()
34+
{
35+
$service = new stdClass();
36+
$psrContainer = $this->getMockBuilder(ContainerInterface::class)
37+
->getMock();
38+
$psrContainer->expects($this->once())
39+
->method('get')
40+
->with('string key')
41+
->willReturn($service);
42+
$decorator = new PsrContainerDecorator($psrContainer);
43+
$this->assertSame($service, $decorator->get('string key'));
44+
}
45+
46+
public function testGetterReturnsDecoratedContainer()
47+
{
48+
$psrContainer = $this->getMockBuilder(ContainerInterface::class)
49+
->getMock();
50+
$decorator = new PsrContainerDecorator($psrContainer);
51+
$this->assertSame($psrContainer, $decorator->getContainer());
52+
}
53+
}

0 commit comments

Comments
 (0)