Skip to content

Commit

Permalink
Add mapping for 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 60bcebc commit 3634a2f
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 0 deletions.
12 changes: 12 additions & 0 deletions doctrine-mongo-mapping.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
<xs:element name="default-discriminator-value" type="odm:default-discriminator-value" minOccurs="0"/>
<xs:element name="sort" type="odm:sort-map" minOccurs="0" />
<xs:element name="criteria" type="odm:criteria-map" minOccurs="0" />
<xs:element name="redundant-fields" type="odm:redundant-field-list" minOccurs="0" />
</xs:sequence>
<xs:attribute name="target-document" type="xs:string" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
Expand All @@ -157,6 +158,7 @@
<xs:element name="default-discriminator-value" type="odm:default-discriminator-value" minOccurs="0"/>
<xs:element name="sort" type="odm:sort-map" minOccurs="0" />
<xs:element name="criteria" type="odm:criteria-map" minOccurs="0" />
<xs:element name="redundant-fields" type="odm:redundant-field-list" minOccurs="0" />
</xs:sequence>
<xs:attribute name="target-document" type="xs:string" />
<xs:attribute name="collection-class" type="xs:string" />
Expand Down Expand Up @@ -184,6 +186,16 @@
</xs:sequence>
</xs:complexType>

<xs:complexType name="redundant-field-list">
<xs:sequence>
<xs:element name="field" type="odm:redundant-field" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="redundant-field">
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>

<xs:complexType name="criteria-type">
<xs:attribute name="field" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="value" type="xs:NMTOKEN" use="required" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,5 @@ final class ReferenceMany extends AbstractField
public $skip;
public $strategy = CollectionHelper::DEFAULT_STRATEGY;
public $collectionClass;
public $redundantFields = array();
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ final class ReferenceOne extends AbstractField
public $criteria = array();
public $limit;
public $skip;
public $redundantFields = array();
}
9 changes: 9 additions & 0 deletions lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,15 @@ public function mapField(array $mapping)
throw MappingException::simpleReferenceRequiresTargetDocument($this->name, $mapping['fieldName']);
}

if (isset($mapping['reference'])
&& isset($mapping['storeAs'])
&& $mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID
&& isset($mapping['redundantFields'])
&& $mapping['redundantFields'] !== []
) {
throw MappingException::simpleReferenceCannotHaveRedundantFields($this->name, $mapping['fieldName']);
}

if (isset($mapping['reference']) && empty($mapping['targetDocument']) && empty($mapping['discriminatorMap']) &&
(isset($mapping['mappedBy']) || isset($mapping['inversedBy']))) {
throw MappingException::owningAndInverseReferencesRequireTargetDocument($this->name, $mapping['fieldName']);
Expand Down
6 changes: 6 additions & 0 deletions lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,12 @@ private function addReferenceMapping(ClassMetadataInfo $class, $reference, $type
if (isset($attributes['also-load'])) {
$mapping['alsoLoadFields'] = explode(',', $attributes['also-load']);
}
if (isset($reference->{'redundant-fields'})) {
foreach ($reference->{'redundant-fields'}->{'field'} as $redundantField) {
$attr = $redundantField->attributes();
$mapping['redundantFields'][] = (string) $attr['name'];
}
}
$this->addFieldMapping($class, $mapping);
}

Expand Down
3 changes: 3 additions & 0 deletions lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ private function addMappingFromReference(ClassMetadataInfo $class, $fieldName, $
if (isset($reference['criteria'])) {
$mapping['criteria'] = $reference['criteria'];
}
if (isset($reference['redundantFields'])) {
$mapping['redundantFields'] = $reference['redundantFields'];
}
$this->addFieldMapping($class, $mapping);
}

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 @@ -254,6 +254,16 @@ public static function simpleReferenceMustNotTargetDiscriminatedDocument($target
return new self("Simple reference must not target document using Single Collection Inheritance, $targetDocument targeted.");
}

/**
* @param string $className
* @param string $fieldName
* @return MappingException
*/
public static function simpleReferenceCannotHaveRedundantFields($className, $fieldName)
{
return new self("Simple reference $className::$fieldName may not store redundant fields");
}

/**
* @param string $strategy
* @param string $className
Expand Down
3 changes: 3 additions & 0 deletions tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,7 @@ class ReferenceStoreAsDocument

/** @ODM\ReferenceOne(targetDocument="Documents\User", storeAs="dbRefWithDb") */
public $ref3;

/** @ODM\ReferenceOne(targetDocument="Documents\User", storeAs="dbRef", redundantFields={"username"}) */
public $ref4;
}
15 changes: 15 additions & 0 deletions tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataInfoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,21 @@ public function testNoReferenceManyInShardKey()
$cm->mapManyEmbedded(['fieldName' => 'referenceMany']);
$cm->setShardKey(array('referenceMany' => 1));
}

/**
* @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException
* @expectedExceptionMessage Simple reference stdClass::referenceOne may not store redundant fields
*/
public function testSimpleReferenceWithRedundantFieldsThrowsError()
{
$cm = new ClassMetadataInfo('stdClass');
$cm->mapOneReference([
'fieldName' => 'referenceOne',
'targetDocument' => 'stdClass',
'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_ID,
'redundantFields' => ['foo', 'bar'],
]);
}
}

class TestCustomRepositoryClass extends DocumentRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ public function testDriver()
'limit' => null,
'skip' => null,
'orphanRemoval' => false,
'redundantFields' => ['name'],
), $classMetadata->fieldMappings['account']);

$this->assertEquals(array(
Expand Down Expand Up @@ -220,6 +221,7 @@ public function testDriver()
'limit' => null,
'skip' => null,
'orphanRemoval' => false,
'redundantFields' => ['name'],
), $classMetadata->fieldMappings['groups']);

$this->assertEquals(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@
<cascade>
<all />
</cascade>
<redundant-fields>
<field name="name"/>
</redundant-fields>
</reference-many>
<reference-one target-document="Documents\Account" field="account">
<cascade>
<all />
</cascade>
<redundant-fields>
<field name="name"/>
</redundant-fields>
</reference-one>
<lifecycle-callbacks>
<lifecycle-callback method="doStuffOnPrePersist" type="prePersist" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ TestDocuments\User:
account:
targetDocument: Documents\Account
cascade: all
redundantFields: [name]
referenceMany:
groups:
targetDocument: Documents\Group
cascade: all
redundantFields: [name]
lifecycleCallbacks:
prePersist: [doStuffOnPrePersist]
postPersist: [doStuffOnPostPersist, doOtherStuffOnPostPersist]
Expand Down

0 comments on commit 3634a2f

Please sign in to comment.