Exemple #1
0
 /**
  * Setter for pageUrl
  *
  * @param string $pageUrl
  */
 public function setPageUrl($pageUrl)
 {
     if ($pageUrl && $this->pageUrl != $pageUrl) {
         $this->eventManager->dispatchEvent(['page_changed'], [sprintf('Page changed from url %s to url %s', $this->pageUrl, $pageUrl)]);
         $this->pageUrl = $pageUrl;
     }
 }
Exemple #2
0
 /**
  * INTERNAL:
  * Creates an entity. Used for reconstitution of persistent entities.
  *
  * @ignore
  * @param string $className The name of the entity class.
  * @param array $data The data for the entity.
  * @param array $hints Any hints to account for during reconstitution/lookup of the entity.
  * @return object The managed entity instance.
  * @internal Highly performance-sensitive method.
  * 
  * @todo Rename: getOrCreateEntity
  */
 public function createEntity($className, array $data, &$hints = array())
 {
     $class = $this->em->getClassMetadata($className);
     //$isReadOnly = isset($hints[Query::HINT_READ_ONLY]);
     if ($class->isIdentifierComposite) {
         $id = array();
         foreach ($class->identifier as $fieldName) {
             $id[$fieldName] = $data[$fieldName];
         }
         $idHash = implode(' ', $id);
     } else {
         $idHash = $data[$class->identifier[0]];
         $id = array($class->identifier[0] => $idHash);
     }
     if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
         $entity = $this->identityMap[$class->rootEntityName][$idHash];
         $oid = spl_object_hash($entity);
         if ($entity instanceof Proxy && !$entity->__isInitialized__) {
             $entity->__isInitialized__ = true;
             $overrideLocalValues = true;
             $this->originalEntityData[$oid] = $data;
             if ($entity instanceof NotifyPropertyChanged) {
                 $entity->addPropertyChangedListener($this);
             }
         } else {
             $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
         }
     } else {
         $entity = $class->newInstance();
         $oid = spl_object_hash($entity);
         $this->entityIdentifiers[$oid] = $id;
         $this->entityStates[$oid] = self::STATE_MANAGED;
         $this->originalEntityData[$oid] = $data;
         $this->identityMap[$class->rootEntityName][$idHash] = $entity;
         if ($entity instanceof NotifyPropertyChanged) {
             $entity->addPropertyChangedListener($this);
         }
         $overrideLocalValues = true;
     }
     if ($overrideLocalValues) {
         foreach ($data as $field => $value) {
             if (isset($class->fieldMappings[$field])) {
                 $class->reflFields[$field]->setValue($entity, $value);
             }
         }
         // Properly initialize any unfetched associations, if partial objects are not allowed.
         if (!isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
             foreach ($class->associationMappings as $field => $assoc) {
                 // Check if the association is not among the fetch-joined associations already.
                 if (isset($hints['fetched'][$className][$field])) {
                     continue;
                 }
                 $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
                 if ($assoc['type'] & ClassMetadata::TO_ONE) {
                     if ($assoc['isOwningSide']) {
                         $associatedId = array();
                         foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
                             $joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null;
                             if ($joinColumnValue !== null) {
                                 $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
                             }
                         }
                         if (!$associatedId) {
                             // Foreign key is NULL
                             $class->reflFields[$field]->setValue($entity, null);
                             $this->originalEntityData[$oid][$field] = null;
                         } else {
                             // Foreign key is set
                             // Check identity map first
                             // FIXME: Can break easily with composite keys if join column values are in
                             //        wrong order. The correct order is the one in ClassMetadata#identifier.
                             $relatedIdHash = implode(' ', $associatedId);
                             if (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])) {
                                 $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash];
                             } else {
                                 if ($targetClass->subClasses) {
                                     // If it might be a subtype, it can not be lazy
                                     $newValue = $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, null, $associatedId);
                                 } else {
                                     if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) {
                                         // TODO: Maybe it could be optimized to do an eager fetch with a JOIN inside
                                         // the persister instead of this rather unperformant approach.
                                         $newValue = $this->em->find($assoc['targetEntity'], $associatedId);
                                     } else {
                                         $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId);
                                     }
                                     // PERF: Inlined & optimized code from UnitOfWork#registerManaged()
                                     $newValueOid = spl_object_hash($newValue);
                                     $this->entityIdentifiers[$newValueOid] = $associatedId;
                                     $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue;
                                     $this->entityStates[$newValueOid] = self::STATE_MANAGED;
                                     // make sure that when an proxy is then finally loaded, $this->originalEntityData is set also!
                                 }
                             }
                             $this->originalEntityData[$oid][$field] = $newValue;
                             $class->reflFields[$field]->setValue($entity, $newValue);
                         }
                     } else {
                         // Inverse side of x-to-one can never be lazy
                         $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, null));
                     }
                 } else {
                     // Inject collection
                     $pColl = new PersistentCollection($this->em, $targetClass, new ArrayCollection());
                     $pColl->setOwner($entity, $assoc);
                     $reflField = $class->reflFields[$field];
                     $reflField->setValue($entity, $pColl);
                     if ($assoc['fetch'] == ClassMetadata::FETCH_LAZY) {
                         $pColl->setInitialized(false);
                     } else {
                         $this->loadCollection($pColl);
                         $pColl->takeSnapshot();
                     }
                     $this->originalEntityData[$oid][$field] = $pColl;
                 }
             }
         }
     }
     //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
     if (isset($class->lifecycleCallbacks[Events::postLoad])) {
         $class->invokeLifecycleCallbacks(Events::postLoad, $entity);
     }
     if ($this->evm->hasListeners(Events::postLoad)) {
         $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em));
     }
     return $entity;
 }
 /**
  * INTERNAL:
  * Creates an entity. Used for reconstitution of persistent entities.
  *
  * @ignore
  * @param string $className The name of the entity class.
  * @param array $data The data for the entity.
  * @param array $hints Any hints to account for during reconstitution/lookup of the entity.
  * @return object The managed entity instance.
  * @internal Highly performance-sensitive method.
  *
  * @todo Rename: getOrCreateEntity
  */
 public function createEntity($className, array $data, &$hints = array())
 {
     $class = $this->em->getClassMetadata($className);
     //$isReadOnly = isset($hints[Query::HINT_READ_ONLY]);
     if ($class->isIdentifierComposite) {
         $id = array();
         foreach ($class->identifier as $fieldName) {
             if (isset($class->associationMappings[$fieldName])) {
                 $id[$fieldName] = $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']];
             } else {
                 $id[$fieldName] = $data[$fieldName];
             }
         }
         $idHash = implode(' ', $id);
     } else {
         if (isset($class->associationMappings[$class->identifier[0]])) {
             $idHash = $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']];
         } else {
             $idHash = $data[$class->identifier[0]];
         }
         $id = array($class->identifier[0] => $idHash);
     }
     if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
         $entity = $this->identityMap[$class->rootEntityName][$idHash];
         $oid = spl_object_hash($entity);
         if ($entity instanceof Proxy && !$entity->__isInitialized__) {
             $entity->__isInitialized__ = true;
             $overrideLocalValues = true;
             if ($entity instanceof NotifyPropertyChanged) {
                 $entity->addPropertyChangedListener($this);
             }
         } else {
             $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
             // If only a specific entity is set to refresh, check that it's the one
             if (isset($hints[Query::HINT_REFRESH_ENTITY])) {
                 $overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity;
             }
         }
         if ($overrideLocalValues) {
             $this->originalEntityData[$oid] = $data;
         }
     } else {
         $entity = $class->newInstance();
         $oid = spl_object_hash($entity);
         $this->entityIdentifiers[$oid] = $id;
         $this->entityStates[$oid] = self::STATE_MANAGED;
         $this->originalEntityData[$oid] = $data;
         $this->identityMap[$class->rootEntityName][$idHash] = $entity;
         if ($entity instanceof NotifyPropertyChanged) {
             $entity->addPropertyChangedListener($this);
         }
         $overrideLocalValues = true;
     }
     if ($overrideLocalValues) {
         foreach ($data as $field => $value) {
             if (isset($class->fieldMappings[$field])) {
                 $class->reflFields[$field]->setValue($entity, $value);
             }
         }
         // Loading the entity right here, if its in the eager loading map get rid of it there.
         unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]);
         // Properly initialize any unfetched associations, if partial objects are not allowed.
         if (!isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
             foreach ($class->associationMappings as $field => $assoc) {
                 // Check if the association is not among the fetch-joined associations already.
                 if (isset($hints['fetchAlias']) && isset($hints['fetched'][$hints['fetchAlias']][$field])) {
                     continue;
                 }
                 $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
                 if ($assoc['type'] & ClassMetadata::TO_ONE) {
                     if ($assoc['isOwningSide']) {
                         $associatedId = array();
                         // TODO: Is this even computed right in all cases of composite keys?
                         foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
                             $joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null;
                             if ($joinColumnValue !== null) {
                                 if ($targetClass->containsForeignIdentifier) {
                                     $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue;
                                 } else {
                                     $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
                                 }
                             }
                         }
                         if (!$associatedId) {
                             // Foreign key is NULL
                             $class->reflFields[$field]->setValue($entity, null);
                             $this->originalEntityData[$oid][$field] = null;
                         } else {
                             if (!isset($hints['fetchMode'][$class->name][$field])) {
                                 $hints['fetchMode'][$class->name][$field] = $assoc['fetch'];
                             }
                             // Foreign key is set
                             // Check identity map first
                             // FIXME: Can break easily with composite keys if join column values are in
                             //        wrong order. The correct order is the one in ClassMetadata#identifier.
                             $relatedIdHash = implode(' ', $associatedId);
                             if (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])) {
                                 $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash];
                                 // if this is an uninitialized proxy, we are deferring eager loads,
                                 // this association is marked as eager fetch, and its an uninitialized proxy (wtf!)
                                 // then we cann append this entity for eager loading!
                                 if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER && isset($hints['deferEagerLoad']) && !$targetClass->isIdentifierComposite && $newValue instanceof Proxy && $newValue->__isInitialized__ === false) {
                                     $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId);
                                 }
                             } else {
                                 if ($targetClass->subClasses) {
                                     // If it might be a subtype, it can not be lazy. There isn't even
                                     // a way to solve this with deferred eager loading, which means putting
                                     // an entity with subclasses at a *-to-one location is really bad! (performance-wise)
                                     $newValue = $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, $associatedId);
                                 } else {
                                     // Deferred eager load only works for single identifier classes
                                     if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER) {
                                         if (isset($hints['deferEagerLoad']) && !$targetClass->isIdentifierComposite) {
                                             // TODO: Is there a faster approach?
                                             $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId);
                                             $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId);
                                         } else {
                                             // TODO: This is very imperformant, ignore it?
                                             $newValue = $this->em->find($assoc['targetEntity'], $associatedId);
                                         }
                                     } else {
                                         $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId);
                                     }
                                     // PERF: Inlined & optimized code from UnitOfWork#registerManaged()
                                     $newValueOid = spl_object_hash($newValue);
                                     $this->entityIdentifiers[$newValueOid] = $associatedId;
                                     $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue;
                                     $this->entityStates[$newValueOid] = self::STATE_MANAGED;
                                     // make sure that when an proxy is then finally loaded, $this->originalEntityData is set also!
                                 }
                             }
                             $this->originalEntityData[$oid][$field] = $newValue;
                             $class->reflFields[$field]->setValue($entity, $newValue);
                             if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) {
                                 $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']];
                                 $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($newValue, $entity);
                             }
                         }
                     } else {
                         // Inverse side of x-to-one can never be lazy
                         $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity));
                     }
                 } else {
                     // Inject collection
                     $pColl = new PersistentCollection($this->em, $targetClass, new ArrayCollection());
                     $pColl->setOwner($entity, $assoc);
                     $reflField = $class->reflFields[$field];
                     $reflField->setValue($entity, $pColl);
                     if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) {
                         $this->loadCollection($pColl);
                         $pColl->takeSnapshot();
                     } else {
                         $pColl->setInitialized(false);
                     }
                     $this->originalEntityData[$oid][$field] = $pColl;
                 }
             }
         }
     }
     //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
     if (isset($class->lifecycleCallbacks[Events::postLoad])) {
         $class->invokeLifecycleCallbacks(Events::postLoad, $entity);
     }
     if ($this->evm->hasListeners(Events::postLoad)) {
         $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em));
     }
     return $entity;
 }
Exemple #4
0
 /**
  * Flush Operation - Write all dirty entries to the CouchDB.
  *
  * @return void
  */
 public function flush()
 {
     $this->detectChangedDocuments();
     if ($this->evm->hasListeners(Event::onFlush)) {
         $this->evm->dispatchEvent(Event::onFlush, new Event\OnFlushEventArgs($this));
     }
     $config = $this->dm->getConfiguration();
     $bulkUpdater = $this->dm->getCouchDBClient()->createBulkUpdater();
     $bulkUpdater->setAllOrNothing($config->getAllOrNothingFlush());
     foreach ($this->scheduledRemovals as $oid => $document) {
         $bulkUpdater->deleteDocument($this->documentIdentifiers[$oid], $this->documentRevisions[$oid]);
         $this->removeFromIdentityMap($document);
         if ($this->evm->hasListeners(Event::postRemove)) {
             $this->evm->dispatchEvent(Event::postRemove, new Event\LifecycleEventArgs($document, $this->dm));
         }
     }
     foreach ($this->scheduledUpdates as $oid => $document) {
         $class = $this->dm->getClassMetadata(get_class($document));
         if ($this->evm->hasListeners(Event::preUpdate)) {
             $this->evm->dispatchEvent(Event::preUpdate, new Event\LifecycleEventArgs($document, $this->dm));
             $this->computeChangeSet($class, $document);
             // TODO: prevent association computations in this case?
         }
         $data = $this->metadataResolver->createDefaultDocumentStruct($class);
         // Convert field values to json values.
         foreach ($this->originalData[$oid] as $fieldName => $fieldValue) {
             if (isset($class->fieldMappings[$fieldName])) {
                 if ($fieldValue !== null && isset($class->fieldMappings[$fieldName]['embedded'])) {
                     // As we store the serialized value in originalEmbeddedData, we can simply copy here.
                     $fieldValue = $this->originalEmbeddedData[$oid][$class->fieldMappings[$fieldName]['jsonName']];
                 } else {
                     if ($fieldValue !== null) {
                         $fieldValue = Type::getType($class->fieldMappings[$fieldName]['type'])->convertToCouchDBValue($fieldValue);
                     }
                 }
                 $data[$class->fieldMappings[$fieldName]['jsonName']] = $fieldValue;
             } else {
                 if (isset($class->associationsMappings[$fieldName])) {
                     if ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_ONE) {
                         if (\is_object($fieldValue)) {
                             $fieldValue = $this->getDocumentIdentifier($fieldValue);
                         } else {
                             $fieldValue = null;
                         }
                         $data = $this->metadataResolver->storeAssociationField($data, $class, $this->dm, $fieldName, $fieldValue);
                     } else {
                         if ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_MANY) {
                             if ($class->associationsMappings[$fieldName]['isOwning']) {
                                 // TODO: Optimize when not initialized yet! In ManyToMany case we can keep track of ALL ids
                                 $ids = array();
                                 if (is_array($fieldValue) || $fieldValue instanceof \Doctrine\Common\Collections\Collection) {
                                     foreach ($fieldValue as $key => $relatedObject) {
                                         $ids[$key] = $this->getDocumentIdentifier($relatedObject);
                                     }
                                 }
                                 $data = $this->metadataResolver->storeAssociationField($data, $class, $this->dm, $fieldName, $ids);
                             }
                         }
                     }
                 } else {
                     if ($class->hasAttachments && $fieldName == $class->attachmentField) {
                         if (is_array($fieldValue) && $fieldValue) {
                             $data['_attachments'] = array();
                             foreach ($fieldValue as $filename => $attachment) {
                                 if (!$attachment instanceof \Doctrine\CouchDB\Attachment) {
                                     throw CouchDBException::invalidAttachment($class->name, $this->documentIdentifiers[$oid], $filename);
                                 }
                                 $data['_attachments'][$filename] = $attachment->toArray();
                             }
                         }
                     }
                 }
             }
         }
         // respect the non mapped data, otherwise they will be deleted.
         if (isset($this->nonMappedData[$oid]) && $this->nonMappedData[$oid]) {
             $data = array_merge($data, $this->nonMappedData[$oid]);
         }
         $rev = $this->getDocumentRevision($document);
         if ($rev) {
             $data['_rev'] = $rev;
         }
         $bulkUpdater->updateDocument($data);
     }
     $response = $bulkUpdater->execute();
     $updateConflictDocuments = array();
     if ($response->status == 201) {
         foreach ($response->body as $docResponse) {
             if (!isset($this->identityMap[$docResponse['id']])) {
                 // deletions
                 continue;
             }
             $document = $this->identityMap[$docResponse['id']];
             if (isset($docResponse['error'])) {
                 $updateConflictDocuments[] = $document;
             } else {
                 $this->documentRevisions[spl_object_hash($document)] = $docResponse['rev'];
                 $class = $this->dm->getClassMetadata(get_class($document));
                 if ($class->isVersioned) {
                     $class->reflFields[$class->versionField]->setValue($document, $docResponse['rev']);
                 }
             }
             if ($this->evm->hasListeners(Event::postUpdate)) {
                 $this->evm->dispatchEvent(Event::postUpdate, new Event\LifecycleEventArgs($document, $this->dm));
             }
         }
     } else {
         if ($response->status >= 400) {
             throw HTTPException::fromResponse($bulkUpdater->getPath(), $response);
         }
     }
     foreach ($this->visitedCollections as $col) {
         $col->takeSnapshot();
     }
     $this->scheduledUpdates = $this->scheduledRemovals = $this->visitedCollections = array();
     if (count($updateConflictDocuments)) {
         throw new UpdateConflictException($updateConflictDocuments);
     }
 }
 /**
  * INTERNAL:
  * Creates an document. Used for reconstitution of documents during hydration.
  *
  * @ignore
  * @param string $className The name of the document class.
  * @param array $data The data for the document.
  * @param array $hints Any hints to account for during reconstitution/lookup of the document.
  * @return object The document instance.
  * @internal Highly performance-sensitive method.
  */
 public function getOrCreateDocument($className, array $data, &$hints = array())
 {
     $class = $this->_dm->getClassMetadata($className);
     $id = (string) $data['_id'];
     if (isset($this->_identityMap[$class->rootDocumentName][$id])) {
         $document = $this->_identityMap[$class->rootDocumentName][$id];
         $oid = spl_object_hash($document);
         if ($document instanceof Proxy && !$document->__isInitialized__) {
             $document->__isInitialized__ = true;
             $overrideLocalValues = true;
         } else {
             $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
         }
     } else {
         $document = $class->newInstance();
         $oid = spl_object_hash($document);
         $this->_documentIdentifiers[$oid] = $id;
         $this->_documentStates[$oid] = self::STATE_MANAGED;
         $this->_originalDocumentData[$oid] = $data;
         $this->_identityMap[$class->rootDocumentName][$id] = $document;
         $overrideLocalValues = true;
     }
     if ($overrideLocalValues) {
         $this->_hydrator->hydrate($class, $document, $data);
     }
     if (isset($class->lifecycleCallbacks[Events::postLoad])) {
         $class->invokeLifecycleCallbacks(Events::postLoad, $document);
     }
     if ($this->_evm->hasListeners(Events::postLoad)) {
         $this->_evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($document, $this->_dm));
     }
     return $document;
 }
Exemple #6
0
 /**
  * Clears the UnitOfWork.
  *
  * @param string $entityName if given, only entities of this type will get detached
  */
 public function clear($entityName = null)
 {
     if ($entityName === null) {
         $this->identityMap = $this->entityIdentifiers = $this->originalEntityData = $this->entityChangeSets = $this->entityStates = $this->scheduledForDirtyCheck = $this->entityInsertions = $this->entityUpdates = $this->entityDeletions = $this->collectionDeletions = $this->collectionUpdates = $this->extraUpdates = $this->orphanRemovals = array();
         if ($this->commitOrderCalculator !== null) {
             $this->commitOrderCalculator->clear();
         }
     } else {
         $visited = array();
         foreach ($this->identityMap as $className => $entities) {
             if ($className === $entityName) {
                 foreach ($entities as $entity) {
                     $this->doDetach($entity, $visited, true);
                 }
             }
         }
     }
     if ($this->evm->hasListeners(Events::onClear)) {
         $this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em, $entityName));
     }
 }
Exemple #7
0
 /**
  * @param \Doctrine\OXM\Mapping\ClassMetadata $class
  * @param  $xmlEntity
  * @return void
  */
 private function persistNew($class, $xmlEntity)
 {
     $oid = spl_object_hash($xmlEntity);
     if (isset($class->lifecycleCallbacks[Events::prePersist])) {
         $class->invokeLifecycleCallbacks(Events::prePersist, $xmlEntity);
     }
     if ($this->evm->hasListeners(Events::prePersist)) {
         $this->evm->dispatchEvent(Events::prePersist, new Event\LifecycleEventArgs($xmlEntity, $this->xem));
     }
     $idGen = $class->idGenerator;
     if (!$idGen->isPostInsertGenerator()) {
         $idValue = $idGen->generate($this->xem, $xmlEntity);
         if (!$idGen instanceof \Doctrine\OXM\Id\AssignedGenerator) {
             $this->entityIdentifiers[$oid] = array($class->identifier => $idValue);
             $class->setIdentifierValue($xmlEntity, $this->entityIdentifiers[$oid]);
         } else {
             $this->entityIdentifiers[$oid] = $idValue;
         }
     }
     $this->entityStates[$oid] = self::STATE_MANAGED;
     $this->scheduleForInsert($xmlEntity);
 }
Exemple #8
0
 /**
  * INTERNAL:
  * Creates an entity. Used for reconstitution of entities during hydration.
  *
  * @ignore
  * @param string $className The name of the entity class.
  * @param array $data The data for the entity.
  * @param array $hints Any hints to account for during reconstitution/lookup of the entity.
  * @return object The entity instance.
  * @internal Highly performance-sensitive method.
  * 
  * @todo Rename: getOrCreateEntity
  */
 public function createEntity($className, array $data, &$hints = array())
 {
     $class = $this->_em->getClassMetadata($className);
     //$isReadOnly = isset($hints[Query::HINT_READ_ONLY]);
     if ($class->isIdentifierComposite) {
         $id = array();
         foreach ($class->identifier as $fieldName) {
             $id[$fieldName] = $data[$fieldName];
         }
         $idHash = implode(' ', $id);
     } else {
         $idHash = $data[$class->identifier[0]];
         $id = array($class->identifier[0] => $idHash);
     }
     if (isset($this->_identityMap[$class->rootEntityName][$idHash])) {
         $entity = $this->_identityMap[$class->rootEntityName][$idHash];
         $oid = spl_object_hash($entity);
         if ($entity instanceof Proxy && !$entity->__isInitialized__) {
             $entity->__isInitialized__ = true;
             $overrideLocalValues = true;
         } else {
             $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
         }
     } else {
         $entity = $class->newInstance();
         $oid = spl_object_hash($entity);
         $this->_entityIdentifiers[$oid] = $id;
         $this->_entityStates[$oid] = self::STATE_MANAGED;
         $this->_originalEntityData[$oid] = $data;
         $this->_identityMap[$class->rootEntityName][$idHash] = $entity;
         if ($entity instanceof NotifyPropertyChanged) {
             $entity->addPropertyChangedListener($this);
         }
         $overrideLocalValues = true;
     }
     if ($overrideLocalValues) {
         if ($this->_useCExtension) {
             doctrine_populate_data($entity, $data);
         } else {
             foreach ($data as $field => $value) {
                 if (isset($class->reflFields[$field])) {
                     $class->reflFields[$field]->setValue($entity, $value);
                 }
             }
         }
         // Properly initialize any unfetched associations, if partial objects are not allowed.
         if (!isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
             foreach ($class->associationMappings as $field => $assoc) {
                 // Check if the association is not among the fetch-joined associations already.
                 if (isset($hints['fetched'][$className][$field])) {
                     continue;
                 }
                 $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
                 if ($assoc->isOneToOne()) {
                     if ($assoc->isOwningSide) {
                         $associatedId = array();
                         foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $srcColumn) {
                             $joinColumnValue = $data[$srcColumn];
                             if ($joinColumnValue !== null) {
                                 $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
                             }
                         }
                         if (!$associatedId) {
                             // Foreign key is NULL
                             $class->reflFields[$field]->setValue($entity, null);
                             $this->_originalEntityData[$oid][$field] = null;
                         } else {
                             // Foreign key is set
                             // Check identity map first
                             // FIXME: Can break easily with composite keys if join column values are in
                             //        wrong order. The correct order is the one in ClassMetadata#identifier.
                             $relatedIdHash = implode(' ', $associatedId);
                             if (isset($this->_identityMap[$targetClass->rootEntityName][$relatedIdHash])) {
                                 $newValue = $this->_identityMap[$targetClass->rootEntityName][$relatedIdHash];
                             } else {
                                 if ($targetClass->subClasses) {
                                     // If it might be a subtype, it can not be lazy
                                     $newValue = $assoc->load($entity, null, $this->_em, $associatedId);
                                 } else {
                                     $newValue = $this->_em->getProxyFactory()->getProxy($assoc->targetEntityName, $associatedId);
                                     $this->_entityIdentifiers[spl_object_hash($newValue)] = $associatedId;
                                     $this->_identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue;
                                 }
                             }
                             $this->_originalEntityData[$oid][$field] = $newValue;
                             $class->reflFields[$field]->setValue($entity, $newValue);
                         }
                     } else {
                         // Inverse side of x-to-one can never be lazy
                         $class->reflFields[$field]->setValue($entity, $assoc->load($entity, null, $this->_em));
                     }
                 } else {
                     // Inject collection
                     $reflField = $class->reflFields[$field];
                     $pColl = new PersistentCollection($this->_em, $targetClass, $reflField->getValue($entity) ?: new ArrayCollection());
                     $pColl->setOwner($entity, $assoc);
                     $reflField->setValue($entity, $pColl);
                     if ($assoc->isLazilyFetched()) {
                         $pColl->setInitialized(false);
                     } else {
                         $assoc->load($entity, $pColl, $this->_em);
                     }
                     $this->_originalEntityData[$oid][$field] = $pColl;
                 }
             }
         }
     }
     //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
     if (isset($class->lifecycleCallbacks[Events::postLoad])) {
         $class->invokeLifecycleCallbacks(Events::postLoad, $entity);
     }
     if ($this->_evm->hasListeners(Events::postLoad)) {
         $this->_evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity));
     }
     return $entity;
 }
Exemple #9
0
 /**
  * INTERNAL:
  * Creates an document. Used for reconstitution of documents during hydration.
  *
  * @ignore
  * @param string $className The name of the document class.
  * @param array $data The data for the document.
  * @param array $hints Any hints to account for during reconstitution/lookup of the document.
  * @return object The document instance.
  * @internal Highly performance-sensitive method.
  */
 public function getOrCreateDocument($className, $data, &$hints = array())
 {
     $class = $this->dm->getClassMetadata($className);
     if ($data instanceof \MongoGridFSFile) {
         $file = $data;
         $data = $file->file;
         $data[$class->file] = $file;
     }
     if ($class->hasDiscriminator()) {
         if (isset($data[$class->discriminatorField['name']])) {
             $type = $data[$class->discriminatorField['name']];
             $class = $this->dm->getClassMetadata($class->discriminatorMap[$data[$class->discriminatorField['name']]]);
             unset($data[$class->discriminatorField['name']]);
         }
     }
     $id = $class->getPHPIdentifierValue($data['_id']);
     if (isset($this->identityMap[$class->rootDocumentName][$id])) {
         $document = $this->identityMap[$class->rootDocumentName][$id];
     } else {
         $document = $class->newInstance();
     }
     if (isset($class->lifecycleCallbacks[ODMEvents::preLoad])) {
         $args = array(&$data);
         $class->invokeLifecycleCallbacks(ODMEvents::preLoad, $document, $args);
     }
     if ($this->evm->hasListeners(ODMEvents::preLoad)) {
         $this->evm->dispatchEvent(ODMEvents::preLoad, new PreLoadEventArgs($document, $this->dm, $data));
     }
     if (isset($this->identityMap[$class->rootDocumentName][$id])) {
         $oid = spl_object_hash($document);
         if ($document instanceof Proxy && !$document->__isInitialized__) {
             $document->__isInitialized__ = true;
             $overrideLocalValues = true;
             if ($document instanceof NotifyPropertyChanged) {
                 $document->addPropertyChangedListener($this);
             }
         } else {
             $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
         }
         if ($overrideLocalValues) {
             $this->hydrator->hydrate($document, $data);
             $this->originalDocumentData[$oid] = $data;
         }
     } else {
         $this->hydrator->hydrate($document, $data);
         $this->registerManaged($document, $id, $data);
     }
     if (isset($class->lifecycleCallbacks[ODMEvents::postLoad])) {
         $class->invokeLifecycleCallbacks(ODMEvents::postLoad, $document);
     }
     if ($this->evm->hasListeners(ODMEvents::postLoad)) {
         $this->evm->dispatchEvent(ODMEvents::postLoad, new LifecycleEventArgs($document, $this->dm));
     }
     return $document;
 }
Exemple #10
0
 /**
  * Clears the UnitOfWork.
  */
 public function clear()
 {
     $this->identityMap = $this->documentIds = $this->documentState = $this->documentTranslations = $this->documentLocales = $this->nonMappedData = $this->originalData = $this->documentChangesets = $this->scheduledUpdates = $this->scheduledAssociationUpdates = $this->scheduledInserts = $this->scheduledMoves = $this->scheduledRemovals = $this->visitedCollections = $this->documentHistory = $this->documentVersion = array();
     if ($this->evm->hasListeners(Event::onClear)) {
         $this->evm->dispatchEvent(Event::onClear, new OnClearEventArgs($this->dm));
     }
     return $this->session->refresh(false);
 }