1 Commits

Author SHA1 Message Date
Benjamin Eberlei
2d1dcf6c20 Initial References Commit 2012-04-07 00:08:48 +02:00
5 changed files with 387 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\KeyValueStore\References;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
/**
* AnnotationDriver for References
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class AnnotationDriver implements Driver
{
private $reader;
public function __construct($reader)
{
$this->reader = $reader;
}
/**
* Loads the metadata for the specified class into the provided container.
*
* @param string $className
* @param ClassMetadata $metadata
*/
function loadMetadataForClass($className, ClassMetadata $metadata)
{
$class = $metadata->getReflectionClass();
if (!$class) {
// this happens when running annotation driver in combination with
// static reflection services. This is not the nicest fix
$class = new \ReflectionClass($metadata->name);
}
// Evaluate annotations on properties/fields
foreach ($class->getProperties() as $property) {
$referenceOneAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\KeyValueStore\References\Annotations\ReferenceOne');
if ($referenceOneAnnot) {
$metadata->addReferenceOne(
$property->getName(),
$referenceOneAnnot->targetEntity
);
}
$referenceManyAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\KeyValueStore\References\Annotations\ReferenceMany');
if ($referenceManyAnnot) {
$metadata->addReferenceMany(
$property->getName(),
$referenceManyAnnot->targetEntity,
$referenceManyAnnot->parentField,
$referenceManyAnnot->rangeField,
);
}
}
}
/**
* Gets the names of all mapped classes known to this driver.
*
* @return array The names of all mapped classes known to this driver.
*/
function getAllClassNames()
{
}
/**
* Whether the class with the specified name should have its metadata loaded.
* This is only the case if it is either mapped as an Entity or a
* MappedSuperclass.
*
* @param string $className
* @return boolean
*/
function isTransient($className)
{
return false;
}
}

View File

@@ -0,0 +1,57 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\KeyValueStore\Integration;
use Doctrine\KeyValueStore\EntityManager;
/**
* Non-transaction save listener to synchronize association with to-one or
* to-many sets of key-value store entities into the storage.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ReferenceListener
{
/**
* @var EntityManager
*/
private $kvsManager;
public function __construct(EntityManager $manager)
{
$this->kvsManager = $manager;
}
public function postLoad($eventArgs)
{
}
public function postUpdate($eventArgs)
{
}
public function postInsert($eventArgs)
{
}
}

View File

@@ -0,0 +1,76 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\KeyValueStore\References;
/**
* Reference Metadata
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ReferenceMetadata
{
const REFERENCE_ONE = 1;
const REFERENCE_MANY = 2;
public $name;
public $namespace;
public $references = array();
public $reflFields = array();
public function __construct($name)
{
$this->name = $name;
if ($pos = strrpos($name, "\\")) {
$this->namespace = substr($name, 0, $pos);
}
}
public function addReferenceOne($fieldName, $targetEntity)
{
if ($this->namespace || strpos($targetEntity, "\\") === false) {
$targetEntity = $this->namespace . "\\" . $targetEntity;
}
$this->references[$fieldName] = array(
'type' => self::REFERENCE_ONE,
'targetEntity' => $targetEntity
);
}
public function addReferenceMany($fieldName, $targetEntity, $parentField, $rangeField)
{
if ($this->namespace || strpos($targetEntity, "\\") === false) {
$targetEntity = $this->namespace . "\\" . $targetEntity;
}
$this->references[$fieldName] = array(
'type' => self::REFERENCE_MANY,
'targetEntity' => $targetEntity,
'parentField' => $parentField,
'rangeField' => $rangeField,
);
}
public function __sleep()
{
return array('name', 'namespace', 'references');
}
}

View File

@@ -0,0 +1,92 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\KeyValueStore\Integration;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\Common\Persistence\Mapping\ReflectionService;
/**
* Metadata factory for Reference Mapping Metadata
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ReferenceMetadataFactory extends AbstractClassMetadataFactory
{
/**
* @var ObjectManager
*/
private $parentManager;
/**
* @var MappingDriver
*/
private $mappingDriver;
public function __construct(ObjectManager $parentManager, MappingDriver $driver)
{
$this->mappingDriver = $driver;
$this->parentManager = $parentManager;
}
protected function initialize()
{
}
protected function getFqcnFromAlias($namespaceAlias, $simpleClassName)
{
throw new \InvalidArgumentException("aliasing is not supported.");
}
protected function doLoadMetadata($class, $parent, $rootEntityFound)
{
$this->getDriver()->loadMetadataForClass($class->name, $class);
}
protected function newClassMetadataInstance($className)
{
return new ReferenceMetadata($className);
}
protected function getDriver()
{
return $this->mappingDriver;
}
protected function wakeupReflection(ClassMetadata $class, ReflectionService $reflService)
{
$class->reflClass = $reflService->getClass($class->name);
foreach ($class->references as $fieldName => $mapping) {
$class->reflFields[$fieldName] = $reflService->getAccessibleProperty($class->name, $fieldName);
}
}
protected function initializeReflection(ClassMetadata $class, ReflectionService $reflService)
{
$reflClass = $reflService->getClass($class->name);
if ($reflClass) {
foreach ($class->references as $fieldName => $mapping) {
$class->reflFields[$fieldName] = $reflService->getAccessibleProperty($class->name, $fieldName);
}
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Doctrine\Tests\KeyValueStore\References;
use Doctrine\KeyValueStore\References\ReferenceMetadata;
class ReferenceMetadataTest extends \PHPUnit_Framework_TestCase
{
public function testCreate()
{
$class = new ReferenceMetadata('Foo\Bar');
$this->assertEquals('Foo', $class->namespace);
$this->assertEquals('Foo\Bar', $class->name);
}
public function testAddReferenceOne()
{
$class = new ReferenceMetadata('Foo\Bar');
$class->addReferenceOne('baz', 'Baz');
$this->assertEquals(array(
'type' => ReferenceMetadata::REFERENCE_ONE,
'targetEntity' => 'Foo\Baz',
), $class->references['baz']);
}
public function testAddReferenceMany()
{
$class = new ReferenceMetadata('Foo\Bar');
$class->addReferenceMany('baz', 'Baz', 'bar', 'range');
$this->assertEquals(array(
'type' => ReferenceMetadata::REFERENCE_MANY,
'targetEntity' => 'Foo\Baz',
'parentField' => 'bar',
'rangeField' => 'range',
), $class->references['baz']);
}
public function testSerialize()
{
$class = new ReferenceMetadata('Foo\Bar');
$class->addReferenceOne('baz1', 'Baz');
$class->addReferenceMany('baz2', 'Baz', 'bar', 'range');
$class = unserialize(serialize($class));
$this->assertEquals('Foo', $class->namespace);
$this->assertEquals('Foo\Bar', $class->name);
$this->assertEquals(array(
'type' => ReferenceMetadata::REFERENCE_ONE,
'targetEntity' => 'Foo\Baz',
), $class->references['baz1']);
$this->assertEquals(array(
'type' => ReferenceMetadata::REFERENCE_MANY,
'targetEntity' => 'Foo\Baz',
'parentField' => 'bar',
'rangeField' => 'range',
), $class->references['baz2']);
}
}