[ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 /* 3 * $Id: Path.php 3076 2006-12-18 08:52:12Z fabien $ 4 * 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 * 17 * This software consists of voluntary contributions made by many individuals 18 * and is licensed under the LGPL. For more information please see 19 * <http://phing.info>. 20 */ 21 22 require_once 'phing/types/DataType.php'; 23 include_once 'phing/util/PathTokenizer.php'; 24 include_once 'phing/types/FileSet.php'; 25 26 /** 27 * This object represents a path as used by include_path or PATH 28 * environment variable. 29 * 30 * This class has been adopted from the Java Ant equivalent. The ability have 31 * path structures in Phing is important; however, because of how PHP classes interact 32 * the ability to specify CLASSPATHs makes less sense than Java.Rather than providing 33 * CLASSPATH for any tasks that take classes as parameters, perhaps a better 34 * solution in PHP is to have an IncludePath task, which prepends paths to PHP's include_path 35 * INI variable. This gets around the problem that simply using a path to load the initial 36 * PHP class is not enough (in most cases the loaded class may assume that it is on the global 37 * PHP include_path, and will try to load dependent classes accordingly). The other option is 38 * to provide a way for this class to add paths to the include path, if desired -- or to create 39 * an IncludePath subclass. Once added, though, when would a path be removed from the include path? 40 * 41 * <p> 42 * <code> 43 * <sometask><br> 44 * <somepath><br> 45 * <pathelement location="/path/to/file" /><br> 46 * <pathelement path="/path/to/class2;/path/to/class3" /><br> 47 * <pathelement location="/path/to/file3" /><br> 48 * </somepath><br> 49 * </sometask><br> 50 * </code> 51 * <p> 52 * The object implemention <code>sometask</code> must provide a method called 53 * <code>createSomepath</code> which returns an instance of <code>Path</code>. 54 * Nested path definitions are handled by the Path object and must be labeled 55 * <code>pathelement</code>.<p> 56 * 57 * The path element takes a parameter <code>path</code> which will be parsed 58 * and split into single elements. It will usually be used 59 * to define a path from an environment variable. 60 * 61 * @author Hans Lellelid <hans@xmpl.org> (Phing) 62 * @author Thomas.Haas@softwired-inc.com (Ant) 63 * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) 64 * @package phing.types 65 */ 66 class Path extends DataType { 67 68 private $elements = array(); 69 70 /** 71 * Constructor for internally instantiated objects sets project. 72 * @param Project $project 73 * @param string $path (for use by IntrospectionHelper) 74 */ 75 public function __construct($project = null, $path = null) { 76 if ($project !== null) { 77 $this->setProject($project); 78 } 79 if ($path !== null) { 80 $this->createPathElement()->setPath($path); 81 } 82 } 83 84 /** 85 * Adds a element definition to the path. 86 * @param $location the location of the element to add (must not be 87 * <code>null</code> nor empty. 88 * @throws BuildException 89 */ 90 public function setDir(PhingFile $location) { 91 if ($this->isReference()) { 92 throw $this->tooManyAttributes(); 93 } 94 $this->createPathElement()->setDir($location); 95 } 96 97 /** 98 * Parses a path definition and creates single PathElements. 99 * @param path the path definition. 100 * @throws BuildException 101 */ 102 public function setPath($path) { 103 if ($this->isReference()) { 104 throw $this->tooManyAttributes(); 105 } 106 $this->createPathElement()->setPath($path); 107 } 108 109 /** 110 * Makes this instance in effect a reference to another Path instance. 111 * 112 * <p>You must not set another attribute or nest elements inside 113 * this element if you make it a reference.</p> 114 * @throws BuildException 115 */ 116 public function setRefid(Reference $r) { 117 if (!empty($this->elements)) { 118 throw $this->tooManyAttributes(); 119 } 120 $this->elements[] = $r; 121 parent::setRefid($r); 122 } 123 124 /** 125 * Creates the nested <code><pathelement></code> element. 126 * @throws BuildException 127 */ 128 public function createPathElement() { 129 if ($this->isReference()) { 130 throw $this->noChildrenAllowed(); 131 } 132 $pe = new PathElement($this); 133 $this->elements[] = $pe; 134 return $pe; 135 } 136 137 /** 138 * Adds a nested <code><fileset></code> element. 139 * @throws BuildException 140 */ 141 public function addFileset(FileSet $fs) { 142 if ($this->isReference()) { 143 throw $this->noChildrenAllowed(); 144 } 145 $this->elements[] = $fs; 146 $this->checked = false; 147 } 148 149 /** 150 * Adds a nested <code><dirset></code> element. 151 * @throws BuildException 152 */ 153 public function addDirset(DirSet $dset) { 154 if ($this->isReference()) { 155 throw $this->noChildrenAllowed(); 156 } 157 $this->elements[] = $dset; 158 $this->checked = false; 159 } 160 161 /** 162 * Creates a nested <code><path></code> element. 163 * @throws BuildException 164 */ 165 public function createPath() { 166 if ($this->isReference()) { 167 throw $this->noChildrenAllowed(); 168 } 169 $p = new Path($this->project); 170 $this->elements[] = $p; 171 $this->checked = false; 172 return $p; 173 } 174 175 /** 176 * Append the contents of the other Path instance to this. 177 */ 178 public function append(Path $other) { 179 if ($other === null) { 180 return; 181 } 182 $l = $other->listPaths(); 183 foreach($l as $path) { 184 if (!in_array($path, $this->elements, true)) { 185 $this->elements[] = $path; 186 } 187 } 188 } 189 190 /** 191 * Adds the components on the given path which exist to this 192 * Path. Components that don't exist, aren't added. 193 * 194 * @param Path $source - Source path whose components are examined for existence. 195 */ 196 public function addExisting(Path $source) { 197 $list = $source->listPaths(); 198 foreach($list as $el) { 199 $f = null; 200 if ($this->project !== null) { 201 $f = $this->project->resolveFile($el); 202 } else { 203 $f = new PhingFile($el); 204 } 205 206 if ($f->exists()) { 207 $this->setDir($f); 208 } else { 209 $this->log("dropping " . $f->__toString() . " from path as it doesn't exist", 210 PROJECT_MSG_VERBOSE); 211 } 212 } 213 } 214 215 /** 216 * Returns all path elements defined by this and nested path objects. 217 * @return array List of path elements. 218 */ 219 public function listPaths() { 220 if (!$this->checked) { 221 // make sure we don't have a circular reference here 222 $stk = array(); 223 array_push($stk, $this); 224 $this->dieOnCircularReference($stk, $this->project); 225 } 226 227 $result = array(); 228 for ($i = 0, $elSize=count($this->elements); $i < $elSize; $i++) { 229 $o = $this->elements[$i]; 230 if ($o instanceof Reference) { 231 $o = $o->getReferencedObject($this->project); 232 // we only support references to paths right now 233 if (!($o instanceof Path)) { 234 $msg = $r->getRefId() . " doesn't denote a path"; 235 throw new BuildException($msg); 236 } 237 } 238 239 if (is_string($o)) { 240 $result[] = $o; 241 } elseif ($o instanceof PathElement) { 242 $parts = $o->getParts(); 243 if ($parts === null) { 244 throw new BuildException("You must either set location or" 245 . " path on <pathelement>"); 246 } 247 foreach($parts as $part) { 248 $result[] = $part; 249 } 250 } elseif ($o instanceof Path) { 251 $p = $o; 252 if ($p->getProject() === null) { 253 $p->setProject($this->getProject()); 254 } 255 $parts = $p->listPaths(); 256 foreach($parts as $part) { 257 $result[] = $part; 258 } 259 } elseif ($o instanceof DirSet) { 260 $dset = $o; 261 $ds = $dset->getDirectoryScanner($this->project); 262 $dirstrs = $ds->getIncludedDirectories(); 263 $dir = $dset->getDir($this->project); 264 $this->addUnlessPresent($result, $dir, $s); 265 266 foreach($dirstrs as $dstr) { 267 $d = new PhingFile($dir, $dstr); 268 $result[] = $d->getAbsolutePath(); 269 } 270 271 } elseif ($o instanceof FileList) { 272 $fl = $o; 273 $dirstrs = $fl->getFiles($this->project); 274 $dir = $fl->getDir($this->project); 275 foreach($dirstrs as $dstr) { 276 $d = new PhingFile($dir, $dstr); 277 $result[] = $d->getAbsolutePath(); 278 } 279 } 280 } 281 282 return array_unique($result); 283 } 284 285 286 /** 287 * Returns a textual representation of the path, which can be used as 288 * CLASSPATH or PATH environment variable definition. 289 * @return string A textual representation of the path. 290 */ 291 public function __toString() { 292 293 $list = $this->listPaths(); 294 295 // empty path return empty string 296 if (empty($list)) { 297 return ""; 298 } 299 300 return implode(PATH_SEPARATOR, $list); 301 } 302 303 /** 304 * Splits a PATH (with : or ; as separators) into its parts. 305 * @param Project $project 306 * @param string $source 307 */ 308 public static function translatePath(Project $project, $source) { 309 $result = array(); 310 if ($source == null) { 311 return ""; 312 } 313 314 $tok = new PathTokenizer($source); 315 $element = ""; 316 while ($tok->hasMoreTokens()) { 317 $pathElement = $tok->nextToken(); 318 try { 319 $element .= self::resolveFile($project, $pathElement); 320 } catch (BuildException $e) { 321 $this->project->log("Dropping path element " . $pathElement 322 . " as it is not valid relative to the project", 323 PROJECT_MSG_VERBOSE); 324 } 325 326 for ($i = 0, $_i=strlen($element); $i < $_i; $i++) { 327 self::translateFileSep($element, $i); 328 } 329 $result[] = $element; 330 } 331 332 return $result; 333 } 334 335 /** 336 * Returns its argument with all file separator characters 337 * replaced so that they match the local OS conventions. 338 */ 339 public static function translateFile($source) { 340 if ($source == null) { 341 return ""; 342 } 343 344 $result = $source; 345 for ($i = 0, $_i=strlen($source); $i < $_i; $i++) { 346 self::translateFileSep($result, $i); 347 } 348 349 return $result; 350 } 351 352 /** 353 * Translates all occurrences of / or \ to correct separator of the 354 * current platform and returns whether it had to do any 355 * replacements. 356 */ 357 protected static function translateFileSep(&$buffer, $pos) { 358 if ($buffer{$pos} == '/' || $buffer{$pos} == '\\') { 359 $buffer{$pos} = DIRECTORY_SEPARATOR; 360 return true; 361 } 362 return false; 363 } 364 365 /** 366 * How many parts does this Path instance consist of. 367 * DEV NOTE: expensive call! list is generated, counted, and then 368 * discareded. 369 * @return int 370 */ 371 public function size() { 372 return count($this->listPaths()); 373 } 374 375 /** 376 * Return a Path that holds the same elements as this instance. 377 */ 378 public function __clone() { 379 $p = new Path($this->project); 380 $p->append($this); 381 return $p; 382 } 383 384 /** 385 * Overrides the version of DataType to recurse on all DataType 386 * child elements that may have been added. 387 * @throws BuildException 388 */ 389 public function dieOnCircularReference(&$stk, Project $p) { 390 391 if ($this->checked) { 392 return; 393 } 394 395 // elements can contain strings, FileSets, Reference, etc. 396 foreach($this->elements as $o) { 397 398 if ($o instanceof Reference) { 399 $o = $o->getReferencedObject($p); 400 } 401 402 if ($o instanceof DataType) { 403 if (in_array($o, $stk, true)) { 404 throw $this->circularReference(); 405 } else { 406 array_push($stk, $o); 407 $o->dieOnCircularReference($stk, $p); 408 array_pop($stk); 409 } 410 } 411 } 412 413 $this->checked = true; 414 } 415 416 /** 417 * Resolve a filename with Project's help - if we know one that is. 418 * 419 * <p>Assume the filename is absolute if project is null.</p> 420 */ 421 private static function resolveFile(Project $project, $relativeName) { 422 if ($project !== null) { 423 $f = $project->resolveFile($relativeName); 424 return $f->getAbsolutePath(); 425 } 426 return $relativeName; 427 } 428 429 } 430 431 432 /** 433 * Helper class, holds the nested <code><pathelement></code> values. 434 */ 435 class PathElement { 436 437 private $parts = array(); 438 private $outer; 439 440 public function __construct(Path $outer) { 441 $this->outer = $outer; 442 } 443 444 public function setDir(PhingFile $loc) { 445 $this->parts = array(Path::translateFile($loc->getAbsolutePath())); 446 } 447 448 public function setPath($path) { 449 $this->parts = Path::translatePath($this->outer->getProject(), $path); 450 } 451 452 public function getParts() { 453 return $this->parts; 454 } 455 } 456 ?>
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 |