Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Applying patch from 'Justas Butkus' to fix CakeSchema::compare()

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...
commit f5fd0695832cdac465e641a144d0ecc3fabb03fc 1 parent 16387f1
Mark Story markstory authored
52 cake/libs/model/cake_schema.php
View
@@ -468,11 +468,11 @@ 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;
}
@@ -480,7 +480,7 @@ function compare($old, $new = null) {
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);
}
@@ -521,6 +521,46 @@ function compare($old, $new = null) {
}
/**
+ * 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
*
* @param array $values options keys(type, null, default, key, length, extra)
@@ -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;
}
@@ -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;
}
29 cake/tests/cases/libs/model/cake_schema.test.php
View
@@ -799,6 +799,35 @@ function testSchemaComparison() {
}
/**
+ * 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.
*
* @return void
Please sign in to comment.
Something went wrong with that request. Please try again.