Skip to content

Commit

Permalink
Try value proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
bakura10 committed Oct 28, 2013
1 parent aabac1f commit a913506
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 36 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"jms/metadata": "dev-master",
"doctrine/common": "~2.4",
"doctrine/doctrine-module": "~0.8",
"ocramius/proxy-manager": "~0.5",
"zendframework/zend-http": "~2.2",
"zendframework/zend-inputfilter": "~2.2",
"zendframework/zend-mvc": "~2.2",
Expand Down
4 changes: 2 additions & 2 deletions src/ZfrRest/Factory/ResourceMetadataFactoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@

use Doctrine\Common\Annotations\AnnotationReader;
use Metadata\Driver\DriverChain;
use Metadata\MetadataFactory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use ZfrRest\Factory\Exception;
use ZfrRest\Resource\Metadata\Driver\AnnotationDriver;
use ZfrRest\Resource\Metadata\ResourceMetadataFactory;

/**
* Factory used to create the resource metadata factory
Expand All @@ -48,7 +48,7 @@ public function createService(ServiceLocatorInterface $serviceLocator)
$doctrineMetadataFactory = $objectManager->getMetadataFactory();

$driverChain = new DriverChain();
$resourceMetadataFactory = new MetadataFactory($driverChain);
$resourceMetadataFactory = new ResourceMetadataFactory($driverChain);

$drivers = $moduleOptions->getDrivers();
foreach ($drivers as $driverOptions) {
Expand Down
75 changes: 41 additions & 34 deletions src/ZfrRest/Resource/Metadata/Driver/AnnotationDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

use Metadata\Driver\DriverInterface;
use Metadata\MetadataFactoryInterface;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ReflectionClass;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory as DoctrineMetadataFactory;
Expand Down Expand Up @@ -52,6 +53,11 @@ class AnnotationDriver implements DriverInterface
*/
protected $resourceMetadataFactory;

/**
* @var LazyLoadingValueHolderFactory
*/
protected $lazyFactory;

/**
* Constructor
*
Expand All @@ -67,58 +73,59 @@ public function __construct(
$this->annotationReader = $reader;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->doctrineMetadataFactory = $doctrineMetadataFactory;
$this->lazyFactory = new LazyLoadingValueHolderFactory();
}

/**
* {@inheritDoc}
*/
public function loadMetadataForClass(ReflectionClass $class)
{
$classMetadata = $this->doctrineMetadataFactory->getMetadataFor($class->getName());

$resourceMetadata = new ResourceMetadata($class->getName());
$resourceMetadata->classMetadata = $classMetadata;

// Process class level annotations
$classAnnotations = $this->annotationReader->getClassAnnotations($class);
$this->processMetadata($resourceMetadata, $classAnnotations);
$initializer = function(&$wrappedObject, $proxy, $method, array $parameters, &$initializer) use ($class) {
$classMetadata = $this->doctrineMetadataFactory->getMetadataFor($class->getName());
$resourceMetadata = new ResourceMetadata($class->getName());

// Then process properties level annotations (for associations)
$classProperties = $class->getProperties();
foreach ($classProperties as $classProperty) {
$propertyAnnotations = $this->annotationReader->getPropertyAnnotations($classProperty);
$resourceMetadata->classMetadata = $classMetadata;

// We need to have at least the ExposeAssociation annotation, so we loop through all the annotations,
// check if it exists, and remove it so that we can process other annotations
foreach ($propertyAnnotations as $key => $propertyAnnotation) {
if ($propertyAnnotation instanceof Annotation\ExposeAssociation) {
unset($propertyAnnotations[$key]);
// Process class level annotations
$classAnnotations = $this->annotationReader->getClassAnnotations($class);
$this->processMetadata($resourceMetadata, $classAnnotations);

$associationName = $classProperty->getName();
// Process property level annotations
$classProperties = $class->getProperties();
foreach ($classProperties as $classProperty) {
$propertyAnnotations = $this->annotationReader->getPropertyAnnotations($classProperty);

// @TODO: We need this to avoid circular dependency
// @TODO: we should find something better as you cannot override REST mapping on inverse sides
if ($classMetadata->isAssociationInverseSide($associationName)) {
return $resourceMetadata;
}
// We need to have at least the ExposeAssociation annotation, so we loop through all the annotations,
// check if it exists, and remove it so that we can process other annotations
foreach ($propertyAnnotations as $key => $propertyAnnotation) {
if ($propertyAnnotation instanceof Annotation\ExposeAssociation) {
unset($propertyAnnotations[$key]);

$targetClass = $classMetadata->getAssociationTargetClass($associationName);
$associationName = $classProperty->getName();
$targetClass = $classMetadata->getAssociationTargetClass($associationName);

// We first load the metadata for the entity, and we then loop through the annotations defined
// at the association level so that the user can override some properties
$resourceAssociationMetadata = clone $this->resourceMetadataFactory
->getMetadataForClass($targetClass)
->getOutsideClassMetadata();
// We first load the metadata for the entity, and we then loop through the annotations defined
// at the association level so that the user can override some properties
$resourceAssociationMetadata = clone $this->resourceMetadataFactory
->getMetadataForClass($targetClass)
->getOutsideClassMetadata();

$this->processMetadata($resourceAssociationMetadata, $propertyAnnotations);
$resourceMetadata->associations[$associationName] = $resourceAssociationMetadata;
$this->processMetadata($resourceAssociationMetadata, $propertyAnnotations);
$resourceMetadata->associations[$associationName] = $resourceAssociationMetadata;

break;
break;
}
}
}
}

return $resourceMetadata;
$initializer = null; // disable initialization
$wrappedObject = $resourceMetadata;

return true;
};

return $this->lazyFactory->createProxy('ZfrRest\Resource\Metadata\ResourceMetadata', $initializer);
}

/**
Expand Down
38 changes: 38 additions & 0 deletions src/ZfrRest/Resource/Metadata/ResourceMetadataFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/

namespace ZfrRest\Resource\Metadata;

use Metadata\MetadataFactory;

/**
* ResourceMetadata
*
* @license MIT
* @author Michaël Gallego <mic.gallego@gmail.com>
*/
class ResourceMetadataFactory extends MetadataFactory
{
/**
* {@inheritDoc}
*/
public function getMetadataForClass($className)
{
return parent::getMetadataForClass($className);
}
}

0 comments on commit a913506

Please sign in to comment.