more tests and first basic update/delete
This commit is contained in:
parent
b6e385d243
commit
73ad0ac454
@ -443,9 +443,9 @@ class Doctrine_ORM_EntityManager
|
|||||||
/**
|
/**
|
||||||
* Deletes the persistent state of the given entity.
|
* Deletes the persistent state of the given entity.
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\Entity $entity
|
* @param object $entity
|
||||||
*/
|
*/
|
||||||
public function delete(Doctrine_ORM_Entity $entity)
|
public function delete($entity)
|
||||||
{
|
{
|
||||||
$this->_errorIfNotActiveOrClosed();
|
$this->_errorIfNotActiveOrClosed();
|
||||||
$this->_unitOfWork->delete($entity);
|
$this->_unitOfWork->delete($entity);
|
||||||
|
@ -80,6 +80,23 @@ class Doctrine_ORM_Export_ClassExporter
|
|||||||
$columns[$mapping['columnName']] = $column;
|
$columns[$mapping['columnName']] = $column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($class->getAssociationMappings() as $mapping) {
|
||||||
|
if ($mapping->isOneToOne() && $mapping->isOwningSide()) {
|
||||||
|
foreach ($mapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
|
||||||
|
$column = array();
|
||||||
|
$column['name'] = $sourceColumn;
|
||||||
|
$column['type'] = $this->_em->getClassMetadata($mapping->getTargetEntityName())
|
||||||
|
->getTypeOfColumn($targetColumn);
|
||||||
|
$columns[$sourceColumn] = $column;
|
||||||
|
}
|
||||||
|
} else if ($mapping->isOneToMany() && $mapping->usesJoinTable()) {
|
||||||
|
//... create join table, one-many through join table supported later
|
||||||
|
throw new Doctrine_Exception("Not yet implemented.");
|
||||||
|
} else if ($mapping->isManyToMany() && $mapping->isOwningSide()) {
|
||||||
|
//... create join table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->_sm->createTable($class->getTableName(), $columns, $options);
|
$this->_sm->createTable($class->getTableName(), $columns, $options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
*
|
*
|
||||||
* @author Roman Borschel <roman@code-factory.org>
|
* @author Roman Borschel <roman@code-factory.org>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @todo Rename to AssociationMapping.
|
|
||||||
*/
|
*/
|
||||||
abstract class Doctrine_ORM_Mapping_AssociationMapping
|
abstract class Doctrine_ORM_Mapping_AssociationMapping
|
||||||
{
|
{
|
||||||
@ -362,6 +361,11 @@ abstract class Doctrine_ORM_Mapping_AssociationMapping
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function usesJoinTable()
|
||||||
|
{
|
||||||
|
return (bool)$this->_joinTable;
|
||||||
|
}
|
||||||
|
|
||||||
abstract public function lazyLoadFor($entity, $entityManager);
|
abstract public function lazyLoadFor($entity, $entityManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ class Doctrine_ORM_Mapping_Driver_AnnotationDriver {
|
|||||||
} else if ($oneToManyAnnot = $property->getAnnotation('DoctrineOneToMany')) {
|
} else if ($oneToManyAnnot = $property->getAnnotation('DoctrineOneToMany')) {
|
||||||
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
|
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
|
||||||
$mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
|
$mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
|
||||||
|
$mapping['cascade'] = $oneToManyAnnot->cascade;
|
||||||
$metadata->mapOneToMany($mapping);
|
$metadata->mapOneToMany($mapping);
|
||||||
} else if ($manyToOneAnnot = $property->getAnnotation('DoctrineManyToOne')) {
|
} else if ($manyToOneAnnot = $property->getAnnotation('DoctrineManyToOne')) {
|
||||||
$mapping['joinColumns'] = $manyToOneAnnot->joinColumns;
|
$mapping['joinColumns'] = $manyToOneAnnot->joinColumns;
|
||||||
|
@ -100,11 +100,17 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
|||||||
/**
|
/**
|
||||||
* Updates an entity.
|
* Updates an entity.
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\Entity $entity The entity to update.
|
* @param object $entity The entity to update.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function update(Doctrine_ORM_Entity $entity)
|
public function update($entity)
|
||||||
{
|
{
|
||||||
|
$updateData = array();
|
||||||
|
$this->_prepareData($entity, $updateData);
|
||||||
|
$id = array_combine($this->_classMetadata->getIdentifierFieldNames(),
|
||||||
|
$this->_em->getUnitOfWork()->getEntityIdentifier($entity));
|
||||||
|
$this->_conn->update($this->_classMetadata->getTableName(), $updateData, $id);
|
||||||
|
|
||||||
/*$dataChangeSet = $entity->_getDataChangeSet();
|
/*$dataChangeSet = $entity->_getDataChangeSet();
|
||||||
$referenceChangeSet = $entity->_getReferenceChangeSet();
|
$referenceChangeSet = $entity->_getReferenceChangeSet();
|
||||||
|
|
||||||
@ -126,12 +132,14 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
|||||||
/**
|
/**
|
||||||
* Deletes an entity.
|
* Deletes an entity.
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\Entity $entity The entity to delete.
|
* @param object $entity The entity to delete.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function delete(Doctrine_ORM_Entity $entity)
|
public function delete($entity)
|
||||||
{
|
{
|
||||||
//TODO: perform delete
|
$id = array_combine($this->_classMetadata->getIdentifierFieldNames(),
|
||||||
|
$this->_em->getUnitOfWork()->getEntityIdentifier($entity));
|
||||||
|
$this->_conn->delete($this->_classMetadata->getTableName(), $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -232,7 +240,7 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
|||||||
*/
|
*/
|
||||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||||
{
|
{
|
||||||
foreach ($this->_em->getUnitOfWork()->getDataChangeSet($entity) as $field => $change) {
|
foreach ($this->_em->getUnitOfWork()->getEntityChangeSet($entity) as $field => $change) {
|
||||||
if (is_array($change)) {
|
if (is_array($change)) {
|
||||||
list ($oldVal, $newVal) = each($change);
|
list ($oldVal, $newVal) = each($change);
|
||||||
} else {
|
} else {
|
||||||
@ -244,16 +252,21 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
|||||||
$columnName = $this->_classMetadata->getColumnName($field);
|
$columnName = $this->_classMetadata->getColumnName($field);
|
||||||
|
|
||||||
if ($this->_classMetadata->hasAssociation($field)) {
|
if ($this->_classMetadata->hasAssociation($field)) {
|
||||||
$assocMapping = $this->_classMetadata->getAssociationMapping($field);
|
if ($newVal !== null) {
|
||||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
$assocMapping = $this->_classMetadata->getAssociationMapping($field);
|
||||||
//echo "NOT TO-ONE OR INVERSE!";
|
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||||
continue;
|
//echo "NOT TO-ONE OR INVERSE!";
|
||||||
}
|
continue;
|
||||||
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
|
}
|
||||||
//TODO: throw exc if field not set
|
//echo "HERE!!!";
|
||||||
$otherClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName());
|
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
|
||||||
$result[$sourceColumn] = $otherClass->getReflectionProperty(
|
//TODO: throw exc if field not set
|
||||||
$otherClass->getFieldName($targetColumn))->getValue($newVal);
|
$otherClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName());
|
||||||
|
$result[$sourceColumn] = $otherClass->getReflectionProperty(
|
||||||
|
$otherClass->getFieldName($targetColumn))->getValue($newVal);
|
||||||
|
}
|
||||||
|
} else if ( ! $isInsert) {
|
||||||
|
echo "NO INSERT AND NEWVAL NULL ON 1-1 ASSOC, OWNING SIDE";
|
||||||
}
|
}
|
||||||
} else if (is_null($newVal)) {
|
} else if (is_null($newVal)) {
|
||||||
$result[$columnName] = null;
|
$result[$columnName] = null;
|
||||||
|
@ -60,7 +60,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
* @todo Not sure this is a good idea. It is a problematic solution because
|
* @todo Not sure this is a good idea. It is a problematic solution because
|
||||||
* it hides the original state while the locked state is active.
|
* it hides the original state while the locked state is active.
|
||||||
*/
|
*/
|
||||||
const STATE_LOCKED = 6;
|
//const STATE_LOCKED = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A detached Entity is an instance with a persistent identity that is not
|
* A detached Entity is an instance with a persistent identity that is not
|
||||||
@ -109,7 +109,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_dataChangeSets = array();
|
protected $_entityChangeSets = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The states of entities in this UnitOfWork.
|
* The states of entities in this UnitOfWork.
|
||||||
@ -167,7 +167,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
protected $_collectionUpdates = array();
|
protected $_collectionUpdates = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The EntityManager the UnitOfWork belongs to.
|
* The EntityManager that "owns" this UnitOfWork instance.
|
||||||
*
|
*
|
||||||
* @var Doctrine\ORM\EntityManager
|
* @var Doctrine\ORM\EntityManager
|
||||||
*/
|
*/
|
||||||
@ -182,8 +182,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
protected $_commitOrderCalculator;
|
protected $_commitOrderCalculator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Initializes a new UnitOfWork instance, bound to the given EntityManager.
|
||||||
* Creates a new UnitOfWork.
|
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\EntityManager $em
|
* @param Doctrine\ORM\EntityManager $em
|
||||||
*/
|
*/
|
||||||
@ -203,7 +202,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
public function commit()
|
public function commit()
|
||||||
{
|
{
|
||||||
// Compute changes in managed entities
|
// Compute changes in managed entities
|
||||||
$this->computeDataChangeSet();
|
$this->computeEntityChangeSets();
|
||||||
|
|
||||||
if (empty($this->_newEntities) &&
|
if (empty($this->_newEntities) &&
|
||||||
empty($this->_deletedEntities) &&
|
empty($this->_deletedEntities) &&
|
||||||
@ -238,42 +237,38 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
$this->_newEntities = array();
|
$this->_newEntities = array();
|
||||||
$this->_dirtyEntities = array();
|
$this->_dirtyEntities = array();
|
||||||
$this->_deletedEntities = array();
|
$this->_deletedEntities = array();
|
||||||
$this->_dataChangeSets = array();
|
$this->_entityChangeSets = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data changeset for an entity.
|
* Gets the changeset for an entity.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getDataChangeSet($entity)
|
public function getEntityChangeSet($entity)
|
||||||
{
|
{
|
||||||
$oid = spl_object_hash($entity);
|
$oid = spl_object_hash($entity);
|
||||||
if (isset($this->_dataChangeSets[$oid])) {
|
if (isset($this->_entityChangeSets[$oid])) {
|
||||||
return $this->_dataChangeSets[$oid];
|
return $this->_entityChangeSets[$oid];
|
||||||
}
|
}
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes all the changes that have been done to entities in the identity map
|
* Computes all the changes that have been done to entities
|
||||||
* since the last commit and stores these changes in _dataChangeSet temporarily
|
* since the last commit and stores these changes in the _entityChangeSet map
|
||||||
* for access by the persisters, until the UoW commit is finished.
|
* temporarily for access by the persisters, until the UoW commit is finished.
|
||||||
*
|
*
|
||||||
* @param array $entities The entities for which to compute the changesets. If this
|
* @param array $entities The entities for which to compute the changesets. If this
|
||||||
* parameter is not specified, the changesets of all entities in the identity
|
* parameter is not specified, the changesets of all entities in the identity
|
||||||
* map are computed.
|
* map are computed.
|
||||||
*/
|
*/
|
||||||
public function computeDataChangeSet(array $entities = null)
|
public function computeEntityChangeSets(array $entities = null)
|
||||||
{
|
{
|
||||||
$entitySet = array();
|
$entitySet = array();
|
||||||
if ( ! is_null($entities)) {
|
if ( ! is_null($entities)) {
|
||||||
foreach ($entities as $entity) {
|
foreach ($entities as $entity) {
|
||||||
$className = get_class($entity);
|
$entitySet[get_class($entity)][] = $entity;
|
||||||
if ( ! isset($entitySet[$className])) {
|
|
||||||
$entitySet[$className] = array();
|
|
||||||
}
|
|
||||||
$entitySet[$className][] = $entity;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$entitySet = $this->_identityMap;
|
$entitySet = $this->_identityMap;
|
||||||
@ -294,23 +289,42 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
$actualData[$name] = $refProp->getValue($entity);
|
$actualData[$name] = $refProp->getValue($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($state == self::STATE_NEW) {
|
if ( ! isset($this->_originalEntityData[$oid])) {
|
||||||
$this->_dataChangeSets[$oid] = $actualData;
|
// Entity is either NEW or MANAGED but not yet fully persisted
|
||||||
|
// (only has an id). These result in an INSERT.
|
||||||
|
$this->_entityChangeSets[$oid] = $actualData;
|
||||||
$this->_originalEntityData[$oid] = $actualData;
|
$this->_originalEntityData[$oid] = $actualData;
|
||||||
} else {
|
} else {
|
||||||
|
// Entity is "fully" MANAGED: it was already fully persisted before
|
||||||
|
// and we have a copy of the original data
|
||||||
$originalData = $this->_originalEntityData[$oid];
|
$originalData = $this->_originalEntityData[$oid];
|
||||||
$changeSet = array();
|
$changeSet = array();
|
||||||
|
$entityIsDirty = false;
|
||||||
foreach ($actualData as $propName => $actualValue) {
|
foreach ($actualData as $propName => $actualValue) {
|
||||||
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
|
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
|
||||||
if (is_object($orgValue) && $orgValue !== $actualValue) {
|
if (is_object($orgValue) && $orgValue !== $actualValue) {
|
||||||
$changeSet[$propName] = array($orgValue => $actualValue);
|
$changeSet[$propName] = array($orgValue => $actualValue);
|
||||||
} else if ($orgValue != $actualValue || (is_null($orgValue) xor is_null($actualValue))) {
|
} else if ($orgValue != $actualValue || (is_null($orgValue) xor is_null($actualValue))) {
|
||||||
$changeSet[$propName] = array($orgValue => $actualValue);
|
$changeSet[$propName] = array($orgValue => $actualValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($changeSet[$propName])) {
|
||||||
|
if ($class->hasAssociation($propName)) {
|
||||||
|
$assoc = $class->getAssociationMapping($propName);
|
||||||
|
if ($assoc->isOneToOne() && $assoc->isOwningSide()) {
|
||||||
|
$entityIsDirty = true;
|
||||||
|
}
|
||||||
|
$this->_handleAssociationValueChanged($assoc, $actualValue);
|
||||||
|
} else {
|
||||||
|
$entityIsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($changeSet) {
|
if ($changeSet) {
|
||||||
$this->_dirtyEntities[$oid] = $entity;
|
if ($entityIsDirty) {
|
||||||
$this->_dataChangeSets[$oid] = $changeSet;
|
$this->_dirtyEntities[$oid] = $entity;
|
||||||
|
}
|
||||||
|
$this->_entityChangeSets[$oid] = $changeSet;
|
||||||
$this->_originalEntityData[$oid] = $actualData;
|
$this->_originalEntityData[$oid] = $actualData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,6 +333,58 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the case during changeset computation where an association value
|
||||||
|
* has changed. For a to-one association this means a new associated instance
|
||||||
|
* has been set. For a to-many association this means a new associated collection/array
|
||||||
|
* of entities has been set.
|
||||||
|
*
|
||||||
|
* @param <type> $assoc
|
||||||
|
* @param <type> $value
|
||||||
|
*/
|
||||||
|
private function _handleAssociationValueChanged($assoc, $value)
|
||||||
|
{
|
||||||
|
if ($assoc->isOneToOne()) {
|
||||||
|
$value = array($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetClass = $this->_em->getClassMetadata($assoc->getTargetEntityName());
|
||||||
|
foreach ($value as $entry) {
|
||||||
|
$state = $this->getEntityState($entry);
|
||||||
|
$oid = spl_object_hash($entry);
|
||||||
|
if ($state == self::STATE_NEW) {
|
||||||
|
// Get identifier, if possible (not post-insert)
|
||||||
|
$idGen = $this->_em->getIdGenerator($targetClass->getClassName());
|
||||||
|
if ( ! $idGen->isPostInsertGenerator()) {
|
||||||
|
$idValue = $idGen->generate($entry);
|
||||||
|
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||||
|
if ( ! $idGen instanceof Doctrine_ORM_Id_Assigned) {
|
||||||
|
$this->_entityIdentifiers[$oid] = array($idValue);
|
||||||
|
$targetClass->getSingleIdReflectionProperty()->setValue($entry, $idValue);
|
||||||
|
} else {
|
||||||
|
$this->_entityIdentifiers[$oid] = $idValue;
|
||||||
|
}
|
||||||
|
$this->addToIdentityMap($entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEW entities are INSERTed within the current unit of work.
|
||||||
|
$data = array();
|
||||||
|
foreach ($targetClass->getReflectionProperties() as $name => $refProp) {
|
||||||
|
$data[$name] = $refProp->getValue($entry);
|
||||||
|
}
|
||||||
|
$oid = spl_object_hash($entry);
|
||||||
|
$this->_newEntities[$oid] = $entry;
|
||||||
|
$this->_entityChangeSets[$oid] = $data;
|
||||||
|
$this->_originalEntityData[$oid] = $data;
|
||||||
|
} else if ($state == self::STATE_DELETED) {
|
||||||
|
throw new Doctrine_Exception("Deleted entity in collection detected during flush.");
|
||||||
|
}
|
||||||
|
// MANAGED associated entities are already taken into account
|
||||||
|
// during changeset calculation anyway, since they are in the identity map.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes all entity insertions for entities of the specified type.
|
* Executes all entity insertions for entities of the specified type.
|
||||||
*
|
*
|
||||||
@ -355,11 +421,10 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
*/
|
*/
|
||||||
private function _executeUpdates($class)
|
private function _executeUpdates($class)
|
||||||
{
|
{
|
||||||
try { throw new Exception(); } catch (Exception $e) { echo $e->getTraceAsString(); }
|
|
||||||
$className = $class->getClassName();
|
$className = $class->getClassName();
|
||||||
$persister = $this->_em->getEntityPersister($className);
|
$persister = $this->_em->getEntityPersister($className);
|
||||||
foreach ($this->_dirtyEntities as $entity) {
|
foreach ($this->_dirtyEntities as $entity) {
|
||||||
if ($entity->getClass()->getClassName() == $className) {
|
if (get_class($entity) == $className) {
|
||||||
$persister->update($entity);
|
$persister->update($entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,7 +440,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
$className = $class->getClassName();
|
$className = $class->getClassName();
|
||||||
$persister = $this->_em->getEntityPersister($className);
|
$persister = $this->_em->getEntityPersister($className);
|
||||||
foreach ($this->_deletedEntities as $entity) {
|
foreach ($this->_deletedEntities as $entity) {
|
||||||
if ($entity->getClass()->getClassName() == $className) {
|
if (get_class($entity) == $className) {
|
||||||
$persister->delete($entity);
|
$persister->delete($entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,13 +519,13 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
$oid = spl_object_hash($entity);
|
$oid = spl_object_hash($entity);
|
||||||
|
|
||||||
if (isset($this->_dirtyEntities[$oid])) {
|
if (isset($this->_dirtyEntities[$oid])) {
|
||||||
throw new Doctrine_Connection_Exception("Dirty object can't be registered as new.");
|
throw new Doctrine_Exception("Dirty object can't be registered as new.");
|
||||||
}
|
}
|
||||||
if (isset($this->_deletedEntities[$oid])) {
|
if (isset($this->_deletedEntities[$oid])) {
|
||||||
throw new Doctrine_Connection_Exception("Removed object can't be registered as new.");
|
throw new Doctrine_Exception("Removed object can't be registered as new.");
|
||||||
}
|
}
|
||||||
if (isset($this->_newEntities[$oid])) {
|
if (isset($this->_newEntities[$oid])) {
|
||||||
throw new Doctrine_Connection_Exception("Object already registered as new. Can't register twice.");
|
throw new Doctrine_Exception("Object already registered as new. Can't register twice.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_newEntities[$oid] = $entity;
|
$this->_newEntities[$oid] = $entity;
|
||||||
@ -783,14 +848,14 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
if ( ! empty($insertNow)) {
|
if ( ! empty($insertNow)) {
|
||||||
// We have no choice. This means that there are new entities
|
// We have no choice. This means that there are new entities
|
||||||
// with an IDENTITY column key generation strategy.
|
// with an IDENTITY column key generation strategy.
|
||||||
$this->computeDataChangeSet($insertNow);
|
$this->computeEntityChangeSets($insertNow);
|
||||||
$commitOrder = $this->_getCommitOrder($insertNow);
|
$commitOrder = $this->_getCommitOrder($insertNow);
|
||||||
foreach ($commitOrder as $class) {
|
foreach ($commitOrder as $class) {
|
||||||
$this->_executeInserts($class);
|
$this->_executeInserts($class);
|
||||||
}
|
}
|
||||||
// remove them from _newEntities and _dataChangeSets
|
// remove them from _newEntities and _entityChangeSets
|
||||||
$this->_newEntities = array_diff_key($this->_newEntities, $insertNow);
|
$this->_newEntities = array_diff_key($this->_newEntities, $insertNow);
|
||||||
$this->_dataChangeSets = array_diff_key($this->_dataChangeSets, $insertNow);
|
$this->_entityChangeSets = array_diff_key($this->_entityChangeSets, $insertNow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,7 +864,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
* This method is internally called during save() cascades as it tracks
|
* This method is internally called during save() cascades as it tracks
|
||||||
* the already visited entities to prevent infinite recursions.
|
* the already visited entities to prevent infinite recursions.
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\Entity $entity The entity to save.
|
* @param object $entity The entity to save.
|
||||||
* @param array $visited The already visited entities.
|
* @param array $visited The already visited entities.
|
||||||
*/
|
*/
|
||||||
private function _doSave($entity, array &$visited, array &$insertNow)
|
private function _doSave($entity, array &$visited, array &$insertNow)
|
||||||
@ -822,10 +887,12 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
$insertNow[$oid] = $entity;
|
$insertNow[$oid] = $entity;
|
||||||
} else {
|
} else {
|
||||||
$idValue = $idGen->generate($entity);
|
$idValue = $idGen->generate($entity);
|
||||||
$this->_entityIdentifiers[$oid] = array($idValue);
|
|
||||||
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||||
if ( ! $idGen instanceof Doctrine_ORM_Id_Assigned) {
|
if ( ! $idGen instanceof Doctrine_ORM_Id_Assigned) {
|
||||||
|
$this->_entityIdentifiers[$oid] = array($idValue);
|
||||||
$class->getSingleIdReflectionProperty()->setValue($entity, $idValue);
|
$class->getSingleIdReflectionProperty()->setValue($entity, $idValue);
|
||||||
|
} else {
|
||||||
|
$this->_entityIdentifiers[$oid] = $idValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->registerNew($entity);
|
$this->registerNew($entity);
|
||||||
@ -835,7 +902,7 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
throw new Doctrine_Exception("Behavior of save() for a detached entity "
|
throw new Doctrine_Exception("Behavior of save() for a detached entity "
|
||||||
. "is not yet defined.");
|
. "is not yet defined.");
|
||||||
case self::STATE_DELETED:
|
case self::STATE_DELETED:
|
||||||
// $entity becomes managed again
|
// entity becomes managed again
|
||||||
if ($this->isRegisteredRemoved($entity)) {
|
if ($this->isRegisteredRemoved($entity)) {
|
||||||
//TODO: better a method for this?
|
//TODO: better a method for this?
|
||||||
unset($this->_deletedEntities[$oid]);
|
unset($this->_deletedEntities[$oid]);
|
||||||
@ -855,11 +922,12 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
/**
|
/**
|
||||||
* Deletes an entity as part of the current unit of work.
|
* Deletes an entity as part of the current unit of work.
|
||||||
*
|
*
|
||||||
* @param Doctrine_ORM_Entity $entity
|
* @param object $entity
|
||||||
*/
|
*/
|
||||||
public function delete($entity)
|
public function delete($entity)
|
||||||
{
|
{
|
||||||
$this->_doDelete($entity, array());
|
$visited = array();
|
||||||
|
$this->_doDelete($entity, $visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -911,8 +979,8 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
}
|
}
|
||||||
$relatedEntities = $class->getReflectionProperty($assocMapping->getSourceFieldName())
|
$relatedEntities = $class->getReflectionProperty($assocMapping->getSourceFieldName())
|
||||||
->getValue($entity);
|
->getValue($entity);
|
||||||
if ($relatedEntities instanceof Doctrine_ORM_Collection &&
|
if (($relatedEntities instanceof Doctrine_ORM_Collection || is_array($relatedEntities))
|
||||||
count($relatedEntities) > 0) {
|
&& count($relatedEntities) > 0) {
|
||||||
foreach ($relatedEntities as $relatedEntity) {
|
foreach ($relatedEntities as $relatedEntity) {
|
||||||
$this->_doSave($relatedEntity, $visited, $insertNow);
|
$this->_doSave($relatedEntity, $visited, $insertNow);
|
||||||
}
|
}
|
||||||
@ -1151,6 +1219,9 @@ class Doctrine_ORM_UnitOfWork
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the identifier of an entity.
|
* Gets the identifier of an entity.
|
||||||
|
* The returned value is always an array of identifier values. If the entity
|
||||||
|
* has a composite primary key then the identifier values are in the same
|
||||||
|
* order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames().
|
||||||
*
|
*
|
||||||
* @param object $entity
|
* @param object $entity
|
||||||
* @return array The identifier values.
|
* @return array The identifier values.
|
||||||
|
@ -8,14 +8,14 @@ require_once 'lib/DoctrineTestInit.php';
|
|||||||
* @author robo
|
* @author robo
|
||||||
*/
|
*/
|
||||||
class Orm_Functional_BasicCRUDTest extends Doctrine_OrmFunctionalTestCase {
|
class Orm_Functional_BasicCRUDTest extends Doctrine_OrmFunctionalTestCase {
|
||||||
public function testFoo() {
|
public function testSingleEntityCRUD() {
|
||||||
$em = $this->_getEntityManager();
|
$em = $this->_getEntityManager();
|
||||||
|
|
||||||
$exporter = new Doctrine_ORM_Export_ClassExporter($em);
|
$exporter = new Doctrine_ORM_Export_ClassExporter($em);
|
||||||
$exporter->exportClasses(array(
|
$exporter->exportClasses(array(
|
||||||
$em->getClassMetadata('CmsUser'),
|
$em->getClassMetadata('CmsUser'),
|
||||||
$em->getClassMetadata('CmsPhonenumber')
|
$em->getClassMetadata('CmsPhonenumber')
|
||||||
));
|
));
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
$user = new CmsUser;
|
$user = new CmsUser;
|
||||||
@ -24,25 +24,33 @@ class Orm_Functional_BasicCRUDTest extends Doctrine_OrmFunctionalTestCase {
|
|||||||
$this->assertTrue(is_numeric($user->id));
|
$this->assertTrue(is_numeric($user->id));
|
||||||
$this->assertTrue($em->contains($user));
|
$this->assertTrue($em->contains($user));
|
||||||
|
|
||||||
$user2 = new CmsUser;
|
|
||||||
$user2->name = 'jwage';
|
|
||||||
$em->save($user2);
|
|
||||||
$this->assertTrue(is_numeric($user2->id));
|
|
||||||
$this->assertTrue($em->contains($user2));
|
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
$user3 = $em->find('CmsUser', $user->id);
|
$user2 = $em->find('CmsUser', $user->id);
|
||||||
$this->assertTrue($user === $user3);
|
$this->assertTrue($user === $user2);
|
||||||
|
|
||||||
$user4 = $em->find('CmsUser', $user2->id);
|
|
||||||
$this->assertTrue($user2 === $user4);
|
|
||||||
|
|
||||||
|
// Add a phonenumber
|
||||||
$ph = new CmsPhonenumber;
|
$ph = new CmsPhonenumber;
|
||||||
$ph->phonenumber = "12345";
|
$ph->phonenumber = "12345";
|
||||||
|
$user->addPhonenumber($ph);
|
||||||
|
$em->flush();
|
||||||
|
$this->assertTrue($em->contains($ph));
|
||||||
|
$this->assertTrue($em->contains($user));
|
||||||
|
|
||||||
$user->phonenumbers[] = $ph;
|
// Update
|
||||||
|
$user->name = 'guilherme';
|
||||||
|
$em->flush();
|
||||||
|
$this->assertEquals('guilherme', $user->name);
|
||||||
|
|
||||||
//var_dump($em->getUnitOfWork())
|
// Delete
|
||||||
|
$em->delete($user);
|
||||||
|
$this->assertTrue($em->getUnitOfWork()->isRegisteredRemoved($user));
|
||||||
|
$em->flush();
|
||||||
|
$this->assertFalse($em->getUnitOfWork()->isRegisteredRemoved($user));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMore() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,15 +119,21 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
|||||||
$this->assertEquals(0, count($avatarPersister->getDeletes()));
|
$this->assertEquals(0, count($avatarPersister->getDeletes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testComputeDataChangeSet()
|
public function testComputeEntityChangeSets()
|
||||||
{
|
{
|
||||||
|
// We need an ID generator for ForumAvatar, because we attach a NEW ForumAvatar
|
||||||
|
// to a (faked) MANAGED instance. During changeset computation this will result
|
||||||
|
// in the UnitOfWork requesting the Id generator of ForumAvatar.
|
||||||
|
$avatarIdGeneratorMock = new Doctrine_IdentityIdGeneratorMock($this->_emMock);
|
||||||
|
$this->_emMock->setIdGenerator('ForumAvatar', $avatarIdGeneratorMock);
|
||||||
|
|
||||||
$user1 = new ForumUser();
|
$user1 = new ForumUser();
|
||||||
$user1->id = 1;
|
$user1->id = 1;
|
||||||
$user1->username = "romanb";
|
$user1->username = "romanb";
|
||||||
$user1->avatar = new ForumAvatar();
|
$user1->avatar = new ForumAvatar();
|
||||||
// Fake managed state
|
// Fake managed state
|
||||||
$this->_unitOfWork->setEntityState($user1, Doctrine_ORM_UnitOfWork::STATE_MANAGED);
|
$this->_unitOfWork->setEntityState($user1, Doctrine_ORM_UnitOfWork::STATE_MANAGED);
|
||||||
|
|
||||||
$user2 = new ForumUser();
|
$user2 = new ForumUser();
|
||||||
$user2->id = 2;
|
$user2->id = 2;
|
||||||
$user2->username = "jwage";
|
$user2->username = "jwage";
|
||||||
@ -143,10 +149,10 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
|||||||
));
|
));
|
||||||
|
|
||||||
// Go
|
// Go
|
||||||
$this->_unitOfWork->computeDataChangeSet(array($user1, $user2));
|
$this->_unitOfWork->computeEntityChangeSets(array($user1, $user2));
|
||||||
|
|
||||||
// Verify
|
// Verify
|
||||||
$user1ChangeSet = $this->_unitOfWork->getDataChangeSet($user1);
|
$user1ChangeSet = $this->_unitOfWork->getEntityChangeSet($user1);
|
||||||
$this->assertTrue(is_array($user1ChangeSet));
|
$this->assertTrue(is_array($user1ChangeSet));
|
||||||
$this->assertEquals(2, count($user1ChangeSet));
|
$this->assertEquals(2, count($user1ChangeSet));
|
||||||
$this->assertTrue(isset($user1ChangeSet['username']));
|
$this->assertTrue(isset($user1ChangeSet['username']));
|
||||||
@ -154,7 +160,7 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
|||||||
$this->assertTrue(isset($user1ChangeSet['avatar']));
|
$this->assertTrue(isset($user1ChangeSet['avatar']));
|
||||||
$this->assertSame(array(null => $user1->avatar), $user1ChangeSet['avatar']);
|
$this->assertSame(array(null => $user1->avatar), $user1ChangeSet['avatar']);
|
||||||
|
|
||||||
$user2ChangeSet = $this->_unitOfWork->getDataChangeSet($user2);
|
$user2ChangeSet = $this->_unitOfWork->getEntityChangeSet($user2);
|
||||||
$this->assertTrue(is_array($user2ChangeSet));
|
$this->assertTrue(is_array($user2ChangeSet));
|
||||||
$this->assertEquals(1, count($user2ChangeSet));
|
$this->assertEquals(1, count($user2ChangeSet));
|
||||||
$this->assertTrue(isset($user2ChangeSet['username']));
|
$this->assertTrue(isset($user2ChangeSet['username']));
|
||||||
|
@ -81,6 +81,7 @@ class Doctrine_EntityManagerMock extends Doctrine_ORM_EntityManager
|
|||||||
$this->_idGenerators[$className] = $generator;
|
$this->_idGenerators[$className] = $generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
public function getIdGenerator($className)
|
public function getIdGenerator($className)
|
||||||
{
|
{
|
||||||
if (isset($this->_idGenerators[$className])) {
|
if (isset($this->_idGenerators[$className])) {
|
||||||
|
@ -14,10 +14,10 @@ class Doctrine_UnitOfWorkMock extends Doctrine_ORM_UnitOfWork {
|
|||||||
* @param <type> $entity
|
* @param <type> $entity
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
public function getDataChangeSet($entity) {
|
public function getEntityChangeSet($entity) {
|
||||||
$oid = spl_object_hash($entity);
|
$oid = spl_object_hash($entity);
|
||||||
return isset($this->_mockDataChangeSets[$oid]) ?
|
return isset($this->_mockDataChangeSets[$oid]) ?
|
||||||
$this->_mockDataChangeSets[$oid] : parent::getDataChangeSet($entity);
|
$this->_mockDataChangeSets[$oid] : parent::getEntityChangeSet($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MOCK API */
|
/* MOCK API */
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* @DoctrineEntity
|
* @DoctrineEntity
|
||||||
*/
|
*/
|
||||||
class CmsPhonenumber implements Doctrine_ORM_Entity
|
class CmsPhonenumber
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="varchar", length=50)
|
||||||
@ -14,4 +14,9 @@ class CmsPhonenumber implements Doctrine_ORM_Entity
|
|||||||
* @DoctrineManyToOne(targetEntity="CmsUser", joinColumns={"user_id" = "id"})
|
* @DoctrineManyToOne(targetEntity="CmsUser", joinColumns={"user_id" = "id"})
|
||||||
*/
|
*/
|
||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
|
public function setUser(CmsUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
$user->addPhonenumber($this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,4 +33,14 @@ class CmsUser
|
|||||||
* @DoctrineOneToMany(targetEntity="CmsArticle", mappedBy="user")
|
* @DoctrineOneToMany(targetEntity="CmsArticle", mappedBy="user")
|
||||||
*/
|
*/
|
||||||
public $articles;
|
public $articles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a phonenumber to the user.
|
||||||
|
*
|
||||||
|
* @param <type> $phone
|
||||||
|
*/
|
||||||
|
public function addPhonenumber(CmsPhonenumber $phone) {
|
||||||
|
$this->phonenumbers[] = $phone;
|
||||||
|
$phone->user = $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user