Skip to content

Instantly share code, notes, and snippets.

@ruthlessfish
Created September 9, 2011 01:11
Show Gist options
  • Save ruthlessfish/1205239 to your computer and use it in GitHub Desktop.
Save ruthlessfish/1205239 to your computer and use it in GitHub Desktop.
convert an array of files into a multi-dimensional array
<?php
/**
* Build Manifest
*
* Requires: PHP 5.3+
*
* Takes an array of file names and builds a multi-dimensional array
* representing a simple file-system.
*
* NOTE: Files are only currently supported as leaf elements in the array.
* For example, if the files array contains '/var/www/html' it will
* create a file called 'html' in the /var/www/ directory.
*
* Example Use Case:
*
* I am building a web interface for Mercurial repositories and I want
* to be able to show the files from any specified revision in a tree view.
* From Mercurial we can call `hg manifest -r REV` and we will get back a list
* of files that we can split on the newline character. We can then pass this array
* on to build_manifest() to get a more tree-friendly data structure.
*
* $files = explode("\n", `hg manifest /path/to/your/repository`);
* $files_arr = build_manifest($files);
*
*
*/
function build_manifest ($files = array())
{
// break each file up into segments
$files = array_map(function($file) {
return explode('/', $file);
}, $files);
// doc root
$manifest = array();
foreach ($files as $file)
{
_build_file($file, $manifest);
}
return $manifest;
}
// helper function
// recursively save file parts in to an array
function _build_file($file, &$parent)
{
$i = count($file) - 1; // current index
$seg = array_shift($file); // next segment
if ($i < 0)
{
throw new Exception('Invalid file name.');
}
// add the file to the directory
if ($i === 0)
{
// prevent duplicates
in_array($seg, $parent) OR $parent[] = $seg;
return;
}
// create the subdirectory if it does not yet exist
isset($parent[$seg]) OR $parent[$seg] = array();
return _build_file($file, $parent[$seg]);
}
// ------------------------------------------------------------------------
// Test
$files = array('readme.txt',
'foo.txt',
'foo/bar.txt',
'foo/bar/baz.txt',
'foo/bar/baz/foo.txt',
'foo/bar/baz/bar.txt',
'foo/bar/baz/baz.txt',
'bar.txt',
'bar/baz.txt',
'bar/baz/foo.txt',
'bar/baz/foo/foo.txt',
'bar/baz/foo/bar.txt',
'bar/baz/foo/baz.txt',
'baz.txt',
'baz/foo.txt',
'baz/foo/bar.txt',
'baz/foo/bar/foo.txt',
'baz/foo/bar/bar.txt',
'baz/foo/bar/baz.txt');
print_r(build_manifest($files));
// Output
Array
(
[0] => readme.txt
[1] => foo.txt
[foo] => Array
(
[0] => bar.txt
[bar] => Array
(
[0] => baz.txt
[baz] => Array
(
[0] => foo.txt
[1] => bar.txt
[2] => baz.txt
)
)
)
[2] => bar.txt
[bar] => Array
(
[0] => baz.txt
[baz] => Array
(
[0] => foo.txt
[foo] => Array
(
[0] => foo.txt
[1] => bar.txt
[2] => baz.txt
)
)
)
[3] => baz.txt
[baz] => Array
(
[0] => foo.txt
[foo] => Array
(
[0] => bar.txt
[bar] => Array
(
[0] => foo.txt
[1] => bar.txt
[2] => baz.txt
)
)
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment