/** * Retrieves the generic information. * * Finds out what the name and value is of this constant on top of the information found using the * DocBlox_Reflection_DocBlockedAbstract parent method. * * @param DocBlox_Reflection_TokenIterator $tokens * * @see DocBlox_Reflection_DocBlockedAbstract::processGenericInformation * * @return void */ protected function processGenericInformation(DocBlox_Reflection_TokenIterator $tokens) { if ($tokens->current()->content == 'define') { // find the first encapsed string and strip the opening and closing // apostrophe $name_token = $tokens->gotoNextByType(T_CONSTANT_ENCAPSED_STRING, 5, array(',')); if (!$name_token) { $this->log('Unable to process constant in file ' . $tokens->getFilename() . ' at line ' . $tokens->current()->getLineNumber(), DocBlox_Core_Log::CRIT); return; } $this->setName(substr($name_token->content, 1, -1)); // skip to after the comma while ($tokens->current()->content != ',') { if ($tokens->next() === false) { break; } } // get everything until the closing brace and use that for value, take child parenthesis under consideration $value = ''; $level = 0; while (!($tokens->current()->content == ')' && $level == -1)) { if ($tokens->next() === false) { break; } switch ($tokens->current()->content) { case '(': $level++; break; case ')': $level--; break; } $value .= $tokens->current()->content; } $this->setValue(trim(substr($value, 0, -1))); } else { // Added T_NAMESPACE in case anyone uses a constant name NAMESPACE in PHP // 5.2.x and tries to parse the code in 5.3.x $this->setName($tokens->gotoNextByType(array(T_STRING, T_NAMESPACE), 10, array('='))->content); $this->setValue($this->findDefault($tokens)); } parent::processGenericInformation($tokens); }
/** * Retrieve the name of the class starting from the T_CLASS token. * * @param DocBlox_Reflection_TokenIterator $tokens * * @return string */ protected function extractClassName(DocBlox_Reflection_TokenIterator $tokens) { // a class name can be a combination of a T_NAMESPACE and T_STRING $name = ''; $limits = array(';', '{', ','); /** @var DocBlox_Token $token */ while ($token = $tokens->next()) { if (in_array($token->content, $limits) || strlen(trim($name)) >= 1 && $token->type == T_WHITESPACE) { $tokens->previous(); break; } $name .= $token->content; } return trim($name); }
/** * Generic method which iterates through all tokens between the braces following the current position in the token * iterator. * * Please note: This method will also move the cursor position in the token iterator forward. * When a token is encountered this method will invoke the processToken method, which is defined in the * DocBlox_Reflection_Abstract class. Literals are ignored. * * @see DocBlox_Reflection_Abstract * * @param DocBlox_Reflection_TokenIterator $tokens * * @return int[] */ public function processTokens(DocBlox_Reflection_TokenIterator $tokens) { $level = -1; $start = 0; $end = 0; $token = null; // parse class contents $this->debug('>> Processing tokens'); while ($tokens->valid()) { /** @var DocBlox_Reflection_Token $token */ $token = $token === null ? $tokens->current() : $tokens->next(); $token_type = false; $token_content = false; if ($token instanceof DocBlox_Reflection_Token) { $token_type = $token->type; $token_content = $token->content; } // if we encounter a semi-colon before we have an opening brace then this is an abstract or interface function // which have no body; stop looking! if ($token_type === null && $token_content === ';' && $level === -1) { return array($start, $end); } if ($token_type == T_CURLY_OPEN || $token_type == T_DOLLAR_OPEN_CURLY_BRACES) { $token_content = '{'; } // determine where the 'braced' section starts and end. // the first open brace encountered is considered the opening brace for the block and processing will // be 'breaked' when the closing brace is encountered if ((!$token_type || $token_type == T_CURLY_OPEN || $token_type == T_DOLLAR_OPEN_CURLY_BRACES) && ($token_content == '{' || $token_content == '}')) { switch ($token_content) { case '{': // expect the first brace to be an opening brace if ($level == -1) { $level++; $start = $tokens->key(); } $level++; break; case '}': if ($level == -1) { continue; } $level--; // reached the end; break from the while if ($level === 0) { $end = $tokens->key(); break 2; // time to say goodbye } break; } continue; } if ($token && $token_type) { // if a token is encountered and it is not a literal, invoke the processToken method $this->processToken($token, $tokens); } } // return the start and end token index return array($start, $end); }
/** * Processes the T_USE token and extracts all namespace aliases. * * @param DocBlox_Reflection_TokenIterator $tokens Tokens to interpret with the * pointer at the token to be processed. * * @return void */ protected function processUse(DocBlox_Reflection_TokenIterator $tokens) { /** @var DocBlox_Reflection_Token $token */ $aliases = array(''); while (($token = $tokens->next()) && $token->content != ';') { // if a comma is found, go to the next alias if (!$token->type && $token->content == ',') { $aliases[] = ''; continue; } $aliases[count($aliases) - 1] .= $token->content; } $result = array(); foreach ($aliases as $key => $alias) { // an AS is always surrounded by spaces; by trimming the $alias we // then know that the first element is the namespace and the last // is the alias. // We explicitly do not use spliti to prevent regular expressions // for performance reasons (the AS may be any case). $alias = explode(' ', trim($alias)); // if there is only one part, that means no AS is given and the // last segment of the namespace functions as alias. if (count($alias) == 1) { $alias_parts = explode('\\', $alias[0]); $alias[] = $alias_parts[count($alias_parts) - 1]; } $result[$alias[count($alias) - 1]] = $alias[0]; unset($aliases[$key]); } $this->namespace_aliases = array_merge($this->namespace_aliases, $result); }