1 <?php
2 //
3 // +------------------------------------------------------------------------+
4 // | PEAR :: Package File Manager |
5 // +------------------------------------------------------------------------+
6 // | Copyright (c) 2003 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 //
20
21 /**
22 * @package PEAR_PackageFileManager
23 */
24 /**
25 * PEAR installer
26 */
27 require_once 'PEAR/Common.php';
28 /**#@+
29 * Error Codes
30 */
31 define('PEAR_PACKAGEFILEMANAGER_NOSTATE', 1);
32 define('PEAR_PACKAGEFILEMANAGER_NOVERSION', 2);
33 define('PEAR_PACKAGEFILEMANAGER_NOPKGDIR', 3);
34 define('PEAR_PACKAGEFILEMANAGER_NOBASEDIR', 3);
35 define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND', 4);
36 define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE', 5);
37 define('PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE', 6);
38 define('PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE', 7);
39 define('PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE', 8);
40 define('PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE', 9);
41 define('PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST', 10);
42 define('PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES', 11);
43 define('PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST', 12);
44 define('PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS', 13);
45 define('PEAR_PACKAGEFILEMANAGER_NOPACKAGE', 14);
46 define('PEAR_PACKAGEFILEMANAGER_WRONG_MROLE', 15);
47 define('PEAR_PACKAGEFILEMANAGER_NOSUMMARY', 16);
48 define('PEAR_PACKAGEFILEMANAGER_NODESC', 17);
49 define('PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS', 18);
50 /**#@-*/
51 /**
52 * Error messages
53 * @global array $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS']
54 */
55 $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'] =
56 array(
57 'en' =>
58 array(
59 PEAR_PACKAGEFILEMANAGER_NOSTATE =>
60 'Release State (option \'state\') must by specified in PEAR_PackageFileManager setOptions (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_NOPKGDIR =>
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_NOCVSENTRIES =>
84 'Directory "%s" is not a CVS directory (it must have the CVS/Entries file)',
85 PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST =>
86 'Package source base directory "%s" doesn\'t exist or isn\'t a directory',
87 PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS =>
88 'Run $managerclass->setOptions() before any other methods',
89 PEAR_PACKAGEFILEMANAGER_NOPACKAGE =>
90 'Package Name (option \'package\') must by specified in PEAR_PackageFileManager '.
91 'setOptions to create a new package.xml',
92 PEAR_PACKAGEFILEMANAGER_NOSUMMARY =>
93 'Package Summary (option \'summary\') must by specified in PEAR_PackageFileManager' .
94 ' setOptions to create a new package.xml',
95 PEAR_PACKAGEFILEMANAGER_NODESC =>
96 'Detailed Package Description (option \'description\') must be' .
97 ' specified in PEAR_PackageFileManager constructor to create a new package.xml',
98 PEAR_PACKAGEFILEMANAGER_WRONG_MROLE =>
99 'Maintainer role must be one of "%s"',
100 PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS =>
101 'Add maintainers to a package before generating the package.xml',
102 ),
103 // other language translations go here
104 );
105 /**
106 * PEAR :: PackageGenerate updates the <filelist></filelist> section
107 * of a PEAR package.xml file to reflect the current files in
108 * preparation for a release.
109 *
110 * The PEAR_PackageGenerate class uses a plugin system to generate the
111 * list of files in a package. This allows both standard recursive
112 * directory parsing (plugin type file) and more intelligent options
113 * such as the CVS browser {@link PEAR_PackageFileManager_Cvs}, which
114 * grabs all files in a local CVS checkout to create the list, ignoring
115 * any other local files.
116 *
117 * Other options include specifying roles for file extensions (all .php
118 * files are role="php", for example), roles for directories (all directories
119 * named "tests" are given role="tests" by default), and exceptions.
120 * Exceptions are specific pathnames with * and ? wildcards that match
121 * a default role, but should have another. For example, perhaps
122 * a debug.tpl template would normally be data, but should be included
123 * in the docs role. Along these lines, to exclude files entirely,
124 * use the ignore option.
125 *
126 * Required options for a release include version, baseinstalldir, state,
127 * and packagedirectory (the full path to the local location of the
128 * package to create a package.xml file for)
129 *
130 * Example usage:
131 * <code>
132 * <?php
133 * require_once('PEAR/PackageFileManager.php');
134 * $packagexml = new PEAR_PackageFileManager;
135 * $e = $packagexml->setOptions(
136 * array('baseinstalldir' => 'PhpDocumentor',
137 * 'version' => '1.2.1',
138 * 'packagedirectory' => 'C:/Web Pages/chiara/phpdoc2/',
139 * 'state' => 'stable',
140 * 'filelistgenerator' => 'cvs', // generate from cvs, use file for directory
141 * 'notes' => 'We\'ve implemented many new and exciting features',
142 * 'ignore' => array('TODO', 'tests/'), // ignore TODO, all files in tests/
143 * 'installexceptions' => array('phpdoc' => '/*'), // baseinstalldir ="/" for phpdoc
144 * 'dir_roles' => array('tutorials' => 'doc'),
145 * 'exceptions' => array('README' => 'doc', // README would be data, now is doc
146 * 'PHPLICENSE.txt' => 'doc'))); // same for the license
147 * if (PEAR::isError($e)) {
148 * echo $e->getMessage();
149 * die();
150 * }
151 * $packagexml->addRole('pkg', 'doc'); // add a new role mapping
152 * $e = $packagexml->writePackageFile();
153 * if (PEAR::isError($e)) {
154 * echo $e->getMessage();
155 * die();
156 * }
157 * ?>
158 *
159 * In addition, a package.xml file can now be generated from
160 * scratch, with the usage of new options package, summary, description, and
161 * the use of the {@link addMaintainer()} method
162 * </code>
163 * @package PEAR_PackageFileManager
164 */
165 class PEAR_PackageFileManager
166 {
167 /**
168 * Format: array(array(regexp-ready string to search for whole path,
169 * regexp-ready string to search for basename of ignore strings),...)
170 * @var false|array
171 * @access private
172 */
173 var $_ignore = false;
174
175 /**
176 * Contents of the package.xml file
177 * @var string
178 * @access private
179 */
180 var $_packageXml = false;
181
182 /**
183 * @access private
184 * @var PEAR_Common
185 */
186 var $_pear;
187
188 /**
189 * @access private
190 * @var string
191 */
192 var $_options = array(
193 'packagefile' => 'package.xml',
194 'filelistgenerator' => 'file',
195 'license' => 'PHP License',
196 'roles' =>
197 array(
198 'php' => 'php',
199 'html' => 'doc',
200 '*' => 'data',
201 ),
202 'dir_roles' =>
203 array(
204 'docs' => 'doc',
205 'examples' => 'doc',
206 'tests' => 'tests',
207 ),
208 'exceptions' => array(),
209 'installexceptions' => array(),
210 'ignore' => array(),
211 'deps' => array(),
212 'notes' => '',
213 'changelognotes' => false,
214 'outputdirectory' => false,
215 'pathtopackagefile' => false,
216 'lang' => 'en',
217 'configure_options' => array(),
218 );
219
220 function PEAR_PackageFileManager()
221 {
222 }
223
224 /**
225 *
226 * @param array
227 */
228 function setOptions($options = array())
229 {
230 if (!isset($options['state'])) {
231 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSTATE);
232 }
233 if (!isset($options['version'])) {
234 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOVERSION);
235 }
236 if (!isset($options['packagedirectory'])) {
237 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPKGDIR);
238 } else {
239 $options['packagedirectory'] = str_replace(DIRECTORY_SEPARATOR,
240 '/',
241 realpath($options['packagedirectory']));
242 if ($options['packagedirectory']{strlen($options['packagedirectory']) - 1} != '/') {
243 $options['packagedirectory'] .= '/';
244 }
245 }
246 if (!isset($options['baseinstalldir'])) {
247 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOBASEDIR);
248 }
249 $this->_options = array_merge($this->_options, $options);
250
251 $path = ($this->_options['pathtopackagefile'] ?
252 $this->_options['pathtopackagefile'] : $this->_options['packagedirectory']);
253 $this->_options['filelistgenerator'] = ucfirst(strtolower($this->_options['filelistgenerator']));
254 if (PEAR::isError($res = $this->_getExistingPackageXML($path, $this->_options['packagefile']))) {
255 return $res;
256 }
257 // attempt to load the interface from the standard PEAR location
258 @include_once('PEAR/PackageFileManager/' . $this->_options['filelistgenerator'] . '.php');
259 if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) {
260 if (isset($this->_options['usergeneratordir'])) {
261 // attempt to load from a user-specified directory
262 $this->_options['usergeneratordir'] = str_replace(DIRECTORY_SEPARATOR,
263 '/',
264 realpath($this->_options['usergeneratordir']));
265 if ($this->_options['usergeneratordir']{strlen($this->_options['usergeneratordir']) - 1} != '/') {
266 $this->_options['usergeneratordir'] .= '/';
267 }
268 @include_once($this->_options['usergeneratordir'] . $this->_options['filelistgenerator'] . '.php');
269 if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) {
270 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE,
271 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']);
272 }
273 } else {
274 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND,
275 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']);
276 }
277 }
278 }
279
280 /**
281 * Add an extension/role mapping to the role mapping option
282 * @param string file extension
283 * @param string role
284 */
285 function addRole($extension, $role)
286 {
287 $this->_options['roles'][$extension] = $role;
288 }
289
290 /**
291 * Add a maintainer to the list of maintainers.
292 *
293 * Every maintainer must have a valid account at pear.php.net. The
294 * first parameter is the account name (for instance, cellog is the
295 * handle for Greg Beaver at pear.php.net). Every maintainer has
296 * one of four possible roles:
297 * - lead: the primary maintainer
298 * - developer: an important developer on the project
299 * - contributor: self-explanatory
300 * - helper: ditto
301 *
302 * Finally, specify the name and email of the maintainer
303 * @param string username on pear.php.net of maintainer
304 * @param lead|developer|contributor|helperrole of maintainer
305 * @param string full name of maintainer
306 * @param string email address of maintainer
307 */
308 function addMaintainer($handle, $role, $name, $email)
309 {
310 if (!$this->_packageXml) {
311 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
312 }
313 if (!in_array($role, $GLOBALS['_PEAR_Common_maintainer_roles'])) {
314 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_WRONG_MROLE,
315 implode(', ', $GLOBALS['_PEAR_Common_maintainer_roles']));
316 }
317 if (!isset($this->_packageXml['maintainers'])) {
318 $this->_packageXml['maintainers'] = array();
319 }
320 $found = false;
321 foreach($this->_packageXml['maintainers'] as $index => $maintainer) {
322 if ($maintainer['handle'] == $handle) {
323 $found = $index;
324 break;
325 }
326 }
327 $maintainer =
328 array('handle' => $handle, 'role' => $role, 'name' => $name, 'email' => $email);
329 if ($found !== false) {
330 $this->_packageXml['maintainers'][$found] = $maintainer;
331 } else {
332 $this->_packageXml['maintainers'][] = $maintainer;
333 }
334 }
335
336 /**
337 * Add an install-time configuration option for building of source
338 *
339 * This option is only useful to PECL projects that are built upon
340 * installation
341 * @param string name of the option
342 * @param string prompt to display to the user
343 * @param string default value
344 */
345 function addConfigureOption($name, $prompt, $default = null)
346 {
347 if (!$this->_packageXml) {
348 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
349 }
350 if (!isset($this->_packageXml['configure_options'])) {
351 $this->_packageXml['configure_options'] = array();
352 }
353 $found = false;
354 foreach($this->_packageXml['configure_options'] as $index => $option) {
355 if ($option['name'] == $name) {
356 $found = $index;
357 break;
358 }
359 }
360 $option = array('name' => $name, 'prompt' => $prompt);
361 if (isset($default)) {
362 $option['default'] = $default;
363 }
364 if ($found !== false) {
365 $this->_packageXml['configure_options'][$found] = $option;
366 } else {
367 $this->_packageXml['configure_options'][] = $option;
368 }
369 }
370
371 /**
372 * Add a dependency on another package, or an extension/php
373 *
374 * This will overwrite an existing dependency if it is found. In
375 * other words, if a dependency on PHP 4.1.0 exists, and
376 * addDependency('php', '4.3.0', 'ge', 'php') is called, the existing
377 * dependency on PHP 4.1.0 will be overwritten with the new one on PHP 4.3.0
378 * @param string Dependency element name
379 * @param string Dependency version
380 * @param string A specific operator for the version, this can be one of:
381 * 'has', 'not', 'lt', 'le', 'eq', 'ne', 'ge', or 'gt'
382 * @param string Dependency type. This can be one of:
383 * 'pkg', 'ext', 'php', 'prog', 'os', 'sapi', or 'zend'
384 */
385 function addDependency($name, $version = false, $operator = 'ge', $type = 'pkg')
386 {
387 if (!$this->_packageXml) {
388 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
389 }
390 $found = false;
391 foreach($this->_options['deps'] as $index => $dep) {
392 if ($dep['name'] == $name && $deps['type'] == $type) {
393 $found = $index;
394 break;
395 }
396 }
397 $dep =
398 array(
399 'name' => $name,
400 'type' => $type);
401 if ($version) {
402 $dep['version'] = $version;
403 if ($operator) {
404 $dep['rel'] = $operator;
405 }
406 }
407
408 if ($found !== false) {
409 $this->_options['deps'][$found] = $dep; // overwrite existing dependency
410 } else {
411 $this->_options['deps'][] = $dep; // add new dependency
412 }
413 }
414
415 /**
416 * Writes the package.xml file out with the newly created <release></release> tag
417 * @param boolean null if no debugging, true if web interface, false if command-line
418 */
419 function writePackageFile($debuginterface = null)
420 {
421 if (!$this->_packageXml) {
422 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
423 }
424 if (!isset($this->_packageXml['maintainers'])) {
425 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS);
426 }
427 extract($this->_options);
428 $date = date('Y-m-d');
429 $this->_packageXml['release_date'] = $date;
430 $this->_packageXml['version'] = $version;
431 $this->_packageXml['release_state'] = $state;
432 $this->_packageXml['release_notes'] = $notes;
433 $this->_pear = new PEAR_Common;
434 $this->_packageXml['filelist'] = $this->_getFileList();
435 if (PEAR::isError($this->_packageXml['filelist'])) {
436 return $this->_packageXml['filelist'];
437 }
438 if (isset($this->_pear->pkginfo['provides'])) {
439 $this->_packageXml['provides'] = $this->_pear->pkginfo['provides'];
440 }
441 $this->_packageXml['release_deps'] = $this->_getDependencies();
442 $this->_updateChangeLog();
443 $common = &$this->_pear;
444 $packagexml = $common->xmlFromInfo($this->_packageXml);
445 if (isset($debuginterface)) {
446 if ($debuginterface) {
447 echo '<pre>' . htmlentities($packagexml) . '</pre>';
448 } else {
449 echo $packagexml;
450 }
451 return true;
452 }
453 $outputdir = ($this->_options['outputdirectory'] ?
454 $this->_options['outputdirectory'] : $this->_options['packagedirectory']);
455 if (is_writable($this->_options['packagedirectory'] . $this->_options['packagefile'])) {
456 if ($fp = @fopen($outputdir . $this->_options['packagefile'] . '.tmp', "w")) {
457 $written = @fwrite($fp, $packagexml);
458 @fclose($fp);
459 if ($written === false) {
460 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE);
461 }
462 if (!@copy($outputdir . $this->_options['packagefile'] . '.tmp',
463 $outputdir . $this->_options['packagefile'])) {
464 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE);
465 } else {
466 @unlink($outputdir . $this->_options['packagefile'] . '.tmp');
467 return true;
468 }
469 } else {
470 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE,
471 $outputdir . $this->_options['packagefile'] . '.tmp');
472 }
473 } else {
474 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE, $outputdir);
475 }
476 }
477
478 /**
479 * ALWAYS use this to test output before overwriting your package.xml!!
480 * @uses writePackageFile() calls with the debug parameter set based on
481 * whether it is called from the command-line or web interface
482 */
483 function debugPackageFile()
484 {
485 $webinterface = isset($_SERVER['PATH_TRANSLATED']);
486 return $this->writePackageFile($webinterface);
487 }
488
489 /**
490 * Utility function to shorten error generation code
491 * @static
492 */
493 function raiseError($code, $i1 = '', $i2 = '')
494 {
495 return PEAR::raiseError('PEAR_PackageFileManager Error: ' .
496 sprintf($GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code],
497 $i1, $i2));
498 }
499
500 /**
501 * Uses {@link PEAR_Common::analyzeSourceCode()} and {@link PEAR_Common::buildProvidesArray()}
502 * to create the <provides></provides> section of the package.xml
503 * @param PEAR_Common
504 * @param string path to source file
505 * @access private
506 */
507 function _addProvides(&$pear, $file)
508 {
509 $pear->buildProvidesArray($pear->analyzeSourceCode($file));
510 }
511
512 /**
513 * @uses getDirTag() generate the xml from the array
514 * @return string
515 * @access private
516 */
517 function _getFileList()
518 {
519 $generatorclass = 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator'];
520 $generator = new $generatorclass($this, $this->_options);
521 return $this->_getDirTag($generator->getFileList());
522 }
523
524 /**
525 * Recursively generate the <filelist> section's <dir> and <file> tags
526 * @param array the sorted directory structure
527 * @param false|stringwhether the parent directory has a role this should
528 * inherit
529 * @param integer indentation level
530 * @access private
531 */
532 function _getDirTag($struc, $role=false)
533 {
534 if (PEAR::isError($struc)) {
535 return $struc;
536 }
537 extract($this->_options);
538 $ret = array();
539 foreach($struc as $dir => $files) {
540 if ($dir === '/') {
541 return $this->_getDirTag($struc[$dir], $role);
542 } else {
543 if (!isset($files['file'])) {
544 $myrole = '';
545 if ($role) {
546 $myrole = $role;
547 } elseif (isset($dir_roles[$dir])) {
548 $myrole = $dir_roles[$dir];
549 }
550 $ret = array_merge($ret, $this->_getDirTag($files, $myrole));
551 } else {
552 $myrole = '';
553 if (!$role)
554 {
555 $myrole = false;
556 if (isset($exceptions[$files['file']])) {
557 $myrole = $exceptions[$files['file']];
558 } elseif (isset($roles[$files['ext']])) {
559 $myrole = $roles[$files['ext']];
560 } else {
561 $myrole = $roles['*'];
562 }
563 } else {
564 $myrole = $role;
565 }
566 if (isset($installexceptions[$files['file']])) {
567 $bi = $installexceptions[$files['file']];
568 } else {
569 $bi = $baseinstalldir;
570 }
571 $ret[$files['path']] = array('role' => $myrole, 'baseinstalldir' => $bi);
572 if ($myrole == 'php') {
573 $this->_addProvides($this->_pear, $files['fullpath']);
574 }
575 }
576 }
577 }
578 return $ret;
579 }
580
581 /**
582 * Retrieve the 'deps' option passed to the constructor
583 * @access private
584 * @return string
585 */
586 function _getDependencies()
587 {
588 if (isset($this->_options['deps'])) {
589 return $this->_options['deps'];
590 } else {
591 return array();
592 }
593 }
594
595 /**
596 * Creates a changelog entry with the current release
597 * notes and dates, or overwrites a previous creation
598 * @access private
599 */
600 function _updateChangeLog()
601 {
602 $curlog = false;
603 foreach($this->_packageXml['changelog'] as $index => $changelog) {
604 if ($changelog['version'] == $this->_options['version']) {
605 $curlog = $index;
606 }
607 }
608 $notes = ($this->_options['changelognotes'] ?
609 $this->_options['changelognotes'] : $this->_options['notes']);
610 $changelog = array('version' => $this->_options['version'],
611 'release_date' => date('Y-m-d'),
612 'release_license' => $this->_options['license'],
613 'release_state' => $this->_options['state'],
614 'release_notes' => $notes,
615 );
616 if ($curlog !== false) {
617 $this->_packageXml['changelog'][$curlog] = $changelog;
618 } else {
619 $this->_packageXml['changelog'][] = $changelog;
620 }
621 }
622
623 /**
624 * @access private
625 */
626 function _getExistingPackageXML($path, $packagefile = 'package.xml')
627 {
628 if (@is_dir($path)) {
629 $contents = @file_get_contents($path . $packagefile);
630 if (!$contents) {
631 return $this->_generateNewPackageXML();
632 } else {
633 $common = new PEAR_Common;
634 $this->_packageXml = $common->infoFromString($contents);
635 if (PEAR::isError($this->_packageXml)) {
636 return $this->_packageXml;
637 }
638 unset($this->_packageXml['filelist']);
639 }
640 return true;
641 } else {
642 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST,
643 $path);
644 }
645 }
646
647 /**
648 * Create the structure for a new package.xml
649 * @access private
650 */
651 function _generateNewPackageXML()
652 {
653 if (!isset($this->_options['package'])) {
654 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPACKAGE);
655 }
656 if (!isset($this->_options['summary'])) {
657 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSUMMARY);
658 }
659 if (!isset($this->_options['description'])) {
660 return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NODESC);
661 }
662 $this->_packageXml = array();
663 $this->_packageXml['package'] = $this->_options['package'];
664 $this->_packageXml['summary'] = $this->_options['summary'];
665 $this->_packageXml['description'] = $this->_options['description'];
666 $this->_packageXml['changelog'] = array();
667 return true;
668 }
669 }
670
if (!function_exists('file_get_contents')) {
671 function file_get_contents($path, $use_include_path = null, $context = null)
672 {
673 $a = @file($path, $use_include_path, $context);
674 if (is_array($a)) {
675 return implode('', $a);
676 } else {
677 return false;
678 }
679 }
680 }
681 ?>