/core/PEAR/PEAR/PackageFile/v1.php
PHP | 1612 lines | 1145 code | 145 blank | 322 comment | 171 complexity | 8e81114ed67b8c843c54e3dd0101ed08 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
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,v 1.75 2009/02/24 23:39:16 dufuz Exp $ 13 * @link http://pear.php.net/package/PEAR 14 * @since File available since Release 1.4.0a1 15 */ 16/** 17 * For error handling 18 */ 19require_once 'PEAR/ErrorStack.php'; 20 21/** 22 * Error code if parsing is attempted with no xml extension 23 */ 24define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3); 25 26/** 27 * Error code if creating the xml parser resource fails 28 */ 29define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4); 30 31/** 32 * Error code used for all sax xml parsing errors 33 */ 34define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5); 35 36/** 37 * Error code used when there is no name 38 */ 39define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6); 40 41/** 42 * Error code when a package name is not valid 43 */ 44define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7); 45 46/** 47 * Error code used when no summary is parsed 48 */ 49define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8); 50 51/** 52 * Error code for summaries that are more than 1 line 53 */ 54define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9); 55 56/** 57 * Error code used when no description is present 58 */ 59define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10); 60 61/** 62 * Error code used when no license is present 63 */ 64define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11); 65 66/** 67 * Error code used when a <version> version number is not present 68 */ 69define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12); 70 71/** 72 * Error code used when a <version> version number is invalid 73 */ 74define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13); 75 76/** 77 * Error code when release state is missing 78 */ 79define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14); 80 81/** 82 * Error code when release state is invalid 83 */ 84define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15); 85 86/** 87 * Error code when release state is missing 88 */ 89define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16); 90 91/** 92 * Error code when release state is invalid 93 */ 94define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17); 95 96/** 97 * Error code when no release notes are found 98 */ 99define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18); 100 101/** 102 * Error code when no maintainers are found 103 */ 104define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19); 105 106/** 107 * Error code when a maintainer has no handle 108 */ 109define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20); 110 111/** 112 * Error code when a maintainer has no handle 113 */ 114define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21); 115 116/** 117 * Error code when a maintainer has no name 118 */ 119define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22); 120 121/** 122 * Error code when a maintainer has no email 123 */ 124define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23); 125 126/** 127 * Error code when a maintainer has no handle 128 */ 129define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24); 130 131/** 132 * Error code when a dependency is not a PHP dependency, but has no name 133 */ 134define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25); 135 136/** 137 * Error code when a dependency has no type (pkg, php, etc.) 138 */ 139define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26); 140 141/** 142 * Error code when a dependency has no relation (lt, ge, has, etc.) 143 */ 144define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27); 145 146/** 147 * Error code when a dependency is not a 'has' relation, but has no version 148 */ 149define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28); 150 151/** 152 * Error code when a dependency has an invalid relation 153 */ 154define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29); 155 156/** 157 * Error code when a dependency has an invalid type 158 */ 159define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30); 160 161/** 162 * Error code when a dependency has an invalid optional option 163 */ 164define('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 */ 169define('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 */ 174define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33); 175 176/** 177 * Error code when rel="has" and version attribute is present. 178 */ 179define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34); 180 181/** 182 * Error code when type="php" and dependency name is present 183 */ 184define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35); 185 186/** 187 * Error code when a configure option has no name 188 */ 189define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36); 190 191/** 192 * Error code when a configure option has no name 193 */ 194define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37); 195 196/** 197 * Error code when a file in the filelist has an invalid role 198 */ 199define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38); 200 201/** 202 * Error code when a file in the filelist has no role 203 */ 204define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39); 205 206/** 207 * Error code when analyzing a php source file that has parse errors 208 */ 209define('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 */ 215define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41); 216 217/** 218 * Error code when an unknown channel is specified 219 */ 220define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42); 221 222/** 223 * Error code when no files are found in the filelist 224 */ 225define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43); 226 227/** 228 * Error code when a file is not valid php according to _analyzeSourceCode() 229 */ 230define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44); 231 232/** 233 * Error code when the channel validator returns an error or warning 234 */ 235define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45); 236 237/** 238 * Error code when a php5 package is packaged in php4 (analysis doesn't work) 239 */ 240define('PEAR_PACKAGEFILE_ERROR_PHP5', 46); 241 242/** 243 * Error code when a file is listed in package.xml but does not exist 244 */ 245define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47); 246 247/** 248 * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne") 249 */ 250define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48); 251 252/** 253 * Error code when a package.xml contains non-ISO-8859-1 characters 254 */ 255define('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 */ 260define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50); 261 262/** 263 * Error code when a package has no lead developer 264 */ 265define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51); 266 267/** 268 * Error code when a filename begins with "." 269 */ 270define('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.8.1 279 * @link http://pear.php.net/package/PEAR 280 * @since Class available since Release 1.4.0a1 281 */ 282class 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" …
Large files files are truncated, but you can click here to view the full file