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

Commit

Permalink
Merge branch 'feature/4146' into develop
Browse files Browse the repository at this point in the history
Close #4146
  • Loading branch information
weierophinney committed Apr 15, 2013
2 parents e6717d5 + b22828d commit 73bb550
Show file tree
Hide file tree
Showing 8 changed files with 401 additions and 5 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
"doctrine/common": ">=2.1",
"ircmaxell/random-lib": "dev-master",
"ircmaxell/security-lib": "dev-master",
"ocramius/proxy-manager": "0.3.*",
"phpunit/PHPUnit": "3.7.*"
},
"suggest": {
"doctrine/common": "Doctrine\\Common >=2.1 for annotation features",
"ext-intl": "ext/intl for i18n features",
"ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable",
"ocramius/proxy-manager": "ProxyManager to handle lazy initialization of services",
"pecl-weakref": "Implementation of weak references for Zend\\Stdlib\\CallbackHandler",
"zendframework/zendpdf": "ZendPdf for creating PDF representations of barcodes",
"zendframework/zendservice-recaptcha": "ZendService\\ReCaptcha for rendering ReCaptchas in Zend\\Captcha and/or Zend\\Form"
Expand Down
4 changes: 2 additions & 2 deletions library/Zend/ServiceManager/DelegatorFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
namespace Zend\ServiceManager;

/**
* Interface for factories that can create delegators for services
* Interface for factories that can create delegates for services
*/
interface DelegatorFactoryInterface
{
/**
* A factory that creates delegators of a given service
* A factory that creates delegates of a given service
*
* @param ServiceLocatorInterface $serviceLocator the service locator which requested the service
* @param string $name the normalized service name
Expand Down
73 changes: 73 additions & 0 deletions library/Zend/ServiceManager/Proxy/LazyServiceFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\ServiceManager\Proxy;

use ProxyManager\Factory\LazyLoadingValueHolderFactory;

use ProxyManager\Proxy\LazyLoadingInterface;
use Zend\ServiceManager\DelegatorFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Exception;

/**
* Delegator factory responsible of instantiating lazy loading value holder proxies of
* given services at runtime
*
* @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md
*/
class LazyServiceFactory implements DelegatorFactoryInterface
{
/**
* @var \ProxyManager\Factory\LazyLoadingValueHolderFactory
*/
protected $proxyFactory;

/**
* @var string[] map of service names to class names
*/
protected $servicesMap;

/**
* @param LazyLoadingValueHolderFactory $proxyFactory
* @param string[] $servicesMap a map of service names to class names of their
* respective classes
*/
public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $servicesMap)
{
$this->proxyFactory = $proxyFactory;
$this->servicesMap = $servicesMap;
}

/**
* {@inheritDoc}
*
* @return object|\ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface
*/
public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
{
$initializer = function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($callback) {
$proxy->setProxyInitializer(null);

$wrappedInstance = call_user_func($callback);

return true;
};

if (isset($this->servicesMap[$requestedName])) {
return $this->proxyFactory->createProxy($this->servicesMap[$requestedName], $initializer);
} elseif (isset($this->servicesMap[$name])) {
return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer);
}

throw new Exception\InvalidServiceNameException(
sprintf('The requested service "%s" was not found in the provided services map', $requestedName)
);
}
}
74 changes: 74 additions & 0 deletions library/Zend/ServiceManager/Proxy/LazyServiceFactoryFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\ServiceManager\Proxy;

use ProxyManager\Configuration;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;

use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Exception;

/**
* Service factory responsible of instantiating {@see \Zend\ServiceManager\Proxy\LazyServiceFactory}
* and configuring it starting from application configuration
*/
class LazyServiceFactoryFactory implements FactoryInterface
{
/**
* {@inheritDoc}
*
* @return \Zend\ServiceManager\Proxy\LazyServiceFactory
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('Config');

if (!isset($config['lazy_services'])) {
throw new Exception\InvalidArgumentException('Missing "lazy_services" config key');
}

$lazyServices = $config['lazy_services'];

if (!isset($lazyServices['class_map'])) {
throw new Exception\InvalidArgumentException('Missing "class_map" config key in "lazy_services"');
}

$factoryConfig = new Configuration();

if (isset($lazyServices['proxies_target_dir'])) {
$factoryConfig->setProxiesTargetDir($lazyServices['proxies_target_dir']);
}

if (!isset($lazyServices['write_proxy_files']) || ! $lazyServices['write_proxy_files']) {
$factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
}

if (isset($lazyServices['auto_generate_proxies'])) {
$factoryConfig->setAutoGenerateProxies($lazyServices['auto_generate_proxies']);

// register the proxy autoloader if the proxies already exist
if (!$lazyServices['auto_generate_proxies']) {
spl_autoload_register($factoryConfig->getProxyAutoloader());

$factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
}
}

//if (!isset($lazyServicesConfig['runtime_evaluate_proxies']))

if (isset($lazyServices['proxies_namespace'])) {
$factoryConfig->setProxiesNamespace($lazyServices['proxies_namespace']);
}

return new LazyServiceFactory(new LazyLoadingValueHolderFactory($factoryConfig), $lazyServices['class_map']);
}
}
8 changes: 5 additions & 3 deletions library/Zend/ServiceManager/ServiceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,13 @@ public function addAbstractFactory($factory, $topOfStack = true)
*/
public function addDelegator($serviceName, $delegatorFactoryName)
{
if (!isset($this->delegators[$this->canonicalizeName($serviceName)])) {
$this->delegators[$this->canonicalizeName($serviceName)] = array();
$cName = $this->canonicalizeName($serviceName);

if (!isset($this->delegators[$cName])) {
$this->delegators[$cName] = array();
}

$this->delegators[$this->canonicalizeName($serviceName)][] = $delegatorFactoryName;
$this->delegators[$cName][] = $delegatorFactoryName;

return $this;
}
Expand Down
158 changes: 158 additions & 0 deletions tests/ZendTest/ServiceManager/Proxy/LazyServiceFactoryFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @package Zend_ServiceManager
*/

namespace ZendTest\ServiceManager\Proxy;

use Zend\ServiceManager\Proxy\LazyServiceFactoryFactory;
use Zend\ServiceManager\ServiceManager;

/**
* Tests for {@see \Zend\ServiceManager\Proxy\LazyServiceFactoryFactory}
*
* @covers \Zend\ServiceManager\Proxy\LazyServiceFactoryFactory
*/
class LazyServiceFactoryFactoryTest extends \PHPUnit_Framework_TestCase
{
/**
* {@inheritDoc}
*/
public function setUp()
{
if (!interface_exists('ProxyManager\\Proxy\\ProxyInterface')) {
$this->markTestSkipped('Please install `ocramius/proxy-manager` to run these tests');
}
}

/**
* @dataProvider invalidConfigProvider
*/
public function testInvalidConfiguration($config)
{
$locator = $this->getMock('Zend\\ServiceManager\\ServiceLocatorInterface');
$factory = new LazyServiceFactoryFactory();

$locator->expects($this->any())->method('get')->with('Config')->will($this->returnValue($config));
$this->setExpectedException('Zend\\ServiceManager\\Exception\\InvalidArgumentException');

$factory->createService($locator);
}

public function testAutoGenerateProxyFiles()
{
$serviceManager = new ServiceManager();
$namespace = 'ZendTestProxy' . uniqid();

$serviceManager->setService(
'Config',
array(
'lazy_services' => array(
'class_map' => array('foo' => __CLASS__),
'proxies_namespace' => $namespace,
'write_proxy_files' => true,
),
)
);
$serviceManager->setFactory('foo-delegator', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
$serviceManager->setInvokableClass('foo', __CLASS__);
$serviceManager->addDelegator('foo', 'foo-delegator');

/* @var $proxy self|\ProxyManager\Proxy\ValueHolderInterface|\ProxyManager\Proxy\LazyLoadingInterface */
$proxy = $serviceManager->create('foo');

$this->assertInstanceOf('ProxyManager\\Proxy\\LazyLoadingInterface', $proxy);
$this->assertInstanceOf(__CLASS__, $proxy);
$this->assertSame(
$namespace . '\__PM__\ZendTest\ServiceManager\Proxy\LazyServiceFactoryFactoryTest',
get_class($proxy)
);
$this->assertFileExists(
sys_get_temp_dir() . '/' . $namespace . '__PM__ZendTestServiceManagerProxyLazyServiceFactoryFactoryTest.php'
);
$this->assertFalse($proxy->isProxyInitialized());
$this->assertEquals($this->invalidConfigProvider(), $proxy->invalidConfigProvider());
$this->assertTrue($proxy->isProxyInitialized());
}

public function testAutoGenerateAndEvaluateProxies()
{
$serviceManager = new ServiceManager();
$namespace = 'ZendTestProxy' . uniqid();

$serviceManager->setService(
'Config',
array(
'lazy_services' => array(
'class_map' => array('foo' => __CLASS__),
'proxies_namespace' => $namespace,
),
)
);
$serviceManager->setFactory('foo-delegator', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
$serviceManager->setInvokableClass('foo', __CLASS__);
$serviceManager->addDelegator('foo', 'foo-delegator');

/* @var $proxy self|\ProxyManager\Proxy\ValueHolderInterface|\ProxyManager\Proxy\LazyLoadingInterface */
$proxy = $serviceManager->create('foo');

$this->assertInstanceOf('ProxyManager\\Proxy\\LazyLoadingInterface', $proxy);
$this->assertInstanceOf(__CLASS__, $proxy);
$this->assertSame(
$namespace . '\__PM__\ZendTest\ServiceManager\Proxy\LazyServiceFactoryFactoryTest',
get_class($proxy)
);
$this->assertFileNotExists(
sys_get_temp_dir() . '/' . $namespace . '__PM__ZendTestServiceManagerProxyLazyServiceFactoryFactoryTest.php'
);
$this->assertFalse($proxy->isProxyInitialized());
$this->assertEquals($this->invalidConfigProvider(), $proxy->invalidConfigProvider());
$this->assertTrue($proxy->isProxyInitialized());
}

public function testRegistersAutoloader()
{
$autoloaders = spl_autoload_functions();
$serviceManager = new ServiceManager();
$namespace = 'ZendTestProxy' . uniqid();

$serviceManager->setService(
'Config',
array(
'lazy_services' => array(
'class_map' => array('foo' => __CLASS__),
'proxies_namespace' => $namespace,
'auto_generate_proxies' => false,
),
)
);
$serviceManager->setFactory('foo-delegator', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
$serviceManager->create('foo-delegator');

$currentAutoloaders = spl_autoload_functions();
$proxyAutoloader = end($currentAutoloaders);

$this->assertCount(count($autoloaders) + 1, $currentAutoloaders);
$this->assertInstanceOf('ProxyManager\\Autoloader\\AutoloaderInterface', $proxyAutoloader);

spl_autoload_unregister($proxyAutoloader);
}

/**
* Provides invalid configuration
*
* @return array
*/
public function invalidConfigProvider()
{
return array(
array(array()),
array(array('lazy_services' => array()))
);
}
}
Loading

0 comments on commit 73bb550

Please sign in to comment.