1 | <?php |
---|
2 | /** |
---|
3 | * PEAR_PackageFile_v1, 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 | * For error handling |
---|
18 | */ |
---|
19 | require_once 'PEAR/ErrorStack.php'; |
---|
20 | |
---|
21 | /** |
---|
22 | * Error code if parsing is attempted with no xml extension |
---|
23 | */ |
---|
24 | define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3); |
---|
25 | |
---|
26 | /** |
---|
27 | * Error code if creating the xml parser resource fails |
---|
28 | */ |
---|
29 | define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4); |
---|
30 | |
---|
31 | /** |
---|
32 | * Error code used for all sax xml parsing errors |
---|
33 | */ |
---|
34 | define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5); |
---|
35 | |
---|
36 | /** |
---|
37 | * Error code used when there is no name |
---|
38 | */ |
---|
39 | define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6); |
---|
40 | |
---|
41 | /** |
---|
42 | * Error code when a package name is not valid |
---|
43 | */ |
---|
44 | define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7); |
---|
45 | |
---|
46 | /** |
---|
47 | * Error code used when no summary is parsed |
---|
48 | */ |
---|
49 | define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8); |
---|
50 | |
---|
51 | /** |
---|
52 | * Error code for summaries that are more than 1 line |
---|
53 | */ |
---|
54 | define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9); |
---|
55 | |
---|
56 | /** |
---|
57 | * Error code used when no description is present |
---|
58 | */ |
---|
59 | define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10); |
---|
60 | |
---|
61 | /** |
---|
62 | * Error code used when no license is present |
---|
63 | */ |
---|
64 | define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11); |
---|
65 | |
---|
66 | /** |
---|
67 | * Error code used when a <version> version number is not present |
---|
68 | */ |
---|
69 | define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12); |
---|
70 | |
---|
71 | /** |
---|
72 | * Error code used when a <version> version number is invalid |
---|
73 | */ |
---|
74 | define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13); |
---|
75 | |
---|
76 | /** |
---|
77 | * Error code when release state is missing |
---|
78 | */ |
---|
79 | define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14); |
---|
80 | |
---|
81 | /** |
---|
82 | * Error code when release state is invalid |
---|
83 | */ |
---|
84 | define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15); |
---|
85 | |
---|
86 | /** |
---|
87 | * Error code when release state is missing |
---|
88 | */ |
---|
89 | define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16); |
---|
90 | |
---|
91 | /** |
---|
92 | * Error code when release state is invalid |
---|
93 | */ |
---|
94 | define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17); |
---|
95 | |
---|
96 | /** |
---|
97 | * Error code when no release notes are found |
---|
98 | */ |
---|
99 | define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18); |
---|
100 | |
---|
101 | /** |
---|
102 | * Error code when no maintainers are found |
---|
103 | */ |
---|
104 | define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19); |
---|
105 | |
---|
106 | /** |
---|
107 | * Error code when a maintainer has no handle |
---|
108 | */ |
---|
109 | define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20); |
---|
110 | |
---|
111 | /** |
---|
112 | * Error code when a maintainer has no handle |
---|
113 | */ |
---|
114 | define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21); |
---|
115 | |
---|
116 | /** |
---|
117 | * Error code when a maintainer has no name |
---|
118 | */ |
---|
119 | define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22); |
---|
120 | |
---|
121 | /** |
---|
122 | * Error code when a maintainer has no email |
---|
123 | */ |
---|
124 | define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23); |
---|
125 | |
---|
126 | /** |
---|
127 | * Error code when a maintainer has no handle |
---|
128 | */ |
---|
129 | define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24); |
---|
130 | |
---|
131 | /** |
---|
132 | * Error code when a dependency is not a PHP dependency, but has no name |
---|
133 | */ |
---|
134 | define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25); |
---|
135 | |
---|
136 | /** |
---|
137 | * Error code when a dependency has no type (pkg, php, etc.) |
---|
138 | */ |
---|
139 | define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26); |
---|
140 | |
---|
141 | /** |
---|
142 | * Error code when a dependency has no relation (lt, ge, has, etc.) |
---|
143 | */ |
---|
144 | define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27); |
---|
145 | |
---|
146 | /** |
---|
147 | * Error code when a dependency is not a 'has' relation, but has no version |
---|
148 | */ |
---|
149 | define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28); |
---|
150 | |
---|
151 | /** |
---|
152 | * Error code when a dependency has an invalid relation |
---|
153 | */ |
---|
154 | define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29); |
---|
155 | |
---|
156 | /** |
---|
157 | * Error code when a dependency has an invalid type |
---|
158 | */ |
---|
159 | define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30); |
---|
160 | |
---|
161 | /** |
---|
162 | * Error code when a dependency has an invalid optional option |
---|
163 | */ |
---|
164 | define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31); |
---|
165 | |
---|
166 | /** |
---|
167 | * Error code when a dependency is a pkg dependency, and has an invalid package name |
---|
168 | */ |
---|
169 | define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32); |
---|
170 | |
---|
171 | /** |
---|
172 | * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel |
---|
173 | */ |
---|
174 | define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33); |
---|
175 | |
---|
176 | /** |
---|
177 | * Error code when rel="has" and version attribute is present. |
---|
178 | */ |
---|
179 | define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34); |
---|
180 | |
---|
181 | /** |
---|
182 | * Error code when type="php" and dependency name is present |
---|
183 | */ |
---|
184 | define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35); |
---|
185 | |
---|
186 | /** |
---|
187 | * Error code when a configure option has no name |
---|
188 | */ |
---|
189 | define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36); |
---|
190 | |
---|
191 | /** |
---|
192 | * Error code when a configure option has no name |
---|
193 | */ |
---|
194 | define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37); |
---|
195 | |
---|
196 | /** |
---|
197 | * Error code when a file in the filelist has an invalid role |
---|
198 | */ |
---|
199 | define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38); |
---|
200 | |
---|
201 | /** |
---|
202 | * Error code when a file in the filelist has no role |
---|
203 | */ |
---|
204 | define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39); |
---|
205 | |
---|
206 | /** |
---|
207 | * Error code when analyzing a php source file that has parse errors |
---|
208 | */ |
---|
209 | define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40); |
---|
210 | |
---|
211 | /** |
---|
212 | * Error code when analyzing a php source file reveals a source element |
---|
213 | * without a package name prefix |
---|
214 | */ |
---|
215 | define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41); |
---|
216 | |
---|
217 | /** |
---|
218 | * Error code when an unknown channel is specified |
---|
219 | */ |
---|
220 | define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42); |
---|
221 | |
---|
222 | /** |
---|
223 | * Error code when no files are found in the filelist |
---|
224 | */ |
---|
225 | define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43); |
---|
226 | |
---|
227 | /** |
---|
228 | * Error code when a file is not valid php according to _analyzeSourceCode() |
---|
229 | */ |
---|
230 | define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44); |
---|
231 | |
---|
232 | /** |
---|
233 | * Error code when the channel validator returns an error or warning |
---|
234 | */ |
---|
235 | define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45); |
---|
236 | |
---|
237 | /** |
---|
238 | * Error code when a php5 package is packaged in php4 (analysis doesn't work) |
---|
239 | */ |
---|
240 | define('PEAR_PACKAGEFILE_ERROR_PHP5', 46); |
---|
241 | |
---|
242 | /** |
---|
243 | * Error code when a file is listed in package.xml but does not exist |
---|
244 | */ |
---|
245 | define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47); |
---|
246 | |
---|
247 | /** |
---|
248 | * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne") |
---|
249 | */ |
---|
250 | define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48); |
---|
251 | |
---|
252 | /** |
---|
253 | * Error code when a package.xml contains non-ISO-8859-1 characters |
---|
254 | */ |
---|
255 | define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49); |
---|
256 | |
---|
257 | /** |
---|
258 | * Error code when a dependency is not a 'has' relation, but has no version |
---|
259 | */ |
---|
260 | define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50); |
---|
261 | |
---|
262 | /** |
---|
263 | * Error code when a package has no lead developer |
---|
264 | */ |
---|
265 | define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51); |
---|
266 | |
---|
267 | /** |
---|
268 | * Error code when a filename begins with "." |
---|
269 | */ |
---|
270 | define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52); |
---|
271 | /** |
---|
272 | * package.xml encapsulator |
---|
273 | * @category pear |
---|
274 | * @package PEAR |
---|
275 | * @author Greg Beaver <cellog@php.net> |
---|
276 | * @copyright 1997-2009 The Authors |
---|
277 | * @license http://opensource.org/licenses/bsd-license.php New BSD License |
---|
278 | * @version Release: 1.9.4 |
---|
279 | * @link http://pear.php.net/package/PEAR |
---|
280 | * @since Class available since Release 1.4.0a1 |
---|
281 | */ |
---|
282 | class PEAR_PackageFile_v1 |
---|
283 | { |
---|
284 | /** |
---|
285 | * @access private |
---|
286 | * @var PEAR_ErrorStack |
---|
287 | * @access private |
---|
288 | */ |
---|
289 | var $_stack; |
---|
290 | |
---|
291 | /** |
---|
292 | * A registry object, used to access the package name validation regex for non-standard channels |
---|
293 | * @var PEAR_Registry |
---|
294 | * @access private |
---|
295 | */ |
---|
296 | var $_registry; |
---|
297 | |
---|
298 | /** |
---|
299 | * An object that contains a log method that matches PEAR_Common::log's signature |
---|
300 | * @var object |
---|
301 | * @access private |
---|
302 | */ |
---|
303 | var $_logger; |
---|
304 | |
---|
305 | /** |
---|
306 | * Parsed package information |
---|
307 | * @var array |
---|
308 | * @access private |
---|
309 | */ |
---|
310 | var $_packageInfo; |
---|
311 | |
---|
312 | /** |
---|
313 | * path to package.xml |
---|
314 | * @var string |
---|
315 | * @access private |
---|
316 | */ |
---|
317 | var $_packageFile; |
---|
318 | |
---|
319 | /** |
---|
320 | * path to package .tgz or false if this is a local/extracted package.xml |
---|
321 | * @var string |
---|
322 | * @access private |
---|
323 | */ |
---|
324 | var $_archiveFile; |
---|
325 | |
---|
326 | /** |
---|
327 | * @var int |
---|
328 | * @access private |
---|
329 | */ |
---|
330 | var $_isValid = 0; |
---|
331 | |
---|
332 | /** |
---|
333 | * Determines whether this packagefile was initialized only with partial package info |
---|
334 | * |
---|
335 | * If this package file was constructed via parsing REST, it will only contain |
---|
336 | * |
---|
337 | * - package name |
---|
338 | * - channel name |
---|
339 | * - dependencies |
---|
340 | * @var boolean |
---|
341 | * @access private |
---|
342 | */ |
---|
343 | var $_incomplete = true; |
---|
344 | |
---|
345 | /** |
---|
346 | * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack |
---|
347 | * @param string Name of Error Stack class to use. |
---|
348 | */ |
---|
349 | function PEAR_PackageFile_v1() |
---|
350 | { |
---|
351 | $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1'); |
---|
352 | $this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); |
---|
353 | $this->_isValid = 0; |
---|
354 | } |
---|
355 | |
---|
356 | function installBinary($installer) |
---|
357 | { |
---|
358 | return false; |
---|
359 | } |
---|
360 | |
---|
361 | function isExtension($name) |
---|
362 | { |
---|
363 | return false; |
---|
364 | } |
---|
365 | |
---|
366 | function setConfig(&$config) |
---|
367 | { |
---|
368 | $this->_config = &$config; |
---|
369 | $this->_registry = &$config->getRegistry(); |
---|
370 | } |
---|
371 | |
---|
372 | function setRequestedGroup() |
---|
373 | { |
---|
374 | // placeholder |
---|
375 | } |
---|
376 | |
---|
377 | /** |
---|
378 | * For saving in the registry. |
---|
379 | * |
---|
380 | * Set the last version that was installed |
---|
381 | * @param string |
---|
382 | */ |
---|
383 | function setLastInstalledVersion($version) |
---|
384 | { |
---|
385 | $this->_packageInfo['_lastversion'] = $version; |
---|
386 | } |
---|
387 | |
---|
388 | /** |
---|
389 | * @return string|false |
---|
390 | */ |
---|
391 | function getLastInstalledVersion() |
---|
392 | { |
---|
393 | if (isset($this->_packageInfo['_lastversion'])) { |
---|
394 | return $this->_packageInfo['_lastversion']; |
---|
395 | } |
---|
396 | return false; |
---|
397 | } |
---|
398 | |
---|
399 | function getInstalledBinary() |
---|
400 | { |
---|
401 | return false; |
---|
402 | } |
---|
403 | |
---|
404 | function listPostinstallScripts() |
---|
405 | { |
---|
406 | return false; |
---|
407 | } |
---|
408 | |
---|
409 | function initPostinstallScripts() |
---|
410 | { |
---|
411 | return false; |
---|
412 | } |
---|
413 | |
---|
414 | function setLogger(&$logger) |
---|
415 | { |
---|
416 | if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) { |
---|
417 | return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); |
---|
418 | } |
---|
419 | $this->_logger = &$logger; |
---|
420 | } |
---|
421 | |
---|
422 | function setPackagefile($file, $archive = false) |
---|
423 | { |
---|
424 | $this->_packageFile = $file; |
---|
425 | $this->_archiveFile = $archive ? $archive : $file; |
---|
426 | } |
---|
427 | |
---|
428 | function getPackageFile() |
---|
429 | { |
---|
430 | return isset($this->_packageFile) ? $this->_packageFile : false; |
---|
431 | } |
---|
432 | |
---|
433 | function getPackageType() |
---|
434 | { |
---|
435 | return 'php'; |
---|
436 | } |
---|
437 | |
---|
438 | function getArchiveFile() |
---|
439 | { |
---|
440 | return $this->_archiveFile; |
---|
441 | } |
---|
442 | |
---|
443 | function packageInfo($field) |
---|
444 | { |
---|
445 | if (!is_string($field) || empty($field) || |
---|
446 | !isset($this->_packageInfo[$field])) { |
---|
447 | return false; |
---|
448 | } |
---|
449 | return $this->_packageInfo[$field]; |
---|
450 | } |
---|
451 | |
---|
452 | function setDirtree($path) |
---|
453 | { |
---|
454 | if (!isset($this->_packageInfo['dirtree'])) { |
---|
455 | $this->_packageInfo['dirtree'] = array(); |
---|
456 | } |
---|
457 | $this->_packageInfo['dirtree'][$path] = true; |
---|
458 | } |
---|
459 | |
---|
460 | function getDirtree() |
---|
461 | { |
---|
462 | if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { |
---|
463 | return $this->_packageInfo['dirtree']; |
---|
464 | } |
---|
465 | return false; |
---|
466 | } |
---|
467 | |
---|
468 | function resetDirtree() |
---|
469 | { |
---|
470 | unset($this->_packageInfo['dirtree']); |
---|
471 | } |
---|
472 | |
---|
473 | function fromArray($pinfo) |
---|
474 | { |
---|
475 | $this->_incomplete = false; |
---|
476 | $this->_packageInfo = $pinfo; |
---|
477 | } |
---|
478 | |
---|
479 | function isIncomplete() |
---|
480 | { |
---|
481 | return $this->_incomplete; |
---|
482 | } |
---|
483 | |
---|
484 | function getChannel() |
---|
485 | { |
---|
486 | return 'pear.php.net'; |
---|
487 | } |
---|
488 | |
---|
489 | function getUri() |
---|
490 | { |
---|
491 | return false; |
---|
492 | } |
---|
493 | |
---|
494 | function getTime() |
---|
495 | { |
---|
496 | return false; |
---|
497 | } |
---|
498 | |
---|
499 | function getExtends() |
---|
500 | { |
---|
501 | if (isset($this->_packageInfo['extends'])) { |
---|
502 | return $this->_packageInfo['extends']; |
---|
503 | } |
---|
504 | return false; |
---|
505 | } |
---|
506 | |
---|
507 | /** |
---|
508 | * @return array |
---|
509 | */ |
---|
510 | function toArray() |
---|
511 | { |
---|
512 | if (!$this->validate(PEAR_VALIDATE_NORMAL)) { |
---|
513 | return false; |
---|
514 | } |
---|
515 | return $this->getArray(); |
---|
516 | } |
---|
517 | |
---|
518 | function getArray() |
---|
519 | { |
---|
520 | return $this->_packageInfo; |
---|
521 | } |
---|
522 | |
---|
523 | function getName() |
---|
524 | { |
---|
525 | return $this->getPackage(); |
---|
526 | } |
---|
527 | |
---|
528 | function getPackage() |
---|
529 | { |
---|
530 | if (isset($this->_packageInfo['package'])) { |
---|
531 | return $this->_packageInfo['package']; |
---|
532 | } |
---|
533 | return false; |
---|
534 | } |
---|
535 | |
---|
536 | /** |
---|
537 | * WARNING - don't use this unless you know what you are doing |
---|
538 | */ |
---|
539 | function setRawPackage($package) |
---|
540 | { |
---|
541 | $this->_packageInfo['package'] = $package; |
---|
542 | } |
---|
543 | |
---|
544 | function setPackage($package) |
---|
545 | { |
---|
546 | $this->_packageInfo['package'] = $package; |
---|
547 | $this->_isValid = false; |
---|
548 | } |
---|
549 | |
---|
550 | function getVersion() |
---|
551 | { |
---|
552 | if (isset($this->_packageInfo['version'])) { |
---|
553 | return $this->_packageInfo['version']; |
---|
554 | } |
---|
555 | return false; |
---|
556 | } |
---|
557 | |
---|
558 | function setVersion($version) |
---|
559 | { |
---|
560 | $this->_packageInfo['version'] = $version; |
---|
561 | $this->_isValid = false; |
---|
562 | } |
---|
563 | |
---|
564 | function clearMaintainers() |
---|
565 | { |
---|
566 | unset($this->_packageInfo['maintainers']); |
---|
567 | } |
---|
568 | |
---|
569 | function getMaintainers() |
---|
570 | { |
---|
571 | if (isset($this->_packageInfo['maintainers'])) { |
---|
572 | return $this->_packageInfo['maintainers']; |
---|
573 | } |
---|
574 | return false; |
---|
575 | } |
---|
576 | |
---|
577 | /** |
---|
578 | * Adds a new maintainer - no checking of duplicates is performed, use |
---|
579 | * updatemaintainer for that purpose. |
---|
580 | */ |
---|
581 | function addMaintainer($role, $handle, $name, $email) |
---|
582 | { |
---|
583 | $this->_packageInfo['maintainers'][] = |
---|
584 | array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name); |
---|
585 | $this->_isValid = false; |
---|
586 | } |
---|
587 | |
---|
588 | function updateMaintainer($role, $handle, $name, $email) |
---|
589 | { |
---|
590 | $found = false; |
---|
591 | if (!isset($this->_packageInfo['maintainers']) || |
---|
592 | !is_array($this->_packageInfo['maintainers'])) { |
---|
593 | return $this->addMaintainer($role, $handle, $name, $email); |
---|
594 | } |
---|
595 | foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { |
---|
596 | if ($maintainer['handle'] == $handle) { |
---|
597 | $found = $i; |
---|
598 | break; |
---|
599 | } |
---|
600 | } |
---|
601 | if ($found !== false) { |
---|
602 | unset($this->_packageInfo['maintainers'][$found]); |
---|
603 | $this->_packageInfo['maintainers'] = |
---|
604 | array_values($this->_packageInfo['maintainers']); |
---|
605 | } |
---|
606 | $this->addMaintainer($role, $handle, $name, $email); |
---|
607 | } |
---|
608 | |
---|
609 | function deleteMaintainer($handle) |
---|
610 | { |
---|
611 | $found = false; |
---|
612 | foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { |
---|
613 | if ($maintainer['handle'] == $handle) { |
---|
614 | $found = $i; |
---|
615 | break; |
---|
616 | } |
---|
617 | } |
---|
618 | if ($found !== false) { |
---|
619 | unset($this->_packageInfo['maintainers'][$found]); |
---|
620 | $this->_packageInfo['maintainers'] = |
---|
621 | array_values($this->_packageInfo['maintainers']); |
---|
622 | return true; |
---|
623 | } |
---|
624 | return false; |
---|
625 | } |
---|
626 | |
---|
627 | function getState() |
---|
628 | { |
---|
629 | if (isset($this->_packageInfo['release_state'])) { |
---|
630 | return $this->_packageInfo['release_state']; |
---|
631 | } |
---|
632 | return false; |
---|
633 | } |
---|
634 | |
---|
635 | function setRawState($state) |
---|
636 | { |
---|
637 | $this->_packageInfo['release_state'] = $state; |
---|
638 | } |
---|
639 | |
---|
640 | function setState($state) |
---|
641 | { |
---|
642 | $this->_packageInfo['release_state'] = $state; |
---|
643 | $this->_isValid = false; |
---|
644 | } |
---|
645 | |
---|
646 | function getDate() |
---|
647 | { |
---|
648 | if (isset($this->_packageInfo['release_date'])) { |
---|
649 | return $this->_packageInfo['release_date']; |
---|
650 | } |
---|
651 | return false; |
---|
652 | } |
---|
653 | |
---|
654 | function setDate($date) |
---|
655 | { |
---|
656 | $this->_packageInfo['release_date'] = $date; |
---|
657 | $this->_isValid = false; |
---|
658 | } |
---|
659 | |
---|
660 | function getLicense() |
---|
661 | { |
---|
662 | if (isset($this->_packageInfo['release_license'])) { |
---|
663 | return $this->_packageInfo['release_license']; |
---|
664 | } |
---|
665 | return false; |
---|
666 | } |
---|
667 | |
---|
668 | function setLicense($date) |
---|
669 | { |
---|
670 | $this->_packageInfo['release_license'] = $date; |
---|
671 | $this->_isValid = false; |
---|
672 | } |
---|
673 | |
---|
674 | function getSummary() |
---|
675 | { |
---|
676 | if (isset($this->_packageInfo['summary'])) { |
---|
677 | return $this->_packageInfo['summary']; |
---|
678 | } |
---|
679 | return false; |
---|
680 | } |
---|
681 | |
---|
682 | function setSummary($summary) |
---|
683 | { |
---|
684 | $this->_packageInfo['summary'] = $summary; |
---|
685 | $this->_isValid = false; |
---|
686 | } |
---|
687 | |
---|
688 | function getDescription() |
---|
689 | { |
---|
690 | if (isset($this->_packageInfo['description'])) { |
---|
691 | return $this->_packageInfo['description']; |
---|
692 | } |
---|
693 | return false; |
---|
694 | } |
---|
695 | |
---|
696 | function setDescription($desc) |
---|
697 | { |
---|
698 | $this->_packageInfo['description'] = $desc; |
---|
699 | $this->_isValid = false; |
---|
700 | } |
---|
701 | |
---|
702 | function getNotes() |
---|
703 | { |
---|
704 | if (isset($this->_packageInfo['release_notes'])) { |
---|
705 | return $this->_packageInfo['release_notes']; |
---|
706 | } |
---|
707 | return false; |
---|
708 | } |
---|
709 | |
---|
710 | function setNotes($notes) |
---|
711 | { |
---|
712 | $this->_packageInfo['release_notes'] = $notes; |
---|
713 | $this->_isValid = false; |
---|
714 | } |
---|
715 | |
---|
716 | function getDeps() |
---|
717 | { |
---|
718 | if (isset($this->_packageInfo['release_deps'])) { |
---|
719 | return $this->_packageInfo['release_deps']; |
---|
720 | } |
---|
721 | return false; |
---|
722 | } |
---|
723 | |
---|
724 | /** |
---|
725 | * Reset dependencies prior to adding new ones |
---|
726 | */ |
---|
727 | function clearDeps() |
---|
728 | { |
---|
729 | unset($this->_packageInfo['release_deps']); |
---|
730 | } |
---|
731 | |
---|
732 | function addPhpDep($version, $rel) |
---|
733 | { |
---|
734 | $this->_isValid = false; |
---|
735 | $this->_packageInfo['release_deps'][] = |
---|
736 | array('type' => 'php', |
---|
737 | 'rel' => $rel, |
---|
738 | 'version' => $version); |
---|
739 | } |
---|
740 | |
---|
741 | function addPackageDep($name, $version, $rel, $optional = 'no') |
---|
742 | { |
---|
743 | $this->_isValid = false; |
---|
744 | $dep = |
---|
745 | array('type' => 'pkg', |
---|
746 | 'name' => $name, |
---|
747 | 'rel' => $rel, |
---|
748 | 'optional' => $optional); |
---|
749 | if ($rel != 'has' && $rel != 'not') { |
---|
750 | $dep['version'] = $version; |
---|
751 | } |
---|
752 | $this->_packageInfo['release_deps'][] = $dep; |
---|
753 | } |
---|
754 | |
---|
755 | function addExtensionDep($name, $version, $rel, $optional = 'no') |
---|
756 | { |
---|
757 | $this->_isValid = false; |
---|
758 | $this->_packageInfo['release_deps'][] = |
---|
759 | array('type' => 'ext', |
---|
760 | 'name' => $name, |
---|
761 | 'rel' => $rel, |
---|
762 | 'version' => $version, |
---|
763 | 'optional' => $optional); |
---|
764 | } |
---|
765 | |
---|
766 | /** |
---|
767 | * WARNING - do not use this function directly unless you know what you're doing |
---|
768 | */ |
---|
769 | function setDeps($deps) |
---|
770 | { |
---|
771 | $this->_packageInfo['release_deps'] = $deps; |
---|
772 | } |
---|
773 | |
---|
774 | function hasDeps() |
---|
775 | { |
---|
776 | return isset($this->_packageInfo['release_deps']) && |
---|
777 | count($this->_packageInfo['release_deps']); |
---|
778 | } |
---|
779 | |
---|
780 | function getDependencyGroup($group) |
---|
781 | { |
---|
782 | return false; |
---|
783 | } |
---|
784 | |
---|
785 | function isCompatible($pf) |
---|
786 | { |
---|
787 | return false; |
---|
788 | } |
---|
789 | |
---|
790 | function isSubpackageOf($p) |
---|
791 | { |
---|
792 | return $p->isSubpackage($this); |
---|
793 | } |
---|
794 | |
---|
795 | function isSubpackage($p) |
---|
796 | { |
---|
797 | return false; |
---|
798 | } |
---|
799 | |
---|
800 | function dependsOn($package, $channel) |
---|
801 | { |
---|
802 | if (strtolower($channel) != 'pear.php.net') { |
---|
803 | return false; |
---|
804 | } |
---|
805 | if (!($deps = $this->getDeps())) { |
---|
806 | return false; |
---|
807 | } |
---|
808 | foreach ($deps as $dep) { |
---|
809 | if ($dep['type'] != 'pkg') { |
---|
810 | continue; |
---|
811 | } |
---|
812 | if (strtolower($dep['name']) == strtolower($package)) { |
---|
813 | return true; |
---|
814 | } |
---|
815 | } |
---|
816 | return false; |
---|
817 | } |
---|
818 | |
---|
819 | function getConfigureOptions() |
---|
820 | { |
---|
821 | if (isset($this->_packageInfo['configure_options'])) { |
---|
822 | return $this->_packageInfo['configure_options']; |
---|
823 | } |
---|
824 | return false; |
---|
825 | } |
---|
826 | |
---|
827 | function hasConfigureOptions() |
---|
828 | { |
---|
829 | return isset($this->_packageInfo['configure_options']) && |
---|
830 | count($this->_packageInfo['configure_options']); |
---|
831 | } |
---|
832 | |
---|
833 | function addConfigureOption($name, $prompt, $default = false) |
---|
834 | { |
---|
835 | $o = array('name' => $name, 'prompt' => $prompt); |
---|
836 | if ($default !== false) { |
---|
837 | $o['default'] = $default; |
---|
838 | } |
---|
839 | if (!isset($this->_packageInfo['configure_options'])) { |
---|
840 | $this->_packageInfo['configure_options'] = array(); |
---|
841 | } |
---|
842 | $this->_packageInfo['configure_options'][] = $o; |
---|
843 | } |
---|
844 | |
---|
845 | function clearConfigureOptions() |
---|
846 | { |
---|
847 | unset($this->_packageInfo['configure_options']); |
---|
848 | } |
---|
849 | |
---|
850 | function getProvides() |
---|
851 | { |
---|
852 | if (isset($this->_packageInfo['provides'])) { |
---|
853 | return $this->_packageInfo['provides']; |
---|
854 | } |
---|
855 | return false; |
---|
856 | } |
---|
857 | |
---|
858 | function getProvidesExtension() |
---|
859 | { |
---|
860 | return false; |
---|
861 | } |
---|
862 | |
---|
863 | function addFile($dir, $file, $attrs) |
---|
864 | { |
---|
865 | $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); |
---|
866 | if ($dir == '/' || $dir == '') { |
---|
867 | $dir = ''; |
---|
868 | } else { |
---|
869 | $dir .= '/'; |
---|
870 | } |
---|
871 | $file = $dir . $file; |
---|
872 | $file = preg_replace('![\\/]+!', '/', $file); |
---|
873 | $this->_packageInfo['filelist'][$file] = $attrs; |
---|
874 | } |
---|
875 | |
---|
876 | function getInstallationFilelist() |
---|
877 | { |
---|
878 | return $this->getFilelist(); |
---|
879 | } |
---|
880 | |
---|
881 | function getFilelist() |
---|
882 | { |
---|
883 | if (isset($this->_packageInfo['filelist'])) { |
---|
884 | return $this->_packageInfo['filelist']; |
---|
885 | } |
---|
886 | return false; |
---|
887 | } |
---|
888 | |
---|
889 | function setFileAttribute($file, $attr, $value) |
---|
890 | { |
---|
891 | $this->_packageInfo['filelist'][$file][$attr] = $value; |
---|
892 | } |
---|
893 | |
---|
894 | function resetFilelist() |
---|
895 | { |
---|
896 | $this->_packageInfo['filelist'] = array(); |
---|
897 | } |
---|
898 | |
---|
899 | function setInstalledAs($file, $path) |
---|
900 | { |
---|
901 | if ($path) { |
---|
902 | return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; |
---|
903 | } |
---|
904 | unset($this->_packageInfo['filelist'][$file]['installed_as']); |
---|
905 | } |
---|
906 | |
---|
907 | function installedFile($file, $atts) |
---|
908 | { |
---|
909 | if (isset($this->_packageInfo['filelist'][$file])) { |
---|
910 | $this->_packageInfo['filelist'][$file] = |
---|
911 | array_merge($this->_packageInfo['filelist'][$file], $atts); |
---|
912 | } else { |
---|
913 | $this->_packageInfo['filelist'][$file] = $atts; |
---|
914 | } |
---|
915 | } |
---|
916 | |
---|
917 | function getChangelog() |
---|
918 | { |
---|
919 | if (isset($this->_packageInfo['changelog'])) { |
---|
920 | return $this->_packageInfo['changelog']; |
---|
921 | } |
---|
922 | return false; |
---|
923 | } |
---|
924 | |
---|
925 | function getPackagexmlVersion() |
---|
926 | { |
---|
927 | return '1.0'; |
---|
928 | } |
---|
929 | |
---|
930 | /** |
---|
931 | * Wrapper to {@link PEAR_ErrorStack::getErrors()} |
---|
932 | * @param boolean determines whether to purge the error stack after retrieving |
---|
933 | * @return array |
---|
934 | */ |
---|
935 | function getValidationWarnings($purge = true) |
---|
936 | { |
---|
937 | return $this->_stack->getErrors($purge); |
---|
938 | } |
---|
939 | |
---|
940 | // }}} |
---|
941 | /** |
---|
942 | * Validation error. Also marks the object contents as invalid |
---|
943 | * @param error code |
---|
944 | * @param array error information |
---|
945 | * @access private |
---|
946 | */ |
---|
947 | function _validateError($code, $params = array()) |
---|
948 | { |
---|
949 | $this->_stack->push($code, 'error', $params, false, false, debug_backtrace()); |
---|
950 | $this->_isValid = false; |
---|
951 | } |
---|
952 | |
---|
953 | /** |
---|
954 | * Validation warning. Does not mark the object contents invalid. |
---|
955 | * @param error code |
---|
956 | * @param array error information |
---|
957 | * @access private |
---|
958 | */ |
---|
959 | function _validateWarning($code, $params = array()) |
---|
960 | { |
---|
961 | $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace()); |
---|
962 | } |
---|
963 | |
---|
964 | /** |
---|
965 | * @param integer error code |
---|
966 | * @access protected |
---|
967 | */ |
---|
968 | function _getErrorMessage() |
---|
969 | { |
---|
970 | return array( |
---|
971 | PEAR_PACKAGEFILE_ERROR_NO_NAME => |
---|
972 | 'Missing Package Name', |
---|
973 | PEAR_PACKAGEFILE_ERROR_NO_SUMMARY => |
---|
974 | 'No summary found', |
---|
975 | PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY => |
---|
976 | 'Summary should be on one line', |
---|
977 | PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION => |
---|
978 | 'Missing description', |
---|
979 | PEAR_PACKAGEFILE_ERROR_NO_LICENSE => |
---|
980 | 'Missing license', |
---|
981 | PEAR_PACKAGEFILE_ERROR_NO_VERSION => |
---|
982 | 'No release version found', |
---|
983 | PEAR_PACKAGEFILE_ERROR_NO_STATE => |
---|
984 | 'No release state found', |
---|
985 | PEAR_PACKAGEFILE_ERROR_NO_DATE => |
---|
986 | 'No release date found', |
---|
987 | PEAR_PACKAGEFILE_ERROR_NO_NOTES => |
---|
988 | 'No release notes found', |
---|
989 | PEAR_PACKAGEFILE_ERROR_NO_LEAD => |
---|
990 | 'Package must have at least one lead maintainer', |
---|
991 | PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS => |
---|
992 | 'No maintainers found, at least one must be defined', |
---|
993 | PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE => |
---|
994 | 'Maintainer %index% has no handle (user ID at channel server)', |
---|
995 | PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE => |
---|
996 | 'Maintainer %index% has no role', |
---|
997 | PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME => |
---|
998 | 'Maintainer %index% has no name', |
---|
999 | PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL => |
---|
1000 | 'Maintainer %index% has no email', |
---|
1001 | PEAR_PACKAGEFILE_ERROR_NO_DEPNAME => |
---|
1002 | 'Dependency %index% is not a php dependency, and has no name', |
---|
1003 | PEAR_PACKAGEFILE_ERROR_NO_DEPREL => |
---|
1004 | 'Dependency %index% has no relation (rel)', |
---|
1005 | PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE => |
---|
1006 | 'Dependency %index% has no type', |
---|
1007 | PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED => |
---|
1008 | 'PHP Dependency %index% has a name attribute of "%name%" which will be' . |
---|
1009 | ' ignored!', |
---|
1010 | PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION => |
---|
1011 | 'Dependency %index% is not a rel="has" or rel="not" dependency, ' . |
---|
1012 | 'and has no version', |
---|
1013 | PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION => |
---|
1014 | 'Dependency %index% is a type="php" dependency, ' . |
---|
1015 | 'and has no version', |
---|
1016 | PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED => |
---|
1017 | 'Dependency %index% is a rel="%rel%" dependency, versioning is ignored', |
---|
1018 | PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL => |
---|
1019 | 'Dependency %index% has invalid optional value "%opt%", should be yes or no', |
---|
1020 | PEAR_PACKAGEFILE_PHP_NO_NOT => |
---|
1021 | 'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' . |
---|
1022 | ' to exclude specific versions', |
---|
1023 | PEAR_PACKAGEFILE_ERROR_NO_CONFNAME => |
---|
1024 | 'Configure Option %index% has no name', |
---|
1025 | PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT => |
---|
1026 | 'Configure Option %index% has no prompt', |
---|
1027 | PEAR_PACKAGEFILE_ERROR_NO_FILES => |
---|
1028 | 'No files in <filelist> section of package.xml', |
---|
1029 | PEAR_PACKAGEFILE_ERROR_NO_FILEROLE => |
---|
1030 | 'File "%file%" has no role, expecting one of "%roles%"', |
---|
1031 | PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE => |
---|
1032 | 'File "%file%" has invalid role "%role%", expecting one of "%roles%"', |
---|
1033 | PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME => |
---|
1034 | 'File "%file%" cannot start with ".", cannot package or install', |
---|
1035 | PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE => |
---|
1036 | 'Parser error: invalid PHP found in file "%file%"', |
---|
1037 | PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX => |
---|
1038 | 'in %file%: %type% "%name%" not prefixed with package name "%package%"', |
---|
1039 | PEAR_PACKAGEFILE_ERROR_INVALID_FILE => |
---|
1040 | 'Parser error: invalid PHP file "%file%"', |
---|
1041 | PEAR_PACKAGEFILE_ERROR_CHANNELVAL => |
---|
1042 | 'Channel validator error: field "%field%" - %reason%', |
---|
1043 | PEAR_PACKAGEFILE_ERROR_PHP5 => |
---|
1044 | 'Error, PHP5 token encountered in %file%, analysis should be in PHP5', |
---|
1045 | PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND => |
---|
1046 | 'File "%file%" in package.xml does not exist', |
---|
1047 | PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS => |
---|
1048 | 'Package.xml contains non-ISO-8859-1 characters, and may not validate', |
---|
1049 | ); |
---|
1050 | } |
---|
1051 | |
---|
1052 | /** |
---|
1053 | * Validate XML package definition file. |
---|
1054 | * |
---|
1055 | * @access public |
---|
1056 | * @return boolean |
---|
1057 | */ |
---|
1058 | function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false) |
---|
1059 | { |
---|
1060 | if (($this->_isValid & $state) == $state) { |
---|
1061 | return true; |
---|
1062 | } |
---|
1063 | $this->_isValid = true; |
---|
1064 | $info = $this->_packageInfo; |
---|
1065 | if (empty($info['package'])) { |
---|
1066 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME); |
---|
1067 | $this->_packageName = $pn = 'unknown'; |
---|
1068 | } else { |
---|
1069 | $this->_packageName = $pn = $info['package']; |
---|
1070 | } |
---|
1071 | |
---|
1072 | if (empty($info['summary'])) { |
---|
1073 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY); |
---|
1074 | } elseif (strpos(trim($info['summary']), "\n") !== false) { |
---|
1075 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY, |
---|
1076 | array('summary' => $info['summary'])); |
---|
1077 | } |
---|
1078 | if (empty($info['description'])) { |
---|
1079 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION); |
---|
1080 | } |
---|
1081 | if (empty($info['release_license'])) { |
---|
1082 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE); |
---|
1083 | } |
---|
1084 | if (empty($info['version'])) { |
---|
1085 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION); |
---|
1086 | } |
---|
1087 | if (empty($info['release_state'])) { |
---|
1088 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE); |
---|
1089 | } |
---|
1090 | if (empty($info['release_date'])) { |
---|
1091 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE); |
---|
1092 | } |
---|
1093 | if (empty($info['release_notes'])) { |
---|
1094 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES); |
---|
1095 | } |
---|
1096 | if (empty($info['maintainers'])) { |
---|
1097 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS); |
---|
1098 | } else { |
---|
1099 | $haslead = false; |
---|
1100 | $i = 1; |
---|
1101 | foreach ($info['maintainers'] as $m) { |
---|
1102 | if (empty($m['handle'])) { |
---|
1103 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE, |
---|
1104 | array('index' => $i)); |
---|
1105 | } |
---|
1106 | if (empty($m['role'])) { |
---|
1107 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE, |
---|
1108 | array('index' => $i, 'roles' => PEAR_Common::getUserRoles())); |
---|
1109 | } elseif ($m['role'] == 'lead') { |
---|
1110 | $haslead = true; |
---|
1111 | } |
---|
1112 | if (empty($m['name'])) { |
---|
1113 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME, |
---|
1114 | array('index' => $i)); |
---|
1115 | } |
---|
1116 | if (empty($m['email'])) { |
---|
1117 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL, |
---|
1118 | array('index' => $i)); |
---|
1119 | } |
---|
1120 | $i++; |
---|
1121 | } |
---|
1122 | if (!$haslead) { |
---|
1123 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD); |
---|
1124 | } |
---|
1125 | } |
---|
1126 | if (!empty($info['release_deps'])) { |
---|
1127 | $i = 1; |
---|
1128 | foreach ($info['release_deps'] as $d) { |
---|
1129 | if (!isset($d['type']) || empty($d['type'])) { |
---|
1130 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE, |
---|
1131 | array('index' => $i, 'types' => PEAR_Common::getDependencyTypes())); |
---|
1132 | continue; |
---|
1133 | } |
---|
1134 | if (!isset($d['rel']) || empty($d['rel'])) { |
---|
1135 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL, |
---|
1136 | array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations())); |
---|
1137 | continue; |
---|
1138 | } |
---|
1139 | if (!empty($d['optional'])) { |
---|
1140 | if (!in_array($d['optional'], array('yes', 'no'))) { |
---|
1141 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL, |
---|
1142 | array('index' => $i, 'opt' => $d['optional'])); |
---|
1143 | } |
---|
1144 | } |
---|
1145 | if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) { |
---|
1146 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION, |
---|
1147 | array('index' => $i)); |
---|
1148 | } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) { |
---|
1149 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED, |
---|
1150 | array('index' => $i, 'rel' => $d['rel'])); |
---|
1151 | } |
---|
1152 | if ($d['type'] == 'php' && !empty($d['name'])) { |
---|
1153 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED, |
---|
1154 | array('index' => $i, 'name' => $d['name'])); |
---|
1155 | } elseif ($d['type'] != 'php' && empty($d['name'])) { |
---|
1156 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME, |
---|
1157 | array('index' => $i)); |
---|
1158 | } |
---|
1159 | if ($d['type'] == 'php' && empty($d['version'])) { |
---|
1160 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION, |
---|
1161 | array('index' => $i)); |
---|
1162 | } |
---|
1163 | if (($d['rel'] == 'not') && ($d['type'] == 'php')) { |
---|
1164 | $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT, |
---|
1165 | array('index' => $i)); |
---|
1166 | } |
---|
1167 | $i++; |
---|
1168 | } |
---|
1169 | } |
---|
1170 | if (!empty($info['configure_options'])) { |
---|
1171 | $i = 1; |
---|
1172 | foreach ($info['configure_options'] as $c) { |
---|
1173 | if (empty($c['name'])) { |
---|
1174 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME, |
---|
1175 | array('index' => $i)); |
---|
1176 | } |
---|
1177 | if (empty($c['prompt'])) { |
---|
1178 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT, |
---|
1179 | array('index' => $i)); |
---|
1180 | } |
---|
1181 | $i++; |
---|
1182 | } |
---|
1183 | } |
---|
1184 | if (empty($info['filelist'])) { |
---|
1185 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES); |
---|
1186 | $errors[] = 'no files'; |
---|
1187 | } else { |
---|
1188 | foreach ($info['filelist'] as $file => $fa) { |
---|
1189 | if (empty($fa['role'])) { |
---|
1190 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE, |
---|
1191 | array('file' => $file, 'roles' => PEAR_Common::getFileRoles())); |
---|
1192 | continue; |
---|
1193 | } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) { |
---|
1194 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE, |
---|
1195 | array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles())); |
---|
1196 | } |
---|
1197 | if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) { |
---|
1198 | // file contains .. parent directory or . cur directory references |
---|
1199 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, |
---|
1200 | array('file' => $file)); |
---|
1201 | } |
---|
1202 | if (isset($fa['install-as']) && |
---|
1203 | preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
---|
1204 | str_replace('\\', '/', $fa['install-as']))) { |
---|
1205 | // install-as contains .. parent directory or . cur directory references |
---|
1206 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, |
---|
1207 | array('file' => $file . ' [installed as ' . $fa['install-as'] . ']')); |
---|
1208 | } |
---|
1209 | if (isset($fa['baseinstalldir']) && |
---|
1210 | preg_match('~/\.\.?(/|\\z)|^\.\.?/~', |
---|
1211 | str_replace('\\', '/', $fa['baseinstalldir']))) { |
---|
1212 | // install-as contains .. parent directory or . cur directory references |
---|
1213 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, |
---|
1214 | array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']')); |
---|
1215 | } |
---|
1216 | } |
---|
1217 | } |
---|
1218 | if (isset($this->_registry) && $this->_isValid) { |
---|
1219 | $chan = $this->_registry->getChannel('pear.php.net'); |
---|
1220 | if (PEAR::isError($chan)) { |
---|
1221 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage()); |
---|
1222 | return $this->_isValid = 0; |
---|
1223 | } |
---|
1224 | $validator = $chan->getValidationObject(); |
---|
1225 | $validator->setPackageFile($this); |
---|
1226 | $validator->validate($state); |
---|
1227 | $failures = $validator->getFailures(); |
---|
1228 | foreach ($failures['errors'] as $error) { |
---|
1229 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error); |
---|
1230 | } |
---|
1231 | foreach ($failures['warnings'] as $warning) { |
---|
1232 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning); |
---|
1233 | } |
---|
1234 | } |
---|
1235 | if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) { |
---|
1236 | if ($this->_analyzePhpFiles()) { |
---|
1237 | $this->_isValid = true; |
---|
1238 | } |
---|
1239 | } |
---|
1240 | if ($this->_isValid) { |
---|
1241 | return $this->_isValid = $state; |
---|
1242 | } |
---|
1243 | return $this->_isValid = 0; |
---|
1244 | } |
---|
1245 | |
---|
1246 | function _analyzePhpFiles() |
---|
1247 | { |
---|
1248 | if (!$this->_isValid) { |
---|
1249 | return false; |
---|
1250 | } |
---|
1251 | if (!isset($this->_packageFile)) { |
---|
1252 | return false; |
---|
1253 | } |
---|
1254 | $dir_prefix = dirname($this->_packageFile); |
---|
1255 | $common = new PEAR_Common; |
---|
1256 | $log = isset($this->_logger) ? array(&$this->_logger, 'log') : |
---|
1257 | array($common, 'log'); |
---|
1258 | $info = $this->getFilelist(); |
---|
1259 | foreach ($info as $file => $fa) { |
---|
1260 | if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) { |
---|
1261 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND, |
---|
1262 | array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file)); |
---|
1263 | continue; |
---|
1264 | } |
---|
1265 | if ($fa['role'] == 'php' && $dir_prefix) { |
---|
1266 | call_user_func_array($log, array(1, "Analyzing $file")); |
---|
1267 | $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); |
---|
1268 | if ($srcinfo) { |
---|
1269 | $this->_buildProvidesArray($srcinfo); |
---|
1270 | } |
---|
1271 | } |
---|
1272 | } |
---|
1273 | $this->_packageName = $pn = $this->getPackage(); |
---|
1274 | $pnl = strlen($pn); |
---|
1275 | if (isset($this->_packageInfo['provides'])) { |
---|
1276 | foreach ((array) $this->_packageInfo['provides'] as $key => $what) { |
---|
1277 | if (isset($what['explicit'])) { |
---|
1278 | // skip conformance checks if the provides entry is |
---|
1279 | // specified in the package.xml file |
---|
1280 | continue; |
---|
1281 | } |
---|
1282 | extract($what); |
---|
1283 | if ($type == 'class') { |
---|
1284 | if (!strncasecmp($name, $pn, $pnl)) { |
---|
1285 | continue; |
---|
1286 | } |
---|
1287 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, |
---|
1288 | array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); |
---|
1289 | } elseif ($type == 'function') { |
---|
1290 | if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { |
---|
1291 | continue; |
---|
1292 | } |
---|
1293 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, |
---|
1294 | array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); |
---|
1295 | } |
---|
1296 | } |
---|
1297 | } |
---|
1298 | return $this->_isValid; |
---|
1299 | } |
---|
1300 | |
---|
1301 | /** |
---|
1302 | * Get the default xml generator object |
---|
1303 | * |
---|
1304 | * @return PEAR_PackageFile_Generator_v1 |
---|
1305 | */ |
---|
1306 | function &getDefaultGenerator() |
---|
1307 | { |
---|
1308 | if (!class_exists('PEAR_PackageFile_Generator_v1')) { |
---|
1309 | require_once 'PEAR/PackageFile/Generator/v1.php'; |
---|
1310 | } |
---|
1311 | $a = &new PEAR_PackageFile_Generator_v1($this); |
---|
1312 | return $a; |
---|
1313 | } |
---|
1314 | |
---|
1315 | /** |
---|
1316 | * Get the contents of a file listed within the package.xml |
---|
1317 | * @param string |
---|
1318 | * @return string |
---|
1319 | */ |
---|
1320 | function getFileContents($file) |
---|
1321 | { |
---|
1322 | if ($this->_archiveFile == $this->_packageFile) { // unpacked |
---|
1323 | $dir = dirname($this->_packageFile); |
---|
1324 | $file = $dir . DIRECTORY_SEPARATOR . $file; |
---|
1325 | $file = str_replace(array('/', '\\'), |
---|
1326 | array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); |
---|
1327 | if (file_exists($file) && is_readable($file)) { |
---|
1328 | return implode('', file($file)); |
---|
1329 | } |
---|
1330 | } else { // tgz |
---|
1331 | if (!class_exists('Archive_Tar')) { |
---|
1332 | require_once 'Archive/Tar.php'; |
---|
1333 | } |
---|
1334 | $tar = &new Archive_Tar($this->_archiveFile); |
---|
1335 | $tar->pushErrorHandling(PEAR_ERROR_RETURN); |
---|
1336 | if ($file != 'package.xml' && $file != 'package2.xml') { |
---|
1337 | $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; |
---|
1338 | } |
---|
1339 | $file = $tar->extractInString($file); |
---|
1340 | $tar->popErrorHandling(); |
---|
1341 | if (PEAR::isError($file)) { |
---|
1342 | return PEAR::raiseError("Cannot locate file '$file' in archive"); |
---|
1343 | } |
---|
1344 | return $file; |
---|
1345 | } |
---|
1346 | } |
---|
1347 | |
---|
1348 | // {{{ analyzeSourceCode() |
---|
1349 | /** |
---|
1350 | * Analyze the source code of the given PHP file |
---|
1351 | * |
---|
1352 | * @param string Filename of the PHP file |
---|
1353 | * @return mixed |
---|
1354 | * @access private |
---|
1355 | */ |
---|
1356 | function _analyzeSourceCode($file) |
---|
1357 | { |
---|
1358 | if (!function_exists("token_get_all")) { |
---|
1359 | return false; |
---|
1360 | } |
---|
1361 | if (!defined('T_DOC_COMMENT')) { |
---|
1362 | define('T_DOC_COMMENT', T_COMMENT); |
---|
1363 | } |
---|
1364 | if (!defined('T_INTERFACE')) { |
---|
1365 | define('T_INTERFACE', -1); |
---|
1366 | } |
---|
1367 | if (!defined('T_IMPLEMENTS')) { |
---|
1368 | define('T_IMPLEMENTS', -1); |
---|
1369 | } |
---|
1370 | if (!$fp = @fopen($file, "r")) { |
---|
1371 | return false; |
---|
1372 | } |
---|
1373 | fclose($fp); |
---|
1374 | $contents = file_get_contents($file); |
---|
1375 | $tokens = token_get_all($contents); |
---|
1376 | /* |
---|
1377 | for ($i = 0; $i < sizeof($tokens); $i++) { |
---|
1378 | @list($token, $data) = $tokens[$i]; |
---|
1379 | if (is_string($token)) { |
---|
1380 | var_dump($token); |
---|
1381 | } else { |
---|
1382 | print token_name($token) . ' '; |
---|
1383 | var_dump(rtrim($data)); |
---|
1384 | } |
---|
1385 | } |
---|
1386 | */ |
---|
1387 | $look_for = 0; |
---|
1388 | $paren_level = 0; |
---|
1389 | $bracket_level = 0; |
---|
1390 | $brace_level = 0; |
---|
1391 | $lastphpdoc = ''; |
---|
1392 | $current_class = ''; |
---|
1393 | $current_interface = ''; |
---|
1394 | $current_class_level = -1; |
---|
1395 | $current_function = ''; |
---|
1396 | $current_function_level = -1; |
---|
1397 | $declared_classes = array(); |
---|
1398 | $declared_interfaces = array(); |
---|
1399 | $declared_functions = array(); |
---|
1400 | $declared_methods = array(); |
---|
1401 | $used_classes = array(); |
---|
1402 | $used_functions = array(); |
---|
1403 | $extends = array(); |
---|
1404 | $implements = array(); |
---|
1405 | $nodeps = array(); |
---|
1406 | $inquote = false; |
---|
1407 | $interface = false; |
---|
1408 | for ($i = 0; $i < sizeof($tokens); $i++) { |
---|
1409 | if (is_array($tokens[$i])) { |
---|
1410 | list($token, $data) = $tokens[$i]; |
---|
1411 | } else { |
---|
1412 | $token = $tokens[$i]; |
---|
1413 | $data = ''; |
---|
1414 | } |
---|
1415 | if ($inquote) { |
---|
1416 | if ($token != '"' && $token != T_END_HEREDOC) { |
---|
1417 | continue; |
---|
1418 | } else { |
---|
1419 | $inquote = false; |
---|
1420 | continue; |
---|
1421 | } |
---|
1422 | } |
---|
1423 | switch ($token) { |
---|
1424 | case T_WHITESPACE : |
---|
1425 | continue; |
---|
1426 | case ';': |
---|
1427 | if ($interface) { |
---|
1428 | $current_function = ''; |
---|
1429 | $current_function_level = -1; |
---|
1430 | } |
---|
1431 | break; |
---|
1432 | case '"': |
---|
1433 | case T_START_HEREDOC: |
---|
1434 | $inquote = true; |
---|
1435 | break; |
---|
1436 | case T_CURLY_OPEN: |
---|
1437 | case T_DOLLAR_OPEN_CURLY_BRACES: |
---|
1438 | case '{': $brace_level++; continue 2; |
---|
1439 | case '}': |
---|
1440 | $brace_level--; |
---|
1441 | if ($current_class_level == $brace_level) { |
---|
1442 | $current_class = ''; |
---|
1443 | $current_class_level = -1; |
---|
1444 | } |
---|
1445 | if ($current_function_level == $brace_level) { |
---|
1446 | $current_function = ''; |
---|
1447 | $current_function_level = -1; |
---|
1448 | } |
---|
1449 | continue 2; |
---|
1450 | case '[': $bracket_level++; continue 2; |
---|
1451 | case ']': $bracket_level--; continue 2; |
---|
1452 | case '(': $paren_level++; continue 2; |
---|
1453 | case ')': $paren_level--; continue 2; |
---|
1454 | case T_INTERFACE: |
---|
1455 | $interface = true; |
---|
1456 | case T_CLASS: |
---|
1457 | if (($current_class_level != -1) || ($current_function_level != -1)) { |
---|
1458 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, |
---|
1459 | array('file' => $file)); |
---|
1460 | return false; |
---|
1461 | } |
---|
1462 | case T_FUNCTION: |
---|
1463 | case T_NEW: |
---|
1464 | case T_EXTENDS: |
---|
1465 | case T_IMPLEMENTS: |
---|
1466 | $look_for = $token; |
---|
1467 | continue 2; |
---|
1468 | case T_STRING: |
---|
1469 | if (version_compare(zend_version(), '2.0', '<')) { |
---|
1470 | if (in_array(strtolower($data), |
---|
1471 | array('public', 'private', 'protected', 'abstract', |
---|
1472 | 'interface', 'implements', 'throw') |
---|
1473 | )) { |
---|
1474 | $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5, |
---|
1475 | array($file)); |
---|
1476 | } |
---|
1477 | } |
---|
1478 | if ($look_for == T_CLASS) { |
---|
1479 | $current_class = $data; |
---|
1480 | $current_class_level = $brace_level; |
---|
1481 | $declared_classes[] = $current_class; |
---|
1482 | } elseif ($look_for == T_INTERFACE) { |
---|
1483 | $current_interface = $data; |
---|
1484 | $current_class_level = $brace_level; |
---|
1485 | $declared_interfaces[] = $current_interface; |
---|
1486 | } elseif ($look_for == T_IMPLEMENTS) { |
---|
1487 | $implements[$current_class] = $data; |
---|
1488 | } elseif ($look_for == T_EXTENDS) { |
---|
1489 | $extends[$current_class] = $data; |
---|
1490 | } elseif ($look_for == T_FUNCTION) { |
---|
1491 | if ($current_class) { |
---|
1492 | $current_function = "$current_class::$data"; |
---|
1493 | $declared_methods[$current_class][] = $data; |
---|
1494 | } elseif ($current_interface) { |
---|
1495 | $current_function = "$current_interface::$data"; |
---|
1496 | $declared_methods[$current_interface][] = $data; |
---|
1497 | } else { |
---|
1498 | $current_function = $data; |
---|
1499 | $declared_functions[] = $current_function; |
---|
1500 | } |
---|
1501 | $current_function_level = $brace_level; |
---|
1502 | $m = array(); |
---|
1503 | } elseif ($look_for == T_NEW) { |
---|
1504 | $used_classes[$data] = true; |
---|
1505 | } |
---|
1506 | $look_for = 0; |
---|
1507 | continue 2; |
---|
1508 | case T_VARIABLE: |
---|
1509 | $look_for = 0; |
---|
1510 | continue 2; |
---|
1511 | case T_DOC_COMMENT: |
---|
1512 | case T_COMMENT: |
---|
1513 | if (preg_match('!^/\*\*\s!', $data)) { |
---|
1514 | $lastphpdoc = $data; |
---|
1515 | if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { |
---|
1516 | $nodeps = array_merge($nodeps, $m[1]); |
---|
1517 | } |
---|
1518 | } |
---|
1519 | continue 2; |
---|
1520 | case T_DOUBLE_COLON: |
---|
1521 | if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { |
---|
1522 | $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, |
---|
1523 | array('file' => $file)); |
---|
1524 | return false; |
---|
1525 | } |
---|
1526 | $class = $tokens[$i - 1][1]; |
---|
1527 | if (strtolower($class) != 'parent') { |
---|
1528 | $used_classes[$class] = true; |
---|
1529 | } |
---|
1530 | continue 2; |
---|
1531 | } |
---|
1532 | } |
---|
1533 | return array( |
---|
1534 | "source_file" => $file, |
---|
1535 | "declared_classes" => $declared_classes, |
---|
1536 | "declared_interfaces" => $declared_interfaces, |
---|
1537 | "declared_methods" => $declared_methods, |
---|
1538 | "declared_functions" => $declared_functions, |
---|
1539 | "used_classes" => array_diff(array_keys($used_classes), $nodeps), |
---|
1540 | "inheritance" => $extends, |
---|
1541 | "implements" => $implements, |
---|
1542 | ); |
---|
1543 | } |
---|
1544 | |
---|
1545 | /** |
---|
1546 | * Build a "provides" array from data returned by |
---|
1547 | * analyzeSourceCode(). The format of the built array is like |
---|
1548 | * this: |
---|
1549 | * |
---|
1550 | * array( |
---|
1551 | * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), |
---|
1552 | * ... |
---|
1553 | * ) |
---|
1554 | * |
---|
1555 | * |
---|
1556 | * @param array $srcinfo array with information about a source file |
---|
1557 | * as returned by the analyzeSourceCode() method. |
---|
1558 | * |
---|
1559 | * @return void |
---|
1560 | * |
---|
1561 | * @access private |
---|
1562 | * |
---|
1563 | */ |
---|
1564 | function _buildProvidesArray($srcinfo) |
---|
1565 | { |
---|
1566 | if (!$this->_isValid) { |
---|
1567 | return false; |
---|
1568 | } |
---|
1569 | $file = basename($srcinfo['source_file']); |
---|
1570 | $pn = $this->getPackage(); |
---|
1571 | $pnl = strlen($pn); |
---|
1572 | foreach ($srcinfo['declared_classes'] as $class) { |
---|
1573 | $key = "class;$class"; |
---|
1574 | if (isset($this->_packageInfo['provides'][$key])) { |
---|
1575 | continue; |
---|
1576 | } |
---|
1577 | $this->_packageInfo['provides'][$key] = |
---|
1578 | array('file'=> $file, 'type' => 'class', 'name' => $class); |
---|
1579 | if (isset($srcinfo['inheritance'][$class])) { |
---|
1580 | $this->_packageInfo['provides'][$key]['extends'] = |
---|
1581 | $srcinfo['inheritance'][$class]; |
---|
1582 | } |
---|
1583 | } |
---|
1584 | foreach ($srcinfo['declared_methods'] as $class => $methods) { |
---|
1585 | foreach ($methods as $method) { |
---|
1586 | $function = "$class::$method"; |
---|
1587 | $key = "function;$function"; |
---|
1588 | if ($method{0} == '_' || !strcasecmp($method, $class) || |
---|
1589 | isset($this->_packageInfo['provides'][$key])) { |
---|
1590 | continue; |
---|
1591 | } |
---|
1592 | $this->_packageInfo['provides'][$key] = |
---|
1593 | array('file'=> $file, 'type' => 'function', 'name' => $function); |
---|
1594 | } |
---|
1595 | } |
---|
1596 | |
---|
1597 | foreach ($srcinfo['declared_functions'] as $function) { |
---|
1598 | $key = "function;$function"; |
---|
1599 | if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) { |
---|
1600 | continue; |
---|
1601 | } |
---|
1602 | if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { |
---|
1603 | $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; |
---|
1604 | } |
---|
1605 | $this->_packageInfo['provides'][$key] = |
---|
1606 | array('file'=> $file, 'type' => 'function', 'name' => $function); |
---|
1607 | } |
---|
1608 | } |
---|
1609 | |
---|
1610 | // }}} |
---|
1611 | } |
---|
1612 | ?> |
---|