*/ namespace Phacil\Framework; /** * PHPDoc Parser * * Simple example usage: * @example $a = new Parser($string); $a->parse(); * * @package Phacil\Framework * @since 2.0.0 */ class PHPDocParser { /** * The PHPDoc string that we want to parse * @var string */ private $string; /** * Storge for the short description * @var string */ private $shortDesc; /** * Storge for the long description * * @var string */ private $longDesc; /** * Storge for all the PHPDoc parameters * * @var array */ private $params = []; /** * Parse each line * * Takes an array containing all the lines in the string and stores * the parsed information in the object properties * * @param array $lines An array of strings to be parsed */ private function parseLines($lines) { foreach($lines as $line) { $parsedLine = $this->parseLine($line); //Parse the line if($parsedLine === false && empty($this->shortDesc)) { if(isset($desc) && is_array($desc)) $this->shortDesc = implode(PHP_EOL, $desc); //Store the first line in the short description $desc = array(); } elseif($parsedLine !== false) { $desc[] = $parsedLine; //Store the line in the long description } } $this->longDesc = implode(PHP_EOL, $desc); } /** * Parse the line * * Takes a string and parses it as a PHPDoc comment * * @param string $line The line to be parsed * @return string|bool|array False if the line contains no parameters or paramaters that aren't valid otherwise, the line that was passed in. */ private function parseLine($line) { //Trim the whitespace from the line $line = trim($line); if(empty($line)) return false; //Empty line if(strpos($line, '@') === 0) { $param = substr($line, 1, strpos($line, ' ') - 1); //Get the parameter name $value = substr($line, strlen($param) + 2); //Get the value if($this->setParam($param, $value)) return false; //Parse the line and return false if the parameter is valid } return $line; } /** * Setup the valid parameters * * @param string $type NOT USED */ private function setupParams($type = "") { $params = array( "access" => '', "author" => '', "copyright" => '', "deprecated"=> '', "example" => '', "ignore" => '', "internal" => '', "link" => '', "param" => '', "return" => '', "see" => '', "since" => '', "tutorial" => '', "version" => '', 'throws' => '', 'todo' => '' ); $this->params = $params; } /** * Parse a parameter or string to display in simple typecast display * * @param string $string The string to parse * @return string Formatted string wiht typecast */ private function formatParamOrReturn($string) { //$pos = strpos($string, ' '); $parts = preg_split('/\s+/', $string, 3, PREG_SPLIT_NO_EMPTY); //$type = substr($string, 0, $pos); if(count($parts) == 3) { $return = [ $parts[1] => [ 'type' => (strpos($parts[0], '|')) ? explode('|',$parts[0]) : $parts[0], 'desc' => $parts[2] ] ]; } elseif (count($parts) == 2) { $return = [ $parts[1] => [ 'type' => (strpos($parts[0], '|')) ? explode('|', $parts[0]) : $parts[0] ] ]; } elseif (count($parts) == 1) { $return = (strpos($parts[0], '|')) ? explode('|', $parts[0]) : $parts[0]; } else { $return = '';} //return '(' . $type . ')' . substr($string, $pos+1); return $return; } /** * Set a parameter * * @param string $param The parameter name to store * @param string $value The value to set * @return bool True = the parameter has been set, false = the parameter was invalid */ private function setParam($param, $value) { if (!array_key_exists($param, $this->params)) $this->params[$param] = ''; if ($param == 'param' || $param == 'return') $value = $this->formatParamOrReturn($value); if (empty($this->params[$param])) { $this->params[$param] = $value; } elseif (is_array($this->params[$param])) { $this->params[$param] = array_merge($this->params[$param], (is_array($value) ? $value : array($value))); } elseif (is_string($this->params[$param])) { $this->params[$param] = array($this->params[$param], $value); } return true; } /** * Setup the initial object * * @param string $string The string we want to parse */ public function __construct($string) { $this->string = $string; //$this->setupParams(); } /** * Parse the string * @return void */ public function parse() { //Get the comment if(preg_match('#^/\*\*(.*)\*/#s', $this->string, $comment) === false) die("Error"); $comment = trim($comment[1]); //Get all the lines and strip the * from the first character if(preg_match_all('#^\s*\*(.*)#m', $comment, $lines) === false) die('Error'); $this->parseLines($lines[1]); } /** * Get the short description * * @return string The short description */ public function getShortDesc() { return $this->shortDesc; } /** * Get the long description * * @return string The long description */ public function getDesc() { return $this->longDesc; } /** * Get the parameters * * @return array The parameters */ public function getParams() { return $this->params; } /** * @param string $key * @return mixed */ public function get($key){ return ($this->$key) ?: null; } }