Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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