1
0
mirror of synced 2024-12-14 07:06:04 +03:00

DDC-130 - Refactored deleteJoinTableRecords() support

This commit is contained in:
Benjamin Eberlei 2010-07-10 12:04:02 +02:00
parent 233b3cd0b9
commit 1794127d51
3 changed files with 63 additions and 35 deletions

View File

@ -68,6 +68,20 @@ class ManyToManyMapping extends AssociationMapping
*/
public $orderBy;
/**
* READ-ONLY: Are entries on the owning side of this join-table deleted through a database onDelete="CASCADE" operation?
*
* @var bool
*/
public $owningIsOnDeleteCascade = false;
/**
* READ-ONLY: Are entries on the inverse side of this join-table deleted through a database onDelete="CASCADE" operation?
*
* @var bool
*/
public $inverseIsOnDeleteCascade = false;
/**
* {@inheritdoc}
*/
@ -115,11 +129,19 @@ class ManyToManyMapping extends AssociationMapping
}
foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) {
if (isset($joinColumn['onDelete']) && strtolower($joinColumn['onDelete']) == 'cascade') {
$this->owningIsOnDeleteCascade = true;
}
$this->relationToSourceKeyColumns[$joinColumn['name']] = $joinColumn['referencedColumnName'];
$this->joinTableColumns[] = $joinColumn['name'];
}
foreach ($mapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) {
if (isset($inverseJoinColumn['onDelete']) && strtolower($inverseJoinColumn['onDelete']) == 'cascade') {
$this->inverseIsOnDeleteCascade = true;
}
$this->relationToTargetKeyColumns[$inverseJoinColumn['name']] = $inverseJoinColumn['referencedColumnName'];
$this->joinTableColumns[] = $inverseJoinColumn['name'];
}
@ -169,6 +191,12 @@ class ManyToManyMapping extends AssociationMapping
$serialized[] = 'joinTableColumns';
$serialized[] = 'relationToSourceKeyColumns';
$serialized[] = 'relationToTargetKeyColumns';
if ($this->owningIsOnDeleteCascade) {
$serialized[] = 'owningIsOnDeleteCascade';
}
if ($this->inverseIsOnDeleteCascade) {
$serialized[] = 'inverseIsOnDeleteCascade';
}
if ($this->orderBy) {
$serialized[] = 'orderBy';
}

View File

@ -335,8 +335,6 @@ class BasicEntityPersister
}
}
private $requiredJoinTableDeletions = null;
/**
* @todo Add check for platform if it supports foreign keys/cascading.
* @param array $identifier
@ -344,44 +342,27 @@ class BasicEntityPersister
*/
protected function deleteJoinTableRecords($identifier)
{
if ($this->requiredJoinTableDeletions === null) {
$this->requiredJoinTableDeletions = array();
foreach ($this->_class->associationMappings AS $mapping) {
/* @var $mapping \Doctrine\ORM\Mapping\AssociationMapping */
if ($mapping->isManyToMany()) {
// TODO: Write test for composite keys
if (!$mapping->isOwningSide) {
$relatedClass = $this->_em->getClassMetadata($mapping->targetEntityName);
$mapping = $relatedClass->associationMappings[$mapping->mappedBy];
$keys = array_keys($mapping->relationToTargetKeyColumns);
foreach ($this->_class->associationMappings AS $mapping) {
/* @var $mapping \Doctrine\ORM\Mapping\AssociationMapping */
if ($mapping->isManyToMany()) {
if($mapping->isOwningSide && (!$mapping->owningIsOnDeleteCascade || !$this->_platform->supportsForeignKeyConstraints())) {
$this->_conn->delete(
$mapping->joinTable['name'],
array_combine(array_keys($mapping->relationToSourceKeyColumns), $identifier)
);
} else if (!$mapping->isOwningSide) {
$relatedClass = $this->_em->getClassMetadata($mapping->targetEntityName);
$relatedMapping = $relatedClass->associationMappings[$mapping->mappedBy];
// this is not semantically correct, onDelete should be an option of the joinColumns
// @todo optimize this (potentially in the validate association/metadata already)
foreach ($mapping->joinTable['inverseJoinColumns'] AS $joinColumn) {
if (strtoupper($joinColumn['onDelete']) == 'CASCADE') {
continue;
}
}
} else {
// this is not semantically correct, onDelete should be an option of the joinColumns
// @todo optimize this (potentially in the validate association/metadata already)
foreach ($mapping->joinTable['joinColumns'] AS $joinColumn) {
if (strtoupper($joinColumn['onDelete']) == 'CASCADE') {
continue;
}
}
$keys = array_keys($mapping->relationToSourceKeyColumns);
if (!$relatedMapping->inverseIsOnDeleteCascade || !$this->_platform->supportsForeignKeyConstraints()) {
$this->_conn->delete(
$relatedMapping->joinTable['name'],
array_combine(array_keys($relatedMapping->relationToTargetKeyColumns), $identifier)
);
}
$this->requiredJoinTableDeletions[$mapping->joinTable['name']] = $keys;
}
}
}
foreach ($this->requiredJoinTableDeletions AS $table => $keys) {
$id = array_combine($keys, $identifier);
$this->_conn->delete($table, $id);
}
}
/**

View File

@ -107,6 +107,25 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
'joinColumns' => array(array('name' => 'CmsUser_id', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE')),
'inverseJoinColumns' => array(array('name' => 'CmsGroup_id', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE'))
), $assoc->joinTable);
$this->assertTrue($assoc->owningIsOnDeleteCascade);
$this->assertTrue($assoc->inverseIsOnDeleteCascade);
}
public function testSerializeManyToManyJoinTableCascade()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->mapManyToMany(
array(
'fieldName' => 'groups',
'targetEntity' => 'CmsGroup'
));
/* @var $assoc \Doctrine\ORM\Mapping\ManyToManyMapping */
$assoc = $cm->associationMappings['groups'];
$assoc = unserialize(serialize($assoc));
$this->assertTrue($assoc->owningIsOnDeleteCascade);
$this->assertTrue($assoc->inverseIsOnDeleteCascade);
}
/**