PageRenderTime 31ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/pear/php/PEAR/PackageFileManager.php

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