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

DDC-117 - Finalize patch, fix all the problems of different use-cases by hugely expanding the test-model.

This commit is contained in:
Benjamin Eberlei 2011-01-01 18:17:19 +01:00
parent 2d27a99a0b
commit 194a90923d
20 changed files with 925 additions and 244 deletions

View File

@ -317,6 +317,10 @@ class ClassMetadata extends ClassMetadataInfo
$serialized[] = 'isMappedSuperclass';
}
if ($this->containsForeignIdentifier) {
$serialized[] = 'containsForeignIdentifier';
}
if ($this->isVersioned) {
$serialized[] = 'isVersioned';
$serialized[] = 'versionField';

View File

@ -255,7 +255,7 @@ class ClassMetadataInfo
* - <b>scale</b> (integer, optional, schema-only)
* The scale of a decimal column. Only valid if the column type is decimal.
*
* - <b>unique (string, optional, schema-only)</b>
[* - <b>'unique'] (string, optional, schema-only)</b>
* Whether a unique constraint should be generated for the column.
*
* @var array
@ -392,6 +392,15 @@ class ClassMetadataInfo
*/
public $isIdentifierComposite = false;
/**
* READ-ONLY: Flag indicating wheather the identifier/primary key contains at least one foreign key association.
*
* This flag is necessary because some code blocks require special treatment of this cases.
*
* @var boolean
*/
public $containsForeignIdentifier = false;
/**
* READ-ONLY: The ID generator used for generating IDs for this class.
*
@ -712,6 +721,10 @@ class ClassMetadataInfo
// Complete id mapping
if (isset($mapping['id']) && $mapping['id'] === true) {
if (isset($mapping['orphanRemoval']) && $mapping['orphanRemoval'] == true) {
throw MappingException::illegalOrphanRemovalOnIdentifierAssociation($this->name, $mapping['fieldName']);
}
if ( ! in_array($mapping['fieldName'], $this->identifier)) {
if (count($mapping['joinColumns']) >= 2) {
throw MappingException::cannotMapCompositePrimaryKeyEntitiesAsForeignId(
@ -720,6 +733,7 @@ class ClassMetadataInfo
}
$this->identifier[] = $mapping['fieldName'];
$this->containsForeignIdentifier = true;
}
// Check for composite key
if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) {
@ -747,6 +761,10 @@ class ClassMetadataInfo
} else {
$mapping['isOwningSide'] = false;
}
if (isset($mapping['id']) && $mapping['id'] === true && $mapping['type'] & ClassMetadata::TO_MANY) {
throw MappingException::illegalToManyIdentifierAssoaction($this->name, $mapping['fieldName']);
}
// Fetch mode. Default fetch mode to LAZY, if not set.
if ( ! isset($mapping['fetch'])) {
@ -797,9 +815,15 @@ class ClassMetadataInfo
'referencedColumnName' => 'id'
));
}
$uniqueContraintColumns = array();
foreach ($mapping['joinColumns'] as $key => &$joinColumn) {
if ($mapping['type'] === self::ONE_TO_ONE) {
$joinColumn['unique'] = true;
if (count($mapping['joinColumns']) == 1) {
$joinColumn['unique'] = true;
} else {
$uniqueContraintColumns[] = $joinColumn['name'];
}
}
if (empty($joinColumn['name'])) {
$joinColumn['name'] = $mapping['fieldName'] . '_id';
@ -811,6 +835,16 @@ class ClassMetadataInfo
$mapping['joinColumnFieldNames'][$joinColumn['name']] = isset($joinColumn['fieldName'])
? $joinColumn['fieldName'] : $joinColumn['name'];
}
if ($uniqueContraintColumns) {
if (!$this->table) {
throw new \RuntimeException("ClassMetadataInfo::setTable() has to be called before defining a one to one relationship.");
}
$this->table['uniqueConstraints'][$mapping['fieldName']."_uniq"] = array(
'columns' => $uniqueContraintColumns
);
}
$mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']);
}
@ -818,6 +852,10 @@ class ClassMetadataInfo
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
(bool) $mapping['orphanRemoval'] : false;
if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
throw MappingException::illegalInverseIdentifierAssocation($this->name, $mapping['fieldName']);
}
return $mapping;
}
@ -1547,6 +1585,74 @@ class ClassMetadataInfo
! ($this->associationMappings[$fieldName]['type'] & self::TO_ONE);
}
/**
* Is this an association that only has a single join column?
*
* @param string $fieldName
* @return bool
*/
public function isAssociationWithSingleJoinColumn($fieldName)
{
return (
isset($this->associationMappings[$fieldName]) &&
isset($this->associationMappings[$fieldName]['joinColumns'][0]) &&
!isset($this->associationMappings[$fieldName]['joinColumns'][1])
);
}
/**
* Return the single association join column (if any).
*
* @param string $fieldName
* @return string
*/
public function getSingleAssociationJoinColumnName($fieldName)
{
if (!$this->isAssociationWithSingleJoinColumn($fieldName)) {
throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName);
}
return $this->associationMappings[$fieldName]['joinColumns'][0]['name'];
}
/**
* Return the single association referenced join column name (if any).
*
* @param string $fieldName
* @return string
*/
public function getSingleAssociationReferencedJoinColumnName($fieldName)
{
if (!$this->isAssociationWithSingleJoinColumn($fieldName)) {
throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName);
}
return $this->associationMappings[$fieldName]['joinColumns'][0]['referencedColumnName'];
}
/**
* Used to retrieve a fieldname for either field or association from a given column,
*
* This method is used in foreign-key as primary-key contexts.
*
* @param string $columnName
* @return string
*/
public function getFieldForColumn($columnName)
{
if (isset($this->fieldNames[$columnName])) {
return $this->fieldNames[$columnName];
} else {
foreach ($this->associationMappings AS $assocName => $mapping) {
if ($this->isAssociationWithSingleJoinColumn($assocName) &&
$this->associationMappings[$assocName]['joinColumns'][0]['name'] == $columnName) {
return $assocName;
}
}
throw MappingException::noFieldNameFoundForColumn($this->name, $columnName);
}
}
/**
* Sets the ID generator used to generate IDs for instances of this class.
*

View File

@ -243,4 +243,31 @@ class MappingException extends \Doctrine\ORM\ORMException
return new self("It is not possible to map entity '".$className."' with a composite primary key ".
"as part of the primary key of another entity '".$targetEntity."#".$targetField."'.");
}
public static function noSingleAssociationJoinColumnFound($className, $field)
{
return new self("'$className#$field' is not an association with a single join column.");
}
public static function noFieldNameFoundForColumn($className, $column)
{
return new self("Cannot find a field on '$className' that is mapped to column '$column'. Either the ".
"field does not exist or an association exists but it has multiple join columns.");
}
public static function illegalOrphanRemovalOnIdentifierAssociation($className, $field)
{
return new self("The orphan removal option is not allowed on an association that is ".
"part of the identifier in '$className#$field'.");
}
public static function illegalInverseIdentifierAssocation($className, $field)
{
return new self("An inverse association is not allowed to be identifier in '$className#$field'.");
}
public static function illegalToManyIdentifierAssoaction($className, $field)
{
return new self("Many-to-many or one-to-many associations are not allowed to be identifier in '$className#$field'.");
}
}

View File

@ -473,6 +473,8 @@ class BasicEntityPersister
foreach ($assoc['sourceToTargetKeyColumns'] as $sourceColumn => $targetColumn) {
if ($newVal === null) {
$result[$owningTable][$sourceColumn] = null;
} else if ($targetClass->containsForeignIdentifier) {
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->getFieldForColumn($targetColumn)];
} else {
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
}
@ -720,13 +722,21 @@ class BasicEntityPersister
* @param PersistentCollection $coll The collection to fill.
*/
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
{
{
$criteria = array();
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
$joinTableConditions = array();
if ($assoc['isOwningSide']) {
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
}
$criteria[$relationKeyColumn] = $value;
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
@ -738,7 +748,15 @@ class BasicEntityPersister
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
// TRICKY: since the association is inverted source and target are flipped
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
}
$criteria[$relationKeyColumn] = $value;
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
@ -955,8 +973,15 @@ class BasicEntityPersister
$joinSql = '';
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
if ($joinSql != '') $joinSql .= ' AND ';
if ($this->_class->containsForeignIdentifier && !isset($this->_class->fieldNames[$sourceColumn])) {
$quotedColumn = $sourceColumn; // join columns cannot be quoted
} else {
$quotedColumn = $this->_class->getQuotedColumnName($this->_class->fieldNames[$sourceColumn], $this->_platform);
}
$joinSql .= $this->_getSQLTableAlias($this->_class->name) .
'.' . $this->_class->getQuotedColumnName($this->_class->fieldNames[$sourceColumn], $this->_platform) . ' = '
'.' . $quotedColumn . ' = '
. $joinTableName . '.' . $joinTableColumn;
}
@ -1160,7 +1185,17 @@ class BasicEntityPersister
$owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
$criteria[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
}
$criteria[$targetKeyColumn] = $value;
} else {
$criteria[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
}
}
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);

View File

@ -117,13 +117,21 @@ class ManyToManyPersister extends AbstractCollectionPersister
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
if ($isComposite) {
$params[] = $identifier1[$class1->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
if ($class1->containsForeignIdentifier) {
$params[] = $identifier1[$class1->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])];
} else {
$params[] = $identifier1[$class1->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
}
} else {
$params[] = array_pop($identifier1);
}
} else {
if ($isComposite) {
$params[] = $identifier2[$class2->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
if ($class2->containsForeignIdentifier) {
$params[] = $identifier2[$class2->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
} else {
$params[] = $identifier2[$class2->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
}
} else {
$params[] = array_pop($identifier2);
}

View File

@ -738,7 +738,11 @@ class SqlWalker implements TreeWalker
}
}
// This condition is not checking ClassMetadata::MANY_TO_ONE, because by definition it cannot
// be the owning side and previously we ensured that $assoc is always the owning side of the associations.
// The owning side is necessary at this point because only it contains the JoinColumn information.
if ($assoc['type'] & ClassMetadata::TO_ONE) {
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
$first = true;
@ -746,15 +750,19 @@ class SqlWalker implements TreeWalker
if ( ! $first) $sql .= ' AND '; else $first = false;
if ($relation['isOwningSide']) {
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform);
$sql .= $sourceTableAlias . '.' . $sourceColumn
. ' = '
. $targetTableAlias . '.' . $quotedTargetColumn;
if ($targetClass->containsForeignIdentifier && !isset($targetClass->fieldNames[$targetColumn])) {
$quotedTargetColumn = $targetColumn; // Join columns cannot be quoted.
} else {
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform);
}
$sql .= $sourceTableAlias . '.' . $sourceColumn . ' = ' . $targetTableAlias . '.' . $quotedTargetColumn;
} else {
$quotedTargetColumn = $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$targetColumn], $this->_platform);
$sql .= $sourceTableAlias . '.' . $quotedTargetColumn
. ' = '
. $targetTableAlias . '.' . $sourceColumn;
if ($sourceClass->containsForeignIdentifier && !isset($sourceClass->fieldNames[$targetColumn])) {
$quotedTargetColumn = $targetColumn; // Join columns cannot be quoted.
} else {
$quotedTargetColumn = $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$targetColumn], $this->_platform);
}
$sql .= $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn;
}
}
} else if ($assoc['type'] == ClassMetadata::MANY_TO_MANY) {
@ -768,17 +776,25 @@ class SqlWalker implements TreeWalker
foreach ($assoc['relationToSourceKeyColumns'] as $relationColumn => $sourceColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $sourceTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform)
. ' = '
. $joinTableAlias . '.' . $relationColumn;
if ($sourceClass->containsForeignIdentifier && !isset($sourceClass->fieldNames[$sourceColumn])) {
$quotedTargetColumn = $sourceColumn; // Join columns cannot be quoted.
} else {
$quotedTargetColumn = $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform);
}
$sql .= $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $relationColumn;
}
} else {
foreach ($assoc['relationToTargetKeyColumns'] as $relationColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $sourceTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$targetColumn], $this->_platform)
. ' = '
. $joinTableAlias . '.' . $relationColumn;
if ($sourceClass->containsForeignIdentifier && !isset($sourceClass->fieldNames[$targetColumn])) {
$quotedTargetColumn = $targetColumn; // Join columns cannot be quoted.
} else {
$quotedTargetColumn = $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$targetColumn], $this->_platform);
}
$sql .= $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $relationColumn;
}
}
@ -792,17 +808,25 @@ class SqlWalker implements TreeWalker
foreach ($assoc['relationToTargetKeyColumns'] as $relationColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform)
. ' = '
. $joinTableAlias . '.' . $relationColumn;
if ($targetClass->containsForeignIdentifier && !isset($targetClass->fieldNames[$targetColumn])) {
$quotedTargetColumn = $targetColumn; // Join columns cannot be quoted.
} else {
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform);
}
$sql .= $targetTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $relationColumn;
}
} else {
foreach ($assoc['relationToSourceKeyColumns'] as $relationColumn => $sourceColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$sourceColumn], $this->_platform)
. ' = '
. $joinTableAlias . '.' . $relationColumn;
if ($targetClass->containsForeignIdentifier && !isset($targetClass->fieldNames[$sourceColumn])) {
$quotedTargetColumn = $sourceColumn; // Join columns cannot be quoted.
} else {
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$sourceColumn], $this->_platform);
}
$sql .= $targetTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $relationColumn;
}
}
}

View File

@ -444,10 +444,10 @@ class SchemaTool
} else if (in_array($referencedColumnName, $class->getIdentifierColumnNames())) {
// it seems to be an entity as foreign key
foreach ($class->getIdentifierFieldNames() AS $fieldName) {
if ($class->hasAssociation($fieldName) && $class->associationMappings[$fieldName]['joinColumns'][0]['name'] == $referencedColumnName) {
if ($class->hasAssociation($fieldName) && $class->getSingleAssociationJoinColumnName($fieldName) == $referencedColumnName) {
return $this->getDefiningClass(
$this->_em->getClassMetadata($class->associationMappings[$fieldName]['targetEntity']),
$class->associationMappings[$fieldName]['joinColumns'][0]['referencedColumnName']
$class->getSingleAssociationReferencedJoinColumnName($fieldName)
);
}
}

View File

@ -1902,7 +1902,11 @@ class UnitOfWork implements PropertyChangedListener
foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
$joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null;
if ($joinColumnValue !== null) {
$associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
if ($targetClass->containsForeignIdentifier) {
$associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue;
} else {
$associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
}
}
}
if ( ! $associatedId) {

View File

@ -0,0 +1,65 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117ApproveChanges
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
private $id;
/**
* @ManyToOne(targetEntity="DDC117ArticleDetails")
* @JoinColumn(name="details_id", referencedColumnName="article_id")
*/
private $articleDetails;
/**
* @ManyToOne(targetEntity="DDC117Reference")
* @JoinColumns({
* @JoinColumn(name="source_id", referencedColumnName="source_id"),
* @JoinColumn(name="target_id", referencedColumnName="target_id")
* })
*/
private $reference;
/**
* @ManyToOne(targetEntity="DDC117Translation")
* @JoinColumns({
* @JoinColumn(name="trans_article_id", referencedColumnName="article_id"),
* @JoinColumn(name="trans_language", referencedColumnName="language")
* })
*/
private $translation;
public function __construct($details, $reference, $translation)
{
$this->articleDetails = $details;
$this->reference = $reference;
$this->translation = $translation;
}
public function getId()
{
return $this->id;
}
public function getArticleDetails()
{
return $this->articleDetails;
}
public function getReference()
{
return $this->reference;
}
public function getTranslation()
{
return $this->translation;
}
}

View File

@ -0,0 +1,81 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117Article
{
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
private $id;
/** @Column */
private $title;
/**
* @OneToMany(targetEntity="DDC117Reference", mappedBy="source", cascade={"remove"})
*/
private $references;
/**
* @OneToOne(targetEntity="DDC117ArticleDetails", mappedBy="article", cascade={"persist", "remove"})
*/
private $details;
/**
* @OneToMany(targetEntity="DDC117Translation", mappedBy="article", cascade={"persist", "remove"})
*/
private $translations;
public function __construct($title)
{
$this->title = $title;
$this->references = new \Doctrine\Common\Collections\ArrayCollection();
$this->translations = new \Doctrine\Common\Collections\ArrayCollection();
}
public function setDetails($details)
{
$this->details = $details;
}
public function id()
{
return $this->id;
}
public function addReference($reference)
{
$this->references[] = $reference;
}
public function references()
{
return $this->references;
}
public function addTranslation($language, $title)
{
$this->translations[] = new DDC117Translation($this, $language, $title);
}
public function getText()
{
return $this->details->getText();
}
public function getDetails()
{
return $this->details;
}
public function resetText()
{
$this->details = null;
}
public function getTranslations()
{
return $this->translations;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117ArticleDetails
{
/**
* @Id
* @OneToOne(targetEntity="DDC117Article", inversedBy="details")
* @JoinColumn(name="article_id", referencedColumnName="article_id")
*/
private $article;
/**
* @Column(type="text")
*/
private $text;
public function __construct($article, $text)
{
$this->article = $article;
$article->setDetails($this);
$this->update($text);
}
public function update($text)
{
$this->text = $text;
}
public function getText()
{
return $this->text;
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117Editor
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
public $id;
/**
* @Column(type="string")
*/
public $name;
/**
* @ManyToMany(targetEntity="DDC117Translation", inversedBy="reviewedByEditors")
* @JoinTable(
* inverseJoinColumns={
* @JoinColumn(name="article_id", referencedColumnName="article_id"),
* @JoinColumn(name="language", referencedColumnName="language")
* },
* joinColumns={
* @JoinColumn(name="editor_id", referencedColumnName="id")
* }
* )
*/
public $reviewingTranslations;
/**
* @ManyToOne(targetEntity="DDC117Translation", inversedBy="lastTranslatedBy")
* @JoinColumns({
* @JoinColumn(name="lt_article_id", referencedColumnName="article_id"),
* @JoinColumn(name="lt_language", referencedColumnName="language")
* })
*/
public $lastTranslation;
public function __construct($name = "")
{
$this->name = $name;
$this->reviewingTranslations = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addLastTranslation(DDC117Translation $t)
{
$this->lastTranslation = $t;
$t->lastTranslatedBy[] = $this;
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117Reference
{
/**
* @Id
* @ManyToOne(targetEntity="DDC117Article", inversedBy="references")
* @JoinColumn(name="source_id", referencedColumnName="article_id")
*/
private $source;
/**
* @Id
* @ManyToOne(targetEntity="DDC117Article", inversedBy="references")
* @JoinColumn(name="target_id", referencedColumnName="article_id")
*/
private $target;
/**
* @column(type="string")
*/
private $description;
/**
* @column(type="datetime")
*/
private $created;
public function __construct($source, $target, $description)
{
$source->addReference($this);
$target->addReference($this);
$this->source = $source;
$this->target = $target;
$this->description = $description;
$this->created = new \DateTime("now");
}
public function source()
{
return $this->source;
}
public function target()
{
return $this->target;
}
public function setDescription($desc)
{
$this->description = $desc;
}
public function getDescription()
{
return $this->description;
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117Translation
{
/**
* @Id
* @ManyToOne(targetEntity="DDC117Article")
* @JoinColumn(name="article_id", referencedColumnName="article_id")
*/
private $article;
/**
* @Id @column(type="string")
*/
private $language;
/**
* @column(type="string")
*/
private $title;
/**
* @ManyToMany(targetEntity="DDC117Editor", mappedBy="reviewingTranslations")
*/
public $reviewedByEditors;
/**
* @OneToMany(targetEntity="DDC117Editor", mappedBy="lastTranslation")
*/
public $lastTranslatedBy;
public function __construct($article, $language, $title)
{
$this->article = $article;
$this->language = $language;
$this->title = $title;
$this->reviewedByEditors = new \Doctrine\Common\Collections\ArrayCollection();
$this->lastTranslatedBy = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getArticleId()
{
return $this->article->id();
}
public function getLanguage()
{
return $this->language;
}
public function getLastTranslatedBy()
{
return $this->lastTranslatedBy;
}
public function getReviewedByEditors()
{
return $this->reviewedByEditors;
}
}

View File

@ -2,6 +2,13 @@
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\DDC117\DDC117ArticleDetails;
use Doctrine\Tests\Models\DDC117\DDC117Article;
use Doctrine\Tests\Models\DDC117\DDC117Reference;
use Doctrine\Tests\Models\DDC117\DDC117Translation;
use Doctrine\Tests\Models\DDC117\DDC117ApproveChanges;
use Doctrine\Tests\Models\DDC117\DDC117Editor;
require_once __DIR__ . '/../../../TestInit.php';
class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
@ -13,19 +20,9 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
private $articleDetails;
protected function setUp() {
$this->useModelSet('ddc117');
parent::setUp();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117Article'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117Reference'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117Translation'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117ArticleDetails'),
));
} catch(\Exception $e) {
}
$this->article1 = new DDC117Article("Foo");
$this->article2 = new DDC117Article("Bar");
@ -53,33 +50,33 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$mapRef = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
$this->assertType(__NAMESPACE__."\DDC117Reference", $mapRef);
$this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->target());
$this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->source());
$this->assertSame($mapRef, $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
$mapRef = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Reference", $mapRef);
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Article", $mapRef->target());
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Article", $mapRef->source());
$this->assertSame($mapRef, $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria));
$this->_em->clear();
$dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE r.source = ?1";
$dql = "SELECT r, s FROM "."Doctrine\Tests\Models\DDC117\DDC117Reference r JOIN r.source s WHERE r.source = ?1";
$dqlRef = $this->_em->createQuery($dql)->setParameter(1, 1)->getSingleResult();
$this->assertType(__NAMESPACE__."\DDC117Reference", $mapRef);
$this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->target());
$this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->source());
$this->assertSame($dqlRef, $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Reference", $mapRef);
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Article", $mapRef->target());
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Article", $mapRef->source());
$this->assertSame($dqlRef, $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria));
$this->_em->clear();
$dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
$dql = "SELECT r, s FROM "."Doctrine\Tests\Models\DDC117\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
$dqlRef = $this->_em->createQuery($dql)->setParameter(1, 'Foo')->getSingleResult();
$this->assertType(__NAMESPACE__."\DDC117Reference", $dqlRef);
$this->assertType(__NAMESPACE__."\DDC117Article", $dqlRef->target());
$this->assertType(__NAMESPACE__."\DDC117Article", $dqlRef->source());
$this->assertSame($dqlRef, $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Reference", $dqlRef);
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Article", $dqlRef->target());
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Article", $dqlRef->source());
$this->assertSame($dqlRef, $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria));
$dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
$dql = "SELECT r, s FROM "."Doctrine\Tests\Models\DDC117\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
$dqlRef = $this->_em->createQuery($dql)->setParameter(1, 'Foo')->getSingleResult();
$this->_em->contains($dqlRef);
@ -92,13 +89,13 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$mapRef = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
$mapRef = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$this->assertNotNull($mapRef);
$mapRef->setDescription("New Description!!");
$this->_em->flush();
$this->_em->clear();
$mapRef = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
$mapRef = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$this->assertEquals('New Description!!', $mapRef->getDescription());
}
@ -108,12 +105,12 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
*/
public function testFetchDql()
{
$dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
$dql = "SELECT r, s FROM "."Doctrine\Tests\Models\DDC117\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
$refs = $this->_em->createQuery($dql)->setParameter(1, 'Foo')->getResult();
$this->assertTrue(count($refs) > 0, "Has to contain at least one Reference.");
foreach ($refs AS $ref) {
$this->assertType(__NAMESPACE__."\DDC117Reference", $ref, "Contains only Reference instances.");
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Reference", $ref, "Contains only Reference instances.");
$this->assertTrue($this->_em->contains($ref), "Contains Reference in the IdentityMap.");
}
}
@ -125,13 +122,13 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$refRep = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
$refRep = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$this->_em->remove($refRep);
$this->_em->flush();
$this->_em->clear();
$this->assertNull($this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
$this->assertNull($this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria));
}
/**
@ -141,13 +138,13 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$dql = "DELETE ".__NAMESPACE__."\DDC117Reference r WHERE r.source = ?1 AND r.target = ?2";
$dql = "DELETE "."Doctrine\Tests\Models\DDC117\DDC117Reference r WHERE r.source = ?1 AND r.target = ?2";
$this->_em->createQuery($dql)
->setParameter(1, $this->article1->id())
->setParameter(2, $this->article2->id())
->execute();
$this->assertNull($this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
$this->assertNull($this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria));
}
/**
@ -155,24 +152,24 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
*/
public function testInverseSideAccess()
{
$this->article1 = $this->_em->find(__NAMESPACE__."\DDC117Article", $this->article1->id());
$this->article1 = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Article", $this->article1->id());
$this->assertEquals(1, count($this->article1->references()));
foreach ($this->article1->references() AS $this->reference) {
$this->assertType(__NAMESPACE__."\DDC117Reference", $this->reference);
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Reference", $this->reference);
$this->assertSame($this->article1, $this->reference->source());
}
$this->_em->clear();
$dql = 'SELECT a, r FROM '. __NAMESPACE__ . '\DDC117Article a INNER JOIN a.references r WHERE a.id = ?1';
$dql = 'SELECT a, r FROM '. 'Doctrine\Tests\Models\DDC117\DDC117Article a INNER JOIN a.references r WHERE a.id = ?1';
$articleDql = $this->_em->createQuery($dql)
->setParameter(1, $this->article1->id())
->getSingleResult();
$this->assertEquals(1, count($this->article1->references()));
foreach ($this->article1->references() AS $this->reference) {
$this->assertType(__NAMESPACE__."\DDC117Reference", $this->reference);
$this->assertType("Doctrine\Tests\Models\DDC117\DDC117Reference", $this->reference);
$this->assertSame($this->article1, $this->reference->source());
}
}
@ -184,20 +181,20 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
$idCriteria = array('article' => $this->article1->id(), 'language' => 'en');
$this->translation = $this->_em->find(__NAMESPACE__ . '\DDC117Translation', $idCriteria);
$this->assertType(__NAMESPACE__ . '\DDC117Translation', $this->translation);
$this->translation = $this->_em->find('Doctrine\Tests\Models\DDC117\DDC117Translation', $idCriteria);
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117Translation', $this->translation);
$this->assertSame($this->translation, $this->_em->find(__NAMESPACE__ . '\DDC117Translation', $idCriteria));
$this->assertSame($this->translation, $this->_em->find('Doctrine\Tests\Models\DDC117\DDC117Translation', $idCriteria));
$this->_em->clear();
$dql = 'SELECT t, a FROM ' . __NAMESPACE__ . '\DDC117Translation t JOIN t.article a WHERE t.article = ?1 AND t.language = ?2';
$dql = 'SELECT t, a FROM ' . 'Doctrine\Tests\Models\DDC117\DDC117Translation t JOIN t.article a WHERE t.article = ?1 AND t.language = ?2';
$dqlTrans = $this->_em->createQuery($dql)
->setParameter(1, $this->article1->id())
->setParameter(2, 'en')
->getSingleResult();
$this->assertType(__NAMESPACE__ . '\DDC117Translation', $this->translation);
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117Translation', $this->translation);
}
/**
@ -205,7 +202,7 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
*/
public function testMixedCompositeKeyViolateUniqueness()
{
$this->article1 = $this->_em->find(__NAMESPACE__ . '\DDC117Article', $this->article1->id());
$this->article1 = $this->_em->find('Doctrine\Tests\Models\DDC117\DDC117Article', $this->article1->id());
$this->article1->addTranslation('en', 'Bar');
$this->article1->addTranslation('en', 'Baz');
@ -235,6 +232,18 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals('not so very long text!', $article->getText());
}
/**
* @group DDC-117
*/
public function testOneToOneCascadeRemove()
{
$article = $this->_em->find(get_class($this->article1), $this->article1->id());
$this->_em->remove($article);
$this->_em->flush();
$this->assertFalse($this->_em->contains($article->getDetails()));
}
/**
* @group DDC-117
*/
@ -251,194 +260,151 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($this->article1);
$this->_em->flush();
}
}
/**
* @Entity
*/
class DDC117Article
{
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
private $id;
/** @Column */
private $title;
/**
* @OneToMany(targetEntity="DDC117Reference", mappedBy="source")
* @group DDC-117
*/
private $references;
public function testReferencesToForeignKeyEntities()
{
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$reference = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$idCriteria = array('article' => $this->article1->id(), 'language' => 'en');
$translation = $this->_em->find('Doctrine\Tests\Models\DDC117\DDC117Translation', $idCriteria);
$approveChanges = new DDC117ApproveChanges($reference->source()->getDetails(), $reference, $translation);
$this->_em->persist($approveChanges);
$this->_em->flush();
$this->_em->clear();
$approveChanges = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117ApproveChanges", $approveChanges->getId());
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails', $approveChanges->getArticleDetails());
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117Reference', $approveChanges->getReference());
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117Translation', $approveChanges->getTranslation());
}
/**
* @OneToOne(targetEntity="DDC117ArticleDetails", mappedBy="article", cascade={"persist"})
* @group DDC-117
*/
private $details;
public function testLoadOneToManyCollectionOfForeignKeyEntities()
{
/* @var $article DDC117Article */
$article = $this->_em->find(get_class($this->article1), $this->article1->id());
$translations = $article->getTranslations();
$this->assertFalse($translations->isInitialized());
$this->assertContainsOnly('Doctrine\Tests\Models\DDC117\DDC117Translation', $translations);
$this->assertTrue($translations->isInitialized());
}
/**
* @OneToMany(targetEntity="DDC117Translation", mappedBy="article", cascade={"persist"})
* @group DDC-117
*/
private $translations;
public function __construct($title)
public function testLoadManyToManyCollectionOfForeignKeyEntities()
{
$this->title = $title;
$this->references = new \Doctrine\Common\Collections\ArrayCollection();
$this->translations = new \Doctrine\Common\Collections\ArrayCollection();
$editor = $this->loadEditorFixture();
$this->assertFalse($editor->reviewingTranslations->isInitialized());
$this->assertContainsOnly("Doctrine\Tests\Models\DDC117\DDC117Translation", $editor->reviewingTranslations);
$this->assertTrue($editor->reviewingTranslations->isInitialized());
$this->_em->clear();
$dql = "SELECT e, t FROM Doctrine\Tests\Models\DDC117\DDC117Editor e JOIN e.reviewingTranslations t WHERE e.id = ?1";
$editor = $this->_em->createQuery($dql)->setParameter(1, $editor->id)->getSingleResult();
$this->assertTrue($editor->reviewingTranslations->isInitialized());
$this->assertContainsOnly("Doctrine\Tests\Models\DDC117\DDC117Translation", $editor->reviewingTranslations);
}
public function setDetails($details)
/**
* @group DDC-117
*/
public function testClearManyToManyCollectionOfForeignKeyEntities()
{
$this->details = $details;
$editor = $this->loadEditorFixture();
$this->assertEquals(3, count($editor->reviewingTranslations));
$editor->reviewingTranslations->clear();
$this->_em->flush();
$this->_em->clear();
$editor = $this->_em->find(get_class($editor), $editor->id);
$this->assertEquals(0, count($editor->reviewingTranslations));
}
public function id()
/**
* @group DDC-117
*/
public function testLoadInverseManyToManyCollection()
{
return $this->id;
$editor = $this->loadEditorFixture();
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117Translation', $editor->reviewingTranslations[0]);
$reviewedBy = $editor->reviewingTranslations[0]->getReviewedByEditors();
$this->assertEquals(1, count($reviewedBy));
$this->assertSame($editor, $reviewedBy[0]);
$this->_em->clear();
$dql = "SELECT t, e FROM Doctrine\Tests\Models\DDC117\DDC117Translation t ".
"JOIN t.reviewedByEditors e WHERE t.article = ?1 AND t.language = ?2";
$trans = $this->_em->createQuery($dql)
->setParameter(1, $this->translation->getArticleId())
->setParameter(2, $this->translation->getLanguage())
->getSingleResult();
$this->assertType('Doctrine\Tests\Models\DDC117\DDC117Translation', $trans);
$this->assertContainsOnly('Doctrine\Tests\Models\DDC117\DDC117Editor', $trans->reviewedByEditors);
$this->assertEquals(1, count($trans->reviewedByEditors));
}
public function addReference($reference)
/**
* @group DDC-117
*/
public function testLoadOneToManyOfSourceEntityWithAssociationIdentifier()
{
$this->references[] = $reference;
$editor = $this->loadEditorFixture();
$editor->addLastTranslation($editor->reviewingTranslations[0]);
$this->_em->flush();
$this->_em->clear();
$editor = $this->_em->find(get_class($editor), $editor->id);
$lastTranslatedBy = $editor->reviewingTranslations[0]->getLastTranslatedBy();
$lastTranslatedBy->count();
$this->assertEquals(1, count($lastTranslatedBy));
}
public function references()
/**
* @return DDC117Editor
*/
private function loadEditorFixture()
{
return $this->references;
}
$editor = new DDC117Editor("beberlei");
public function addTranslation($language, $title)
{
$this->translations[] = new DDC117Translation($this, $language, $title);
}
/* @var $article1 DDC117Article */
$article1 = $this->_em->find(get_class($this->article1), $this->article1->id());
foreach ($article1->getTranslations() AS $translation) {
$editor->reviewingTranslations[] = $translation;
}
public function getText()
{
return $this->details->getText();
/* @var $article2 DDC117Article */
$article2 = $this->_em->find(get_class($this->article2), $this->article2->id());
$article2->addTranslation("de", "Vanille-Krapferl"); // omnomnom
$article2->addTranslation("fr", "Sorry can't speak french!");
foreach ($article2->getTranslations() AS $translation) {
$this->_em->persist($translation); // otherwise persisting the editor won't work, reachability!
$editor->reviewingTranslations[] = $translation;
}
$this->_em->persist($editor);
$this->_em->flush();
$this->_em->clear();
return $this->_em->find(get_class($editor), $editor->id);
}
}
/**
* @Entity
*/
class DDC117ArticleDetails
{
/**
* @Id
* @OneToOne(targetEntity="DDC117Article", inversedBy="details")
* @JoinColumn(name="article_id", referencedColumnName="article_id")
*/
private $article;
/**
* @Column(type="text")
*/
private $text;
public function __construct($article, $text)
{
$this->article = $article;
$article->setDetails($this);
$this->update($text);
}
public function update($text)
{
$this->text = $text;
}
public function getText()
{
return $this->text;
}
}
/**
* @Entity
*/
class DDC117Reference
{
/**
* @Id
* @ManyToOne(targetEntity="DDC117Article", inversedBy="references")
* @JoinColumn(name="source_id", referencedColumnName="article_id")
*/
private $source;
/**
* @Id
* @ManyToOne(targetEntity="DDC117Article", inversedBy="references")
* @JoinColumn(name="target_id", referencedColumnName="article_id")
*/
private $target;
/**
* @column(type="string")
*/
private $description;
/**
* @column(type="datetime")
*/
private $created;
public function __construct($source, $target, $description)
{
$source->addReference($this);
$target->addReference($this);
$this->source = $source;
$this->target = $target;
$this->description = $description;
$this->created = new \DateTime("now");
}
public function source()
{
return $this->source;
}
public function target()
{
return $this->target;
}
public function setDescription($desc)
{
$this->description = $desc;
}
public function getDescription()
{
return $this->description;
}
}
/**
* @Entity
*/
class DDC117Translation
{
/**
* @Id
* @ManyToOne(targetEntity="DDC117Article")
* @JoinColumn(name="article_id", referencedColumnName="article_id")
*/
private $article;
/**
* @Id @column(type="string")
*/
private $language;
/**
* @column(type="string")
*/
private $title;
public function __construct($article, $language, $title)
{
$this->article = $article;
$this->language = $language;
$this->title = $title;
}
}

View File

@ -18,7 +18,7 @@ class DDC881Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC881Phonecall'),
));
} catch (\Exception $e) {
}
}
@ -74,6 +74,22 @@ class DDC881Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($call2);
$this->_em->flush();
$this->_em->clear();
// fetch-join that foreign-key/primary-key entity association
$dql = "SELECT c, p FROM " . __NAMESPACE__ . "\DDC881PhoneCall c JOIN c.phonenumber p";
$calls = $this->_em->createQuery($dql)->getResult();
$this->assertEquals(2, count($calls));
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $calls[0]->getPhoneNumber());
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $calls[1]->getPhoneNumber());
$dql = "SELECT p, c FROM " . __NAMESPACE__ . "\DDC881PhoneNumber p JOIN p.calls c";
$numbers = $this->_em->createQuery($dql)->getResult();
$this->assertEquals(2, count($numbers));
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $numbers[0]->getCalls());
$this->assertTrue($numbers[0]->getCalls()->isInitialized());
}
}
@ -131,6 +147,16 @@ class DDC881PhoneNumber
*/
private $phonenumber;
/**
* @OneToMany(targetEntity="DDC881PhoneCall", mappedBy="phonenumber")
*/
private $calls;
public function __construct()
{
$this->calls = new \Doctrine\Common\Collections\ArrayCollection();
}
public function setId($id)
{
$this->id = $id;
@ -146,6 +172,10 @@ class DDC881PhoneNumber
$this->phonenumber = $phoneNumber;
}
public function getCalls()
{
return $this->calls;
}
}
/**
@ -161,7 +191,7 @@ class DDC881PhoneCall
*/
private $id;
/**
* @OneToOne(targetEntity="DDC881PhoneNumber",cascade={"all"})
* @ManyToOne(targetEntity="DDC881PhoneNumber", inversedBy="calls", cascade={"all"})
* @JoinColumns({
* @JoinColumn(name="phonenumber_id", referencedColumnName="id"),
* @JoinColumn(name="user_id", referencedColumnName="user_id")
@ -178,4 +208,8 @@ class DDC881PhoneCall
$this->phonenumber = $phoneNumber;
}
public function getPhoneNumber()
{
return $this->phonenumber;
}
}

View File

@ -300,4 +300,71 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', "No mapping found for field 'foo' on class 'Doctrine\Tests\Models\CMS\CmsUser'.");
$cm->getFieldMapping('foo');
}
/**
* @group DDC-117
*/
public function testMapIdentifierAssociation()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails');
$cm->mapOneToOne(array(
'fieldName' => 'article',
'id' => true,
'targetEntity' => 'Doctrine\Tests\Models\DDC117\DDC117Article',
'joinColumns' => array(),
));
$this->assertTrue($cm->containsForeignIdentifier, "Identifier Association should set 'containsForeignIdentifier' boolean flag.");
$this->assertEquals(array("article"), $cm->identifier);
}
/**
* @group DDC-117
*/
public function testOrphanRemovalIdentifierAssociation()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails');
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'The orphan removal option is not allowed on an association that');
$cm->mapOneToOne(array(
'fieldName' => 'article',
'id' => true,
'targetEntity' => 'Doctrine\Tests\Models\DDC117\DDC117Article',
'orphanRemoval' => true,
'joinColumns' => array(),
));
}
/**
* @group DDC-117
*/
public function testInverseIdentifierAssocation()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails');
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'An inverse association is not allowed to be identifier in');
$cm->mapOneToOne(array(
'fieldName' => 'article',
'id' => true,
'mappedBy' => 'details', // INVERSE!
'targetEntity' => 'Doctrine\Tests\Models\DDC117\DDC117Article',
'joinColumns' => array(),
));
}
/**
* @group DDC-117
*/
public function testIdentifierAssocationManyToMany()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails');
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'Many-to-many or one-to-many associations are not allowed to be identifier in');
$cm->mapManyToMany(array(
'fieldName' => 'article',
'id' => true,
'targetEntity' => 'Doctrine\Tests\Models\DDC117\DDC117Article',
'joinColumns' => array(),
));
}
}

View File

@ -495,6 +495,22 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertInvalidDQL('SELECT g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g');
}
/**
* @group DDC-117
*/
public function testSizeOfForeignKeyOneToManyPrimaryKeyEntity()
{
$this->assertValidDQL("SELECT a, t FROM Doctrine\Tests\Models\DDC117\DDC117Article a JOIN a.translations t WHERE SIZE(a.translations) > 0");
}
/**
* @group DDC-117
*/
public function testSizeOfForeignKeyManyToManyPrimaryKeyEntity()
{
$this->assertValidDQL("SELECT e, t FROM Doctrine\Tests\Models\DDC117\DDC117Editor e JOIN e.reviewingTranslations t WHERE SIZE(e.reviewingTranslations) > 0");
}
}
/** @Entity */

View File

@ -91,6 +91,14 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\DirectoryTree\File',
'Doctrine\Tests\Models\DirectoryTree\Directory',
),
'ddc117' => array(
'Doctrine\Tests\Models\DDC117\DDC117Article',
'Doctrine\Tests\Models\DDC117\DDC117Reference',
'Doctrine\Tests\Models\DDC117\DDC117Translation',
'Doctrine\Tests\Models\DDC117\DDC117ArticleDetails',
'Doctrine\Tests\Models\DDC117\DDC117ApproveChanges',
'Doctrine\Tests\Models\DDC117\DDC117Editor',
),
);
protected function useModelSet($setName)
@ -173,6 +181,16 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM Directory WHERE parentDirectory_id IS NOT NULL');
$conn->executeUpdate('DELETE FROM Directory');
}
if (isset($this->_usedModelSets['ddc117'])) {
return;
$conn->executeUpdate('DELETE FROM ddc117editor_ddc117translation');
$conn->executeUpdate('DELETE FROM DDC117Editor');
$conn->executeUpdate('DELETE FROM DDC117ApproveChanges');
$conn->executeUpdate('DELETE FROM DDC117Reference');
$conn->executeUpdate('DELETE FROM DDC117ArticleDetails');
$conn->executeUpdate('DELETE FROM DDC117Translation');
$conn->executeUpdate('DELETE FROM DDC117Article');
}
$this->_em->clear();
}

View File

@ -93,6 +93,10 @@ class TestUtil
'driver' => 'pdo_sqlite',
'memory' => true
);
if (isset($GLOBALS['db_path'])) {
$params['path'] = $GLOBALS['db_path'];
unlink($GLOBALS['db_path']);
}
$conn = \Doctrine\DBAL\DriverManager::getConnection($params);
}