PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/app/siteinvoice/lib/PEAR/PEAR/PackageFile/v1.php

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