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

Fix DDC-2494

This commit is contained in:
Fabio B. Silva 2013-06-11 13:44:08 -04:00 committed by fabios
parent b15758bb42
commit d685f592fe
4 changed files with 273 additions and 45 deletions

View File

@ -114,9 +114,8 @@ class SimpleObjectHydrator extends AbstractHydrator
}
// Convert field to a valid PHP value
if (isset($cache[$column]['field'])) {
$type = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type']);
$value = $type->convertToPHPValue($value, $this->_platform);
if (isset($cache[$column]['type'])) {
$value = Type::getType($cache[$column]['type'])->convertToPHPValue($value, $this->_platform);
}
// Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
@ -145,44 +144,51 @@ class SimpleObjectHydrator extends AbstractHydrator
*/
protected function hydrateColumnInfo($entityName, $column)
{
switch (true) {
case (isset($this->_rsm->fieldMappings[$column])):
$class = isset($this->declaringClasses[$column])
? $this->declaringClasses[$column]
: $this->class;
// If class is not part of the inheritance, ignore
if ( ! ($class->name === $entityName || is_subclass_of($entityName, $class->name))) {
return null;
}
if (isset($this->_rsm->fieldMappings[$column])) {
$name = $this->_rsm->fieldMappings[$column];
$class = isset($this->declaringClasses[$column])
? $this->declaringClasses[$column]
: $this->class;
return array(
'class' => $class,
'name' => $this->_rsm->fieldMappings[$column],
'field' => true,
);
case (isset($this->_rsm->relationMap[$column])):
$class = isset($this->_rsm->relationMap[$column])
? $this->_rsm->relationMap[$column]
: $this->class;
// If class is not self referencing, ignore
if ( ! ($class === $entityName || is_subclass_of($entityName, $class))) {
return null;
}
// TODO: Decide what to do with associations. It seems original code is incomplete.
// One solution is to load the association, but it might require extra efforts.
return array('name' => $column);
case (isset($this->_rsm->metaMappings[$column])):
return array(
'name' => $this->_rsm->metaMappings[$column]
);
default:
// If class is not part of the inheritance, ignore
if ( ! ($class->name === $entityName || is_subclass_of($entityName, $class->name))) {
return null;
}
return array(
'name' => $name,
'type' => $class->fieldMappings[$name]['type']
);
}
if (isset($this->_rsm->relationMap[$column])) {
$class = isset($this->_rsm->relationMap[$column])
? $this->_rsm->relationMap[$column]
: $this->class;
// If class is not self referencing, ignore
if ( ! ($class === $entityName || is_subclass_of($entityName, $class))) {
return null;
}
// TODO: Decide what to do with associations. It seems original code is incomplete.
// One solution is to load the association, but it might require extra efforts.
return array('name' => $column);
}
if (isset($this->_rsm->metaMappings[$column])) {
$name = $this->_rsm->metaMappings[$column];
$type = isset($this->_rsm->typeMappings[$column])
? $this->_rsm->typeMappings[$column]
: null;
return array(
'name' => $name,
'type' => $type
);
}
return null;
}
}

View File

@ -1334,16 +1334,22 @@ class BasicEntityPersister
return '';
}
$columnList = array();
$columnList = array();
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
foreach ($assoc['joinColumns'] as $joinColumn) {
$type = null;
$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;
$this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, isset($assoc['id']) && $assoc['id'] === true);
if (isset($targetClass->fieldNames[$joinColumn['referencedColumnName']])) {
$type = $targetClass->fieldMappings[$targetClass->fieldNames[$joinColumn['referencedColumnName']]]['type'];
}
$this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type);
}
return implode(', ', $columnList);

View File

@ -543,14 +543,15 @@ class ResultSetMapping
/**
* Adds a meta column (foreign key or discriminator column) to the result set.
*
* @param string $alias
* @param string $columnName
* @param string $fieldName
* @param string $alias The result alias with which the meta result should be placed in the result structure.
* @param string $columnName The name of the column in the SQL result set.
* @param string $fieldName The name of the field on the declaring class.
* @param bool $isIdentifierColumn
* @param string $type The column type
*
* @return ResultSetMapping This ResultSetMapping instance.
*/
public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false)
public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false, $type = null)
{
$this->metaMappings[$columnName] = $fieldName;
$this->columnOwnerMap[$columnName] = $alias;
@ -559,6 +560,10 @@ class ResultSetMapping
$this->isIdentifierColumn[$alias][$columnName] = true;
}
if ($type) {
$this->typeMappings[$columnName] = $type;
}
return $this;
}
}

View File

@ -0,0 +1,211 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* @group DDC-2494
*/
class DDC2494Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
DDC2494TinyIntType::$calls = array();
Type::addType('ddc2494_tinyint', __NAMESPACE__ . '\DDC2494TinyIntType');
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(DDC2494Currency::CLASSNAME),
$this->_em->getClassMetadata(DDC2494Campaign::CLASSNAME),
));
}
public function testIssue()
{
$currency = new DDC2494Currency(1, 2);
$this->_em->persist($currency);
$this->_em->flush();
$campaign = new DDC2494Campaign($currency);
$this->_em->persist($campaign);
$this->_em->flush();
$this->_em->close();
$this->assertArrayHasKey('convertToDatabaseValue', DDC2494TinyIntType::$calls);
$this->assertCount(3, DDC2494TinyIntType::$calls['convertToDatabaseValue']);
$item = $this->_em->find(DDC2494Campaign::CLASSNAME, $campaign->getId());
$this->assertInstanceOf(DDC2494Campaign::CLASSNAME, $item);
$this->assertInstanceOf(DDC2494Currency::CLASSNAME, $item->getCurrency());
$queryCount = $this->getCurrentQueryCount();
$this->assertInstanceOf('\Doctrine\Common\Proxy\Proxy', $item->getCurrency());
$this->assertFalse($item->getCurrency()->__isInitialized());
$this->assertArrayHasKey('convertToPHPValue', DDC2494TinyIntType::$calls);
$this->assertCount(1, DDC2494TinyIntType::$calls['convertToPHPValue']);
$this->assertInternalType('integer', $item->getCurrency()->getId());
$this->assertCount(1, DDC2494TinyIntType::$calls['convertToPHPValue']);
$this->assertFalse($item->getCurrency()->__isInitialized());
$this->assertEquals($queryCount, $this->getCurrentQueryCount());
$this->assertInternalType('integer', $item->getCurrency()->getTemp());
$this->assertCount(3, DDC2494TinyIntType::$calls['convertToPHPValue']);
$this->assertTrue($item->getCurrency()->__isInitialized());
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
}
}
/**
* @Table(name="ddc2494_currency")
* @Entity
*/
class DDC2494Currency
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(type="integer", type="ddc2494_tinyint")
*/
protected $id;
/**
* @Column(name="temp", type="ddc2494_tinyint", nullable=false)
*/
protected $temp;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @OneToMany(targetEntity="DDC2494Campaign", mappedBy="currency")
*/
protected $campaigns;
public function __construct($id, $temp)
{
$this->id = $id;
$this->temp = $temp;
}
public function getId()
{
return $this->id;
}
public function getTemp()
{
return $this->temp;
}
public function getCampaigns()
{
return $this->campaigns;
}
}
/**
* @Table(name="ddc2494_campaign")
* @Entity
*/
class DDC2494Campaign
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
protected $id;
/**
* @var \Doctrine\Tests\ORM\Functional\Ticket\DDC2494Currency
*
* @ManyToOne(targetEntity="DDC2494Currency", inversedBy="campaigns")
* @JoinColumn(name="currency_id", referencedColumnName="id", nullable=false)
*/
protected $currency;
public function __construct(DDC2494Currency $currency)
{
$this->currency = $currency;
}
public function getId()
{
return $this->id;
}
/**
* @return \Doctrine\Tests\ORM\Functional\Ticket\DDC2494Currency
*/
public function getCurrency()
{
return $this->currency;
}
}
class DDC2494TinyIntType extends Type
{
public static $calls = array();
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration);
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
$return = (string) $value;
self::$calls[__FUNCTION__][] = array(
'value' => $value,
'return' => $return,
'platform' => $platform,
);
return $return;
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
$return = (integer) $value;
self::$calls[__FUNCTION__][] = array(
'value' => $value,
'return' => $return,
'platform' => $platform,
);
return $return;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'ddc2494_tinyint';
}
}