Skip to content

Commit

Permalink
Applying patch from 'Justas Butkus' to fix CakeSchema::compare()
Browse files Browse the repository at this point in the history
Fixes issues with comparing null == '' and adds a new protected method to handle null aware array difference generation.
Tests added.
Fixes #1206
  • Loading branch information
markstory committed Oct 28, 2010
1 parent 16387f1 commit f5fd069
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 6 deletions.
52 changes: 46 additions & 6 deletions cake/libs/model/cake_schema.php
Expand Up @@ -468,19 +468,19 @@ function compare($old, $new = null) {
if (!array_key_exists($table, $old)) {
$tables[$table]['add'] = $fields;
} else {
$diff = array_diff_assoc($fields, $old[$table]);
$diff = $this->_arrayDiffAssoc($fields, $old[$table]);
if (!empty($diff)) {
$tables[$table]['add'] = $diff;
}
$diff = array_diff_assoc($old[$table], $fields);
$diff = $this->_arrayDiffAssoc($old[$table], $fields);
if (!empty($diff)) {
$tables[$table]['drop'] = $diff;
}
}

foreach ($fields as $field => $value) {
if (isset($old[$table][$field])) {
$diff = array_diff_assoc($value, $old[$table][$field]);
$diff = $this->_arrayDiffAssoc($value, $old[$table][$field]);
if (!empty($diff) && $field !== 'indexes' && $field !== 'tableParameters') {
$tables[$table]['change'][$field] = array_merge($old[$table][$field], $diff);
}
Expand Down Expand Up @@ -520,6 +520,46 @@ function compare($old, $new = null) {
return $tables;
}

/**
* Extended array_diff_assoc noticing change from/to NULL values
*
* It behaves almost the same way as array_diff_assoc except for NULL values: if
* one of the values is not NULL - change is detected. It is useful in situation
* where one value is strval('') ant other is strval(null) - in string comparing
* methods this results as EQUAL, while it is not.
*
* @param array $array1 Base array
* @param array $array2 Corresponding array checked for equality
* @return array Difference as array with array(keys => values) from input array
* where match was not found.
* @access protected
*/
function _arrayDiffAssoc($array1, $array2) {
$difference = array();
foreach ($array1 as $key => $value) {
if (!array_key_exists($key, $array2)) {
$difference[$key] = $value;
continue;
}
$correspondingValue = $array2[$key];
if (is_null($value) !== is_null($correspondingValue)) {
$difference[$key] = $value;
continue;
}
if (is_bool($value) !== is_bool($correspondingValue)) {
$difference[$key] = $value;
continue;
}
$value = strval($value);
$correspondingValue = strval($correspondingValue);
if ($value === $correspondingValue) {
continue;
}
$difference[$key] = $value;
}
return $difference;
}

/**
* Formats Schema columns from Model Object
*
Expand Down Expand Up @@ -596,7 +636,7 @@ function _compareTableParameters($new, $old) {
if (!is_array($new) || !is_array($old)) {
return false;
}
$change = array_diff_assoc($new, $old);
$change = $this->_arrayDiffAssoc($new, $old);
return $change;
}

Expand All @@ -614,12 +654,12 @@ function _compareIndexes($new, $old) {

$add = $drop = array();

$diff = array_diff_assoc($new, $old);
$diff = $this->_arrayDiffAssoc($new, $old);
if (!empty($diff)) {
$add = $diff;
}

$diff = array_diff_assoc($old, $new);
$diff = $this->_arrayDiffAssoc($old, $new);
if (!empty($diff)) {
$drop = $diff;
}
Expand Down
29 changes: 29 additions & 0 deletions cake/tests/cases/libs/model/cake_schema.test.php
Expand Up @@ -798,6 +798,35 @@ function testSchemaComparison() {
$this->assertEqual($expected, $compare);
}

/**
* test comparing '' and null and making sure they are different.
*
* @return void
*/
function testCompareEmptyStringAndNull() {
$One =& new CakeSchema(array(
'posts' => array(
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false, 'default' => '')
)
));
$Two =& new CakeSchema(array(
'posts' => array(
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false, 'default' => null)
)
));
$compare = $One->compare($Two);
$expected = array(
'posts' => array(
'change' => array(
'name' => array('type' => 'string', 'null' => false, 'default' => null)
)
)
);
$this->assertEqual($expected, $compare);
}

/**
* Test comparing tableParameters and indexes.
*
Expand Down

0 comments on commit f5fd069

Please sign in to comment.