|
|
@@ -1114,4 +1114,100 @@ class Set {
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Takes in a flat array and returns a nested array
|
|
|
+ *
|
|
|
+ * @param mixed $data
|
|
|
+ * @param array $options Options are:
|
|
|
+ * 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
|
|
|
+ * root - the id of the desired top-most result
|
|
|
+ * @return array of results, nested
|
|
|
+ * @link
|
|
|
+ */
|
|
|
+ public static function nest($data, $options = array()) {
|
|
|
+ if (!$data) {
|
|
|
+ return $data;
|
|
|
+ }
|
|
|
+
|
|
|
+ $alias = key(current($data));
|
|
|
+ $options += array(
|
|
|
+ 'idPath' => "/$alias/id",
|
|
|
+ 'parentPath' => "/$alias/parent_id",
|
|
|
+ 'children' => 'children',
|
|
|
+ 'root' => null
|
|
|
+ );
|
|
|
+
|
|
|
+ $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 = Set::get($result, $idKeys);
|
|
|
+ $parentId = Set::get($result, $parentKeys);
|
|
|
+
|
|
|
+ if (isset($idMap[$id][$options['children']])) {
|
|
|
+ $idMap[$id] = array_merge($result, (array)$idMap[$id]);
|
|
|
+ } else {
|
|
|
+ $idMap[$id] = array_merge($result, array($options['children'] => array()));
|
|
|
+ }
|
|
|
+ if (!$parentId || !in_array($parentId, $ids)) {
|
|
|
+ $return[] =& $idMap[$id];
|
|
|
+ } else {
|
|
|
+ $idMap[$parentId][$options['children']][] =& $idMap[$id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($options['root']) {
|
|
|
+ $root = $options['root'];
|
|
|
+ } else {
|
|
|
+ $root = Set::get($return[0], $parentKeys);
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($return as $i => $result) {
|
|
|
+ $id = Set::get($result, $idKeys);
|
|
|
+ $parentId = Set::get($result, $parentKeys);
|
|
|
+ if ($id !== $root && $parentId != $root) {
|
|
|
+ unset($return[$i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return array_values($return);
|
|
|
+ }
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the value at the specified position
|
|
|
+ *
|
|
|
+ * @param mixed $input an array
|
|
|
+ * @param mixed $path string or array of array keys
|
|
|
+ * @return the value at the specified position or null if it doesn't exist
|
|
|
+ */
|
|
|
+ public static function get($input, $path = null) {
|
|
|
+ if (is_string($path)) {
|
|
|
+ if (strpos($path, '/') !== false) {
|
|
|
+ $keys = explode('/', trim($path, '/'));
|
|
|
+ } else {
|
|
|
+ $keys = explode('.', trim($path, '.'));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $keys = $path;
|
|
|
+ }
|
|
|
+ if (!$keys) {
|
|
|
+ return $input;
|
|
|
+ }
|
|
|
+
|
|
|
+ $return = $input;
|
|
|
+ foreach($keys as $key) {
|
|
|
+ if (!isset($return[$key])) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ $return = $return[$key];
|
|
|
+ }
|
|
|
+ return $return;
|
|
|
+ }
|
|
|
}
|