1
0
mirror of synced 2025-02-22 07:03:13 +03:00

[DDC-408][DDC-1150][DDC-1277] Implemented support to parameter expanding on associations.

This commit is contained in:
Guilherme Blanco 2011-08-13 21:28:54 -03:00
parent e13720c33d
commit 63a2f02f4d
3 changed files with 199 additions and 45 deletions

View File

@ -833,15 +833,11 @@ class ClassMetadataInfo implements ClassMetadata
// Cascades // Cascades
$cascades = isset($mapping['cascade']) ? array_map('strtolower', $mapping['cascade']) : array(); $cascades = isset($mapping['cascade']) ? array_map('strtolower', $mapping['cascade']) : array();
if (in_array('all', $cascades)) { if (in_array('all', $cascades)) {
$cascades = array( $cascades = array('remove', 'persist', 'refresh', 'merge', 'detach');
'remove',
'persist',
'refresh',
'merge',
'detach'
);
} }
$mapping['cascade'] = $cascades; $mapping['cascade'] = $cascades;
$mapping['isCascadeRemove'] = in_array('remove', $cascades); $mapping['isCascadeRemove'] = in_array('remove', $cascades);
$mapping['isCascadePersist'] = in_array('persist', $cascades); $mapping['isCascadePersist'] = in_array('persist', $cascades);

View File

@ -26,6 +26,7 @@ use PDO,
Doctrine\ORM\ORMException, Doctrine\ORM\ORMException,
Doctrine\ORM\OptimisticLockException, Doctrine\ORM\OptimisticLockException,
Doctrine\ORM\EntityManager, Doctrine\ORM\EntityManager,
Doctrine\ORM\UnitOfWork,
Doctrine\ORM\Query, Doctrine\ORM\Query,
Doctrine\ORM\PersistentCollection, Doctrine\ORM\PersistentCollection,
Doctrine\ORM\Mapping\MappingException, Doctrine\ORM\Mapping\MappingException,
@ -1224,6 +1225,7 @@ class BasicEntityPersister
} else { } else {
throw ORMException::unrecognizedField($field); throw ORMException::unrecognizedField($field);
} }
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?'); $conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
} }
return $conditionSql; return $conditionSql;
@ -1313,18 +1315,96 @@ class BasicEntityPersister
continue; // skip null values. continue; // skip null values.
} }
$type = null; $types[] = $this->getType($field, $value);
if (isset($this->_class->fieldMappings[$field])) { $params[] = $this->getValue($value);
}
return array($params, $types);
}
/**
* Infer field type to be used by parameter type casting.
*
* @param string $field
* @param mixed $value
* @return integer
*/
private function getType($field, $value)
{
switch (true) {
case (isset($this->_class->fieldMappings[$field])):
$type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType(); $type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType();
} break;
if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET; case (isset($this->_class->associationMappings[$field])):
$assoc = $this->_class->associationMappings[$field];
if (count($assoc['sourceToTargetKeyColumns']) > 1) {
throw Query\QueryException::associationPathCompositeKeyNotSupported();
}
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
$targetColumn = $assoc['joinColumns'][0]['referencedColumnName'];
$type = null;
if (isset($targetClass->fieldNames[$targetColumn])) {
$type = Type::getType($targetClass->fieldMappings[$targetClass->fieldNames[$targetColumn]]['type'])->getBindingType();
}
break;
default:
$type = null;
}
if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET;
}
return $type;
}
/**
* Retrieve parameter value
*
* @param mixed $value
* @return mixed
*/
private function getValue($value)
{
if (is_array($value)) {
$newValue = array();
foreach ($value as $itemValue) {
$newValue[] = $this->getIndividualValue($itemValue);
} }
$params[] = $value; return $newValue;
$types[] = $type;
} }
return array($params, $types);
return $this->getIndividualValue($value);
}
/**
* Retrieve an invidiual parameter value
*
* @param mixed $value
* @return mixed
*/
private function getIndividualValue($value)
{
if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) {
if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
$idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
} else {
$class = $this->_em->getClassMetadata(get_class($value));
$idValues = $class->getIdentifierValues($value);
}
$value = $idValues[key($idValues)];
}
return $value;
} }
/** /**

View File

@ -3,8 +3,8 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\CMS\CmsUser; use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsAddress; use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
@ -18,6 +18,12 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
parent::setUp(); parent::setUp();
} }
public function tearDown()
{
$this->_em->getConfiguration()->setEntityNamespaces(array());
parent::tearDown();
}
public function loadFixture() public function loadFixture()
{ {
$user = new CmsUser; $user = new CmsUser;
@ -33,14 +39,67 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($user2); $this->_em->persist($user2);
$this->_em->flush(); $this->_em->flush();
$user1Id = $user->getId(); $user1Id = $user->getId();
unset($user); unset($user);
unset($user2); unset($user2);
$this->_em->clear(); $this->_em->clear();
return $user1Id; return $user1Id;
} }
public function loadAssociatedFixture()
{
$address = new CmsAddress();
$address->city = "Berlin";
$address->country = "Germany";
$address->street = "Foostreet";
$address->zip = "12345";
$user = new CmsUser();
$user->name = 'Roman';
$user->username = 'romanb';
$user->status = 'freak';
$user->setAddress($address);
$this->_em->persist($user);
$this->_em->persist($address);
$this->_em->flush();
$this->_em->clear();
return array($user->id, $address->id);
}
public function buildUser($name, $username, $status, $address)
{
$user = new CmsUser();
$user->name = $name;
$user->username = $username;
$user->status = $status;
$user->setAddress($address);
$this->_em->persist($user);
$this->_em->flush();
return $user;
}
public function buildAddress($country, $city, $street, $zip)
{
$address = new CmsAddress();
$address->country = $country;
$address->city = $city;
$address->street = $street;
$address->zip = $zip;
$this->_em->persist($address);
$this->_em->flush();
return $address;
}
public function testBasicFind() public function testBasicFind()
{ {
$user1Id = $this->loadFixture(); $user1Id = $this->loadFixture();
@ -64,6 +123,53 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals('dev', $users[0]->status); $this->assertEquals('dev', $users[0]->status);
} }
public function testFindByAssociationWithIntegerAsParameter()
{
$address1 = $this->buildAddress('Germany', 'Berlim', 'Foo st.', '123456');
$user1 = $this->buildUser('Benjamin', 'beberlei', 'dev', $address1);
$address2 = $this->buildAddress('Brazil', 'São Paulo', 'Bar st.', '654321');
$user2 = $this->buildUser('Guilherme', 'guilhermeblanco', 'freak', $address2);
$address3 = $this->buildAddress('USA', 'Nashville', 'Woo st.', '321654');
$user3 = $this->buildUser('Jonathan', 'jwage', 'dev', $address3);
unset($address1);
unset($address2);
unset($address3);
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
$addresses = $repository->findBy(array('user' => array($user1->getId(), $user2->getId())));
$this->assertEquals(2, count($addresses));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress',$addresses[0]);
}
public function testFindByAssociationWithObjectAsParameter()
{
$address1 = $this->buildAddress('Germany', 'Berlim', 'Foo st.', '123456');
$user1 = $this->buildUser('Benjamin', 'beberlei', 'dev', $address1);
$address2 = $this->buildAddress('Brazil', 'São Paulo', 'Bar st.', '654321');
$user2 = $this->buildUser('Guilherme', 'guilhermeblanco', 'freak', $address2);
$address3 = $this->buildAddress('USA', 'Nashville', 'Woo st.', '321654');
$user3 = $this->buildUser('Jonathan', 'jwage', 'dev', $address3);
unset($address1);
unset($address2);
unset($address3);
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
$addresses = $repository->findBy(array('user' => array($user1, $user2)));
$this->assertEquals(2, count($addresses));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress',$addresses[0]);
}
public function testFindFieldByMagicCall() public function testFindFieldByMagicCall()
{ {
@ -99,12 +205,6 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(2, count($users)); $this->assertEquals(2, count($users));
} }
public function tearDown()
{
$this->_em->getConfiguration()->setEntityNamespaces(array());
parent::tearDown();
}
/** /**
* @expectedException \Doctrine\ORM\ORMException * @expectedException \Doctrine\ORM\ORMException
*/ */
@ -201,28 +301,6 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$repos->foo(); $repos->foo();
} }
public function loadAssociatedFixture()
{
$address = new CmsAddress();
$address->city = "Berlin";
$address->country = "Germany";
$address->street = "Foostreet";
$address->zip = "12345";
$user = new CmsUser();
$user->name = 'Roman';
$user->username = 'romanb';
$user->status = 'freak';
$user->setAddress($address);
$this->_em->persist($user);
$this->_em->persist($address);
$this->_em->flush();
$this->_em->clear();
return array($user->id, $address->id);
}
/** /**
* @group DDC-817 * @group DDC-817
*/ */