ソースを参照

Merge pull request #3716 from cakephp/3.0-associated-dot-notation

3.0 associated dot notation
Mark Story 11 年 前
コミット
aef69a1f15

+ 4 - 10
src/ORM/Associations.php

@@ -15,6 +15,7 @@
 namespace Cake\ORM;
 
 use Cake\ORM\Association;
+use Cake\ORM\AssociationsNormalizerTrait;
 use Cake\ORM\Entity;
 use Cake\ORM\Table;
 
@@ -26,6 +27,8 @@ use Cake\ORM\Table;
  */
 class Associations {
 
+	use AssociationsNormalizerTrait;
+
 /**
  * Stored associations
  *
@@ -262,16 +265,7 @@ class Associations {
 			return [];
 		}
 
-		$result = [];
-		foreach ($keys as $key => $value) {
-			if (is_int($key)) {
-				$key = $value;
-				$value = [];
-			}
-			$result[$key] = $value;
-		}
-
-		return $result;
+		return $this->_normalizeAssociations($keys);
 	}
 
 }

+ 66 - 0
src/ORM/AssociationsNormalizerTrait.php

@@ -0,0 +1,66 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.0.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\ORM;
+
+/**
+ * Contains methods for parsing the associated tables array that is typically
+ * passed to  a save operation
+ */
+trait AssociationsNormalizerTrait {
+
+/**
+ * Returns an array out of the original passed associations list where dot notation
+ * is transformed into nested arrays so that they can be parsed by other routines
+ *
+ * @param array $associations The array of included associations.
+ * @return array An array having dot notation transformed into nested arrays
+ */
+	protected function _normalizeAssociations($associations) {
+		$result = [];
+		foreach ($associations as $table => $options) {
+			$pointer =& $result;
+
+			if (is_int($table)) {
+				$table = $options;
+				$options = [];
+			}
+
+			if (!strpos($table, '.')) {
+				$result[$table] = $options;
+				continue;
+			}
+
+			$path = explode('.', $table);
+			$table = array_pop($path);
+			$first = array_shift($path);
+			$pointer += [$first => []];
+			$pointer =& $pointer[$first];
+			$pointer += ['associated' => []];
+
+			foreach ($path as $t) {
+				$pointer += ['associated' => []];
+				$pointer['associated'] += [$t => []];
+				$pointer['associated'][$t] += ['associated' => []];
+				$pointer =& $pointer['associated'][$t];
+			}
+
+			$pointer['associated'] += [$table => []];
+			$pointer['associated'][$table] = $options + $pointer['associated'][$table];
+		}
+
+		return isset($result['associated']) ? $result['associated'] : $result;
+	}
+
+}

+ 4 - 0
src/ORM/Marshaller.php

@@ -19,6 +19,7 @@ use Cake\Database\Expression\TupleComparison;
 use Cake\Database\Type;
 use Cake\Datasource\EntityInterface;
 use Cake\ORM\Association;
+use Cake\ORM\AssociationsNormalizerTrait;
 use Cake\ORM\Table;
 
 /**
@@ -33,6 +34,8 @@ use Cake\ORM\Table;
  */
 class Marshaller {
 
+	use AssociationsNormalizerTrait;
+
 /**
  * Whether or not this marhshaller is in safe mode.
  *
@@ -66,6 +69,7 @@ class Marshaller {
  */
 	protected function _buildPropertyMap($include) {
 		$map = [];
+		$include = $this->_normalizeAssociations($include);
 		foreach ($include as $key => $nested) {
 			if (is_int($key) && is_scalar($nested)) {
 				$key = $nested;

+ 2 - 2
src/ORM/Table.php

@@ -1566,7 +1566,7 @@ class Table implements RepositoryInterface, EventListener {
  * {{{
  * $articles = $this->Articles->newEntity(
  *   $this->request->data(),
- *   ['Tags', 'Comments' => ['associated' => ['Users']]]
+ *   ['Tags', 'Comments.Users']
  * );
  * }}}
  *
@@ -1589,7 +1589,7 @@ class Table implements RepositoryInterface, EventListener {
  * {{{
  * $articles = $this->Articles->newEntities(
  *   $this->request->data(),
- *   ['Tags', 'Comments' => ['associated' => ['Users']]]
+ *   ['Tags', 'Comments.Users']
  * );
  * }}}
  *

+ 3 - 15
tests/TestCase/ORM/MarshallerTest.php

@@ -352,13 +352,7 @@ class MarshallerTest extends TestCase {
 		$articlesTags->belongsTo('Users');
 
 		$marshall = new Marshaller($this->articles);
-		$result = $marshall->one($data, [
-			'Tags' => [
-				'associated' => [
-					'_joinData' => ['associated' => ['Users']]
-				]
-			]
-		]);
+		$result = $marshall->one($data, ['Tags._joinData.Users']);
 		$this->assertInstanceOf(
 			'Cake\ORM\Entity',
 			$result->tags[0]->_joinData->user,
@@ -392,7 +386,7 @@ class MarshallerTest extends TestCase {
 			]
 		];
 		$marshall = new Marshaller($this->comments);
-		$result = $marshall->one($data, ['Articles' => ['associated' => ['Users']]]);
+		$result = $marshall->one($data, ['Articles.Users']);
 
 		$this->assertEquals(
 			$data['article']['title'],
@@ -870,13 +864,7 @@ class MarshallerTest extends TestCase {
 		$articlesTags = TableRegistry::get('ArticlesTags');
 		$articlesTags->belongsTo('Users');
 
-		$options = [
-			'Tags' => [
-				'associated' => [
-					'_joinData' => ['associated' => ['Users']]
-				]
-			]
-		];
+		$options = ['Tags._joinData.Users'];
 		$marshall = new Marshaller($this->articles);
 		$entity = $marshall->one($data, $options);
 		$entity->accessible('*', true);

+ 3 - 3
tests/TestCase/ORM/QueryRegressionTest.php

@@ -151,7 +151,7 @@ class QueryRegressionTest extends TestCase {
 				]
 			]
 		];
-		$entity = $articles->patchEntity($entity, $data, ['Highlights' => ['associated' => ['_joinData']]]);
+		$entity = $articles->patchEntity($entity, $data, ['Highlights._joinData']);
 		$articles->save($entity);
 		$entity = $articles->get(2, ['contain' => ['Highlights']]);
 		$this->assertEquals(4, $entity->highlights[0]->_joinData->tag_id);
@@ -227,11 +227,11 @@ class QueryRegressionTest extends TestCase {
 			]
 		];
 		$entity = $articles->patchEntity($entity, $data, [
-			'Highlights' => ['associated' => ['_joinData' => ['associated' => ['Authors']], 'Authors']]
+			'Highlights._joinData.Authors', 'Highlights.Authors'
 		]);
 		$articles->save($entity, [
 			'associated' => [
-				'Highlights' => ['associated' => ['_joinData' => ['associated' => ['Authors']], 'Authors']]
+				'Highlights._joinData.Authors', 'Highlights.Authors'
 			]
 		]);
 		$entity = $articles->get(2, [

+ 6 - 8
tests/TestCase/ORM/TableTest.php

@@ -2919,14 +2919,12 @@ class TableTest extends \Cake\TestSuite\TestCase {
 		$this->assertSame($entity, $articles->save($entity, [
 			'associated' => [
 				'authors' => [
-					'validate' => 'special',
-					'associated' => [
-						'supervisors' => [
-							'atomic' => false,
-							'validate' => false,
-							'associated' => false
-						]
-					]
+					'validate' => 'special'
+				],
+				'authors.supervisors' => [
+					'atomic' => false,
+					'validate' => false,
+					'associated' => false
 				]
 			]
 		]));