keep existing data in unique HABTM closes LH 275

ported to 2.0 branch from cakephp/cakephp#93
This commit is contained in:
Rachman Chavik 2011-05-23 13:50:59 +07:00
parent ab5bfdccfd
commit 90af608489
3 changed files with 31 additions and 11 deletions

View file

@ -154,7 +154,7 @@ if (!empty($associations['hasAndBelongsToMany'])):
$out .= "\t\t\t'joinTable' => '{$relation['joinTable']}',\n"; $out .= "\t\t\t'joinTable' => '{$relation['joinTable']}',\n";
$out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n";
$out .= "\t\t\t'associationForeignKey' => '{$relation['associationForeignKey']}',\n"; $out .= "\t\t\t'associationForeignKey' => '{$relation['associationForeignKey']}',\n";
$out .= "\t\t\t'unique' => true,\n"; $out .= "\t\t\t'unique' => 'keepExisting',\n";
$out .= "\t\t\t'conditions' => '',\n"; $out .= "\t\t\t'conditions' => '',\n";
$out .= "\t\t\t'fields' => '',\n"; $out .= "\t\t\t'fields' => '',\n";
$out .= "\t\t\t'order' => '',\n"; $out .= "\t\t\t'order' => '',\n";

View file

@ -2782,15 +2782,15 @@ class DboSource extends DataSource {
$statement = $this->_connection->prepare($sql); $statement = $this->_connection->prepare($sql);
$this->begin(); $this->begin();
foreach ($values[0] as $key => $val) { foreach ($values[key($values)] as $key => $val) {
$type = $this->introspectType($val); $type = $this->introspectType($val);
$columnMap[$key] = $pdoMap[$type]; $columnMap[$key] = $pdoMap[$type];
} }
for ($x = 0; $x < $count; $x++) { foreach ($values as $row => $value) {
$i = 1; $i = 1;
foreach ($values[$x] as $key => $val) { foreach ($value as $col => $val) {
$statement->bindValue($i, $val, $columnMap[$key]); $statement->bindValue($i, $val, $columnMap[$col]);
$i += 1; $i += 1;
} }
$statement->execute(); $statement->execute();

View file

@ -1715,7 +1715,7 @@ class Model extends Object {
) )
); );
$newData = $newValues = array(); $newData = $newValues = $newJoins = array();
$primaryAdded = false; $primaryAdded = false;
$fields = array( $fields = array(
@ -1731,11 +1731,12 @@ class Model extends Object {
foreach ((array)$data as $row) { foreach ((array)$data as $row) {
if ((is_string($row) && (strlen($row) == 36 || strlen($row) == 16)) || is_numeric($row)) { if ((is_string($row) && (strlen($row) == 36 || strlen($row) == 16)) || is_numeric($row)) {
$newJoins[] = $row;
$values = array($id, $row); $values = array($id, $row);
if ($isUUID && $primaryAdded) { if ($isUUID && $primaryAdded) {
$values[] = String::uuid(); $values[] = String::uuid();
} }
$newValues[] = $values; $newValues[$row] = $values;
unset($values); unset($values);
} elseif (isset($row[$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { } elseif (isset($row[$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
$newData[] = $row; $newData[] = $row;
@ -1744,6 +1745,7 @@ class Model extends Object {
} }
} }
$keepExisting = $this->hasAndBelongsToMany[$assoc]['unique'] === 'keepExisting';
if ($this->hasAndBelongsToMany[$assoc]['unique']) { if ($this->hasAndBelongsToMany[$assoc]['unique']) {
$conditions = array( $conditions = array(
$join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id $join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id
@ -1751,16 +1753,20 @@ class Model extends Object {
if (!empty($this->hasAndBelongsToMany[$assoc]['conditions'])) { if (!empty($this->hasAndBelongsToMany[$assoc]['conditions'])) {
$conditions = array_merge($conditions, (array)$this->hasAndBelongsToMany[$assoc]['conditions']); $conditions = array_merge($conditions, (array)$this->hasAndBelongsToMany[$assoc]['conditions']);
} }
$associationForeignKey = $this->{$join}->alias .'.'. $this->hasAndBelongsToMany[$assoc]['associationForeignKey'];
$links = $this->{$join}->find('all', array( $links = $this->{$join}->find('all', array(
'conditions' => $conditions, 'conditions' => $conditions,
'recursive' => empty($this->hasAndBelongsToMany[$assoc]['conditions']) ? -1 : 0, 'recursive' => empty($this->hasAndBelongsToMany[$assoc]['conditions']) ? -1 : 0,
'fields' => $this->hasAndBelongsToMany[$assoc]['associationForeignKey'] 'fields' => $associationForeignKey,
)); ));
$associationForeignKey = "{$join}." . $this->hasAndBelongsToMany[$assoc]['associationForeignKey'];
$oldLinks = Set::extract($links, "{n}.{$associationForeignKey}"); $oldLinks = Set::extract($links, "{n}.{$associationForeignKey}");
if (!empty($oldLinks)) { if (!empty($oldLinks)) {
$conditions[$associationForeignKey] = $oldLinks; if ($keepExisting && !empty($newJoins)) {
$conditions[$associationForeignKey] = array_diff($oldLinks, $newJoins);
} else {
$conditions[$associationForeignKey] = $oldLinks;
}
$dbMulti->delete($this->{$join}, $conditions); $dbMulti->delete($this->{$join}, $conditions);
} }
} }
@ -1774,7 +1780,21 @@ class Model extends Object {
} }
if (!empty($newValues)) { if (!empty($newValues)) {
$dbMulti->insertMulti($this->{$join}, $fields, $newValues); if ($keepExisting && !empty($links)) {
foreach ($links as $link) {
$oldJoin = $link[$join][$this->hasAndBelongsToMany[$assoc]['associationForeignKey']];
if (! in_array($oldJoin, $newJoins) ) {
$conditions[$associationForeignKey] = $oldJoin;
$db->delete($this->{$join}, $conditions);
} else {
unset($newValues[$oldJoin]);
}
}
$newValues = array_values($newValues);
}
if (!empty($newValues)) {
$dbMulti->insertMulti($this->{$join}, $fields, $newValues);
}
} }
} }
} }