예제 #1
0
 /**
  * Test a function or method for a given class
  *
  * @dataProvider dataReflectionTestFunctions
  *
  * @param string|array $function The function name, or array of class name and method name.
  */
 public function testFunction($function)
 {
     // We can't pass Reflector objects in here because they get printed out as the
     // data set when a test fails
     if (is_array($function)) {
         $ref = new \ReflectionMethod($function[0], $function[1]);
         $name = $function[0] . '::' . $function[1] . '()';
     } else {
         $ref = new \ReflectionFunction($function);
         $name = $function . '()';
     }
     $docblock = new \phpDocumentor\Reflection\DocBlock($ref);
     $doc_comment = $ref->getDocComment();
     $method_params = $ref->getParameters();
     $doc_params = $docblock->getTagsByName('param');
     $this->assertNotFalse($doc_comment, sprintf('The docblock for `%s` should not be missing.', $name));
     $this->assertNotEmpty($docblock->getShortDescription(), sprintf('The docblock description for `%s` should not be empty.', $name));
     $this->assertSame(count($method_params), count($doc_params), sprintf('The number of @param docs for `%s` should match its number of parameters.', $name));
     // @TODO check description ends in full stop
     foreach ($method_params as $i => $param) {
         $param_doc = $doc_params[$i];
         $description = $param_doc->getDescription();
         $content = $param_doc->getContent();
         // @TODO decide how to handle variadic functions
         // ReflectionParameter::isVariadic — Checks if the parameter is variadic
         $is_hash = 0 === strpos($description, '{') && strlen($description) - 1 === strrpos($description, '}');
         if ($is_hash) {
             $lines = explode("\n", $description);
             $description = $lines[1];
         }
         $this->assertNotEmpty($description, sprintf('The @param description for the `%s` parameter of `%s` should not be empty.', $param_doc->getVariableName(), $name));
         list($param_doc_type, $param_doc_name) = preg_split('#\\s+#', $param_doc->getContent());
         $this->assertSame('$' . $param->getName(), $param_doc_name, sprintf('The @param name for the `%s` parameter of `%s` is incorrect.', '$' . $param->getName(), $name));
         if ($param->isArray()) {
             $this->assertNotFalse(strpos($param_doc_type, 'array'), sprintf('The @param type hint for the `%s` parameter of `%s` should state that it accepts an array.', $param_doc->getVariableName(), $name));
         }
         if (($param_class = $param->getClass()) && 'stdClass' !== $param_class->getName()) {
             $this->assertNotFalse(strpos($param_doc_type, $param_class->getName()), sprintf('The @param type hint for the `%s` parameter of `%s` should state that it accepts an object of type `%s`.', $param_doc->getVariableName(), $name, $param_class->getName()));
         }
         $this->assertFalse(strpos($param_doc_type, 'callback'), sprintf('`callback` is not a valid type. `callable` should be used in the @param type hint for the `%s` parameter of `%s` instead.', $param_doc->getVariableName(), $name));
         if ($param->isCallable()) {
             $this->assertNotFalse(strpos($param_doc_type, 'callable'), sprintf('The @param type hint for the `%s` parameter of `%s` should state that it accepts a callable.', $param_doc->getVariableName(), $name));
         }
         if ($param->isOptional()) {
             $this->assertNotFalse(strpos($description, 'Optional.'), sprintf('The @param description for the optional `%s` parameter of `%s` should state that it is optional.', $param_doc->getVariableName(), $name));
         } else {
             $this->assertFalse(strpos($description, 'Optional.'), sprintf('The @param description for the required `%s` parameter of `%s` should not state that it is optional.', $param_doc->getVariableName(), $name));
         }
         if ($param->isDefaultValueAvailable() && array() !== $param->getDefaultValue()) {
             $this->assertNotFalse(strpos($description, 'Default '), sprintf('The @param description for the `%s` parameter of `%s` should state its default value.', $param_doc->getVariableName(), $name));
         } else {
             $this->assertFalse(strpos($description, 'Default '), sprintf('The @param description for the `%s` parameter of `%s` should not state a default value.', $param_doc->getVariableName(), $name));
         }
     }
 }
예제 #2
0
 /**
  * Scans this class for any method containing the @phpdoc-event tag and
  * connects it to the event dispatcher.
  *
  * The @phpdoc-event tag has as description the name of the event to
  * connect to. When encountered will that event be linked to the associated
  * method.
  *
  * It is thus important that such a method has a single argument $event of
  * type sfEvent. This contains the arguments that were dispatched.
  *
  * @return void
  */
 protected function connectHooksToDispatcher()
 {
     $refl = new \ReflectionObject($this);
     // connect all events of the each method to the event_dispatcher
     /** @var \ReflectionMethod $method */
     foreach ($refl->getMethods() as $method) {
         if (!$method->getDocComment()) {
             continue;
         }
         $docblock = new \phpDocumentor\Reflection\DocBlock($method->getDocComment());
         /** @var \phpDocumentor\Reflection\DocBlock\Tag $event */
         foreach ($docblock->getTagsByName('phpdoc-event') as $event) {
             $this->event_dispatcher->addListener($event->getDescription(), array($this, $method->getName()));
         }
     }
 }
예제 #3
0
 /**
  * Factory depuis une reflection
  *
  * @param ReflectionProperty $reflection
  * @return static
  */
 public static function fromReflection(ReflectionProperty $reflection)
 {
     // gestion du type
     $type = implode('|', $reflection->getDocBlockTypeStrings());
     // cas de la valeur null
     $value = $reflection->getDefaultValue();
     if (is_null($value)) {
         $value = Maker::NO_VALUE;
         $class = $reflection->getDeclaringClass();
         foreach ($class->getAst()->stmts as $stmt) {
             // si pas un attribut, on zap
             if (!$stmt instanceof \PhpParser\Node\Stmt\Property) {
                 continue;
             }
             foreach ($stmt->props as $prop) {
                 if ($prop instanceof \PhpParser\Node\Stmt\PropertyProperty) {
                     // lecture du fichier
                     $file = file($class->getFileName());
                     if (!empty($line = $file[$prop->getLine() - 1])) {
                         if (strpos($line, '=')) {
                             $value = null;
                         }
                     }
                 }
             }
         }
     }
     // construction
     $property = new static($reflection->getName(), $value, $type);
     // docblock
     $docblock = new \phpDocumentor\Reflection\DocBlock($reflection->getDocComment());
     $property->setSummary($docblock->getShortDescription());
     $property->setDescription($docblock->getLongDescription());
     // gestion des modifiers
     $reflection->isPrivate() ? $property->enablePrivate() : $property->disablePrivate();
     $reflection->isProtected() ? $property->enableProtected() : $property->disabledProtected();
     $reflection->isPublic() ? $property->enablePublic() : $property->disablePublic();
     $reflection->isStatic() ? $property->enableStatic() : $property->disableStatic();
     return $property;
 }
예제 #4
0
 protected function loadClassMethods(\ReflectionClass $reflectedObject)
 {
     $this->classMethods = array();
     $classMethods = $reflectedObject->getMethods();
     if (!empty($classMethods)) {
         foreach ($classMethods as $classMethod) {
             $reflectedMethod = $reflectedObject->getMethod($classMethod->name);
             $method = new Object\Method();
             $method->setName($reflectedMethod->getName());
             $method->setLevel($this->level + 1);
             // static
             if ($reflectedMethod->isStatic()) {
                 $method->setStatic();
             }
             // visibility
             if ($reflectedMethod->isPublic()) {
                 $method->setVisibility(Object\VisibilityInterface::VISIBILITY_PUBLIC);
                 $this->publicMethodsNumber++;
             } elseif ($reflectedMethod->isProtected()) {
                 $method->setVisibility(Object\VisibilityInterface::VISIBILITY_PROTECTED);
                 $this->protectedMethodsNumber++;
             } elseif ($reflectedMethod->isPrivate()) {
                 $method->setVisibility(Object\VisibilityInterface::VISIBILITY_PRIVATE);
                 $this->privateMethodsNumber++;
             }
             // phpdoc comment
             if (class_exists('\\phpDocumentor\\Reflection\\DocBlock')) {
                 $phpdoc = new \phpDocumentor\Reflection\DocBlock($reflectedMethod->getDocComment());
                 $method->setShortDescription($phpdoc->getShortDescription());
                 $method->setLongDescription($phpdoc->getLongDescription());
             }
             // parameters
             $methodParameters = $reflectedMethod->getParameters();
             foreach ($methodParameters as $methodParameterReflected) {
                 $methodParameter = new Object\MethodParameter();
                 $methodParameter->setName($methodParameterReflected->getName());
                 $class = $methodParameterReflected->getClass();
                 if ($class instanceof \ReflectionClass) {
                     $methodParameter->setType($class->getName());
                 } elseif ($methodParameterReflected->isArray()) {
                     $methodParameter->setType('array');
                 }
                 if ($methodParameterReflected->isPassedByReference()) {
                     $methodParameter->setReference();
                 }
                 if ($methodParameterReflected->isDefaultValueAvailable()) {
                     $default = $methodParameterReflected->getDefaultValue();
                     $defaultValueType = $this->factory->factory($default, $this->level + 1);
                     $methodParameter->setDefaultValue($defaultValueType);
                 }
                 $method->addMethodParameter($methodParameter);
             }
             $this->classMethods[] = $method;
         }
     }
     // order methods
     usort($this->classMethods, function (Object\Method $methodA, Object\Method $methodB) {
         $orderValueA = $methodA->getVisibility() . $methodA->getName();
         $orderValueB = $methodB->getVisibility() . $methodB->getName();
         return strcasecmp($orderValueA, $orderValueB);
     });
 }
예제 #5
0
파일: Maker.php 프로젝트: frenchfrogs/maker
 /**
  * Analyse $class for extract self content
  *
  * @return $this
  */
 protected function reflect()
 {
     $reflection = $this->getClass();
     // docblock
     $docblock = new \phpDocumentor\Reflection\DocBlock($reflection->getDocComment());
     $this->setSummary($docblock->getShortDescription());
     $this->setDescription($docblock->getLongDescription());
     // NAMESPACE
     $namespace = $reflection->getNamespaceName();
     if (!empty($namespace)) {
         $this->setNamespace($namespace);
     }
     // ALIAS
     $file = $reflection->getFileName();
     $this->setFilename($file);
     // lecture du fichier
     if (file_exists($file)) {
         $file = file($file);
         //Première lignes du fichier
         foreach (array_slice($file, 0, $reflection->getStartLine()) as $line) {
             // analyse de partern d'alias
             if (preg_match('#use (?<class>[^\\s^;]+)(\\s+as\\s+(?<alias>[^\\s^;]+))?\\s*;?#', $line, $match)) {
                 $class = $match['class'];
                 $alias = empty($match['alias']) ? collect(explode('\\', $class))->last() : $match['alias'];
                 $this->addAlias($alias, $class);
             }
         }
     }
     // PARENT CLASS
     $parent = $reflection->getParentClass();
     if (!empty($parent)) {
         $this->setParent($parent->getName());
     }
     // CONSTANT
     $this->setConstants($reflection->getConstants());
     // PROPERTIES
     foreach ($reflection->getProperties() as $property) {
         $this->addProperty(Property::fromReflection($property));
     }
     // METHODS
     foreach ($reflection->getImmediateMethods() as $method) {
         $this->addMethod(Method::fromReflection($method));
     }
     return $this;
 }
예제 #6
0
 public function beforeTraverse(array $nodes)
 {
     $node = null;
     $key = 0;
     foreach ($nodes as $k => $n) {
         if (!$n instanceof \PHPParser_Node_Stmt_InlineHTML) {
             $node = $n;
             $key = $k;
             break;
         }
     }
     if ($node) {
         $comments = (array) $node->getAttribute('comments');
         // remove non-DocBlock comments
         $comments = array_values(array_filter($comments, function ($comment) {
             return $comment instanceof \PHPParser_Comment_Doc;
         }));
         if (!empty($comments)) {
             $docblock = new \phpDocumentor\Reflection\DocBlock((string) $comments[0]);
             // the first DocBlock in a file documents the file if
             // * it precedes another DocBlock or
             // * it contains a @package tag and doesn't precede a class
             //   declaration or
             // * it precedes a non-documentable element (thus no include,
             //   require, class, function, define, const)
             if (count($comments) > 1 || !$node instanceof \PHPParser_Node_Stmt_Class && $docblock->hasTag('package') || !$this->isNodeDocumentable($node)) {
                 $docblock->line_number = $comments[0]->getLine();
                 $this->doc_block = $docblock;
                 // remove the file level DocBlock from the node's comments
                 $comments = array_slice($comments, 1);
             }
         }
         // always update the comments attribute so that standard comments
         // do not stop DocBlock from being attached to an element
         $node->setAttribute('comments', $comments);
         $nodes[$key] = $node;
     }
     \phpDocumentor\Plugin\EventDispatcher::getInstance()->dispatch('reflection.docblock-extraction.post', \phpDocumentor\Reflection\Events\PostDocBlockExtractionEvent::createInstance($this)->setDocblock($this->doc_block));
     return $nodes;
 }
예제 #7
0
 /**
  * Displays available options and parameters this component offers.
  *
  * @apiMethod GET
  * @apiUri    /
  * @return    void
  */
 public function indexTask()
 {
     // var to hold output
     $output = new stdClass();
     $output->component = substr($this->_option, 4);
     $bits = explode('v', get_class($this));
     $output->version = str_replace('_', '.', end($bits));
     $output->tasks = array();
     $output->errors = array();
     // create reflection class of file
     $classReflector = new ReflectionClass($this);
     // loop through each method and process doc
     foreach ($classReflector->getMethods() as $method) {
         // create docblock object & make sure we have something
         $phpdoc = new \phpDocumentor\Reflection\DocBlock($method);
         // skip constructor
         if (substr($method->getName(), -4) != 'Task' || in_array($method->getName(), array('registerTask', 'unregisterTask'))) {
             continue;
         }
         // skip method in the parent class (already processed),
         /*if ($className != $method->getDeclaringClass()->getName())
         		{
         			//continue;
         		}*/
         // skip if we dont have a short desc
         // but put in error
         if (!$phpdoc->getShortDescription()) {
             $output->errors[] = sprintf('Missing docblock for method "%s" in "%s"', $method->getName(), str_replace(PATH_ROOT, '', $classReflector->getFileName()));
             continue;
         }
         // create endpoint data array
         $endpoint = array('name' => substr($method->getName(), 0, -4), 'description' => preg_replace('/\\s+/', ' ', $phpdoc->getShortDescription()), 'method' => '', 'uri' => '', 'parameters' => array());
         // loop through each tag
         foreach ($phpdoc->getTags() as $tag) {
             // get tag name and content
             $name = strtolower(str_replace('api', '', $tag->getName()));
             $content = $tag->getContent();
             // handle parameters separately
             // json decode param input
             if ($name == 'parameter') {
                 $parameter = json_decode($content);
                 if (json_last_error() != JSON_ERROR_NONE) {
                     $output->errors[] = sprintf('Unable to parse parameter info for method "%s" in "%s"', $method->getName(), str_replace(PATH_ROOT, '', $classReflector->getFileName()));
                     continue;
                 }
                 $endpoint['parameters'][] = (array) $parameter;
                 continue;
             }
             if ($name == 'uri' && $method->getName() == 'indexTask') {
                 $content .= $output->component;
             }
             // add data to endpoint data
             $endpoint[$name] = $content;
         }
         // add endpoint to output
         $output->tasks[] = $endpoint;
     }
     if (count($output->errors) <= 0) {
         unset($output->errors);
     }
     $this->send($output);
 }
 /**
  * @param $route
  * @return array
  */
 private function addRouteDefinition(\DC\Router\IRoute $route)
 {
     $path = $this->simplifyPathForSwagger($route->getPath());
     $method = strtolower($route->getMethod());
     $callable = $route->getCallable();
     $reflection = $this->reflector->getReflectionFunctionForCallable($callable);
     if ($reflection instanceof \ReflectionMethod) {
         if (!$reflection->getDeclaringClass()->implementsInterface('\\DC\\Router\\Swagger\\ISwaggerAPI')) {
             return;
         }
     }
     $phpdoc = new \phpDocumentor\Reflection\DocBlock($reflection);
     if (count($phpdoc->getTagsByName(SwaggerExcludeTag::$name)) > 0) {
         return;
     }
     $routeDef = ["produces" => ["application/json"], "responses" => []];
     if ($method == "post" || $method == "put") {
         $routeDef["consumes"] = ["application/json"];
     }
     if ($reflection instanceof \ReflectionMethod) {
         $reflectionClass = $reflection->getDeclaringClass();
         $routeDef["tags"] = [$this->addTagForController($reflectionClass)];
     }
     $parameters = $this->routeMatcher->getParameterInfo($route);
     $paramTags = $phpdoc->getTagsByName("param");
     $reflectionParameters = $reflection->getParameters();
     $reflectionParametersByName = [];
     foreach ($reflectionParameters as $parameter) {
         $reflectionParametersByName[$parameter->getName()] = $parameter;
     }
     foreach ($parameters as $parameter) {
         $matchingParamTags = array_filter($paramTags, function ($t) use($parameter) {
             return $t->getVariableName() == '$' . $parameter->getInternalName();
         });
         $paramTag = reset($matchingParamTags);
         $reflectionParameter = $reflectionParametersByName[$parameter->getInternalName()];
         $required = !isset($reflectionParameter) || !$reflectionParameter->isOptional();
         $paramDef = ["name" => $parameter->getQueryName(), "in" => $parameter->getPlacement(), "required" => $required];
         if ($paramTag != null) {
             $paramDef["description"] = $paramTag->getDescription();
             $paramDef += $this->getTypeDefinition($paramTag->getType());
         } else {
             $paramDef["type"] = "string";
         }
         $routeDef["parameters"][] = $paramDef;
     }
     /**
      * @var $returnTag \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag[]
      */
     $returnTag = $phpdoc->getTagsByName("return");
     if (count($returnTag) > 0) {
         $returnTypes = $returnTag[0]->getTypes();
         if (!isset($returnTypes)) {
             $returnTypes = [$returnTag[0]->getType()];
         }
         foreach ($returnTypes as $type) {
             $defRef = $this->getTypeDefinitionOrReference($type);
             $routeDef["responses"][200] = ["schema" => $defRef, "description" => $returnTag[0]->getDescription()];
         }
     }
     /** @var $throwsTags \phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag[] */
     $throwsTags = $phpdoc->getTagsByName("throws");
     if (count($throwsTags) > 0) {
         foreach ($throwsTags as $throwsTag) {
             $type = $throwsTag->getType();
             $defRef = $this->getTypeDefinitionOrReference($type);
             $routeDef["responses"][500] = ["schema" => $defRef, "description" => $throwsTag->getDescription()];
         }
     }
     $routeDef["summary"] = $phpdoc->getShortDescription();
     $description = $phpdoc->getLongDescription()->getContents();
     if (strlen($description) > 0) {
         $routeDef["description"] = $description;
     }
     $this->def['paths'][$path][$method] = $routeDef;
 }
예제 #9
0
 /**
  *
  *
  * @param ReflectionMethod $reflection
  * @return Method
  */
 public static function fromReflection(ReflectionMethod $reflection)
 {
     // gestion du type
     //       $type = implode('|', $reflection->getDocBlockTypeStrings());
     //
     // construction
     $method = new static($reflection->getName(), [], $reflection->getBodyCode());
     // docblock
     $docblock = new \phpDocumentor\Reflection\DocBlock($reflection->getDocComment());
     $method->setSummary($docblock->getShortDescription());
     $method->setDescription($docblock->getLongDescription());
     // gestion des modifiers
     $reflection->isPrivate() ? $method->enablePrivate() : $method->disablePrivate();
     $reflection->isProtected() ? $method->enableProtected() : $method->disabledProtected();
     $reflection->isPublic() ? $method->enablePublic() : $method->disablePublic();
     $reflection->isStatic() ? $method->enableStatic() : $method->disableStatic();
     $reflection->isFinal() ? $method->enableFinal() : $method->disableFinal();
     foreach ($reflection->getParameters() as $parameter) {
         $method->addParameter(Parameter::fromReflection($parameter));
     }
     return $method;
 }
예제 #10
0
 public static function getPropsAsStringByReflectionMethod(\ReflectionMethod $method, $withoutValues = false)
 {
     $props = array();
     if ($method->getDocComment()) {
         $docComment = new \phpDocumentor\Reflection\DocBlock($method->getDocComment());
         foreach ($docComment->getTags() as $tag) {
             /* @var $tag \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag */
             if ($tag->getName() == "param") {
                 $props[] = self::getInstance()->getValueByType($tag->getType(), $withoutValues);
             }
         }
     } else {
         foreach ($method->getParameters() as $parameter) {
             //                    var_dump($parameter->getDefaultValue());
             //                  var_dump($parameter->getDefaultValueConstantName());
             $param = \ReflectionParameter::export(array($parameter->getDeclaringClass()->name, $parameter->getDeclaringFunction()->name), $parameter->name, true);
             preg_match('/(\\[ )(<)(.*)(>)( )([^\\]=]+)/', $param, $matches);
             if (count($matches) === 7) {
                 $t = explode(" ", trim($matches[6]));
                 if (count($t) === 2) {
                     if (strtolower($t[0]) == "array") {
                         return 'array()';
                     }
                     if (strtolower($t[0]) == "closure") {
                         return 'function(){}';
                     }
                     $props[] = '$this->getMock(\'' . str_replace('\\', '\\\\', $t[0]) . '\')';
                 } else {
                     if ($parameter->isDefaultValueAvailable()) {
                         $props[] = $parameter->getDefaultValue();
                     } else {
                         $props[] = 1;
                     }
                 }
             }
         }
     }
     $props2 = array();
     foreach ($props as $prop2) {
         if ($prop2 != "") {
             $props2[] = $prop2;
         }
     }
     return implode(",", $props2);
 }