PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file v1.php

Documentation is available at v1.php

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

Documentation generated on Wed, 06 Jul 2011 23:31:28 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.