Хранилища Subversion ant

Редакция

Содержимое файла | Последнее изменение | Открыть журнал | RSS

Редакция Автор № строки Строка
69 alex-w 1
<?php
2
/**
3
 * package.xml parsing 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-2008 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.27 2008/01/03 20:55:16 cellog Exp $
19
 * @link       http://pear.php.net/package/PEAR
20
 * @since      File available since Release 1.4.0a1
21
 */
22
/**
23
 * package.xml abstraction class
24
 */
25
require_once 'PEAR/PackageFile/v1.php';
26
/**
27
 * Parser for package.xml version 1.0
28
 * @category   pear
29
 * @package    PEAR
30
 * @author     Greg Beaver <cellog@php.net>
31
 * @copyright  1997-2008 The PHP Group
32
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
33
 * @version    Release: @PEAR-VER@
34
 * @link       http://pear.php.net/package/PEAR
35
 * @since      Class available since Release 1.4.0a1
36
 */
37
class PEAR_PackageFile_Parser_v1
38
{
39
    var $_registry;
40
    var $_config;
41
    var $_logger;
42
    /**
43
     * BC hack to allow PEAR_Common::infoFromString() to sort of
44
     * work with the version 2.0 format - there's no filelist though
45
     * @param PEAR_PackageFile_v2
46
     */
47
    function fromV2($packagefile)
48
    {
49
        $info = $packagefile->getArray(true);
50
        $ret = new PEAR_PackageFile_v1;
51
        $ret->fromArray($info['old']);
52
    }
53
 
54
    function setConfig(&$c)
55
    {
56
        $this->_config = &$c;
57
        $this->_registry = &$c->getRegistry();
58
    }
59
 
60
    function setLogger(&$l)
61
    {
62
        $this->_logger = &$l;
63
    }
64
 
65
    /**
66
     * @param string contents of package.xml file, version 1.0
67
     * @return bool success of parsing
68
     */
69
    function &parse($data, $file, $archive = false)
70
    {
71
        if (!extension_loaded('xml')) {
72
            return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
73
        }
74
        $xp = xml_parser_create();
75
        if (!$xp) {
76
            $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
77
            return $a;
78
        }
79
        xml_set_object($xp, $this);
80
        xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
81
        xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
82
        xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
83
 
84
        $this->element_stack = array();
85
        $this->_packageInfo = array('provides' => array());
86
        $this->current_element = false;
87
        unset($this->dir_install);
88
        $this->_packageInfo['filelist'] = array();
89
        $this->filelist =& $this->_packageInfo['filelist'];
90
        $this->dir_names = array();
91
        $this->in_changelog = false;
92
        $this->d_i = 0;
93
        $this->cdata = '';
94
        $this->_isValid = true;
95
 
96
        if (!xml_parse($xp, $data, 1)) {
97
            $code = xml_get_error_code($xp);
98
            $line = xml_get_current_line_number($xp);
99
            xml_parser_free($xp);
100
            $a = &PEAR::raiseError(sprintf("XML error: %s at line %d",
101
                           $str = xml_error_string($code), $line), 2);
102
            return $a;
103
        }
104
 
105
        xml_parser_free($xp);
106
 
107
        $pf = new PEAR_PackageFile_v1;
108
        $pf->setConfig($this->_config);
109
        if (isset($this->_logger)) {
110
            $pf->setLogger($this->_logger);
111
        }
112
        $pf->setPackagefile($file, $archive);
113
        $pf->fromArray($this->_packageInfo);
114
        return $pf;
115
    }
116
    // {{{ _unIndent()
117
 
118
    /**
119
     * Unindent given string
120
     *
121
     * @param string $str The string that has to be unindented.
122
     * @return string
123
     * @access private
124
     */
125
    function _unIndent($str)
126
    {
127
        // remove leading newlines
128
        $str = preg_replace('/^[\r\n]+/', '', $str);
129
        // find whitespace at the beginning of the first line
130
        $indent_len = strspn($str, " \t");
131
        $indent = substr($str, 0, $indent_len);
132
        $data = '';
133
        // remove the same amount of whitespace from following lines
134
        foreach (explode("\n", $str) as $line) {
135
            if (substr($line, 0, $indent_len) == $indent) {
136
                $data .= substr($line, $indent_len) . "\n";
137
            } elseif (trim(substr($line, 0, $indent_len))) {
138
                $data .= ltrim($line);
139
            }
140
        }
141
        return $data;
142
    }
143
 
144
    // Support for package DTD v1.0:
145
    // {{{ _element_start_1_0()
146
 
147
    /**
148
     * XML parser callback for ending elements.  Used for version 1.0
149
     * packages.
150
     *
151
     * @param resource  $xp    XML parser resource
152
     * @param string    $name  name of ending element
153
     *
154
     * @return void
155
     *
156
     * @access private
157
     */
158
    function _element_start_1_0($xp, $name, $attribs)
159
    {
160
        array_push($this->element_stack, $name);
161
        $this->current_element = $name;
162
        $spos = sizeof($this->element_stack) - 2;
163
        $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
164
        $this->current_attributes = $attribs;
165
        $this->cdata = '';
166
        switch ($name) {
167
            case 'dir':
168
                if ($this->in_changelog) {
169
                    break;
170
                }
171
                if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
172
                    $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
173
                        $attribs['name']);
174
                    if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
175
                        $attribs['name'] = substr($attribs['name'], 0,
176
                            strlen($attribs['name']) - 1);
177
                    }
178
                    if (strpos($attribs['name'], '/') === 0) {
179
                        $attribs['name'] = substr($attribs['name'], 1);
180
                    }
181
                    $this->dir_names[] = $attribs['name'];
182
                }
183
                if (isset($attribs['baseinstalldir'])) {
184
                    $this->dir_install = $attribs['baseinstalldir'];
185
                }
186
                if (isset($attribs['role'])) {
187
                    $this->dir_role = $attribs['role'];
188
                }
189
                break;
190
            case 'file':
191
                if ($this->in_changelog) {
192
                    break;
193
                }
194
                if (isset($attribs['name'])) {
195
                    $path = '';
196
                    if (count($this->dir_names)) {
197
                        foreach ($this->dir_names as $dir) {
198
                            $path .= $dir . '/';
199
                        }
200
                    }
201
                    $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
202
                        $attribs['name']);
203
                    unset($attribs['name']);
204
                    $this->current_path = $path;
205
                    $this->filelist[$path] = $attribs;
206
                    // Set the baseinstalldir only if the file don't have this attrib
207
                    if (!isset($this->filelist[$path]['baseinstalldir']) &&
208
                        isset($this->dir_install))
209
                    {
210
                        $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
211
                    }
212
                    // Set the Role
213
                    if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
214
                        $this->filelist[$path]['role'] = $this->dir_role;
215
                    }
216
                }
217
                break;
218
            case 'replace':
219
                if (!$this->in_changelog) {
220
                    $this->filelist[$this->current_path]['replacements'][] = $attribs;
221
                }
222
                break;
223
            case 'maintainers':
224
                $this->_packageInfo['maintainers'] = array();
225
                $this->m_i = 0; // maintainers array index
226
                break;
227
            case 'maintainer':
228
                // compatibility check
229
                if (!isset($this->_packageInfo['maintainers'])) {
230
                    $this->_packageInfo['maintainers'] = array();
231
                    $this->m_i = 0;
232
                }
233
                $this->_packageInfo['maintainers'][$this->m_i] = array();
234
                $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
235
                break;
236
            case 'changelog':
237
                $this->_packageInfo['changelog'] = array();
238
                $this->c_i = 0; // changelog array index
239
                $this->in_changelog = true;
240
                break;
241
            case 'release':
242
                if ($this->in_changelog) {
243
                    $this->_packageInfo['changelog'][$this->c_i] = array();
244
                    $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
245
                } else {
246
                    $this->current_release = &$this->_packageInfo;
247
                }
248
                break;
249
            case 'deps':
250
                if (!$this->in_changelog) {
251
                    $this->_packageInfo['release_deps'] = array();
252
                }
253
                break;
254
            case 'dep':
255
                // dependencies array index
256
                if (!$this->in_changelog) {
257
                    $this->d_i++;
258
                    isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
259
                    $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
260
                }
261
                break;
262
            case 'configureoptions':
263
                if (!$this->in_changelog) {
264
                    $this->_packageInfo['configure_options'] = array();
265
                }
266
                break;
267
            case 'configureoption':
268
                if (!$this->in_changelog) {
269
                    $this->_packageInfo['configure_options'][] = $attribs;
270
                }
271
                break;
272
            case 'provides':
273
                if (empty($attribs['type']) || empty($attribs['name'])) {
274
                    break;
275
                }
276
                $attribs['explicit'] = true;
277
                $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
278
                break;
279
            case 'package' :
280
                if (isset($attribs['version'])) {
281
                    $this->_packageInfo['xsdversion'] = trim($attribs['version']);
282
                } else {
283
                    $this->_packageInfo['xsdversion'] = '1.0';
284
                }
285
                if (isset($attribs['packagerversion'])) {
286
                    $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
287
                }
288
                break;
289
        }
290
    }
291
 
292
    // }}}
293
    // {{{ _element_end_1_0()
294
 
295
    /**
296
     * XML parser callback for ending elements.  Used for version 1.0
297
     * packages.
298
     *
299
     * @param resource  $xp    XML parser resource
300
     * @param string    $name  name of ending element
301
     *
302
     * @return void
303
     *
304
     * @access private
305
     */
306
    function _element_end_1_0($xp, $name)
307
    {
308
        $data = trim($this->cdata);
309
        switch ($name) {
310
            case 'name':
311
                switch ($this->prev_element) {
312
                    case 'package':
313
                        $this->_packageInfo['package'] = $data;
314
                        break;
315
                    case 'maintainer':
316
                        $this->current_maintainer['name'] = $data;
317
                        break;
318
                }
319
                break;
320
            case 'extends' :
321
                $this->_packageInfo['extends'] = $data;
322
                break;
323
            case 'summary':
324
                $this->_packageInfo['summary'] = $data;
325
                break;
326
            case 'description':
327
                $data = $this->_unIndent($this->cdata);
328
                $this->_packageInfo['description'] = $data;
329
                break;
330
            case 'user':
331
                $this->current_maintainer['handle'] = $data;
332
                break;
333
            case 'email':
334
                $this->current_maintainer['email'] = $data;
335
                break;
336
            case 'role':
337
                $this->current_maintainer['role'] = $data;
338
                break;
339
            case 'version':
340
                //$data = ereg_replace ('[^a-zA-Z0-9._\-]', '_', $data);
341
                if ($this->in_changelog) {
342
                    $this->current_release['version'] = $data;
343
                } else {
344
                    $this->_packageInfo['version'] = $data;
345
                }
346
                break;
347
            case 'date':
348
                if ($this->in_changelog) {
349
                    $this->current_release['release_date'] = $data;
350
                } else {
351
                    $this->_packageInfo['release_date'] = $data;
352
                }
353
                break;
354
            case 'notes':
355
                // try to "de-indent" release notes in case someone
356
                // has been over-indenting their xml ;-)
357
                $data = $this->_unIndent($this->cdata);
358
                if ($this->in_changelog) {
359
                    $this->current_release['release_notes'] = $data;
360
                } else {
361
                    $this->_packageInfo['release_notes'] = $data;
362
                }
363
                break;
364
            case 'warnings':
365
                if ($this->in_changelog) {
366
                    $this->current_release['release_warnings'] = $data;
367
                } else {
368
                    $this->_packageInfo['release_warnings'] = $data;
369
                }
370
                break;
371
            case 'state':
372
                if ($this->in_changelog) {
373
                    $this->current_release['release_state'] = $data;
374
                } else {
375
                    $this->_packageInfo['release_state'] = $data;
376
                }
377
                break;
378
            case 'license':
379
                if ($this->in_changelog) {
380
                    $this->current_release['release_license'] = $data;
381
                } else {
382
                    $this->_packageInfo['release_license'] = $data;
383
                }
384
                break;
385
            case 'dep':
386
                if ($data && !$this->in_changelog) {
387
                    $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
388
                }
389
                break;
390
            case 'dir':
391
                if ($this->in_changelog) {
392
                    break;
393
                }
394
                array_pop($this->dir_names);
395
                break;
396
            case 'file':
397
                if ($this->in_changelog) {
398
                    break;
399
                }
400
                if ($data) {
401
                    $path = '';
402
                    if (count($this->dir_names)) {
403
                        foreach ($this->dir_names as $dir) {
404
                            $path .= $dir . '/';
405
                        }
406
                    }
407
                    $path .= $data;
408
                    $this->filelist[$path] = $this->current_attributes;
409
                    // Set the baseinstalldir only if the file don't have this attrib
410
                    if (!isset($this->filelist[$path]['baseinstalldir']) &&
411
                        isset($this->dir_install))
412
                    {
413
                        $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
414
                    }
415
                    // Set the Role
416
                    if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
417
                        $this->filelist[$path]['role'] = $this->dir_role;
418
                    }
419
                }
420
                break;
421
            case 'maintainer':
422
                if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
423
                    $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
424
                }
425
                $this->m_i++;
426
                break;
427
            case 'release':
428
                if ($this->in_changelog) {
429
                    $this->c_i++;
430
                }
431
                break;
432
            case 'changelog':
433
                $this->in_changelog = false;
434
                break;
435
        }
436
        array_pop($this->element_stack);
437
        $spos = sizeof($this->element_stack) - 1;
438
        $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
439
        $this->cdata = '';
440
    }
441
 
442
    // }}}
443
    // {{{ _pkginfo_cdata_1_0()
444
 
445
    /**
446
     * XML parser callback for character data.  Used for version 1.0
447
     * packages.
448
     *
449
     * @param resource  $xp    XML parser resource
450
     * @param string    $name  character data
451
     *
452
     * @return void
453
     *
454
     * @access private
455
     */
456
    function _pkginfo_cdata_1_0($xp, $data)
457
    {
458
        if (isset($this->cdata)) {
459
            $this->cdata .= $data;
460
        }
461
    }
462
 
463
    // }}}
464
}
465
?>