Browse Source

Fix error in marshalling belongsToMany relations.

When removing all belongsTo associations `_ids` can be an empty scalar
value. The marshaller should handle empty scalar values gracefully.

Refs #3485
mark_story 12 years ago
parent
commit
85aecb628f
2 changed files with 61 additions and 2 deletions
  1. 6 2
      src/ORM/Marshaller.php
  2. 55 0
      tests/TestCase/ORM/MarshallerTest.php

+ 6 - 2
src/ORM/Marshaller.php

@@ -170,7 +170,7 @@ class Marshaller {
  * @return array An array of built entities.
  */
 	protected function _belongsToMany(Association $assoc, array $data, $include = []) {
-		$hasIds = isset($data['_ids']);
+		$hasIds = array_key_exists('_ids', $data);
 		if ($hasIds && is_array($data['_ids'])) {
 			return $this->_loadBelongsToMany($assoc, $data['_ids']);
 		}
@@ -361,9 +361,13 @@ class Marshaller {
  * @return mixed
  */
 	protected function _mergeBelongsToMany($original, $assoc, $value, $include) {
-		if (isset($value['_ids']) && is_array($value['_ids'])) {
+		$hasIds = array_key_exists('_ids', $value);
+		if ($hasIds && is_array($value['_ids'])) {
 			return $this->_loadBelongsToMany($assoc, $value['_ids']);
 		}
+		if ($hasIds) {
+			return [];
+		}
 
 		if (!in_array('_joinData', $include) && !isset($include['_joinData'])) {
 			return $this->mergeMany($original, $value, $include);

+ 55 - 0
tests/TestCase/ORM/MarshallerTest.php

@@ -477,7 +477,22 @@ class MarshallerTest extends TestCase {
 		];
 		$marshall = new Marshaller($this->articles);
 		$result = $marshall->one($data, ['Tags']);
+		$this->assertCount(0, $result->tags);
 
+		$data = [
+			'title' => 'Haz tags',
+			'body' => 'Some content here',
+			'tags' => ['_ids' => false]
+		];
+		$result = $marshall->one($data, ['Tags']);
+		$this->assertCount(0, $result->tags);
+
+		$data = [
+			'title' => 'Haz tags',
+			'body' => 'Some content here',
+			'tags' => ['_ids' => null]
+		];
+		$result = $marshall->one($data, ['Tags']);
 		$this->assertCount(0, $result->tags);
 
 		$data = [
@@ -726,6 +741,46 @@ class MarshallerTest extends TestCase {
 	}
 
 /**
+ * Tests that merging data to an entity containing belongsToMany and _ids
+ * will ignore empty values.
+ *
+ * @return void
+ */
+	public function testMergeBelongsToManyEntitiesFromIdsEmptyValue() {
+		$entity = new Entity([
+			'title' => 'Haz tags',
+			'body' => 'Some content here',
+			'tags' => [
+				new Entity(['id' => 1, 'name' => 'Cake']),
+				new Entity(['id' => 2, 'name' => 'PHP'])
+			]
+		]);
+
+		$data = [
+			'title' => 'Haz moar tags',
+			'tags' => ['_ids' => '']
+		];
+		$entity->accessible('*', true);
+		$marshall = new Marshaller($this->articles);
+		$result = $marshall->merge($entity, $data, ['Tags']);
+		$this->assertCount(0, $result->tags);
+
+		$data = [
+			'title' => 'Haz moar tags',
+			'tags' => ['_ids' => false]
+		];
+		$result = $marshall->merge($entity, $data, ['Tags']);
+		$this->assertCount(0, $result->tags);
+
+		$data = [
+			'title' => 'Haz moar tags',
+			'tags' => ['_ids' => null]
+		];
+		$result = $marshall->merge($entity, $data, ['Tags']);
+		$this->assertCount(0, $result->tags);
+	}
+
+/**
  * Test merging the _joinData entity for belongstomany associations.
  *
  * @return void