/**
  * 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]);
     }
 }
Пример #2
0
 private static function spyInvokations($object, array $methodOverrides, ReflectionClass $reflection)
 {
     $factory = new AccessInterceptorValueHolderFactory();
     $mock = $factory->createProxy($object);
     $id = spl_object_hash($mock);
     self::$mockInspectors[$id] = new ObjectInspector();
     foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
         if ($method->isStatic()) {
             continue;
         }
         $prefix = function ($proxy, $instance, $method, $parameters, &$returnEarly) use($id, $methodOverrides) {
             if (array_key_exists($method, $methodOverrides)) {
                 $returnEarly = true;
                 $returnValue = $methodOverrides[$method];
                 if ($returnValue instanceof \Closure) {
                     $returnValue = call_user_func_array($returnValue, $parameters);
                 }
                 self::$mockInspectors[$id]->recordInvokation($method, array_values($parameters), $returnValue);
                 return $returnValue;
             }
         };
         $suffix = function ($proxy, $instance, $method, $parameters, $returnValue) use($id) {
             self::$mockInspectors[$id]->recordInvokation($method, array_values($parameters), $returnValue);
         };
         $mock->setMethodPrefixInterceptor($method->getName(), $prefix);
         $mock->setMethodSuffixInterceptor($method->getName(), $suffix);
     }
     return $mock;
 }
Пример #3
0
 /**
  * @param mixed $instance
  *
  * @return AccessInterceptorInterface
  */
 public function generate($instance) : AccessInterceptorInterface
 {
     $class = new ReflectionClass($instance);
     $proxy = $this->proxyFactory->createProxy($instance);
     foreach ($this->collectCacheMethods($class) as $method => $annotations) {
         $this->registerPrefixInterceptor($proxy, $method, $annotations);
         $this->registerSuffixInterceptor($proxy, $method, $annotations);
     }
     return $proxy;
 }
Пример #4
0
 public function proxyFromBean(AbstractBean $bean)
 {
     $object = $bean->getObject();
     if ($object === null) {
         return null;
     }
     $rc = new \ReflectionClass($object);
     $methods = $rc->getMethods();
     $beforeCall = $this->getBeforeCallMethod($methods, $bean);
     $afterCall = $this->getAfterCallMethod($methods, $bean);
     $proxyObject = $this->proxyFactory->createProxy($object, $beforeCall, $afterCall);
     return $proxyObject;
 }
 /**
  * {@inheritDoc}
  *
  * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::__construct
  * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::createProxy
  * @covers \ProxyManager\Factory\AccessInterceptorValueHolderFactory::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'));
     $this->signatureChecker->expects($this->atLeastOnce())->method('checkSignature');
     $this->classSignatureGenerator->expects($this->once())->method('addSignature')->will($this->returnArgument(0));
     $factory = new AccessInterceptorValueHolderFactory($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);
 }
 /**
  * @param  Table                      $table
  * @return AccessInterceptorInterface
  */
 public function createProxy(RestController $controller)
 {
     return $this->factory->createProxy($controller);
 }
Пример #7
0
<?php

require_once __DIR__ . '/../vendor/autoload.php';
use ProxyManager\Factory\AccessInterceptorValueHolderFactory;
class Foo
{
    public function doFoo()
    {
        echo "Foo!\n";
    }
}
$factory = new AccessInterceptorValueHolderFactory();
$proxy = $factory->createProxy(new Foo(), array('doFoo' => function () {
    echo "pre-foo!\n";
}), array('doFoo' => function () {
    echo "post-foo!\n";
}));
$proxy->doFoo();
Пример #8
0
 /**
  * Transform Entity to a new Object
  * If the target Object has the EntityProxy trait, then it will also generate a proxy class
  *
  * @param $objSrc
  * @return mixed
  */
 public function transform($objSrc)
 {
     $objSrcData = $this->hydrator->extract($objSrc);
     $entityProxyClass = $this->annotationReader->getEntityTransformTargetClass(get_class($objSrc));
     if ($entityProxyClass != $this->class) {
         $entityAnnotations = $this->annotationReader->getEntityAnnotations($this->class);
         $associations = $entityAnnotations->getAssociationMappings();
         foreach ($associations as $key => $association) {
             if (isset($objSrcData[$key])) {
                 $collection = $objSrcData[$key];
                 $items = array();
                 foreach ($collection as $item) {
                     $items[] = $item;
                 }
                 $objSrcData[$key] = new ArrayCollection($items);
             }
         }
         $objDest = $this->instantiate($entityProxyClass);
         $this->hydrator->hydrate($objSrcData, $objDest);
         /**
          * Check if EntityProxy
          */
         if ($this->isEntityProxy($objDest)) {
             $reflectionClass = new \ReflectionClass($objDest);
             $reflectionProperty = $reflectionClass->getProperty('entity');
             $reflectionProperty->setAccessible(true);
             $reflectionProperty->setValue($objDest, $objSrc);
             $reflectionProperty->setAccessible(false);
             $reflectionProperty = $reflectionClass->getProperty('hydrator');
             $reflectionProperty->setAccessible(true);
             $reflectionProperty->setValue($objDest, $this->hydrator);
             $reflectionProperty->setAccessible(false);
             $syncedPropertyAnnotations = $this->annotationReader->getEntityTransformationSyncedProperties($this->class);
             if ($syncedPropertyAnnotations) {
                 $syncedProperties = $syncedPropertyAnnotations;
             } else {
                 $syncedProperties = array_keys($objSrcData);
             }
             $reflectionProperty = $reflectionClass->getProperty('syncedProperties');
             $reflectionProperty->setAccessible(true);
             $reflectionProperty->setValue($objDest, $syncedProperties);
             $reflectionProperty->setAccessible(false);
             $factory = new Factory();
             $proxy = $factory->createProxy($objDest, array());
             $syncAuto = $this->annotationReader->getEntitySyncAuto($this->class);
             if ($syncAuto) {
                 $syncedListeners = $this->annotationReader->getEntitySyncListeners($this->class);
                 if (!$syncedListeners) {
                     $syncedListeners = array();
                     foreach (array_keys($objSrcData) as $property) {
                         $syncedListeners[] = Inflector::camelize('set_' . $property);
                     }
                     foreach ($associations as $associationKey => $association) {
                         $associationKey = Inflector::singularize($associationKey);
                         $syncedListeners[] = Inflector::camelize('add_' . $associationKey);
                         $syncedListeners[] = Inflector::camelize('remove_' . $associationKey);
                     }
                 }
                 foreach ($syncedListeners as $syncListener) {
                     $proxy->setMethodSuffixInterceptor($syncListener, function ($proxy, $instance) {
                         $instance->syncToEntity();
                     });
                 }
             }
             return $proxy;
         }
         return $objDest;
     }
     return $objSrc;
 }
Пример #9
0
 /**
  * Transform Entity to proxy object
  *
  * @param $objSrc
  * @return mixed
  * @throws \Exception
  */
 public function transform($objSrc)
 {
     // No need to transform scalar or null values
     if (is_scalar($objSrc) || is_null($objSrc)) {
         return $objSrc;
     }
     $objSrcData = $this->hydrator->extract($objSrc);
     $objSrcClass = $this->annotationReader->getDoctrineProxyResolver()->unwrapDoctrineProxyClass(get_class($objSrc));
     $proxyClass = $this->annotationReader->getProxyTargetClass(get_class($objSrc));
     if (!$proxyClass) {
         return $objSrc;
     }
     if ($proxyClass != $objSrcClass) {
         $doctrineAnnotations = $this->annotationReader->getDoctrineAnnotations($this->class);
         $associations = $doctrineAnnotations->getAssociationNames();
         /**
          * Lazy Load Associations
          */
         foreach ($associations as $key) {
             if (isset($objSrcData[$key])) {
                 $propertyValue = $objSrcData[$key];
                 $factory = new LazyLoadingValueHolderFactory();
                 $initializer = function (&$wrappedObject, LazyLoadingInterface $proxy, $method, array $parameters, &$initializer) use($propertyValue) {
                     $initializer = null;
                     if ($propertyValue instanceof ArrayCollection) {
                         $items = array();
                         foreach ($propertyValue as $item) {
                             $items[] = $this->proxyManager->transform($item);
                         }
                         $wrappedObject = new ArrayCollection($items);
                     } else {
                         $wrappedObject = $this->proxyManager->transform($propertyValue);
                     }
                     return true;
                 };
                 // check if property final
                 $reflectionClass = new \ReflectionClass(get_class($propertyValue));
                 if ($reflectionClass->isFinal()) {
                     $objSrcData[$key] = $propertyValue;
                 } else {
                     if ($propertyValue instanceof Collection) {
                         $objSrcData[$key] = $factory->createProxy(get_class($propertyValue), $initializer);
                     } else {
                         $objSrcData[$key] = $factory->createProxy($this->annotationReader->getProxyTargetClass(get_class($propertyValue)), $initializer);
                     }
                 }
             }
         }
         $objDest = $this->proxyManager->instantiate($proxyClass);
         /**
          * Throw Exceptions
          */
         if (!$objDest instanceof $objSrcClass) {
             throw new \Exception('The proxy target class should extend the underlying data object.  Proxy Class: ' . $proxyClass);
         }
         if (!$this->isProxy($objDest)) {
             throw new \Exception('The proxy target class should use the Proxy trait.  Proxy Class: ' . $proxyClass);
         }
         /**
          * Hydrate the data
          */
         $this->hydrate($objSrcData, $objDest);
         /**
          * Sync Properties
          */
         $syncProperties = $this->annotationReader->getProxySyncedProperties($this->class);
         if ($syncProperties == Constants::SYNC_PROPERTIES_ALL) {
             $syncProperties = array_keys($objSrcData);
         }
         /**
          * Sync Methods
          */
         $syncMethods = $this->annotationReader->getProxySyncMethods($this->class);
         if ($syncMethods == Constants::SYNC_METHODS_ALL) {
             $syncMethods = array();
             foreach (array_keys($objSrcData) as $property) {
                 $syncMethods[] = Inflector::camelize('set_' . $property);
             }
             foreach ($associations as $associationKey => $association) {
                 $associationKey = Inflector::singularize($associationKey);
                 $associationKeyPlural = Inflector::pluralize($associationKey);
                 $syncMethods[] = Inflector::camelize('add_' . $associationKey);
                 $syncMethods[] = Inflector::camelize('remove_' . $associationKey);
                 $syncMethods[] = Inflector::camelize('set_' . $associationKeyPlural);
                 $syncMethods[] = Inflector::camelize('set_' . $associationKey);
             }
         } elseif ($syncMethods == Constants::SYNC_METHODS_NONE) {
             $syncMethods = array();
         }
         /**
          * Set properties on proxied object
          */
         PropertyAccess::set($objDest, 'dataObject', $objSrc);
         PropertyAccess::set($objDest, 'transformer', $this);
         PropertyAccess::set($objDest, 'syncProperties', $syncProperties);
         PropertyAccess::set($objDest, 'syncMethods', $syncMethods);
         /**
          * Attach Interceptors
          */
         $factory = new Factory();
         $proxy = $factory->createProxy($objDest, array());
         foreach ($syncMethods as $syncMethod) {
             $proxy->setMethodSuffixInterceptor($syncMethod, function ($proxy, $instance) use($syncMethod) {
                 $syncMethods = PropertyAccess::get($instance, 'syncMethods');
                 if (is_array($syncMethods) && in_array($syncMethod, $syncMethods)) {
                     $instance->syncData();
                 }
             });
         }
         return $proxy;
     }
     return $objSrc;
 }
 /**
  * @param  Table                      $table
  * @return AccessInterceptorInterface
  */
 public function createProxy(Table $table)
 {
     return $this->factory->createProxy($table);
 }
Пример #11
0
 /**
  * Create a new entity manager
  *
  * @param DriverInterface        $driver
  * @param MapperInterface        $mapper
  * @param SerialiserMap          $serialiser_map
  * @param KeySchemeInterface     $key_scheme
  * @param Configuration          $configuration
  * @param EntityCachingInterface $cache
  * @return EntityManager
  */
 public static function build(DriverInterface $driver, MapperInterface $mapper, SerialiserMap $serialiser_map = null, KeySchemeInterface $key_scheme = null, Configuration $configuration = null, EntityCachingInterface $cache = null)
 {
     $em_conf = $configuration ?: new Configuration();
     $proxy_conf = new \ProxyManager\Configuration();
     $proxy_conf->setProxiesTargetDir($em_conf->getCacheDir());
     $proxy_conf->setProxiesNamespace(Writer::PROXY_NAMESPACE);
     $proxy_factory = new AccessInterceptorValueHolderFactory($proxy_conf);
     $interceptor_factor = new EntityManagerInterceptorFactory();
     $em = new self($driver, $mapper, $serialiser_map, $key_scheme, $em_conf, $cache);
     $proxy = $proxy_factory->createProxy($em, $interceptor_factor->getPrefixInterceptors(), $interceptor_factor->getSuffixInterceptors());
     $em->setProxy($proxy);
     return $proxy;
 }