Skip to content
Permalink
Browse files

allow set nest to work with any-d arrays

not just model-formatted arrays
  • Loading branch information...
AD7six committed Jan 10, 2012
1 parent 442d889 commit 5608d63541b568684b19b07f18669dd675876c6d
Showing with 51 additions and 31 deletions.
  1. +2 −4 lib/Cake/Model/Model.php
  2. +49 −27 lib/Cake/Utility/Set.php
@@ -2813,10 +2813,8 @@ protected function _findThreaded($state, $query, $results = array()) {
return $query;
} elseif ($state === 'after') {
return Set::nest($results, array(
'alias' => $this->alias,
'key' => $this->primaryKey,
'parent' => 'parent_id',
'children' => 'children'
'idPath' => '/' . $this->alias . '/' . $this->primaryKey,
'parentPath' => '/' . $this->alias . '/parent_id'
));
}
}
@@ -1116,13 +1116,10 @@ public static function apply($path, $data, $callback, $options = array()) {
}
/**
* Takes in a flat 2 dimensional array and returns a nested array
* Takes in a flat array and returns a nested array
*
* @param mixed $data
* @param array $options Options are:
* alias - the first array key to look for
* key - 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
* idPath - the path to a key that identifies each entry
* parentPath - the path to a key that identifies the parent of each entry
@@ -1134,31 +1131,37 @@ public static function nest($data, $options = array()) {
return $data;
}
$alias = key(current($data));
$options = array(
'alias' => key(current($data)),
'key' => 'id',
'parentId' => 'parent_id',
'children' => 'children',
'idPath' => "/$alias/id",
'parentPath' => "/$alias/parent_id",
'children' => 'children'
) + $options;
if (empty($options['idPath'])) {
$options['idPath'] = '/' . $options['alias'] . '/' . $options['key'];
}
if (empty($options['parentPath'])) {
$options['parentPath'] = '/' . $options['alias'] . '/' . $options['parentId'];
}
$return = $idMap = array();
$ids = Set::extract($data, $options['idPath']);
$idKeys = explode('/', trim($options['idPath'], '/'));
$parentKeys = explode('/', trim($options['parentPath'], '/'));
foreach ($data as $result) {
$result[$options['children']] = array();
$id = $result[$options['alias']][$options['key']];
if (isset($result[$options['alias']][$options['parentId']])) {
$parentId = $result[$options['alias']][$options['parentId']];
} else {
$id = $result;
foreach($idKeys as $key) {
$id = $id[$key];
}
$parentId = $result;
foreach($parentKeys as $key) {
if (!isset($parentId[$key])) {
break;
}
$parentId = $parentId[$key];
}
if (!is_scalar($parentId)) {
$parentId = null;
}
if (isset($idMap[$id][$options['children']])) {
$idMap[$id] = array_merge($result, (array)$idMap[$id]);
} else {
@@ -1170,17 +1173,36 @@ public static function nest($data, $options = array()) {
$idMap[$parentId][$options['children']][] =& $idMap[$id];
}
}
if (count($return) > 1) {
$ids = array_unique(Set::extract($options['parentPath'], $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]);
}
$root = $return[0];
foreach($parentKeys as $key) {
if (!isset($root[$key])) {
break;
}
$root = $root[$key];
}
if (!is_scalar($root)) {
$root = null;
}
foreach ($return as $i => $result) {
$parentId = $result;
foreach($parentKeys as $key) {
if (!isset($parentId[$key])) {
break;
}
$parentId = $parentId[$key];
}
if (!is_scalar($parentId)) {
$parentId = null;
}
if ($parentId != $root) {
unset($return[$i]);
}
}
return $return;
}
}

0 comments on commit 5608d63

Please sign in to comment.
You can’t perform that action at this time.