1
0
mirror of synced 2025-01-18 14:31:40 +03:00

Merge branch 'master' of github.com:doctrine/doctrine2

This commit is contained in:
Guilherme Blanco 2011-06-09 15:43:37 -03:00
commit fdbc909bde
19 changed files with 645 additions and 41 deletions

View File

@ -232,6 +232,7 @@
<php minimum_version="5.3.0" />
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
</dependencies>
<ignore>bin</ignore>
<ignore>Doctrine/Common/</ignore>
<ignore>Doctrine/DBAL/</ignore>
<ignore>Doctrine/ORM/</ignore>
@ -254,6 +255,7 @@
<php minimum_version="5.3.0" />
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
</dependencies>
<ignore>bin</ignore>
<ignore>Doctrine/Common/</ignore>
<ignore>Doctrine/DBAL/</ignore>
<ignore>Doctrine/ORM/</ignore>

View File

@ -47,9 +47,13 @@ class AssignedGenerator extends AbstractIdGenerator
if ($class->isIdentifierComposite) {
$idFields = $class->getIdentifierFieldNames();
foreach ($idFields as $idField) {
$value = $class->getReflectionProperty($idField)->getValue($entity);
$value = $class->reflFields[$idField]->getValue($entity);
if (isset($value)) {
if (is_object($value)) {
if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
throw ORMException::entityMissingForeignAssignedId($entity, $value);
}
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
} else {
@ -64,6 +68,10 @@ class AssignedGenerator extends AbstractIdGenerator
$value = $class->reflFields[$idField]->getValue($entity);
if (isset($value)) {
if (is_object($value)) {
if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
throw ORMException::entityMissingForeignAssignedId($entity, $value);
}
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
} else {

View File

@ -325,7 +325,8 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
if (!$class->discriminatorColumn) {
throw MappingException::missingDiscriminatorColumn($class->name);
}
} else if ($class->isMappedSuperclass && (count($class->discriminatorMap) || $class->discriminatorColumn)) {
} else if ($class->isMappedSuperclass && $class->name == $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) {
// second condition is necessary for mapped superclasses in the middle of an inheritance hierachy
throw MappingException::noInheritanceOnMappedSuperClass($class->name);
}

View File

@ -356,9 +356,6 @@ class XmlDriver extends AbstractFileDriver
$joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement->{'join-column'});
} else if (isset($manyToOneElement->{'join-columns'})) {
foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
if (!isset($joinColumnElement['name'])) {
$joinColumnElement['name'] = $name;
}
$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
}
}

View File

@ -34,10 +34,25 @@ class ORMException extends Exception
return new self("It's a requirement to specify a Metadata Driver and pass it ".
"to Doctrine\ORM\Configuration::setMetadataDriverImpl().");
}
public static function entityMissingForeignAssignedId($entity, $relatedEntity)
{
return new self(
"Entity of type " . get_class($entity) . " has identity through a foreign entity " . get_class($relatedEntityClass) . ", " .
"however this entity has no ientity itself. You have to call EntityManager#persist() on the related entity " .
"and make sure it an identifier was generated before trying to persist '" . get_class($entity) . "'. In case " .
"of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call " .
"EntityManager#flush() between both persist operations."
);
}
public static function entityMissingAssignedId($entity)
{
return new self("Entity of type " . get_class($entity) . " is missing an assigned ID.");
return new self("Entity of type " . get_class($entity) . " is missing an assigned ID. " .
"The identifier generation strategy for this entity requires the ID field to be populated before ".
"EntityManager#persist() is called. If you want automatically generated identifiers instead " .
"you need to adjust the metadata mapping accordingly."
);
}
public static function unrecognizedField($field)

View File

@ -269,7 +269,8 @@ class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy
$this->_entityPersister = $entityPersister;
$this->_identifier = $identifier;
}
private function __load()
/** @private */
public function __load()
{
if (!$this->__isInitialized__ && $this->_entityPersister) {
$this->__isInitialized__ = true;
@ -279,7 +280,7 @@ class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy
unset($this->_entityPersister, $this->_identifier);
}
}
<methods>
public function __sleep()

View File

@ -135,4 +135,10 @@ class QueryException extends \Doctrine\ORM\ORMException
"in the query."
);
}
public static function instanceOfUnrelatedClass($className, $rootClass)
{
return new self("Cannot check if a child of '" . $rootClass . "' is instanceof '" . $className . "', " .
"inheritance hierachy exists between these two classes.");
}
}

View File

@ -1657,6 +1657,10 @@ class SqlWalker implements TreeWalker
$sql .= $this->_conn->quote($class->discriminatorValue);
} else {
$discrMap = array_flip($class->discriminatorMap);
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
}
$sql .= $this->_conn->quote($discrMap[$entityClassName]);
}

View File

@ -137,8 +137,7 @@ EOT
$toType = strtolower($input->getArgument('to-type'));
$cme = new ClassMetadataExporter();
$exporter = $cme->getExporter($toType, $destPath);
$exporter = $this->getExporter($toType, $destPath);
$exporter->setOverwriteExistingFiles( ($input->getOption('force') !== false) );
if ($toType == 'annotation') {
@ -167,4 +166,11 @@ EOT
$output->write('No Metadata Classes to process.' . PHP_EOL);
}
}
protected function getExporter($toType, $destPath)
{
$cme = new ClassMetadataExporter();
return $cme->getExporter($toType, $destPath);
}
}

View File

@ -120,22 +120,30 @@ class PhpExporter extends AbstractExporter
$associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray);
} else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
$method = 'mapOneToMany';
$oneToManyMappingArray = array(
'mappedBy' => $associationMapping['mappedBy'],
'orphanRemoval' => $associationMapping['orphanRemoval'],
'orderBy' => $associationMapping['orderBy']
$method = 'mapOneToMany';
$potentialAssociationMappingIndexes = array(
'mappedBy',
'orphanRemoval',
'orderBy',
);
foreach ($potentialAssociationMappingIndexes as $index) {
if (isset($associationMapping[$index])) {
$oneToManyMappingArray[$index] = $associationMapping[$index];
}
}
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
} else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
$method = 'mapManyToMany';
$manyToManyMappingArray = array(
'mappedBy' => $associationMapping['mappedBy'],
'joinTable' => $associationMapping['joinTable'],
'orderBy' => $associationMapping['orderBy']
$method = 'mapManyToMany';
$potentialAssociationMappingIndexes = array(
'mappedBy',
'joinTable',
'orderBy',
);
foreach ($potentialAssociationMappingIndexes as $index) {
if (isset($associationMapping[$index])) {
$manyToManyMappingArray[$index] = $associationMapping[$index];
}
}
$associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray);
}

View File

@ -43,7 +43,7 @@ class YamlExporter extends AbstractExporter
*
* TODO: Should this code be pulled out in to a toArray() method in ClassMetadata
*
* @param ClassMetadataInfo $metadata
* @param ClassMetadataInfo $metadata
* @return mixed $exported
*/
public function exportClassMetadata(ClassMetadataInfo $metadata)
@ -84,9 +84,9 @@ class YamlExporter extends AbstractExporter
if (isset($metadata->table['uniqueConstraints'])) {
$array['uniqueConstraints'] = $metadata->table['uniqueConstraints'];
}
$fieldMappings = $metadata->fieldMappings;
$ids = array();
foreach ($fieldMappings as $name => $fieldMapping) {
$fieldMapping['column'] = $fieldMapping['columnName'];
@ -94,7 +94,7 @@ class YamlExporter extends AbstractExporter
$fieldMapping['columnName'],
$fieldMapping['fieldName']
);
if ($fieldMapping['column'] == $name) {
unset($fieldMapping['column']);
}
@ -111,7 +111,7 @@ class YamlExporter extends AbstractExporter
if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
$ids[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $this->_getIdGeneratorTypeString($metadata->generatorType);
}
if ($ids) {
$array['fields'] = $ids;
}
@ -145,7 +145,7 @@ class YamlExporter extends AbstractExporter
'targetEntity' => $associationMapping['targetEntity'],
'cascade' => $cascade,
);
if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
$joinColumns = $associationMapping['joinColumns'];
$newJoinColumns = array();
@ -164,7 +164,7 @@ class YamlExporter extends AbstractExporter
'joinColumns' => $newJoinColumns,
'orphanRemoval' => $associationMapping['orphanRemoval'],
);
$associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray);
$array['oneToOne'][$name] = $associationMappingArray;
} else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
@ -172,7 +172,7 @@ class YamlExporter extends AbstractExporter
'mappedBy' => $associationMapping['mappedBy'],
'inversedBy' => $associationMapping['inversedBy'],
'orphanRemoval' => $associationMapping['orphanRemoval'],
'orderBy' => $associationMapping['orderBy']
'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
);
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
@ -182,9 +182,9 @@ class YamlExporter extends AbstractExporter
'mappedBy' => $associationMapping['mappedBy'],
'inversedBy' => $associationMapping['inversedBy'],
'joinTable' => $associationMapping['joinTable'],
'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
);
$associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray);
$array['manyToMany'][$name] = $associationMappingArray;
}

View File

@ -746,7 +746,7 @@ class UnitOfWork implements PropertyChangedListener
$hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate);
foreach ($this->entityUpdates as $oid => $entity) {
if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) {
if (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className) {
if ($hasPreUpdateLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity);
@ -759,7 +759,9 @@ class UnitOfWork implements PropertyChangedListener
);
}
$persister->update($entity);
if ($this->entityChangeSets[$oid]) {
$persister->update($entity);
}
unset($this->entityUpdates[$oid]);
if ($hasPostUpdateLifecycleCallbacks) {
@ -786,7 +788,7 @@ class UnitOfWork implements PropertyChangedListener
$hasListeners = $this->evm->hasListeners(Events::postRemove);
foreach ($this->entityDeletions as $oid => $entity) {
if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) {
if (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className) {
$persister->delete($entity);
unset(
$this->entityDeletions[$oid],
@ -1290,6 +1292,10 @@ class UnitOfWork implements PropertyChangedListener
}
$visited[$oid] = $entity; // mark visited
// Cascade first, because scheduleForDelete() removes the entity from the identity map, which
// can cause problems when a lazy proxy has to be initialized for the cascade operation.
$this->cascadeRemove($entity, $visited);
$class = $this->em->getClassMetadata(get_class($entity));
$entityState = $this->getEntityState($entity);
@ -1313,7 +1319,6 @@ class UnitOfWork implements PropertyChangedListener
throw new UnexpectedValueException("Unexpected entity state: $entityState.");
}
$this->cascadeRemove($entity, $visited);
}
/**
@ -1674,6 +1679,7 @@ class UnitOfWork implements PropertyChangedListener
if ( ! $assoc['isCascadePersist']) {
continue;
}
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if (($relatedEntities instanceof Collection || is_array($relatedEntities))) {
if ($relatedEntities instanceof PersistentCollection) {
@ -1702,7 +1708,11 @@ class UnitOfWork implements PropertyChangedListener
if ( ! $assoc['isCascadeRemove']) {
continue;
}
//TODO: If $entity instanceof Proxy => Initialize ?
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
$entity->__load();
}
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection || is_array($relatedEntities)) {
// If its a PersistentCollection initialization is intended! No unwrap!
@ -1865,8 +1875,8 @@ class UnitOfWork implements PropertyChangedListener
}
$id = array($class->identifier[0] => $idHash);
}
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
$entity = $this->identityMap[$class->rootEntityName][$idHash];
$oid = spl_object_hash($entity);
if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
@ -2255,7 +2265,7 @@ class UnitOfWork implements PropertyChangedListener
*/
public function clearEntityChangeSet($oid)
{
unset($this->entityChangeSets[$oid]);
$this->entityChangeSets[$oid] = array();
}
/* PropertyChangedListener implementation */
@ -2335,7 +2345,28 @@ class UnitOfWork implements PropertyChangedListener
{
return $this->collectionUpdates;
}
/**
* Helper method to initialize a lazy loading proxy or persistent collection.
*
* @param object
* @return void
*/
public function initializeObject($obj)
{
if ($obj instanceof Proxy) {
$obj->__load();
} else if ($obj instanceof PersistentCollection) {
$obj->initialize();
}
}
/**
* Helper method to show an object as string.
*
* @param object $obj
* @return string
*/
private static function objToStr($obj)
{
return method_exists($obj, '__toString') ? (string)$obj : get_class($obj).'@'.spl_object_hash($obj);

View File

@ -342,4 +342,19 @@ class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCa
$this->assertEquals('Developers_New1', $user->groups[0]->name);
$this->assertEquals('Developers_New2', $user->groups[1]->name);
}
/**
* @group DDC-733
*/
public function testInitializePersistentCollection()
{
$user = $this->addCmsUserGblancoWithGroups(2);
$this->_em->clear();
$user = $this->_em->find(get_class($user), $user->id);
$this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
$this->_em->getUnitOfWork()->initializeObject($user->groups);
$this->assertTrue($user->groups->isInitialized(), "Collection should be initialized after calling UnitOfWork::initializeObject()");
}
}

View File

@ -97,4 +97,37 @@ class ReferenceProxyTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertTrue($clone->isCloned);
$this->assertFalse($entity->isCloned);
}
/**
* @group DDC-733
*/
public function testInitializeProxy()
{
$id = $this->createProduct();
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$this->assertFalse($entity->__isInitialized__, "Pre-Condition: Object is unitialized proxy.");
$this->_em->getUnitOfWork()->initializeObject($entity);
$this->assertTrue($entity->__isInitialized__, "Should be initialized after called UnitOfWork::initializeObject()");
}
/**
* @group DDC-1163
*/
public function testInitializeChangeAndFlushProxy()
{
$id = $this->createProduct();
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$entity->setName('Doctrine 2 Cookbook');
$this->_em->flush();
$this->_em->clear();
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$this->assertEquals('Doctrine 2 Cookbook', $entity->getName());
}
}

View File

@ -0,0 +1,215 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1163
*/
class DDC1163Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163Product'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163SpecialProduct'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163ProxyHolder'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163Tag'),
));
}
public function testIssue()
{
$this->createSpecialProductAndProxyHolderReferencingIt();
$this->_em->clear();
$this->createProxyForSpecialProduct();
$this->setPropertyAndAssignTagToSpecialProduct();
// fails
$this->_em->flush();
}
private function createSpecialProductAndProxyHolderReferencingIt()
{
$specialProduct = new DDC1163SpecialProduct();
$this->_em->persist($specialProduct);
$proxyHolder = new DDC1163ProxyHolder();
$this->_em->persist($proxyHolder);
$proxyHolder->setSpecialProduct($specialProduct);
$this->_em->flush();
$this->productId = $specialProduct->getId();
$this->proxyHolderId = $proxyHolder->getId();
}
/**
* We want Doctrine to instantiate a lazy-load proxy for the previously created
* 'SpecialProduct' and register it.
*
* When Doctrine loads the 'ProxyHolder', it will do just that because the 'ProxyHolder'
* references the 'SpecialProduct'.
*/
private function createProxyForSpecialProduct()
{
/* @var $proxyHolder ProxyHolder */
$proxyHolder = $this->_em->find(__NAMESPACE__ . '\\DDC1163ProxyHolder', $this->proxyHolderId);
$this->assertInstanceOf(__NAMESPACE__.'\\DDC1163SpecialProduct', $proxyHolder->getSpecialProduct());
}
private function setPropertyAndAssignTagToSpecialProduct()
{
/* @var $specialProduct SpecialProduct */
$specialProduct = $this->_em->find(__NAMESPACE__ . '\\DDC1163SpecialProduct', $this->productId);
$this->assertInstanceOf(__NAMESPACE__.'\\DDC1163SpecialProduct', $specialProduct);
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $specialProduct);
$specialProduct->setSubclassProperty('foobar');
// this screams violation of law of demeter ;)
$this->assertEquals(
__NAMESPACE__.'\\DDC1163SpecialProduct',
$this->_em->getUnitOfWork()->getEntityPersister(get_class($specialProduct))->getClassMetadata()->name
);
$tag = new DDC1163Tag('Foo');
$this->_em->persist($tag);
$tag->setProduct($specialProduct);
}
}
/**
* @Entity
*/
class DDC1163ProxyHolder
{
/**
* @var int
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var SpecialProduct
* @OneToOne(targetEntity="DDC1163SpecialProduct")
*/
private $specialProduct;
public function getId()
{
return $this->id;
}
public function setSpecialProduct(DDC1163SpecialProduct $specialProduct)
{
$this->specialProduct = $specialProduct;
}
public function getSpecialProduct()
{
return $this->specialProduct;
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"special" = "DDC1163SpecialProduct"})
*/
abstract class DDC1163Product
{
/**
* @var int
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
public function getId()
{
return $this->id;
}
}
/**
* @Entity
*/
class DDC1163SpecialProduct extends DDC1163Product
{
/**
* @var string
* @Column(name="subclass_property", type="string", nullable=true)
*/
private $subclassProperty;
/**
* @param string $value
*/
public function setSubclassProperty($value)
{
$this->subclassProperty = $value;
}
}
/**
* @Entity
*/
class DDC1163Tag
{
/**
* @var int
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
* @Column(name="name", type="string")
*/
private $name;
/**
* @var Product
* @ManyToOne(targetEntity="DDC1163Product", inversedBy="tags")
* @JoinColumns({
* @JoinColumn(name="product_id", referencedColumnName="id")
* })
*/
private $product;
/**
* @param string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* @param Product $product
*/
public function setProduct(DDC1163Product $product)
{
$this->product = $product;
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
class DDC1181Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1181Hotel'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1181Booking'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1181Room'),
));
}
/**
* @group DDC-1181
*/
public function testIssue()
{
$hotel = new DDC1181Hotel();
$room1 = new DDC1181Room();
$room2 = new DDC1181Room();
$this->_em->persist($hotel);
$this->_em->persist($room1);
$this->_em->persist($room2);
$this->_em->flush();
$booking1 = new DDC1181Booking;
$booking1->hotel = $hotel;
$booking1->room = $room1;
$booking2 = new DDC1181Booking;
$booking2->hotel = $hotel;
$booking2->room = $room2;
$hotel->bookings[] = $booking1;
$hotel->bookings[] = $booking2;
$this->_em->persist($booking1);
$this->_em->persist($booking2);
$this->_em->flush();
$this->_em->remove($hotel);
$this->_em->flush();
}
}
/**
* @Entity
*/
class DDC1181Hotel
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/**
* @oneToMany(targetEntity="DDC1181Booking", mappedBy="hotel", cascade={"remove"})
* @var Booking[]
*/
public $bookings;
}
/**
* @Entity
*/
class DDC1181Booking
{
/**
* @var Hotel
*
* @Id
* @ManyToOne(targetEntity="DDC1181Hotel", inversedBy="bookings")
* @JoinColumns({
* @JoinColumn(name="hotel_id", referencedColumnName="id")
* })
*/
public $hotel;
/**
* @var Room
*
* @Id
* @ManyToOne(targetEntity="DDC1181Room")
* @JoinColumns({
* @JoinColumn(name="room_id", referencedColumnName="id")
* })
*/
public $room;
}
/**
* @Entity
*/
class DDC1181Room
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
}

View File

@ -0,0 +1,93 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
use DateTime, Doctrine\DBAL\Types\Type;
class DDC1193Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1193Company'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1193Person'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1193Account')
));
}
/**
* @group DDC-1193
*/
public function testIssue()
{
$company = new DDC1193Company();
$person = new DDC1193Person();
$account = new DDC1193Account();
$person->account = $account;
$person->company = $company;
$company->member = $person;
$this->_em->persist($company);
$this->_em->flush();
$companyId = $company->id;
$accountId = $account->id;
$this->_em->clear();
$company = $this->_em->find(get_class($company), $companyId);
$this->assertTrue($this->_em->getUnitOfWork()->isInIdentityMap($company), "Company is in identity map.");
$this->assertFalse($company->member->__isInitialized__, "Pre-Condition");
$this->assertTrue($this->_em->getUnitOfWork()->isInIdentityMap($company->member), "Member is in identity map.");
$this->_em->remove($company);
$this->_em->flush();
$this->assertEquals(count($this->_em->getRepository(get_class($account))->findAll()), 0);
}
}
/** @Entity */
class DDC1193Company {
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
/** @OneToOne(targetEntity="DDC1193Person", cascade={"persist", "remove"}) */
public $member;
}
/** @Entity */
class DDC1193Person {
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
/**
* @OneToOne(targetEntity="DDC1193Account", cascade={"persist", "remove"})
*/
public $account;
}
/** @Entity */
class DDC1193Account {
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
}

View File

@ -184,6 +184,21 @@ class AnnotationDriverTest extends AbstractMappingDriverTest
$cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\AnnotationParent');
$this->assertEquals(array("postLoad" => array("postLoad"), "preUpdate" => array("preUpdate")), $cm->lifecycleCallbacks);
}
/**
* @group DDC-1156
*/
public function testMappedSuperclassInMiddleOfInheritanceHierachy()
{
$annotationDriver = $this->_loadDriver();
$em = $this->_getTestEntityManager();
$em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
$factory->setEntityManager($em);
$cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\ChildEntity');
}
}
/**
@ -264,4 +279,35 @@ class AnnotationParent
class AnnotationChild extends AnnotationParent
{
}
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorMap({"s"="SuperEntity", "c"="ChildEntity"})
*/
class SuperEntity
{
/** @Id @Column(type="string") */
private $id;
}
/**
* @MappedSuperclass
*/
class MiddleMappedSuperclass extends SuperEntity
{
/** @Column(type="string") */
private $name;
}
/**
* @Entity
*/
class ChildEntity extends MiddleMappedSuperclass
{
/**
* @Column(type="string")
*/
private $text;
}

View File

@ -383,6 +383,28 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr = 'employee'"
);
}
/**
* @group DDC-1194
*/
public function testSupportsInstanceOfExpressionsInWherePartPrefixedSlash()
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF \Doctrine\Tests\Models\Company\CompanyEmployee",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr = 'employee'"
);
}
/**
* @group DDC-1194
*/
public function testSupportsInstanceOfExpressionsInWherePartWithUnrelatedClass()
{
$this->assertInvalidSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF \Doctrine\Tests\Models\CMS\CmsUser",
"Doctrine\ORM\Query\QueryException"
);
}
public function testSupportsInstanceOfExpressionsInWherePartInDeeperLevel()
{