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