/** * Verifies that proxies generated from different factories will retain their specific implementation * and won't conflict * * @dataProvider getTestedClasses */ public function testCanGenerateMultipleDifferentProxiesForSameClass($className) { $skipScopeLocalizerTests = false; $ghostProxyFactory = new LazyLoadingGhostFactory(); $virtualProxyFactory = new LazyLoadingValueHolderFactory(); $accessInterceptorFactory = new AccessInterceptorValueHolderFactory(); $accessInterceptorScopeLocalizerFactory = new AccessInterceptorScopeLocalizerFactory(); $initializer = function () { }; $reflectionClass = new ReflectionClass($className); if (!method_exists('Closure', 'bind') && $reflectionClass->getProperties(ReflectionProperty::IS_PRIVATE)) { $skipScopeLocalizerTests = true; } $generated = array($ghostProxyFactory->createProxy($className, $initializer), $virtualProxyFactory->createProxy($className, $initializer), $accessInterceptorFactory->createProxy(new $className())); if (!$skipScopeLocalizerTests) { $generated[] = $accessInterceptorScopeLocalizerFactory->createProxy(new $className()); } foreach ($generated as $key => $proxy) { $this->assertInstanceOf($className, $proxy); foreach ($generated as $comparedKey => $comparedProxy) { if ($comparedKey === $key) { continue; } $this->assertNotSame(get_class($comparedProxy), get_class($proxy)); } } $this->assertInstanceOf('ProxyManager\\Proxy\\GhostObjectInterface', $generated[0]); $this->assertInstanceOf('ProxyManager\\Proxy\\VirtualProxyInterface', $generated[1]); $this->assertInstanceOf('ProxyManager\\Proxy\\AccessInterceptorInterface', $generated[2]); $this->assertInstanceOf('ProxyManager\\Proxy\\ValueHolderInterface', $generated[2]); if (!$skipScopeLocalizerTests) { $this->assertInstanceOf('ProxyManager\\Proxy\\AccessInterceptorInterface', $generated[3]); } }
/** * {@inheritDoc} */ public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback) { $service = call_user_func($callback); if (!$service instanceof ServiceLocatorInterface) { return $service; } // @todo maybe this should be a callback, and `locatorInterceptors` should not be used explicitly return $this->proxyFactory->createProxy($service, array(), $this->locatorInterceptors); }
<?php /** * This example demonstrates how an access interceptor scope localizer * (which is a specific type of smart reference) is safe to use to * proxy fluent interfaces. */ require_once __DIR__ . '/../vendor/autoload.php'; use ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory; class FluentCounter { public $counter = 0; /** @return FluentCounter */ public function fluentMethod() { $this->counter += 1; return $this; } } $factory = new AccessInterceptorScopeLocalizerFactory(); $foo = new FluentCounter(); /* @var $proxy FluentCounter */ $proxy = $factory->createProxy($foo, array('fluentMethod' => function ($proxy) { echo "pre-fluentMethod #{$proxy->counter}!\n"; }), array('fluentMethod' => function ($proxy) { echo "post-fluentMethod #{$proxy->counter}!\n"; })); $proxy->fluentMethod()->fluentMethod()->fluentMethod()->fluentMethod(); echo 'The proxy counter is now at ' . $proxy->counter . "\n"; echo 'The real instance counter is now at ' . $foo->counter . "\n";
/** * {@inheritDoc} * * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::__construct * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::createProxy * @covers \ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory::getGenerator * * NOTE: serious mocking going on in here (a class is generated on-the-fly) - careful */ public function testWillTryAutoGeneration() { $instance = new stdClass(); $proxyClassName = UniqueIdentifierGenerator::getIdentifier('bar'); $generator = $this->getMock('ProxyManager\\GeneratorStrategy\\GeneratorStrategyInterface'); $autoloader = $this->getMock('ProxyManager\\Autoloader\\AutoloaderInterface'); $this->config->expects($this->any())->method('getGeneratorStrategy')->will($this->returnValue($generator)); $this->config->expects($this->any())->method('getProxyAutoloader')->will($this->returnValue($autoloader)); $generator->expects($this->once())->method('generate')->with($this->callback(function (ClassGenerator $targetClass) use($proxyClassName) { return $targetClass->getName() === $proxyClassName; })); // simulate autoloading $autoloader->expects($this->once())->method('__invoke')->with($proxyClassName)->will($this->returnCallback(function () use($proxyClassName) { eval('class ' . $proxyClassName . ' extends \\ProxyManagerTestAsset\\AccessInterceptorValueHolderMock {}'); })); $this->inflector->expects($this->once())->method('getProxyClassName')->with('stdClass')->will($this->returnValue($proxyClassName)); $this->inflector->expects($this->once())->method('getUserClassName')->with('stdClass')->will($this->returnValue('ProxyManagerTestAsset\\LazyLoadingMock')); $factory = new AccessInterceptorScopeLocalizerFactory($this->config); /* @var $proxy \ProxyManagerTestAsset\AccessInterceptorValueHolderMock */ $proxy = $factory->createProxy($instance, array('foo'), array('bar')); $this->assertInstanceOf($proxyClassName, $proxy); $this->assertSame($instance, $proxy->instance); $this->assertSame(array('foo'), $proxy->prefixInterceptors); $this->assertSame(array('bar'), $proxy->suffixInterceptors); }