1
0
mirror of synced 2025-02-20 22:23:14 +03:00

Abstracted infering binding types away in a helper

This commit is contained in:
Jasper N. Brouwer 2014-11-12 15:13:17 +01:00 committed by Marco Pivetta
parent 4f9f7eedf5
commit f7b14085f2
3 changed files with 157 additions and 111 deletions

View File

@ -25,6 +25,8 @@ use Doctrine\ORM\Persisters\SqlExpressionVisitor;
use Doctrine\ORM\Persisters\SqlValueVisitor;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Query;
use Doctrine\ORM\UnitOfWork;
use Doctrine\ORM\Utility\PersisterHelper as Helper;
/**
* Persister for many-to-many collections.
@ -384,7 +386,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
: $sourceClass->getFieldForColumn($columnName);
$params[] = $identifier[$field];
$types[] = $this->getType($field, $sourceClass);
$types[] = Helper::getTypeOfField($field, $sourceClass, $this->em);
}
return array($params, $types);

View File

@ -863,12 +863,12 @@ class BasicEntityPersister implements EntityPersister
list($params, $types) = $valueVisitor->getParamsAndTypes();
foreach ($params as $param) {
$sqlParams[] = $this->getValue($param);
$sqlParams[] = Helper::getValue($param, $this->em);
}
foreach ($types as $type) {
list($field, $value) = $type;
$sqlTypes[] = $this->getType($field, $value);
$sqlTypes[] = $this->getType($field, $value, $this->class);
}
return array($sqlParams, $sqlTypes);
@ -1306,13 +1306,14 @@ class BasicEntityPersister implements EntityPersister
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
foreach ($assoc['joinColumns'] as $joinColumn) {
$type = $this->getColumnType($joinColumn['referencedColumnName'], null, $targetClass);
$isIdentifier = isset($assoc['id']) && $assoc['id'] === true;
$quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
$resultColumnName = $this->getSQLColumnAlias($joinColumn['name']);
$columnList[] = $this->getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
. '.' . $quotedColumn . ' AS ' . $resultColumnName;
$type = Helper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em);
$this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type);
}
@ -1762,8 +1763,8 @@ class BasicEntityPersister implements EntityPersister
continue; // skip null values.
}
$types[] = $this->getType($field, $value);
$params[] = $this->getValue($value);
$types[] = $this->getType($field, $value, $this->class);
$params[] = Helper::getValue($value, $this->em);
}
return array($params, $types);
@ -1788,7 +1789,7 @@ class BasicEntityPersister implements EntityPersister
}
$types[] = $this->getType($criterion['field'], $criterion['value'], $criterion['class']);
$params[] = $this->getValue($criterion['value']);
$params[] = Helper::getValue($criterion['value'], $this->em);
}
return array($params, $types);
@ -1797,7 +1798,7 @@ class BasicEntityPersister implements EntityPersister
/**
* Infers the binding type of a field by parameter type casting.
*
* @param string $field
* @param string $fieldName
* @param mixed $value
* @param ClassMetadata|null $class
*
@ -1805,11 +1806,9 @@ class BasicEntityPersister implements EntityPersister
*
* @throws \Doctrine\ORM\Query\QueryException
*/
private function getType($field, $value, ClassMetadata $class = null)
private function getType($fieldName, $value, ClassMetadata $class)
{
if ($class === null) {
$class = $this->class;
}
$type = Helper::getTypeOfField($fieldName, $class, $this->em);
switch (true) {
case (isset($this->class->fieldMappings[$field])):
@ -1867,105 +1866,6 @@ class BasicEntityPersister implements EntityPersister
return $type;
}
/**
* Infers the binding type of a column by parameter type casting.
*
* @param string $columnName
* @param mixed $value
* @param ClassMetadata $class
* @return int|string|null
*/
private function getColumnType($columnName, $value, ClassMetadata $class)
{
$type = null;
switch (true) {
case (isset($class->fieldNames[$columnName])):
$fieldName = $class->fieldNames[$columnName];
if (isset($class->fieldMappings[$fieldName])) {
$type = $class->fieldMappings[$fieldName]['type'];
}
break;
default:
$type = $this->getAssociationColumnType($columnName, $class);
}
if (is_array($value)) {
$type = Type::getType($type)->getBindingType();
$type += Connection::ARRAY_PARAM_OFFSET;
}
return $type;
}
/**
* Infers the binding type of a column by traversing association mappings.
*
* @param string $columnName
* @param ClassMetadata $class
* @return string|null
*/
private function getAssociationColumnType($columnName, ClassMetadata $class)
{
foreach ($class->associationMappings as $assoc) {
foreach ($assoc['joinColumns'] as $joinColumn) {
if ($joinColumn['name'] == $columnName) {
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
$targetColumn = $joinColumn['referencedColumnName'];
if (isset($targetClass->fieldNames[$targetColumn])) {
return $targetClass->fieldMappings[$targetClass->fieldNames[$targetColumn]]['type'];
}
return $this->getAssociationColumnType($targetColumn, $class);
}
}
}
return null;
}
/**
* Retrieves parameter value.
*
* @param mixed $value
*
* @return mixed
*/
private function getValue($value)
{
if ( ! is_array($value)) {
return $this->getIndividualValue($value);
}
$newValue = array();
foreach ($value as $itemValue) {
$newValue[] = $this->getIndividualValue($itemValue);
}
return $newValue;
}
/**
* Retrieves an individual parameter value.
*
* @param mixed $value
*
* @return mixed
*/
private function getIndividualValue($value)
{
if ( ! is_object($value) || ! $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) {
return $value;
}
return $this->em->getUnitOfWork()->getSingleIdentifierValue($value);
}
/**
* {@inheritdoc}
*/

View File

@ -0,0 +1,144 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Utility;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\QueryException;
/**
* The PersisterHelper contains logic to infer binding types which is used in
* several persisters.
*
* @link www.doctrine-project.org
* @since 2.5
* @author Jasper N. Brouwer <jasper@nerdsweide.nl>
*/
class PersisterHelper
{
/**
* @param mixed $value
* @param EntityManagerInterface $em
*
* @return mixed
*/
public static function getValue($value, EntityManagerInterface $em)
{
if ( ! is_array($value)) {
return self::getIndividualValue($value, $em);
}
$newValue = array();
foreach ($value as $itemValue) {
$newValue[] = self::getIndividualValue($itemValue, $em);
}
return $newValue;
}
/**
* @param mixed $value
* @param EntityManagerInterface $em
*
* @return mixed
*/
private static function getIndividualValue($value, EntityManagerInterface $em)
{
if ( ! is_object($value) || ! $em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) {
return $value;
}
return $em->getUnitOfWork()->getSingleIdentifierValue($value);
}
/**
* @param string $fieldName
* @param ClassMetadata $class
* @param EntityManagerInterface $em
*
* @throws QueryException
* @return string|null
*/
public static function getTypeOfField($fieldName, ClassMetadata $class, EntityManagerInterface $em)
{
/** @var \Doctrine\ORM\Mapping\ClassMetadataInfo $class */
if (isset($class->fieldMappings[$fieldName])) {
return $class->fieldMappings[$fieldName]['type'];
}
if ( ! isset($class->associationMappings[$fieldName])) {
return null;
}
$assoc = $class->associationMappings[$fieldName];
if (count($assoc['sourceToTargetKeyColumns']) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported();
}
$targetColumnName = $assoc['joinColumns'][0]['referencedColumnName'];
$targetClass = $em->getClassMetadata($assoc['targetEntity']);
return self::getTypeOfColumn($targetColumnName, $targetClass, $em);
}
/**
* @param string $columnName
* @param ClassMetadata $class
* @param EntityManagerInterface $em
*
* @return string|null
*/
public static function getTypeOfColumn($columnName, ClassMetadata $class, EntityManagerInterface $em)
{
/** @var \Doctrine\ORM\Mapping\ClassMetadataInfo $class */
if (isset($class->fieldNames[$columnName])) {
$fieldName = $class->fieldNames[$columnName];
if (isset($class->fieldMappings[$fieldName])) {
return $class->fieldMappings[$fieldName]['type'];
}
return null;
}
foreach ($class->associationMappings as $assoc) {
if (!isset($assoc['joinColumns'])) {
continue;
}
foreach ($assoc['joinColumns'] as $joinColumn) {
if ($joinColumn['name'] == $columnName) {
$targetColumnName = $joinColumn['referencedColumnName'];
$targetClass = $em->getClassMetadata($assoc['targetEntity']);
return self::getTypeOfColumn($targetColumnName, $targetClass, $em);
}
}
}
return null;
}
}