Skip to content

Commit

Permalink
Store redundant fields in references
Browse files Browse the repository at this point in the history
  • Loading branch information
alcaeus committed Nov 23, 2016
1 parent 3634a2f commit 42af3f2
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lib/Doctrine/ODM/MongoDB/DocumentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Doctrine\ODM\MongoDB\Proxy\ProxyFactory;
use Doctrine\ODM\MongoDB\Query\FilterCollection;
use Doctrine\ODM\MongoDB\Repository\RepositoryFactory;
use Doctrine\ODM\MongoDB\Types\Type;

/**
* The DocumentManager class is the central access point for managing the
Expand Down Expand Up @@ -738,6 +739,23 @@ public function createDBRef($document, array $referenceMapping = null)
$dbRef[$discriminatorField] = $discriminatorValue;
}

if ($referenceMapping !== null && isset($referenceMapping['redundantFields'])) {
foreach ($referenceMapping['redundantFields'] as $fieldName) {
if ($class->hasAssociation($fieldName)) {
throw MappingException::redundantAssociationNotAllowed(get_class($document), $fieldName);
}

if (! $class->hasField($fieldName)) {
throw MappingException::mappingNotFound(get_class($document), $fieldName);
}

$mapping = $class->getFieldMapping($fieldName);
$value = $class->getFieldValue($document, $fieldName);

$dbRef[$fieldName] = Type::getType($mapping['type'])->convertToDatabaseValue($value);
}
}

return $dbRef;
}

Expand Down
10 changes: 10 additions & 0 deletions lib/Doctrine/ODM/MongoDB/Mapping/MappingException.php
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ public static function simpleReferenceCannotHaveRedundantFields($className, $fie
return new self("Simple reference $className::$fieldName may not store redundant fields");
}

/**
* @param string $className
* @param string $fieldName
* @return MappingException
*/
public static function redundantAssociationNotAllowed($className, $fieldName)
{
return new self("Association $className::$fieldName can not be stored as redundant field");
}

/**
* @param string $strategy
* @param string $className
Expand Down
13 changes: 13 additions & 0 deletions tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,19 @@ public function testDifferentStoreAsDbReferences()
$this->assertArrayHasKey('$db', $dbRef);
}

public function testDbRefWithRedundantField()
{
$r = new \Documents\User();
$r->setUsername('foo');
$this->dm->persist($r);
$d = new ReferenceStoreAsDocument();
$class = $this->dm->getClassMetadata(get_class($d));

$dbRef = $this->dm->createDBRef($r, $class->associationMappings['ref4']);
$this->assertArrayHasKey('username', $dbRef);
$this->assertSame('foo', $dbRef['username']);
}

private function getMockClassMetadataFactory()
{
return $this->createMock('Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory');
Expand Down
118 changes: 118 additions & 0 deletions tests/Doctrine/ODM/MongoDB/Tests/Functional/RedundantFieldsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

namespace Doctrine\ODM\MongoDB\Tests\Functional;

use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

class RedundantFieldsTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest
{
public function testSimpleRedundantField()
{
$blog = new Blog('my-blog');
$this->dm->persist($blog);

$post = new Post($blog, 'My first post');
$this->dm->persist($post);
$this->dm->flush();

$rawPost = $this->dm->createQueryBuilder(Post::class)
->find()
->field('id')
->equals($post->getId())
->hydrate(false)
->getQuery()
->getSingleResult();

$this->assertSame('my-blog', $rawPost['blog']['title']);
$this->assertInstanceOf(\MongoDate::class, $rawPost['blog']['creationDate']);
}

public function testDatabaseValueIsPreparedInQuery()
{
$blog = new Blog('my-blog');
$this->dm->persist($blog);

$post = new Post($blog, 'My first post');
$this->dm->persist($post);
$this->dm->flush();

$result = $this->dm->createQueryBuilder(Post::class)
->find()
->field('blog.creationDate')
->equals($blog->getCreationDate())
->getQuery()
->execute();

$this->assertCount(1, $result);
}
}

/**
* @ODM\Document()
*/
class Blog
{
/** @ODM\Id */
protected $id;

/** @ODM\Field(type="string") */
protected $title;

/** @ODM\Field(type="date") */
protected $creationDate;

public function __construct($title)
{
$this->title = $title;
$this->creationDate = new \DateTime();
}

public function getId()
{
return $this->id;
}

public function getTitle()
{
return $this->title;
}

public function getCreationDate()
{
return $this->creationDate;
}
}

/** @ODM\Document */
class Post
{
/** @ODM\Id */
protected $id;

/** @ODM\ReferenceOne(targetDocument="Blog", redundantFields={"title","creationDate"}) */
protected $blog;

/** @ODM\Field(type="string") */
protected $title;

public function __construct(Blog $blog, $title)
{
$this->blog = $blog;
$this->title = $title;
}

public function getId()
{
return $this->id;
}

public function getBlog()
{
return $this->blog;
}

public function getTitle()
{
return $this->title;
}
}

0 comments on commit 42af3f2

Please sign in to comment.