[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 = isset($mapping['cascade']) ? array_map('strtolower', $mapping['cascade']) : array();
|
||||
|
||||
if (in_array('all', $cascades)) {
|
||||
$cascades = array(
|
||||
'remove',
|
||||
'persist',
|
||||
'refresh',
|
||||
'merge',
|
||||
'detach'
|
||||
);
|
||||
$cascades = array('remove', 'persist', 'refresh', 'merge', 'detach');
|
||||
}
|
||||
|
||||
$mapping['cascade'] = $cascades;
|
||||
$mapping['isCascadeRemove'] = in_array('remove', $cascades);
|
||||
$mapping['isCascadePersist'] = in_array('persist', $cascades);
|
||||
|
@ -26,6 +26,7 @@ use PDO,
|
||||
Doctrine\ORM\ORMException,
|
||||
Doctrine\ORM\OptimisticLockException,
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\UnitOfWork,
|
||||
Doctrine\ORM\Query,
|
||||
Doctrine\ORM\PersistentCollection,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
@ -1213,7 +1214,7 @@ class BasicEntityPersister
|
||||
} else {
|
||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.';
|
||||
}
|
||||
|
||||
|
||||
$conditionSql .= $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
|
||||
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
|
||||
// very careless developers could potentially open up this normally hidden api for userland attacks,
|
||||
@ -1224,6 +1225,7 @@ class BasicEntityPersister
|
||||
} else {
|
||||
throw ORMException::unrecognizedField($field);
|
||||
}
|
||||
|
||||
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
|
||||
}
|
||||
return $conditionSql;
|
||||
@ -1313,18 +1315,96 @@ class BasicEntityPersister
|
||||
continue; // skip null values.
|
||||
}
|
||||
|
||||
$type = null;
|
||||
if (isset($this->_class->fieldMappings[$field])) {
|
||||
$types[] = $this->getType($field, $value);
|
||||
$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();
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$type += Connection::ARRAY_PARAM_OFFSET;
|
||||
break;
|
||||
|
||||
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;
|
||||
$types[] = $type;
|
||||
return $newValue;
|
||||
}
|
||||
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;
|
||||
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
@ -18,6 +18,12 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->_em->getConfiguration()->setEntityNamespaces(array());
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function loadFixture()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
@ -33,13 +39,66 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->persist($user2);
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$user1Id = $user->getId();
|
||||
|
||||
unset($user);
|
||||
unset($user2);
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
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()
|
||||
{
|
||||
@ -64,6 +123,53 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$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()
|
||||
{
|
||||
@ -99,12 +205,6 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals(2, count($users));
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->_em->getConfiguration()->setEntityNamespaces(array());
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Doctrine\ORM\ORMException
|
||||
*/
|
||||
@ -201,28 +301,6 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$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
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user