[DDC-408][DDC-1150][DDC-1277] Implemented support to parameter expanding on associations.
This commit is contained in:
parent
e13720c33d
commit
63a2f02f4d
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user