Split out download page (text was heavily augmented). Also:
[xhtml-compiler.git] / XHTMLCompiler / Directory.php
blob5ccf83745dc8025c95fad9d97377bd43c223a65f
1 <?php
3 /**
4 * Represents a directory in the filesystem
5 */
6 class XHTMLCompiler_Directory
9 /** Location of directory this object represents, w/o trailing slash */
10 protected $name;
12 /** Non-blank location of directory, safe for directory handling functions */
13 protected $safeName;
15 /**
16 * Path to directory you wish to instantiate.
18 public function __construct($name) {
19 $name = str_replace('\\', '/', $name); // normalize \ to /
20 $l = strlen($name) - 1; // index of last character
21 if ($l >= 0 && $name[$l] == '/') $name = substr($name, 0, $l); // truncate trailing slash
22 if ($name === '.') $name = ''; // we want the "unsafe" but pretty version
23 $safe_name = ($name === '') ? '.' : $name;
24 if (!is_dir($safe_name)) {
25 throw new Exception("Directory $safe_name does not exist");
27 $this->name = $name;
28 $this->safeName = $safe_name;
31 /**
32 * Returns name of directory without trailing slash
33 * @note This function works in all cases, but can be slightly
34 * redundant if the application is prepending it to
35 * a filename (compare index.html versus ./index.html)
37 public function getName() {return $this->safeName;}
39 /**
40 * Returns name of directory with trailing slash, prepared for
41 * a filename to be appended (s = slash, it is NOT safe)
42 * @note If the directory is the current working directory, a blank
43 * string is returned instead. This makes this method good
44 * for web-contexts, and reasonably well when appending it
45 * onto filenames, but will NOT work if you're actually trying
46 * to refer to a directory (see getNAme() for that)
48 public function getSName() {
49 return ($this->name === '') ? '' : $this->name . '/';
52 /**
53 * Recursively scans directory for files
54 * @return Tree of files in the directory, file => size
56 public function getTree() {
57 $dir = new RecursiveDirectoryIterator($this->safeName);
58 $tree = array();
59 $dirs = array(array($dir, &$tree));
61 for($i = 0; $i < count($dirs); ++$i) {
62 $d =& $dirs[$i][0]; // current directory iterator
63 $tier =& $dirs[$i][1]; // current directory tree to write to
64 for($d->rewind(); $d->valid(); $d->next()) {
65 if ($d->isDir()) {
66 // initialize new directory tree
67 $tier[$d->getFilename()] = array();
68 // file away another directory to process
69 $dirs[] = array($d->getChildren(), &$tier[$d->getFilename()]);
70 } else {
71 // add the file to the directory tree
72 $tier[$d->getFilename()] = $d->getSize();
77 return $tree;
80 /**
81 * Scans directory recursively for files with a certain file extension
82 * @param $ext_match Extension with period to look for, cannot have
83 * more than one period within it
84 * @return List of matching files, with fully qualified relative
85 * paths (not tree format)
87 public function scanRecursively($ext_match) {
88 $tree = $this->getTree();
89 $dirs = array(array('', &$tree));
90 $ret = array();
91 for ($i = 0; $i < count($dirs); ++$i) {
92 $base = $dirs[$i][0]; // base directory prefix
93 $tier = $dirs[$i][1]; // tree node we're reading from
94 foreach ($tier as $name => $contents) {
95 if (is_array($contents)) {
96 // directory
97 $dirs[] = array($base . $name . '/', $contents);
98 } else {
99 // name
100 $ext = strrchr($name, '.');
101 if ($ext != $ext_match) continue;
102 $ret[] = $this->getSName() . $base . $name;
106 return $ret;
110 * Scans just the current directory for files matching extension
111 * @param $ext_match Extension with period to look for, cannot have
112 * more than one period within it
113 * @return List of matching files
115 public function scanFlat($ext_match) {
116 $files = scandir($this->safeName);
117 $ret = array();
118 foreach ($files as $name) {
119 if (empty($name) || $name[0] == '.') continue;
120 $ext = strrchr($name, '.');
121 if ($ext != $ext_match) continue;
122 $ret[] = $this->getSName() . $name;
124 return $ret;
128 * Scans directory for files with matching extension
129 * @param $ext_match File extension to match
130 * @param $recursive Whether or not to search recursively
132 public function scan($ext, $recursive) {
133 if ($recursive) return $this->scanRecursively($ext);
134 else return $this->scanFlat($ext);