= 0 && $name[$l] == '/') $name = substr($name, 0, $l); // truncate trailing slash if ($name === '.') $name = ''; // we want the "unsafe" but pretty version $safe_name = ($name === '') ? '.' : $name; if (!$php->isDir($safe_name)) { throw new Exception("Directory $safe_name does not exist"); } $this->name = $name; $this->safeName = $safe_name; } /** * Returns name of directory without trailing slash * @note This function works in all cases, but can be slightly * redundant if the application is prepending it to * a filename (compare index.html versus ./index.html) */ public function getName() {return $this->safeName;} /** * Returns name of directory with trailing slash, prepared for * a filename to be appended (s = slash, it is NOT safe) * @note If the directory is the current working directory, a blank * string is returned instead. This makes this method good * for web-contexts, and reasonably well when appending it * onto filenames, but will NOT work if you're actually trying * to refer to a directory (see getNAme() for that) */ public function getSName() { return ($this->name === '') ? '' : $this->name . '/'; } /** * Recursively scans directory for files * @return Tree of files in the directory, file => size */ public function getTree() { $dir = new RecursiveDirectoryIterator($this->safeName); $tree = array(); $dirs = array(array($dir, &$tree)); for($i = 0; $i < count($dirs); ++$i) { $d =& $dirs[$i][0]; // current directory iterator $tier =& $dirs[$i][1]; // current directory tree to write to for($d->rewind(); $d->valid(); $d->next()) { if ($d->isDir()) { // initialize new directory tree $tier[$d->getFilename()] = array(); // file away another directory to process $dirs[] = array($d->getChildren(), &$tier[$d->getFilename()]); } else { // add the file to the directory tree $tier[$d->getFilename()] = $d->getSize(); } } } return $tree; } /** * Scans directory recursively for files with a certain file extension * @param $ext_match Extension with period to look for, cannot have * more than one period within it * @return List of matching files, with fully qualified relative * paths (not tree format) */ public function scanRecursively($ext_match) { $tree = $this->getTree(); $dirs = array(array('', &$tree)); $ret = array(); for ($i = 0; $i < count($dirs); ++$i) { $base = $dirs[$i][0]; // base directory prefix $tier = $dirs[$i][1]; // tree node we're reading from foreach ($tier as $name => $contents) { if (is_array($contents)) { // directory $dirs[] = array($base . $name . '/', $contents); } else { // name $ext = strrchr($name, '.'); if ($ext != $ext_match) continue; $ret[] = $this->getSName() . $base . $name; } } } return $ret; } /** * Scans just the current directory for files matching extension * @param $ext_match Extension with period to look for, cannot have * more than one period within it * @return List of matching files */ public function scanFlat($ext_match) { $files = scandir($this->safeName); $ret = array(); foreach ($files as $name) { if (empty($name) || $name[0] == '.') continue; $ext = strrchr($name, '.'); if ($ext != $ext_match) continue; $ret[] = $this->getSName() . $name; } return $ret; } /** * Scans directory for files with matching extension * @param $ext_match File extension to match * @param $recursive Whether or not to search recursively */ public function scan($ext, $recursive) { if ($recursive) return $this->scanRecursively($ext); else return $this->scanFlat($ext); } } ?>