[ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 3 /** 4 * @package pake 5 * @author Fabien Potencier <fabien.potencier@symfony-project.com> 6 * @copyright 2004-2005 Fabien Potencier <fabien.potencier@symfony-project.com> 7 * @license see the LICENSE file included in the distribution 8 * @version SVN: $Id: pakeFinder.class.php 3268 2007-01-13 20:19:33Z fabien $ 9 */ 10 11 require_once dirname(__FILE__).'/pakeGlobToRegex.class.php'; 12 require_once dirname(__FILE__).'/pakeNumberCompare.class.php'; 13 14 if (class_exists('pakeFinder')) 15 { 16 return; 17 } 18 19 /** 20 * 21 * Allow to build rules to find files and directories. 22 * 23 * All rules may be invoked several times, except for ->in() method. 24 * Some rules are cumulative (->name() for example) whereas others are destructive 25 * (most recent value is used, ->maxdepth() method for example). 26 * 27 * All methods return the current pakeFinder object to allow easy chaining: 28 * 29 * $files = pakeFinder::type('file')->name('*.php')->in(.); 30 * 31 * Interface loosely based on perl File::Find::Rule module. 32 * 33 * @package pake 34 * @author Fabien Potencier <fabien.potencier@symfony-project.com> 35 * @copyright 2004-2005 Fabien Potencier <fabien.potencier@symfony-project.com> 36 * @license see the LICENSE file included in the distribution 37 * @version SVN: $Id: pakeFinder.class.php 3268 2007-01-13 20:19:33Z fabien $ 38 */ 39 class pakeFinder 40 { 41 private $type = 'file'; 42 private $names = array(); 43 private $prunes = array(); 44 private $discards = array(); 45 private $execs = array(); 46 private $mindepth = 0; 47 private $sizes = array(); 48 private $maxdepth = 1000000; 49 private $relative = false; 50 private $follow_link = false; 51 private $search_dir = ''; 52 53 /** 54 * Sets maximum directory depth. 55 * 56 * Finder will descend at most $level levels of directories below the starting point. 57 * 58 * @param integer level 59 * @return object current pakeFinder object 60 */ 61 public function maxdepth($level) 62 { 63 $this->maxdepth = $level; 64 65 return $this; 66 } 67 68 /** 69 * Sets minimum directory depth. 70 * 71 * Finder will start applying tests at level $level. 72 * 73 * @param integer level 74 * @return object current pakeFinder object 75 */ 76 public function mindepth($level) 77 { 78 $this->mindepth = $level; 79 80 return $this; 81 } 82 83 public function get_type() 84 { 85 return $this->type; 86 } 87 88 /** 89 * Sets the type of elements to returns. 90 * 91 * @param string directory or file or any (for both file and directory) 92 * @return object new pakeFinder object 93 */ 94 public static function type($name) 95 { 96 $finder = new pakeFinder(); 97 98 if (strtolower(substr($name, 0, 3)) == 'dir') 99 { 100 $finder->type = 'directory'; 101 } 102 else if (strtolower($name) == 'any') 103 { 104 $finder->type = 'any'; 105 } 106 else 107 { 108 $finder->type = 'file'; 109 } 110 111 return $finder; 112 } 113 114 /* 115 * glob, patterns (must be //) or strings 116 */ 117 private function to_regex($str) 118 { 119 if ($str[0] == '/' && $str[strlen($str) - 1] == '/') 120 { 121 return $str; 122 } 123 else 124 { 125 return pakeGlobToRegex::glob_to_regex($str); 126 } 127 } 128 129 private function args_to_array($arg_list, $not = false) 130 { 131 $list = array(); 132 133 for ($i = 0; $i < count($arg_list); $i++) 134 { 135 if (is_array($arg_list[$i])) 136 { 137 foreach ($arg_list[$i] as $arg) 138 { 139 $list[] = array($not, $this->to_regex($arg)); 140 } 141 } 142 else 143 { 144 $list[] = array($not, $this->to_regex($arg_list[$i])); 145 } 146 } 147 148 return $list; 149 } 150 151 /** 152 * Adds rules that files must match. 153 * 154 * You can use patterns (delimited with / sign), globs or simple strings. 155 * 156 * $finder->name('*.php') 157 * $finder->name('/\.php$/') // same as above 158 * $finder->name('test.php') 159 * 160 * @param list a list of patterns, globs or strings 161 * @return object current pakeFinder object 162 */ 163 public function name() 164 { 165 $args = func_get_args(); 166 $this->names = array_merge($this->names, $this->args_to_array($args)); 167 168 return $this; 169 } 170 171 /** 172 * Adds rules that files must not match. 173 * 174 * @see ->name() 175 * @param list a list of patterns, globs or strings 176 * @return object current pakeFinder object 177 */ 178 public function not_name() 179 { 180 $args = func_get_args(); 181 $this->names = array_merge($this->names, $this->args_to_array($args, true)); 182 183 return $this; 184 } 185 186 /** 187 * Adds tests for file sizes. 188 * 189 * $finder->size('> 10K'); 190 * $finder->size('<= 1Ki'); 191 * $finder->size(4); 192 * 193 * @param list a list of comparison strings 194 * @return object current pakeFinder object 195 */ 196 public function size() 197 { 198 $args = func_get_args(); 199 for ($i = 0; $i < count($args); $i++) 200 { 201 $this->sizes[] = new pakeNumberCompare($args[$i]); 202 } 203 204 return $this; 205 } 206 207 /** 208 * Traverses no further. 209 * 210 * @param list a list of patterns, globs to match 211 * @return object current pakeFinder object 212 */ 213 public function prune() 214 { 215 $args = func_get_args(); 216 $this->prunes = array_merge($this->prunes, $this->args_to_array($args)); 217 218 return $this; 219 } 220 221 /** 222 * Discards elements that matches. 223 * 224 * @param list a list of patterns, globs to match 225 * @return object current pakeFinder object 226 */ 227 public function discard() 228 { 229 $args = func_get_args(); 230 $this->discards = array_merge($this->discards, $this->args_to_array($args)); 231 232 return $this; 233 } 234 235 /** 236 * Ignores version control directories. 237 * 238 * Currently supports subversion, CVS, DARCS, Gnu Arch, Monotone, Bazaar-NG 239 * 240 * @return object current pakeFinder object 241 */ 242 public function ignore_version_control() 243 { 244 $ignores = array('.svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr'); 245 246 return $this->discard($ignores)->prune($ignores); 247 } 248 249 /** 250 * Executes function or method for each element. 251 * 252 * Element match if functino or method returns true. 253 * 254 * $finder->exec('myfunction'); 255 * $finder->exec(array($object, 'mymethod')); 256 * 257 * @param mixed function or method to call 258 * @return object current pakeFinder object 259 */ 260 public function exec() 261 { 262 $args = func_get_args(); 263 for ($i = 0; $i < count($args); $i++) 264 { 265 if (is_array($args[$i]) && !method_exists($args[$i][0], $args[$i][1])) 266 { 267 throw new pakeException(sprintf("Method %s does not exist for object %s.", $args[$i][1], $args[$i][0])); 268 } 269 else if (!is_array($args[$i]) && !function_exists($args[$i])) 270 { 271 throw new pakeException(sprintf("Function %s does not exist.", $args[$i])); 272 } 273 274 $this->execs[] = $args[$i]; 275 } 276 277 return $this; 278 } 279 280 /** 281 * Returns relative paths for all files and directories. 282 * 283 * @return object current pakeFinder object 284 */ 285 public function relative() 286 { 287 $this->relative = true; 288 289 return $this; 290 } 291 292 /** 293 * Symlink following. 294 * 295 * @return object current sfFinder object 296 */ 297 public function follow_link() 298 { 299 $this->follow_link = true; 300 301 return $this; 302 } 303 304 /** 305 * Searches files and directories which match defined rules. 306 * 307 * @return array list of files and directories 308 */ 309 public function in() 310 { 311 $files = array(); 312 $here_dir = getcwd(); 313 $numargs = func_num_args(); 314 $arg_list = func_get_args(); 315 316 // first argument is an array? 317 if ($numargs == 1 && is_array($arg_list[0])) 318 { 319 $arg_list = $arg_list[0]; 320 $numargs = count($arg_list); 321 } 322 323 $dirs = array(); 324 for ($i = 0; $i < $numargs; $i++) 325 { 326 if ($argDirs = glob($arg_list[$i])) 327 { 328 $dirs = array_merge($dirs, $argDirs); 329 } 330 } 331 332 foreach ($dirs as $dir) 333 { 334 $real_dir = realpath($dir); 335 336 // absolute path? 337 if (!self::isPathAbsolute($real_dir)) 338 { 339 $dir = $here_dir.DIRECTORY_SEPARATOR.$real_dir; 340 } 341 else 342 { 343 $dir = $real_dir; 344 } 345 346 if (!is_dir($real_dir)) 347 { 348 continue; 349 } 350 351 $this->search_dir = $dir; 352 353 if ($this->relative) 354 { 355 $files = array_merge($files, str_replace($dir.DIRECTORY_SEPARATOR, '', $this->search_in($dir))); 356 } 357 else 358 { 359 $files = array_merge($files, $this->search_in($dir)); 360 } 361 } 362 363 return array_unique($files); 364 } 365 366 private function search_in($dir, $depth = 0) 367 { 368 if ($depth > $this->maxdepth) 369 { 370 return array(); 371 } 372 373 if (is_link($dir) && !$this->follow_link) 374 { 375 return array(); 376 } 377 378 $files = array(); 379 380 if (is_dir($dir)) 381 { 382 $current_dir = opendir($dir); 383 while (false !== $entryname = readdir($current_dir)) 384 { 385 if ($entryname == '.' || $entryname == '..') continue; 386 387 $current_entry = $dir.DIRECTORY_SEPARATOR.$entryname; 388 if (is_link($current_entry) && !$this->follow_link) 389 { 390 continue; 391 } 392 393 if (is_dir($current_entry)) 394 { 395 if (($this->type == 'directory' || $this->type == 'any') && ($depth >= $this->mindepth) && !$this->is_discarded($dir, $entryname) && $this->match_names($dir, $entryname) && $this->exec_ok($dir, $entryname)) 396 { 397 $files[] = realpath($current_entry); 398 } 399 400 if (!$this->is_pruned($dir, $entryname)) 401 { 402 $files = array_merge($files, $this->search_in($current_entry, $depth + 1)); 403 } 404 } 405 else 406 { 407 if (($this->type != 'directory' || $this->type == 'any') && ($depth >= $this->mindepth) && !$this->is_discarded($dir, $entryname) && $this->match_names($dir, $entryname) && $this->size_ok($dir, $entryname) && $this->exec_ok($dir, $entryname)) 408 { 409 $files[] = realpath($current_entry); 410 } 411 } 412 } 413 closedir($current_dir); 414 } 415 416 return $files; 417 } 418 419 private function match_names($dir, $entry) 420 { 421 if (!count($this->names)) return true; 422 423 // we must match one "not_name" rules to be ko 424 $one_not_name_rule = false; 425 foreach ($this->names as $args) 426 { 427 list($not, $regex) = $args; 428 if ($not) 429 { 430 $one_not_name_rule = true; 431 if (preg_match($regex, $entry)) 432 { 433 return false; 434 } 435 } 436 } 437 438 $one_name_rule = false; 439 // we must match one "name" rules to be ok 440 foreach ($this->names as $args) 441 { 442 list($not, $regex) = $args; 443 if (!$not) 444 { 445 $one_name_rule = true; 446 if (preg_match($regex, $entry)) 447 { 448 return true; 449 } 450 } 451 } 452 453 if ($one_not_name_rule && $one_name_rule) 454 { 455 return false; 456 } 457 else if ($one_not_name_rule) 458 { 459 return true; 460 } 461 else if ($one_name_rule) 462 { 463 return false; 464 } 465 else 466 { 467 return true; 468 } 469 } 470 471 private function size_ok($dir, $entry) 472 { 473 if (!count($this->sizes)) return true; 474 475 if (!is_file($dir.DIRECTORY_SEPARATOR.$entry)) return true; 476 477 $filesize = filesize($dir.DIRECTORY_SEPARATOR.$entry); 478 foreach ($this->sizes as $number_compare) 479 { 480 if (!$number_compare->test($filesize)) return false; 481 } 482 483 return true; 484 } 485 486 private function is_pruned($dir, $entry) 487 { 488 if (!count($this->prunes)) return false; 489 490 foreach ($this->prunes as $args) 491 { 492 $regex = $args[1]; 493 if (preg_match($regex, $entry)) return true; 494 } 495 496 return false; 497 } 498 499 private function is_discarded($dir, $entry) 500 { 501 if (!count($this->discards)) return false; 502 503 foreach ($this->discards as $args) 504 { 505 $regex = $args[1]; 506 if (preg_match($regex, $entry)) return true; 507 } 508 509 return false; 510 } 511 512 private function exec_ok($dir, $entry) 513 { 514 if (!count($this->execs)) return true; 515 516 foreach ($this->execs as $exec) 517 { 518 if (!call_user_func_array($exec, array($dir, $entry))) return false; 519 } 520 521 return true; 522 } 523 524 public static function isPathAbsolute($path) 525 { 526 if ($path{0} == '/' || $path{0} == '\\' || 527 (strlen($path) > 3 && ctype_alpha($path{0}) && 528 $path{1} == ':' && 529 ($path{2} == '\\' || $path{2} == '/') 530 ) 531 ) 532 { 533 return true; 534 } 535 536 return false; 537 } 538 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |