Permalink
Browse files

[DDC-408][DDC-1150][DDC-1277] Implemented support to parameter expand…

…ing on associations.
  • Loading branch information...
1 parent e13720c commit 63a2f02f4ddea1ab9191b0e4acfd1d790d2247c7 @guilhermeblanco guilhermeblanco committed Aug 14, 2011
@@ -833,15 +833,11 @@ protected function _validateAndCompleteAssociationMapping(array $mapping)
// 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 @@
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 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
} 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 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
} else {
throw ORMException::unrecognizedField($field);
}
+
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
}
return $conditionSql;
@@ -1313,18 +1315,96 @@ private function expandParameters($criteria)
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();
+ 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);
}
- if (is_array($value)) {
- $type += Connection::ARRAY_PARAM_OFFSET;
+
+ return $newValue;
+ }
+
+ 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);
}
- $params[] = $value;
- $types[] = $type;
+ $value = $idValues[key($idValues)];
}
- return array($params, $types);
+
+ 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 @@ protected function setUp() {
parent::setUp();
}
+ public function tearDown()
+ {
+ $this->_em->getConfiguration()->setEntityNamespaces(array());
+ parent::tearDown();
+ }
+
public function loadFixture()
{
$user = new CmsUser;
@@ -33,13 +39,66 @@ public function loadFixture()
$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 @@ public function testFindByField()
$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 @@ public function testFindByAlias()
$this->assertEquals(2, count($users));
}
- public function tearDown()
- {
- $this->_em->getConfiguration()->setEntityNamespaces(array());
- parent::tearDown();
- }
-
/**
* @expectedException \Doctrine\ORM\ORMException
*/
@@ -201,28 +301,6 @@ public function testInvalidMagicCall()
$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
*/

0 comments on commit 63a2f02

Please sign in to comment.