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