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