Merge commit 'upstream/master'
This commit is contained in:
commit
7fefe3f4b4
@ -36,7 +36,11 @@ class SingleScalarHydrator extends AbstractHydrator
|
||||
{
|
||||
$cache = array();
|
||||
$result = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (count($result) > 1 || count($result[key($result)]) > 1) {
|
||||
$num = count($result);
|
||||
|
||||
if ($num == 0) {
|
||||
throw new \Doctrine\ORM\NoResultException;
|
||||
} else if ($num > 1 || count($result[key($result)]) > 1) {
|
||||
throw new \Doctrine\ORM\NonUniqueResultException;
|
||||
}
|
||||
$result = $this->_gatherScalarRowData($result[key($result)], $cache);
|
||||
|
@ -243,10 +243,10 @@ class ClassMetadata extends ClassMetadataInfo
|
||||
|
||||
// Store ReflectionProperty of mapped field
|
||||
$sourceFieldName = $assocMapping->sourceFieldName;
|
||||
|
||||
$refProp = $this->reflClass->getProperty($sourceFieldName);
|
||||
$refProp->setAccessible(true);
|
||||
$this->reflFields[$sourceFieldName] = $refProp;
|
||||
|
||||
$refProp = $this->reflClass->getProperty($sourceFieldName);
|
||||
$refProp->setAccessible(true);
|
||||
$this->reflFields[$sourceFieldName] = $refProp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +155,7 @@ abstract class AbstractFileDriver implements Driver
|
||||
if ($this->_paths) {
|
||||
foreach ((array) $this->_paths as $path) {
|
||||
if ( ! is_dir($path)) {
|
||||
throw MappingException::driverRequiresConfiguredDirectoryPath();
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath();
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
|
@ -465,6 +465,11 @@ class SqlWalker implements TreeWalker
|
||||
$fieldName = array_pop($parts);
|
||||
$dqlAlias = $pathExpr->identificationVariable;
|
||||
$class = $this->_queryComponents[$dqlAlias]['metadata'];
|
||||
|
||||
if (isset($class->inheritedAssociationFields[$fieldName])) {
|
||||
$class = $this->_em->getClassMetadata($class->inheritedAssociationFields[$fieldName]);
|
||||
}
|
||||
|
||||
$assoc = $class->associationMappings[$fieldName];
|
||||
|
||||
if ($assoc->isOwningSide) {
|
||||
@ -472,8 +477,8 @@ class SqlWalker implements TreeWalker
|
||||
if (count($assoc->sourceToTargetKeyColumns) > 1) {
|
||||
throw QueryException::associationPathCompositeKeyNotSupported();
|
||||
}
|
||||
$sql .= $this->walkIdentificationVariable($dqlAlias) . '.'
|
||||
. reset($assoc->targetToSourceKeyColumns);
|
||||
$sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.'
|
||||
. reset($assoc->targetToSourceKeyColumns);
|
||||
} else {
|
||||
// 2- Inverse side: NOT (YET?) SUPPORTED
|
||||
throw QueryException::associationPathInverseSideNotSupported();
|
||||
@ -683,23 +688,15 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
$joinAssocPathExpr = $join->joinAssociationPathExpression;
|
||||
$joinedDqlAlias = $join->aliasIdentificationVariable;
|
||||
$targetQComp = $this->_queryComponents[$joinedDqlAlias];
|
||||
$targetClass = $targetQComp['metadata'];
|
||||
$relation = $targetQComp['relation'];
|
||||
$sourceClass = $this->_queryComponents[$joinAssocPathExpr->identificationVariable]['metadata'];
|
||||
|
||||
$relation = $this->_queryComponents[$joinedDqlAlias]['relation'];
|
||||
$targetClass = $this->_em->getClassMetadata($relation->targetEntityName);
|
||||
$sourceClass = $this->_em->getClassMetadata($relation->sourceEntityName);
|
||||
$targetTableName = $targetClass->getQuotedTableName($this->_platform);
|
||||
$targetTableAlias = $this->getSqlTableAlias($targetClass->getTableName(), $joinedDqlAlias);
|
||||
$sourceTableAlias = $this->getSqlTableAlias(
|
||||
$sourceClass->getTableName(), $joinAssocPathExpr->identificationVariable
|
||||
);
|
||||
$targetTableAlias = $this->getSqlTableAlias($targetClass->table['name'], $joinedDqlAlias);
|
||||
$sourceTableAlias = $this->getSqlTableAlias($sourceClass->table['name'], $joinAssocPathExpr->identificationVariable);
|
||||
|
||||
// Ensure we got the owning side, since it has all mapping info
|
||||
if ( ! $relation->isOwningSide) {
|
||||
$assoc = $targetClass->associationMappings[$relation->mappedBy];
|
||||
} else {
|
||||
$assoc = $relation;
|
||||
}
|
||||
$assoc = ( ! $relation->isOwningSide) ? $targetClass->associationMappings[$relation->mappedBy] : $relation;
|
||||
|
||||
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) {
|
||||
if ($relation->isOneToMany() || $relation->isManyToMany()) {
|
||||
@ -713,7 +710,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
foreach ($assoc->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
if ( ! $first) $sql .= ' AND '; else $first = false;
|
||||
|
||||
|
||||
if ($relation->isOwningSide) {
|
||||
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform);
|
||||
$sql .= $sourceTableAlias . '.' . $sourceColumn
|
||||
|
@ -95,9 +95,9 @@ EOT
|
||||
$deleted = $cacheDriver->delete($id);
|
||||
|
||||
if (is_array($deleted)) {
|
||||
$this->_printDeleted($deleted);
|
||||
$this->_printDeleted($output, $deleted);
|
||||
} else if (is_bool($deleted) && $deleted) {
|
||||
$this->_printDeleted(array($id));
|
||||
$this->_printDeleted($output, array($id));
|
||||
}
|
||||
|
||||
$outputed = true;
|
||||
@ -105,12 +105,12 @@ EOT
|
||||
}
|
||||
|
||||
// Removing based on --regex
|
||||
if (($regex = $input->getOption('regex')) !== null && $regexps) {
|
||||
if (($regexps = $input->getOption('regex')) !== null && $regexps) {
|
||||
foreach($regexps as $regex) {
|
||||
$output->write($outputed ? PHP_EOL : '');
|
||||
$output->write(sprintf('Clearing Result cache entries that match the regular expression "<info>%s</info>"', $regex) . PHP_EOL);
|
||||
|
||||
$this->_printDeleted($cacheDriver->deleteByRegex('/' . $regex. '/'));
|
||||
$this->_printDeleted($output, $cacheDriver->deleteByRegex('/' . $regex. '/'));
|
||||
|
||||
$outputed = true;
|
||||
}
|
||||
@ -122,7 +122,7 @@ EOT
|
||||
$output->write($outputed ? PHP_EOL : '');
|
||||
$output->write(sprintf('Clearing Result cache entries that have the prefix "<info>%s</info>"', $prefix) . PHP_EOL);
|
||||
|
||||
$this->_printDeleted($cacheDriver->deleteByPrefix($prefix));
|
||||
$this->_printDeleted($output, $cacheDriver->deleteByPrefix($prefix));
|
||||
|
||||
$outputed = true;
|
||||
}
|
||||
@ -134,7 +134,7 @@ EOT
|
||||
$output->write($outputed ? PHP_EOL : '');
|
||||
$output->write(sprintf('Clearing Result cache entries that have the suffix "<info>%s</info>"', $suffix) . PHP_EOL);
|
||||
|
||||
$this->_printDeleted($cacheDriver->deleteBySuffix($suffix));
|
||||
$this->_printDeleted($output, $cacheDriver->deleteBySuffix($suffix));
|
||||
|
||||
$outputed = true;
|
||||
}
|
||||
@ -143,9 +143,9 @@ EOT
|
||||
// Removing ALL entries
|
||||
if ( ! $ids && ! $regexps && ! $prefixes && ! $suffixes) {
|
||||
$output->write($outputed ? PHP_EOL : '');
|
||||
$output->write('Clearing ALL Result cache entries');
|
||||
$output->write('Clearing ALL Result cache entries' . PHP_EOL);
|
||||
|
||||
$this->_printDeleted($cacheDriver->deleteAll());
|
||||
$this->_printDeleted($output, $cacheDriver->deleteAll());
|
||||
|
||||
$outputed = true;
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ class ConvertMappingCommand extends Console\Command\Command
|
||||
'dest-path', InputArgument::REQUIRED,
|
||||
'The path to generate your entities classes.'
|
||||
),
|
||||
new InputArgument(
|
||||
'from-database', InputArgument::OPTIONAL, 'The path of mapping information.'
|
||||
new InputOption(
|
||||
'from-database', null, null, 'Whether or not to convert mapping information from existing database.'
|
||||
),
|
||||
new InputOption(
|
||||
'extend', null, InputOption::PARAMETER_OPTIONAL,
|
||||
@ -86,10 +86,7 @@ EOT
|
||||
{
|
||||
$em = $this->getHelper('em')->getEntityManager();
|
||||
|
||||
$metadatas = $em->getMetadataFactory()->getAllMetadata();
|
||||
$metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter'));
|
||||
|
||||
if ($input->getArgument('from-database') === true) {
|
||||
if ($input->getOption('from-database') === true) {
|
||||
$em->getConfiguration()->setMetadataDriverImpl(
|
||||
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
|
||||
$em->getConnection()->getSchemaManager()
|
||||
@ -97,8 +94,14 @@ EOT
|
||||
);
|
||||
}
|
||||
|
||||
$metadatas = $em->getMetadataFactory()->getAllMetadata();
|
||||
$metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter'));
|
||||
|
||||
// Process destination directory
|
||||
$destPath = realpath($input->getArgument('dest-path'));
|
||||
if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
|
||||
mkdir($destPath, 0777, true);
|
||||
}
|
||||
$destPath = realpath($destPath);
|
||||
|
||||
if ( ! file_exists($destPath)) {
|
||||
throw new \InvalidArgumentException(
|
||||
|
@ -65,12 +65,21 @@ EOT
|
||||
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
|
||||
{
|
||||
$em = $this->getHelper('em')->getEntityManager();
|
||||
$em->getConfiguration()->ensureProductionSettings();
|
||||
|
||||
if ($input->getOption('complete') !== null) {
|
||||
$em->getConnection()->connect();
|
||||
$error = false;
|
||||
try {
|
||||
$em->getConfiguration()->ensureProductionSettings();
|
||||
|
||||
if ($input->getOption('complete') !== null) {
|
||||
$em->getConnection()->connect();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$error = true;
|
||||
$output->writeln('<error>' . $e->getMessage() . '</error>');
|
||||
}
|
||||
|
||||
$output->write('Environment is correctly configured for production.');
|
||||
if ($error === false) {
|
||||
$output->write('<info>Environment is correctly configured for production.</info>' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
}
|
@ -79,6 +79,10 @@ EOT
|
||||
$destPath = $em->getConfiguration()->getProxyDir();
|
||||
}
|
||||
|
||||
if ( ! is_dir($destPath)) {
|
||||
mkdir($destPath, 0777, true);
|
||||
}
|
||||
|
||||
$destPath = realpath($destPath);
|
||||
|
||||
if ( ! file_exists($destPath)) {
|
||||
|
@ -933,6 +933,9 @@ public function <methodName>()
|
||||
case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY:
|
||||
return 'IDENTITY';
|
||||
|
||||
case ClassMetadataInfo::GENERATOR_TYPE_NONE:
|
||||
return 'NONE';
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid provided IdGeneratorType: ' . $type);
|
||||
}
|
||||
|
@ -224,7 +224,47 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testGetSingleResultThrowsExceptionOnNoResult()
|
||||
{
|
||||
$this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a")
|
||||
->getSingleResult();
|
||||
->getSingleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Doctrine\ORM\NoResultException
|
||||
*/
|
||||
public function testGetSingleScalarResultThrowsExceptionOnNoResult()
|
||||
{
|
||||
$this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a")
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function testGetSingleScalarResultThrowsExceptionOnNonUniqueResult()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
$user->username = 'gblanco';
|
||||
$user->status = 'developer';
|
||||
|
||||
$article1 = new CmsArticle;
|
||||
$article1->topic = "Doctrine 2";
|
||||
$article1->text = "This is an introduction to Doctrine 2.";
|
||||
$user->addArticle($article1);
|
||||
|
||||
$article2 = new CmsArticle;
|
||||
$article2->topic = "Symfony 2";
|
||||
$article2->text = "This is an introduction to Symfony 2.";
|
||||
$user->addArticle($article2);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($article1);
|
||||
$this->_em->persist($article2);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a")
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
public function testSupportsQueriesWithEntityNamespaces()
|
||||
|
71
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
Normal file
71
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class DDC448Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448MainTable'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448ConnectedClass'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448SubTable'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$q = $this->_em->createQuery("select b from ".__NAMESPACE__."\\DDC448SubTable b where b.connectedClassId = ?1");
|
||||
$this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.connectedClassId AS connectedClassId2 FROM SubTable s1_ INNER JOIN DDC448MainTable d0_ ON s1_.id = d0_.id WHERE d0_.connectedClassId = ?', $q->getSQL());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorColumn(name="discr", type="smallint")
|
||||
* @DiscriminatorMap({
|
||||
* "0" = "DDC448MainTable",
|
||||
* "1" = "DDC448SubTable"
|
||||
* })
|
||||
*/
|
||||
class DDC448MainTable
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(name="id", type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC448ConnectedClass", cascade={"all"}, fetch="EAGER")
|
||||
* @JoinColumn(name="connectedClassId", referencedColumnName="id", onDelete="CASCADE", onUpdate="CASCADE", nullable=true)
|
||||
*/
|
||||
private $connectedClassId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="connectedClass")
|
||||
* @HasLifecycleCallbacks
|
||||
*/
|
||||
class DDC448ConnectedClass
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(name="id", type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id; // connected with DDC448MainTable
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="SubTable")
|
||||
*/
|
||||
class DDC448SubTable extends DDC448MainTable
|
||||
{
|
||||
}
|
69
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
Normal file
69
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class DDC493Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Customer'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Distributor'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Contact')
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$q = $this->_em->createQuery("select u, u.contact.data from ".__NAMESPACE__."\\DDC493Distributor u");
|
||||
$this->assertEquals('SELECT d0_.id AS id0, d1_.data AS data1, d0_.discr AS discr2, d0_.contact AS contact3 FROM DDC493Distributor d2_ INNER JOIN DDC493Customer d0_ ON d2_.id = d0_.id INNER JOIN DDC493Contact d1_ ON d0_.contact = d1_.id', $q->getSQL());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorColumn(name="discr", type="string")
|
||||
* @DiscriminatorMap({"distributor" = "DDC493Distributor", "customer" = "DDC493Customer"})
|
||||
*/
|
||||
class DDC493Customer {
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC493Contact", cascade={"remove","persist"})
|
||||
* @JoinColumn(name="contact", referencedColumnName="id")
|
||||
*/
|
||||
public $contact;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC493Distributor extends DDC493Customer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC493Contact
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
/** @Column(type="string") */
|
||||
public $data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
71
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
Normal file
71
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class DDC513Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513OfferItem'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513Item'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513Price'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513OfferItem u left join u.price p");
|
||||
$this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513OfferItem d1_ INNER JOIN DDC513Item d0_ ON d1_.id = d0_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC513OfferItem extends DDC513Item
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorColumn(name="discr", type="string")
|
||||
* @DiscriminatorMap({"item" = "DDC513Item", "offerItem" = "DDC513OfferItem"})
|
||||
*/
|
||||
class DDC513Item
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC513Price", cascade={"remove","persist"})
|
||||
* @JoinColumn(name="price", referencedColumnName="id")
|
||||
*/
|
||||
public $price;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC513Price {
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/** @Column(type="string") */
|
||||
public $data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
<entity name="Doctrine\Tests\ORM\Mapping\CTI">
|
||||
<discriminiator-column name="discr" type="string" length=""/>
|
||||
<discriminator-column name="discr" type="string" length=""/>
|
||||
<discriminator-map>
|
||||
<discriminator-mapping value="foo" class="CTIFoo"/>
|
||||
<discriminator-mapping value="bar" class="CTIBar"/>
|
||||
|
Loading…
Reference in New Issue
Block a user