public function __invoke(Analysis $analysis) { $definitions = $analysis->getAnnotationsOfType('\\Swagger\\Annotations\\Definition'); // Use the class names for @SWG\Definition() foreach ($definitions as $definition) { if ($definition->definition === null) { if ($definition->_context->is('class')) { $definition->definition = $definition->_context->class; } elseif ($definition->_context->is('trait')) { $definition->definition = $definition->_context->trait; } // if ($definition->type === null) { // $definition->type = 'object'; // } } } // Merge unmerged @SWG\Property annotations into the @SWG\Definition of the class $unmergedProperties = $analysis->unmerged()->getAnnotationsOfType('\\Swagger\\Annotations\\Property'); foreach ($unmergedProperties as $property) { $definitonContext = $property->_context->with('class') ?: $property->_context->with('trait'); if ($definitonContext->annotations) { $definition = false; foreach ($definitonContext->annotations as $annotation) { if ($annotation instanceof Definition) { $definition = $annotation; } } if ($definition) { $definition->merge([$property], true); } } } }
public function __invoke(Analysis $analysis) { $schemas = $analysis->getAnnotationsOfType('\\Swagger\\Annotations\\Schema'); foreach ($schemas as $schema) { if ($schema->_context->is('class')) { $existing = []; foreach ($schema->properties as $property) { if ($property->property) { $existing[] = $property->property; } } $classes = $analysis->getSuperClasses($schema->_context->fullyQualifiedName($schema->_context->class)); foreach ($classes as $class) { foreach ($class['properties'] as $property) { foreach ($property->annotations as $annotation) { if ($annotation instanceof Property && in_array($annotation->property, $existing) === false) { $existing[] = $annotation->property; $schema->merge([$annotation], true); } } } } } } }
public function __invoke(Analysis $analysis) { $paths = []; // Merge @SWG\Paths with the same path. foreach ($analysis->swagger->paths as $annotation) { if (empty($annotation->path)) { Logger::notice($annotation->identity() . ' is missing required property "path" in ' . $annotation->_context); } elseif (isset($paths[$annotation->path])) { $paths[$annotation->path]->mergeProperties($annotation); $analysis->annotations->detach($annotation); } else { $paths[$annotation->path] = $annotation; } } // Merge @SWG\Operations into existing @SWG\Paths or create a new one. $operations = $analysis->unmerged()->getAnnotationsOfType('\\Swagger\\Annotations\\Operation'); foreach ($operations as $operation) { if ($operation->path) { if (empty($paths[$operation->path])) { $paths[$operation->path] = new Path(['path' => $operation->path, '_context' => new Context(['generated' => true], $operation->_context)]); $analysis->annotations->attach($paths[$operation->path]); } if ($paths[$operation->path]->merge([$operation])) { Logger::notice('Unable to merge ' . $operation->identity() . ' in ' . $operation->_context); } } } $analysis->swagger->paths = array_values($paths); }
public function __invoke(Analysis $analysis) { $refs = []; /** @var Definition $definition */ foreach ($analysis->swagger->definitions as $definition) { if ($definition->definition) { $refs[strtolower($definition->_context->fullyQualifiedName($definition->_context->class))] = '#/definitions/' . $definition->definition; } } $allProperties = $analysis->getAnnotationsOfType('\\Swagger\\Annotations\\Property'); /** @var \Swagger\Annotations\Property $property */ foreach ($allProperties as $property) { $context = $property->_context; // Use the property names for @SWG\Property() if ($property->property === null) { $property->property = $context->property; } if (preg_match('/@var\\s+(?<type>[^\\s]+)([ \\t])?(?<description>.+)?$/im', $context->comment, $varMatches)) { if ($property->description === null && isset($varMatches['description'])) { $property->description = trim($varMatches['description']); } if ($property->type === null) { preg_match('/^([^\\[]+)(.*$)/', trim($varMatches['type']), $typeMatches); $type = $typeMatches[1]; if (array_key_exists(strtolower($type), static::$types)) { $type = static::$types[strtolower($type)]; if (is_array($type)) { if ($property->format === null) { $property->format = $type[1]; } $type = $type[0]; } $property->type = $type; } elseif ($property->ref === null && $typeMatches[2] === '') { $tmpKey = strtolower($context->fullyQualifiedName($type)); $property->ref = array_key_exists($tmpKey, $refs) ? $refs[$tmpKey] : null; } if ($typeMatches[2] === '[]') { if ($property->items === null) { $property->items = new Items(['type' => $property->type, '_context' => new Context(['generated' => true], $context)]); if ($property->items->type === null) { $tmpKey = strtolower($context->fullyQualifiedName($type)); $property->items->ref = array_key_exists($tmpKey, $refs) ? $refs[$tmpKey] : null; } } $property->type = 'array'; } } } if ($property->description === null) { $property->description = $context->phpdocContent(); } } }
public function testProcessor() { $swagger = new Swagger([]); $info = new Info([]); $analysis = new Analysis([$swagger, $info]); $this->assertNull($analysis->swagger); $this->assertNull($swagger->info); $analysis->process(new MergeIntoSwagger()); $this->assertInstanceOf('Swagger\\Annotations\\Swagger', $analysis->swagger); $this->assertSame($info, $swagger->info); $this->assertCount(0, $analysis->unmerged()->annotations); }
public function __invoke(Analysis $analysis) { $allOperations = $analysis->getAnnotationsOfType('\\Swagger\\Annotations\\Operation'); /** @var Operation $operation */ foreach ($allOperations as $operation) { if (null === $operation->summary) { $operation->summary = $operation->_context->phpdocSummary(); } if (null === $operation->description) { $operation->description = $operation->_context->phpdocDescription(); } } }
public function testMergeOperationsWithSamePath() { $swagger = new Swagger([]); $analysis = new Analysis([$swagger, new Get(['path' => '/comments']), new Post(['path' => '/comments'])]); $analysis->process(new MergeIntoSwagger()); $analysis->process(new BuildPaths()); $this->assertCount(1, $swagger->paths); $path = $swagger->paths[0]; $this->assertSame('/comments', $path->path); $this->assertInstanceOf('\\Swagger\\Annotations\\Path', $path); $this->assertInstanceOf('\\Swagger\\Annotations\\Get', $path->get); $this->assertInstanceOf('\\Swagger\\Annotations\\Post', $path->post); $this->assertNull($path->put); }
public function testRegisterProcessor() { $counter = 0; $analysis = new Analysis(); $analysis->process(); $this->assertSame(0, $counter); $countProcessor = function (Analysis $a) use(&$counter) { $counter++; }; Analysis::registerProcessor($countProcessor); $analysis->process(); $this->assertSame(1, $counter); Analysis::unregisterProcessor($countProcessor); $analysis->process(); $this->assertSame(1, $counter); }
public function __invoke(Analysis $analysis) { $split = $analysis->split(); $merged = $split->merged->annotations; $unmerged = $split->unmerged->annotations; foreach ($analysis->annotations as $annotation) { if (property_exists($annotation, '_unmerged')) { foreach ($annotation->_unmerged as $i => $item) { if ($merged->contains($item)) { unset($annotation->_unmerged[$i]); // Property was merged } } } } $analysis->swagger->_unmerged = []; foreach ($unmerged as $annotation) { $analysis->swagger->_unmerged[] = $annotation; } }
/** * {@inheritDoc} */ public function getServiceConfig() { return array('aliases' => array('service.swagger' => 'Swagger\\Annotations\\Swagger'), 'factories' => array('SwaggerModule\\Options\\ModuleOptions' => function ($serviceManager) { $config = $serviceManager->get('Config'); $config = isset($config['swagger']) ? $config['swagger'] : null; if ($config === null) { throw new RuntimeException('Configuration for SwaggerModule was not found'); } return new SwaggerModuleOptions($config); }, 'Swagger\\Annotations\\Swagger' => function ($serviceManager) { /** @var $options \SwaggerModule\Options\ModuleOptions */ $options = $serviceManager->get('SwaggerModule\\Options\\ModuleOptions'); $analyser = new SwaggerStaticAnalyser(); $analysis = new SwaggerAnalysis(); $processors = SwaggerAnalysis::processors(); // Crawl directory and parse all files $paths = $options->getPaths(); foreach ($paths as $directory) { $finder = SwaggerUtil::finder($directory); foreach ($finder as $file) { $analysis->addAnalysis($analyser->fromFile($file->getPathname())); } } // Post processing $analysis->process($processors); // Validation (Generate notices & warnings) $analysis->validate(); // Pass options to analyzer $resourceOptions = $options->getResourceOptions(); if (!empty($resourceOptions['defaultBasePath'])) { $analysis->swagger->basePath = $resourceOptions['defaultBasePath']; } if (!empty($resourceOptions['defaultHost'])) { $analysis->swagger->host = $resourceOptions['defaultHost']; } if (!empty($resourceOptions['schemes'])) { $analysis->swagger->schemes = $resourceOptions['schemes']; } return $analysis->swagger; })); }
/** * Scan the filesystem for swagger annotations and build swagger-documentation. * * @param string|array|Finder $directory The directory(s) or filename(s) * @param array $options * exclude: string|array $exclude The directory(s) or filename(s) to exclude (as absolute or relative paths) * analyser: defaults to StaticAnalyser * analysis: defaults to a new Analysis * processors: defaults to the registered processors in Analysis * @return Swagger */ function scan($directory, $options = array()) { $analyser = @$options['analyser'] ?: new StaticAnalyser(); $analysis = @$options['analysis'] ?: new Analysis(); $processors = @$options['processors'] ?: Analysis::processors(); $exclude = @$options['exclude'] ?: null; // Crawl directory and parse all files $finder = Util::finder($directory, $exclude); foreach ($finder as $file) { $analysis->addAnalysis($analyser->fromFile($file->getPathname())); } // Post processing $analysis->process($processors); // Validation (Generate notices & warnings) $analysis->validate(); return $analysis->swagger; }
public function testCleanUnmergedProcessor() { $comment = <<<END @SWG\\Info( title="Info only has one contact field.", version="test", ) @SWG\\License( name="MIT", @SWG\\Contact( name="Batman" ) ) END; $analysis = new Analysis($this->parseComment($comment)); $this->assertCount(3, $analysis->annotations); $analysis->process(new MergeIntoSwagger()); $this->assertCount(4, $analysis->annotations); $before = $analysis->split(); $this->assertCount(2, $before->merged->annotations, 'Generated @SWG\\Swagger + @SWG\\Info'); $this->assertCount(2, $before->unmerged->annotations, '@SWG\\License + @SWG\\Contact'); $this->assertCount(0, $analysis->swagger->_unmerged); $analysis->validate(); // Validation fails to detect the unmerged annotations. // CleanUnmerged should place the unmerged annotions into the swagger->_unmerged array. $analysis->process(new CleanUnmerged()); $between = $analysis->split(); $this->assertCount(2, $between->merged->annotations, 'Generated @SWG\\Swagger + @SWG\\Info'); $this->assertCount(2, $between->unmerged->annotations, '@SWG\\License + @SWG\\Contact'); $this->assertCount(2, $analysis->swagger->_unmerged); // 1 would also be oke, Could a'Only the @SWG\License' $this->assertSwaggerLogEntryStartsWith('Unexpected @SWG\\License(), expected to be inside @SWG\\Info in '); $this->assertSwaggerLogEntryStartsWith('Unexpected @SWG\\Contact(), expected to be inside @SWG\\Info in '); $analysis->validate(); // When a processor places a previously unmerged annotation into the swagger obect. $license = $analysis->getAnnotationsOfType('Swagger\\Annotations\\License')[0]; $contact = $analysis->getAnnotationsOfType('Swagger\\Annotations\\Contact')[0]; $analysis->swagger->info->contact = $contact; $this->assertCount(1, $license->_unmerged); $analysis->process(new CleanUnmerged()); $this->assertCount(0, $license->_unmerged); $after = $analysis->split(); $this->assertCount(3, $after->merged->annotations, 'Generated @SWG\\Swagger + @SWG\\Info + @SWG\\Contact'); $this->assertCount(1, $after->unmerged->annotations, '@SWG\\License'); $this->assertCount(1, $analysis->swagger->_unmerged); $this->assertSwaggerLogEntryStartsWith('Unexpected @SWG\\License(), expected to be inside @SWG\\Info in '); $analysis->validate(); }
public function provideDataForGetScanOptions() { return ['exclude' => ['exclude', __DIR__], 'analyser' => ['analyser', $this->prophesize('Swagger\\StaticAnalyser')->reveal()], 'analysis' => ['analysis', $this->prophesize('Swagger\\Analysis')->reveal()], 'processors' => ['processors', Analysis::processors()]]; }
/** * Same as the Swagger\scan however allows for LaravelModels * * @param string|array|Finder $directory The directory(s) or filename(s) * @param array $options * exclude: string|array $exclude The directory(s) or filename(s) to exclude (as absolute or relative paths) * analyser: defaults to StaticAnalyser * analysis: defaults to a new Analysis * processors: defaults to the registered processors in Analysis * models: the laravel models to convert into definitions * @return Swagger */ function scan($directory, $options = array()) { $models = @$options['models'] ?: []; $options['processors'] = @$options['processors'] ?: array_merge([new LaravelSwagger($models)], Analysis::processors()); return \Swagger\scan($directory, $options); }
/** * Loads the Laravel Models into the Swagger JSON * * @param Analysis $analysis */ private function load_models(Analysis $analysis) { foreach ($this->models as $model) { /** @var Model $model */ $obj = new $model(); if ($obj instanceof Model) { //check to make sure it is a model $reflection = new ReflectionClass($obj); $with = $reflection->getProperty('with'); $with->setAccessible(true); $list = Schema::getColumnListing($obj->getTable()); $list = array_diff($list, $obj->getHidden()); $properties = []; foreach ($list as $item) { $data = ['property' => $item, 'type' => $this->get_type($obj->getTable(), $item)]; $default = $this->get_default($obj->getTable(), $item); if (!is_null($default)) { $data['default'] = $default; } $properties[] = new Property($data); } foreach ($with->getValue($obj) as $item) { $class = get_class($obj->{$item}()->getModel()); $properties[] = new Property(['property' => $item, 'ref' => '#/definitions/' . $class]); } $definition = new Definition(['definition' => $model, 'properties' => $properties]); $analysis->addAnnotation($definition, new Context(['-', $model])); } } }