Thanks to visit codestin.com
Credit goes to github.com

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

Commit b22828d

Browse files
committed
Merge pull request #4146 from Ocramius/feature/proxy-delegate-services
Lazy services
2 parents e6717d5 + 3299c82 commit b22828d

File tree

8 files changed

+401
-5
lines changed

8 files changed

+401
-5
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
"doctrine/common": ">=2.1",
1616
"ircmaxell/random-lib": "dev-master",
1717
"ircmaxell/security-lib": "dev-master",
18+
"ocramius/proxy-manager": "0.3.*",
1819
"phpunit/PHPUnit": "3.7.*"
1920
},
2021
"suggest": {
2122
"doctrine/common": "Doctrine\\Common >=2.1 for annotation features",
2223
"ext-intl": "ext/intl for i18n features",
2324
"ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable",
25+
"ocramius/proxy-manager": "ProxyManager to handle lazy initialization of services",
2426
"pecl-weakref": "Implementation of weak references for Zend\\Stdlib\\CallbackHandler",
2527
"zendframework/zendpdf": "ZendPdf for creating PDF representations of barcodes",
2628
"zendframework/zendservice-recaptcha": "ZendService\\ReCaptcha for rendering ReCaptchas in Zend\\Captcha and/or Zend\\Form"

library/Zend/ServiceManager/DelegatorFactoryInterface.php

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

1212
/**
13-
* Interface for factories that can create delegators for services
13+
* Interface for factories that can create delegates for services
1414
*/
1515
interface DelegatorFactoryInterface
1616
{
1717
/**
18-
* A factory that creates delegators of a given service
18+
* A factory that creates delegates of a given service
1919
*
2020
* @param ServiceLocatorInterface $serviceLocator the service locator which requested the service
2121
* @param string $name the normalized service name
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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-2013 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace Zend\ServiceManager\Proxy;
11+
12+
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
13+
14+
use ProxyManager\Proxy\LazyLoadingInterface;
15+
use Zend\ServiceManager\DelegatorFactoryInterface;
16+
use Zend\ServiceManager\ServiceLocatorInterface;
17+
use Zend\ServiceManager\Exception;
18+
19+
/**
20+
* Delegator factory responsible of instantiating lazy loading value holder proxies of
21+
* given services at runtime
22+
*
23+
* @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md
24+
*/
25+
class LazyServiceFactory implements DelegatorFactoryInterface
26+
{
27+
/**
28+
* @var \ProxyManager\Factory\LazyLoadingValueHolderFactory
29+
*/
30+
protected $proxyFactory;
31+
32+
/**
33+
* @var string[] map of service names to class names
34+
*/
35+
protected $servicesMap;
36+
37+
/**
38+
* @param LazyLoadingValueHolderFactory $proxyFactory
39+
* @param string[] $servicesMap a map of service names to class names of their
40+
* respective classes
41+
*/
42+
public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $servicesMap)
43+
{
44+
$this->proxyFactory = $proxyFactory;
45+
$this->servicesMap = $servicesMap;
46+
}
47+
48+
/**
49+
* {@inheritDoc}
50+
*
51+
* @return object|\ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface
52+
*/
53+
public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
54+
{
55+
$initializer = function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($callback) {
56+
$proxy->setProxyInitializer(null);
57+
58+
$wrappedInstance = call_user_func($callback);
59+
60+
return true;
61+
};
62+
63+
if (isset($this->servicesMap[$requestedName])) {
64+
return $this->proxyFactory->createProxy($this->servicesMap[$requestedName], $initializer);
65+
} elseif (isset($this->servicesMap[$name])) {
66+
return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer);
67+
}
68+
69+
throw new Exception\InvalidServiceNameException(
70+
sprintf('The requested service "%s" was not found in the provided services map', $requestedName)
71+
);
72+
}
73+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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-2013 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace Zend\ServiceManager\Proxy;
11+
12+
use ProxyManager\Configuration;
13+
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
14+
15+
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
16+
use Zend\ServiceManager\FactoryInterface;
17+
use Zend\ServiceManager\ServiceLocatorInterface;
18+
use Zend\ServiceManager\Exception;
19+
20+
/**
21+
* Service factory responsible of instantiating {@see \Zend\ServiceManager\Proxy\LazyServiceFactory}
22+
* and configuring it starting from application configuration
23+
*/
24+
class LazyServiceFactoryFactory implements FactoryInterface
25+
{
26+
/**
27+
* {@inheritDoc}
28+
*
29+
* @return \Zend\ServiceManager\Proxy\LazyServiceFactory
30+
*/
31+
public function createService(ServiceLocatorInterface $serviceLocator)
32+
{
33+
$config = $serviceLocator->get('Config');
34+
35+
if (!isset($config['lazy_services'])) {
36+
throw new Exception\InvalidArgumentException('Missing "lazy_services" config key');
37+
}
38+
39+
$lazyServices = $config['lazy_services'];
40+
41+
if (!isset($lazyServices['class_map'])) {
42+
throw new Exception\InvalidArgumentException('Missing "class_map" config key in "lazy_services"');
43+
}
44+
45+
$factoryConfig = new Configuration();
46+
47+
if (isset($lazyServices['proxies_target_dir'])) {
48+
$factoryConfig->setProxiesTargetDir($lazyServices['proxies_target_dir']);
49+
}
50+
51+
if (!isset($lazyServices['write_proxy_files']) || ! $lazyServices['write_proxy_files']) {
52+
$factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
53+
}
54+
55+
if (isset($lazyServices['auto_generate_proxies'])) {
56+
$factoryConfig->setAutoGenerateProxies($lazyServices['auto_generate_proxies']);
57+
58+
// register the proxy autoloader if the proxies already exist
59+
if (!$lazyServices['auto_generate_proxies']) {
60+
spl_autoload_register($factoryConfig->getProxyAutoloader());
61+
62+
$factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
63+
}
64+
}
65+
66+
//if (!isset($lazyServicesConfig['runtime_evaluate_proxies']))
67+
68+
if (isset($lazyServices['proxies_namespace'])) {
69+
$factoryConfig->setProxiesNamespace($lazyServices['proxies_namespace']);
70+
}
71+
72+
return new LazyServiceFactory(new LazyLoadingValueHolderFactory($factoryConfig), $lazyServices['class_map']);
73+
}
74+
}

library/Zend/ServiceManager/ServiceManager.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,11 +326,13 @@ public function addAbstractFactory($factory, $topOfStack = true)
326326
*/
327327
public function addDelegator($serviceName, $delegatorFactoryName)
328328
{
329-
if (!isset($this->delegators[$this->canonicalizeName($serviceName)])) {
330-
$this->delegators[$this->canonicalizeName($serviceName)] = array();
329+
$cName = $this->canonicalizeName($serviceName);
330+
331+
if (!isset($this->delegators[$cName])) {
332+
$this->delegators[$cName] = array();
331333
}
332334

333-
$this->delegators[$this->canonicalizeName($serviceName)][] = $delegatorFactoryName;
335+
$this->delegators[$cName][] = $delegatorFactoryName;
334336

335337
return $this;
336338
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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-2013 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
* @package Zend_ServiceManager
9+
*/
10+
11+
namespace ZendTest\ServiceManager\Proxy;
12+
13+
use Zend\ServiceManager\Proxy\LazyServiceFactoryFactory;
14+
use Zend\ServiceManager\ServiceManager;
15+
16+
/**
17+
* Tests for {@see \Zend\ServiceManager\Proxy\LazyServiceFactoryFactory}
18+
*
19+
* @covers \Zend\ServiceManager\Proxy\LazyServiceFactoryFactory
20+
*/
21+
class LazyServiceFactoryFactoryTest extends \PHPUnit_Framework_TestCase
22+
{
23+
/**
24+
* {@inheritDoc}
25+
*/
26+
public function setUp()
27+
{
28+
if (!interface_exists('ProxyManager\\Proxy\\ProxyInterface')) {
29+
$this->markTestSkipped('Please install `ocramius/proxy-manager` to run these tests');
30+
}
31+
}
32+
33+
/**
34+
* @dataProvider invalidConfigProvider
35+
*/
36+
public function testInvalidConfiguration($config)
37+
{
38+
$locator = $this->getMock('Zend\\ServiceManager\\ServiceLocatorInterface');
39+
$factory = new LazyServiceFactoryFactory();
40+
41+
$locator->expects($this->any())->method('get')->with('Config')->will($this->returnValue($config));
42+
$this->setExpectedException('Zend\\ServiceManager\\Exception\\InvalidArgumentException');
43+
44+
$factory->createService($locator);
45+
}
46+
47+
public function testAutoGenerateProxyFiles()
48+
{
49+
$serviceManager = new ServiceManager();
50+
$namespace = 'ZendTestProxy' . uniqid();
51+
52+
$serviceManager->setService(
53+
'Config',
54+
array(
55+
'lazy_services' => array(
56+
'class_map' => array('foo' => __CLASS__),
57+
'proxies_namespace' => $namespace,
58+
'write_proxy_files' => true,
59+
),
60+
)
61+
);
62+
$serviceManager->setFactory('foo-delegator', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
63+
$serviceManager->setInvokableClass('foo', __CLASS__);
64+
$serviceManager->addDelegator('foo', 'foo-delegator');
65+
66+
/* @var $proxy self|\ProxyManager\Proxy\ValueHolderInterface|\ProxyManager\Proxy\LazyLoadingInterface */
67+
$proxy = $serviceManager->create('foo');
68+
69+
$this->assertInstanceOf('ProxyManager\\Proxy\\LazyLoadingInterface', $proxy);
70+
$this->assertInstanceOf(__CLASS__, $proxy);
71+
$this->assertSame(
72+
$namespace . '\__PM__\ZendTest\ServiceManager\Proxy\LazyServiceFactoryFactoryTest',
73+
get_class($proxy)
74+
);
75+
$this->assertFileExists(
76+
sys_get_temp_dir() . '/' . $namespace . '__PM__ZendTestServiceManagerProxyLazyServiceFactoryFactoryTest.php'
77+
);
78+
$this->assertFalse($proxy->isProxyInitialized());
79+
$this->assertEquals($this->invalidConfigProvider(), $proxy->invalidConfigProvider());
80+
$this->assertTrue($proxy->isProxyInitialized());
81+
}
82+
83+
public function testAutoGenerateAndEvaluateProxies()
84+
{
85+
$serviceManager = new ServiceManager();
86+
$namespace = 'ZendTestProxy' . uniqid();
87+
88+
$serviceManager->setService(
89+
'Config',
90+
array(
91+
'lazy_services' => array(
92+
'class_map' => array('foo' => __CLASS__),
93+
'proxies_namespace' => $namespace,
94+
),
95+
)
96+
);
97+
$serviceManager->setFactory('foo-delegator', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
98+
$serviceManager->setInvokableClass('foo', __CLASS__);
99+
$serviceManager->addDelegator('foo', 'foo-delegator');
100+
101+
/* @var $proxy self|\ProxyManager\Proxy\ValueHolderInterface|\ProxyManager\Proxy\LazyLoadingInterface */
102+
$proxy = $serviceManager->create('foo');
103+
104+
$this->assertInstanceOf('ProxyManager\\Proxy\\LazyLoadingInterface', $proxy);
105+
$this->assertInstanceOf(__CLASS__, $proxy);
106+
$this->assertSame(
107+
$namespace . '\__PM__\ZendTest\ServiceManager\Proxy\LazyServiceFactoryFactoryTest',
108+
get_class($proxy)
109+
);
110+
$this->assertFileNotExists(
111+
sys_get_temp_dir() . '/' . $namespace . '__PM__ZendTestServiceManagerProxyLazyServiceFactoryFactoryTest.php'
112+
);
113+
$this->assertFalse($proxy->isProxyInitialized());
114+
$this->assertEquals($this->invalidConfigProvider(), $proxy->invalidConfigProvider());
115+
$this->assertTrue($proxy->isProxyInitialized());
116+
}
117+
118+
public function testRegistersAutoloader()
119+
{
120+
$autoloaders = spl_autoload_functions();
121+
$serviceManager = new ServiceManager();
122+
$namespace = 'ZendTestProxy' . uniqid();
123+
124+
$serviceManager->setService(
125+
'Config',
126+
array(
127+
'lazy_services' => array(
128+
'class_map' => array('foo' => __CLASS__),
129+
'proxies_namespace' => $namespace,
130+
'auto_generate_proxies' => false,
131+
),
132+
)
133+
);
134+
$serviceManager->setFactory('foo-delegator', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
135+
$serviceManager->create('foo-delegator');
136+
137+
$currentAutoloaders = spl_autoload_functions();
138+
$proxyAutoloader = end($currentAutoloaders);
139+
140+
$this->assertCount(count($autoloaders) + 1, $currentAutoloaders);
141+
$this->assertInstanceOf('ProxyManager\\Autoloader\\AutoloaderInterface', $proxyAutoloader);
142+
143+
spl_autoload_unregister($proxyAutoloader);
144+
}
145+
146+
/**
147+
* Provides invalid configuration
148+
*
149+
* @return array
150+
*/
151+
public function invalidConfigProvider()
152+
{
153+
return array(
154+
array(array()),
155+
array(array('lazy_services' => array()))
156+
);
157+
}
158+
}

0 commit comments

Comments
 (0)