1
0
mirror of synced 2025-01-18 22:41:43 +03:00

[2.0][DDC-279] Fixed.

This commit is contained in:
romanb 2010-01-29 21:24:29 +00:00
parent 1ad982a4fe
commit 94d41dfbdc
11 changed files with 85 additions and 76 deletions

View File

@ -124,9 +124,9 @@ class EntityManager
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;

View File

@ -4,7 +4,7 @@ namespace Doctrine\ORM\Event;
class LifecycleEventArgs extends \Doctrine\Common\EventArgs
{
private $_em;
//private $_em;
private $_entity;
public function __construct($entity)
@ -17,8 +17,10 @@ class LifecycleEventArgs extends \Doctrine\Common\EventArgs
return $this->_entity;
}
/*
public function getEntityManager()
{
return $this->_em;
}
*/
}

View File

@ -62,7 +62,6 @@ class ObjectHydrator extends AbstractHydrator
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = array();
//$this->_resultPointers[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = '';
$class = $this->_em->getClassMetadata($className);
@ -73,16 +72,26 @@ class ObjectHydrator extends AbstractHydrator
// Remember which associations are "fetch joined", so that we know where to inject
// collection stubs or proxies and where not.
if (isset($this->_rsm->relationMap[$dqlAlias])) {
$targetClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
$targetClass = $this->_getClassMetadata($targetClassName);
$assoc = $targetClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
$this->_hints['fetched'][$assoc->sourceEntityName][$assoc->sourceFieldName] = true;
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
$sourceClass = $this->_getClassMetadata($sourceClassName);
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
$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) {
$this->_hints['fetched'][$assoc->targetEntityName][$assoc->mappedByFieldName] = true;
$this->_hints['fetched'][$className][$assoc->mappedByFieldName] = true;
} else {
if (isset($targetClass->inverseMappings[$className][$assoc->sourceFieldName])) {
$inverseAssoc = $targetClass->inverseMappings[$className][$assoc->sourceFieldName];
$this->_hints['fetched'][$assoc->targetEntityName][$inverseAssoc->sourceFieldName] = true;
if (isset($sourceClass->inverseMappings[$className][$assoc->sourceFieldName])) {
$inverseAssoc = $sourceClass->inverseMappings[$className][$assoc->sourceFieldName];
$this->_hints['fetched'][$className][$inverseAssoc->sourceFieldName] = true;
if ($class->subClasses) {
foreach ($class->subClasses as $targetSubclassName) {
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc->sourceFieldName] = true;
}
}
}
}
}

View File

@ -383,8 +383,9 @@ class AnnotationDriver implements Driver
}
/**
* Whether the class with the specified name should have its metadata loaded.
* This is only the case if it is annotated with either @Entity or
* Whether the class with the specified name is transient. Only non-transient
* 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.
*
* @param string $className

View File

@ -121,4 +121,10 @@ class MappingException extends \Doctrine\ORM\ORMException
{
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.');
}
}

View File

@ -76,7 +76,7 @@ class OneToManyMapping extends AssociationMapping
{
parent::_validateAndCompleteMapping($mapping);
// one-side MUST be inverse (must have mappedBy)
// OneToMany-side MUST be inverse (must have mappedBy)
if ( ! isset($mapping['mappedBy'])) {
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
}

View File

@ -221,9 +221,16 @@ class OneToOneMapping extends AssociationMapping
$targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]->sourceFieldName
: 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();
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
if ($em->getUnitOfWork()->isReadOnly($sourceEntity)) {
@ -233,7 +240,7 @@ class OneToOneMapping extends AssociationMapping
$targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($joinColumnValues, $targetEntity, $this, $hints);
if ($targetEntity !== null && $inverseField && ! $targetClass->isCollectionValuedAssociation($inverseField)) {
if ($targetEntity !== null && $inverseField && ! $targetClass->isCollectionValuedAssociation($inverseField)) {
$targetClass->reflFields[$inverseField]->setValue($targetEntity, $sourceEntity);
}
} else {
@ -245,8 +252,9 @@ class OneToOneMapping extends AssociationMapping
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
//TODO: Should never happen. Exception?
$conditions[$targetKeyColumn] = $joinColumnValues[$sourceKeyColumn];
throw MappingException::joinColumnMustPointToMappedField(
$sourceClass->name, $sourceKeyColumn
);
}
}
@ -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)
{

View File

@ -53,7 +53,7 @@ class StandardEntityPersister
protected $_class;
/**
* The Connection instance.
* The underlying Connection of the used EntityManager.
*
* @var Doctrine\DBAL\Connection $conn
*/
@ -289,28 +289,6 @@ class StandardEntityPersister
$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.
*
@ -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 PersistentCollection The collection to fill.

View File

@ -584,16 +584,16 @@ class QueryBuilder
* ->set('u.password', md5('password'))
* ->where($or);
*
* @param mixed $where The WHERE statement
* @return QueryBuilder $qb
* @param mixed $predicates The predicates.
* @return QueryBuilder
*/
public function where($where)
public function where($predicates)
{
if ( ! (func_num_args() == 1 && ($where instanceof Expr\Andx || $where instanceof Expr\Orx))) {
$where = new Expr\Andx(func_get_args());
if ( ! (func_num_args() == 1 && ($predicates instanceof Expr\Andx || $predicates instanceof Expr\Orx))) {
$predicates = new Expr\Andx(func_get_args());
}
return $this->add('where', $where);
return $this->add('where', $predicates);
}
/**

View File

@ -1217,7 +1217,7 @@ class UnitOfWork implements PropertyChangedListener
break;
case self::STATE_DETACHED:
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:
// Entity becomes managed again
if ($this->isScheduledForDelete($entity)) {
@ -1766,10 +1766,10 @@ class UnitOfWork implements PropertyChangedListener
if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
foreach ($class->associationMappings as $field => $assoc) {
// Check if the association is not among the fetch-joined associations already.
if (isset($hints['fetched'][$class->rootEntityName][$field])) {
if (isset($hints['fetched'][$className][$field])) {
continue;
}
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
if ($assoc->isOneToOne()) {

View File

@ -10,9 +10,10 @@ class DDC279Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityXAbstract'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC279EntityX'),
$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
$this->_em->flush();
$this->_em->clear();
$result = $this->_em->createQuery(
$query = $this->_em->createQuery(
'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'
)->getArrayResult();
'INNER JOIN x.y y INNER JOIN y.z z WHERE x.id = ?1'
)->setParameter(1, $x->id);
$result = $query->getResult();
$expected1 = 'Y';
$expected2 = 'Z';
$expected = array(
0 => array(
'id' => 1,
'data' => 'X',
'y' => array(
'id' => 1,
'data' => 'Y',
'z' => array(
'id' => 1,
'data' => 'Z',
)
),
),
);
$this->assertEquals($expected, $result);
$this->assertEquals(1, count($result));
$this->assertEquals($expected1, $result[0]->y->data);
$this->assertEquals($expected2, $result[0]->y->z->data);
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"DDC279EntityX" = "DDC279EntityX"})
*/
class DDC279EntityX
abstract class DDC279EntityXAbstract
{
/**
* @Id
@ -80,8 +78,15 @@ class DDC279EntityX
*/
public $data;
}
/**
* @Entity
*/
class DDC279EntityX extends DDC279EntityXAbstract
{
/**
* @OneToOne(targetEntity="Doctrine\Tests\ORM\Functional\Ticket\DDC279EntityY")
* @OneToOne(targetEntity="DDC279EntityY")
* @JoinColumn(name="y_id", referencedColumnName="id")
*/
public $y;
@ -105,7 +110,7 @@ class DDC279EntityY
public $data;
/**
* @OneToOne(targetEntity="Doctrine\Tests\ORM\Functional\Ticket\DDC279EntityZ")
* @OneToOne(targetEntity="DDC279EntityZ")
* @JoinColumn(name="z_id", referencedColumnName="id")
*/
public $z;