Commit 94d41dfb authored by romanb's avatar romanb

[2.0][DDC-279] Fixed.

parent 1ad982a4
...@@ -124,9 +124,9 @@ class EntityManager ...@@ -124,9 +124,9 @@ class EntityManager
private $_hydrators = array(); private $_hydrators = array();
/** /**
* The proxy factory which creates association or reference proxies. * The proxy factory used to create dynamic proxies.
* *
* @var ProxyFactory * @var Doctrine\ORM\Proxy\ProxyFactory
*/ */
private $_proxyFactory; private $_proxyFactory;
......
...@@ -4,7 +4,7 @@ namespace Doctrine\ORM\Event; ...@@ -4,7 +4,7 @@ namespace Doctrine\ORM\Event;
class LifecycleEventArgs extends \Doctrine\Common\EventArgs class LifecycleEventArgs extends \Doctrine\Common\EventArgs
{ {
private $_em; //private $_em;
private $_entity; private $_entity;
public function __construct($entity) public function __construct($entity)
...@@ -17,8 +17,10 @@ class LifecycleEventArgs extends \Doctrine\Common\EventArgs ...@@ -17,8 +17,10 @@ class LifecycleEventArgs extends \Doctrine\Common\EventArgs
return $this->_entity; return $this->_entity;
} }
/*
public function getEntityManager() public function getEntityManager()
{ {
return $this->_em; return $this->_em;
} }
*/
} }
\ No newline at end of file
...@@ -62,7 +62,6 @@ class ObjectHydrator extends AbstractHydrator ...@@ -62,7 +62,6 @@ class ObjectHydrator extends AbstractHydrator
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) { foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = array(); $this->_identifierMap[$dqlAlias] = array();
//$this->_resultPointers[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = ''; $this->_idTemplate[$dqlAlias] = '';
$class = $this->_em->getClassMetadata($className); $class = $this->_em->getClassMetadata($className);
...@@ -73,16 +72,26 @@ class ObjectHydrator extends AbstractHydrator ...@@ -73,16 +72,26 @@ class ObjectHydrator extends AbstractHydrator
// Remember which associations are "fetch joined", so that we know where to inject // Remember which associations are "fetch joined", so that we know where to inject
// collection stubs or proxies and where not. // collection stubs or proxies and where not.
if (isset($this->_rsm->relationMap[$dqlAlias])) { if (isset($this->_rsm->relationMap[$dqlAlias])) {
$targetClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]]; $sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
$targetClass = $this->_getClassMetadata($targetClassName); $sourceClass = $this->_getClassMetadata($sourceClassName);
$assoc = $targetClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]]; $assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
$this->_hints['fetched'][$assoc->sourceEntityName][$assoc->sourceFieldName] = true; $this->_hints['fetched'][$sourceClassName][$assoc->sourceFieldName] = true;
if ($sourceClass->subClasses) {
foreach ($sourceClass->subClasses as $sourceSubclassName) {
$this->_hints['fetched'][$sourceSubclassName][$assoc->sourceFieldName] = true;
}
}
if ($assoc->mappedByFieldName) { if ($assoc->mappedByFieldName) {
$this->_hints['fetched'][$assoc->targetEntityName][$assoc->mappedByFieldName] = true; $this->_hints['fetched'][$className][$assoc->mappedByFieldName] = true;
} else { } else {
if (isset($targetClass->inverseMappings[$className][$assoc->sourceFieldName])) { if (isset($sourceClass->inverseMappings[$className][$assoc->sourceFieldName])) {
$inverseAssoc = $targetClass->inverseMappings[$className][$assoc->sourceFieldName]; $inverseAssoc = $sourceClass->inverseMappings[$className][$assoc->sourceFieldName];
$this->_hints['fetched'][$assoc->targetEntityName][$inverseAssoc->sourceFieldName] = true; $this->_hints['fetched'][$className][$inverseAssoc->sourceFieldName] = true;
if ($class->subClasses) {
foreach ($class->subClasses as $targetSubclassName) {
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc->sourceFieldName] = true;
}
}
} }
} }
} }
......
...@@ -383,8 +383,9 @@ class AnnotationDriver implements Driver ...@@ -383,8 +383,9 @@ class AnnotationDriver implements Driver
} }
/** /**
* Whether the class with the specified name should have its metadata loaded. * Whether the class with the specified name is transient. Only non-transient
* This is only the case if it is annotated with either @Entity or * classes, that is entities and mapped superclasses, should have their metadata loaded.
* A class is non-transient if it is annotated with either @Entity or
* @MappedSuperclass in the class doc block. * @MappedSuperclass in the class doc block.
* *
* @param string $className * @param string $className
......
...@@ -121,4 +121,10 @@ class MappingException extends \Doctrine\ORM\ORMException ...@@ -121,4 +121,10 @@ class MappingException extends \Doctrine\ORM\ORMException
{ {
return new self('An error occurred in ' . $entity, 0, $previousException); return new self('An error occurred in ' . $entity, 0, $previousException);
} }
public static function joinColumnMustPointToMappedField($className, $joinColumn)
{
return new self('The column ' . $joinColumn . ' must be mapped to a field in class '
. $className . ' since it is referenced by a join column of another class.');
}
} }
\ No newline at end of file
...@@ -76,7 +76,7 @@ class OneToManyMapping extends AssociationMapping ...@@ -76,7 +76,7 @@ class OneToManyMapping extends AssociationMapping
{ {
parent::_validateAndCompleteMapping($mapping); parent::_validateAndCompleteMapping($mapping);
// one-side MUST be inverse (must have mappedBy) // OneToMany-side MUST be inverse (must have mappedBy)
if ( ! isset($mapping['mappedBy'])) { if ( ! isset($mapping['mappedBy'])) {
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']); throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
} }
......
...@@ -221,9 +221,16 @@ class OneToOneMapping extends AssociationMapping ...@@ -221,9 +221,16 @@ class OneToOneMapping extends AssociationMapping
$targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]->sourceFieldName $targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]->sourceFieldName
: false; : false;
// Mark inverse side as fetched in the hints, otherwise the UoW would
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
$hints = array(); $hints = array();
if ($inverseField) { if ($inverseField) {
$hints['fetched'][$targetClass->rootEntityName][$inverseField] = true; $hints['fetched'][$targetClass->name][$inverseField] = true;
if ($targetClass->subClasses) {
foreach ($targetClass->subClasses as $targetSubclassName) {
$hints['fetched'][$targetSubclassName][$inverseField] = true;
}
}
} }
/* cascade read-only status /* cascade read-only status
if ($em->getUnitOfWork()->isReadOnly($sourceEntity)) { if ($em->getUnitOfWork()->isReadOnly($sourceEntity)) {
...@@ -245,8 +252,9 @@ class OneToOneMapping extends AssociationMapping ...@@ -245,8 +252,9 @@ class OneToOneMapping extends AssociationMapping
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); $conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else { } else {
//TODO: Should never happen. Exception? throw MappingException::joinColumnMustPointToMappedField(
$conditions[$targetKeyColumn] = $joinColumnValues[$sourceKeyColumn]; $sourceClass->name, $sourceKeyColumn
);
} }
} }
...@@ -262,7 +270,7 @@ class OneToOneMapping extends AssociationMapping ...@@ -262,7 +270,7 @@ class OneToOneMapping extends AssociationMapping
} }
/** /**
* @internal Experimental. For MetaModel API, Doctrine 2.1. * @internal Experimental. For MetaModel API, Doctrine 2.1 or later.
*/ */
public static function __set_state(array $state) public static function __set_state(array $state)
{ {
......
...@@ -53,7 +53,7 @@ class StandardEntityPersister ...@@ -53,7 +53,7 @@ class StandardEntityPersister
protected $_class; protected $_class;
/** /**
* The Connection instance. * The underlying Connection of the used EntityManager.
* *
* @var Doctrine\DBAL\Connection $conn * @var Doctrine\DBAL\Connection $conn
*/ */
...@@ -289,28 +289,6 @@ class StandardEntityPersister ...@@ -289,28 +289,6 @@ class StandardEntityPersister
$this->_conn->delete($this->_class->primaryTable['name'], $id); $this->_conn->delete($this->_class->primaryTable['name'], $id);
} }
/**
* Adds an entity to delete.
*
* @param object $entity
* @todo Impl.
*/
public function addDelete($entity)
{
}
/**
* Executes all pending entity deletions.
*
* @see addDelete()
* @todo Impl.
*/
public function executeDeletions()
{
}
/** /**
* Gets the ClassMetadata instance of the entity class this persister is used for. * Gets the ClassMetadata instance of the entity class this persister is used for.
* *
...@@ -560,7 +538,7 @@ class StandardEntityPersister ...@@ -560,7 +538,7 @@ class StandardEntityPersister
} }
/** /**
* Loads a collection of entities into a one-to-many association. * Loads a collection of entities in a one-to-many association.
* *
* @param array $criteria The criteria by which to select the entities. * @param array $criteria The criteria by which to select the entities.
* @param PersistentCollection The collection to fill. * @param PersistentCollection The collection to fill.
......
...@@ -584,16 +584,16 @@ class QueryBuilder ...@@ -584,16 +584,16 @@ class QueryBuilder
* ->set('u.password', md5('password')) * ->set('u.password', md5('password'))
* ->where($or); * ->where($or);
* *
* @param mixed $where The WHERE statement * @param mixed $predicates The predicates.
* @return QueryBuilder $qb * @return QueryBuilder
*/ */
public function where($where) public function where($predicates)
{ {
if ( ! (func_num_args() == 1 && ($where instanceof Expr\Andx || $where instanceof Expr\Orx))) { if ( ! (func_num_args() == 1 && ($predicates instanceof Expr\Andx || $predicates instanceof Expr\Orx))) {
$where = new Expr\Andx(func_get_args()); $predicates = new Expr\Andx(func_get_args());
} }
return $this->add('where', $where); return $this->add('where', $predicates);
} }
/** /**
......
...@@ -1217,7 +1217,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1217,7 +1217,7 @@ class UnitOfWork implements PropertyChangedListener
break; break;
case self::STATE_DETACHED: case self::STATE_DETACHED:
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
"Behavior of save() for a detached entity is not yet defined."); "Behavior of persist() for a detached entity is not yet defined.");
case self::STATE_REMOVED: case self::STATE_REMOVED:
// Entity becomes managed again // Entity becomes managed again
if ($this->isScheduledForDelete($entity)) { if ($this->isScheduledForDelete($entity)) {
...@@ -1766,7 +1766,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1766,7 +1766,7 @@ class UnitOfWork implements PropertyChangedListener
if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) { if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
foreach ($class->associationMappings as $field => $assoc) { foreach ($class->associationMappings as $field => $assoc) {
// Check if the association is not among the fetch-joined associations already. // Check if the association is not among the fetch-joined associations already.
if (isset($hints['fetched'][$class->rootEntityName][$field])) { if (isset($hints['fetched'][$className][$field])) {
continue; continue;
} }
......
...@@ -10,9 +10,10 @@ class DDC279Test extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -10,9 +10,10 @@ class DDC279Test extends \Doctrine\Tests\OrmFunctionalTestCase
{ {
parent::setUp(); parent::setUp();
$this->_schemaTool->createSchema(array( $this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityXAbstract'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityX'), $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityX'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityY'), $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityY'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityZ') $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityZ'),
)); ));
} }
...@@ -39,34 +40,31 @@ class DDC279Test extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -39,34 +40,31 @@ class DDC279Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->flush(); $this->_em->flush();
$this->_em->clear(); $this->_em->clear();
$result = $this->_em->createQuery( $query = $this->_em->createQuery(
'SELECT x, y, z FROM Doctrine\Tests\ORM\Functional\Ticket\DDC279EntityX x '. 'SELECT x, y, z FROM Doctrine\Tests\ORM\Functional\Ticket\DDC279EntityX x '.
'INNER JOIN x.y y INNER JOIN y.z z WHERE x.id = 1' 'INNER JOIN x.y y INNER JOIN y.z z WHERE x.id = ?1'
)->getArrayResult(); )->setParameter(1, $x->id);
$expected = array( $result = $query->getResult();
0 => array(
'id' => 1, $expected1 = 'Y';
'data' => 'X', $expected2 = 'Z';
'y' => array(
'id' => 1, $this->assertEquals(1, count($result));
'data' => 'Y',
'z' => array( $this->assertEquals($expected1, $result[0]->y->data);
'id' => 1, $this->assertEquals($expected2, $result[0]->y->z->data);
'data' => 'Z',
)
),
),
);
$this->assertEquals($expected, $result);
} }
} }
/** /**
* @Entity * @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"DDC279EntityX" = "DDC279EntityX"})
*/ */
class DDC279EntityX abstract class DDC279EntityXAbstract
{ {
/** /**
* @Id * @Id
...@@ -80,8 +78,15 @@ class DDC279EntityX ...@@ -80,8 +78,15 @@ class DDC279EntityX
*/ */
public $data; public $data;
}
/**
* @Entity
*/
class DDC279EntityX extends DDC279EntityXAbstract
{
/** /**
* @OneToOne(targetEntity="Doctrine\Tests\ORM\Functional\Ticket\DDC279EntityY") * @OneToOne(targetEntity="DDC279EntityY")
* @JoinColumn(name="y_id", referencedColumnName="id") * @JoinColumn(name="y_id", referencedColumnName="id")
*/ */
public $y; public $y;
...@@ -105,7 +110,7 @@ class DDC279EntityY ...@@ -105,7 +110,7 @@ class DDC279EntityY
public $data; public $data;
/** /**
* @OneToOne(targetEntity="Doctrine\Tests\ORM\Functional\Ticket\DDC279EntityZ") * @OneToOne(targetEntity="DDC279EntityZ")
* @JoinColumn(name="z_id", referencedColumnName="id") * @JoinColumn(name="z_id", referencedColumnName="id")
*/ */
public $z; public $z;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment