1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * Recursively reads a directory 6 * 7 * PHP versions 4 and 5 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA 22 * 23 * @category File Formats 24 * @package File_Archive 25 * @author Vincent Lascaux <vincentlascaux@php.net> 26 * @copyright 1997-2005 The PHP Group 27 * @license http://www.gnu.org/copyleft/lesser.html LGPL 28 * @version CVS: $Id: Directory.php,v 1.21 2005/07/07 12:24:58 vincentlascaux Exp $ 29 * @link http://pear.php.net/package/File_Archive 30 */ 31 32require_once "File/Archive/Reader/Relay.php"; 33require_once "File/Archive/Reader/File.php"; 34 35/** 36 * Recursively reads a directory 37 */ 38class File_Archive_Reader_Directory extends File_Archive_Reader_Relay 39{ 40 /** 41 * @var String URL of the directory that must be read 42 * @access private 43 */ 44 var $directory; 45 /** 46 * @var Int The subdirectories will be read up to a depth of maxRecurs 47 * If maxRecurs == 0, the subdirectories will not be read 48 * If maxRecurs == -1, the depth is considered infinite 49 * @access private 50 */ 51 var $maxRecurs; 52 /** 53 * @var Object Handle returned by the openedDirectory function 54 * @access private 55 */ 56 var $directoryHandle = null; 57 58 /** 59 * $directory is the path of the directory that must be read 60 * If $maxRecurs is specified, the subdirectories will be read up to a depth 61 * of $maxRecurs. In particular, if $maxRecurs == 0, the subdirectories 62 * won't be read. 63 */ 64 function File_Archive_Reader_Directory($directory, $symbolic='', 65 $maxRecurs=-1) 66 { 67 parent::File_Archive_Reader_Relay($tmp = null); 68 $this->directory = empty($directory) ? '.' : $directory; 69 $this->symbolic = $this->getStandardURL($symbolic); 70 $this->maxRecurs = $maxRecurs; 71 } 72 73 /** 74 * @see File_Archive_Reader::close() 75 */ 76 function close() 77 { 78 $error = parent::close(); 79 80 if ($this->directoryHandle !== null) { 81 closedir($this->directoryHandle); 82 $this->directoryHandle = null; 83 } 84 85 return $error; 86 } 87 88 /** 89 * @see File_Archive_Reader::next() 90 * 91 * The files are returned in the same order as readdir 92 */ 93 function next() 94 { 95 if ($this->directoryHandle === null) { 96 $this->directoryHandle = opendir($this->directory); 97 if (!is_resource($this->directoryHandle)) { 98 return PEAR::raiseError( 99 "Directory {$this->directory} not found" 100 ); 101 } 102 } 103 104 while ($this->source === null || 105 ($error = $this->source->next()) !== true) { 106 107 if ($this->source !== null) { 108 $this->source->close(); 109 } 110 111 $file = readdir($this->directoryHandle); 112 if ($file == '.' || $file == '..') { 113 continue; 114 } 115 if ($file === false) { 116 return false; 117 } 118 119 $current = $this->directory.'/'.$file; 120 if (is_dir($current)) { 121 if ($this->maxRecurs != 0) { 122 $this->source = new File_Archive_Reader_Directory( 123 $current, $file.'/', $this->maxRecurs-1 124 ); 125 } 126 } else { 127 $this->source = new File_Archive_Reader_File($current, $file); 128 } 129 } 130 131 return $error; 132 } 133 134 /** 135 * @see File_Archive_Reader::getFilename() 136 */ 137 function getFilename() { return $this->symbolic . parent::getFilename(); } 138 139 /** 140 * @see File_Archive_Reader::makeWriterRemoveFiles() 141 */ 142 function makeWriterRemoveFiles($pred) 143 { 144 if ($source !== null && $pred->isTrue($this)) { 145 $toUnlink = $this->getDataFilename(); 146 } else { 147 $toUnlink = null; 148 } 149 150 while ($this->next()) { 151 if ($toUnlink !== null && 152 !@unlink($toUnlink)) { 153 return PEAR::raiseError("Unable to unlink $toUnlink"); 154 } 155 $toUnlink = ($pred->isTrue($this) ? $this->getDataFilename() : null); 156 } 157 if ($toUnlink !== null && 158 !@unlink("Unable to unlink $toUnlink")) { 159 return PEAR::raiseError($pred); 160 } 161 162 require_once "File/Archive/Writer/Files.php"; 163 164 $writer = new File_Archive_Writer_Files($this->directory); 165 $this->close(); 166 return $writer; 167 } 168 169 function &getLastSource() 170 { 171 if ($this->source === null || 172 is_a($this->source, 'File_Archive_Reader_File')) { 173 return $this->source; 174 } else { 175 return $this->source->getLastSource(); 176 } 177 } 178 179 /** 180 * @see File_Archive_Reader::makeWriterRemoveBlocks() 181 */ 182 function makeWriterRemoveBlocks($blocks, $seek = 0) 183 { 184 $lastSource = &$this->getLastSource(); 185 if ($lastSource === null) { 186 return PEAR::raiseError('No file selected'); 187 } 188 189 require_once "File/Archive/Writer/Files.php"; 190 191 $writer = $lastSource->makeWriterRemoveBlocks($blocks, $seek); 192 if (!PEAR::isError($writer)) { 193 $writer->basePath = $this->directory; 194 $this->close(); 195 } 196 197 return $writer; 198 } 199 200 /** 201 * @see File_Archive_Reader::makeAppendWriter 202 */ 203 function makeAppendWriter() 204 { 205 require_once "File/Archive/Writer/Files.php"; 206 207 if ($this->source === null || 208 is_a($this->source, 'File_Archive_Reader_File') ) { 209 $writer = new File_Archive_Writer_Files($this->directory); 210 } else { 211 $writer = $this->source->makeAppendWriter($seek); 212 } 213 214 $this->close(); 215 216 return $writer; 217 } 218} 219 220?>