Subversion Repositories Applications.gtt

Rev

Rev 94 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
94 jpm 1
<?php
2
/**
3
 * package.xml generation class, package.xml version 1.0
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * LICENSE: This source file is subject to version 3.0 of the PHP license
8
 * that is available through the world-wide-web at the following URI:
9
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
10
 * the PHP License and are unable to obtain it through the web, please
11
 * send a note to license@php.net so we can mail you a copy immediately.
12
 *
13
 * @category   pear
14
 * @package    PEAR
15
 * @author     Greg Beaver <cellog@php.net>
16
 * @copyright  1997-2006 The PHP Group
17
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
18
 * @version    CVS: $Id: v1.php,v 1.72 2006/05/10 02:56:19 cellog Exp $
19
 * @link       http://pear.php.net/package/PEAR
20
 * @since      File available since Release 1.4.0a1
21
 */
22
/**
23
 * needed for PEAR_VALIDATE_* constants
24
 */
25
require_once 'PEAR/Validate.php';
26
require_once 'System.php';
27
require_once 'PEAR/PackageFile/v2.php';
28
/**
29
 * This class converts a PEAR_PackageFile_v1 object into any output format.
30
 *
31
 * Supported output formats include array, XML string, and a PEAR_PackageFile_v2
32
 * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
33
 * @category   pear
34
 * @package    PEAR
35
 * @author     Greg Beaver <cellog@php.net>
36
 * @copyright  1997-2006 The PHP Group
37
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
38
 * @version    Release: 1.5.1
39
 * @link       http://pear.php.net/package/PEAR
40
 * @since      Class available since Release 1.4.0a1
41
 */
42
class PEAR_PackageFile_Generator_v1
43
{
44
    /**
45
     * @var PEAR_PackageFile_v1
46
     */
47
    var $_packagefile;
48
    function PEAR_PackageFile_Generator_v1(&$packagefile)
49
    {
50
        $this->_packagefile = &$packagefile;
51
    }
52
 
53
    function getPackagerVersion()
54
    {
55
        return '1.5.1';
56
    }
57
 
58
    /**
59
     * @param PEAR_Packager
60
     * @param bool if true, a .tgz is written, otherwise a .tar is written
61
     * @param string|null directory in which to save the .tgz
62
     * @return string|PEAR_Error location of package or error object
63
     */
64
    function toTgz(&$packager, $compress = true, $where = null)
65
    {
66
        require_once 'Archive/Tar.php';
67
        if ($where === null) {
68
            if (!($where = System::mktemp(array('-d')))) {
69
                return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
70
            }
71
        } elseif (!@System::mkDir(array('-p', $where))) {
72
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
73
                ' not be created');
74
        }
75
        if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
76
              !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
77
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
78
                ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
79
        }
80
        if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
81
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
82
        }
83
        $pkginfo = $this->_packagefile->getArray();
84
        $ext = $compress ? '.tgz' : '.tar';
85
        $pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
86
        $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
87
        if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
88
              !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
89
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
90
                getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
91
        }
92
        if ($pkgfile = $this->_packagefile->getPackageFile()) {
93
            $pkgdir = dirname(realpath($pkgfile));
94
            $pkgfile = basename($pkgfile);
95
        } else {
96
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
97
                'be created from a real file');
98
        }
99
        // {{{ Create the package file list
100
        $filelist = array();
101
        $i = 0;
102
 
103
        foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
104
            $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
105
            if (!file_exists($file)) {
106
                return PEAR::raiseError("File does not exist: $fname");
107
            } else {
108
                $filelist[$i++] = $file;
109
                if (!isset($atts['md5sum'])) {
110
                    $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
111
                }
112
                $packager->log(2, "Adding file $fname");
113
            }
114
        }
115
        // }}}
116
        $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
117
        if ($packagexml) {
118
            $tar =& new Archive_Tar($dest_package, $compress);
119
            $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
120
            // ----- Creates with the package.xml file
121
            $ok = $tar->createModify(array($packagexml), '', $where);
122
            if (PEAR::isError($ok)) {
123
                return $ok;
124
            } elseif (!$ok) {
125
                return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
126
            }
127
            // ----- Add the content of the package
128
            if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
129
                return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
130
            }
131
            return $dest_package;
132
        }
133
    }
134
 
135
    /**
136
     * @param string|null directory to place the package.xml in, or null for a temporary dir
137
     * @param int one of the PEAR_VALIDATE_* constants
138
     * @param string name of the generated file
139
     * @param bool if true, then no analysis will be performed on role="php" files
140
     * @return string|PEAR_Error path to the created file on success
141
     */
142
    function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
143
                           $nofilechecking = false)
144
    {
145
        if (!$this->_packagefile->validate($state, $nofilechecking)) {
146
            return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
147
                null, null, null, $this->_packagefile->getValidationWarnings());
148
        }
149
        if ($where === null) {
150
            if (!($where = System::mktemp(array('-d')))) {
151
                return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
152
            }
153
        } elseif (!@System::mkDir(array('-p', $where))) {
154
            return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
155
                ' not be created');
156
        }
157
        $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
158
        $np = @fopen($newpkgfile, 'wb');
159
        if (!$np) {
160
            return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
161
               "$name as $newpkgfile");
162
        }
163
        fwrite($np, $this->toXml($state, true));
164
        fclose($np);
165
        return $newpkgfile;
166
    }
167
 
168
    /**
169
     * fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
170
     *
171
     * @param string $string
172
     * @return string
173
     * @access private
174
     */
175
    function _fixXmlEncoding($string)
176
    {
177
        if (version_compare(phpversion(), '5.0.0', 'lt')) {
178
            $string = utf8_encode($string);
179
        }
180
        return strtr($string, array(
181
                                          '&'  => '&amp;',
182
                                          '>'  => '&gt;',
183
                                          '<'  => '&lt;',
184
                                          '"'  => '&quot;',
185
                                          '\'' => '&apos;' ));
186
    }
187
 
188
    /**
189
     * Return an XML document based on the package info (as returned
190
     * by the PEAR_Common::infoFrom* methods).
191
     *
192
     * @return string XML data
193
     */
194
    function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
195
    {
196
        $this->_packagefile->setDate(date('Y-m-d'));
197
        if (!$this->_packagefile->validate($state, $nofilevalidation)) {
198
            return false;
199
        }
200
        $pkginfo = $this->_packagefile->getArray();
201
        static $maint_map = array(
202
            "handle" => "user",
203
            "name" => "name",
204
            "email" => "email",
205
            "role" => "role",
206
            );
207
        $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
208
        $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
209
        $ret .= "<package version=\"1.0\" packagerversion=\"1.5.1\">\n" .
210
" <name>$pkginfo[package]</name>";
211
        if (isset($pkginfo['extends'])) {
212
            $ret .= "\n<extends>$pkginfo[extends]</extends>";
213
        }
214
        $ret .=
215
 "\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
216
" <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
217
" <maintainers>\n";
218
        foreach ($pkginfo['maintainers'] as $maint) {
219
            $ret .= "  <maintainer>\n";
220
            foreach ($maint_map as $idx => $elm) {
221
                $ret .= "   <$elm>";
222
                $ret .= $this->_fixXmlEncoding($maint[$idx]);
223
                $ret .= "</$elm>\n";
224
            }
225
            $ret .= "  </maintainer>\n";
226
        }
227
        $ret .= "  </maintainers>\n";
228
        $ret .= $this->_makeReleaseXml($pkginfo, false, $state);
229
        if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
230
            $ret .= " <changelog>\n";
231
            foreach ($pkginfo['changelog'] as $oldrelease) {
232
                $ret .= $this->_makeReleaseXml($oldrelease, true);
233
            }
234
            $ret .= " </changelog>\n";
235
        }
236
        $ret .= "</package>\n";
237
        return $ret;
238
    }
239
 
240
    // }}}
241
    // {{{ _makeReleaseXml()
242
 
243
    /**
244
     * Generate part of an XML description with release information.
245
     *
246
     * @param array  $pkginfo    array with release information
247
     * @param bool   $changelog  whether the result will be in a changelog element
248
     *
249
     * @return string XML data
250
     *
251
     * @access private
252
     */
253
    function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
254
    {
255
        // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
256
        $indent = $changelog ? "  " : "";
257
        $ret = "$indent <release>\n";
258
        if (!empty($pkginfo['version'])) {
259
            $ret .= "$indent  <version>$pkginfo[version]</version>\n";
260
        }
261
        if (!empty($pkginfo['release_date'])) {
262
            $ret .= "$indent  <date>$pkginfo[release_date]</date>\n";
263
        }
264
        if (!empty($pkginfo['release_license'])) {
265
            $ret .= "$indent  <license>$pkginfo[release_license]</license>\n";
266
        }
267
        if (!empty($pkginfo['release_state'])) {
268
            $ret .= "$indent  <state>$pkginfo[release_state]</state>\n";
269
        }
270
        if (!empty($pkginfo['release_notes'])) {
271
            $ret .= "$indent  <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
272
            ."\n$indent  </notes>\n";
273
        }
274
        if (!empty($pkginfo['release_warnings'])) {
275
            $ret .= "$indent  <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
276
        }
277
        if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
278
            $ret .= "$indent  <deps>\n";
279
            foreach ($pkginfo['release_deps'] as $dep) {
280
                $ret .= "$indent   <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
281
                if (isset($dep['version'])) {
282
                    $ret .= " version=\"$dep[version]\"";
283
                }
284
                if (isset($dep['optional'])) {
285
                    $ret .= " optional=\"$dep[optional]\"";
286
                }
287
                if (isset($dep['name'])) {
288
                    $ret .= ">$dep[name]</dep>\n";
289
                } else {
290
                    $ret .= "/>\n";
291
                }
292
            }
293
            $ret .= "$indent  </deps>\n";
294
        }
295
        if (isset($pkginfo['configure_options'])) {
296
            $ret .= "$indent  <configureoptions>\n";
297
            foreach ($pkginfo['configure_options'] as $c) {
298
                $ret .= "$indent   <configureoption name=\"".
299
                    $this->_fixXmlEncoding($c['name']) . "\"";
300
                if (isset($c['default'])) {
301
                    $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
302
                }
303
                $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
304
                $ret .= "/>\n";
305
            }
306
            $ret .= "$indent  </configureoptions>\n";
307
        }
308
        if (isset($pkginfo['provides'])) {
309
            foreach ($pkginfo['provides'] as $key => $what) {
310
                $ret .= "$indent  <provides type=\"$what[type]\" ";
311
                $ret .= "name=\"$what[name]\" ";
312
                if (isset($what['extends'])) {
313
                    $ret .= "extends=\"$what[extends]\" ";
314
                }
315
                $ret .= "/>\n";
316
            }
317
        }
318
        if (isset($pkginfo['filelist'])) {
319
            $ret .= "$indent  <filelist>\n";
320
            if ($state ^ PEAR_VALIDATE_PACKAGING) {
321
                $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
322
            } else {
323
                foreach ($pkginfo['filelist'] as $file => $fa) {
324
                    if (!isset($fa['role'])) {
325
                        $fa['role'] = '';
326
                    }
327
                    $ret .= "$indent   <file role=\"$fa[role]\"";
328
                    if (isset($fa['baseinstalldir'])) {
329
                        $ret .= ' baseinstalldir="' .
330
                            $this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
331
                    }
332
                    if (isset($fa['md5sum'])) {
333
                        $ret .= " md5sum=\"$fa[md5sum]\"";
334
                    }
335
                    if (isset($fa['platform'])) {
336
                        $ret .= " platform=\"$fa[platform]\"";
337
                    }
338
                    if (!empty($fa['install-as'])) {
339
                        $ret .= ' install-as="' .
340
                            $this->_fixXmlEncoding($fa['install-as']) . '"';
341
                    }
342
                    $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
343
                    if (empty($fa['replacements'])) {
344
                        $ret .= "/>\n";
345
                    } else {
346
                        $ret .= ">\n";
347
                        foreach ($fa['replacements'] as $r) {
348
                            $ret .= "$indent    <replace";
349
                            foreach ($r as $k => $v) {
350
                                $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
351
                            }
352
                            $ret .= "/>\n";
353
                        }
354
                        $ret .= "$indent   </file>\n";
355
                    }
356
                }
357
            }
358
            $ret .= "$indent  </filelist>\n";
359
        }
360
        $ret .= "$indent </release>\n";
361
        return $ret;
362
    }
363
 
364
    /**
365
     * @param array
366
     * @access protected
367
     */
368
    function recursiveXmlFilelist($list)
369
    {
370
        $this->_dirs = array();
371
        foreach ($list as $file => $attributes) {
372
            $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
373
        }
374
        return $this->_formatDir($this->_dirs);
375
    }
376
 
377
    /**
378
     * @param array
379
     * @param array
380
     * @param string|null
381
     * @param array|null
382
     * @access private
383
     */
384
    function _addDir(&$dirs, $dir, $file = null, $attributes = null)
385
    {
386
        if ($dir == array() || $dir == array('.')) {
387
            $dirs['files'][basename($file)] = $attributes;
388
            return;
389
        }
390
        $curdir = array_shift($dir);
391
        if (!isset($dirs['dirs'][$curdir])) {
392
            $dirs['dirs'][$curdir] = array();
393
        }
394
        $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
395
    }
396
 
397
    /**
398
     * @param array
399
     * @param string
400
     * @param string
401
     * @access private
402
     */
403
    function _formatDir($dirs, $indent = '', $curdir = '')
404
    {
405
        $ret = '';
406
        if (!count($dirs)) {
407
            return '';
408
        }
409
        if (isset($dirs['dirs'])) {
410
            uksort($dirs['dirs'], 'strnatcasecmp');
411
            foreach ($dirs['dirs'] as $dir => $contents) {
412
                $usedir = "$curdir/$dir";
413
                $ret .= "$indent   <dir name=\"$dir\">\n";
414
                $ret .= $this->_formatDir($contents, "$indent ", $usedir);
415
                $ret .= "$indent   </dir> <!-- $usedir -->\n";
416
            }
417
        }
418
        if (isset($dirs['files'])) {
419
            uksort($dirs['files'], 'strnatcasecmp');
420
            foreach ($dirs['files'] as $file => $attribs) {
421
                $ret .= $this->_formatFile($file, $attribs, $indent);
422
            }
423
        }
424
        return $ret;
425
    }
426
 
427
    /**
428
     * @param string
429
     * @param array
430
     * @param string
431
     * @access private
432
     */
433
    function _formatFile($file, $attributes, $indent)
434
    {
435
        $ret = "$indent   <file role=\"$attributes[role]\"";
436
        if (isset($attributes['baseinstalldir'])) {
437
            $ret .= ' baseinstalldir="' .
438
                $this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
439
        }
440
        if (isset($attributes['md5sum'])) {
441
            $ret .= " md5sum=\"$attributes[md5sum]\"";
442
        }
443
        if (isset($attributes['platform'])) {
444
            $ret .= " platform=\"$attributes[platform]\"";
445
        }
446
        if (!empty($attributes['install-as'])) {
447
            $ret .= ' install-as="' .
448
                $this->_fixXmlEncoding($attributes['install-as']) . '"';
449
        }
450
        $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
451
        if (empty($attributes['replacements'])) {
452
            $ret .= "/>\n";
453
        } else {
454
            $ret .= ">\n";
455
            foreach ($attributes['replacements'] as $r) {
456
                $ret .= "$indent    <replace";
457
                foreach ($r as $k => $v) {
458
                    $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
459
                }
460
                $ret .= "/>\n";
461
            }
462
            $ret .= "$indent   </file>\n";
463
        }
464
        return $ret;
465
    }
466
 
467
    // {{{ _unIndent()
468
 
469
    /**
470
     * Unindent given string (?)
471
     *
472
     * @param string $str The string that has to be unindented.
473
     * @return string
474
     * @access private
475
     */
476
    function _unIndent($str)
477
    {
478
        // remove leading newlines
479
        $str = preg_replace('/^[\r\n]+/', '', $str);
480
        // find whitespace at the beginning of the first line
481
        $indent_len = strspn($str, " \t");
482
        $indent = substr($str, 0, $indent_len);
483
        $data = '';
484
        // remove the same amount of whitespace from following lines
485
        foreach (explode("\n", $str) as $line) {
486
            if (substr($line, 0, $indent_len) == $indent) {
487
                $data .= substr($line, $indent_len) . "\n";
488
            }
489
        }
490
        return $data;
491
    }
492
 
493
    /**
494
     * @return array
495
     */
496
    function dependenciesToV2()
497
    {
498
        $arr = array();
499
        $this->_convertDependencies2_0($arr);
500
        return $arr['dependencies'];
501
    }
502
 
503
    /**
504
     * Convert a package.xml version 1.0 into version 2.0
505
     *
506
     * Note that this does a basic conversion, to allow more advanced
507
     * features like bundles and multiple releases
508
     * @param string the classname to instantiate and return.  This must be
509
     *               PEAR_PackageFile_v2 or a descendant
510
     * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
511
     *                strictest parameters will be converted
512
     * @return PEAR_PackageFile_v2|PEAR_Error
513
     */
514
    function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
515
    {
516
        if ($strict) {
517
            if (!$this->_packagefile->validate()) {
518
                $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
519
                    ' to version 2.0', null, null, null,
520
                    $this->_packagefile->getValidationWarnings(true));
521
                return $a;
522
            }
523
        }
524
        $arr = array(
525
            'attribs' => array(
526
                             'version' => '2.0',
527
                             'xmlns' => 'http://pear.php.net/dtd/package-2.0',
528
                             'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
529
                             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
530
                             'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
531
"http://pear.php.net/dtd/tasks-1.0.xsd\n" .
532
"http://pear.php.net/dtd/package-2.0\n" .
533
'http://pear.php.net/dtd/package-2.0.xsd',
534
                         ),
535
            'name' => $this->_packagefile->getPackage(),
536
            'channel' => 'pear.php.net',
537
        );
538
        $arr['summary'] = $this->_packagefile->getSummary();
539
        $arr['description'] = $this->_packagefile->getDescription();
540
        $maintainers = $this->_packagefile->getMaintainers();
541
        foreach ($maintainers as $maintainer) {
542
            if ($maintainer['role'] != 'lead') {
543
                continue;
544
            }
545
            $new = array(
546
                'name' => $maintainer['name'],
547
                'user' => $maintainer['handle'],
548
                'email' => $maintainer['email'],
549
                'active' => 'yes',
550
            );
551
            $arr['lead'][] = $new;
552
        }
553
        if (!isset($arr['lead'])) { // some people... you know?
554
            $arr['lead'] = array(
555
                'name' => 'unknown',
556
                'user' => 'unknown',
557
                'email' => 'noleadmaintainer@example.com',
558
                'active' => 'no',
559
            );
560
        }
561
        if (count($arr['lead']) == 1) {
562
            $arr['lead'] = $arr['lead'][0];
563
        }
564
        foreach ($maintainers as $maintainer) {
565
            if ($maintainer['role'] == 'lead') {
566
                continue;
567
            }
568
            $new = array(
569
                'name' => $maintainer['name'],
570
                'user' => $maintainer['handle'],
571
                'email' => $maintainer['email'],
572
                'active' => 'yes',
573
            );
574
            $arr[$maintainer['role']][] = $new;
575
        }
576
        if (isset($arr['developer']) && count($arr['developer']) == 1) {
577
            $arr['developer'] = $arr['developer'][0];
578
        }
579
        if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
580
            $arr['contributor'] = $arr['contributor'][0];
581
        }
582
        if (isset($arr['helper']) && count($arr['helper']) == 1) {
583
            $arr['helper'] = $arr['helper'][0];
584
        }
585
        $arr['date'] = $this->_packagefile->getDate();
586
        $arr['version'] =
587
            array(
588
                'release' => $this->_packagefile->getVersion(),
589
                'api' => $this->_packagefile->getVersion(),
590
            );
591
        $arr['stability'] =
592
            array(
593
                'release' => $this->_packagefile->getState(),
594
                'api' => $this->_packagefile->getState(),
595
            );
596
        $licensemap =
597
            array(
598
                'php' => 'http://www.php.net/license',
599
                'php license' => 'http://www.php.net/license',
600
                'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
601
                'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
602
                'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
603
                'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
604
                'mit' => 'http://www.opensource.org/licenses/mit-license.php',
605
                'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
606
                'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
607
            );
608
        if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
609
            $arr['license'] = array(
610
                'attribs' => array('uri' =>
611
                    $licensemap[strtolower($this->_packagefile->getLicense())]),
612
                '_content' => $this->_packagefile->getLicense()
613
                );
614
        } else {
615
            // don't use bogus uri
616
            $arr['license'] = $this->_packagefile->getLicense();
617
        }
618
        $arr['notes'] = $this->_packagefile->getNotes();
619
        $temp = array();
620
        $arr['contents'] = $this->_convertFilelist2_0($temp);
621
        $this->_convertDependencies2_0($arr);
622
        $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
623
            'extsrcrelease' : 'phprelease';
624
        if ($release == 'extsrcrelease') {
625
            $arr['channel'] = 'pecl.php.net';
626
            $arr['providesextension'] = $arr['name']; // assumption
627
        }
628
        $arr[$release] = array();
629
        if ($this->_packagefile->getConfigureOptions()) {
630
            $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
631
            foreach ($arr[$release]['configureoption'] as $i => $opt) {
632
                $arr[$release]['configureoption'][$i] = array('attribs' => $opt);
633
            }
634
            if (count($arr[$release]['configureoption']) == 1) {
635
                $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
636
            }
637
        }
638
        $this->_convertRelease2_0($arr[$release], $temp);
639
        if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
640
            // multiple extsrcrelease tags added in PEAR 1.4.1
641
            $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
642
        }
643
        if ($cl = $this->_packagefile->getChangelog()) {
644
            foreach ($cl as $release) {
645
                $rel = array();
646
                $rel['version'] =
647
                    array(
648
                        'release' => $release['version'],
649
                        'api' => $release['version'],
650
                    );
651
                if (!isset($release['release_state'])) {
652
                    $release['release_state'] = 'stable';
653
                }
654
                $rel['stability'] =
655
                    array(
656
                        'release' => $release['release_state'],
657
                        'api' => $release['release_state'],
658
                    );
659
                if (isset($release['release_date'])) {
660
                    $rel['date'] = $release['release_date'];
661
                } else {
662
                    $rel['date'] = date('Y-m-d');
663
                }
664
                if (isset($release['release_license'])) {
665
                    if (isset($licensemap[strtolower($release['release_license'])])) {
666
                        $uri = $licensemap[strtolower($release['release_license'])];
667
                    } else {
668
                        $uri = 'http://www.example.com';
669
                    }
670
                    $rel['license'] = array(
671
                            'attribs' => array('uri' => $uri),
672
                            '_content' => $release['release_license']
673
                        );
674
                } else {
675
                    $rel['license'] = $arr['license'];
676
                }
677
                if (!isset($release['release_notes'])) {
678
                    $release['release_notes'] = 'no release notes';
679
                }
680
                $rel['notes'] = $release['release_notes'];
681
                $arr['changelog']['release'][] = $rel;
682
            }
683
        }
684
        $ret = new $class;
685
        $ret->setConfig($this->_packagefile->_config);
686
        if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
687
            $ret->setLogger($this->_packagefile->_logger);
688
        }
689
        $ret->fromArray($arr);
690
        return $ret;
691
    }
692
 
693
    /**
694
     * @param array
695
     * @param bool
696
     * @access private
697
     */
698
    function _convertDependencies2_0(&$release, $internal = false)
699
    {
700
        $peardep = array('pearinstaller' =>
701
            array('min' => '1.4.0b1')); // this is a lot safer
702
        $required = $optional = array();
703
        $release['dependencies'] = array();
704
        if ($this->_packagefile->hasDeps()) {
705
            foreach ($this->_packagefile->getDeps() as $dep) {
706
                if (!isset($dep['optional']) || $dep['optional'] == 'no') {
707
                    $required[] = $dep;
708
                } else {
709
                    $optional[] = $dep;
710
                }
711
            }
712
            foreach (array('required', 'optional') as $arr) {
713
                $deps = array();
714
                foreach ($$arr as $dep) {
715
                    // organize deps by dependency type and name
716
                    if (!isset($deps[$dep['type']])) {
717
                        $deps[$dep['type']] = array();
718
                    }
719
                    if (isset($dep['name'])) {
720
                        $deps[$dep['type']][$dep['name']][] = $dep;
721
                    } else {
722
                        $deps[$dep['type']][] = $dep;
723
                    }
724
                }
725
                do {
726
                    if (isset($deps['php'])) {
727
                        $php = array();
728
                        if (count($deps['php']) > 1) {
729
                            $php = $this->_processPhpDeps($deps['php']);
730
                        } else {
731
                            if (!isset($deps['php'][0])) {
732
                                list($key, $blah) = each ($deps['php']); // stupid buggy versions
733
                                $deps['php'] = array($blah[0]);
734
                            }
735
                            $php = $this->_processDep($deps['php'][0]);
736
                            if (!$php) {
737
                                break; // poor mans throw
738
                            }
739
                        }
740
                        $release['dependencies'][$arr]['php'] = $php;
741
                    }
742
                } while (false);
743
                do {
744
                    if (isset($deps['pkg'])) {
745
                        $pkg = array();
746
                        $pkg = $this->_processMultipleDepsName($deps['pkg']);
747
                        if (!$pkg) {
748
                            break; // poor mans throw
749
                        }
750
                        $release['dependencies'][$arr]['package'] = $pkg;
751
                    }
752
                } while (false);
753
                do {
754
                    if (isset($deps['ext'])) {
755
                        $pkg = array();
756
                        $pkg = $this->_processMultipleDepsName($deps['ext']);
757
                        $release['dependencies'][$arr]['extension'] = $pkg;
758
                    }
759
                } while (false);
760
                // skip sapi - it's not supported so nobody will have used it
761
                // skip os - it's not supported in 1.0
762
            }
763
        }
764
        if (isset($release['dependencies']['required'])) {
765
            $release['dependencies']['required'] =
766
                array_merge($peardep, $release['dependencies']['required']);
767
        } else {
768
            $release['dependencies']['required'] = $peardep;
769
        }
770
        if (!isset($release['dependencies']['required']['php'])) {
771
            $release['dependencies']['required']['php'] =
772
                array('min' => '4.0.0');
773
        }
774
        $order = array();
775
        $bewm = $release['dependencies']['required'];
776
        $order['php'] = $bewm['php'];
777
        $order['pearinstaller'] = $bewm['pearinstaller'];
778
        isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
779
        isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
780
        $release['dependencies']['required'] = $order;
781
    }
782
 
783
    /**
784
     * @param array
785
     * @access private
786
     */
787
    function _convertFilelist2_0(&$package)
788
    {
789
        $ret = array('dir' =>
790
                    array(
791
                        'attribs' => array('name' => '/'),
792
                        'file' => array()
793
                        )
794
                    );
795
        $package['platform'] =
796
        $package['install-as'] = array();
797
        $this->_isExtension = false;
798
        foreach ($this->_packagefile->getFilelist() as $name => $file) {
799
            $file['name'] = $name;
800
            if (isset($file['role']) && $file['role'] == 'src') {
801
                $this->_isExtension = true;
802
            }
803
            if (isset($file['replacements'])) {
804
                $repl = $file['replacements'];
805
                unset($file['replacements']);
806
            } else {
807
                unset($repl);
808
            }
809
            if (isset($file['install-as'])) {
810
                $package['install-as'][$name] = $file['install-as'];
811
                unset($file['install-as']);
812
            }
813
            if (isset($file['platform'])) {
814
                $package['platform'][$name] = $file['platform'];
815
                unset($file['platform']);
816
            }
817
            $file = array('attribs' => $file);
818
            if (isset($repl)) {
819
                foreach ($repl as $replace ) {
820
                    $file['tasks:replace'][] = array('attribs' => $replace);
821
                }
822
                if (count($repl) == 1) {
823
                    $file['tasks:replace'] = $file['tasks:replace'][0];
824
                }
825
            }
826
            $ret['dir']['file'][] = $file;
827
        }
828
        return $ret;
829
    }
830
 
831
    /**
832
     * Post-process special files with install-as/platform attributes and
833
     * make the release tag.
834
     *
835
     * This complex method follows this work-flow to create the release tags:
836
     *
837
     * <pre>
838
     * - if any install-as/platform exist, create a generic release and fill it with
839
     *   o <install as=..> tags for <file name=... install-as=...>
840
     *   o <install as=..> tags for <file name=... platform=!... install-as=..>
841
     *   o <ignore> tags for <file name=... platform=...>
842
     *   o <ignore> tags for <file name=... platform=... install-as=..>
843
     * - create a release for each platform encountered and fill with
844
     *   o <install as..> tags for <file name=... install-as=...>
845
     *   o <install as..> tags for <file name=... platform=this platform install-as=..>
846
     *   o <install as..> tags for <file name=... platform=!other platform install-as=..>
847
     *   o <ignore> tags for <file name=... platform=!this platform>
848
     *   o <ignore> tags for <file name=... platform=other platform>
849
     *   o <ignore> tags for <file name=... platform=other platform install-as=..>
850
     *   o <ignore> tags for <file name=... platform=!this platform install-as=..>
851
     * </pre>
852
     *
853
     * It does this by accessing the $package parameter, which contains an array with
854
     * indices:
855
     *
856
     *  - platform: mapping of file => OS the file should be installed on
857
     *  - install-as: mapping of file => installed name
858
     *  - osmap: mapping of OS => list of files that should be installed
859
     *    on that OS
860
     *  - notosmap: mapping of OS => list of files that should not be
861
     *    installed on that OS
862
     *
863
     * @param array
864
     * @param array
865
     * @access private
866
     */
867
    function _convertRelease2_0(&$release, $package)
868
    {
869
        //- if any install-as/platform exist, create a generic release and fill it with
870
        if (count($package['platform']) || count($package['install-as'])) {
871
            $generic = array();
872
            $genericIgnore = array();
873
            foreach ($package['install-as'] as $file => $as) {
874
                //o <install as=..> tags for <file name=... install-as=...>
875
                if (!isset($package['platform'][$file])) {
876
                    $generic[] = $file;
877
                    continue;
878
                }
879
                //o <install as=..> tags for <file name=... platform=!... install-as=..>
880
                if (isset($package['platform'][$file]) &&
881
                      $package['platform'][$file]{0} == '!') {
882
                    $generic[] = $file;
883
                    continue;
884
                }
885
                //o <ignore> tags for <file name=... platform=... install-as=..>
886
                if (isset($package['platform'][$file]) &&
887
                      $package['platform'][$file]{0} != '!') {
888
                    $genericIgnore[] = $file;
889
                    continue;
890
                }
891
            }
892
            foreach ($package['platform'] as $file => $platform) {
893
                if (isset($package['install-as'][$file])) {
894
                    continue;
895
                }
896
                if ($platform{0} != '!') {
897
                    //o <ignore> tags for <file name=... platform=...>
898
                    $genericIgnore[] = $file;
899
                }
900
            }
901
            if (count($package['platform'])) {
902
                $oses = $notplatform = $platform = array();
903
                foreach ($package['platform'] as $file => $os) {
904
                    // get a list of oses
905
                    if ($os{0} == '!') {
906
                        if (isset($oses[substr($os, 1)])) {
907
                            continue;
908
                        }
909
                        $oses[substr($os, 1)] = count($oses);
910
                    } else {
911
                        if (isset($oses[$os])) {
912
                            continue;
913
                        }
914
                        $oses[$os] = count($oses);
915
                    }
916
                }
917
                //- create a release for each platform encountered and fill with
918
                foreach ($oses as $os => $releaseNum) {
919
                    $release[$releaseNum]['installconditions']['os']['name'] = $os;
920
                    $release[$releaseNum]['filelist'] = array('install' => array(),
921
                        'ignore' => array());
922
                    foreach ($package['install-as'] as $file => $as) {
923
                        //o <install as=..> tags for <file name=... install-as=...>
924
                        if (!isset($package['platform'][$file])) {
925
                            $release[$releaseNum]['filelist']['install'][] =
926
                                array(
927
                                    'attribs' => array(
928
                                        'name' => $file,
929
                                        'as' => $as,
930
                                    ),
931
                                );
932
                            continue;
933
                        }
934
                        //o <install as..> tags for
935
                        //  <file name=... platform=this platform install-as=..>
936
                        if (isset($package['platform'][$file]) &&
937
                              $package['platform'][$file] == $os) {
938
                            $release[$releaseNum]['filelist']['install'][] =
939
                                array(
940
                                    'attribs' => array(
941
                                        'name' => $file,
942
                                        'as' => $as,
943
                                    ),
944
                                );
945
                            continue;
946
                        }
947
                        //o <install as..> tags for
948
                        //  <file name=... platform=!other platform install-as=..>
949
                        if (isset($package['platform'][$file]) &&
950
                              $package['platform'][$file] != "!$os" &&
951
                              $package['platform'][$file]{0} == '!') {
952
                            $release[$releaseNum]['filelist']['install'][] =
953
                                array(
954
                                    'attribs' => array(
955
                                        'name' => $file,
956
                                        'as' => $as,
957
                                    ),
958
                                );
959
                            continue;
960
                        }
961
                        //o <ignore> tags for
962
                        //  <file name=... platform=!this platform install-as=..>
963
                        if (isset($package['platform'][$file]) &&
964
                              $package['platform'][$file] == "!$os") {
965
                            $release[$releaseNum]['filelist']['ignore'][] =
966
                                array(
967
                                    'attribs' => array(
968
                                        'name' => $file,
969
                                    ),
970
                                );
971
                            continue;
972
                        }
973
                        //o <ignore> tags for
974
                        //  <file name=... platform=other platform install-as=..>
975
                        if (isset($package['platform'][$file]) &&
976
                              $package['platform'][$file]{0} != '!' &&
977
                              $package['platform'][$file] != $os) {
978
                            $release[$releaseNum]['filelist']['ignore'][] =
979
                                array(
980
                                    'attribs' => array(
981
                                        'name' => $file,
982
                                    ),
983
                                );
984
                            continue;
985
                        }
986
                    }
987
                    foreach ($package['platform'] as $file => $platform) {
988
                        if (isset($package['install-as'][$file])) {
989
                            continue;
990
                        }
991
                        //o <ignore> tags for <file name=... platform=!this platform>
992
                        if ($platform == "!$os") {
993
                            $release[$releaseNum]['filelist']['ignore'][] =
994
                                array(
995
                                    'attribs' => array(
996
                                        'name' => $file,
997
                                    ),
998
                                );
999
                            continue;
1000
                        }
1001
                        //o <ignore> tags for <file name=... platform=other platform>
1002
                        if ($platform{0} != '!' && $platform != $os) {
1003
                            $release[$releaseNum]['filelist']['ignore'][] =
1004
                                array(
1005
                                    'attribs' => array(
1006
                                        'name' => $file,
1007
                                    ),
1008
                                );
1009
                        }
1010
                    }
1011
                    if (!count($release[$releaseNum]['filelist']['install'])) {
1012
                        unset($release[$releaseNum]['filelist']['install']);
1013
                    }
1014
                    if (!count($release[$releaseNum]['filelist']['ignore'])) {
1015
                        unset($release[$releaseNum]['filelist']['ignore']);
1016
                    }
1017
                }
1018
                if (count($generic) || count($genericIgnore)) {
1019
                    $release[count($oses)] = array();
1020
                    if (count($generic)) {
1021
                        foreach ($generic as $file) {
1022
                            if (isset($package['install-as'][$file])) {
1023
                                $installas = $package['install-as'][$file];
1024
                            } else {
1025
                                $installas = $file;
1026
                            }
1027
                            $release[count($oses)]['filelist']['install'][] =
1028
                                array(
1029
                                    'attribs' => array(
1030
                                        'name' => $file,
1031
                                        'as' => $installas,
1032
                                    )
1033
                                );
1034
                        }
1035
                    }
1036
                    if (count($genericIgnore)) {
1037
                        foreach ($genericIgnore as $file) {
1038
                            $release[count($oses)]['filelist']['ignore'][] =
1039
                                array(
1040
                                    'attribs' => array(
1041
                                        'name' => $file,
1042
                                    )
1043
                                );
1044
                        }
1045
                    }
1046
                }
1047
                // cleanup
1048
                foreach ($release as $i => $rel) {
1049
                    if (isset($rel['filelist']['install']) &&
1050
                          count($rel['filelist']['install']) == 1) {
1051
                        $release[$i]['filelist']['install'] =
1052
                            $release[$i]['filelist']['install'][0];
1053
                    }
1054
                    if (isset($rel['filelist']['ignore']) &&
1055
                          count($rel['filelist']['ignore']) == 1) {
1056
                        $release[$i]['filelist']['ignore'] =
1057
                            $release[$i]['filelist']['ignore'][0];
1058
                    }
1059
                }
1060
                if (count($release) == 1) {
1061
                    $release = $release[0];
1062
                }
1063
            } else {
1064
                // no platform atts, but some install-as atts
1065
                foreach ($package['install-as'] as $file => $value) {
1066
                    $release['filelist']['install'][] =
1067
                        array(
1068
                            'attribs' => array(
1069
                                'name' => $file,
1070
                                'as' => $value
1071
                            )
1072
                        );
1073
                }
1074
                if (count($release['filelist']['install']) == 1) {
1075
                    $release['filelist']['install'] = $release['filelist']['install'][0];
1076
                }
1077
            }
1078
        }
1079
    }
1080
 
1081
    /**
1082
     * @param array
1083
     * @return array
1084
     * @access private
1085
     */
1086
    function _processDep($dep)
1087
    {
1088
        if ($dep['type'] == 'php') {
1089
            if ($dep['rel'] == 'has') {
1090
                // come on - everyone has php!
1091
                return false;
1092
            }
1093
        }
1094
        $php = array();
1095
        if ($dep['type'] != 'php') {
1096
            $php['name'] = $dep['name'];
1097
            if ($dep['type'] == 'pkg') {
1098
                $php['channel'] = 'pear.php.net';
1099
            }
1100
        }
1101
        switch ($dep['rel']) {
1102
            case 'gt' :
1103
                $php['min'] = $dep['version'];
1104
                $php['exclude'] = $dep['version'];
1105
            break;
1106
            case 'ge' :
1107
                if (!isset($dep['version'])) {
1108
                    if ($dep['type'] == 'php') {
1109
                        if (isset($dep['name'])) {
1110
                            $dep['version'] = $dep['name'];
1111
                        }
1112
                    }
1113
                }
1114
                $php['min'] = $dep['version'];
1115
            break;
1116
            case 'lt' :
1117
                $php['max'] = $dep['version'];
1118
                $php['exclude'] = $dep['version'];
1119
            break;
1120
            case 'le' :
1121
                $php['max'] = $dep['version'];
1122
            break;
1123
            case 'eq' :
1124
                $php['min'] = $dep['version'];
1125
                $php['max'] = $dep['version'];
1126
            break;
1127
            case 'ne' :
1128
                $php['exclude'] = $dep['version'];
1129
            break;
1130
            case 'not' :
1131
                $php['conflicts'] = 'yes';
1132
            break;
1133
        }
1134
        return $php;
1135
    }
1136
 
1137
    /**
1138
     * @param array
1139
     * @return array
1140
     */
1141
    function _processPhpDeps($deps)
1142
    {
1143
        $test = array();
1144
        foreach ($deps as $dep) {
1145
            $test[] = $this->_processDep($dep);
1146
        }
1147
        $min = array();
1148
        $max = array();
1149
        foreach ($test as $dep) {
1150
            if (!$dep) {
1151
                continue;
1152
            }
1153
            if (isset($dep['min'])) {
1154
                $min[$dep['min']] = count($min);
1155
            }
1156
            if (isset($dep['max'])) {
1157
                $max[$dep['max']] = count($max);
1158
            }
1159
        }
1160
        if (count($min) > 0) {
1161
            uksort($min, 'version_compare');
1162
        }
1163
        if (count($max) > 0) {
1164
            uksort($max, 'version_compare');
1165
        }
1166
        if (count($min)) {
1167
            // get the highest minimum
1168
            $min = array_pop($a = array_flip($min));
1169
        } else {
1170
            $min = false;
1171
        }
1172
        if (count($max)) {
1173
            // get the lowest maximum
1174
            $max = array_shift($a = array_flip($max));
1175
        } else {
1176
            $max = false;
1177
        }
1178
        if ($min) {
1179
            $php['min'] = $min;
1180
        }
1181
        if ($max) {
1182
            $php['max'] = $max;
1183
        }
1184
        $exclude = array();
1185
        foreach ($test as $dep) {
1186
            if (!isset($dep['exclude'])) {
1187
                continue;
1188
            }
1189
            $exclude[] = $dep['exclude'];
1190
        }
1191
        if (count($exclude)) {
1192
            $php['exclude'] = $exclude;
1193
        }
1194
        return $php;
1195
    }
1196
 
1197
    /**
1198
     * process multiple dependencies that have a name, like package deps
1199
     * @param array
1200
     * @return array
1201
     * @access private
1202
     */
1203
    function _processMultipleDepsName($deps)
1204
    {
1205
        $tests = array();
1206
        foreach ($deps as $name => $dep) {
1207
            foreach ($dep as $d) {
1208
                $tests[$name][] = $this->_processDep($d);
1209
            }
1210
        }
1211
        foreach ($tests as $name => $test) {
1212
            $php = array();
1213
            $min = array();
1214
            $max = array();
1215
            $php['name'] = $name;
1216
            foreach ($test as $dep) {
1217
                if (!$dep) {
1218
                    continue;
1219
                }
1220
                if (isset($dep['channel'])) {
1221
                    $php['channel'] = 'pear.php.net';
1222
                }
1223
                if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
1224
                    $php['conflicts'] = 'yes';
1225
                }
1226
                if (isset($dep['min'])) {
1227
                    $min[$dep['min']] = count($min);
1228
                }
1229
                if (isset($dep['max'])) {
1230
                    $max[$dep['max']] = count($max);
1231
                }
1232
            }
1233
            if (count($min) > 0) {
1234
                uksort($min, 'version_compare');
1235
            }
1236
            if (count($max) > 0) {
1237
                uksort($max, 'version_compare');
1238
            }
1239
            if (count($min)) {
1240
                // get the highest minimum
1241
                $min = array_pop($a = array_flip($min));
1242
            } else {
1243
                $min = false;
1244
            }
1245
            if (count($max)) {
1246
                // get the lowest maximum
1247
                $max = array_shift($a = array_flip($max));
1248
            } else {
1249
                $max = false;
1250
            }
1251
            if ($min) {
1252
                $php['min'] = $min;
1253
            }
1254
            if ($max) {
1255
                $php['max'] = $max;
1256
            }
1257
            $exclude = array();
1258
            foreach ($test as $dep) {
1259
                if (!isset($dep['exclude'])) {
1260
                    continue;
1261
                }
1262
                $exclude[] = $dep['exclude'];
1263
            }
1264
            if (count($exclude)) {
1265
                $php['exclude'] = $exclude;
1266
            }
1267
            $ret[] = $php;
1268
        }
1269
        return $ret;
1270
    }
1271
}
1272
?>