public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { // description if (null === $annotation->getDescription()) { $comments = explode("\n", $annotation->getDocumentation()); // just set the first line $comment = trim($comments[0]); $comment = preg_replace("#\n+#", ' ', $comment); $comment = preg_replace('#\\s+#', ' ', $comment); $comment = preg_replace('#[_`*]+#', '', $comment); if ('@' !== substr($comment, 0, 1)) { $annotation->setDescription($comment); } } // requirements $requirements = $annotation->getRequirements(); foreach ($route->getRequirements() as $name => $value) { if (!isset($requirements[$name]) && '_method' !== $name && '_scheme' !== $name) { $requirements[$name] = array('requirement' => $value, 'dataType' => '', 'description' => ''); } if ('_scheme' === $name) { $https = 'https' == $value; $annotation->setHttps($https); } } if (method_exists($route, 'getSchemes')) { $annotation->setHttps(in_array('https', $route->getSchemes())); } $paramDocs = array(); foreach (explode("\n", $this->commentExtractor->getDocComment($method)) as $line) { if (preg_match('{^@param (.+)}', trim($line), $matches)) { $paramDocs[] = $matches[1]; } if (preg_match('{^@deprecated\\b(.*)}', trim($line), $matches)) { $annotation->setDeprecated(true); } if (preg_match('{^@link\\b(.*)}', trim($line), $matches)) { $annotation->setLink($matches[1]); } } $regexp = '{(\\w*) *\\$%s\\b *(.*)}i'; foreach ($route->compile()->getVariables() as $var) { $found = false; foreach ($paramDocs as $paramDoc) { if (preg_match(sprintf($regexp, preg_quote($var)), $paramDoc, $matches)) { $requirements[$var]['dataType'] = isset($matches[1]) ? $matches[1] : ''; $requirements[$var]['description'] = $matches[2]; if (!isset($requirements[$var]['requirement'])) { $requirements[$var]['requirement'] = ''; } $found = true; break; } } if (!isset($requirements[$var]) && false === $found) { $requirements[$var] = array('requirement' => '', 'dataType' => '', 'description' => ''); } } $annotation->setRequirements($requirements); }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { foreach ($annotations as $annot) { if ($annot instanceof Secure || $annot instanceof PreAuthorize) { $annotation->setAuthentication(true); } } }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { foreach ($annotations as $annot) { if ($annot instanceof Cache) { $annotation->setCache($annot->getMaxAge()); } } }
/** * {@inheritdoc} */ public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { if (!$route->getOption('old_options')) { return; } $annotation->setDeprecated(true); $annotation->setDocumentation($annotation->getDocumentation() . "\n\nDeprecated since v1.8. Will be removed in v2.0"); }
/** * @param array $documentation * * @return array */ public function create(array $documentation) { $apiDoc = new ApiDoc($documentation); if (array_key_exists('route', $documentation) === true) { $apiDoc->setRoute($this->router->getRouteCollection()->get($documentation['route'])); } return array(self::KEY_ANNOTATION => $apiDoc, self::KEY_RESOURCE => $documentation[self::KEY_RESOURCE]); }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { foreach ($annotations as $annot) { if ($annot instanceof PreAuthorize) { $annotation->setAuthentication(true); } elseif ($annot instanceof Secure) { $annotation->setAuthentication(true); $annotation->setAuthenticationRoles(is_array($annot->roles) ? $annot->roles : explode(',', $annot->roles)); } } }
/** * Parse route parameters in order to populate ApiDoc. * * @param \Nelmio\ApiDocBundle\Annotation\ApiDoc $annotation * @param array $annotations * @param \Symfony\Component\Routing\Route $route * @param \ReflectionMethod $method */ public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { if (!$annotation instanceof \Itkg\ApiDocBundle\Annotation\ApiDoc) { return; } $content = ''; foreach ($annotation->getResources() as $resource) { if (!file_exists($file = sprintf('%s/%s', $this->rootPath, $resource))) { throw new NotFoundHttpException(sprintf('Resources file %s does not exist', $file)); } $content .= $this->parser->text(file_get_contents($file)); } $annotation->setResourcesContent($content); }
/** * @return array */ public function toArray() { $data = parent::toArray(); $data['resources'] = $this->resources; $data['resourcesContent'] = $this->resourcesContent; return $data; }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { foreach ($annotations as $annot) { if ($annot instanceof RequestParam) { $annotation->addParameter($annot->name, array('required' => $annot->strict && $annot->default === null, 'dataType' => $annot->requirements, 'description' => $annot->description, 'readonly' => false)); } elseif ($annot instanceof QueryParam) { if ($annot->strict && $annot->default === null) { $annotation->addRequirement($annot->name, array('requirement' => $annot->requirements, 'dataType' => '', 'description' => $annot->description)); } elseif ($annot->default !== null) { $annotation->addFilter($annot->name, array('requirement' => $annot->requirements, 'description' => $annot->description, 'default' => $annot->default)); } else { $annotation->addFilter($annot->name, array('requirement' => $annot->requirements, 'description' => $annot->description)); } } } }
/** * {@inheritdoc} */ public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { if ($route->getOption('group') !== DictionaryEntityRouteOptionsResolver::ROUTE_GROUP) { return; } $pluralAlias = $route->getDefault(DictionaryEntityRouteOptionsResolver::ENTITY_ATTRIBUTE); if (!$pluralAlias) { return; } $className = $this->entityAliasResolver->getClassByPluralAlias($pluralAlias); $pluralName = $this->entityClassNameProvider->getEntityClassPluralName($className); if ($pluralName) { $annotation->setDescription(strtr(static::DESCRIPTION_TEMPLATE, ['{plural_name}' => $pluralName])); $annotation->setDocumentation(strtr(static::DOCUMENTATION_TEMPLATE, ['{plural_name}' => $pluralName])); } else { $annotation->setDescription(strtr(static::FALLBACK_DESCRIPTION_TEMPLATE, ['{class}' => $className])); $annotation->setDocumentation(strtr(static::FALLBACK_DOCUMENTATION_TEMPLATE, ['{class}' => $className])); } }
/** * @inheritdoc */ public function __construct(array $data) { if (isset($data['value'])) { if (isset($data['value']['default'])) { $data = array_merge($data['value']['default'], $data['value']); } else { $data = $data['value']; } } parent::__construct($data); }
/** * @inheritdoc */ public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { foreach ($annotations as $annot) { if ($annot instanceof RequestParam) { $requirements = $this->handleRequirements($annot->requirements); $data = array('required' => $annot->strict && $annot->nullable === false && $annot->default === null, 'dataType' => $requirements . ($annot->array ? '[]' : ''), 'actualType' => $this->inferType($requirements), 'subType' => null, 'description' => $annot->description, 'readonly' => false); if ($annot->strict === false) { $data['default'] = $annot->default; } $annotation->addParameter($annot->name, $data); } elseif ($annot instanceof QueryParam) { if ($annot->strict && $annot->nullable === false && $annot->default === null) { $annotation->addRequirement($annot->name, array('requirement' => $this->handleRequirements($annot->requirements) . ($annot->array ? '[]' : ''), 'dataType' => '', 'description' => $annot->description)); } elseif ($annot->default !== null) { $annotation->addFilter($annot->name, array('requirement' => $this->handleRequirements($annot->requirements) . ($annot->array ? '[]' : ''), 'description' => $annot->description, 'default' => $annot->default)); } else { $annotation->addFilter($annot->name, array('requirement' => $this->handleRequirements($annot->requirements) . ($annot->array ? '[]' : ''), 'description' => $annot->description)); } } } }
/** * {@inheritdoc} */ public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { foreach ($annotations as $description) { if (!$description instanceof ApiDescription) { continue; } $current = $annotation->toArray(); $request = []; foreach ($description->getRequest() as $name => $field) { $request[$name] = $this->convertField($field); } $annotation->setParameters(array_merge($annotation->getParameters(), $request)); if (!isset($current['response'])) { $response = []; foreach ($description->getResponse() as $name => $field) { $response[$name] = $this->convertField($field); } $annotation->setResponse($response); } } }
public function __construct(array $data) { parent::__construct($data); if (isset($data['method'])) { $this->method = $data['method']; } else { $this->method = 'ANY'; } if (isset($data['uri'])) { $this->uri = $data['uri']; } else { throw new \LogicException('@ApiDoc annotation should contain required parameter "uri".'); } }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { if ($method->name == 'cgetAction' && (is_subclass_of($method->class, 'KwfBundle\\Controller\\FOSRestModelController') || $method->class == 'KwfBundle\\Controller\\FOSRestModelController')) { $annotation->addParameter('limit', array('required' => true, 'dataType' => 'int', 'default' => '25')); $annotation->addParameter('start', array('required' => true, 'dataType' => 'int', 'default' => '0')); $annotation->addParameter('sort', array('required' => false, 'dataType' => 'string', 'default' => '')); $annotation->addParameter('query', array('required' => false, 'dataType' => 'string', 'default' => null)); $annotation->addParameter('filter', array('required' => false, 'dataType' => 'json string', 'default' => null)); } }
/** * {@inheritdoc} */ public function formatOne(ApiDoc $annotation) { return $this->renderOne($this->processAnnotation($annotation->toArray())); }
public function testSetRoute() { $route = new Route('/path/{foo}', ['foo' => 'bar', 'nested' => ['key1' => 'value1', 'key2' => 'value2']], [], [], '{foo}.awesome_host.com'); $apiDoc = new ApiDoc([]); $apiDoc->setRoute($route); $this->assertSame($route, $apiDoc->getRoute()); $this->assertEquals('bar.awesome_host.com', $apiDoc->getHost()); $this->assertEquals('ANY', $apiDoc->getMethod()); }
public function testConstructWithRequestAndResponseBodyAsFile() { $data = array('requestBody' => array('file' => __DIR__ . '/../Fixtures/Resources/doc/exampleBody.json'), 'responseBody' => array('file' => __DIR__ . '/../Fixtures/Resources/doc/exampleBody.json')); $annot = new ApiDoc($data); $array = $annot->toArray(); $this->assertTrue(is_array($array)); $this->assertTrue(!empty($array['requestBodyExample'])); $this->assertTrue(!empty($array['responseBodyExample'])); }
/** * @param $resource * @param ApiDoc $annotation * @param Resource|Resource $dunglasResource * @param Route $route * @return ApiDoc */ private function addFilters($resource, ApiDoc $annotation, Resource $dunglasResource, Route $route) { $data = $annotation->toArray(); $tags = isset($data['tags']) ? $data['tags'] : []; //filter embed if ('DELETE' !== $annotation->getMethod()) { $availableIncludes = $this->transformerHelper->getAvailableIncludes($resource); $defaultIncludes = $this->transformerHelper->getDefaultIncludes($resource); if (false === array_key_exists('embed', $tags)) { $annotation->addFilter('embed', ['requirement' => '\\t', 'description' => 'Include resources within other resources.', 'available' => is_array($availableIncludes) ? implode(',', $availableIncludes) : $availableIncludes, 'default' => is_array($defaultIncludes) ? implode(',', $defaultIncludes) : $defaultIncludes]); } else { unset($data['requirements']['embed']); $data['tags']['embed'] = "#298A08"; $path = explode('/', $route->getPath()); $embed = array_pop($path); $singularize = Inflector::singularize($embed); if ($embed !== $singularize) { $data['tags']['collection'] = "#0040FF"; } foreach ($data['requirements'] as $key => $value) { $data['requirements'][$key] = array_merge(['name' => $key], $value); } $annotation = new ApiDoc($data); $routeClone = clone $route; $annotation->setRoute($routeClone); $tags = isset($annotation->toArray()['tags']) ? $annotation->toArray()['tags'] : []; } } if (false !== array_key_exists('collection', $tags)) { foreach ($dunglasResource->getFilters() as $filter) { foreach ($filter->getDescription($dunglasResource) as $key => $value) { $annotation->addFilter($key, ['type' => isset($value['type']) ? $value['type'] : 'string', 'requirement' => isset($value['requirement']) ? $value['requirement'] : '[a-zA-Z0-9-]+', 'description' => isset($value['description']) ? $value['description'] : $key . ' filter', 'default' => '']); } } //filter perpage $annotation->addFilter('perpage', ['requirement' => '\\d+', 'description' => 'How many object return per page.', 'default' => 10]); //filter perpage $annotation->addFilter('page', ['requirement' => '\\d+', 'description' => 'How many page start to return.', 'default' => 1]); } return $annotation; }
/** * {@inheritdoc} */ public function formatOne(ApiDoc $annotation) { return $annotation->toArray(); }
/** * @param ApiDoc $doc * @return Route */ public function setDoc($doc) { $this->doc = $doc; $this->doc->setRoute($this); return $this; }
public function testConstructWithCache() { $data = array('cache' => '60'); $annot = new ApiDoc($data); $array = $annot->toArray(); $this->assertEquals($data['cache'], $array['cache']); }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { // description if (null === $annotation->getDescription()) { $comments = explode("\n", $annotation->getDocumentation()); // just set the first line $comment = trim($comments[0]); $comment = preg_replace("#\n+#", ' ', $comment); $comment = preg_replace('#\\s+#', ' ', $comment); $comment = preg_replace('#[_`*]+#', '', $comment); if ('@' !== substr($comment, 0, 1)) { $annotation->setDescription($comment); } } // schema if ($annotation->getSchema() !== null) { $path = 'file://' . realpath($this->schemaPath . $annotation->getSchema()); $properties = (array) json_decode(file_get_contents($path))->properties; $tab = []; foreach ($properties as $objectName => $property) { if (isset($property->properties)) { $tab = array_merge($tab, $annotation->schemaFormat($property->properties, $property->required, $objectName)); } else { $required = json_decode(file_get_contents($path))->required; $tab = array_merge($tab, $annotation->schemaFormat($properties, $required)); } } $annotation->setParameters($tab); } // requirements $requirements = $annotation->getRequirements(); foreach ($route->getRequirements() as $name => $value) { if (!isset($requirements[$name]) && '_method' !== $name && '_scheme' !== $name) { $requirements[$name] = array('requirement' => $value, 'dataType' => '', 'description' => ''); } if ('_scheme' === $name) { $https = 'https' == $value; $annotation->setHttps($https); } } if (method_exists($route, 'getSchemes')) { $annotation->setHttps(in_array('https', $route->getSchemes())); } $paramDocs = array(); foreach (explode("\n", $this->commentExtractor->getDocComment($method)) as $line) { if (preg_match('{^@param (.+)}', trim($line), $matches)) { $paramDocs[] = $matches[1]; } if (preg_match('{^@deprecated}', trim($line))) { $annotation->setDeprecated(true); } if (preg_match('{^@link (.+)}', trim($line), $matches)) { $annotation->setLink($matches[1]); } } $regexp = '{(\\w*) *\\$%s\\b *(.*)}i'; foreach ($route->compile()->getVariables() as $var) { $found = false; foreach ($paramDocs as $paramDoc) { if (preg_match(sprintf($regexp, preg_quote($var)), $paramDoc, $matches)) { $annotationRequirements = $annotation->getrequirements(); if (!isset($annotationRequirements[$var]['dataType'])) { $requirements[$var]['dataType'] = isset($matches[1]) ? $matches[1] : ''; } if (!isset($annotationRequirements[$var]['description'])) { $requirements[$var]['description'] = $matches[2]; } if (!isset($requirements[$var]['requirement']) && !isset($annotationRequirements[$var]['requirement'])) { $requirements[$var]['requirement'] = ''; } $found = true; break; } } if (!isset($requirements[$var]) && false === $found) { $requirements[$var] = array('requirement' => '', 'dataType' => '', 'description' => ''); } } $annotation->setRequirements($requirements); }
/** * Builds ApiDoc annotation from DunglasApiBundle data. * * @param bool $collection * @param ResourceInterface $resource * @param OperationInterface $operation * @param array $resourceHydraDoc * @param array $entrypointHydraDoc * * @return ApiDoc */ private function getApiDoc($collection, ResourceInterface $resource, OperationInterface $operation, array $resourceHydraDoc, array $entrypointHydraDoc = []) { $method = $operation->getRoute()->getMethods()[0]; if ($collection) { $operationHydraDoc = $this->getCollectionOperationHydraDoc($resource->getShortName(), $method, $entrypointHydraDoc); } else { $operationHydraDoc = $this->getOperationHydraDoc($operation->getRoute()->getMethods()[0], $resourceHydraDoc); } $route = $operation->getRoute(); $data = ['resource' => $route->getPath(), 'description' => $operationHydraDoc['hydra:title'], 'resourceDescription' => $resourceHydraDoc['hydra:title'], 'section' => $resourceHydraDoc['hydra:title']]; $entityClass = $resource->getEntityClass(); if (isset($operationHydraDoc['expects']) && 'owl:Nothing' !== $operationHydraDoc['expects']) { $data['input'] = sprintf('%s:%s', DunglasApiParser::IN_PREFIX, $entityClass); } if (isset($operationHydraDoc['returns']) && 'owl:Nothing' !== $operationHydraDoc['returns']) { $data['output'] = sprintf('%s:%s', DunglasApiParser::OUT_PREFIX, $entityClass); } if (Request::METHOD_GET === $method && $collection) { $data['filters'] = []; foreach ($resource->getFilters() as $filter) { foreach ($filter->getDescription($resource) as $name => $definition) { $data['filters'][] = ['name' => $name] + $definition; } } } $apiDoc = new ApiDoc($data); $apiDoc->setRoute($route); return $apiDoc; }
/** * Parses annotations for a given method, and adds new information to the given ApiDoc * annotation. Useful to extract information from the FOSRestBundle annotations. * * @param ApiDoc $annotation * @param Route $route * @param ReflectionMethod $method */ protected function parseAnnotations(ApiDoc $annotation, Route $route, \ReflectionMethod $method) { foreach ($this->reader->getMethodAnnotations($method) as $annot) { if (is_subclass_of($annot, self::FOS_REST_PARAM_CLASS)) { if ($annot->strict) { $annotation->addRequirement($annot->name, array('requirement' => $annot->requirements, 'type' => '', 'description' => $annot->description)); } else { $annotation->addFilter($annot->name, array('requirement' => $annot->requirements, 'description' => $annot->description)); } } } }
public function testAlignmentOfOutputAndResponseModels2() { $data = array('responseMap' => array(200 => 'FooBar', 400 => 'Foo\\ValidationErrorCollection')); $apiDoc = new ApiDoc($data); $map = $apiDoc->getResponseMap(); $this->assertCount(2, $map); $this->assertArrayHasKey(200, $map); $this->assertArrayHasKey(400, $map); $this->assertEquals($apiDoc->getOutput(), $map[200]); }
public function testConstructWithMultipleTags() { $data = array('tags' => array('experimental', 'alpha')); $annot = new ApiDoc($data); $array = $annot->toArray(); $this->assertTrue(is_array($array)); $this->assertTrue(is_array($array['tags']), 'Tags should be in array'); $this->assertEquals($data['tags'], $array['tags']); }
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method) { if (!($objectName = $route->getDefault('_jarves_object')) || !($object = $this->objects->getDefinition($objectName))) { return; } if ($entryPointPath = $route->getDefault('_jarves_entry_point')) { $adminUtils = new \Jarves\Admin\Utils($this->jarves); $entryPoint = $adminUtils->getEntryPoint($entryPointPath); $annotation->setSection(sprintf('%s %s %s', $entryPoint->isFrameworkWindow() ? 'Framework Window: ' : '', $entryPoint->getBundle() ? ($entryPoint->getBundle()->getLabel() ?: $entryPoint->getBundle()->getBundleName()) . ', ' : 'No Bundle, ', $entryPoint->getLabel() ?: $entryPoint->getPath())); } else { $objectKey = $route->getDefault('_jarves_object_section') ?: $route->getDefault('_jarves_object'); $objectSection = $this->objects->getDefinition($objectKey); $annotation->setSection(sprintf('Object %s', $objectKey)); } $filters = $annotation->getFilters(); if (@$filters['fields']) { $fields = []; foreach ($object->getFields() as $field) { if ('object' === $field->getId()) { $foreignObject = $this->objects->getDefinition($field->getObject()); foreach ($foreignObject->getFields() as $fField) { $filters[] = $field->getId() . '.' . $fField->getId(); } } else { $fields[] = $field->getId(); } } $annotation->addFilter('fields', ['requirement' => '.*', 'description' => "Comma separated list of fields. Possible fields to select: \n" . implode(', ', $fields)]); } $annotation->setDescription(str_replace('%object%', $object->getBundle()->getBundleName() . ':' . lcfirst($object->getId()), $annotation->getDescription())); $isRelationRoute = $route->getDefault('_jarves_object_relation'); $requirePk = $route->getDefault('_jarves_object_requirePk'); $method = explode(':', $route->getDefault('_controller'))[1]; // maybe in version 1.1 // if ($isRelationRoute) { // $objectKey = $route->getDefault('_jarves_object_section') ? : $route->getDefault('_jarves_object'); // $objectParent = $this->jarves->getObjects()->getDefinition($objectKey); // // foreach ($objectParent->getFields() as $field) { // if ($field->isPrimaryKey()) { // $annotation->addRequirement( // $field->getId(), // [ // 'requirement' => $field->getRequiredRegex(), // 'dataType' => $field->getPhpDataType(), // 'description' => '(' . $objectParent->getId() . ') ' . $field->getDescription() // ] // ); // } // } // } if ($requirePk) { foreach ($object->getFields() as $field) { if (!$field->hasFieldType()) { continue; } if ($field->isPrimaryKey()) { $annotation->addRequirement(($isRelationRoute ? lcfirst($object->getId()) . '_' : '') . $field->getId(), ['requirement' => $field->getRequiredRegex(), 'dataType' => $field->getPhpDataType(), 'description' => $isRelationRoute ? '(' . $object->getId() . ') ' : '']); } } } //add all fields to some actions if (in_array($method, ['addItemAction', 'patchItemAction', 'updateItemAction'])) { foreach ($object->getFields() as $field) { if (!$field->hasFieldType()) { continue; } if ($field->isRequired() && !$field->getDefault()) { $annotation->addRequirement($field->getId(), array('requirement' => $field->getRequiredRegex(), 'dataType' => $field->getPhpDataType(), 'description' => ($isRelationRoute ? '(' . $object->getId() . ') ' : '') . $field->getLabel())); } else { $annotation->addParameter($field->getId(), array('format' => $field->getRequiredRegex(), 'dataType' => $field->getPhpDataType(), 'default' => $field->getDefault(), 'description' => $field->getLabel() . ($field->isAutoIncrement() ? ' (autoIncremented)' : ''), 'readonly' => false, 'required' => false)); } } } }
/** * @param ApiDoc $annotation * @param ApiResource $resource */ protected function addPagination(ApiDoc $annotation, ApiResource $resource) { if ($resource->hasPagination()) { $annotation->addFilter('page', ['description' => 'Page']); } }
public function toArray() { $array = parent::toArray(); $array['uri'] = $this->getRpcMethod() ? $this->getRpcMethod()->getMethod() : ''; // $array['method'] = 'RPC'; return $array; }