public function getClassMetadata($class) { $metadata = new \Doctrine\ODM\CouchDB\Mapping\ClassMetadata($class); $metadata->initializeReflection(new RuntimeReflectionService()); $metadata->wakeupReflection(new RuntimeReflectionService()); return $metadata; }
/** * @param object $document * @param ClassMetadata $cm * @param DocumentManager $dm * @return array */ public function generate($document, ClassMetadata $cm, DocumentManager $dm) { $id = $cm->getIdentifierValue($document); if (!$id) { throw new \Exception("no id"); } return $id; }
/** * @param object $document * @param ClassMetadata $cm * @param DocumentManager $dm * @return array */ public function generate($document, ClassMetadata $cm, DocumentManager $dm) { $id = $cm->getIdentifierValue($document); if (!$id) { throw CouchDBException::assignedIdGeneratorNoIdFound($cm->name); } return $id; }
public function setUp() { $this->type = 'Doctrine\\Tests\\ODM\\CouchDB\\UoWUser'; $this->dm = \Doctrine\ODM\CouchDB\DocumentManager::create(array('dbname' => 'test')); $this->uow = new UnitOfWork($this->dm); $metadata = new \Doctrine\ODM\CouchDB\Mapping\ClassMetadata($this->type); $metadata->mapField(array('fieldName' => 'id', 'id' => true)); $metadata->mapField(array('fieldName' => 'username', 'type' => 'string')); $metadata->idGenerator = \Doctrine\ODM\CouchDB\Mapping\ClassMetadata::IDGENERATOR_ASSIGNED; $cmf = $this->dm->getClassMetadataFactory(); $cmf->setMetadataFor($this->type, $metadata); }
public function setUp() { if (!class_exists('Doctrine\\ODM\\CouchDB\\Version')) { $this->markTestSkipped('Doctrine CouchDB has to be installed for this test to run.'); } $c = $this->getMock('FOS\\UserBundle\\Util\\CanonicalizerInterface'); $ef = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'); $class = new ClassMetadata(self::USERTYPE); $class->mapField(array('fieldName' => 'username')); $this->dm = $this->getMock('Doctrine\\ODM\\CouchDB\\DocumentManager', array('getRepository', 'persist', 'remove', 'flush', 'getClassMetadata'), array(), '', false); $this->repository = $this->getMock('Doctrine\\ODM\\CouchDB\\DocumentRepository', array('findBy', 'findAll'), array(), '', false); $this->dm->expects($this->any())->method('getRepository')->with($this->equalTo(self::USERTYPE))->will($this->returnValue($this->repository)); $this->dm->expects($this->any())->method('getClassMetadata')->with($this->equalTo(self::USERTYPE))->will($this->returnValue($class)); $this->userManager = new UserManager($ef, $c, $c, $this->dm, self::USERTYPE); }
/** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadata $class) { /* @var $xmlRoot SimpleXMLElement */ $xmlRoot = $this->getElement($className); if ($xmlRoot->getName() == "document") { $class->setCustomRepositoryClass(isset($xmlRoot['repository-class']) ? (string) $xmlRoot['repository-class'] : null); if (isset($xmlRoot['indexed']) && $xmlRoot['indexed'] == true) { $class->indexed = true; } } else { if ($xmlRoot->getName() == "embedded-document") { $class->isEmbeddedDocument = true; } else { if ($xmlRoot->getName() == "mapped-superclass") { $class->isMappedSuperclass = true; } else { throw MappingException::classIsNotAValidDocument($className); } } } // Evaluate <field ...> mappings if (isset($xmlRoot->field)) { foreach ($xmlRoot->field as $fieldMapping) { $class->mapField(array('fieldName' => (string) $fieldMapping['name'], 'jsonName' => isset($fieldMapping['json-name']) ? (string) $fieldMapping['json-name'] : null, 'indexed' => isset($fieldMapping['index']) ? (bool) $fieldMapping['index'] : false, 'type' => isset($fieldMapping['type']) ? (string) $fieldMapping['type'] : null, 'isVersionField' => isset($fieldMapping['version']) ? true : null)); } } // Evaluate <id ..> mappings foreach ($xmlRoot->id as $idElement) { $class->mapField(array('fieldName' => (string) $idElement['name'], 'indexed' => isset($idElement['index']) ? (bool) $idElement['index'] : false, 'type' => isset($idElement['type']) ? (string) $idElement['type'] : null, 'id' => true, 'strategy' => isset($idElement['strategy']) ? (string) $idElement['strategy'] : null)); } // Evaluate <many-to-one ..> mappings if (isset($xmlRoot->{"reference-one"})) { foreach ($xmlRoot->{"reference-one"} as $referenceOneElement) { $class->mapManyToOne(array('cascade' => isset($referenceManyElement->cascade) ? $this->getCascadeMode($referenceManyElement->cascade) : 0, 'targetDocument' => (string) $referenceOneElement['target-document'], 'fieldName' => (string) $referenceOneElement['field'], 'jsonName' => isset($referenceOneElement['json-name']) ? (string) $referenceOneElement['json-name'] : null)); } } // Evaluate <many-to-one ..> mappings if (isset($xmlRoot->{"reference-many"})) { foreach ($xmlRoot->{"reference-many"} as $referenceManyElement) { $class->mapManyToMany(array('cascade' => isset($referenceManyElement->cascade) ? $this->getCascadeMode($referenceManyElement->cascade) : 0, 'targetDocument' => (string) $referenceManyElement['target-document'], 'fieldName' => (string) $referenceManyElement['field'], 'jsonName' => isset($referenceManyElement['json-name']) ? (string) $referenceManyElement['json-name'] : null, 'mappedBy' => isset($referenceManyElement['mapped-by']) ? (string) $referenceManyElement['mapped-by'] : null)); } } // Evaluate <attachments ..> mapping if (isset($xmlRoot->{"attachments"})) { $class->mapAttachments((string) $xmlRoot->{"attachments"}[0]['field']); } // Evaluate <embed-one /> if (isset($xmlRoot->{'embed-one'})) { foreach ($xmlRoot->{'embed-one'} as $embedOneElement) { $class->mapEmbedded(array('targetDocument' => (string) $embedOneElement['target-document'], 'fieldName' => (string) $embedOneElement['field'], 'jsonName' => isset($embedOneElement['json-name']) ? (string) $embedOneElement['json-name'] : null, 'embedded' => 'one')); } } // Evaluate <embed-many /> if (isset($xmlRoot->{'embed-many'})) { foreach ($xmlRoot->{'embed-many'} as $embedManyElement) { $class->mapEmbedded(array('targetDocument' => (string) $embedManyElement['target-document'], 'fieldName' => (string) $embedManyElement['field'], 'jsonName' => isset($embedManyElement['json-name']) ? (string) $embedManyElement['json-name'] : null, 'embedded' => 'many')); } } }
/** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadata $class) { $element = $this->getElement($className); if ($element['type'] == 'document') { $class->setCustomRepositoryClass(isset($element['repositoryClass']) ? $element['repositoryClass'] : null); if (isset($element['indexed']) && $element['indexed'] == true) { $class->indexed = true; } } else { if ($element['type'] == 'embedded') { $class->isEmbeddedDocument = true; } else { if (strtolower($element['type']) == "mappedsuperclass") { $class->isMappedSuperclass = true; } else { throw MappingException::classIsNotAValidDocument($className); } } } if (isset($element['id'])) { foreach ($element['id'] as $fieldName => $idElement) { $class->mapField(array('fieldName' => $fieldName, 'indexed' => isset($idElement['indexed']) ? (bool) $idElement['indexed'] : false, 'type' => isset($idElement['type']) ? $idElement['type'] : null, 'id' => true, 'strategy' => isset($idElement['strategy']) ? $idElement['strategy'] : null)); } } if (isset($element['fields'])) { foreach ($element['fields'] as $fieldName => $fieldElement) { $class->mapField(array('fieldName' => $fieldName, 'jsonName' => isset($fieldElement['jsonName']) ? $fieldElement['jsonName'] : null, 'indexed' => isset($fieldElement['indexed']) ? (bool) $fieldElement['indexed'] : false, 'type' => isset($fieldElement['type']) ? $fieldElement['type'] : null, 'isVersionField' => isset($fieldElement['version']) ? true : null)); } } if (isset($element['referenceOne'])) { foreach ($element['referenceOne'] as $field => $referenceOneElement) { $class->mapManyToOne(array('cascade' => isset($referenceManyElement->cascade) ? $this->getCascadeMode($referenceManyElement->cascade) : 0, 'targetDocument' => (string) $referenceOneElement['targetDocument'], 'fieldName' => $field, 'jsonName' => isset($referenceOneElement['jsonName']) ? (string) $referenceOneElement['jsonName'] : null)); } } if (isset($element['referenceMany'])) { foreach ($element['referenceMany'] as $field => $referenceManyElement) { $class->mapManyToMany(array('cascade' => isset($referenceManyElement->cascade) ? $this->getCascadeMode($referenceManyElement->cascade) : 0, 'targetDocument' => (string) $referenceManyElement['targetDocument'], 'fieldName' => $field, 'jsonName' => isset($referenceManyElement['jsonName']) ? (string) $referenceManyElement['jsonName'] : null, 'mappedBy' => isset($referenceManyElement['mappedBy']) ? (string) $referenceManyElement['mappedBy'] : null)); } } if (isset($element['attachments'])) { $class->mapAttachments($element['attachments']); } if (isset($element['embedOne'])) { foreach ($element['embedOne'] as $field => $embedOneElement) { $class->mapEmbedded(array('targetDocument' => (string) $embedOneElement['targetDocument'], 'fieldName' => $field, 'jsonName' => isset($embedOneElement['jsonName']) ? (string) $embedOneElement['jsonName'] : null, 'embedded' => 'one')); } } if (isset($element['embedMany'])) { foreach ($element['embedMany'] as $field => $embedManyElement) { $class->mapEmbedded(array('targetDocument' => (string) $embedManyElement['targetDocument'], 'fieldName' => $field, 'jsonName' => isset($embedManyElement['jsonName']) ? (string) $embedManyElement['jsonName'] : null, 'embedded' => 'many')); } } }
/** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadata $class) { $reflClass = $class->getReflectionClass(); $classAnnotations = $this->reader->getClassAnnotations($reflClass); if (isset($classAnnotations['Doctrine\\ODM\\CouchDB\\Mapping\\Document'])) { $documentAnnot = $classAnnotations['Doctrine\\ODM\\CouchDB\\Mapping\\Document']; if ($documentAnnot->indexed) { $class->indexed = true; } $class->setCustomRepositoryClass($documentAnnot->repositoryClass); } elseif (isset($classAnnotations['Doctrine\\ODM\\CouchDB\\Mapping\\EmbeddedDocument'])) { $documentAnnot = $classAnnotations['Doctrine\\ODM\\CouchDB\\Mapping\\EmbeddedDocument']; $class->isEmbeddedDocument = true; } else { if (isset($classAnnotations['Doctrine\\ODM\\CouchDB\\Mapping\\MappedSuperclass'])) { $class->isMappedSuperclass = true; } else { throw MappingException::classIsNotAValidDocument($className); } } foreach ($reflClass->getProperties() as $property) { $mapping = array(); $mapping['fieldName'] = $property->getName(); foreach ($this->reader->getPropertyAnnotations($property) as $fieldAnnot) { if ($fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\Field) { if ($fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\Version) { $mapping['isVersionField'] = true; } $mapping = array_merge($mapping, (array) $fieldAnnot); unset($mapping['value']); $class->mapField($mapping); } else { if ($fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\ReferenceOne) { $cascade = 0; foreach ($fieldAnnot->cascade as $cascadeMode) { $cascade += constant('Doctrine\\ODM\\CouchDB\\Mapping\\ClassMetadata::CASCADE_' . strtoupper($cascadeMode)); } $fieldAnnot->cascade = $cascade; $mapping = array_merge($mapping, (array) $fieldAnnot); unset($mapping['value']); $class->mapManyToOne($mapping); } else { if ($fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\ReferenceMany) { $cascade = 0; foreach ($fieldAnnot->cascade as $cascadeMode) { $cascade += constant('Doctrine\\ODM\\CouchDB\\Mapping\\ClassMetadata::CASCADE_' . strtoupper($cascadeMode)); } $fieldAnnot->cascade = $cascade; $mapping = array_merge($mapping, (array) $fieldAnnot); unset($mapping['value']); $class->mapManyToMany($mapping); } else { if ($fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\Attachments) { $class->mapAttachments($mapping['fieldName']); } else { if ($fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\EmbedOne || $fieldAnnot instanceof \Doctrine\ODM\CouchDB\Mapping\EmbedMany) { $mapping = array_merge($mapping, (array) $fieldAnnot); unset($mapping['value']); $class->mapEmbedded($mapping); } } } } } } } }
/** * @param ClassMetadata $class * @param object $document * @return void */ public function computeChangeSet(ClassMetadata $class, $document) { if ($document instanceof Proxy\Proxy && !$document->__isInitialized__) { return; } $oid = \spl_object_hash($document); $actualData = array(); $embeddedActualData = array(); // 1. compute the actual values of the current document foreach ($class->reflFields as $fieldName => $reflProperty) { $value = $reflProperty->getValue($document); if ($class->isCollectionValuedAssociation($fieldName) && $value !== null && !$value instanceof PersistentCollection) { if (!$value instanceof Collection) { $value = new ArrayCollection($value); } if ($class->associationsMappings[$fieldName]['isOwning']) { $coll = new PersistentIdsCollection($value, $class->associationsMappings[$fieldName]['targetDocument'], $this->dm, array()); } else { $coll = new PersistentViewCollection($value, $this->dm, $this->documentIdentifiers[$oid], $class->associationsMappings[$fieldName]); } $class->reflFields[$fieldName]->setValue($document, $coll); $actualData[$fieldName] = $coll; } else { $actualData[$fieldName] = $value; if (isset($class->fieldMappings[$fieldName]['embedded']) && $value !== null) { // serializing embedded value right here, to be able to detect changes for later invocations $embeddedActualData[$fieldName] = $this->embeddedSerializer->serializeEmbeddedDocument($value, $class->fieldMappings[$fieldName]); } } // TODO: ORM transforms arrays and collections into persistent collections } // unset the revision field if necessary, it is not to be managed by the user in write scenarios. if ($class->isVersioned) { unset($actualData[$class->versionField]); } // 2. Compare to the original, or find out that this document is new. if (!isset($this->originalData[$oid])) { // document is New and should be inserted $this->originalData[$oid] = $actualData; $this->scheduledUpdates[$oid] = $document; $this->originalEmbeddedData[$oid] = $embeddedActualData; } else { // document is "fully" MANAGED: it was already fully persisted before // and we have a copy of the original data $changed = false; foreach ($actualData as $fieldName => $fieldValue) { // Important to not check embeded values here, because those are objects, equality check isn't enough // if (isset($class->fieldMappings[$fieldName]) && !isset($class->fieldMappings[$fieldName]['embedded']) && $this->originalData[$oid][$fieldName] !== $fieldValue) { $changed = true; break; } else { if (isset($class->associationsMappings[$fieldName])) { if (!$class->associationsMappings[$fieldName]['isOwning']) { continue; } if ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_ONE && $this->originalData[$oid][$fieldName] !== $fieldValue) { $changed = true; break; } else { if ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_MANY) { if (!$fieldValue instanceof PersistentCollection) { // if its not a persistent collection and the original value changed. otherwise it could just be null $changed = true; break; } else { if ($fieldValue->changed()) { $this->visitedCollections[] = $fieldValue; $changed = true; break; } } } } } else { if ($class->hasAttachments && $fieldName == $class->attachmentField) { // array of value objects, can compare that stricly if ($this->originalData[$oid][$fieldName] !== $fieldValue) { $changed = true; break; } } } } } // Check embedded documents here, only if there is no change yet if (!$changed) { foreach ($embeddedActualData as $fieldName => $fieldValue) { if (!isset($this->originalEmbeddedData[$oid][$fieldName]) || $this->embeddedSerializer->isChanged($actualData[$fieldName], $this->originalEmbeddedData[$oid][$fieldName], $class->fieldMappings[$fieldName])) { $changed = true; break; } } } if ($changed) { $this->originalData[$oid] = $actualData; $this->scheduledUpdates[$oid] = $document; $this->originalEmbeddedData[$oid] = $embeddedActualData; } } // 3. check if any cascading needs to happen foreach ($class->associationsMappings as $name => $assoc) { if ($this->originalData[$oid][$name]) { $this->computeAssociationChanges($assoc, $this->originalData[$oid][$name]); } } }
public function testDeriveChildMetadata() { $cm = new ClassMetadata("Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Person"); $cm->mapField(array('fieldName' => 'id', 'id' => true)); $cm->mapField(array('fieldName' => 'username', 'type' => 'string')); $cm->mapAttachments('attachments'); $cm->mapManyToOne(array('targetDocument' => 'Address', 'fieldName' => 'address')); $child = new ClassMetadata('Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Employee'); $cm->deriveChildMetadata($child); $child->mapField(array('fieldName' => 'status', 'type' => 'string')); $this->assertFalse(isset($child->fieldMappings['status']['declared'])); $this->assertEquals("Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Employee", $child->name); $this->assertTrue(isset($child->fieldMappings['id']), "id field has to be on child metadata"); $this->assertEquals("Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Person", $child->fieldMappings['id']['declared']); $this->assertTrue(isset($child->fieldMappings['username']), "Username field has to be on child metadata"); $this->assertEquals("Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Person", $child->fieldMappings['username']['declared']); $this->assertTrue(isset($child->associationsMappings['address']), "address association has to be on child metadata"); $this->assertEquals("Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Person", $child->associationsMappings['address']['declared']); $this->assertEquals("attachments", $child->attachmentField); $this->assertEquals("Doctrine\\Tests\\ODM\\CouchDB\\Mapping\\Person", $child->attachmentDeclaredClass); return $child; }