Skip to content
This repository
Browse code

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 authored October 27, 2010
52  cake/libs/model/cake_schema.php
@@ -468,11 +468,11 @@ function compare($old, $new = null) {
468 468
 			if (!array_key_exists($table, $old)) {
469 469
 				$tables[$table]['add'] = $fields;
470 470
 			} else {
471  
-				$diff = array_diff_assoc($fields, $old[$table]);
  471
+				$diff = $this->_arrayDiffAssoc($fields, $old[$table]);
472 472
 				if (!empty($diff)) {
473 473
 					$tables[$table]['add'] = $diff;
474 474
 				}
475  
-				$diff = array_diff_assoc($old[$table], $fields);
  475
+				$diff = $this->_arrayDiffAssoc($old[$table], $fields);
476 476
 				if (!empty($diff)) {
477 477
 					$tables[$table]['drop'] = $diff;
478 478
 				}
@@ -480,7 +480,7 @@ function compare($old, $new = null) {
480 480
 
481 481
 			foreach ($fields as $field => $value) {
482 482
 				if (isset($old[$table][$field])) {
483  
-					$diff = array_diff_assoc($value, $old[$table][$field]);
  483
+					$diff = $this->_arrayDiffAssoc($value, $old[$table][$field]);
484 484
 					if (!empty($diff) && $field !== 'indexes' && $field !== 'tableParameters') {
485 485
 						$tables[$table]['change'][$field] = array_merge($old[$table][$field], $diff);
486 486
 					}
@@ -521,6 +521,46 @@ function compare($old, $new = null) {
521 521
 	}
522 522
 
523 523
 /**
  524
+ * Extended array_diff_assoc noticing change from/to NULL values
  525
+ *
  526
+ * It behaves almost the same way as array_diff_assoc except for NULL values: if
  527
+ * one of the values is not NULL - change is detected. It is useful in situation
  528
+ * where one value is strval('') ant other is strval(null) - in string comparing
  529
+ * methods this results as EQUAL, while it is not.
  530
+ *
  531
+ * @param array $array1 Base array
  532
+ * @param array $array2 Corresponding array checked for equality
  533
+ * @return array Difference as array with array(keys => values) from input array
  534
+ *     where match was not found.
  535
+ * @access protected
  536
+ */
  537
+	function _arrayDiffAssoc($array1, $array2) {
  538
+		$difference = array();
  539
+		foreach ($array1 as $key => $value) {
  540
+			if (!array_key_exists($key, $array2)) {
  541
+				$difference[$key] = $value;
  542
+				continue;
  543
+			}
  544
+			$correspondingValue = $array2[$key];
  545
+			if (is_null($value) !== is_null($correspondingValue)) {
  546
+				$difference[$key] = $value;
  547
+				continue;
  548
+			}
  549
+			if (is_bool($value) !== is_bool($correspondingValue)) {
  550
+				$difference[$key] = $value;
  551
+				continue;
  552
+			}
  553
+			$value = strval($value);
  554
+			$correspondingValue = strval($correspondingValue);
  555
+			if ($value === $correspondingValue) {
  556
+				continue;
  557
+			}
  558
+			$difference[$key] = $value;
  559
+		}
  560
+		return $difference;
  561
+	}
  562
+
  563
+/**
524 564
  * Formats Schema columns from Model Object
525 565
  *
526 566
  * @param array $values options keys(type, null, default, key, length, extra)
@@ -596,7 +636,7 @@ function _compareTableParameters($new, $old) {
596 636
 		if (!is_array($new) || !is_array($old)) {
597 637
 			return false;
598 638
 		}
599  
-		$change = array_diff_assoc($new, $old);
  639
+		$change = $this->_arrayDiffAssoc($new, $old);
600 640
 		return $change;
601 641
 	}
602 642
 
@@ -614,12 +654,12 @@ function _compareIndexes($new, $old) {
614 654
 
615 655
 		$add = $drop = array();
616 656
 
617  
-		$diff = array_diff_assoc($new, $old);
  657
+		$diff = $this->_arrayDiffAssoc($new, $old);
618 658
 		if (!empty($diff)) {
619 659
 			$add = $diff;
620 660
 		}
621 661
 
622  
-		$diff = array_diff_assoc($old, $new);
  662
+		$diff = $this->_arrayDiffAssoc($old, $new);
623 663
 		if (!empty($diff)) {
624 664
 			$drop = $diff;
625 665
 		}
29  cake/tests/cases/libs/model/cake_schema.test.php
@@ -799,6 +799,35 @@ function testSchemaComparison() {
799 799
 	}
800 800
 
801 801
 /**
  802
+ * test comparing '' and null and making sure they are different.
  803
+ *
  804
+ * @return void
  805
+ */
  806
+	function testCompareEmptyStringAndNull() {
  807
+		$One =& new CakeSchema(array(
  808
+			'posts' => array(
  809
+				'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
  810
+				'name' => array('type' => 'string', 'null' => false, 'default' => '')
  811
+			)
  812
+		));
  813
+		$Two =& new CakeSchema(array(
  814
+			'posts' => array(
  815
+				'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
  816
+				'name' => array('type' => 'string', 'null' => false, 'default' => null)
  817
+			)
  818
+		));
  819
+		$compare = $One->compare($Two);
  820
+		$expected = array(
  821
+			'posts' => array(
  822
+				'change' => array(
  823
+					'name' => array('type' => 'string', 'null' => false, 'default' => null)
  824
+				)
  825
+			)
  826
+		);
  827
+		$this->assertEqual($expected, $compare);
  828
+	}
  829
+
  830
+/**
802 831
  * Test comparing tableParameters and indexes.
803 832
  *
804 833
  * @return void

0 notes on commit f5fd069

Please sign in to comment.
Something went wrong with that request. Please try again.