Permalink
Browse files

Ensuring Mongo object arrays don't get stored as strings, fixes #623.…

… Implementing schema null value support, fixes #629.
  • Loading branch information...
1 parent c28ba6d commit 7bc8e2502f738bba8a97b516021b90f2360d20e0 @nateabele nateabele committed Sep 13, 2012
View
6 data/DocumentSchema.php
@@ -31,11 +31,10 @@ public function cast($object, $key, $data, array $options = array()) {
$classes = $this->_classes;
$fieldName = is_int($key) ? null : $key;
+ $pathKey = $basePathKey;
if ($fieldName) {
$pathKey = $basePathKey ? "{$basePathKey}.{$fieldName}" : $fieldName;
- } else {
- $pathKey = $basePathKey;
}
if ($data instanceof $classes['set'] || $data instanceof $classes['entity']) {
@@ -92,6 +91,9 @@ protected function _castArray($object, $val, $pathKey, $options, $defaults) {
* handler, if available.
*/
protected function _castType($value, $field) {
+ if ($this->is('null', $field) && ($value === null || $value === "")) {
+ return null;
+ }
if (!is_scalar($value)) {
return $value;
}
View
2 data/entity/Document.php
@@ -121,7 +121,7 @@ public function &__get($name) {
if (isset($this->_embedded[$name]) && !isset($this->_relationships[$name])) {
throw new RuntimeException("Not implemented.");
}
- $result = parent::__get($name);
+ $result =& parent::__get($name);
if ($result !== null || array_key_exists($name, $this->_updated)) {
return $result;
View
23 data/source/mongo_db/Exporter.php
@@ -53,10 +53,10 @@ public static function toCommand($changes) {
protected static function _create($export, array $options) {
$export += array('data' => array(), 'update' => array(), 'key' => '');
$data = Set::merge($export['data'], $export['update']);
+
if (array_keys($data) == range(0, count($data) - 1)) {
$data = $export['update'];
}
-
$localOpts = array('finalize' => false) + $options;
foreach ($data as $key => $val) {
@@ -110,16 +110,25 @@ protected static function _update($export) {
$original = $export['data'];
$isArray = is_object($value) && get_class($value) == static::$_classes['set'];
- if ($isArray && isset($original[$key]) && $value->data() != $original[$key]->data()) {
- $value = $value->data();
- }
- if ($isArray && !isset($original[$key])) {
- $value = $value->data();
+ $options = array('handlers' => array(
+ 'MongoDate' => function($value) { return $value; },
+ 'MongoId' => function($value) { return $value; }
+ ));
+
+ if ($isArray) {
+ $newValue = $value->to('array', $options);
+ $originalValue = null;
+
+ if (isset($original[$key])) {
+ $originalValue = $original[$key]->to('array', $options);
+ }
+ if ($newValue !== $originalValue) {
+ $value = $value->to('array', $options);
+ }
}
$result = static::_append($result, "{$path}{$key}", $value, 'update');
}
return array_filter($result);
-
}
/**
View
57 tests/cases/data/source/mongo_db/ExporterTest.php
@@ -13,8 +13,8 @@
use lithium\data\source\MongoDb;
use lithium\data\entity\Document;
use lithium\data\collection\DocumentSet;
-use lithium\data\source\mongo_db\Exporter;
use lithium\data\source\mongo_db\Schema;
+use lithium\data\source\mongo_db\Exporter;
use lithium\tests\mocks\data\source\mongo_db\MockResult;
class ExporterTest extends \lithium\test\Unit {
@@ -570,14 +570,13 @@ public function testNestedArrayMongoIdCasting() {
$handlers = $this->_handlers;
$options = compact('model', 'handlers');
- $schema = new Schema(array(
- 'fields' =>array(
- '_id' => array('type' => 'MongoId'),
- 'title' => array('type' => 'text'),
- 'similar_text' => array('type' => 'array'),
- 'similar_text.articles' => array('type' => 'MongoId', 'array' => true),
- 'similar_text.books' => array('type' => 'MongoId', 'array' => true),
- 'similar_text.magazines' => array('type' => 'MongoId', 'array' => true)
+ $schema = new Schema(array('fields' => array(
+ '_id' => array('type' => 'MongoId'),
+ 'title' => array('type' => 'text'),
+ 'similar_text' => array('type' => 'array'),
+ 'similar_text.articles' => array('type' => 'MongoId', 'array' => true),
+ 'similar_text.books' => array('type' => 'MongoId', 'array' => true),
+ 'similar_text.magazines' => array('type' => 'MongoId', 'array' => true)
)));
$result = $schema->cast(null, null, $data, $options);
$this->assertTrue($result['similar_text']['articles'][0] instanceof MongoId);
@@ -586,6 +585,46 @@ public function testNestedArrayMongoIdCasting() {
$this->assertTrue($result['similar_text']['magazines'][0] instanceof MongoId);
$this->assertTrue($result['similar_text']['magazines'][1] instanceof MongoId);
}
+
+ /**
+ * Tests that updating arrays of `MongoId`s correctly preserves their type.
+ */
+ public function testUpdatingMongoIdArray() {
+ $schema = new Schema(array('fields' => array(
+ 'list' => array('type' => 'id', 'array' => true)
+ )));
+
+ $doc = new Document(array('exists' => true, 'data' => array(
+ 'list' => array(new MongoId(), new MongoId(), new MongoId())
+ )));
+ $this->assertEqual(array(), Exporter::get('update', $doc->export()));
+
+ $doc->list[] = new MongoId();
+ $doc->list[] = new MongoId();
+ $result = Exporter::get('update', $doc->export());
+
+ $this->assertEqual(1, count($result));
+ $this->assertEqual(1, count($result['update']));
+ $this->assertEqual(5, count($result['update']['list']));
+
+ for ($i = 0; $i < 5; $i++) {
+ $this->assertTrue($result['update']['list'][$i] instanceof MongoId);
+ }
+
+ $doc = new Document(array('exists' => true, 'data' => array(
+ 'list' => array(new MongoId(), new MongoId(), new MongoId())
+ )));
+ $doc->list = array(new MongoId(), new MongoId(), new MongoId());
+ $result = Exporter::get('update', $doc->export());
+
+ $this->assertEqual(1, count($result));
+ $this->assertEqual(1, count($result['update']));
+ $this->assertEqual(3, count($result['update']['list']));
+
+ for ($i = 0; $i < 3; $i++) {
+ $this->assertTrue($result['update']['list'][$i] instanceof MongoId);
+ }
+ }
}
?>
View
38 tests/cases/util/CollectionTest.php
@@ -299,31 +299,42 @@ function($i) { return is_array($i) ? join(',', $i) : $i; }, $collection->to('arr
$this->assertEqual($expected, $result);
}
+ public function testCollectionHandlers() {
+ $obj = new stdClass();
+ $obj->a = "b";
+ $handlers = array('stdClass' => function($v) { return (array) $v; });
+ $data = array('test' => new Collection(array('data' => compact('obj')))) + compact('obj');
+
+ $collection = new Collection(compact('data'));
+ $expected = array(
+ 'test' => array('obj' => array('a' => 'b')),
+ 'obj' => array('a' => 'b')
+ );
+ $this->assertIdentical($expected, $collection->to('array', compact('handlers')));
+
+ $handlers = array('stdClass' => function($v) { return $v; });
+ $expected = array('test' => compact('obj')) + compact('obj');
+ $this->assertIdentical($expected, $collection->to('array', compact('handlers')));
+ }
+
/**
* Tests that the Collection::sort method works appropriately.
- *
- * @return void
*/
public function testCollectionSort() {
- // Typical numeric sort using the default "sort" PHP function
+
$collection = new Collection(array('data' => array(5,3,4,1,2)));
$collection->sort();
$expected = array(1,2,3,4,5);
$this->assertEqual($expected, $collection->to('array'));
- // String sort using "sort"
- $collection = new Collection(array('data' => array('alan','dave','betsy','carl')));
- $collection->sort();
+ $collection = new Collection(array('data' => array('alan', 'dave', 'betsy', 'carl')));
$expected = array('alan','betsy','carl','dave');
- $this->assertEqual($expected, $collection->to('array'));
+ $this->assertEqual($expected, $collection->sort()->to('array'));
- // String sort using strcasecmp
- $collection = new Collection(array('data' => array('Alan','Dave','betsy','carl')));
- $collection->sort('strcasecmp');
- $expected = array('Alan','betsy','carl','Dave');
- $this->assertEqual($expected, $collection->to('array'));
+ $collection = new Collection(array('data' => array('Alan', 'Dave', 'betsy', 'carl')));
+ $expected = array('Alan', 'betsy', 'carl', 'Dave');
+ $this->assertEqual($expected, $collection->sort('strcasecmp')->to('array'));
- // Numeric sort using custom function
$collection = new Collection(array('data' => array(5,3,4,1,2)));
$collection->sort(function ($a,$b) {
if ($a == $b) {
@@ -334,7 +345,6 @@ public function testCollectionSort() {
$expected = array(5,4,3,2,1);
$this->assertEqual($expected, $collection->to('array'));
- // Test fail
$collection = new Collection(array('data' => array(5,3,4,1,2)));
$result = $collection->sort('blahgah');
$this->assertEqual($collection->to('array'), $result->to('array'));
View
2 util/Collection.php
@@ -543,7 +543,7 @@ public static function toArray($data, array $options = array()) {
$result[$key] = $options['handlers'][$class]($item);
break;
case (method_exists($item, 'to')):
- $result[$key] = $item->to('array');
+ $result[$key] = $item->to('array', $options);
break;
case ($vars = get_object_vars($item)):
$result[$key] = static::toArray($vars, $options);

0 comments on commit 7bc8e25

Please sign in to comment.