1
0
mirror of synced 2025-01-18 22:41:43 +03:00

Rebase to master

This commit is contained in:
Michaël Gallego 2013-12-22 16:30:46 +01:00
parent 0dbd742588
commit 160b07d1e3
2 changed files with 127 additions and 29 deletions

View File

@ -869,8 +869,14 @@ final class PersistentCollection implements Collection, Selectable
return $this->coll->matching($criteria);
}
if ($this->association['type'] !== ClassMetadata::ONE_TO_MANY) {
throw new \RuntimeException("Matching Criteria on PersistentCollection only works on OneToMany associations at the moment.");
if ($this->association['type'] !== ClassMetadata::ONE_TO_MANY
&& $this->association['type'] !== ClassMetadata::MANY_TO_MANY) {
throw new \RuntimeException("Matching Criteria on PersistentCollection only works on OneToMany and ManyToMany associations at the moment.");
}
if ($this->association['type'] === ClassMetadata::MANY_TO_MANY) {
$persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association);
return new ArrayCollection($persister->loadCriteria($this, $this->owner, $criteria));
}
$builder = Criteria::expr();

View File

@ -19,8 +19,10 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Query;
use Doctrine\ORM\UnitOfWork;
/**
@ -257,7 +259,11 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* @param \Doctrine\ORM\PersistentCollection $coll
* @param int $offset
* @param int|null $length
*
* @return array
*/
public function slice(PersistentCollection $coll, $offset, $length = null)
{
@ -276,7 +282,10 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* @param \Doctrine\ORM\PersistentCollection $coll
* @param object $element
*
* @return boolean
*/
public function contains(PersistentCollection $coll, $element)
{
@ -302,7 +311,10 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* @param \Doctrine\ORM\PersistentCollection $coll
* @param object $element
*
* @return boolean
*/
public function removeElement(PersistentCollection $coll, $element)
{
@ -485,29 +497,12 @@ class ManyToManyPersister extends AbstractCollectionPersister
return array('', '');
}
$conditions = array();
$association = $mapping;
if ( ! $mapping['isOwningSide']) {
$class = $this->em->getClassMetadata($mapping['targetEntity']);
$association = $class->associationMappings[$mapping['mappedBy']];
}
// A join is needed if there is filtering on the target entity
$tableName = $this->quoteStrategy->getTableName($rootClass, $this->platform);
$joinSql = ' JOIN ' . $tableName . ' te' . ' ON';
$joinColumns = $mapping['isOwningSide']
? $association['joinTable']['inverseJoinColumns']
: $association['joinTable']['joinColumns'];
$onConditions = $this->getOnConditionSQL($mapping);
foreach ($joinColumns as $joinColumn) {
$joinColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
$refColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
$conditions[] = ' t.' . $joinColumnName . ' = ' . 'te.' . $refColumnName;
}
$joinSql .= implode(' AND ', $conditions);
$joinSql .= implode(' AND ', $onConditions);
return array($joinSql, $filterSql);
}
@ -533,4 +528,101 @@ class ManyToManyPersister extends AbstractCollectionPersister
$sql = implode(' AND ', $filterClauses);
return $sql ? "(" . $sql . ")" : "";
}
/**
* Generate ON condition
*
* @param array $mapping
* @return array
*/
protected function getOnConditionSQL($mapping)
{
$association = $mapping;
if ( ! $mapping['isOwningSide']) {
$class = $this->em->getClassMetadata($mapping['targetEntity']);
$association = $class->associationMappings[$mapping['mappedBy']];
}
$targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
$joinColumns = $mapping['isOwningSide']
? $association['joinTable']['inverseJoinColumns']
: $association['joinTable']['joinColumns'];
$conditions = array();
foreach ($joinColumns as $joinColumn) {
$joinColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
$refColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
$conditions[] = ' t.' . $joinColumnName . ' = ' . 'te.' . $refColumnName;
}
return $conditions;
}
/**
* Loads Entities matching the given Criteria object.
*
* @param PersistentCollection $coll
* @param object $owner
* @param \Doctrine\Common\Collections\Criteria $criteria
* @return array
*/
public function loadCriteria(PersistentCollection $coll, $owner, Criteria $criteria)
{
list($quotedJoinTable, $whereClauses, $params) = $this->getJoinTableRestrictions($coll, $owner, true);
$parameters = $this->expandCriteriaParameters($criteria);
foreach ($parameters as $parameter) {
list($name, $value) = $parameter;
$whereClauses[] = sprintf("te.%s = ?", $name);
$params[] = $value;
}
$mapping = $coll->getMapping();
$targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
$tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform);
$onConditions = $this->getOnConditionSQL($mapping);
$sql = 'SELECT * FROM ' . $tableName . ' te'
. ' JOIN ' . $quotedJoinTable . ' ON'
. implode(' AND ', $onConditions)
. ' WHERE ' . implode(' AND ', $whereClauses);
$stmt = $this->conn->executeQuery($sql, $params);
$hydrator = $this->em->newHydrator(Query::HYDRATE_ARRAY);
$rsm = new Query\ResultSetMapping();
$rsm->addEntityResult($mapping['targetEntity'], 'r');
return $hydrator->hydrateAll($stmt, $rsm);
}
/**
* Expands Criteria Parameters by walking the expressions and grabbing all
* parameters and types from it.
*
* @param \Doctrine\Common\Collections\Criteria $criteria
*
* @return array(array(), array())
*/
private function expandCriteriaParameters(Criteria $criteria)
{
$expression = $criteria->getWhereExpression();
if ($expression === null) {
return array(array(), array());
}
$valueVisitor = new SqlValueVisitor();
$valueVisitor->dispatch($expression);
list($values, $types) = $valueVisitor->getParamsAndTypes();
return $types;
}
}