/**
  * 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);
 }