From f7b14085f2105d7dbb57597f32d1119d5f71eb62 Mon Sep 17 00:00:00 2001 From: "Jasper N. Brouwer" Date: Wed, 12 Nov 2014 15:13:17 +0100 Subject: [PATCH] Abstracted infering binding types away in a helper --- .../Collection/ManyToManyPersister.php | 4 +- .../Entity/BasicEntityPersister.php | 120 ++------------- lib/Doctrine/ORM/Utility/PersisterHelper.php | 144 ++++++++++++++++++ 3 files changed, 157 insertions(+), 111 deletions(-) create mode 100644 lib/Doctrine/ORM/Utility/PersisterHelper.php diff --git a/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php index 3a09079c7..448ad9904 100644 --- a/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php @@ -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); diff --git a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php index a9e25b363..d39527128 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php @@ -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} */ diff --git a/lib/Doctrine/ORM/Utility/PersisterHelper.php b/lib/Doctrine/ORM/Utility/PersisterHelper.php new file mode 100644 index 000000000..66a83d396 --- /dev/null +++ b/lib/Doctrine/ORM/Utility/PersisterHelper.php @@ -0,0 +1,144 @@ +. + */ + +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 + */ +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; + } +}