Browse Source

move find threaded logic to the set class

AD7six 14 years ago
parent
commit
7b640b8123
3 changed files with 66 additions and 49 deletions
  1. 6 37
      lib/Cake/Model/Model.php
  2. 0 12
      lib/Cake/Test/Case/Model/ModelReadTest.php
  3. 60 0
      lib/Cake/Utility/Set.php

+ 6 - 37
lib/Cake/Model/Model.php

@@ -2812,43 +2812,12 @@ class Model extends Object implements CakeEventListener {
 		if ($state === 'before') {
 			return $query;
 		} elseif ($state === 'after') {
-			$return = $idMap = array();
-			$ids = Set::extract($results, '{n}.' . $this->alias . '.' . $this->primaryKey);
-
-			foreach ($results as $result) {
-				$result['children'] = array();
-				$id = $result[$this->alias][$this->primaryKey];
-				if (!isset($result[$this->alias]['parent_id'])) {
-					trigger_error(
-						__d('cake_dev', 'You cannot use find("threaded") on models without a "parent_id" field.'),
-						E_USER_WARNING
-					);
-					return $return;
-				}
-				$parentId = $result[$this->alias]['parent_id'];
-				if (isset($idMap[$id]['children'])) {
-					$idMap[$id] = array_merge($result, (array)$idMap[$id]);
-				} else {
-					$idMap[$id] = array_merge($result, array('children' => array()));
-				}
-				if (!$parentId || !in_array($parentId, $ids)) {
-					$return[] =& $idMap[$id];
-				} else {
-					$idMap[$parentId]['children'][] =& $idMap[$id];
-				}
-			}
-			if (count($return) > 1) {
-				$ids = array_unique(Set::extract('/' . $this->alias . '/parent_id', $return));
-				if (count($ids) > 1) {
-					$root = $return[0][$this->alias]['parent_id'];
-					foreach ($return as $key => $value) {
-						if ($value[$this->alias]['parent_id'] != $root) {
-							unset($return[$key]);
-						}
-					}
-				}
-			}
-			return $return;
+			return Set::nest($results, array(
+                'alias' => $this->alias,
+                'primaryKey' => $this->primaryKey,
+                'parent' => 'parent_id',
+                'children' => 'children'
+            ));
 		}
 	}
 

+ 0 - 12
lib/Cake/Test/Case/Model/ModelReadTest.php

@@ -2991,18 +2991,6 @@ class ModelReadTest extends BaseModelTest {
 	}
 
 /**
- * find(threaded) should trigger errors whne there is no parent_id field.
- *
- * @expectedException PHPUnit_Framework_Error_Warning
- * @return void
- */
-	public function testFindThreadedError() {
-		$this->loadFixtures('Apple', 'Sample');
-		$Apple = new Apple();
-		$Apple->find('threaded');
-	}
-
-/**
  * testFindAllThreaded method
  *
  * @return void

+ 60 - 0
lib/Cake/Utility/Set.php

@@ -1114,4 +1114,64 @@ class Set {
 		}
 		return null;
 	}
+
+/**
+ * Takes in a flat 2 dimensional array and returns a nested array
+ *
+ * @param mixed $data
+ * @param array $options Options are:
+ *      alias - the first array key to look for
+ *      primaryKey - the key to use to identify the rows
+ *      parentId - the key to use to identify the parent
+ *      children - the key name to use in the resultset for children
+ * @return array of results, nested
+ * @link
+ */
+	public static function nest($data, $options = array()) {
+		if (!$data) {
+			return $data;
+		}
+
+		$options = array(
+			'alias' => key(current($data)),
+			'primaryKey' => 'id',
+			'parentId' => 'parent_id',
+			'children' => 'children'
+		) + $options;
+
+		$return = $idMap = array();
+		$ids = Set::extract($data, '{n}.' . $options['alias'] . '.' . $options['primaryKey']);
+
+		foreach ($data as $result) {
+			$result[$options['children']] = array();
+			$id = $result[$options['alias']][$options['primaryKey']];
+			if (isset($result[$options['alias']][$options['parentId']])) {
+				$parentId = $result[$options['alias']][$options['parentId']];
+			} else {
+				$parentId = null;
+			}
+			if (isset($idMap[$id]['children'])) {
+				$idMap[$id] = array_merge($result, (array)$idMap[$id]);
+			} else {
+				$idMap[$id] = array_merge($result, array('children' => array()));
+			}
+			if (!$parentId || !in_array($parentId, $ids)) {
+				$return[] =& $idMap[$id];
+			} else {
+				$idMap[$parentId]['children'][] =& $idMap[$id];
+			}
+		}
+		if (count($return) > 1) {
+			$ids = array_unique(Set::extract('/' . $options['alias'] . '/' . $options['parentId'], $return));
+			if (count($ids) > 1) {
+				$root = $return[0][$options['alias']][$options['parentId']];
+				foreach ($return as $key => $value) {
+					if ($value[$options['alias']][$options['parentId']] != $root) {
+						unset($return[$key]);
+					}
+				}
+			}
+		}
+		return $return;
+	}
 }