Rebase to master
This commit is contained in:
parent
0dbd742588
commit
160b07d1e3
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user