private function processObject($object, SimpleXMLIterator $xml) { $attributes = $object; foreach ($attributes as $name => $attribute) { $xml->addAttribute($name, $attribute); } $attributes = ["class" => null]; $reflection = new \ReflectionObject($object); $attributes = $this->extractDocComments($reflection->getDocComment()); foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { if ($comment = $property->getDocComment()) { preg_match_all("/@(?'annotation'[^\\s]+)\\s+(?'value'[^\\s]+)+/m", $comment, $results); if (!empty($result)) { foreach ($results as $result) { $attributes[$result["annotation"]] = $result["value"]; } var_dump($comment, $result); } } } foreach ($attributes as $name => $attribute) { $xml->addAttribute($name, $attribute); } return $attributes; }
/** * Displays an information about single aspect * * @param SymfonyStyle $io Input-output style * @param Aspect $aspect Instance of aspect */ private function showAspectInfo(SymfonyStyle $io, Aspect $aspect) { $refAspect = new \ReflectionObject($aspect); $aspectName = $refAspect->getName(); $io->section($aspectName); $io->writeln('Defined in: <info>' . $refAspect->getFileName() . '</info>'); $docComment = $refAspect->getDocComment(); if ($docComment) { $io->writeln($this->getPrettyText($docComment)); } $this->showAspectPointcutsAndAdvisors($io, $aspect); }
protected function getDocumentationForConfig($config) { $configReflection = new ReflectionObject($config); $comment = $configReflection->getDocComment(); $descriptions = array(); preg_match_all('/^\\s?\\*\\s?@property-read\\s+[a-z]+\\s+([a-z_]+)\\s+(.+)/m', $comment, $matches); foreach ($matches[0] as $index => $match) { $propertyName = $matches[1][$index]; $description = $matches[2][$index]; $descriptions[$propertyName] = $this->parseDescription($description); } $configOptionsProperty = $configReflection->getProperty('options'); $configOptionsProperty->setAccessible(true); /** @var UTCW_Type[] $options */ $options = $configOptionsProperty->getValue($config); $result = array(); foreach ($options as $optionName => $option) { if (!isset($descriptions[$optionName])) { throw new Exception('Option ' . $optionName . ' is missing its description'); } $description = $descriptions[$optionName]; // Don't add internal properties if ($description === '@internal') { continue; } $result[] = sprintf('## %s ##', $this->keyToName($optionName)); $result[] = sprintf('Description: %s ', $descriptions[$optionName]); $result[] = sprintf('Type: %s ', $this->typeName(get_class($option))); $result[] = sprintf('Name: `%s` ', $optionName); $result[] = sprintf('Default: %s ', $this->defaultDescription($option->getDefaultValue())); if ($option instanceof UTCW_SetType) { $setReflection = new ReflectionObject($option); $setOptionsProperty = $setReflection->getProperty('options'); $setOptionsProperty->setAccessible(true); $setOptions = $setOptionsProperty->getValue($option); $result[] = sprintf('Valid values: `%s` ', join('`, `', $setOptions['values'])); } if ($option instanceof UTCW_ClassType) { $classReflection = new ReflectionObject($option); $classOptionsProperty = $classReflection->getProperty('options'); $classOptionsProperty->setAccessible(true); $classOptions = $classOptionsProperty->getValue($option); $classMap = $classOptions['classMap']; $result[] = sprintf('Predefined values: `%s` ', join('`, `', array_keys($classMap))); $result[] = sprintf('Predefined classes: `%s` ', join('`, `', $classMap)); $result[] = sprintf('Base class to extend: `%s` ', $classOptions['baseClass']); } $result[] = sprintf('Shortcode example: `[utcw %s=%s]` ', $optionName, $this->generateExample($option)); $result[] = ''; } return $result; }
/** * Tries to find the controller for the given route */ public function actionFindRoute() { $comment = ""; $route = $_POST['AAuthOperation']['name']; list($controller, $actionId) = Yii::app()->createController($route); if (!is_object($controller)) { // no such controller if (substr($route, -2, 2) == "/*") { $route = substr($route, 0, -2); list($controller, $actionId) = Yii::app()->createController($route); if (is_object($controller) && is_object($controller->module)) { $reflection = new ReflectionObject($controller->module); $comment = strtr(trim(preg_replace('/^\\s*\\**( |\\t)?/m', '', trim(trim($reflection->getDocComment()), '/'))), "\r", ''); if (preg_match('/^\\s*@\\w+/m', $comment, $matches, PREG_OFFSET_CAPTURE)) { $comment = trim(substr($comment, 0, $matches[0][1])); } } } } else { if ($actionId == "") { $actionId = $controller->defaultAction; } $reflection = new ReflectionObject($controller); if ($actionId == "*") { $comment = strtr(trim(preg_replace('/^\\s*\\**( |\\t)?/m', '', trim(trim($reflection->getDocComment()), '/'))), "\r", ''); if (preg_match('/^\\s*@\\w+/m', $comment, $matches, PREG_OFFSET_CAPTURE)) { $comment = trim(substr($comment, 0, $matches[0][1])); } } else { if ($reflection->hasMethod("action" . $actionId)) { $action = $reflection->getMethod("action" . $actionId); $comment = strtr(trim(preg_replace('/^\\s*\\**( |\\t)?/m', '', trim(trim($action->getDocComment()), '/'))), "\r", ''); if (preg_match('/^\\s*@\\w+/m', $comment, $matches, PREG_OFFSET_CAPTURE)) { $comment = trim(substr($comment, 0, $matches[0][1])); } } } } $response = array("comment" => $comment, "url" => $this->createAbsoluteUrl($route)); header("Content-type: application/json"); echo json_encode($response); }
/** * Invoke * * @return string */ public function invoke() { SCA::$logger->log('Entering'); //component_name, string reference_name, string method_name, array arguments // Reflection::export(new ReflectionObject($this->mediator)); try { // get the arguments from the mediator $arg_array = $this->mediator->getArgArray(); if ($this->class_name != null) { SCA::$logger->log('Attempt to create a service'); $this->service = new $this->class_name(); $reflection = new ReflectionObject($this->service); $reader = new SCA_CommentReader($reflection->getDocComment()); // if it's an SCA service recreate the instance // with all the references filled in if ($reader->isService()) { SCA::$logger->log('Create SCA service'); $this->service = SCA::createInstanceAndFillInReferences($this->class_name); } else { SCA::$logger->log('Create PHP object'); } } //invoke the function if ($this->service != null) { SCA::$logger->log('Invoke service as PHP object'); // it's a class with a member function // so call it. Even if it's an SCA service // we are not relying of SCA service bindings // at this point. We just want the references // that will have been set up on initialization // above. $return = call_user_func_array(array($this->service, $this->method_name), $arg_array); } else { if (function_exists($this->method_name)) { SCA::$logger->log('Invoke service as PHP function'); // it's not just a script so turn // off output buffering and then call // the function ob_end_clean(); $return = call_user_func_array($this->method_name, $arg_array); } else { SCA::$logger->log('Invoke service as PHP script'); // the script will have already executed // because it was included so all we have to // do here is return the contents of the // output buffer. $return = ob_get_contents(); ob_end_clean(); } } } catch (Exception $e) { SCA::$logger->log('Caught ' . $e->getMessage()); throw $e; } SCA::$logger->log('Exiting'); return $return; }
function quicky_modifier_debug_print_var($var, $charset = 'utf-8', $depth = 1, $length = 40) { $countForCollapse = 5; if ($depth > 10) { return ' max depth !!! '; } $_replace = array("\n" => '<i>\\n</i>', "\r" => '<i>\\r</i>', "\t" => '<i>\\t</i>'); $hache = 'i' . substr(md5(serialize($var) . rand(0, 1000) . $depth), 3, 12); switch (gettype($var)) { case 'array': $count = count($var); $results = '<span class="active" onclick="toggle(\'' . $hache . '\'); toggle(\'' . $hache . '_close\');"><b>Array</b> (' . $count . ') <span id="' . $hache . '_close" ' . ($count <= $countForCollapse ? 'style="display:none;"' : '') . ' class="collapse_title">[...]</span></span>'; $results .= '<span id="' . $hache . '" class="collapseble" ' . ($count > $countForCollapse ? 'style="display:none;"' : '') . '>'; foreach ($var as $curr_key => $curr_val) { $results .= '<br>' . str_repeat(' ', $depth * 2) . '<i>' . strtr($curr_key, $_replace) . '</i> => ' . quicky_modifier_debug_print_var($curr_val, $charset, $depth + 1, 20); } $results .= '</span>'; break; case 'object': $reflectionObject = new ReflectionObject($var); $properties = $reflectionObject->getProperties(ReflectionProperty::IS_PUBLIC); $desc = iconv('utf-8', $charset, htmlspecialchars($reflectionObject->getDocComment())); $desc = str_replace(array('"', ' ', "\n", "\r", "\t"), array('\\"', ' ', '<br/>', ' '), $desc); $methods = $reflectionObject->getMethods(ReflectionMethod::IS_PUBLIC); $count = count($properties) + count($methods); $results = '<span title="' . $desc . '" class="nobr active" onclick="toggle(\'' . $hache . '\'); toggle(\'' . $hache . '_close\');"><b>' . get_class($var) . '</b> Object (vars: ' . count($properties) . ' / methods: ' . count($methods) . ') <span id="' . $hache . '_close" ' . ($count <= $countForCollapse ? 'style="display:none;"' : '') . ' class="collapse_title">{...}</span></span>'; $results .= '<span id="' . $hache . '" class="collapseble" ' . ($count > $countForCollapse ? 'style="display:none;"' : '') . '>'; foreach ($properties as $propertyReflection) { /* @var $propertyReflection ReflectionProperty */ $desc = iconv('utf-8', $charset, htmlspecialchars($propertyReflection->getDocComment())); $desc = str_replace(array('"', ' ', "\n", "\r", "\t"), array('\\"', ' ', '<br/>', ' '), $desc); $results .= '<br>' . str_repeat(' ', $depth * 2) . '<span class="nobr" title="' . $desc . '"><i> ->' . strtr($propertyReflection->getName(), $_replace) . '</i></span> = ' . quicky_modifier_debug_print_var($propertyReflection->getValue($var), $charset, $depth + 1, 20); } foreach ($methods as $methodReflection) { /* @var $methodReflection ReflectionMethod */ $args = array(); foreach ($methodReflection->getParameters() as $param) { /* @var $param ReflectionParameter */ $argument = $param->getName(); if ($param->isArray()) { $argument = 'array ' . $argument; } elseif ($param->getClass()) { $argument = $param->getClass()->getName() . ' ' . $argument; } if ($param->isPassedByReference()) { $argument = '&' . $argument; } if ($param->isOptional()) { if ($param->isDefaultValueAvailable()) { $defData = str_replace(array(' ', "\n", "\r", "\t"), '', var_export($param->getDefaultValue(), 1)); /** @see http://bugs.php.net/bug.php?id=33312 */ if (!empty($defData)) { $argument = $argument . '=' . $defData; } } $argument = '[' . $argument . ']'; } $args[] = $argument; } $desc = iconv('utf-8', $charset, $methodReflection->getDocComment()); if (!$desc) { $desc = $methodReflection->getDocComment(); } $desc = str_replace(array('"', ' ', "\n", "\r", "\t"), array('\\"', ' ', '<br/>', ' '), htmlspecialchars($desc)); $results .= '<br>' . str_repeat(' ', $depth * 2) . '<span class="nobr" title="' . $desc . '"><b> -> function</b> ' . $methodReflection->getName() . '(' . implode(', ', $args) . ')</span>'; } $results .= '</span>'; break; case 'boolean': case 'NULL': case 'resource': if (true === $var) { $results = 'true'; } elseif (false === $var) { $results = 'false'; } elseif (null === $var) { $results = 'null'; } else { $results = htmlspecialchars((string) $var); } $results = '<i>' . $results . '</i>'; break; case 'integer': case 'float': $results = htmlspecialchars((string) $var); break; case 'unknown type': default: $results = (string) $var; if (strlen($results) > $length) { $results = '<span id="' . $hache . '_close" class="active nobr collapse_title" onclick="toggle(\'' . $hache . '_close\'); toggle(\'' . $hache . '\');">' . strtr(htmlspecialchars(substr($results, 0, $length - 3)), $_replace) . '... (' . strlen($results) . ')' . '</span>' . '<span id="' . $hache . '" style="display:none;" class="active collapseble" onclick="toggle(\'' . $hache . '_close\'); toggle(\'' . $hache . '\');">' . strtr(htmlspecialchars($results), $_replace) . '</span>' . '<script> function f' . $hache . '_new_window(){ window.open("", "", "width=880, height=600, resizable, scrollbars=yes").document.write("<textarea rows=40 cols=80>' . str_replace(array("\n", "\r"), array('\\n', '\\r'), htmlspecialchars($results, ENT_QUOTES, $charset)) . '</textarea>"); return false; } </script> <span class="active" onclick="return f' . $hache . '_new_window();" title="open in new window">' . '¤' . '</span>'; } } return $results; }
/** * does the actual collection of data about available services * @return array of AmfphpDiscovery_ServiceInfo */ public function discover() { $serviceNames = $this->getServiceNames(self::$serviceFolders, self::$serviceNames2ClassFindInfo); $ret = array(); foreach ($serviceNames as $serviceName) { $serviceObject = Amfphp_Core_Common_ServiceRouter::getServiceObjectStatically($serviceName, self::$serviceFolders, self::$serviceNames2ClassFindInfo); $objR = new ReflectionObject($serviceObject); $objComment = $this->formatComment($objR->getDocComment()); if (false !== strpos($objComment, '@amfphpHide')) { //methods including @amfHide should not appear in the back office but should still be accessible. continue; } $methodRs = $objR->getMethods(ReflectionMethod::IS_PUBLIC); $methods = array(); foreach ($methodRs as $methodR) { $methodName = $methodR->name; if (substr($methodName, 0, 1) == '_') { //methods starting with a '_' as they are reserved, so filter them out continue; } $parameters = array(); $paramRs = $methodR->getParameters(); $methodComment = $this->formatComment($methodR->getDocComment()); if (false !== strpos($methodComment, '@amfphpHide')) { //methods including @amfHide should not appear in the back office but should still be accessible. continue; } $parsedMethodComment = $this->parseMethodComment($methodComment); foreach ($paramRs as $paramR) { $parameterName = $paramR->name; //get type from type hinting or from parsed method comment. type hinting has priority $type = ''; //get example from parsed method comment only $example = ''; if (isset($parsedMethodComment['param'][$parameterName])) { $paramMeta = $parsedMethodComment['param'][$parameterName]; if (isset($paramMeta['type'])) { $type = $paramMeta['type']; } if (isset($paramMeta['example'])) { $example = $paramMeta['example']; } } try { //this code will throw an exception saying that the class does not exist, only if the class is a namespace. //in that case there's not much that can be done, so just ignore type. if ($paramR->getClass()) { $type = $paramR->getClass()->name; } } catch (Exception $e) { } $parameterInfo = new AmfphpDiscovery_ParameterDescriptor($parameterName, $type, $example); $parameters[] = $parameterInfo; } //get return from parsed return comment if exists $return = ''; if (isset($parsedMethodComment['return'])) { $return = $parsedMethodComment['return']; } $methods[$methodName] = new AmfphpDiscovery_MethodDescriptor($methodName, $parameters, $methodComment, $return); } $ret[$serviceName] = new AmfphpDiscovery_ServiceDescriptor($serviceName, $methods, $objComment); } //note : filtering must be done at the end, as for example excluding a Vo class needed by another creates issues foreach ($ret as $serviceName => $serviceObj) { foreach (self::$excludePaths as $excludePath) { if (strpos($serviceName, $excludePath) !== false) { unset($ret[$serviceName]); break; } } } return $ret; }
/** * Process to get reflection from file * * @return void * @throws ComponentException */ public function process() { // workaround for get reflection of closure function $bootstrap = $view = $module = $controller = null; /** @var \Closure|object $closure */ $closure = (include $this->file); if (!is_callable($closure)) { throw new ComponentException("There is no callable structure in file `{$this->file}`"); } if ($closure instanceof \Closure) { $reflection = new \ReflectionFunction($closure); } else { $reflection = new \ReflectionObject($closure); } // check and normalize params by doc comment $docComment = $reflection->getDocComment(); // get all options by one regular expression if (preg_match_all('/\\s*\\*\\s*\\@([a-z0-9-_]+)\\s+(.*).*\\s+/i', $docComment, $matches)) { foreach ($matches[1] as $i => $key) { $this->setOption($key, $matches[2][$i]); } } // init routes $this->initRoute(); // parameters available for Closure only if ($reflection instanceof \ReflectionFunction) { // get params and convert it to simple array $reflectionParams = $reflection->getParameters(); // setup params and optional params foreach ($reflectionParams as $param) { $name = $param->getName(); // if some function params is missed in description if (!isset($this->params[$name])) { $this->params[$name] = null; } if ($param->isOptional()) { $this->values[$name] = $param->getDefaultValue(); } } } }
/** * does the actual collection of data about available services * @return array of AmfphpDiscovery_ServiceInfo */ public function discover() { $serviceNames = $this->getServiceNames(self::$serviceFolderPaths, self::$serviceNames2ClassFindInfo); $ret = array(); foreach ($serviceNames as $serviceName) { $serviceObject = Amfphp_Core_Common_ServiceRouter::getServiceObjectStatically($serviceName, self::$serviceFolderPaths, self::$serviceNames2ClassFindInfo); $objR = new ReflectionObject($serviceObject); $objComment = $objR->getDocComment(); $methodRs = $objR->getMethods(ReflectionMethod::IS_PUBLIC); $methods = array(); foreach ($methodRs as $methodR) { $methodName = $methodR->name; if (substr($methodName, 0, 1) == '_') { //methods starting with a '_' as they are reserved, so filter them out continue; } $parameters = array(); $paramRs = $methodR->getParameters(); $methodComment = $methodR->getDocComment(); $parsedMethodComment = $this->parseMethodComment($methodComment); foreach ($paramRs as $paramR) { $parameterName = $paramR->name; $type = ''; if ($paramR->getClass()) { $type = $paramR->getClass()->name; } else { if (isset($parsedMethodComment['param'][$parameterName])) { $type = $parsedMethodComment['param'][$parameterName]; } } $parameterInfo = new AmfphpDiscovery_ParameterDescriptor($parameterName, $type); $parameters[] = $parameterInfo; } $methods[$methodName] = new AmfphpDiscovery_MethodDescriptor($methodName, $parameters, $methodComment, $parsedMethodComment['return']); } $ret[$serviceName] = new AmfphpDiscovery_ServiceDescriptor($serviceName, $methods, $objComment); } //note : filtering must be done at the end, as for example excluding a Vo class needed by another creates issues foreach ($ret as $serviceName => $serviceObj) { foreach (self::$excludePaths as $excludePath) { if (strpos($serviceName, $excludePath) !== false) { unset($ret[$serviceName]); break; } } } return $ret; }
/** * @param $param * @param \ReflectionObject $reflection */ private function buildFromObject($param, $reflection = null) { foreach ($param as $key => $value) { $this->object['Object default'][$key] = $value; } // Get info on the object $this->object['Reflection']['In namespace'] = $reflection->inNamespace() ? 'Yes' : 'No'; if ($reflection->inNamespace()) { $this->object['Class namespace'] = $reflection->getNamespaceName(); } $this->object['Reflection']['Class name'] = $reflection->getName(); $this->object['Reflection']['Is internal'] = $reflection->isInternal() ? 'Yes' : 'No'; $this->object['Reflection']['Is iterable'] = $reflection->isIterateable() ? 'Yes' : 'No'; $this->object['Reflection']['Is abstract'] = $reflection->isAbstract() ? 'Yes' : 'No'; $this->object['Reflection']['Is final'] = $reflection->isFinal() ? 'Yes' : 'No'; $this->object['Reflection']['Is user defined'] = $reflection->isUserDefined() ? 'Yes' : 'No'; $this->object['Reflection']['Is instantiable'] = $reflection->isInstantiable() ? 'Yes' : 'No'; $this->object['Reflection']['Is clonable'] = $reflection->isCloneable() ? 'Yes' : 'No'; $this->object['Reflection']['Is interface'] = $reflection->isInterface() ? 'Yes' : 'No'; $this->object['Reflection']['Class constants'] = !empty($reflection->getConstants()) ? $reflection->getConstants() : 'Class has no constants'; $this->object['Reflection']['Class static properties'] = !empty($reflection->getStaticProperties()) ? $reflection->getStaticProperties() : 'Class has no static properties'; $this->object['Reflection']['Class default properties'] = !empty($reflection->getDefaultProperties()) ? $reflection->getDefaultProperties() : 'Class has no default properties'; if (null === $reflection->getConstructor()) { $this->object['Reflection']['Class construct'] = 'Class has no construct.'; } else { $this->object['Reflection']['Class construct'] = $reflection->getConstructor(); } $this->object['Reflection']['Class interfaces'] = !empty($reflection->getInterfaces()) ? $reflection->getInterfaces() : 'Class implements no interfaces'; $this->object['Reflection']['Class traits'] = !empty($reflection->getTraits()) ? $reflection->getTraits() : 'Class has no traits'; $this->object['Reflection']['Class parent'] = $reflection->getParentClass() !== false ? $reflection->getParentClass() : 'Class has no parent'; if (false === $reflection->getFileName()) { $this->object['Reflection']['Defined in'] = 'Class is internal, no definition to provide.'; } else { $this->object['Reflection']['Defined in'] = $reflection->getFileName(); } if (false === $reflection->getFileName()) { $this->object['Reflection']['Start line'] = 'Class is internal, no start line to provide.'; } else { $this->object['Reflection']['Start line'] = $reflection->getFileName(); } if (false === $reflection->getEndLine()) { $this->object['Reflection']['End line'] = 'Class is internal, no end line to provide.'; } else { $this->object['Reflection']['End line'] = $reflection->getEndLine(); } if (false === $reflection->getDocComment()) { $this->object['Reflection']['Doc comments'] = 'No documents to provide.'; } else { $this->object['Reflection']['Doc comments'] = $reflection->getDocComment(); } // End get info $this->html .= "<span class=\"js-parent-object\">"; if (!empty($this->object['Object default'])) { $this->html .= "<div class=\"js-object-default-tab \"><button class=\"button-reflection button\">Show reflection</button></div>"; $this->html .= "<div class=\"js-object-default \">"; $this->buildFromObjectIterationInformationRecursive($this->object['Object default']); $this->html .= "</div>"; } if ($param instanceof \Closure) { $this->html .= "<div class=\"js-object-default-tab \"><button class=\"button-reflection button\">Show reflection</button></div>"; $this->html .= "<div class=\"js-object-default \">"; $this->html .= "<span class=\"css-type-string\">Nothing here...</span>"; $this->html .= "</div>"; } $this->html .= "<div class=\"js-object-reflection-tab hide\"><button class=\"button-class-default button\">Show default</button></div>"; $this->html .= "<div class=\"js-object-reflection hide\">"; $this->buildFromObjectReflectionInformationRecursive($this->object['Reflection']); $this->html .= "</div>"; $this->html .= "</span>"; $this->object = []; }
/** * @param \ReflectionObject $reflection */ private static function is($reflection, $annotation) { $refComments = $reflection->getDocComment(); if (preg_match('/@' . $annotation . '/', $refComments)) { return true; } return false; }
private function _getDocBlock($obj) { if (is_string($obj)) { /** * Obj is either a function or a class name. */ if (function_exists($obj)) { /** * Obj is a function name. */ $reflection = new ReflectionFunction($obj); $docblock = $reflection->getDocComment(); } elseif (class_exists($obj, false)) { /** * Obj is a class name. */ $reflection = new ReflectionClass($obj); $docblock = $reflection->getDocComment(); } else { throw new Exception('Invalid class or function name.'); } } elseif (is_array($obj)) { /** * Check for "call_user_func()" syntax. */ if (is_string($obj[0]) || is_object($obj)) { /** * Static method format. */ $reflection = new ReflectionMethod($obj[0], $obj[1]); $docblock = $reflection->getDocComment(); } else { /** * Unknown array object passed. */ throw new Exception('Got unknown object type.'); } } elseif (is_object($obj)) { /** * Obj is an object instance. */ $reflection = new ReflectionObject($obj); $docblock = $reflection->getDocComment(); } if ($docblock === false) { $docblock = ''; } return $docblock; }
/** * Get annotation * @param string $name * return string */ public function getAnnotation($name) { if ($this->annotations === NULL) { $this->annotations = array(); $reflection = new ReflectionObject($this); $doc = $reflection->getDocComment(); $matches = array(); if (preg_match_all('/@([a-zA-Z]+)([^*]+)\\*/', $doc, $matches)) { for ($i = 0, $size = sizeof($matches[1]); $i < $size; $i++) { $this->annotations[$matches[1][$i]] = trim($matches[2][$i]); } } } return isset($this->annotations[$name]) ? $this->annotations[$name] : NULL; }