/** * Return a single method by given name or index of info * * @param string|int $methodNameOrInfoIndex * @throws Exception\InvalidArgumentException * @return MethodScanner */ public function getMethod($methodNameOrInfoIndex) { $this->scan(); if (is_int($methodNameOrInfoIndex)) { $info = $this->infos[$methodNameOrInfoIndex]; if ($info['type'] != 'method') { throw new Exception\InvalidArgumentException('Index of info offset is not about a method'); } } elseif (is_string($methodNameOrInfoIndex)) { $methodFound = false; foreach ($this->infos as $info) { if ($info['type'] === 'method' && $info['name'] === $methodNameOrInfoIndex) { $methodFound = true; break; } } if (!$methodFound) { return false; } } if (!isset($info)) { // @todo find a way to test this die('Massive Failure, test this'); } $m = new MethodScanner(array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1), $this->nameInformation); $m->setClass($this->name); $m->setScannerClass($this); return $m; }
/** * Return a list of methods * * @return MethodScanner[] */ public function getMethods() { $this->scan(); if (!empty($this->methods)) { return $this->methods; } foreach ($this->infos as $info) { if ($info['type'] !== 'method' && $info['type'] !== 'use') { continue; } // Merge in trait methods if ($info['type'] === "use") { $traitMethods = []; $traits = $this->getTraits(); $insteadof = $this->getBlockedTraitMethods(); $aliases = $this->getTraitAliases(); foreach ($traits as $trait) { $tempMethods = $trait->getMethods(); foreach ($tempMethods as $tempMethod) { $methodFullName = $trait->getName() . '::' . $tempMethod->getName(); $methodAlias = array_search($methodFullName, $aliases); if (false !== $methodAlias) { // trait::method is aliased // clone the tempMethod as we need to change // the name and possibly the visibility of the // scanned method. // // @todo setName and setVisibility were added to // MethodScanner to accomplish this, may not be the // best option, could use ReflectionClass instead? $newMethod = clone $tempMethod; $newMethod->setName($methodAlias); // if visibility exists, change it on the MethodScanner $visibility = $this->getVisibilityForAlias($methodAlias); if (null !== $visibility) { $newMethod->setVisibility($visibility); } $traitMethods[$methodAlias] = $newMethod; } elseif (in_array($methodFullName, $insteadof)) { // ignore overridden methods continue; } else { if (array_key_exists($tempMethod->getName(), $traitMethods)) { throw new Exception\RuntimeException(sprintf('Trait method %s has not been applied because there are' . ' collisions with other trait methods see: (insteadof OR as)', $tempMethod->getName())); } $traitMethods[$tempMethod->getName()] = $tempMethod; } } } $this->methods = array_merge($this->methods, array_values($traitMethods)); continue; } $m = new MethodScanner(array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1), $this->nameInformation); $m->setClass($this->name); $m->setScannerClass($this); $this->methods[] = $m; } return $this->methods; }
protected function processParams(&$def, DerivedClassScanner $sClass, MethodScanner $sMethod) { if (count($sMethod->getParameters()) === 0) { return; } $methodName = $sMethod->getName(); $def['parameters'][$methodName] = array(); foreach ($sMethod->getParameters(true) as $position => $p) { /** @var $p \Zend\Code\Scanner\ParameterScanner */ $actualParamName = $p->getName(); $paramName = $this->createDistinctParameterName($actualParamName, $sClass->getName()); $fqName = $sClass->getName() . '::' . $sMethod->getName() . ':' . $position; $def['parameters'][$methodName][$fqName] = array(); // set the class name, if it exists $def['parameters'][$methodName][$fqName][] = $actualParamName; $def['parameters'][$methodName][$fqName][] = ($p->getClass() !== null) ? $p->getClass() : null; $def['parameters'][$methodName][$fqName][] = !$p->isOptional(); } }
/** * Builds a method object based on the provided method scanner * * @param MethodScanner $classMethod * @return Method */ protected function buildMethod(MethodScanner $classMethod) { $method = new Method($classMethod->getName()); $method->setNumberOfParameters($classMethod->getNumberOfParameters()); // Loop through annotations if ($annotations = $classMethod->getAnnotations($this->annotationManager)) { foreach ($annotations as $annotation) { // @todo annotations should implement some kind of interface? if (method_exists($annotation, 'decorateObject')) { $annotation->decorateObject($method); } } } return $method; }
/** * Return the parameters for a method * * 3 item array: * #1 - Class name, string if it exists, else null * #2 - Optional?, boolean * #3 - Instantiable, boolean if class exists, otherwise null * * @return array */ public function compileScannerInjectionMethodParmeters(MethodScanner $methodScanner, $introspectionType) { $params = array(); $parameterScanners = $methodScanner->getParameters(true); // rules according to type $rules = $this->getIntrospectionRuleset()->getRules($introspectionType); /* @var $p Zend\Code\Scanner\ParameterScanner */ foreach ($parameterScanners as $p) { $paramName = $p->getName(); // create array for this parameter $params[$paramName] = array(); // get name, and class if it exists $pcName = $p->getClass(); if ($this->directoryScanner->hasClass($pcName)) { $pc = $this->directoryScanner->getClass($pcName); } if ($pcName) { // @todo Should we throw an exception if its an unknown type? $params[$paramName][] = $pcName; } else { $params[$paramName][] = null; } if ($introspectionType == IntrospectionRuleset::TYPE_SETTER && $rules['paramCanBeOptional']) { $params[$paramName][] = true; } else { $params[$paramName][] = $p->isOptional(); } if (isset($pc)) { $params[$paramName][] = ($pc->isInstantiable()) ? true : false; } else { $params[$paramName][] = null; } } return $params; }