[2.0][DDC-164][DDC-165] Fixed. Cleaned up ManyToManyMapping. Cleaned up identifier handling and handling of composite identifiers in some places.
This commit is contained in:
parent
a9d739a743
commit
555b097641
@ -30,8 +30,10 @@ foreach ($revisions as $rev) {
|
||||
$xml = simplexml_load_file($logsPath . $rev . '/log.xml');
|
||||
foreach ($xml->testsuite as $suite) {
|
||||
foreach ($suite->testcase as $test) {
|
||||
$name = (string)$suite['name'] . '#' . (string)$test['name'];
|
||||
$graphs[$name][] = (double)$test['time'];
|
||||
if (stripos((string)$suite['name'], 'performance') !== false || stripos((string)$test['name'], 'performance') !== false) {
|
||||
$name = (string)$suite['name'] . '#' . (string)$test['name'];
|
||||
$graphs[$name][] = (double)$test['time'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ namespace Doctrine\DBAL\Types;
|
||||
|
||||
/**
|
||||
* Type that maps an SQL INT to a PHP integer.
|
||||
*
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
class IntegerType extends Type
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getMetadataDriverImpl()
|
||||
{
|
||||
if($this->_attributes['metadataDriverImpl'] == null) {
|
||||
if ($this->_attributes['metadataDriverImpl'] == null) {
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader(new \Doctrine\Common\Cache\ArrayCache);
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
$this->_attributes['metadataDriverImpl'] = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader);
|
||||
|
@ -121,12 +121,12 @@ final class ClassMetadata extends ClassMetadataInfo
|
||||
* Gets the ReflectionProperty for the single identifier field.
|
||||
*
|
||||
* @return ReflectionProperty
|
||||
* @throws DoctrineException If the class has a composite identifier.
|
||||
* @throws BadMethodCallException If the class has a composite identifier.
|
||||
*/
|
||||
public function getSingleIdReflectionProperty()
|
||||
{
|
||||
if ($this->isIdentifierComposite) {
|
||||
throw DoctrineException::singleIdNotAllowedOnCompositePrimaryKey();
|
||||
throw new \BadMethodCallException("Class " . $this->name . " has a composite identifier.");
|
||||
}
|
||||
return $this->reflFields[$this->identifier[0]];
|
||||
}
|
||||
@ -163,12 +163,12 @@ final class ClassMetadata extends ClassMetadataInfo
|
||||
foreach ($this->identifier as $idField) {
|
||||
$value = $this->reflFields[$idField]->getValue($entity);
|
||||
if ($value !== null) {
|
||||
$id[] = $value;
|
||||
$id[$idField] = $value;
|
||||
}
|
||||
}
|
||||
return $id;
|
||||
} else {
|
||||
return $this->reflFields[$this->identifier[0]]->getValue($entity);
|
||||
return array($this->identifier[0] => $this->reflFields[$this->identifier[0]]->getValue($entity));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,8 +108,9 @@ class ClassMetadataFactory
|
||||
if (($cached = $this->_cacheDriver->fetch($cacheKey)) !== false) {
|
||||
$this->_loadedMetadata[$className] = $cached;
|
||||
} else {
|
||||
$this->_loadMetadata($className);
|
||||
$this->_cacheDriver->save($cacheKey, $this->_loadedMetadata[$className], null);
|
||||
foreach ($this->_loadMetadata($className) as $loadedClassName) {
|
||||
$this->_cacheDriver->save($cacheKey, $this->_loadedMetadata[$className], null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->_loadMetadata($className);
|
||||
@ -151,6 +152,8 @@ class ClassMetadataFactory
|
||||
*/
|
||||
protected function _loadMetadata($name)
|
||||
{
|
||||
$loaded = array();
|
||||
|
||||
// Collect parent classes, ignoring transient (not-mapped) classes.
|
||||
$parentClass = $name;
|
||||
$parentClasses = array();
|
||||
@ -241,7 +244,11 @@ class ClassMetadataFactory
|
||||
if ( ! $class->isMappedSuperclass) {
|
||||
array_unshift($visited, $className);
|
||||
}
|
||||
|
||||
$loaded[] = $className;
|
||||
}
|
||||
|
||||
return $loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,6 +264,9 @@ class ClassMetadataInfo
|
||||
* as any join columns and discriminator columns.
|
||||
*
|
||||
* @var array
|
||||
* @todo Remove. Or at least remove from serialization/unserialization and instead
|
||||
* populate them during runtime.
|
||||
* See http://www.doctrine-project.org/jira/browse/DDC-132.
|
||||
*/
|
||||
public $resultColumnNames = array();
|
||||
|
||||
@ -486,7 +489,7 @@ class ClassMetadataInfo
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
*/
|
||||
public function getOwningClass($fieldName)
|
||||
/*public function getOwningClass($fieldName)
|
||||
{
|
||||
if ($this->inheritanceType == self::INHERITANCE_TYPE_NONE) {
|
||||
return $this->name;
|
||||
@ -494,7 +497,7 @@ class ClassMetadataInfo
|
||||
$mapping = $this->getFieldMapping($fieldName);
|
||||
return $mapping['inherited'];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Gets the name of the root class of the mapped entity hierarchy. If the entity described
|
||||
|
@ -40,24 +40,14 @@ namespace Doctrine\ORM\Mapping;
|
||||
class ManyToManyMapping extends AssociationMapping
|
||||
{
|
||||
/**
|
||||
* The key columns of the source table.
|
||||
* Maps the columns in the relational table to the columns in the source table.
|
||||
*/
|
||||
public $sourceKeyColumns = array();
|
||||
public $relationToSourceKeyColumns = array();
|
||||
|
||||
/**
|
||||
* The key columns of the target table.
|
||||
* Maps the columns in the relation table to the columns in the target table.
|
||||
*/
|
||||
public $targetKeyColumns = array();
|
||||
|
||||
/**
|
||||
* Maps the columns in the source table to the columns in the relation table.
|
||||
*/
|
||||
public $sourceToRelationKeyColumns = array();
|
||||
|
||||
/**
|
||||
* Maps the columns in the target table to the columns in the relation table.
|
||||
*/
|
||||
public $targetToRelationKeyColumns = array();
|
||||
public $relationToTargetKeyColumns = array();
|
||||
|
||||
/**
|
||||
* List of aggregated column names on the join table.
|
||||
@ -105,46 +95,35 @@ class ManyToManyMapping extends AssociationMapping
|
||||
$joinColumn['name'] = trim($joinColumn['name'], '`');
|
||||
$joinColumn['quoted'] = true;
|
||||
}
|
||||
$this->sourceToRelationKeyColumns[$joinColumn['referencedColumnName']] = $joinColumn['name'];
|
||||
$this->relationToSourceKeyColumns[$joinColumn['name']] = $joinColumn['referencedColumnName'];
|
||||
$this->joinTableColumns[] = $joinColumn['name'];
|
||||
}
|
||||
$this->sourceKeyColumns = array_keys($this->sourceToRelationKeyColumns);
|
||||
|
||||
foreach ($mapping['joinTable']['inverseJoinColumns'] as &$inverseJoinColumn) {
|
||||
if ($inverseJoinColumn['name'][0] == '`') {
|
||||
$inverseJoinColumn['name'] = trim($inverseJoinColumn['name'], '`');
|
||||
$inverseJoinColumn['quoted'] = true;
|
||||
}
|
||||
$this->targetToRelationKeyColumns[$inverseJoinColumn['referencedColumnName']] = $inverseJoinColumn['name'];
|
||||
$this->relationToTargetKeyColumns[$inverseJoinColumn['name']] = $inverseJoinColumn['referencedColumnName'];
|
||||
$this->joinTableColumns[] = $inverseJoinColumn['name'];
|
||||
}
|
||||
$this->targetKeyColumns = array_keys($this->targetToRelationKeyColumns);
|
||||
}
|
||||
}
|
||||
|
||||
public function getJoinTableColumnNames()
|
||||
{
|
||||
return $this->joinTableColumns;
|
||||
//return array_merge(array_keys($this->relationToSourceKeyColumns), array_keys($this->relationToTargetKeyColumns));
|
||||
}
|
||||
|
||||
public function getRelationToSourceKeyColumns()
|
||||
{
|
||||
return $this->relationToSourceKeyColumns;
|
||||
}
|
||||
|
||||
public function getSourceToRelationKeyColumns()
|
||||
public function getRelationToTargetKeyColumns()
|
||||
{
|
||||
return $this->sourceToRelationKeyColumns;
|
||||
}
|
||||
|
||||
public function getTargetToRelationKeyColumns()
|
||||
{
|
||||
return $this->targetToRelationKeyColumns;
|
||||
}
|
||||
|
||||
public function getSourceKeyColumns()
|
||||
{
|
||||
return $this->sourceKeyColumns;
|
||||
}
|
||||
|
||||
public function getTargetKeyColumns()
|
||||
{
|
||||
return $this->targetKeyColumns;
|
||||
return $this->relationToTargetKeyColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,7 +140,7 @@ class ManyToManyMapping extends AssociationMapping
|
||||
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
|
||||
$joinTableConditions = array();
|
||||
if ($this->isOwningSide) {
|
||||
foreach ($this->sourceToRelationKeyColumns as $sourceKeyColumn => $relationKeyColumn) {
|
||||
foreach ($this->relationToSourceKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
|
||||
// getting id
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$joinTableConditions[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
@ -172,7 +151,7 @@ class ManyToManyMapping extends AssociationMapping
|
||||
} else {
|
||||
$owningAssoc = $em->getClassMetadata($this->targetEntityName)->associationMappings[$this->mappedByFieldName];
|
||||
// TRICKY: since the association is inverted source and target are flipped
|
||||
foreach ($owningAssoc->targetToRelationKeyColumns as $sourceKeyColumn => $relationKeyColumn) {
|
||||
foreach ($owningAssoc->relationToTargetKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
|
||||
// getting id
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$joinTableConditions[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
|
@ -162,11 +162,18 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
* Gets the class descriptor for the owning entity class.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @deprecated
|
||||
* @todo Remove
|
||||
*/
|
||||
public function getOwnerClass()
|
||||
{
|
||||
return $this->_typeClass;
|
||||
}
|
||||
|
||||
public function getTypeClass()
|
||||
{
|
||||
return $this->_typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
@ -430,13 +437,22 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
*/
|
||||
public function contains($element)
|
||||
{
|
||||
// TODO: Assuming the identity of entities in a collection is always based
|
||||
// on their primary key (there is no equals/hashCode in PHP),
|
||||
// if the collection is not initialized, we could issue a straight
|
||||
// SQL "SELECT 1" on the association (table) without initializing
|
||||
// the collection.
|
||||
|
||||
// TODO: Change to use PK identity, not php object identity!?
|
||||
/* DRAFT
|
||||
if ($this->_initialized) {
|
||||
return $this->_coll->contains($element);
|
||||
} else {
|
||||
if ($element is MANAGED) {
|
||||
if ($this->_coll->contains($element)) {
|
||||
return true;
|
||||
}
|
||||
$exists = check db for existence;
|
||||
if ($exists) {
|
||||
$this->_coll->add($element);
|
||||
}
|
||||
return $exists;
|
||||
}
|
||||
return false;
|
||||
}*/
|
||||
|
||||
$this->_initialize();
|
||||
return $this->_coll->contains($element);
|
||||
|
@ -48,13 +48,13 @@ abstract class AbstractCollectionPersister
|
||||
$this->_conn = $em->getConnection();
|
||||
}
|
||||
|
||||
public function recreate(PersistentCollection $coll)
|
||||
/*public function recreate(PersistentCollection $coll)
|
||||
{
|
||||
if ($coll->getRelation()->isInverseSide()) {
|
||||
return;
|
||||
}
|
||||
//...
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Deletes the persistent state represented by the given collection.
|
||||
@ -110,8 +110,8 @@ abstract class AbstractCollectionPersister
|
||||
}
|
||||
}
|
||||
|
||||
public function updateRows(PersistentCollection $coll)
|
||||
{}
|
||||
//public function updateRows(PersistentCollection $coll)
|
||||
//{}
|
||||
|
||||
public function insertRows(PersistentCollection $coll)
|
||||
{
|
||||
|
@ -78,8 +78,11 @@ class JoinedSubclassPersister extends StandardEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Gets the name of the table that owns the column the given field is mapped to.
|
||||
* Does only look upwards in the hierarchy, not downwards.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
* @override
|
||||
*/
|
||||
public function getOwningTable($fieldName)
|
||||
@ -372,4 +375,10 @@ class JoinedSubclassPersister extends StandardEntityPersister
|
||||
. $joinSql
|
||||
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '');
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _processSqlResult(array $sqlResult)
|
||||
{
|
||||
return $this->_processSqlResultInheritanceAware($sqlResult);
|
||||
}
|
||||
}
|
||||
|
@ -48,15 +48,12 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
* @internal Order of the parameters must be the same as the order of the columns in
|
||||
* _getDeleteRowSql.
|
||||
*/
|
||||
protected function _getDeleteRowSqlParameters(PersistentCollection $coll, $element)
|
||||
{
|
||||
$params = array_merge(
|
||||
$this->_uow->getEntityIdentifier($coll->getOwner()),
|
||||
$this->_uow->getEntityIdentifier($element)
|
||||
);
|
||||
//var_dump($params);
|
||||
return $params;
|
||||
return $this->_collectJoinTableColumnParameters($coll, $element);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,12 +68,14 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
* @internal Order of the parameters must be the same as the order of the columns in
|
||||
* _getInsertRowSql.
|
||||
*/
|
||||
protected function _getInsertRowSql(PersistentCollection $coll)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
$joinTable = $mapping->getJoinTable();
|
||||
$columns = $mapping->getJoinTableColumnNames();
|
||||
$columns = $mapping->joinTableColumns;
|
||||
return 'INSERT INTO ' . $joinTable['name'] . ' (' . implode(', ', $columns) . ')'
|
||||
. ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
|
||||
}
|
||||
@ -85,16 +84,52 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
* @internal Order of the parameters must be the same as the order of the columns in
|
||||
* _getInsertRowSql.
|
||||
*/
|
||||
protected function _getInsertRowSqlParameters(PersistentCollection $coll, $element)
|
||||
{
|
||||
// FIXME: This is still problematic for composite keys because we silently
|
||||
// rely on a specific ordering of the columns.
|
||||
$params = array_merge(
|
||||
$this->_uow->getEntityIdentifier($coll->getOwner()),
|
||||
$this->_uow->getEntityIdentifier($element)
|
||||
);
|
||||
//var_dump($params);
|
||||
return $this->_collectJoinTableColumnParameters($coll, $element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the parameters for inserting/deleting on the join table in the order
|
||||
* of the join table columns as specified in ManyToManyMapping#joinTableColumns.
|
||||
*
|
||||
* @param $coll
|
||||
* @param $element
|
||||
* @return array
|
||||
*/
|
||||
private function _collectJoinTableColumnParameters(PersistentCollection $coll, $element)
|
||||
{
|
||||
$params = array();
|
||||
$mapping = $coll->getMapping();
|
||||
$isComposite = count($mapping->joinTableColumns) > 2;
|
||||
|
||||
$identifier1 = $this->_uow->getEntityIdentifier($coll->getOwner());
|
||||
$identifier2 = $this->_uow->getEntityIdentifier($element);
|
||||
|
||||
if ($isComposite) {
|
||||
$class1 = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||
$class2 = $coll->getTypeClass();
|
||||
}
|
||||
|
||||
foreach ($mapping->joinTableColumns as $joinTableColumn) {
|
||||
if (isset($mapping->relationToSourceKeyColumns[$joinTableColumn])) {
|
||||
if ($isComposite) {
|
||||
$params[] = $identifier1[$class1->fieldNames[$mapping->relationToSourceKeyColumns[$joinTableColumn]]];
|
||||
} else {
|
||||
$params[] = array_pop($identifier1);
|
||||
}
|
||||
} else {
|
||||
if ($isComposite) {
|
||||
$params[] = $identifier2[$class2->fieldNames[$mapping->relationToTargetKeyColumns[$joinTableColumn]]];
|
||||
} else {
|
||||
$params[] = array_pop($identifier2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
@ -108,7 +143,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
$mapping = $coll->getMapping();
|
||||
$joinTable = $mapping->getJoinTable();
|
||||
$whereClause = '';
|
||||
foreach ($mapping->sourceToRelationKeyColumns as $relationColumn) {
|
||||
foreach ($mapping->relationToSourceKeyColumns as $relationColumn => $srcColumn) {
|
||||
if ($whereClause !== '') $whereClause .= ' AND ';
|
||||
$whereClause .= "$relationColumn = ?";
|
||||
}
|
||||
@ -119,11 +154,23 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
* @internal Order of the parameters must be the same as the order of the columns in
|
||||
* _getDeleteSql.
|
||||
*/
|
||||
protected function _getDeleteSqlParameters(PersistentCollection $coll)
|
||||
{
|
||||
//FIXME: This is still problematic for composite keys because we silently
|
||||
// rely on a specific ordering of the columns.
|
||||
return $this->_uow->getEntityIdentifier($coll->getOwner());
|
||||
$params = array();
|
||||
$mapping = $coll->getMapping();
|
||||
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
|
||||
if (count($mapping->relationToSourceKeyColumns) > 1) {
|
||||
$sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner()));
|
||||
foreach ($mapping->relationToSourceKeyColumns as $relColumn => $srcColumn) {
|
||||
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
|
||||
}
|
||||
} else {
|
||||
$params[] = array_pop($identifier);
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
@ -21,6 +21,8 @@
|
||||
|
||||
namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
/**
|
||||
* Persister for entities that participate in a hierarchy mapped with the
|
||||
* SINGLE_TABLE strategy.
|
||||
@ -44,4 +46,39 @@ class SingleTablePersister extends StandardEntityPersister
|
||||
$this->_class->discriminatorValue;
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _getSelectColumnList()
|
||||
{
|
||||
$columnList = parent::_getSelectColumnList();
|
||||
// Append discriminator column
|
||||
$columnList .= ', ' . $this->_class->getQuotedDiscriminatorColumnName($this->_platform);
|
||||
///$tableAlias = $this->_class->getQuotedTableName($this->_platform);
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
// Append subclass columns
|
||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||
if ( ! isset($mapping['inherited'])) {
|
||||
$columnList .= ', ' . $subClass->getQuotedColumnName($fieldName, $this->_platform);
|
||||
}
|
||||
}
|
||||
|
||||
// Append subclass foreign keys
|
||||
foreach ($subClass->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide && $assoc->isOneToOne() && ! isset($subClass->inheritedAssociationFields[$assoc->sourceFieldName])) {
|
||||
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
|
||||
$columnList .= ', ' /*. $tableAlias . '.'*/ . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $columnList;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _processSqlResult(array $sqlResult)
|
||||
{
|
||||
return $this->_processSqlResultInheritanceAware($sqlResult);
|
||||
}
|
||||
}
|
@ -21,13 +21,11 @@
|
||||
|
||||
namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\Common\DoctrineException,
|
||||
Doctrine\ORM\ORMException,
|
||||
use Doctrine\ORM\ORMException,
|
||||
Doctrine\Common\Collections\ArrayCollection,
|
||||
Doctrine\DBAL\Connection,
|
||||
Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\UnitOfWork,
|
||||
Doctrine\ORM\Query,
|
||||
Doctrine\ORM\PersistentCollection,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
@ -43,6 +41,7 @@ use Doctrine\Common\DoctrineException,
|
||||
* @version $Revision: 3406 $
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @todo Rename: BasicEntityPersister
|
||||
*/
|
||||
class StandardEntityPersister
|
||||
{
|
||||
@ -53,13 +52,6 @@ class StandardEntityPersister
|
||||
*/
|
||||
protected $_class;
|
||||
|
||||
/**
|
||||
* The name of the entity the persister is used for.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_entityName;
|
||||
|
||||
/**
|
||||
* The Connection instance.
|
||||
*
|
||||
@ -101,7 +93,6 @@ class StandardEntityPersister
|
||||
$this->_em = $em;
|
||||
$this->_conn = $em->getConnection();
|
||||
$this->_platform = $this->_conn->getDatabasePlatform();
|
||||
$this->_entityName = $class->name;
|
||||
$this->_class = $class;
|
||||
}
|
||||
|
||||
@ -189,10 +180,10 @@ class StandardEntityPersister
|
||||
$versionField = $this->_class->versionField;
|
||||
$identifier = $this->_class->getIdentifierColumnNames();
|
||||
$versionFieldColumnName = $this->_class->getColumnName($versionField);
|
||||
|
||||
//FIXME: Order with composite keys might not be correct
|
||||
$sql = "SELECT " . $versionFieldColumnName . " FROM " . $class->getQuotedTableName($this->_platform) .
|
||||
" WHERE " . implode(' = ? AND ', $identifier) . " = ?";
|
||||
$value = $this->_conn->fetchColumn($sql, (array) $id);
|
||||
$value = $this->_conn->fetchColumn($sql, array_values($id));
|
||||
$this->_class->setFieldValue($entity, $versionField, $value);
|
||||
}
|
||||
|
||||
@ -347,15 +338,13 @@ class StandardEntityPersister
|
||||
if (isset($this->_class->associationMappings[$field])) {
|
||||
$assocMapping = $this->_class->associationMappings[$field];
|
||||
// Only owning side of x-1 associations can have a FK column.
|
||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
if ( ! $assocMapping->isOneToOne() || ! $assocMapping->isOwningSide) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: One-one self-referencing of the same class.
|
||||
if ($newVal !== null /*&& $assocMapping->sourceEntityName == $assocMapping->targetEntityName*/) {
|
||||
|
||||
if ($newVal !== null) {
|
||||
$oid = spl_object_hash($newVal);
|
||||
$isScheduledForInsert = $uow->isScheduledForInsert($newVal);
|
||||
if (isset($this->_queuedInserts[$oid]) || $isScheduledForInsert) {
|
||||
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
|
||||
// The associated entity $newVal is not yet persisted, so we must
|
||||
// set $newVal = null, in order to insert a null value and schedule an
|
||||
// extra update on the UnitOfWork.
|
||||
@ -366,15 +355,19 @@ class StandardEntityPersister
|
||||
}
|
||||
}
|
||||
|
||||
if ($newVal !== null) {
|
||||
$newValId = $uow->getEntityIdentifier($newVal);
|
||||
}
|
||||
|
||||
$targetClass = $this->_em->getClassMetadata($assocMapping->targetEntityName);
|
||||
$owningTable = $this->getOwningTable($field);
|
||||
|
||||
foreach ($assocMapping->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
$quotedSourceColumn = $assocMapping->getQuotedJoinColumnName($sourceColumn, $this->_platform);
|
||||
if ($newVal === null) {
|
||||
$result[$this->getOwningTable($field)][$quotedSourceColumn] = null;
|
||||
$result[$owningTable][$quotedSourceColumn] = null;
|
||||
} else {
|
||||
$otherClass = $this->_em->getClassMetadata($assocMapping->targetEntityName);
|
||||
$result[$this->getOwningTable($field)][$quotedSourceColumn] =
|
||||
$otherClass->reflFields[$otherClass->fieldNames[$targetColumn]]
|
||||
->getValue($newVal);
|
||||
$result[$owningTable][$quotedSourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
|
||||
}
|
||||
}
|
||||
} else if ($newVal === null) {
|
||||
@ -426,7 +419,7 @@ class StandardEntityPersister
|
||||
* @param array $id The identifier of the entity as an associative array from column names to values.
|
||||
* @param object $entity The entity to refresh.
|
||||
*/
|
||||
public function refresh(array $id, $entity)
|
||||
final public function refresh(array $id, $entity)
|
||||
{
|
||||
$stmt = $this->_conn->prepare($this->_getSelectEntitiesSql($id));
|
||||
$stmt->execute(array_values($id));
|
||||
@ -550,7 +543,6 @@ class StandardEntityPersister
|
||||
$stmt = $this->_conn->prepare($this->_getSelectManyToManyEntityCollectionSql($assoc, $criteria));
|
||||
$stmt->execute(array_values($criteria));
|
||||
while ($result = $stmt->fetch(Connection::FETCH_ASSOC)) {
|
||||
//$coll->add($this->_createEntity($result));
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
@ -570,38 +562,48 @@ class StandardEntityPersister
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $joinColumnValues = array();
|
||||
$entityName = $this->_entityName;
|
||||
|
||||
foreach ($result as $column => $value) {
|
||||
$column = $this->_class->resultColumnNames[$column];
|
||||
if (isset($this->_class->fieldNames[$column])) {
|
||||
$fieldName = $this->_class->fieldNames[$column];
|
||||
$data[$fieldName] = Type::getType($this->_class->fieldMappings[$fieldName]['type'])
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
} else if ($this->_class->discriminatorColumn !== null && $column == $this->_class->discriminatorColumn['name']) {
|
||||
$entityName = $this->_class->discriminatorMap[$value];
|
||||
} else {
|
||||
$data[$column] = $value;
|
||||
$joinColumnValues[$column] = $value;
|
||||
}
|
||||
}
|
||||
list($entityName, $data) = $this->_processSqlResult($result);
|
||||
|
||||
if ($entity !== null) {
|
||||
$hints[Query::HINT_REFRESH] = true;
|
||||
$id = array();
|
||||
if ($this->_class->isIdentifierComposite) {
|
||||
foreach ($this->_class->identifier as $fieldName) {
|
||||
$id[] = $data[$fieldName];
|
||||
$id[$fieldName] = $data[$fieldName];
|
||||
}
|
||||
} else {
|
||||
$id = array($data[$this->_class->identifier[0]]);
|
||||
$id = array($this->_class->identifier[0] => $data[$this->_class->identifier[0]]);
|
||||
}
|
||||
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
|
||||
}
|
||||
|
||||
return $this->_em->getUnitOfWork()->createEntity($entityName, $data, $hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an SQL result set row that contains data for an entity of the type
|
||||
* this persister is responsible for.
|
||||
*
|
||||
* @param array $sqlResult The SQL result set row to process.
|
||||
* @return array A tuple where the first value is the actual type of the entity and
|
||||
* the second value the data of the entity.
|
||||
*/
|
||||
protected function _processSqlResult(array $sqlResult)
|
||||
{
|
||||
$data = array();
|
||||
foreach ($sqlResult as $column => $value) {
|
||||
$column = $this->_class->resultColumnNames[$column];
|
||||
if (isset($this->_class->fieldNames[$column])) {
|
||||
$field = $this->_class->fieldNames[$column];
|
||||
$data[$field] = Type::getType($this->_class->fieldMappings[$field]['type'])
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
} else {
|
||||
$data[$column] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return array($this->_class->name, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SELECT SQL to select one or more entities by a set of field criteria.
|
||||
@ -611,23 +613,6 @@ class StandardEntityPersister
|
||||
*/
|
||||
protected function _getSelectEntitiesSql(array &$criteria, $assoc = null)
|
||||
{
|
||||
$columnList = '';
|
||||
|
||||
// Add regular columns to select list
|
||||
foreach ($this->_class->fieldNames as $field) {
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||
}
|
||||
|
||||
// Add join columns (foreign keys) to select list
|
||||
foreach ($this->_class->associationMappings as $assoc2) {
|
||||
if ($assoc2->isOwningSide && $assoc2->isOneToOne()) {
|
||||
foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
|
||||
$columnList .= ', ' . $assoc2->getQuotedJoinColumnName($srcColumn, $this->_platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct WHERE conditions
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
@ -647,11 +632,39 @@ class StandardEntityPersister
|
||||
$conditionSql .= ' = ?';
|
||||
}
|
||||
|
||||
return 'SELECT ' . $columnList
|
||||
return 'SELECT ' . $this->_getSelectColumnList()
|
||||
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform)
|
||||
. ($conditionSql ? ' WHERE ' . $conditionSql : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL fragment with the list of columns to select when querying for
|
||||
* a entity of the type of this persister.
|
||||
*
|
||||
* @return string The SQL fragment.
|
||||
*/
|
||||
protected function _getSelectColumnList()
|
||||
{
|
||||
$columnList = '';
|
||||
|
||||
// Add regular columns to select list
|
||||
foreach ($this->_class->fieldNames as $field) {
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||
}
|
||||
|
||||
// Add join columns (foreign keys) to select list
|
||||
foreach ($this->_class->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
|
||||
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
|
||||
$columnList .= ', ' . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $columnList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL to select a collection of entities in a many-many association.
|
||||
*
|
||||
@ -678,16 +691,16 @@ class StandardEntityPersister
|
||||
|
||||
if ($manyToMany->isOwningSide) {
|
||||
$owningAssoc = $manyToMany;
|
||||
$joinClauses = $manyToMany->targetToRelationKeyColumns;
|
||||
$joinClauses = $manyToMany->relationToTargetKeyColumns;
|
||||
} else {
|
||||
$owningAssoc = $this->_em->getClassMetadata($manyToMany->targetEntityName)->associationMappings[$manyToMany->mappedByFieldName];
|
||||
$joinClauses = $owningAssoc->sourceToRelationKeyColumns;
|
||||
$joinClauses = $owningAssoc->relationToSourceKeyColumns;
|
||||
}
|
||||
|
||||
$joinTableName = $owningAssoc->getQuotedJoinTableName($this->_platform);
|
||||
|
||||
$joinSql = '';
|
||||
foreach ($joinClauses as $sourceColumn => $joinTableColumn) {
|
||||
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
||||
if ($joinSql != '') $joinSql .= ' AND ';
|
||||
$joinSql .= $this->_class->getQuotedTableName($this->_platform) .
|
||||
'.' . $this->_class->getQuotedColumnName($this->_class->fieldNames[$sourceColumn], $this->_platform) . ' = '
|
||||
@ -710,4 +723,50 @@ class StandardEntityPersister
|
||||
. $joinSql
|
||||
. ' WHERE ' . $conditionSql;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
final protected function _processSqlResultInheritanceAware(array $sqlResult)
|
||||
{
|
||||
$data = array();
|
||||
$entityName = $this->_class->name;
|
||||
foreach ($sqlResult as $column => $value) {
|
||||
$column = $this->_class->resultColumnNames[$column];
|
||||
if (($class = $this->_findDeclaringClass($column)) !== false) {
|
||||
$field = $class->fieldNames[$column];
|
||||
$data[$field] = Type::getType($class->fieldMappings[$field]['type'])
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
} else if ($column == $this->_class->discriminatorColumn['name']) {
|
||||
$entityName = $this->_class->discriminatorMap[$value];
|
||||
} else {
|
||||
$data[$column] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return array($entityName, $data);
|
||||
}
|
||||
|
||||
private function _findDeclaringClass($column)
|
||||
{
|
||||
static $cache = array();
|
||||
|
||||
if (isset($cache[$column])) {
|
||||
return $cache[$column];
|
||||
}
|
||||
|
||||
if (isset($this->_class->fieldNames[$column])) {
|
||||
$cache[$column] = $this->_class;
|
||||
return $this->_class;
|
||||
}
|
||||
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
if (isset($subClass->fieldNames[$column])) {
|
||||
$cache[$column] = $subClass;
|
||||
return $subClass;
|
||||
}
|
||||
}
|
||||
|
||||
$cache[$column] = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,28 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Proxy;
|
||||
|
||||
/**
|
||||
* Marker interface for proxy classes.
|
||||
* Interface for proxy classes.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
|
@ -208,12 +208,12 @@ final class Query extends AbstractQuery
|
||||
|
||||
$paramMappings = $this->_parserResult->getParameterMappings();
|
||||
|
||||
if(count($paramMappings) != count($params)) {
|
||||
if (count($paramMappings) != count($params)) {
|
||||
throw QueryException::invalidParameterNumber();
|
||||
}
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
if(!isset($paramMappings[$key])) {
|
||||
if ( ! isset($paramMappings[$key])) {
|
||||
throw QueryException::unknownParameter($key);
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ class SqlWalker implements TreeWalker
|
||||
}
|
||||
}
|
||||
|
||||
// LEFT JOIN subclass tables, only if partial objects disallowed
|
||||
// LEFT JOIN subclass tables, if partial objects disallowed
|
||||
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
||||
foreach ($class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
@ -327,7 +327,7 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= $AST->orderByClause ? $this->walkOrderByClause($AST->orderByClause) : '';
|
||||
|
||||
$q = $this->getQuery();
|
||||
$sql = $this->getConnection()->getDatabasePlatform()->modifyLimitQuery(
|
||||
$sql = $this->_platform->modifyLimitQuery(
|
||||
$sql, $q->getMaxResults(), $q->getFirstResult()
|
||||
);
|
||||
|
||||
@ -678,13 +678,13 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= $assoc->getQuotedJoinTableName($this->_platform) . ' ' . $joinTableAlias . ' ON ';
|
||||
|
||||
if ($relation->isOwningSide) {
|
||||
foreach ($assoc->sourceToRelationKeyColumns as $sourceColumn => $relationColumn) {
|
||||
foreach ($assoc->relationToSourceKeyColumns as $relationColumn => $sourceColumn) {
|
||||
$sql .= $sourceTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform)
|
||||
. ' = '
|
||||
. $joinTableAlias . '.' . $assoc->getQuotedJoinColumnName($relationColumn, $this->_platform);
|
||||
}
|
||||
} else {
|
||||
foreach ($assoc->targetToRelationKeyColumns as $targetColumn => $relationColumn) {
|
||||
foreach ($assoc->relationToTargetKeyColumns as $relationColumn => $targetColumn) {
|
||||
$sql .= $sourceTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform)
|
||||
. ' = '
|
||||
. $joinTableAlias . '.' . $assoc->getQuotedJoinColumnName($relationColumn, $this->_platform);
|
||||
@ -697,13 +697,13 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
|
||||
|
||||
if ($relation->isOwningSide) {
|
||||
foreach ($assoc->targetToRelationKeyColumns as $targetColumn => $relationColumn) {
|
||||
foreach ($assoc->relationToTargetKeyColumns as $relationColumn => $targetColumn) {
|
||||
$sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform)
|
||||
. ' = '
|
||||
. $joinTableAlias . '.' . $assoc->getQuotedJoinColumnName($relationColumn, $this->_platform);
|
||||
}
|
||||
} else {
|
||||
foreach ($assoc->sourceToRelationKeyColumns as $sourceColumn => $relationColumn) {
|
||||
foreach ($assoc->relationToSourceKeyColumns as $relationColumn => $sourceColumn) {
|
||||
$sql .= $targetTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform)
|
||||
. ' = '
|
||||
. $joinTableAlias . '.' . $assoc->getQuotedJoinColumnName($relationColumn, $this->_platform);
|
||||
@ -787,7 +787,7 @@ class SqlWalker implements TreeWalker
|
||||
$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
} else {
|
||||
// IdentificationVariable
|
||||
// $expr == IdentificationVariable
|
||||
$dqlAlias = $expr;
|
||||
$queryComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $queryComp['metadata'];
|
||||
|
@ -23,7 +23,6 @@ namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection,
|
||||
Doctrine\Common\Collections\Collection,
|
||||
Doctrine\Common\DoctrineException,
|
||||
Doctrine\Common\NotifyPropertyChanged,
|
||||
Doctrine\Common\PropertyChangedListener,
|
||||
Doctrine\ORM\Event\LifecycleEventArgs,
|
||||
@ -405,6 +404,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->_scheduledForDirtyCheck[$className] : $entities;
|
||||
|
||||
foreach ($entitiesToProcess as $entity) {
|
||||
// Ignore uninitialized proxy objects
|
||||
if ($entity instanceof Proxy && ! $entity->__isInitialized__()) {
|
||||
continue;
|
||||
}
|
||||
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here.
|
||||
$oid = spl_object_hash($entity);
|
||||
if ( ! isset($this->_entityInsertions[$oid]) && isset($this->_entityStates[$oid])) {
|
||||
@ -580,7 +583,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$idValue = $idGen->generate($this->_em, $entry);
|
||||
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||
if ( ! $idGen instanceof \Doctrine\ORM\Id\Assigned) {
|
||||
$this->_entityIdentifiers[$oid] = array($idValue);
|
||||
$this->_entityIdentifiers[$oid] = array($targetClass->identifier[0] => $idValue);
|
||||
$targetClass->getSingleIdReflectionProperty()->setValue($entry, $idValue);
|
||||
} else {
|
||||
$this->_entityIdentifiers[$oid] = $idValue;
|
||||
@ -601,7 +604,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
} else if ($state == self::STATE_REMOVED) {
|
||||
throw DoctrineException::removedEntityInCollectionDetected();
|
||||
throw ORMException::removedEntityInCollectionDetected($entity, $assoc);
|
||||
}
|
||||
// MANAGED associated entities are already taken into account
|
||||
// during changeset calculation anyway, since they are in the identity map.
|
||||
@ -700,7 +703,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$oid = spl_object_hash($entity);
|
||||
$idField = $class->identifier[0];
|
||||
$class->reflFields[$idField]->setValue($entity, $id);
|
||||
$this->_entityIdentifiers[$oid] = array($id);
|
||||
$this->_entityIdentifiers[$oid] = array($idField => $id);
|
||||
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||
$this->_originalEntityData[$oid][$idField] = $id;
|
||||
$this->addToIdentityMap($entity);
|
||||
@ -1198,7 +1201,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ( ! $idGen->isPostInsertGenerator()) {
|
||||
$idValue = $idGen->generate($this->_em, $entity);
|
||||
if ( ! $idGen instanceof \Doctrine\ORM\Id\Assigned) {
|
||||
$this->_entityIdentifiers[$oid] = array($idValue);
|
||||
$this->_entityIdentifiers[$oid] = array($class->identifier[0] => $idValue);
|
||||
$class->setIdentifierValues($entity, $idValue);
|
||||
} else {
|
||||
$this->_entityIdentifiers[$oid] = $idValue;
|
||||
@ -1359,7 +1362,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$id = $targetClass->getIdentifierValues($other);
|
||||
$proxy = $this->_em->getProxyFactory()->getProxy($assoc2->targetEntityName, $id);
|
||||
$prop->setValue($managedCopy, $proxy);
|
||||
$this->registerManaged($proxy, (array)$id, array());
|
||||
$this->registerManaged($proxy, $id, array());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1701,12 +1704,12 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ($class->isIdentifierComposite) {
|
||||
$id = array();
|
||||
foreach ($class->identifier as $fieldName) {
|
||||
$id[] = $data[$fieldName];
|
||||
$id[$fieldName] = $data[$fieldName];
|
||||
}
|
||||
$idHash = implode(' ', $id);
|
||||
} else {
|
||||
$id = array($data[$class->identifier[0]]);
|
||||
$idHash = $id[0];
|
||||
$idHash = $data[$class->identifier[0]];
|
||||
$id = array($class->identifier[0] => $idHash);
|
||||
}
|
||||
|
||||
if (isset($this->_identityMap[$class->rootEntityName][$idHash])) {
|
||||
@ -1754,7 +1757,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $srcColumn) {
|
||||
$joinColumnValue = $data[$srcColumn];
|
||||
if ($joinColumnValue !== null) {
|
||||
$associatedId[$targetColumn] = $joinColumnValue;
|
||||
$associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
|
||||
}
|
||||
}
|
||||
if ( ! $associatedId) {
|
||||
|
@ -20,6 +20,7 @@ class AllTests
|
||||
$suite = new \Doctrine\Tests\OrmFunctionalTestSuite('Doctrine Orm Functional');
|
||||
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\BasicFunctionalTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\DefaultValuesTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\AdvancedAssociationTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\NativeQueryTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\SingleTableInheritanceTest');
|
||||
|
@ -509,4 +509,37 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
"select count(u.id) from Doctrine\Tests\Models\CMS\CmsUser u")
|
||||
->getSingleScalarResult());
|
||||
}
|
||||
|
||||
//DRAFT OF EXPECTED/DESIRED BEHAVIOR
|
||||
/*public function testPersistentCollectionContainsDoesNeverInitialize()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
$user->username = 'gblanco';
|
||||
$user->status = 'developer';
|
||||
|
||||
$group = new CmsGroup;
|
||||
$group->name = 'Developers';
|
||||
|
||||
$user->addGroup($group);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$group = $this->_em->find(get_class($group), $group->getId());
|
||||
|
||||
|
||||
|
||||
$user2 = new CmsUser;
|
||||
$user2->id = $user->getId();
|
||||
$this->assertFalse($group->getUsers()->contains($user2));
|
||||
$this->assertFalse($group->getUsers()->isInitialized());
|
||||
|
||||
$user2 = $this->_em->getReference(get_class($user), $user->getId());
|
||||
$this->assertTrue($group->getUsers()->contains($user2));
|
||||
$this->assertFalse($group->getUsers()->isInitialized());
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->assertSame($related2, $related2->getCTIParent()->getRelated());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
127
tests/Doctrine/Tests/ORM/Functional/DefaultValuesTest.php
Normal file
127
tests/Doctrine/Tests/ORM/Functional/DefaultValuesTest.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
/**
|
||||
* Tests basic operations on entities with default values.
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\DefaultValueUser'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\DefaultValueAddress')
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
// Swallow all exceptions. We do not test the schema tool here.
|
||||
}
|
||||
}
|
||||
|
||||
public function testSimpleDetachMerge() {
|
||||
$user = new DefaultValueUser;
|
||||
$user->name = 'romanb';
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$userId = $user->id; // e.g. from $_REQUEST
|
||||
$user2 = $this->_em->getReference(get_class($user), $userId);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->assertFalse($user2->__isInitialized__());
|
||||
|
||||
$a = new DefaultValueAddress;
|
||||
$a->country = 'de';
|
||||
$a->zip = '12345';
|
||||
$a->city = 'Berlin';
|
||||
$a->street = 'Sesamestreet';
|
||||
|
||||
$a->user = $user2;
|
||||
$this->_em->persist($a);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertFalse($user2->__isInitialized__());
|
||||
$this->_em->clear();
|
||||
|
||||
$a2 = $this->_em->find(get_class($a), $a->id);
|
||||
$this->assertTrue($a2->getUser() instanceof DefaultValueUser);
|
||||
$this->assertEquals($userId, $a2->getUser()->getId());
|
||||
$this->assertEquals('Poweruser', $a2->getUser()->type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Entity @Table(name="defaultvalueuser")
|
||||
*/
|
||||
class DefaultValueUser
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @Column(type="string")
|
||||
*/
|
||||
public $name = '';
|
||||
/**
|
||||
* @Column(type="string")
|
||||
*/
|
||||
public $type = 'Poweruser';
|
||||
/**
|
||||
* @OneToOne(targetEntity="DefaultValueAddress", mappedBy="user", cascade={"persist"})
|
||||
*/
|
||||
public $address;
|
||||
|
||||
public function getId() {return $this->id;}
|
||||
}
|
||||
|
||||
/**
|
||||
* CmsAddress
|
||||
*
|
||||
* @Entity @Table(name="defaultvalueaddresses")
|
||||
*/
|
||||
class DefaultValueAddress
|
||||
{
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
* @Id @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @Column(type="string", length=50)
|
||||
*/
|
||||
public $country;
|
||||
|
||||
/**
|
||||
* @Column(type="string", length=50)
|
||||
*/
|
||||
public $zip;
|
||||
|
||||
/**
|
||||
* @Column(type="string", length=50)
|
||||
*/
|
||||
public $city;
|
||||
|
||||
/**
|
||||
* Testfield for Schema Updating Tests.
|
||||
*/
|
||||
public $street;
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DefaultValueUser")
|
||||
* @JoinColumn(name="user_id", referencedColumnName="id")
|
||||
*/
|
||||
public $user;
|
||||
|
||||
public function getUser() {return $this->user;}
|
||||
}
|
@ -137,6 +137,24 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertNull($result[0]['e_related_entity_id']);
|
||||
$this->assertEquals('child', $result[0]['e_discr']);
|
||||
}
|
||||
|
||||
public function testPolymorphicFind()
|
||||
{
|
||||
$child = new ChildEntity;
|
||||
$child->setData('thedata');
|
||||
$child->setNumber(1234);
|
||||
|
||||
$this->_em->persist($child);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$child2 = $this->_em->find('Doctrine\Tests\ORM\Functional\ParentEntity', $child->getId());
|
||||
|
||||
$this->assertTrue($child2 instanceof ChildEntity);
|
||||
$this->assertEquals('thedata', $child2->getData());
|
||||
$this->assertSame(1234, $child2->getNumber());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,7 +56,7 @@ class TestUtil
|
||||
// Connect to tmpdb in order to drop and create the real test db.
|
||||
$tmpConn = \Doctrine\DBAL\DriverManager::getConnection($tmpDbParams);
|
||||
$realConn = \Doctrine\DBAL\DriverManager::getConnection($realDbParams);
|
||||
|
||||
|
||||
$dbname = $realConn->getDatabase();
|
||||
$realConn->close();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user