| [ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 // 3 // +------------------------------------------------------------------------+ 4 // | PEAR :: Package File Manager | 5 // +------------------------------------------------------------------------+ 6 // | Copyright (c) 2003-2004 Gregory Beaver | 7 // | Email cellog@phpdoc.org | 8 // +------------------------------------------------------------------------+ 9 // | This source file is subject to version 3.00 of the PHP License, | 10 // | that is available at http://www.php.net/license/3_0.txt. | 11 // | If you did not receive a copy of the PHP license and are unable to | 12 // | obtain it through the world-wide-web, please send a note to | 13 // | license@php.net so we can mail you a copy immediately. | 14 // +------------------------------------------------------------------------+ 15 // | Portions of this code based on phpDocumentor | 16 // | Web http://www.phpdoc.org | 17 // | Mirror http://phpdocu.sourceforge.net/ | 18 // +------------------------------------------------------------------------+ 19 // $Id: PackageFileManager.php,v 1.42 2005/04/06 22:21:20 cellog Exp $ 20 // 21 22 /** 23 * @package PEAR_PackageFileManager 24 */ 25 /** 26 * PEAR installer 27 */ 28 require_once 'PEAR/Common.php'; 29 /**#@+ 30 * Error Codes 31 */ 32 define('PEAR_PACKAGEFILEMANAGER_NOSTATE', 1); 33 define('PEAR_PACKAGEFILEMANAGER_NOVERSION', 2); 34 define('PEAR_PACKAGEFILEMANAGER_NOPKGDIR', 3); 35 define('PEAR_PACKAGEFILEMANAGER_NOBASEDIR', 4); 36 define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND', 5); 37 define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE', 6); 38 define('PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE', 7); 39 define('PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE', 8); 40 define('PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE', 9); 41 define('PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE', 10); 42 define('PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST', 11); 43 define('PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES', 12); 44 define('PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST', 13); 45 define('PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS', 14); 46 define('PEAR_PACKAGEFILEMANAGER_NOPACKAGE', 15); 47 define('PEAR_PACKAGEFILEMANAGER_WRONG_MROLE', 16); 48 define('PEAR_PACKAGEFILEMANAGER_NOSUMMARY', 17); 49 define('PEAR_PACKAGEFILEMANAGER_NODESC', 18); 50 define('PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS', 19); 51 define('PEAR_PACKAGEFILEMANAGER_NO_FILES', 20); 52 define('PEAR_PACKAGEFILEMANAGER_IGNORED_EVERYTHING', 21); 53 define('PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE', 22); 54 define('PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE', 23); 55 define('PEAR_PACKAGEFILEMANAGER_INVALID_ROLE', 24); 56 define('PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE', 25); 57 define('PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED', 26); 58 define('PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO', 27); 59 /**#@-*/ 60 /** 61 * Error messages 62 * @global array $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'] 63 */ 64 $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'] = 65 array( 66 'en' => 67 array( 68 PEAR_PACKAGEFILEMANAGER_NOSTATE => 69 'Release State (option \'state\') must by specified in PEAR_PackageFileManager setOptions (alpha|beta|stable)', 70 PEAR_PACKAGEFILEMANAGER_NOVERSION => 71 'Release Version (option \'version\') must be specified in PEAR_PackageFileManager setOptions', 72 PEAR_PACKAGEFILEMANAGER_NOPKGDIR => 73 'Package source base directory (option \'packagedirectory\') must be ' . 74 'specified in PEAR_PackageFileManager setOptions', 75 PEAR_PACKAGEFILEMANAGER_NOBASEDIR => 76 'Package install base directory (option \'baseinstalldir\') must be ' . 77 'specified in PEAR_PackageFileManager setOptions', 78 PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND => 79 'Base class "%s" can\'t be located', 80 PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE => 81 'Base class "%s" can\'t be located in default or user-specified directories', 82 PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE => 83 'Failed to write package.xml file to destination directory', 84 PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE => 85 'Destination directory "%s" is unwritable', 86 PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE => 87 'Failed to copy package.xml.tmp file to package.xml', 88 PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE => 89 'Failed to open temporary file "%s" for writing', 90 PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST => 91 'package.xml file path "%s" doesn\'t exist or isn\'t a directory', 92 PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES => 93 'Directory "%s" is not a CVS directory (it must have the CVS/Entries file)', 94 PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST => 95 'Package source base directory "%s" doesn\'t exist or isn\'t a directory', 96 PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS => 97 'Run $managerclass->setOptions() before any other methods', 98 PEAR_PACKAGEFILEMANAGER_NOPACKAGE => 99 'Package Name (option \'package\') must by specified in PEAR_PackageFileManager '. 100 'setOptions to create a new package.xml', 101 PEAR_PACKAGEFILEMANAGER_NOSUMMARY => 102 'Package Summary (option \'summary\') must by specified in PEAR_PackageFileManager' . 103 ' setOptions to create a new package.xml', 104 PEAR_PACKAGEFILEMANAGER_NODESC => 105 'Detailed Package Description (option \'description\') must be' . 106 ' specified in PEAR_PackageFileManager setOptions to create a new package.xml', 107 PEAR_PACKAGEFILEMANAGER_WRONG_MROLE => 108 'Maintainer role must be one of "%s", was "%s"', 109 PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS => 110 'Add maintainers to a package before generating the package.xml', 111 PEAR_PACKAGEFILEMANAGER_NO_FILES => 112 'No files found, check the path "%s"', 113 PEAR_PACKAGEFILEMANAGER_IGNORED_EVERYTHING => 114 'No files left, check the path "%s" and ignore option "%s"', 115 PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE => 116 'Package validation failed:%s%s', 117 PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE => 118 'Replacement Type must be one of "%s", was passed "%s"', 119 PEAR_PACKAGEFILEMANAGER_INVALID_ROLE => 120 'Invalid file role passed to addRole, must be one of "%s", was passed "%s"', 121 PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE => 122 'addDependency had PHP as a package, use type="php"', 123 PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED => 124 'path "%path%" contains CVS directory', 125 PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO => 126 'PHP_Compat is not installed, cannot detect dependencies', 127 ), 128 // other language translations go here 129 ); 130 /** 131 * PEAR :: PackageFileManager updates the <filelist></filelist> section 132 * of a PEAR package.xml file to reflect the current files in 133 * preparation for a release. 134 * 135 * The PEAR_PackageFileManager class uses a plugin system to generate the 136 * list of files in a package. This allows both standard recursive 137 * directory parsing (plugin type file) and more intelligent options 138 * such as the CVS browser {@link PEAR_PackageFileManager_Cvs}, which 139 * grabs all files in a local CVS checkout to create the list, ignoring 140 * any other local files. 141 * 142 * Other options include specifying roles for file extensions (all .php 143 * files are role="php", for example), roles for directories (all directories 144 * named "tests" are given role="tests" by default), and exceptions. 145 * Exceptions are specific pathnames with * and ? wildcards that match 146 * a default role, but should have another. For example, perhaps 147 * a debug.tpl template would normally be data, but should be included 148 * in the docs role. Along these lines, to exclude files entirely, 149 * use the ignore option. 150 * 151 * Required options for a release include version, baseinstalldir, state, 152 * and packagedirectory (the full path to the local location of the 153 * package to create a package.xml file for) 154 * 155 * Example usage: 156 * <code> 157 * <?php 158 * require_once('PEAR/PackageFileManager.php'); 159 * $packagexml = new PEAR_PackageFileManager; 160 * $e = $packagexml->setOptions( 161 * array('baseinstalldir' => 'PhpDocumentor', 162 * 'version' => '1.2.1', 163 * 'packagedirectory' => 'C:/Web Pages/chiara/phpdoc2/', 164 * 'state' => 'stable', 165 * 'filelistgenerator' => 'cvs', // generate from cvs, use file for directory 166 * 'notes' => 'We\'ve implemented many new and exciting features', 167 * 'ignore' => array('TODO', 'tests/'), // ignore TODO, all files in tests/ 168 * 'installexceptions' => array('phpdoc' => '/*'), // baseinstalldir ="/" for phpdoc 169 * 'dir_roles' => array('tutorials' => 'doc'), 170 * 'exceptions' => array('README' => 'doc', // README would be data, now is doc 171 * 'PHPLICENSE.txt' => 'doc'))); // same for the license 172 * if (PEAR::isError($e)) { 173 * echo $e->getMessage(); 174 * die(); 175 * } 176 * $e = $test->addPlatformException('pear-phpdoc.bat', 'windows'); 177 * if (PEAR::isError($e)) { 178 * echo $e->getMessage(); 179 * exit; 180 * } 181 * $packagexml->addRole('pkg', 'doc'); // add a new role mapping 182 * if (PEAR::isError($e)) { 183 * echo $e->getMessage(); 184 * exit; 185 * } 186 * // replace @PHP-BIN@ in this file with the path to php executable! pretty neat 187 * $e = $test->addReplacement('pear-phpdoc', 'pear-config', '@PHP-BIN@', 'php_bin'); 188 * if (PEAR::isError($e)) { 189 * echo $e->getMessage(); 190 * exit; 191 * } 192 * $e = $test->addReplacement('pear-phpdoc.bat', 'pear-config', '@PHP-BIN@', 'php_bin'); 193 * if (PEAR::isError($e)) { 194 * echo $e->getMessage(); 195 * exit; 196 * } 197 * // note use of {@link debugPackageFile()} - this is VERY important 198 * if (isset($_GET['make']) || (isset($_SERVER['argv'][2]) && 199 * $_SERVER['argv'][2] == 'make')) { 200 * $e = $packagexml->writePackageFile(); 201 * } else { 202 * $e = $packagexml->debugPackageFile(); 203 * } 204 * if (PEAR::isError($e)) { 205 * echo $e->getMessage(); 206 * die(); 207 * } 208 * ?> 209 * </code> 210 * 211 * In addition, a package.xml file can now be generated from 212 * scratch, with the usage of new options package, summary, description, and 213 * the use of the {@link addMaintainer()} method 214 * @package PEAR_PackageFileManager 215 */ 216 class PEAR_PackageFileManager 217 { 218 /** 219 * Format: array(array(regexp-ready string to search for whole path, 220 * regexp-ready string to search for basename of ignore strings),...) 221 * @var false|array 222 * @access private 223 */ 224 var $_ignore = false; 225 226 /** 227 * Contents of the package.xml file 228 * @var string 229 * @access private 230 */ 231 var $_packageXml = false; 232 233 /** 234 * Contents of the original package.xml file, if any 235 * @var string 236 * @access private 237 */ 238 var $_oldPackageXml = false; 239 240 /** 241 * @access private 242 * @var PEAR_Common 243 */ 244 var $_pear; 245 246 /** 247 * @access private 248 * @var array 249 */ 250 var $_warningStack = array(); 251 252 /** 253 * flag used to determine whether to use PHP_CompatInfo to detect deps 254 * @var boolean 255 * @access private 256 */ 257 var $_detectDependencies = false; 258 259 /** 260 * @access private 261 * @var string 262 */ 263 var $_options = array( 264 'packagefile' => 'package.xml', 265 'doctype' => 'http://pear.php.net/dtd/package-1.0', 266 'filelistgenerator' => 'file', 267 'license' => 'PHP License', 268 'changelogoldtonew' => true, 269 'roles' => 270 array( 271 'php' => 'php', 272 'html' => 'doc', 273 '*' => 'data', 274 ), 275 'dir_roles' => 276 array( 277 'docs' => 'doc', 278 'examples' => 'doc', 279 'tests' => 'test', 280 ), 281 'exceptions' => array(), 282 'installexceptions' => array(), 283 'installas' => array(), 284 'platformexceptions' => array(), 285 'scriptphaseexceptions' => array(), 286 'ignore' => array(), 287 'include' => false, 288 'deps' => false, 289 'maintainers' => false, 290 'notes' => '', 291 'changelognotes' => false, 292 'outputdirectory' => false, 293 'pathtopackagefile' => false, 294 'lang' => 'en', 295 'configure_options' => array(), 296 'replacements' => array(), 297 'pearcommonclass' => false, 298 'simpleoutput' => false, 299 'addhiddenfiles' => false, 300 'cleardependencies' => false, 301 ); 302 303 /** 304 * Does nothing, use setOptions 305 * 306 * The constructor is not used in order to be able to 307 * return a PEAR_Error from setOptions 308 * @see setOptions() 309 */ 310 function PEAR_PackageFileManager() 311 { 312 } 313 314 /** 315 * Set package.xml generation options 316 * 317 * The options array is indexed as follows: 318 * <code> 319 * $options = array('option_name' => <optionvalue>); 320 * </code> 321 * 322 * The documentation below simplifies this description through 323 * the use of option_name without quotes 324 * 325 * Configuration options: 326 * - lang: lang controls the language in which error messages are 327 * displayed. There are currently only English error messages, 328 * but any contributed will be added over time.<br> 329 * Possible values: en (default) 330 * - packagefile: the name of the packagefile, defaults to package.xml 331 * - pathtopackagefile: the path to an existing package file to read in, 332 * if different from the packagedirectory 333 * - packagedirectory: the path to the base directory of the package. For 334 * package PEAR_PackageFileManager, this path is 335 * /path/to/pearcvs/pear/PEAR_PackageFileManager where 336 * /path/to/pearcvs is a local path on your hard drive 337 * - outputdirectory: the path in which to place the generated package.xml 338 * by default, this is ignored, and the package.xml is 339 * created in the packagedirectory 340 * - filelistgenerator: the <filelist> section plugin which will be used. 341 * In this release, there are two generator plugins, 342 * file and cvs. For details, see the docs for these 343 * plugins 344 * - usergeneratordir: For advanced users. If you write your own filelist 345 * generator plugin, use this option to tell 346 * PEAR_PackageFileManager where to find the file that 347 * contains it. If the plugin is named foo, the class 348 * must be named PEAR_PackageFileManager_Foo 349 * no matter where it is located. By default, the Foo 350 * plugin is located in PEAR/PackageFileManager/Foo.php. 351 * If you pass /path/to/foo in this option, setOptions 352 * will look for PEAR_PackageFileManager_Foo in 353 * /path/to/foo/Foo.php 354 * - doctype: Specifies the DTD of the package.xml file. Default is 355 * http://pear.php.net/dtd/package-1.0 356 * - pearcommonclass: Specifies the name of the class to instantiate, default 357 * is PEAR_Common, but users can override this with a custom 358 * class that implements PEAR_Common's method interface 359 * - changelogoldtonew: True if the ChangeLog should list from oldest entry to 360 * newest. Set to false if you would like new entries first 361 * - simpleoutput: True if the package.xml should not contain md5sum or <provides /> 362 * for readability 363 * - addhiddenfiles: True if you wish to add hidden files/directories that begin with . 364 * like .bashrc. This is only used by the File generator. The CVS 365 * generator will use all files in CVS regardless of format 366 * 367 * package.xml simple options: 368 * - baseinstalldir: The base directory to install this package in. For 369 * package PEAR_PackageFileManager, this is "PEAR", for 370 * package PEAR, this is "/" 371 * - license: The license this release is released under. Default is 372 * PHP License if left unspecified 373 * - notes: Release notes, any text describing what makes this release unique 374 * - changelognotes: notes for the changelog, this should be more detailed than 375 * the release notes. By default, PEAR_PackageFileManager uses 376 * the notes option for the changelog as well 377 * - version: The version number for this release. Remember the convention for 378 * numbering: initial alpha is between 0 and 1, add b<beta number> for 379 * beta as in 1.0b1, the integer portion of the version should specify 380 * backwards compatibility, as in 1.1 is backwards compatible with 1.0, 381 * but 2.0 is not backwards compatible with 1.10. Also note that 1.10 382 * is a greater release version than 1.1 (think of it as "one point ten" 383 * and "one point one"). Bugfix releases should be a third decimal as in 384 * 1.0.1, 1.0.2 385 * - package: [optional] Package name. Use this to create a new package.xml, or 386 * overwrite an existing one from another package used as a template 387 * - summary: [optional] Summary of package purpose 388 * - description: [optional] Description of package purpose. Note that the above 389 * three options are not optional when creating a new package.xml 390 * from scratch 391 * 392 * <b>WARNING</b>: all complex options that require a file path are case-sensitive 393 * 394 * package.xml complex options: 395 * - cleardependencies: since version 1.3.0, this option will erase any existing 396 * dependencies in the package.xml if set to true 397 * - ignore: an array of filenames, directory names, or wildcard expressions specifying 398 * files to exclude entirely from the package.xml. Wildcards are operating system 399 * wildcards * and ?. file*foo.php will exclude filefoo.php, fileabrfoo.php and 400 * filewho_is_thisfoo.php. file?foo.php will exclude fileafoo.php and will not 401 * exclude fileaafoo.php. test/ will exclude all directories and subdirectories of 402 * ANY directory named test encountered in directory parsing. *test* will exclude 403 * all files and directories that contain test in their name 404 * - include: an array of filenames, directory names, or wildcard expressions specifying 405 * files to include in the listing. All other files will be ignored. 406 * Wildcards are in the same format as ignore 407 * - roles: this is an array mapping file extension to install role. This 408 * specifies default behavior that can be overridden by the exceptions 409 * option and dir_roles option. use {@link addRole()} to add a new 410 * role to the pre-existing array 411 * - dir_roles: this is an array mapping directory name to install role. All 412 * files in a directory whose name matches the directory will be 413 * given the install role specified. Single files can be excluded 414 * from this using the exceptions option. The directory should be 415 * a relative path from the baseinstalldir, or "/" for the baseinstalldir 416 * - exceptions: specify file role for specific files. This array maps all files 417 * matching the exact name of a file to a role as in "file.ext" => "role" 418 * - deps: dependency array. Pass in an empty array to clear all dependencies, and use 419 * {@link addDependency()} to add new ones/replace existing ones 420 * - maintainers: maintainers array. Pass in an empty array to clear all maintainers, and 421 * use {@link addMaintainer()} to add a new maintainer/replace existing maintainer 422 * - installexceptions: array mapping of specific filenames to baseinstalldir values. Use 423 * this to force the installation of a file into another directory, 424 * such as forcing a script to be in the root scripts directory so that 425 * it will be in the path. The filename must be a relative path to the 426 * packagedirectory 427 * - platformexceptions: array mapping of specific filenames to the platform they should be 428 * installed on. Use this to specify unix-only files or windows-only 429 * files. The format of the platform string must be 430 * OS-version-cpu-extra if any more specific information is needed, 431 * and the OS must be in lower case as in "windows." The match is 432 * performed using a regular expression, but uses * and ? wildcards 433 * instead of .* and .?. Note that hpux/aix/irix/linux are all 434 * exclusive. To select non-windows, use (*ix|*ux) 435 * - scriptphaseexceptions: array mapping of scripts to their install phase. This can be 436 * one of: pre-install, post-install, pre-uninstall, post-uninstall, 437 * pre-build, post-build, pre-setup, or post-setup 438 * - installas: array mapping of specific filenames to the filename they should be installed as. 439 * Use this to specify new filenames for files that should be installed. This will 440 * often be used in conjunction with platformexceptions if there are two files for 441 * different OSes that must have the same name when installed. 442 * - replacements: array mapping of specific filenames to complex text search-and-replace that 443 * should be performed upon install. The format is: 444 * <pre> 445 * filename => array('type' => php-const|pear-config|package-info 446 * 'from' => text in file 447 * 'to' => name of variable) 448 * </pre> 449 * if type is php-const, then 'to' must be the name of a PHP Constant. 450 * If type is pear-config, then 'to' must be the name of a PEAR config 451 * variable accessible through a PEAR_Config class->get() method. If 452 * type is package-info, then 'to' must be the name of a section from 453 * the package.xml file used to install this file. 454 * - globalreplacements: a list of replacements that should be performed on every single file. 455 * The format is the same as replacements (since 1.4.0) 456 * - configure_options: array specifies build options for PECL packages (you should probably 457 * use PECL_Gen instead, but it's here for completeness) 458 * @see PEAR_PackageFileManager_File 459 * @see PEAR_PackageFileManager_CVS 460 * @return void|PEAR_Error 461 * @throws PEAR_PACKAGEFILEMANAGER_NOSTATE 462 * @throws PEAR_PACKAGEFILEMANAGER_NOVERSION 463 * @throws PEAR_PACKAGEFILEMANAGER_NOPKGDIR 464 * @throws PEAR_PACKAGEFILEMANAGER_NOBASEDIR 465 * @throws PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE 466 * @throws PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND 467 * @param array 468 */ 469 function setOptions($options = array(), $internal = false) 470 { 471 if (!$internal) { 472 if (!isset($options['state'])) { 473 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSTATE); 474 } 475 if (!isset($options['version'])) { 476 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOVERSION); 477 } 478 } 479 if (!isset($options['packagedirectory']) && !$internal) { 480 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPKGDIR); 481 } elseif (isset($options['packagedirectory'])) { 482 $options['packagedirectory'] = str_replace(DIRECTORY_SEPARATOR, 483 '/', 484 realpath($options['packagedirectory'])); 485 if ($options['packagedirectory']{strlen($options['packagedirectory']) - 1} != '/') { 486 $options['packagedirectory'] .= '/'; 487 } 488 } 489 if (isset($options['pathtopackagefile'])) { 490 $options['pathtopackagefile'] = str_replace(DIRECTORY_SEPARATOR, 491 '/', 492 realpath($options['pathtopackagefile'])); 493 if ($options['pathtopackagefile']{strlen($options['pathtopackagefile']) - 1} != '/') { 494 $options['pathtopackagefile'] .= '/'; 495 } 496 } 497 if (!isset($options['baseinstalldir']) && !$internal) { 498 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOBASEDIR); 499 } 500 $this->_options = array_merge($this->_options, $options); 501 502 if (!class_exists($this->_options['pearcommonclass'])) { 503 if ($this->_options['simpleoutput']) { 504 if ($this->isIncludeable('PEAR/PackageFile/Generator/v1.php')) { 505 include_once 'PEAR/PackageFileManager/SimpleGenerator.php'; 506 $this->_options['pearcommonclass'] = 'PEAR_PackageFileManager_SimpleGenerator'; 507 } else { 508 include_once 'PEAR/PackageFileManager/XMLOutput.php'; 509 $this->_options['pearcommonclass'] = 'PEAR_PackageFileManager_XMLOutput'; 510 } 511 } else { 512 $this->_options['pearcommonclass'] = 'PEAR_Common'; 513 } 514 } 515 $path = ($this->_options['pathtopackagefile'] ? 516 $this->_options['pathtopackagefile'] : $this->_options['packagedirectory']); 517 $this->_options['filelistgenerator'] = 518 ucfirst(strtolower($this->_options['filelistgenerator'])); 519 if (!$internal) { 520 if (PEAR::isError($res = 521 $this->_getExistingPackageXML($path, $this->_options['packagefile']))) { 522 return $res; 523 } 524 } 525 if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) { 526 // attempt to load the interface from the standard PEAR location 527 if ($this->isIncludeable('PEAR/PackageFileManager/' . 528 $this->_options['filelistgenerator'] . '.php')) { 529 include_once('PEAR/PackageFileManager/' . 530 $this->_options['filelistgenerator'] . '.php'); 531 } elseif (isset($this->_options['usergeneratordir'])) { 532 // attempt to load from a user-specified directory 533 if (is_dir(realpath($this->_options['usergeneratordir']))) { 534 $this->_options['usergeneratordir'] = 535 str_replace(DIRECTORY_SEPARATOR, 536 '/', 537 realpath($this->_options['usergeneratordir'])); 538 if ($this->_options['usergeneratordir']{strlen($this->_options['usergeneratordir']) 539 - 1} != '/') { 540 $this->_options['usergeneratordir'] .= '/'; 541 } 542 } else { 543 $this->_options['usergeneratordir'] = '////'; 544 } 545 if (file_exists($this->_options['usergeneratordir'] . 546 $this->_options['filelistgenerator'] . '.php') && 547 is_readable($this->_options['usergeneratordir'] . 548 $this->_options['filelistgenerator'] . '.php')) { 549 include_once($this->_options['usergeneratordir'] . 550 $this->_options['filelistgenerator'] . '.php'); 551 } 552 if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) { 553 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE, 554 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']); 555 } 556 } else { 557 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND, 558 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']); 559 } 560 } 561 } 562 563 /** 564 * Import options from an existing package.xml 565 * 566 * @return true|PEAR_Error 567 */ 568 function importOptions($packagefile, $options = array()) 569 { 570 $options['cleardependencies'] = $options['deps'] = $options['maintainers'] = false; 571 $this->setOptions($options, true); 572 if (PEAR::isError($res = $this->_getExistingPackageXML(dirname($packagefile) . 573 DIRECTORY_SEPARATOR, basename($packagefile)))) { 574 return $res; 575 } 576 $this->_options['package'] = $this->_oldPackageXml['package']; 577 $this->_options['summary'] = $this->_oldPackageXml['summary']; 578 $this->_options['description'] = $this->_oldPackageXml['description']; 579 $this->_options['date'] = $this->_oldPackageXml['release_date']; 580 $this->_options['version'] = $this->_oldPackageXml['version']; 581 $this->_options['license'] = $this->_oldPackageXml['release_license']; 582 $this->_options['state'] = $this->_oldPackageXml['release_state']; 583 $this->_options['notes'] = $this->_oldPackageXml['release_notes']; 584 if (isset($this->_oldPackagexml['release_deps'])) { 585 $this->_options['deps'] = $this->_oldPackageXml['release_deps']; 586 } 587 $this->_options['maintainers'] = $this->_oldPackageXml['maintainers']; 588 return true; 589 } 590 591 /** 592 * Get the existing options 593 * @return array 594 */ 595 function getOptions() 596 { 597 return $this->_options; 598 } 599 600 /** 601 * Add an extension/role mapping to the role mapping option 602 * 603 * Roles influence both where a file is installed and how it is installed. 604 * Files with role="data" are in a completely different directory hierarchy 605 * from the program files of role="php" 606 * 607 * In PEAR 1.3b2, these roles are 608 * - php (most common) 609 * - data 610 * - doc 611 * - test 612 * - script (gives the file an executable attribute) 613 * - src 614 * @param string file extension 615 * @param string role 616 * @throws PEAR_PACKAGEFILEMANAGER_INVALID_ROLE 617 */ 618 function addRole($extension, $role) 619 { 620 $roles = call_user_func(array($this->_options['pearcommonclass'], 'getfileroles')); 621 if (!in_array($role, $roles)) { 622 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_ROLE, implode($roles, ', '), $role); 623 } 624 $this->_options['roles'][$extension] = $role; 625 } 626 627 /** 628 * Add an install-time platform conditional install for a file 629 * 630 * The format of the platform string must be 631 * OS-version-cpu-extra if any more specific information is needed, 632 * and the OS must be in lower case as in "windows." The match is 633 * performed using a regular expression, but uses * and ? wildcards 634 * instead of .* and .?. Note that hpux/aix/irix/linux are all 635 * exclusive. To select non-windows, use (*ix|*ux) 636 * 637 * This information is based on eyeing the source for OS/Guess.php, so 638 * if you are unsure of what to do, read that file. 639 * @param string relative path of file (relative to packagedirectory option) 640 * @param string platform descriptor string 641 */ 642 function addPlatformException($path, $platform) 643 { 644 if (!isset($this->_options['platformexceptions'])) { 645 $this->_options['platformexceptions'] = array(); 646 } 647 $this->_options['platformexceptions'][$path] = $platform; 648 } 649 650 /** 651 * Add a replacement option for all files 652 * 653 * This sets an install-time complex search-and-replace function 654 * allowing the setting of platform-specific variables in all 655 * installed files. 656 * 657 * if $type is php-const, then $to must be the name of a PHP Constant. 658 * If $type is pear-config, then $to must be the name of a PEAR config 659 * variable accessible through a {@link PEAR_Config::get()} method. If 660 * type is package-info, then $to must be the name of a section from 661 * the package.xml file used to install this file. 662 * @param string relative path of file (relative to packagedirectory option) 663 * @param string variable type, either php-const, pear-config or package-info 664 * @param string text to replace in the source file 665 * @param string variable name to use for replacement 666 * @throws PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE 667 */ 668 function addGlobalReplacement($type, $from, $to) 669 { 670 if (!isset($this->_options['globalreplacements'])) { 671 $this->_options['globalreplacements'] = array(); 672 } 673 $types = call_user_func(array($this->_options['pearcommonclass'], 'getreplacementtypes')); 674 if (!in_array($type, $types)) { 675 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE, 676 implode($types, ', '), $type); 677 } 678 $this->_options['globalreplacements'][] = 679 array('type' => $type, 'from' => $from, 'to' => $to); 680 } 681 682 /** 683 * Add a replacement option for a file 684 * 685 * This sets an install-time complex search-and-replace function 686 * allowing the setting of platform-specific variables in an 687 * installed file. 688 * 689 * if $type is php-const, then $to must be the name of a PHP Constant. 690 * If $type is pear-config, then $to must be the name of a PEAR config 691 * variable accessible through a {@link PEAR_Config::get()} method. If 692 * type is package-info, then $to must be the name of a section from 693 * the package.xml file used to install this file. 694 * @param string relative path of file (relative to packagedirectory option) 695 * @param string variable type, either php-const, pear-config or package-info 696 * @param string text to replace in the source file 697 * @param string variable name to use for replacement 698 * @throws PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE 699 */ 700 function addReplacement($path, $type, $from, $to) 701 { 702 if (!isset($this->_options['replacements'])) { 703 $this->_options['replacements'] = array(); 704 } 705 $types = call_user_func(array($this->_options['pearcommonclass'], 'getreplacementtypes')); 706 if (!in_array($type, $types)) { 707 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE, 708 implode($types, ', '), $type); 709 } 710 $this->_options['replacements'][$path][] = array('type' => $type, 'from' => $from, 'to' => $to); 711 } 712 713 /** 714 * Add a maintainer to the list of maintainers. 715 * 716 * Every maintainer must have a valid account at pear.php.net. The 717 * first parameter is the account name (for instance, cellog is the 718 * handle for Greg Beaver at pear.php.net). Every maintainer has 719 * one of four possible roles: 720 * - lead: the primary maintainer 721 * - developer: an important developer on the project 722 * - contributor: self-explanatory 723 * - helper: ditto 724 * 725 * Finally, specify the name and email of the maintainer 726 * @param string username on pear.php.net of maintainer 727 * @param lead|developer|contributor|helper role of maintainer 728 * @param string full name of maintainer 729 * @param string email address of maintainer 730 */ 731 function addMaintainer($handle, $role, $name, $email) 732 { 733 if (!$this->_packageXml) { 734 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS); 735 } 736 if (!in_array($role, $GLOBALS['_PEAR_Common_maintainer_roles'])) { 737 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_WRONG_MROLE, 738 implode(', ', call_user_func(array($this->_options['pearcommonclass'], 739 'getUserRoles'))), 740 $role); 741 } 742 if (!isset($this->_packageXml['maintainers'])) { 743 $this->_packageXml['maintainers'] = array(); 744 } 745 $found = false; 746 foreach($this->_packageXml['maintainers'] as $index => $maintainer) { 747 if ($maintainer['handle'] == $handle) { 748 $found = $index; 749 break; 750 } 751 } 752 $maintainer = 753 array('handle' => $handle, 'role' => $role, 'name' => $name, 'email' => $email); 754 if ($found !== false) { 755 $this->_packageXml['maintainers'][$found] = $maintainer; 756 } else { 757 $this->_packageXml['maintainers'][] = $maintainer; 758 } 759 } 760 761 /** 762 * Add an install-time configuration option for building of source 763 * 764 * This option is only useful to PECL projects that are built upon 765 * installation 766 * @param string name of the option 767 * @param string prompt to display to the user 768 * @param string default value 769 * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS 770 * @return void|PEAR_Error 771 */ 772 function addConfigureOption($name, $prompt, $default = null) 773 { 774 if (!$this->_packageXml) { 775 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS); 776 } 777 if (!isset($this->_packageXml['configure_options'])) { 778 $this->_packageXml['configure_options'] = array(); 779 } 780 $found = false; 781 foreach($this->_packageXml['configure_options'] as $index => $option) { 782 if ($option['name'] == $name) { 783 $found = $index; 784 break; 785 } 786 } 787 $option = array('name' => $name, 'prompt' => $prompt); 788 if (isset($default)) { 789 $option['default'] = $default; 790 } 791 if ($found !== false) { 792 $this->_packageXml['configure_options'][$found] = $option; 793 } else { 794 $this->_packageXml['configure_options'][] = $option; 795 } 796 } 797 798 /** 799 * @return void|PEAR_Error 800 * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS 801 */ 802 function detectDependencies() 803 { 804 if (!$this->_packageXml) { 805 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS); 806 } 807 if (!$this->isIncludeable('PHP/CompatInfo.php')) { 808 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PHP_COMPAT_NOT_INSTALLED); 809 } else { 810 if (include_once('PHP/CompatInfo.php')) { 811 $this->_detectDependencies = true; 812 } else { 813 $this->raiseError(PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO); 814 } 815 } 816 } 817 818 function isIncludeable($file) 819 { 820 if (!defined('PATH_SEPARATOR')) { 821 define('PATH_SEPARATOR', strtolower(substr(PHP_OS, 0, 3)) == 'win' ? ';' : ':'); 822 } 823 foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $path) { 824 if (file_exists($path . DIRECTORY_SEPARATOR . $file) && 825 is_readable($path . DIRECTORY_SEPARATOR . $file)) { 826 return true; 827 } 828 } 829 return false; 830 } 831 832 /** 833 * Add a dependency on another package, or an extension/php 834 * 835 * This will overwrite an existing dependency if it is found. In 836 * other words, if a dependency on PHP 4.1.0 exists, and 837 * addDependency('php', '4.3.0', 'ge', 'php') is called, the existing 838 * dependency on PHP 4.1.0 will be overwritten with the new one on PHP 4.3.0 839 * @param string Dependency element name 840 * @param string Dependency version 841 * @param string A specific operator for the version, this can be one of: 842 * 'has', 'not', 'lt', 'le', 'eq', 'ne', 'ge', or 'gt' 843 * @param string Dependency type. This can be one of: 844 * 'pkg', 'ext', 'php', 'prog', 'os', 'sapi', or 'zend' 845 * @param boolean true if dependency is optional 846 * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS 847 * @throws PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE 848 * @return void|PEAR_Error 849 */ 850 function addDependency($name, $version = false, $operator = 'ge', $type = 'pkg', $optional = false) 851 { 852 if (!$this->_packageXml) { 853 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS); 854 } 855 if ((strtolower($name) == 'php') && (strtolower($type) == 'pkg')) { 856 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE); 857 } 858 if (!isset($this->_packageXml['release_deps']) || !is_array($this->_packageXml['release_deps'])) { 859 $this->_packageXml['release_deps'] = array(); 860 } 861 $found = false; 862 foreach($this->_packageXml['release_deps'] as $index => $dep) { 863 if ($type == 'php') { 864 if ($dep['type'] == 'php') { 865 $found = $index; 866 break; 867 } 868 } else { 869 if (isset($dep['name']) && $dep['name'] == $name && $dep['type'] == $type) { 870 $found = $index; 871 break; 872 } 873 } 874 } 875 $dep = 876 array( 877 'name' => $name, 878 'type' => $type); 879 if ($type == 'php') { 880 unset($dep['name']); 881 } 882 if ($operator) { 883 $dep['rel'] = $operator; 884 if ($dep['rel'] != 'has' && $version) { 885 $dep['version'] = $version; 886 } 887 } 888 889 if ($optional) { 890 $dep['optional'] = 'yes'; 891 } else { 892 $dep['optional'] = 'no'; 893 } 894 895 if ($found !== false) { 896 $this->_packageXml['release_deps'][$found] = $dep; // overwrite existing dependency 897 } else { 898 $this->_packageXml['release_deps'][] = $dep; // add new dependency 899 } 900 } 901 902 /** 903 * Writes the package.xml file out with the newly created <release></release> tag 904 * 905 * ALWAYS use {@link debugPackageFile} to verify that output is correct before 906 * overwriting your package.xml 907 * @param boolean null if no debugging, true if web interface, false if command-line 908 * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS 909 * @throws PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS 910 * @throws PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE 911 * @throws PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE 912 * @throws PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE 913 * @throws PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE 914 * @return void|PEAR_Error 915 */ 916 function writePackageFile($debuginterface = null) 917 { 918 if (!$this->_packageXml) { 919 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS); 920 } 921 if (!isset($this->_packageXml['maintainers']) || empty($this->_packageXml['maintainers'])) { 922 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS); 923 } 924 extract($this->_options); 925 $date = date('Y-m-d'); 926 if (isset($package)) { 927 $this->_packageXml['package'] = $package; 928 } 929 if (isset($summary)) { 930 $this->_packageXml['summary'] = $summary; 931 } 932 if (isset($description)) { 933 $this->_packageXml['description'] = $description; 934 } 935 $this->_packageXml['release_date'] = $date; 936 $this->_packageXml['version'] = $version; 937 $this->_packageXml['release_license'] = $license; 938 $this->_packageXml['release_state'] = $state; 939 $this->_packageXml['release_notes'] = $notes; 940 $PEAR_Common = $this->_options['pearcommonclass']; 941 $this->_pear = new $PEAR_Common; 942 if (method_exists($this->_pear, 'setPackageFileManager')) { 943 $this->_pear->setPackageFileManager($this); 944 } 945 $this->_packageXml['filelist'] = $this->_getFileList(); 946 $warnings = $this->getWarnings(); 947 if (count($warnings)) { 948 $nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n"); 949 foreach($warnings as $errmsg) { 950 echo 'WARNING: ' . $errmsg['message'] . $nl; 951 } 952 } 953 if (PEAR::isError($this->_packageXml['filelist'])) { 954 return $this->_packageXml['filelist']; 955 } 956 if (isset($this->_pear->pkginfo['provides'])) { 957 $this->_packageXml['provides'] = $this->_pear->pkginfo['provides']; 958 } 959 if ($this->_options['simpleoutput']) { 960 unset($this->_packageXml['provides']); 961 } 962 $this->_packageXml['release_deps'] = $this->_getDependencies(); 963 $this->_updateChangeLog(); 964 965 $common = &$this->_pear; 966 $warnings = $errors = array(); 967 if (method_exists($common, 'setPackageFileManagerOptions')) { 968 $common->setPackageFileManagerOptions($this->_options); 969 } 970 $packagexml = $common->xmlFromInfo($this->_packageXml); 971 $common->validatePackageInfo($packagexml, $warnings, $errors, 972 $this->_options['packagedirectory']); 973 if (count($errors)) { 974 $ret = ''; 975 $nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n"); 976 foreach($errors as $errmsg) { 977 $ret .= $errmsg . $nl; 978 } 979 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE, $nl, $ret); 980 } 981 if (count($warnings)) { 982 $nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n"); 983 foreach($warnings as $errmsg) { 984 echo $errmsg . $nl; 985 } 986 } 987 if (!strpos($packagexml, '<!DOCTYPE')) { 988 // hack to fix pear 989 $packagexml = str_replace('<package version="1.0">', 990 '<!DOCTYPE package SYSTEM "' . $this->_options['doctype'] . 991 "\">\n<package version=\"1.0\">", 992 $packagexml); 993 } 994 if (isset($debuginterface)) { 995 if ($debuginterface) { 996 echo '<pre>' . htmlentities($packagexml) . '</pre>'; 997 } else { 998 echo $packagexml; 999 } 1000 return true; 1001 } 1002 $outputdir = ($this->_options['outputdirectory'] ? 1003 $this->_options['outputdirectory'] : $this->_options['packagedirectory']); 1004 if ((file_exists($outputdir . $this->_options['packagefile']) && 1005 is_writable($outputdir . $this->_options['packagefile'])) 1006 || 1007 @touch($outputdir . $this->_options['packagefile'])) { 1008 if ($fp = @fopen($outputdir . $this->_options['packagefile'] . '.tmp', "w")) { 1009 $written = @fwrite($fp, $packagexml); 1010 @fclose($fp); 1011 if ($written === false) { 1012 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE); 1013 } 1014 if (!@copy($outputdir . $this->_options['packagefile'] . '.tmp', 1015 $outputdir . $this->_options['packagefile'])) { 1016 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE); 1017 } else { 1018 @unlink($outputdir . $this->_options['packagefile'] . '.tmp'); 1019 return true; 1020 } 1021 } else { 1022 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE, 1023 $outputdir . $this->_options['packagefile'] . '.tmp'); 1024 } 1025 } else { 1026 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE, $outputdir); 1027 } 1028 } 1029 1030 /** 1031 * ALWAYS use this to test output before overwriting your package.xml!! 1032 * 1033 * This method instructs writePackageFile() to simply print the package.xml 1034 * to output, either command-line or web-friendly (this is automatic 1035 * based on the value of php_sapi_name()) 1036 * @uses writePackageFile() calls with the debug parameter set based on 1037 * whether it is called from the command-line or web interface 1038 */ 1039 function debugPackageFile() 1040 { 1041 $webinterface = php_sapi_name() != 'cli'; 1042 return $this->writePackageFile($webinterface); 1043 } 1044 1045 /** 1046 * Store a warning on the warning stack 1047 */ 1048 function pushWarning($code, $info) 1049 { 1050 $this->_warningStack[] = array('code' => $code, 1051 'message' => $this->_getMessage($code, $info)); 1052 } 1053 1054 /** 1055 * Retrieve the list of warnings 1056 * @return array 1057 */ 1058 function getWarnings() 1059 { 1060 $a = $this->_warningStack; 1061 $this->_warningStack = array(); 1062 return $a; 1063 } 1064 1065 /** 1066 * Retrieve an error message from a code 1067 * @access private 1068 * @return string Error message 1069 */ 1070 function _getMessage($code, $info) 1071 { 1072 $msg = $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code]; 1073 foreach ($info as $name => $value) { 1074 $msg = str_replace('%' . $name . '%', $value, $msg); 1075 } 1076 return $msg; 1077 } 1078 1079 /** 1080 * Utility function to shorten error generation code 1081 * 1082 * {@source} 1083 * @return PEAR_Error 1084 * @static 1085 */ 1086 function raiseError($code, $i1 = '', $i2 = '') 1087 { 1088 return PEAR::raiseError('PEAR_PackageFileManager Error: ' . 1089 sprintf($GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code], 1090 $i1, $i2), $code); 1091 } 1092 1093 /** 1094 * Uses {@link PEAR_Common::analyzeSourceCode()} and {@link PEAR_Common::buildProvidesArray()} 1095 * to create the <provides></provides> section of the package.xml 1096 * @param PEAR_Common 1097 * @param string path to source file 1098 * @access private 1099 */ 1100 function _addProvides(&$pear, $file) 1101 { 1102 if (!($a = $pear->analyzeSourceCode($file))) { 1103 return; 1104 } else { 1105 $pear->buildProvidesArray($a); 1106 } 1107 } 1108 1109 /** 1110 * @uses getDirTag() generate the xml from the array 1111 * @return string 1112 * @access private 1113 */ 1114 function _getFileList() 1115 { 1116 $generatorclass = 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']; 1117 $generator = new $generatorclass($this, $this->_options); 1118 if ($this->_options['simpleoutput'] && is_a($this->_pear, 'PEAR_Common')) { 1119 return $this->_getSimpleDirTag($this->_struc = $generator->getFileList()); 1120 } 1121 return $this->_getDirTag($this->_struc = $generator->getFileList()); 1122 } 1123 1124 /** 1125 * Recursively generate the <filelist> section's <dir> and <file> tags, but with 1126 * simple human-readable output 1127 * @param array|PEAR_Error the sorted directory structure, or an error 1128 * from filelist generation 1129 * @param false|string whether the parent directory has a role this should 1130 * inherit 1131 * @param integer indentation level 1132 * @return array|PEAR_Error 1133 * @access private 1134 */ 1135 function _getSimpleDirTag($struc, $role = false, $_curdir = '') 1136 { 1137 if (PEAR::isError($struc)) { 1138 return $struc; 1139 } 1140 extract($this->_options); 1141 $ret = array(); 1142 foreach($struc as $dir => $files) { 1143 if (false && $dir === '/') { 1144 // global directory role? overrides all exceptions except file exceptions 1145 if (isset($dir_roles['/'])) { 1146 $role = $dir_roles['/']; 1147 } 1148 return array( 1149 'baseinstalldir' => $this->_options['baseinstalldir'], 1150 '##files' => $this->_getSimpleDirTag($struc[$dir], $role, ''), 1151 'name' => '/'); 1152 } else { 1153 if (!isset($files['file'])) { 1154 if (isset($dir_roles[$_curdir . $dir])) { 1155 $myrole = $dir_roles[$_curdir . $dir]; 1156 } else { 1157 $myrole = $role; 1158 } 1159 $ret[$dir] = array(); 1160 if ($dir == '/') { 1161 $ret[$dir]['baseinstalldir'] = $this->_options['baseinstalldir']; 1162 } 1163 $ret[$dir]['name'] = $dir; 1164 $recurdir = ($_curdir == '') ? $dir . '/' : $_curdir . $dir . '/'; 1165 if ($recurdir == '//') { 1166 $recurdir = ''; 1167 } 1168 $ret[$dir]['##files'] = $this->_getSimpleDirTag($files, $myrole, $recurdir); 1169 } else { 1170 $myrole = ''; 1171 if (!$role) 1172 { 1173 $myrole = false; 1174 if (isset($exceptions[$files['path']])) { 1175 $myrole = $exceptions[$files['path']]; 1176 } elseif (isset($roles[$files['ext']])) { 1177 $myrole = $roles[$files['ext']]; 1178 } else { 1179 $myrole = $roles['*']; 1180 } 1181 } else { 1182 $myrole = $role; 1183 if (isset($exceptions[$files['path']])) { 1184 $myrole = $exceptions[$files['path']]; 1185 } 1186 } 1187 $test = explode('/', $files['path']); 1188 foreach ($test as $subpath) { 1189 if ($subpath == 'CVS') { 1190 $this->pushWarning(PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED, 1191 array('path' => $files['path'])); 1192 } 1193 } 1194 $ret[$files['file']] = array('role' => $myrole); 1195 if (isset($installexceptions[$files['path']])) { 1196 $ret[$files['file']]['baseinstalldir'] = 1197 $installexceptions[$files['path']]; 1198 } 1199 if (isset($platformexceptions[$files['path']])) { 1200 $ret[$files['file']]['platform'] = $platformexceptions[$files['path']]; 1201 } 1202 if (isset($installas[$files['path']])) { 1203 $ret[$files['file']]['install-as'] = $installas[$files['path']]; 1204 } 1205 if (isset($replacements[$files['path']])) { 1206 $ret[$files['file']]['replacements'] = $replacements[$files['path']]; 1207 } 1208 if (isset($globalreplacements)) { 1209 if (!isset($ret[$files['file']]['replacements'])) { 1210 $ret[$files['file']]['replacements'] = array(); 1211 } 1212 $ret[$files['file']]['replacements'] = array_merge( 1213 $ret[$files['file']]['replacements'], $globalreplacements); 1214 } 1215 } 1216 } 1217 } 1218 return $ret; 1219 } 1220 1221 /** 1222 * Recursively generate the <filelist> section's <dir> and <file> tags 1223 * @param array|PEAR_Error the sorted directory structure, or an error 1224 * from filelist generation 1225 * @param false|string whether the parent directory has a role this should 1226 * inherit 1227 * @param integer indentation level 1228 * @return array|PEAR_Error 1229 * @access private 1230 */ 1231 function _getDirTag($struc, $role=false, $_curdir = '') 1232 { 1233 if (PEAR::isError($struc)) { 1234 return $struc; 1235 } 1236 extract($this->_options); 1237 $ret = array(); 1238 foreach($struc as $dir => $files) { 1239 if ($dir === '/') { 1240 // global directory role? overrides all exceptions except file exceptions 1241 if (isset($dir_roles['/'])) { 1242 $role = $dir_roles['/']; 1243 } 1244 return $this->_getDirTag($struc[$dir], $role, ''); 1245 } else { 1246 if (!isset($files['file'])) { 1247 $myrole = ''; 1248 if (isset($dir_roles[$_curdir . $dir])) { 1249 $myrole = $dir_roles[$_curdir . $dir]; 1250 } elseif ($role) { 1251 $myrole = $role; 1252 } 1253 $ret = array_merge($ret, $this->_getDirTag($files, $myrole, $_curdir . $dir . '/')); 1254 } else { 1255 $myrole = ''; 1256 if (!$role) 1257 { 1258 $myrole = false; 1259 if (isset($exceptions[$files['path']])) { 1260 $myrole = $exceptions[$files['path']]; 1261 } elseif (isset($roles[$files['ext']])) { 1262 $myrole = $roles[$files['ext']]; 1263 } else { 1264 $myrole = $roles['*']; 1265 } 1266 } else { 1267 $myrole = $role; 1268 if (isset($exceptions[$files['path']])) { 1269 $myrole = $exceptions[$files['path']]; 1270 } 1271 } 1272 if (isset($installexceptions[$files['path']])) { 1273 $bi = $installexceptions[$files['path']]; 1274 } else { 1275 $bi = $this->_options['baseinstalldir']; 1276 } 1277 $test = explode('/', $files['path']); 1278 foreach ($test as $subpath) { 1279 if ($subpath == 'CVS') { 1280 $this->pushWarning(PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED, array('path' => $files['path'])); 1281 } 1282 } 1283 $ret[$files['path']] = 1284 array('role' => $myrole, 1285 'baseinstalldir' => $bi, 1286 ); 1287 if (!isset($this->_options['simpleoutput'])) { 1288 $md5sum = @md5_file($this->_options['packagedirectory'] . $files['path']); 1289 if (!empty($md5sum)) { 1290 $ret[$files['path']]['md5sum'] = $md5sum; 1291 } 1292 } elseif (isset($ret[$files['path']]['md5sum'])) { 1293 unset($ret[$files['path']]['md5sum']); 1294 } 1295 if (isset($platformexceptions[$files['path']])) { 1296 $ret[$files['path']]['platform'] = $platformexceptions[$files['path']]; 1297 } 1298 if (isset($installas[$files['path']])) { 1299 $ret[$files['path']]['install-as'] = $installas[$files['path']]; 1300 } 1301 if (isset($replacements[$files['path']])) { 1302 $ret[$files['path']]['replacements'] = $replacements[$files['path']]; 1303 } 1304 if (isset($globalreplacements)) { 1305 if (!isset($ret[$files['path']]['replacements'])) { 1306 $ret[$files['path']]['replacements'] = array(); 1307 } 1308 $ret[$files['path']]['replacements'] = array_merge( 1309 $ret[$files['path']]['replacements'], $globalreplacements); 1310 } 1311 if ($myrole == 'php' && !$this->_options['simpleoutput']) { 1312 $this->_addProvides($this->_pear, $files['fullpath']); 1313 } 1314 } 1315 } 1316 } 1317 return $ret; 1318 } 1319 1320 /** 1321 * @param array 1322 * @access private 1323 */ 1324 function _traverseFileArray($files, &$ret) { 1325 foreach ($files as $file) { 1326 if (!isset($file['fullpath'])) { 1327 $this->_traverseFileArray($file, $ret); 1328 } else { 1329 $ret[] = $file['fullpath']; 1330 } 1331 } 1332 } 1333 1334 /** 1335 * Retrieve the 'deps' option passed to the constructor 1336 * @access private 1337 * @return array 1338 */ 1339 function _getDependencies() 1340 { 1341 if ($this->_detectDependencies) { 1342 $this->_traverseFileArray($this->_struc, $ret); 1343 $compatinfo = new PHP_CompatInfo(); 1344 $info = $compatinfo->parseArray($ret); 1345 $ret = $this->addDependency('php',$info['version'],'ge','php',false); 1346 if (is_a($ret, 'PEAR_Error')) { 1347 return $ret; 1348 } 1349 foreach ($info['extensions'] as $ext) { 1350 $this->addDependency($ext, '', 'has', 'ext', false); 1351 } 1352 } 1353 if (isset($this->_packageXml['release_deps']) && 1354 is_array($this->_packageXml['release_deps'])) { 1355 return $this->_packageXml['release_deps']; 1356 } else { 1357 return array(); 1358 } 1359 } 1360 1361 /** 1362 * Creates a changelog entry with the current release 1363 * notes and dates, or overwrites a previous creation 1364 * @access private 1365 */ 1366 function _updateChangeLog() 1367 { 1368 $curlog = $oldchangelog = false; 1369 if (!isset($this->_packageXml['changelog'])) { 1370 $changelog = array(); 1371 if (isset($this->_oldPackageXml['release_notes'])) { 1372 $changelog['release_notes'] = $this->_oldPackageXml['release_notes']; 1373 } 1374 if (isset($this->_oldPackageXml['version'])) { 1375 $changelog['version'] = $this->_oldPackageXml['version']; 1376 } 1377 if (isset($this->_oldPackageXml['release_date'])) { 1378 $changelog['release_date'] = $this->_oldPackageXml['release_date']; 1379 } 1380 if (isset($this->_oldPackageXml['release_license'])) { 1381 $changelog['release_license'] = $this->_oldPackageXml['release_license']; 1382 } 1383 if (isset($this->_oldPackageXml['release_state'])) { 1384 $changelog['release_state'] = $this->_oldPackageXml['release_state']; 1385 } 1386 if (count($changelog)) { 1387 $this->_packageXml['changelog'] = array($changelog); 1388 } else { 1389 $this->_packageXml['changelog'] = array(); 1390 } 1391 } else { 1392 if (isset($this->_oldPackageXml['release_notes'])) { 1393 $oldchangelog['release_notes'] = $this->_oldPackageXml['release_notes']; 1394 } 1395 if (isset($this->_oldPackageXml['version'])) { 1396 $oldchangelog['version'] = $this->_oldPackageXml['version']; 1397 } 1398 if (isset($this->_oldPackageXml['release_date'])) { 1399 $oldchangelog['release_date'] = $this->_oldPackageXml['release_date']; 1400 } 1401 if (isset($this->_oldPackageXml['release_license'])) { 1402 $oldchangelog['release_license'] = $this->_oldPackageXml['release_license']; 1403 } 1404 if (isset($this->_oldPackageXml['release_state'])) { 1405 $oldchangelog['release_state'] = $this->_oldPackageXml['release_state']; 1406 } 1407 } 1408 $hasoldversion = false; 1409 foreach($this->_packageXml['changelog'] as $index => $changelog) { 1410 if ($oldchangelog && isset($oldchangelog['version']) 1411 && strnatcasecmp($oldchangelog['version'], $changelog['version']) == 0) { 1412 $hasoldversion = true; 1413 } 1414 if (isset($changelog['version']) && strnatcasecmp($changelog['version'], $this->_options['version']) == 0) { 1415 $curlog = $index; 1416 } 1417 if (isset($this->_packageXml['changelog'][$index]['release_notes'])) { 1418 $this->_packageXml['changelog'][$index]['release_notes'] = trim($changelog['release_notes']); 1419 } 1420 // the parsing of the release notes adds a \n for some reason 1421 } 1422 if (!$hasoldversion && $oldchangelog && count($oldchangelog) 1423 && $oldchangelog['version'] != $this->_options['version']) { 1424 $this->_packageXml['changelog'][] = $oldchangelog; 1425 } 1426 $notes = ($this->_options['changelognotes'] ? 1427 $this->_options['changelognotes'] : $this->_options['notes']); 1428 $changelog = array('version' => $this->_options['version'], 1429 'release_date' => date('Y-m-d'), 1430 'release_license' => $this->_options['license'], 1431 'release_state' => $this->_options['state'], 1432 'release_notes' => $notes, 1433 ); 1434 if ($curlog !== false) { 1435 $this->_packageXml['changelog'][$curlog] = $changelog; 1436 } else { 1437 $this->_packageXml['changelog'][] = $changelog; 1438 } 1439 usort($this->_packageXml['changelog'], array($this, '_changelogsort')); 1440 } 1441 1442 /** 1443 * @static 1444 * @access private 1445 */ 1446 function _changelogsort($a, $b) 1447 { 1448 if ($this->_options['changelogoldtonew']) { 1449 $c = strtotime($a['release_date']); 1450 $d = strtotime($b['release_date']); 1451 $v1 = $a['version']; 1452 $v2 = $b['version']; 1453 } else { 1454 $d = strtotime($a['release_date']); 1455 $c = strtotime($b['release_date']); 1456 $v2 = $a['version']; 1457 $v1 = $b['version']; 1458 } 1459 if ($c - $d > 0) { 1460 return 1; 1461 } elseif ($c - $d < 0) { 1462 return -1; 1463 } 1464 return version_compare($v1, $v2); 1465 } 1466 1467 /** 1468 * @return true|PEAR_Error 1469 * @uses _generateNewPackageXML() if no package.xml is found, it 1470 * calls this to create a new one 1471 * @param string full path to package file 1472 * @param string name of package file 1473 * @throws PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST 1474 * @access private 1475 */ 1476 function _getExistingPackageXML($path, $packagefile = 'package.xml') 1477 { 1478 if (is_string($path) && is_dir($path)) { 1479 $contents = false; 1480 if (file_exists($path . $packagefile)) { 1481 $contents = file_get_contents($path . $packagefile); 1482 } 1483 if (!$contents) { 1484 return $this->_generateNewPackageXML(); 1485 } else { 1486 $PEAR_Common = $this->_options['pearcommonclass']; 1487 if (!class_exists($PEAR_Common)) { 1488 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS); 1489 } 1490 $common = new $PEAR_Common; 1491 if (is_a($common, 'PEAR_Common')) { 1492 $this->_oldPackageXml = 1493 $this->_packageXml = $common->infoFromString($contents); 1494 } else { // new way 1495 require_once 'PEAR/PackageFile.php'; 1496 $z = &PEAR_Config::singleton(); 1497 $pkg = &new PEAR_PackageFile($z); 1498 $pf = &$pkg->fromXmlString($contents, PEAR_VALIDATE_DOWNLOADING, $path . $packagefile); 1499 if (PEAR::isError($pf)) { 1500 return $pf; 1501 } 1502 if ($pf->getPackagexmlVersion() != '1.0') { 1503 return PEAR::raiseError('PEAR_PackageFileManager can only manage ' . 1504 'package.xml version 1.0, use PEAR_PackageFileManager_v2 for newer' . 1505 ' package files'); 1506 } 1507 $this->_oldPackageXml = 1508 $this->_packageXml = $pf->toArray(); 1509 } 1510 if (PEAR::isError($this->_packageXml)) { 1511 return $this->_packageXml; 1512 } 1513 if ($this->_options['cleardependencies']) { 1514 $this->_packageXml['release_deps'] = $this->_options['deps']; 1515 } 1516 if ($this->_options['deps'] !== false) { 1517 $this->_packageXml['release_deps'] = $this->_options['deps']; 1518 } else { 1519 if (isset($this->_packageXml['release_deps'])) { 1520 $this->_options['deps'] = $this->_packageXml['release_deps']; 1521 } 1522 } 1523 if ($this->_options['maintainers'] !== false) { 1524 $this->_packageXml['maintainers'] = $this->_options['maintainers']; 1525 } else { 1526 $this->_options['maintainers'] = $this->_packageXml['maintainers']; 1527 } 1528 unset($this->_packageXml['filelist']); 1529 unset($this->_packageXml['provides']); 1530 } 1531 return true; 1532 } else { 1533 if (!is_string($path)) { 1534 $path = gettype($path); 1535 } 1536 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST, 1537 $path); 1538 } 1539 } 1540 1541 /** 1542 * Create the structure for a new package.xml 1543 * 1544 * @uses $_packageXml emulates reading in a package.xml 1545 * by using the package, summary and description 1546 * options 1547 * @return true|PEAR_Error 1548 * @access private 1549 */ 1550 function _generateNewPackageXML() 1551 { 1552 $this->_oldPackageXml = false; 1553 if (!isset($this->_options['package'])) { 1554 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPACKAGE); 1555 } 1556 if (!isset($this->_options['summary'])) { 1557 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSUMMARY); 1558 } 1559 if (!isset($this->_options['description'])) { 1560 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NODESC); 1561 } 1562 $this->_packageXml = array(); 1563 $this->_packageXml['package'] = $this->_options['package']; 1564 $this->_packageXml['summary'] = $this->_options['summary']; 1565 $this->_packageXml['description'] = $this->_options['description']; 1566 $this->_packageXml['changelog'] = array(); 1567 if ($this->_options['deps'] !== false) { 1568 $this->_packageXml['release_deps'] = $this->_options['deps']; 1569 } else { 1570 $this->_packageXml['release_deps'] = $this->_options['deps'] = array(); 1571 } 1572 if ($this->_options['maintainers'] !== false) { 1573 $this->_packageXml['maintainers'] = $this->_options['maintainers']; 1574 } else { 1575 $this->_packageXml['maintainers'] = $this->_options['maintainers'] = array(); 1576 } 1577 return true; 1578 } 1579 } 1580 1581 if (!function_exists('file_get_contents')) { 1582 /** 1583 * @ignore 1584 */ 1585 function file_get_contents($path, $use_include_path = null, $context = null) 1586 { 1587 $a = @file($path, $use_include_path, $context); 1588 if (is_array($a)) { 1589 return implode('', $a); 1590 } else { 1591 return false; 1592 } 1593 } 1594 } 1595 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |