Location: PHPKode > projects > Dev's CMS > devscms/includes/class.treesort.php
<?php

class treesort
{
	public static function sort($items, $addHelpers = true)
	{
		$children = array();    // Parent's children
		$itemsize = array();    // Family sizes
		
		// Get children by parent
		foreach ($items as $item) {
			if ($item['parent_id'] != 0) {
				$children[$item['parent_id']][] = $item['id'];
			}
			$itemsize[$item['id']] = 1;
		}
		
		$adopted = array();     // Children that have been adopted
		for ($i = 0; count($children) != 0; $i++) {
			$itemId = $items[$i]['id'];
			//echo "id: {$itemId}\n";
			
			// If I have children
			if (isset($children[$itemId])) {
				//echo "\tchildren: " . count($children[$itemId]) . "\n";
				$offset = 1;
				
				// Loop through children and append them after me
				foreach ($children[$itemId] as $id) {
					$itemsize[$itemId] += $itemsize[$id];  // Update my family size
					$adopted[$id] = true;
					$childIndex = self::getIndexInArray($items, $id);
					//echo "\t\tchild size/id/index: $itemsize[$id] $id $childIndex\n";
					// Move child with family
					for ($j = 0; $j < $itemsize[$id]; $j++) {
						if ($childIndex + $j < $i + $offset) {
							$childIndexReal = $childIndex;  // When we move a child, the next will come to into position
							$i--;   // If child is before me, I should adjust my index pointer
						} else {
							$childIndexReal = $childIndex + $j;
						}
						$child = array($items[$childIndexReal]);
						unset($items[$childIndexReal]);
						array_splice($items, $i + $offset++, 0, $child);
						/*if ($itemId == 2) {
							self::debug($items, $itemsize);
						}*/
					}
				}
				
				// Resize parent if it has adopted me
				$thisId = $itemId;
				while (isset($adopted[$thisId])) {
					$parentId = $items[self::getIndexInArray($items, $thisId)]['parent_id'];
					$itemsize[$parentId] += $itemsize[$itemId];
					$thisId = $parentId;
				}
				
				unset($children[$itemId]);
				/*if ($itemId == 2) {
					var_dump($items);var_dump($children);var_dump($itemsize);var_dump($adopted);die;
				}*/
			}
			/*if ($i == count($items) - 1) {
				$items = array_merge($items, array());
				
				$i = -1;
				if ($break) {var_dump($items);var_dump($children);var_dump($itemsize);var_dump($adopted);
					break;
				}
				$break = true;
			}*/
		}
		
		if ($addHelpers) {
			return self::addHelpers($items);
		} else {
			return $items;
		}
	}
	
	public static function getIndexInArray(&$items, $id)
	{
		foreach ($items as $index => $item) {
			if ($item['id'] == $id) {
				return $index;
			}
		}
		return null;
	}
	
	public static function addHelpers($items)
	{
		$level = 0;
		$parentIds = array(0);
		$lastParentId = 0;
		$last = null;
		$first = true;
		foreach ($items as &$item) {
			if ($item['parent_id'] != $lastParentId) {
				if (in_array($item['parent_id'], $parentIds)) {
					if (isset($lastIndex)) {
						$items[$lastIndex] = true;
					}
					for ($i = count($parentIds) - 1; $item['parent_id'] != $parentIds[$i]; $i--) {
						$level--;
						unset($parentIds[$i]);
					}
				
				} else {
					if (isset($last)) {
						$last['has_children'] = true;
					}
					$parentIds[count($parentIds)] = $item['parent_id'];
					$level++;
				}
			}
			
			$item['level'] = $level;
			$item['first'] = $first;
			$item['has_children'] = false;
			$lastParentId = $item['parent_id'];
			$first = false;
			$last = &$item;
		}
		
		return $items;
	}
	
	private static function _debug($items, $itemsize)
	{
		echo "----\n";
		foreach ($items as $item) {
			echo "$item[id]:$item[name] - {$itemsize[$item['id']]}\n";
		}
		echo "----\n";
	}
}




/*$sorted = array();        1
$idToIndex = array();
$orphans = array();

foreach ($categories as $category) {
	if ($category['parent_id'] == 0) {
		$sorted[] = $category;
		$idToIndex[$category['id']] = count($sorted) - 1;
		if (isset($orphans[$category['id']])) {
			// If orphans exist, append them
			$index = $idToIndex[$category['id']] + 1;
			array_splice($sorted, $index, 0, $orphans[$category['id']]);
			foreach ($orphans[$category['id']] as $orphan) {
				$idToIndex[$orphan['id']] = $index++;
			}
			unset($orphans[$category['id']]);
		}
	} else {
		if ($category['parent_id'] == 2) {var_dump($idToIndex);}
		if (isset($idToIndex[$category['parent_id']])) {
			if (count($sorted) > 1) {
				for ($index = $idToIndex[$category['parent_id']] + 1;
						isset($sorted[$index]) && 
						$sorted[$index]['parent_id'] == $category['parent_id'];
					$index++) {}
			} else {
				$index = 1;
			}
			array_splice($sorted, $index, 0, array($category));
			$idToIndex[$category['id']] = $index;
		
		} else {
			$orphans[$category['parent_id']][] = $category;
		}
	}
}*/
Return current item: Dev's CMS