welcome back to dyb-tech

This commit is contained in:
Daniel Guzman
2024-05-18 02:28:01 +02:00
parent 9513cdba09
commit 9f30bc98c7
6149 changed files with 668407 additions and 0 deletions
@@ -0,0 +1,795 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Context;
use OpenApi\Generator;
use OpenApi\Annotations as OA;
use OpenApi\Util;
use Symfony\Component\Yaml\Yaml;
/**
* The openapi annotation base class.
*/
abstract class AbstractAnnotation implements \JsonSerializable
{
/**
* While the OpenAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
* For further details see https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions
* The keys inside the array will be prefixed with `x-`.
*
* @var array<string,mixed>
*/
public $x = Generator::UNDEFINED;
/**
* Arbitrary attachables for this annotation.
* These will be ignored but can be used for custom processing.
*
* @var array
*/
public $attachables = Generator::UNDEFINED;
/**
* @var Context|null
*/
public $_context = null;
/**
* Annotations that couldn't be merged by mapping or postprocessing.
*
* @var array
*/
public $_unmerged = [];
/**
* The properties which are required by [the spec](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md).
*
* @var array
*/
public static $_required = [];
/**
* Specify the type of the property.
*
* Examples:
* 'name' => 'string' // a string
* 'required' => 'boolean', // true or false
* 'tags' => '[string]', // array containing strings
* 'in' => ["query", "header", "path", "formData", "body"] // must be one on these
* 'oneOf' => [Schema::class] // array of schema objects.
*
* @var array<string,string|array<string>>
*/
public static $_types = [];
/**
* Declarative mapping of Annotation types to properties.
* Examples:
* Info::clas => 'info', // Set @OA\Info annotation as the info property.
* Parameter::clas => ['parameters'], // Append @OA\Parameter annotations the parameters array.
* PathItem::clas => ['paths', 'path'], // Append @OA\PathItem annotations the paths array and use path as key.
*
* @var array<class-string<AbstractAnnotation>,string|array<string>>
*/
public static $_nested = [];
/**
* Reverse mapping of $_nested with the allowed parent annotations.
*
* @var array<class-string<AbstractAnnotation>>
*/
public static $_parents = [];
/**
* List of properties are blacklisted from the JSON output.
*
* @var array<string>
*/
public static $_blacklist = ['_context', '_unmerged', '_analysis', 'attachables'];
public function __construct(array $properties)
{
if (isset($properties['_context'])) {
$this->_context = $properties['_context'];
unset($properties['_context']);
} elseif (Generator::$context) {
$this->_context = Generator::$context;
} else {
$this->_context = Context::detect(1);
}
if ($this->_context->is('annotations') === false) {
$this->_context->annotations = [];
}
$this->_context->annotations[] = $this;
$nestedContext = new Context(['nested' => $this], $this->_context);
foreach ($properties as $property => $value) {
if (property_exists($this, $property)) {
$this->{$property} = $value;
if (is_array($value)) {
foreach ($value as $key => $annotation) {
if ($annotation instanceof AbstractAnnotation) {
$this->{$property}[$key] = $this->nested($annotation, $nestedContext);
}
}
}
} elseif ($property !== 'value') {
$this->{$property} = $value;
} elseif (is_array($value)) {
$annotations = [];
foreach ($value as $annotation) {
if ($annotation instanceof AbstractAnnotation) {
$annotations[] = $annotation;
} else {
$this->_context->logger->warning('Unexpected field in ' . $this->identity() . ' in ' . $this->_context);
}
}
$this->merge($annotations);
} elseif (is_object($value)) {
$this->merge([$value]);
} else {
if (!Generator::isDefault($value)) {
$this->_context->logger->warning('Unexpected parameter "' . $property . '" in ' . $this->identity());
}
}
}
if ($this instanceof OpenApi) {
if ($this->_context->root()->version) {
// override via `Generator::setVersion()`
$this->openapi = $this->_context->root()->version;
} else {
$this->_context->root()->version = $this->openapi;
}
}
}
public function __get(string $property)
{
$properties = get_object_vars($this);
$this->_context->logger->warning('Property "' . $property . '" doesn\'t exist in a ' . $this->identity() . ', existing properties: "' . implode('", "', array_keys($properties)) . '" in ' . $this->_context);
}
/**
* @param mixed $value
*/
public function __set(string $property, $value): void
{
$fields = get_object_vars($this);
foreach (static::$_blacklist as $_property) {
unset($fields[$_property]);
}
$this->_context->logger->warning('Ignoring unexpected property "' . $property . '" for ' . $this->identity() . ', expecting "' . implode('", "', array_keys($fields)) . '" in ' . $this->_context);
}
/**
* Merge given annotations to their mapped properties configured in static::$_nested.
*
* Annotations that couldn't be merged are added to the _unmerged array.
*
* @param AbstractAnnotation[] $annotations
* @param bool $ignore Ignore unmerged annotations
*
* @return AbstractAnnotation[] The unmerged annotations
*/
public function merge(array $annotations, bool $ignore = false): array
{
$unmerged = [];
$nestedContext = new Context(['nested' => $this], $this->_context);
foreach ($annotations as $annotation) {
$mapped = false;
if ($details = $this->matchNested($annotation)) {
$property = $details->value;
if (is_array($property)) {
$property = $property[0];
if (Generator::isDefault($this->{$property})) {
$this->{$property} = [];
}
$this->{$property}[] = $this->nested($annotation, $nestedContext);
$mapped = true;
} elseif (Generator::isDefault($this->{$property})) {
// ignore duplicate nested if only one expected
$this->{$property} = $this->nested($annotation, $nestedContext);
$mapped = true;
}
}
if (!$mapped) {
$unmerged[] = $annotation;
}
}
if (!$ignore) {
foreach ($unmerged as $annotation) {
$this->_unmerged[] = $this->nested($annotation, $nestedContext);
}
}
return $unmerged;
}
/**
* Merge the properties from the given object into this annotation.
* Prevents overwriting properties that are already configured.
*
* @param object $object
*/
public function mergeProperties($object): void
{
$currentValues = get_object_vars($this);
foreach ($object as $property => $value) {
if ($property === '_context') {
continue;
}
if (Generator::isDefault($currentValues[$property])) {
// Overwrite default values
$this->{$property} = $value;
continue;
}
if ($property === '_unmerged') {
$this->_unmerged = array_merge($this->_unmerged, $value);
continue;
}
if ($currentValues[$property] !== $value) {
// New value is not the same?
if (Generator::isDefault($value)) {
continue;
}
$identity = method_exists($object, 'identity') ? $object->identity() : get_class($object);
$context1 = $this->_context;
$context2 = property_exists($object, '_context') ? $object->_context : 'unknown';
if (is_object($this->{$property}) && $this->{$property} instanceof AbstractAnnotation) {
$context1 = $this->{$property}->_context;
}
$this->_context->logger->error('Multiple definitions for ' . $identity . '->' . $property . "\n Using: " . $context1 . "\n Skipping: " . $context2);
}
}
}
/**
* Generate the documentation in YAML format.
*/
public function toYaml(?int $flags = null): string
{
if ($flags === null) {
$flags = Yaml::DUMP_OBJECT_AS_MAP ^ Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE;
}
return Yaml::dump(json_decode($this->toJson(JSON_INVALID_UTF8_IGNORE)), 10, 2, $flags);
}
/**
* Generate the documentation in JSON format.
*/
public function toJson(?int $flags = null): string
{
if ($flags === null) {
$flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_IGNORE;
}
return json_encode($this, $flags);
}
public function __debugInfo()
{
$properties = [];
foreach (get_object_vars($this) as $property => $value) {
if (!Generator::isDefault($value)) {
$properties[$property] = $value;
}
}
return $properties;
}
/**
* @return mixed
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$data = new \stdClass();
// Strip undefined values.
foreach (get_object_vars($this) as $property => $value) {
if (!Generator::isDefault($value)) {
$data->{$property} = $value;
}
}
// Strip properties that are for internal (swagger-php) use.
foreach (static::$_blacklist as $property) {
unset($data->{$property});
}
// Correct empty array to empty objects.
foreach (static::$_types as $property => $type) {
if ($type === 'object' && is_array($data->{$property}) && empty($data->{$property})) {
$data->{$property} = new \stdClass();
}
}
// Inject vendor properties.
unset($data->x);
if (is_array($this->x)) {
foreach ($this->x as $property => $value) {
$prefixed = 'x-' . $property;
$data->{$prefixed} = $value;
}
}
// Map nested keys
foreach (static::$_nested as $nested) {
if (is_string($nested) || count($nested) === 1) {
continue;
}
$property = $nested[0];
if (Generator::isDefault($this->{$property})) {
continue;
}
$keyField = $nested[1];
$object = new \stdClass();
foreach ($this->{$property} as $key => $item) {
if (is_numeric($key) === false && is_array($item)) {
$object->{$key} = $item;
} else {
$key = $item->{$keyField};
if (!Generator::isDefault($key) && empty($object->{$key})) {
if ($item instanceof \JsonSerializable) {
$object->{$key} = $item->jsonSerialize();
} else {
$object->{$key} = $item;
}
unset($object->{$key}->{$keyField});
}
}
}
$data->{$property} = $object;
}
// $ref
if (isset($data->ref)) {
// Only specific https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#reference-object
$ref = ['$ref' => $data->ref];
if ($this->_context->version === OpenApi::VERSION_3_1_0) {
foreach (['summary', 'description'] as $prop) {
if (property_exists($this, $prop)) {
if (!Generator::isDefault($this->{$prop})) {
$ref[$prop] = $data->{$prop};
}
}
}
}
if (property_exists($this, 'nullable') && $this->nullable === true) {
$ref = ['oneOf' => [$ref]];
if ($this->_context->version == OpenApi::VERSION_3_1_0) {
$ref['oneOf'][] = ['type' => 'null'];
} else {
$ref['nullable'] = $data->nullable;
}
unset($data->nullable);
// preserve other properties
foreach (get_object_vars($this) as $property => $value) {
if ('_' == $property[0] || in_array($property, ['ref', 'nullable'])) {
continue;
}
if (!Generator::isDefault($value)) {
$ref[$property] = $value;
}
}
}
$data = (object) $ref;
}
if ($this->_context->version === OpenApi::VERSION_3_1_0) {
if (isset($data->nullable)) {
if (true === $data->nullable) {
if (isset($data->oneOf)) {
$data->oneOf[] = ['type' => 'null'];
} elseif (isset($data->anyOf)) {
$data->anyOf[] = ['type' => 'null'];
} elseif (isset($data->allOf)) {
$data->allOf[] = ['type' => 'null'];
} else {
$data->type = (array) $data->type;
$data->type[] = 'null';
}
}
unset($data->nullable);
}
if (isset($data->minimum) && isset($data->exclusiveMinimum)) {
if (true === $data->exclusiveMinimum) {
$data->exclusiveMinimum = $data->minimum;
unset($data->minimum);
} elseif (false === $data->exclusiveMinimum) {
unset($data->exclusiveMinimum);
}
}
if (isset($data->maximum) && isset($data->exclusiveMaximum)) {
if (true === $data->exclusiveMaximum) {
$data->exclusiveMaximum = $data->maximum;
unset($data->maximum);
} elseif (false === $data->exclusiveMaximum) {
unset($data->exclusiveMaximum);
}
}
}
return $data;
}
/**
* Validate annotation tree, and log notices & warnings.
*
* @param array $stack the path of annotations above this annotation in the tree
* @param array $skip (prevent stack overflow, when traversing an infinite dependency graph)
* @param string $ref Current ref path?
* @param object $context a free-form context contains
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
if (in_array($this, $skip, true)) {
return true;
}
$valid = true;
// Report orphaned annotations
foreach ($this->_unmerged as $annotation) {
if (!is_object($annotation)) {
$this->_context->logger->warning('Unexpected type: "' . gettype($annotation) . '" in ' . $this->identity() . '->_unmerged, expecting a Annotation object');
break;
}
/** @var class-string<AbstractAnnotation> $class */
$class = get_class($annotation);
if ($details = $this->matchNested($annotation)) {
$property = $details->value;
if (is_array($property)) {
$this->_context->logger->warning('Only one ' . Util::shorten(get_class($annotation)) . '() allowed for ' . $this->identity() . ' multiple found, skipped: ' . $annotation->_context);
} else {
$this->_context->logger->warning('Only one ' . Util::shorten(get_class($annotation)) . '() allowed for ' . $this->identity() . " multiple found in:\n Using: " . $this->{$property}->_context . "\n Skipped: " . $annotation->_context);
}
} elseif ($annotation instanceof AbstractAnnotation) {
$message = 'Unexpected ' . $annotation->identity();
if ($class::$_parents) {
$message .= ', expected to be inside ' . implode(', ', Util::shorten($class::$_parents));
}
$this->_context->logger->warning($message . ' in ' . $annotation->_context);
}
$valid = false;
}
// Report conflicting key
foreach (static::$_nested as $annotationClass => $nested) {
if (is_string($nested) || count($nested) === 1) {
continue;
}
$property = $nested[0];
if (Generator::isDefault($this->{$property})) {
continue;
}
$keys = [];
$keyField = $nested[1];
foreach ($this->{$property} as $key => $item) {
if (is_array($item) && is_numeric($key) === false) {
$this->_context->logger->warning($this->identity() . '->' . $property . ' is an object literal, use nested ' . Util::shorten($annotationClass) . '() annotation(s) in ' . $this->_context);
$keys[$key] = $item;
} elseif (Generator::isDefault($item->{$keyField})) {
$this->_context->logger->error($item->identity() . ' is missing key-field: "' . $keyField . '" in ' . $item->_context);
} elseif (isset($keys[$item->{$keyField}])) {
$this->_context->logger->error('Multiple ' . $item->_identity([]) . ' with the same ' . $keyField . '="' . $item->{$keyField} . "\":\n " . $item->_context . "\n " . $keys[$item->{$keyField}]->_context);
} else {
$keys[$item->{$keyField}] = $item;
}
}
}
if (property_exists($this, 'ref') && !Generator::isDefault($this->ref) && is_string($this->ref)) {
if (substr($this->ref, 0, 2) === '#/' && count($stack) > 0 && $stack[0] instanceof OpenApi) {
// Internal reference
try {
$stack[0]->ref($this->ref);
} catch (\Exception $e) {
$this->_context->logger->warning($e->getMessage() . ' for ' . $this->identity() . ' in ' . $this->_context, ['exception' => $e]);
}
}
} else {
// Report missing required fields (when not a $ref)
foreach (static::$_required as $property) {
if (Generator::isDefault($this->{$property})) {
$message = 'Missing required field "' . $property . '" for ' . $this->identity() . ' in ' . $this->_context;
foreach (static::$_nested as $class => $nested) {
$nestedProperty = is_array($nested) ? $nested[0] : $nested;
if ($property === $nestedProperty) {
if ($this instanceof OpenApi) {
$message = 'Required ' . Util::shorten($class) . '() not found';
} elseif (is_array($nested)) {
$message = $this->identity() . ' requires at least one ' . Util::shorten($class) . '() in ' . $this->_context;
} else {
$message = $this->identity() . ' requires a ' . Util::shorten($class) . '() in ' . $this->_context;
}
break;
}
}
$this->_context->logger->warning($message);
}
}
}
// Report invalid types
foreach (static::$_types as $property => $type) {
$value = $this->{$property};
if (Generator::isDefault($value) || $value === null) {
continue;
}
if (is_string($type)) {
if ($this->validateType($type, $value) === false) {
$valid = false;
$this->_context->logger->warning($this->identity() . '->' . $property . ' is a "' . gettype($value) . '", expecting a "' . $type . '" in ' . $this->_context);
}
} elseif (is_array($type)) { // enum?
if (in_array($value, $type) === false) {
$this->_context->logger->warning($this->identity() . '->' . $property . ' "' . $value . '" is invalid, expecting "' . implode('", "', $type) . '" in ' . $this->_context);
}
} else {
throw new \Exception('Invalid ' . get_class($this) . '::$_types[' . $property . ']');
}
}
$stack[] = $this;
return self::_validate($this, $stack, $skip, $ref, $context) ? $valid : false;
}
/**
* Recursively validate all annotation properties.
*
* @param array|object $fields
*/
private static function _validate($fields, array $stack, array $skip, string $baseRef, ?object $context): bool
{
$valid = true;
$blacklist = [];
if (is_object($fields)) {
if (in_array($fields, $skip, true)) {
return true;
}
$skip[] = $fields;
$blacklist = property_exists($fields, '_blacklist') ? $fields::$_blacklist : [];
}
foreach ($fields as $field => $value) {
if ($value === null || is_scalar($value) || in_array($field, $blacklist)) {
continue;
}
$ref = $baseRef !== '' ? $baseRef . '/' . urlencode((string) $field) : urlencode((string) $field);
if (is_object($value)) {
if (method_exists($value, 'validate')) {
if (!$value->validate($stack, $skip, $ref, $context)) {
$valid = false;
}
} elseif (!self::_validate($value, $stack, $skip, $ref, $context)) {
$valid = false;
}
} elseif (is_array($value) && !self::_validate($value, $stack, $skip, $ref, $context)) {
$valid = false;
}
}
return $valid;
}
/**
* Return a identity for easy debugging.
* Example: "@OA\Get(path="/pets")".
*/
public function identity(): string
{
$class = get_class($this);
$properties = [];
/** @var class-string<AbstractAnnotation> $parent */
foreach (static::$_parents as $parent) {
foreach ($parent::$_nested as $annotationClass => $entry) {
if ($annotationClass === $class && is_array($entry) && !Generator::isDefault($this->{$entry[1]})) {
$properties[] = $entry[1];
break 2;
}
}
}
return $this->_identity($properties);
}
/**
* Check if `$other` can be nested and if so return details about where/how.
*
* @param AbstractAnnotation $other the other annotation
*
* @return null|object key/value object or `null`
*/
public function matchNested($other)
{
if ($other instanceof AbstractAnnotation && array_key_exists($root = $other->getRoot(), static::$_nested)) {
return (object) ['key' => $root, 'value' => static::$_nested[$root]];
}
return null;
}
/**
* Get the root annotation.
*
* This is used for resolving type equality and nesting rules to allow those rules to also work for custom,
* derived annotation classes.
*
* @return class-string the root annotation class in the `OpenApi\\Annotations` namespace
*/
public function getRoot(): string
{
$class = get_class($this);
do {
if (0 === strpos($class, 'OpenApi\\Annotations\\')) {
break;
}
} while ($class = get_parent_class($class));
return $class;
}
/**
* Match the annotation root.
*
* @param class-string $rootClass the root class to match
*/
public function isRoot(string $rootClass): bool
{
return $this->getRoot() == $rootClass;
}
/**
* Helper for generating the identity().
*/
protected function _identity(array $properties): string
{
$fields = [];
foreach ($properties as $property) {
$value = $this->{$property};
if ($value !== null && !Generator::isDefault($value)) {
$fields[] = $property . '=' . (is_string($value) ? '"' . $value . '"' : $value);
}
}
return Util::shorten(get_class($this)) . '(' . implode(',', $fields) . ')';
}
/**
* Validates the matching of the property value to a annotation type.
*
* @param string $type The annotations property type
* @param mixed $value The property value
*/
private function validateType(string $type, $value): bool
{
if (substr($type, 0, 1) === '[' && substr($type, -1) === ']') { // Array of a specified type?
if ($this->validateType('array', $value) === false) {
return false;
}
$itemType = substr($type, 1, -1);
foreach ($value as $i => $item) {
if ($this->validateType($itemType, $item) === false) {
return false;
}
}
return true;
}
if (is_subclass_of($type, AbstractAnnotation::class)) {
$type = 'object';
}
return $this->validateDefaultTypes($type, $value);
}
/**
* Validates default Open Api types.
*
* @param string $type The property type
* @param mixed $value The value to validate
*/
private function validateDefaultTypes(string $type, $value): bool
{
if (str_contains($type, '|')) {
$types = explode('|', $type);
foreach ($types as $type) {
if ($this->validateDefaultTypes($type, $value)) {
return true;
}
}
return false;
}
switch ($type) {
case 'string':
return is_string($value);
case 'boolean':
return is_bool($value);
case 'integer':
return is_int($value);
case 'number':
return is_numeric($value);
case 'object':
return is_object($value);
case 'array':
return $this->validateArrayType($value);
case 'scheme':
return in_array($value, ['http', 'https', 'ws', 'wss'], true);
default:
throw new \Exception('Invalid type "' . $type . '"');
}
}
/**
* Validate array type.
*
* @param mixed $value
*/
private function validateArrayType($value): bool
{
if (is_array($value) === false) {
return false;
}
$count = 0;
foreach ($value as $i => $item) {
// not a array, but a hash/map
if ($count !== $i) {
return false;
}
$count++;
}
return true;
}
/**
* Wrap the context with a reference to the annotation it is nested in.
*
* @param AbstractAnnotation $annotation
*
* @return AbstractAnnotation
*/
protected function nested(AbstractAnnotation $annotation, Context $nestedContext)
{
if (property_exists($annotation, '_context') && $annotation->_context === $this->_context) {
$annotation->_context = $nestedContext;
}
return $annotation;
}
protected function combine(...$args): array
{
$combined = [];
foreach ($args as $arg) {
if (is_array($arg)) {
$combined = array_merge($combined, $arg);
} else {
$combined[] = $arg;
}
}
return array_filter($combined, function ($value) {
return !Generator::isDefault($value) && $value !== null;
});
}
}
@@ -0,0 +1,38 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class AdditionalProperties extends Schema
{
/**
* @inheritdoc
*/
public static $_parents = [
Schema::class,
Property::class,
Items::class,
JsonContent::class,
XmlContent::class,
AdditionalProperties::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Discriminator::class => 'discriminator',
Items::class => 'items',
Property::class => ['properties', 'property'],
ExternalDocumentation::class => 'externalDocs',
Xml::class => 'xml',
AdditionalProperties::class => 'additionalProperties',
Attachable::class => ['attachables'],
];
}
@@ -0,0 +1,74 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* A container for custom data to be attached to an annotation.
*
* These will be ignored by `swagger-php` but can be used for custom processing.
*
* @Annotation
*/
class Attachable extends AbstractAnnotation
{
/**
* @inheritdoc
*/
public static $_parents = [
AdditionalProperties::class,
Components::class,
Contact::class,
Delete::class,
Discriminator::class,
Examples::class,
ExternalDocumentation::class,
Flow::class,
Get::class,
Head::class,
Header::class,
Info::class,
Items::class,
JsonContent::class,
License::class,
Link::class,
MediaType::class,
OpenApi::class,
Operation::class,
Options::class,
Parameter::class,
Patch::class,
PathItem::class,
PathParameter::class,
Post::class,
Property::class,
Put::class,
RequestBody::class,
Response::class,
Schema::class,
SecurityScheme::class,
Server::class,
ServerVariable::class,
Tag::class,
Trace::class,
Webhook::class,
Xml::class,
XmlContent::class,
];
/**
* Allows to type-hint a specific parent annotation class.
*
* Container to allow custom annotations that are limited to a subset of potential parent
* annotation classes.
*
* @return array<class-string>|null List of valid parent annotation classes. If `null`, the default nesting rules apply.
*/
public function allowedParents(): ?array
{
return null;
}
}
@@ -0,0 +1,146 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
use OpenApi\Util;
/**
* Holds a set of reusable objects for different aspects of the OA.
*
* All objects defined within the components object will have no effect on the API unless they are explicitly
* referenced from properties outside the components object.
*
* @see [OAI Components Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#components-object)
*
* @Annotation
*/
class Components extends AbstractAnnotation
{
public const COMPONENTS_PREFIX = '#/components/';
/**
* Schema reference.
*
* @var string
*/
public const SCHEMA_REF = '#/components/schemas/';
/**
* Reusable Schemas.
*
* @var array<Schema|\OpenApi\Attributes\Schema>
*/
public $schemas = Generator::UNDEFINED;
/**
* Reusable Responses.
*
* @var Response[]
*/
public $responses = Generator::UNDEFINED;
/**
* Reusable Parameters.
*
* @var Parameter[]
*/
public $parameters = Generator::UNDEFINED;
/**
* Reusable Examples.
*
* @var Examples[]
*/
public $examples = Generator::UNDEFINED;
/**
* Reusable Request Bodies.
*
* @var RequestBody[]
*/
public $requestBodies = Generator::UNDEFINED;
/**
* Reusable Headers.
*
* @var Header[]
*/
public $headers = Generator::UNDEFINED;
/**
* Reusable Security Schemes.
*
* @var SecurityScheme[]
*/
public $securitySchemes = Generator::UNDEFINED;
/**
* Reusable Links.
*
* @var Link[]
*/
public $links = Generator::UNDEFINED;
/**
* Reusable Callbacks.
*
* @var array
*/
public $callbacks = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Response::class => ['responses', 'response'],
Parameter::class => ['parameters', 'parameter'],
PathParameter::class => ['parameters', 'parameter'],
RequestBody::class => ['requestBodies', 'request'],
Examples::class => ['examples', 'example'],
Header::class => ['headers', 'header'],
SecurityScheme::class => ['securitySchemes', 'securityScheme'],
Link::class => ['links', 'link'],
Schema::class => ['schemas', 'schema'],
Attachable::class => ['attachables'],
];
/**
* Generate a `#/components/...` reference for the given annotation.
*
* A `string` component value always assumes type `Schema`.
*
* @param AbstractAnnotation|string $component
*/
public static function ref($component, bool $encode = true): string
{
if ($component instanceof AbstractAnnotation) {
foreach (Components::$_nested as $type => $nested) {
// exclude attachables
if (2 == count($nested)) {
if ($component instanceof $type) {
$type = $nested[0];
$name = $component->{$nested[1]};
break;
}
}
}
} else {
$type = 'schemas';
$name = $component;
}
return self::COMPONENTS_PREFIX . $type . '/' . ($encode ? Util::refEncode((string) $name) : $name);
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Contact information for the exposed API.
*
* @see [OAI Contact Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#contact-object)
*
* @Annotation
*/
class Contact extends AbstractAnnotation
{
/**
* The identifying name of the contact person/organization.
*
* @var string
*/
public $name = Generator::UNDEFINED;
/**
* The URL pointing to the contact information.
*
* @var string
*/
public $url = Generator::UNDEFINED;
/**
* The email address of the contact person/organization.
*
* @var string
*/
public $email = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'name' => 'string',
'url' => 'string',
'email' => 'string',
];
/**
* @inheritdoc
*/
public static $_parents = [
Info::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
}
@@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* A `@OA\Request` cookie parameter.
*
* @Annotation
*/
class CookieParameter extends Parameter
{
/**
* @inheritdoc
* This takes 'cookie' as the default location.
*/
public $in = 'cookie';
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Delete extends Operation
{
/**
* @inheritdoc
*/
public $method = 'delete';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
@@ -0,0 +1,69 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* The discriminator is a specific object in a schema which is used to inform the consumer of
* the specification of an alternative schema based on the value associated with it.
*
* This object is based on the [JSON Schema Specification](http://json-schema.org) and uses a predefined subset of it.
* On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
*
* @see [OAI Discriminator Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#discriminatorObject)
* @see [JSON Schema](http://json-schema.org/)
*
* @Annotation
*/
class Discriminator extends AbstractAnnotation
{
/**
* The name of the property in the payload that will hold the discriminator value.
*
* @var string
*/
public $propertyName = Generator::UNDEFINED;
/**
* An object to hold mappings between payload values and schema names or references.
*
* @var string[]
*/
public $mapping = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['propertyName'];
/**
* @inheritdoc
*/
public static $_types = [
'propertyName' => 'string',
];
/**
* @inheritdoc
*/
public static $_parents = [
Schema::class,
Property::class,
AdditionalProperties::class,
Items::class,
JsonContent::class,
XmlContent::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
}
+98
View File
@@ -0,0 +1,98 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* @Annotation
*/
class Examples extends AbstractAnnotation
{
/**
* The relative or absolute path to an example.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* The key into `#/components/examples`.
*
* @var string
*/
public $example = Generator::UNDEFINED;
/**
* Short description for the example.
*
* @var string
*/
public $summary = Generator::UNDEFINED;
/**
* Embedded literal example.
*
* The value field and externalValue field are mutually exclusive.
*
* To represent examples of media types that cannot naturally be represented
* in JSON or YAML, use a string value to contain the example, escaping where necessary.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Embedded literal example.
*
* The value field and externalValue field are mutually exclusive.
*
* To represent examples of media types that cannot naturally be represented
* in JSON or YAML, use a string value to contain the example, escaping where necessary.
*
* @var int|string|array
*/
public $value = Generator::UNDEFINED;
/**
* An URL that points to the literal example.
*
* This provides the capability to reference examples that cannot easily be included
* in JSON or YAML documents.
*
* The value field and externalValue field are mutually exclusive.
*
* @var string
*/
public $externalValue = Generator::UNDEFINED;
public static $_types = [
'summary' => 'string',
'description' => 'string',
'externalValue' => 'string',
];
public static $_required = ['summary'];
public static $_parents = [
Components::class,
Parameter::class,
PathParameter::class,
MediaType::class,
JsonContent::class,
XmlContent::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
}
@@ -0,0 +1,76 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Allows referencing an external resource for extended documentation.
*
* @see [OAI External Documentation Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#external-documentation-object)
*
* @Annotation
*/
class ExternalDocumentation extends AbstractAnnotation
{
/**
* A short description of the target documentation. GFM syntax can be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* The URL for the target documentation.
*
* @var string
*/
public $url = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'description' => 'string',
'url' => 'string',
];
/**
* @inheritdoc
*/
public static $_required = ['url'];
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
Tag::class,
Schema::class,
AdditionalProperties::class,
Property::class,
Operation::class,
Get::class,
Post::class,
Put::class,
Delete::class,
Patch::class,
Head::class,
Options::class,
Trace::class,
Items::class,
JsonContent::class,
XmlContent::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
}
+106
View File
@@ -0,0 +1,106 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Configuration details for a supported OAuth Flow.
*
* @see [OAI OAuth Flow Object](https://swagger.io/specification/#oauthFlowObject)
*
* @Annotation
*/
class Flow extends AbstractAnnotation
{
/**
* The authorization url to be used for this flow.
*
* This must be in the form of an url.
*
* @var string
*/
public $authorizationUrl = Generator::UNDEFINED;
/**
* The token URL to be used for this flow.
*
* This must be in the form of an url.
*
* @var string
*/
public $tokenUrl = Generator::UNDEFINED;
/**
* The URL to be used for obtaining refresh tokens.
*
* This must be in the form of an url.
*
* @var string
*/
public $refreshUrl = Generator::UNDEFINED;
/**
* Flow name.
*
* One of ['implicit', 'password', 'authorizationCode', 'clientCredentials'].
*
* @var string
*/
public $flow = Generator::UNDEFINED;
/**
* The available scopes for the OAuth2 security scheme.
*
* A map between the scope name and a short description for it.
*
* @var array
*/
public $scopes = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['scopes', 'flow'];
/**
* @inheritdoc
*/
public static $_types = [
'flow' => ['implicit', 'password', 'authorizationCode', 'clientCredentials'],
'refreshUrl' => 'string',
'authorizationUrl' => 'string',
'tokenUrl' => 'string',
];
/**
* @inheritdoc
*/
public static $_parents = [
SecurityScheme::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
if (is_array($this->scopes) && empty($this->scopes)) {
$this->scopes = new \stdClass();
}
return parent::jsonSerialize();
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Get extends Operation
{
/**
* @inheritdoc
*/
public $method = 'get';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Head extends Operation
{
/**
* @inheritdoc
*/
public $method = 'head';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
+101
View File
@@ -0,0 +1,101 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* @see [OAI Header Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#headerObject).
*
* @Annotation
*/
class Header extends AbstractAnnotation
{
/**
* The relative or absolute path to the endpoint.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* @var string
*/
public $header = Generator::UNDEFINED;
/**
* A brief description of the parameter.
*
* This could contain examples of use.
* CommonMark syntax MAY be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* @var bool
*/
public $required = Generator::UNDEFINED;
/**
* Schema object.
*
* @var Schema
*/
public $schema = Generator::UNDEFINED;
/**
* Specifies that a parameter is deprecated and SHOULD be transitioned out of usage.
*
* @var bool
*/
public $deprecated = Generator::UNDEFINED;
/**
* Sets the ability to pass empty-valued parameters.
*
* This is valid only for query parameters and allows sending a parameter with an empty value.
*
* Default value is false.
*
* If style is used, and if behavior is n/a (cannot be serialized), the value of allowEmptyValue SHALL be ignored.
*
* @var bool
*/
public $allowEmptyValue = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['header', 'schema'];
/**
* @inheritdoc
*/
public static $_types = [
'header' => 'string',
'description' => 'string',
];
/**
* @inheritdoc
*/
public static $_nested = [
Schema::class => 'schema',
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Components::class,
Response::class,
];
}
@@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* A `@OA\Request` header parameter.
*
* @Annotation
*/
class HeaderParameter extends Parameter
{
/**
* @inheritdoc
* This takes 'header' as the default location.
*/
public $in = 'header';
}
+98
View File
@@ -0,0 +1,98 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* The object provides metadata about the API.
*
* The metadata may be used by the clients if needed and may be presented in editing or documentation generation tools for convenience.
*
* @see [OAI Info Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#info-object)
*
* @Annotation
*/
class Info extends AbstractAnnotation
{
/**
* The title of the application.
*
* @var string
*/
public $title = Generator::UNDEFINED;
/**
* A short description of the application.
*
* CommonMark syntax may be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* An URL to the Terms of Service for the API.
*
* Must be in the format of an url.
*
* @var string
*/
public $termsOfService = Generator::UNDEFINED;
/**
* The contact information for the exposed API.
*
* @var Contact
*/
public $contact = Generator::UNDEFINED;
/**
* The license information for the exposed API.
*
* @var License
*/
public $license = Generator::UNDEFINED;
/**
* The version of the OpenAPI document (which is distinct from the OpenAPI Specification version or the API implementation version).
*
* @var string
*/
public $version = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['title', 'version'];
/**
* @inheritdoc
*/
public static $_types = [
'title' => 'string',
'version' => 'string',
'description' => 'string',
'termsOfService' => 'string',
];
/**
* @inheritdoc
*/
public static $_nested = [
Contact::class => 'contact',
License::class => 'license',
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
];
}
+62
View File
@@ -0,0 +1,62 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* The description of an item in a Schema with type `array`.
*
* @Annotation
*/
class Items extends Schema
{
/**
* @inheritdoc
*/
public static $_nested = [
Discriminator::class => 'discriminator',
Items::class => 'items',
Property::class => ['properties', 'property'],
ExternalDocumentation::class => 'externalDocs',
Xml::class => 'xml',
AdditionalProperties::class => 'additionalProperties',
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Property::class,
AdditionalProperties::class,
Schema::class,
JsonContent::class,
XmlContent::class,
Items::class,
];
/**
* @inheritdoc
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
if (in_array($this, $skip, true)) {
return true;
}
$valid = parent::validate($stack, $skip, $ref, $context);
$parent = end($stack);
if ($parent instanceof Schema && $parent->type !== 'array') {
$this->_context->logger->warning('@OA\\Items() parent type must be "array" in ' . $this->_context);
$valid = false;
}
// @todo Additional validation when used inside a Header or Parameter context.
return $valid;
}
}
@@ -0,0 +1,47 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Shorthand for a json response.
*
* Use as `@OA\Schema` inside a `Response` and `MediaType`->`'application/json'` will be generated.
*
* @Annotation
*/
class JsonContent extends Schema
{
/**
* An associative array of Examples attributes.
*
* The keys represent the name of the example and the values are instances of the Examples attribute.
* Each example is used to show how the content of the request or response should look like.
*
* @var array<string,Examples>
*/
public $examples = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_parents = [];
/**
* @inheritdoc
*/
public static $_nested = [
Discriminator::class => 'discriminator',
Items::class => 'items',
Property::class => ['properties', 'property'],
ExternalDocumentation::class => 'externalDocs',
AdditionalProperties::class => 'additionalProperties',
Examples::class => ['examples', 'example'],
Attachable::class => ['attachables'],
];
}
+102
View File
@@ -0,0 +1,102 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* License information for the exposed API.
*
* @see [OAI License Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#license-object)
*
* @Annotation
*/
class License extends AbstractAnnotation
{
/**
* The license name used for the API.
*
* @var string
*/
public $name = Generator::UNDEFINED;
/**
* An SPDX license expression for the API. The `identifier` field is mutually exclusive of the `url` field.
*
* @var string
*/
public $identifier = Generator::UNDEFINED;
/**
* An URL to the license used for the API. This MUST be in the form of a URL.
*
* The `url` field is mutually exclusive of the `identifier` field.
*
* @var string
*/
public $url = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'name' => 'string',
'identifier' => 'string',
'url' => 'string',
];
/**
* @inheritdoc
*/
public static $_required = ['name'];
/**
* @inheritdoc
*/
public static $_parents = [
Info::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$data = parent::jsonSerialize();
if ($this->_context->isVersion(OpenApi::VERSION_3_0_0)) {
unset($data->identifier);
}
return $data;
}
/**
* @inheritdoc
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
$valid = parent::validate($stack, $skip, $ref, $context);
if ($this->_context->isVersion(OpenApi::VERSION_3_1_0)) {
if (!Generator::isDefault($this->url) && $this->identifier !== Generator::UNDEFINED) {
$this->_context->logger->warning($this->identity() . ' url and identifier are mutually exclusive');
$valid = false;
}
}
return $valid;
}
}
+114
View File
@@ -0,0 +1,114 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* The Link object represents a possible design-time link for a response.
*
* The presence of a link does not guarantee the caller's ability to successfully invoke it, rather it provides a known
* relationship and traversal mechanism between responses and other operations.
*
* Unlike dynamic links (i.e. links provided in the response payload), the OA linking mechanism does not require
* link information in the runtime response.
*
* For computing links, and providing instructions to execute them, a runtime expression is used for
* accessing values in an operation and using them as parameters while invoking the linked operation.
*
* @see [OAI Link Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#link-object)
*
* @Annotation
*/
class Link extends AbstractAnnotation
{
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* The key into MediaType->links array.
*
* @var string
*/
public $link = Generator::UNDEFINED;
/**
* A relative or absolute reference to an OA operation.
*
* This field is mutually exclusive of the <code>operationId</code> field, and must point to an Operation object.
*
* Relative values may be used to locate an existing Operation object in the OpenAPI definition.
*
* @var string
*/
public $operationRef = Generator::UNDEFINED;
/**
* The name of an existing, resolvable OA operation, as defined with a unique <code>operationId</code>.
*
* This field is mutually exclusive of the <code>operationRef</code> field.
*
* @var string
*/
public $operationId = Generator::UNDEFINED;
/**
* A map representing parameters to pass to an operation as specified with operationId or identified via
* operationRef.
*
* The key is the parameter name to be used, whereas the value can be a constant or an expression to
* be evaluated and passed to the linked operation.
* The parameter name can be qualified using the parameter location [{in}.]{name} for operations
* that use the same parameter name in different locations (e.g. path.id).
*
* @var array<string,mixed>
*/
public $parameters = Generator::UNDEFINED;
/**
* A literal value or {expression} to use as a request body when calling the target operation.
*
* @var mixed
*/
public $requestBody = Generator::UNDEFINED;
/**
* A description of the link.
*
* CommonMark syntax may be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* A server object to be used by the target operation.
*
* @var Server
*/
public $server = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_nested = [
Server::class => 'server',
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Components::class,
Response::class,
];
}
@@ -0,0 +1,88 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Each Media Type object provides schema and examples for the media type identified by its key.
*
* @see [OAI Media Type Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object)
*
* @Annotation
*/
class MediaType extends AbstractAnnotation
{
/**
* The key into Operation->content array.
*
* @var string
*/
public $mediaType = Generator::UNDEFINED;
/**
* The schema defining the type used for the request body.
*
* @var Schema
*/
public $schema = Generator::UNDEFINED;
/**
* Example of the media type.
*
* The example object should be in the correct format as specified by the media type.
* The example object is mutually exclusive of the examples object.
*
* Furthermore, if referencing a schema which contains an example,
* the example value shall override the example provided by the schema.
*
* @var mixed
*/
public $example = Generator::UNDEFINED;
/**
* Examples of the media type.
*
* Each example object should match the media type and specified schema if present.
* The examples object is mutually exclusive of the example object.
*
* Furthermore, if referencing a schema which contains an example,
* the examples value shall override the example provided by the schema.
*
* @var array<string,Examples>
*/
public $examples = Generator::UNDEFINED;
/**
* A map between a property name and its encoding information.
*
* The key, being the property name, must exist in the schema as a property.
*
* The encoding object shall only apply to requestBody objects when the media type is multipart or
* application/x-www-form-urlencoded.
*
* @var array<string,mixed>
*/
public $encoding = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_nested = [
Schema::class => 'schema',
Examples::class => ['examples', 'example'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Response::class,
RequestBody::class,
];
}
+271
View File
@@ -0,0 +1,271 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Analysis;
use OpenApi\Generator;
use OpenApi\Util;
/**
* This is the root document object for the API specification.
*
* @see [OAI OpenApi Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#openapi-object)
*
* @Annotation
*/
class OpenApi extends AbstractAnnotation
{
public const VERSION_3_0_0 = '3.0.0';
public const VERSION_3_1_0 = '3.1.0';
public const DEFAULT_VERSION = self::VERSION_3_0_0;
public const SUPPORTED_VERSIONS = [self::VERSION_3_0_0, self::VERSION_3_1_0];
/**
* The semantic version number of the OpenAPI Specification version that the OpenAPI document uses.
*
* The openapi field should be used by tooling specifications and clients to interpret the OpenAPI document.
*
* A version specified via `Generator::setVersion()` will overwrite this value.
*
* This is not related to the API info::version string.
*
* @var string
*/
public $openapi = self::DEFAULT_VERSION;
/**
* Provides metadata about the API. The metadata may be used by tooling as required.
*
* @var Info
*/
public $info = Generator::UNDEFINED;
/**
* An array of <code>@Server</code> objects, which provide connectivity information to a target server.
*
* If not provided, or is an empty array, the default value would be a Server Object with an url value of <code>/</code>.
*
* @var Server[]
*/
public $servers = Generator::UNDEFINED;
/**
* The available paths and operations for the API.
*
* @var PathItem[]
*/
public $paths = Generator::UNDEFINED;
/**
* An element to hold various components for the specification.
*
* @var Components
*/
public $components = Generator::UNDEFINED;
/**
* A declaration of which security mechanisms can be used across the API.
*
* The list of values includes alternative security requirement objects that can be used.
* Only one of the security requirement objects need to be satisfied to authorize a request.
* Individual operations can override this definition.
* To make security optional, an empty security requirement `({})` can be included in the array.
*
* @var array
*/
public $security = Generator::UNDEFINED;
/**
* A list of tags used by the specification with additional metadata.
*
* The order of the tags can be used to reflect on their order by the parsing tools.
* Not all tags that are used by the Operation Object must be declared.
* The tags that are not declared may be organized randomly or based on the tools' logic.
* Each tag name in the list must be unique.
*
* @var Tag[]
*/
public $tags = Generator::UNDEFINED;
/**
* Additional external documentation.
*
* @var ExternalDocumentation
*/
public $externalDocs = Generator::UNDEFINED;
/**
* The available webhooks for the API.
*
* @var Webhook[]
*/
public $webhooks = Generator::UNDEFINED;
/**
* @var Analysis
*/
public $_analysis = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['openapi', 'info'];
/**
* @inheritdoc
*/
public static $_nested = [
Info::class => 'info',
Server::class => ['servers'],
PathItem::class => ['paths', 'path'],
Components::class => 'components',
Tag::class => ['tags'],
ExternalDocumentation::class => 'externalDocs',
Webhook::class => ['webhooks', 'webhook'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_types = [];
/**
* @inheritdoc
*/
public function validate(?array $stack = null, ?array $skip = null, string $ref = '', $context = null): bool
{
if ($stack !== null || $skip !== null || $ref !== '') {
$this->_context->logger->warning('Nested validation for ' . $this->identity() . ' not allowed');
return false;
}
if (!in_array($this->openapi, self::SUPPORTED_VERSIONS)) {
$this->_context->logger->warning('Unsupported OpenAPI version "' . $this->openapi . '". Allowed versions are: ' . implode(', ', self::SUPPORTED_VERSIONS));
return false;
}
/* paths is optional in 3.1.0 */
if ($this->openapi === self::VERSION_3_0_0 && Generator::isDefault($this->paths)) {
$this->_context->logger->warning('Required @OA\PathItem() not found');
}
if ($this->openapi === self::VERSION_3_1_0
&& Generator::isDefault($this->paths)
&& Generator::isDefault($this->webhooks)
&& Generator::isDefault($this->components)
) {
$this->_context->logger->warning("At least one of 'Required @OA\PathItem(), @OA\Components() or @OA\Webhook() not found'");
return false;
}
return parent::validate([], [], '#', new \stdClass());
}
/**
* Save the OpenAPI documentation to a file.
*/
public function saveAs(string $filename, string $format = 'auto'): void
{
if ($format === 'auto') {
$format = strtolower(substr($filename, -5)) === '.json' ? 'json' : 'yaml';
}
if (strtolower($format) === 'json') {
$content = $this->toJson();
} else {
$content = $this->toYaml();
}
if (file_put_contents($filename, $content) === false) {
throw new \Exception('Failed to saveAs("' . $filename . '", "' . $format . '")');
}
}
/**
* Look up an annotation with a $ref url.
*
* @param string $ref The $ref value, for example: "#/components/schemas/Product"
*/
public function ref(string $ref)
{
if (substr($ref, 0, 2) !== '#/') {
// @todo Add support for external (http) refs?
throw new \Exception('Unsupported $ref "' . $ref . '", it should start with "#/"');
}
return $this->resolveRef($ref, '#/', $this, []);
}
/**
* Recursive helper for ref().
*
* @param array|AbstractAnnotation $container
*/
private static function resolveRef(string $ref, string $resolved, $container, array $mapping)
{
if ($ref === $resolved) {
return $container;
}
$path = substr($ref, strlen($resolved));
$slash = strpos($path, '/');
$subpath = $slash === false ? $path : substr($path, 0, $slash);
$property = Util::refDecode($subpath);
$unresolved = $slash === false ? $resolved . $subpath : $resolved . $subpath . '/';
if (is_object($container)) {
if (property_exists($container, $property) === false) {
throw new \Exception('$ref "' . $ref . '" not found');
}
if ($slash === false) {
return $container->{$property};
}
$mapping = [];
if ($container instanceof AbstractAnnotation) {
foreach ($container::$_nested as $nestedClass => $nested) {
if (is_string($nested) === false && count($nested) === 2 && $nested[0] === $property) {
$mapping[$nestedClass] = $nested[1];
}
}
}
return self::resolveRef($ref, $unresolved, $container->{$property}, $mapping);
} elseif (is_array($container)) {
if (array_key_exists($property, $container)) {
return self::resolveRef($ref, $unresolved, $container[$property], []);
}
foreach ($mapping as $nestedClass => $keyField) {
foreach ($container as $key => $item) {
if (is_numeric($key) && is_object($item) && $item instanceof $nestedClass && (string) $item->{$keyField} === $property) {
return self::resolveRef($ref, $unresolved, $item, []);
}
}
}
}
throw new \Exception('$ref "' . $unresolved . '" not found');
}
/**
* @inheritdoc
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$data = parent::jsonSerialize();
if (false === $this->_context->isVersion(OpenApi::VERSION_3_1_0)) {
unset($data->webhooks);
}
return $data;
}
}
+248
View File
@@ -0,0 +1,248 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Base class for `@OA\Get`, `@OA\Post`, `@OA\Put`, etc.
*
* Describes a single API operation on a path.
*
* @see [OAI Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#operation-object)
*
* @Annotation
*/
abstract class Operation extends AbstractAnnotation
{
/**
* Key in the OpenApi "Paths Object" for this operation.
*
* @var string
*/
public $path = Generator::UNDEFINED;
/**
* A list of tags for API documentation control.
*
* Tags can be used for logical grouping of operations by resources or any other qualifier.
*
* @var string[]
*/
public $tags = Generator::UNDEFINED;
/**
* Key in the OpenApi "Path Item Object" for this operation.
*
* Allowed values: 'get', 'post', put', 'patch', 'delete', 'options', 'head' and 'trace'.
*
* @var string
*/
public $method = Generator::UNDEFINED;
/**
* A short summary of what the operation does.
*
* @var string
*/
public $summary = Generator::UNDEFINED;
/**
* A verbose explanation of the operation behavior.
*
* CommonMark syntax MAY be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Additional external documentation for this operation.
*
* @var ExternalDocumentation
*/
public $externalDocs = Generator::UNDEFINED;
/**
* Unique string used to identify the operation.
*
* The id must be unique among all operations described in the API.
* Tools and libraries may use the operationId to uniquely identify an operation, therefore, it is recommended to
* follow common programming naming conventions.
*
* @var string
*/
public $operationId = Generator::UNDEFINED;
/**
* A list of parameters that are applicable for this operation.
*
* If a parameter is already defined at the Path Item, the new definition will override it but can never remove it.
* The list must not include duplicated parameters.
*
* A unique parameter is defined by a combination of a name and location.
*
* The list can use the Reference Object to link to parameters that are defined at the OpenAPI Object's
* components/parameters.
*
* @var Parameter[]
*/
public $parameters = Generator::UNDEFINED;
/**
* The request body applicable for this operation.
*
* The requestBody is only supported in HTTP methods where the HTTP 1.1 specification RFC7231 has explicitly
* defined semantics for request bodies. In other cases where the HTTP spec is vague, requestBody shall be ignored
* by consumers.
*
* @var RequestBody
*/
public $requestBody = Generator::UNDEFINED;
/**
* The list of possible responses as they are returned from executing this operation.
*
* @var Response[]
*/
public $responses = Generator::UNDEFINED;
/**
* A map of possible out-of band callbacks related to the parent operation.
*
* The key is a unique identifier for the Callback Object.
*
* Each value in the map is a Callback Object that describes a request that may be initiated by the API provider
* and the expected responses. The key value used to identify the callback object is an expression, evaluated at
* runtime, that identifies a URL to use for the callback operation.
*
* @var array
*/
public $callbacks = Generator::UNDEFINED;
/**
* Declares this operation to be deprecated.
*
* Consumers should refrain from usage of the declared operation.
*
* Default value is false.
*
* @var bool
*/
public $deprecated = Generator::UNDEFINED;
/**
* A declaration of which security mechanisms can be used for this operation.
*
* The list of values includes alternative security requirement objects that can be used.
*
* Only one of the security requirement objects need to be satisfied to authorize a request.
*
* This definition overrides any declared top-level security.
* To remove a top-level security declaration, an empty array can be used.
*
* @var array
*/
public $security = Generator::UNDEFINED;
/**
* An alternative server array to service this operation.
*
* If an alternative server object is specified at the Path Item Object or Root level, it will be overridden by
* this value.
*
* @var Server[]
*/
public $servers = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['responses'];
/**
* @inheritdoc
*/
public static $_types = [
'path' => 'string',
'method' => 'string',
'tags' => '[string]',
'summary' => 'string',
'description' => 'string',
'deprecated' => 'boolean',
];
/**
* @inheritdoc
*/
public static $_nested = [
Parameter::class => ['parameters'],
PathParameter::class => ['parameters'],
Response::class => ['responses', 'response'],
ExternalDocumentation::class => 'externalDocs',
Server::class => ['servers'],
RequestBody::class => 'requestBody',
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$data = parent::jsonSerialize();
unset($data->method);
unset($data->path);
// ensure security elements are object
if (isset($data->security) && is_array($data->security)) {
foreach ($data->security as $key => $scheme) {
$data->security[$key] = (object) $scheme;
}
}
return $data;
}
/**
* @inheritdoc
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
if (in_array($this, $skip, true)) {
return true;
}
$valid = parent::validate($stack, $skip, $ref, $context);
if (!Generator::isDefault($this->responses)) {
foreach ($this->responses as $response) {
if (!Generator::isDefault($response->response) && $response->response !== 'default' && preg_match('/^([12345]{1}[0-9]{2})|([12345]{1}XX)$/', (string) $response->response) === 0) {
$this->_context->logger->warning('Invalid value "' . $response->response . '" for ' . $response->_identity([]) . '->response, expecting "default", a HTTP Status Code or HTTP Status Code range definition in ' . $response->_context);
$valid = false;
}
}
}
if (is_object($context) && !Generator::isDefault($this->operationId)) {
if (!property_exists($context, 'operationIds')) {
$context->operationIds = [];
}
if (in_array($this->operationId, $context->operationIds)) {
$this->_context->logger->warning('operationId must be unique. Duplicate value found: "' . $this->operationId . '"');
$valid = false;
}
$context->operationIds[] = $this->operationId;
}
return $valid;
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Options extends Operation
{
/**
* @inheritdoc
*/
public $method = 'options';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
+301
View File
@@ -0,0 +1,301 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Describes a single operation parameter.
*
* A unique parameter is defined by a combination of a name and location.
*
* @see [OAA Parameter Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object)
*
* @Annotation
*/
class Parameter extends AbstractAnnotation
{
/**
* The relative or absolute path to the endpoint.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* The key into <code>Components::parameters</code> or <code>PathItem::parameters</code> array.
*
* @var string
*/
public $parameter = Generator::UNDEFINED;
/**
* The (case-sensitive) name of the parameter.
*
* If in is "path", the name field must correspond to the associated path segment from the path field in the Paths Object.
*
* If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition shall be ignored.
* For all other cases, the name corresponds to the parameter name used by the in property.
*
* @var string
*/
public $name = Generator::UNDEFINED;
/**
* The location of the parameter.
*
* Possible values are "query", "header", "path" or "cookie".
*
* @var string
*/
public $in = Generator::UNDEFINED;
/**
* A brief description of the parameter.
*
* This could contain examples of use.
*
* CommonMark syntax may be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Determines whether this parameter is mandatory.
*
* If the parameter location is "path", this property is required and its value must be true.
* Otherwise, the property may be included and its default value is false.
*
* @var bool
*/
public $required = Generator::UNDEFINED;
/**
* Specifies that a parameter is deprecated and should be transitioned out of usage.
*
* @var bool
*/
public $deprecated = Generator::UNDEFINED;
/**
* Sets the ability to pass empty-valued parameters.
*
* This is valid only for query parameters and allows sending a parameter with an empty value.
*
* Default value is false.
*
* If style is used, and if behavior is n/a (cannot be serialized), the value of allowEmptyValue shall be ignored.
*
* @var bool
*/
public $allowEmptyValue = Generator::UNDEFINED;
/**
* Describes how the parameter value will be serialized depending on the type of the parameter value.
*
* Default values (based on value of in): for query - form; for path - simple; for header - simple; for cookie - form.
*
* @var string
*/
public $style = Generator::UNDEFINED;
/**
* When this is true, parameter values of type array or object generate separate parameters for each value of the array or key-value pair of the map.
*
* For other types of parameters this property has no effect.
*
* When style is form, the default value is true.
* For all other styles, the default value is false.
*
* @var bool
*/
public $explode = Generator::UNDEFINED;
/**
* Determines whether the parameter value should allow reserved characters, as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding.
*
* This property only applies to parameters with an in value of query.
*
* The default value is false.
*
* @var bool
*/
public $allowReserved = Generator::UNDEFINED;
/**
* The schema defining the type used for the parameter.
*
* @var Schema
*/
public $schema = Generator::UNDEFINED;
/**
* Example of the media type.
*
* The example should match the specified schema and encoding properties if present.
* The example object is mutually exclusive of the examples object.
* Furthermore, if referencing a schema which contains an example, the example value shall override the example provided by the schema.
* To represent examples of media types that cannot naturally be represented in JSON or YAML, a string value can contain the example with escaping where necessary.
*
* @var mixed
*/
public $example = Generator::UNDEFINED;
/**
* Examples of the media type.
*
* Each example should contain a value in the correct format as specified in the parameter encoding.
* The examples object is mutually exclusive of the example object.
* Furthermore, if referencing a schema which contains an example, the examples value shall override the example provided by the schema.
*
* @var array<string,Examples>
*/
public $examples = Generator::UNDEFINED;
/**
* A map containing the representations for the parameter.
*
* The key is the media type and the value describes it.
* The map must only contain one entry.
*
* @var array<MediaType>|JsonContent|XmlContent|Attachable
*/
public $content = Generator::UNDEFINED;
/**
* Path-style parameters defined by RFC6570.
*
* @see [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7)
*/
public $matrix = Generator::UNDEFINED;
/**
* Label style parameters defined by RFC6570.
*
* @see [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.5)
*/
public $label = Generator::UNDEFINED;
/**
* Form style parameters defined by RFC6570.
*
* This option replaces collectionFormat with a csv (when explode is false) or multi (when explode is true) value from OpenAPI 2.0.
*
* @see [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.8)
*/
public $form = Generator::UNDEFINED;
/**
* Simple style parameters defined by RFC6570.
*
* This option replaces collectionFormat with a csv value from OpenAPI 2.0.
*
* @see [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.2)
*
* @var array
*/
public $simple = Generator::UNDEFINED;
/**
* Space separated array values.
*
* This option replaces collectionFormat equal to ssv from OpenAPI 2.0.
*
* @var array
*/
public $spaceDelimited = Generator::UNDEFINED;
/**
* Pipe separated array values.
*
* This option replaces collectionFormat equal to pipes from OpenAPI 2.0.
*
* @var array
*/
public $pipeDelimited = Generator::UNDEFINED;
/**
* Provides a simple way of rendering nested objects using form parameters.
*/
public $deepObject = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['name', 'in'];
/**
* @inheritdoc
*/
public static $_types = [
'name' => 'string',
'in' => ['query', 'header', 'path', 'cookie'],
'description' => 'string',
'style' => ['matrix', 'label', 'form', 'simple', 'spaceDelimited', 'pipeDelimited', 'deepObject'],
'required' => 'boolean',
];
/**
* @inheritdoc
*/
public static $_nested = [
Schema::class => 'schema',
Examples::class => ['examples', 'example'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Components::class,
PathItem::class,
Operation::class,
Get::class,
Post::class,
Put::class,
Delete::class,
Patch::class,
Head::class,
Options::class,
Trace::class,
];
/**
* @inheritdoc
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
if (in_array($this, $skip, true)) {
return true;
}
$valid = parent::validate($stack, $skip, $ref, $context);
if (Generator::isDefault($this->ref)) {
if ($this->in === 'body') {
if (Generator::isDefault($this->schema)) {
$this->_context->logger->warning('Field "schema" is required when ' . $this->identity() . ' is in "' . $this->in . '" in ' . $this->_context);
$valid = false;
}
}
}
return $valid;
}
/**
* @inheritdoc
*/
public function identity(): string
{
return parent::_identity(['name', 'in']);
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Patch extends Operation
{
/**
* @inheritdoc
*/
public $method = 'patch';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
+158
View File
@@ -0,0 +1,158 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Describes the operations available on a single path.
*
* A Path Item may be empty, due to ACL constraints.
* The path itself is still exposed to the documentation viewer, but they will not know which operations and parameters are available.
*
* @see [OAI Path Item Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object)
*
* @Annotation
*/
class PathItem extends AbstractAnnotation
{
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* An optional, string summary, intended to apply to all operations in this path.
*
* @var string
*/
public $summary = Generator::UNDEFINED;
/**
* An optional, string description, intended to apply to all operations in this path.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Key for the Path Object (OpenApi->paths array).
*
* @var string
*/
public $path = Generator::UNDEFINED;
/**
* A definition of a GET operation on this path.
*
* @var Get
*/
public $get = Generator::UNDEFINED;
/**
* A definition of a PUT operation on this path.
*
* @var Put
*/
public $put = Generator::UNDEFINED;
/**
* A definition of a POST operation on this path.
*
* @var Post
*/
public $post = Generator::UNDEFINED;
/**
* A definition of a DELETE operation on this path.
*
* @var Delete
*/
public $delete = Generator::UNDEFINED;
/**
* A definition of a OPTIONS operation on this path.
*
* @var Options
*/
public $options = Generator::UNDEFINED;
/**
* A definition of a HEAD operation on this path.
*
* @var Head
*/
public $head = Generator::UNDEFINED;
/**
* A definition of a PATCH operation on this path.
*
* @var Patch
*/
public $patch = Generator::UNDEFINED;
/**
* A definition of a TRACE operation on this path.
*
* @var Trace
*/
public $trace = Generator::UNDEFINED;
/**
* An alternative server array to service all operations in this path.
*
* @var Server[]
*/
public $servers = Generator::UNDEFINED;
/**
* A list of parameters that are applicable for all the operations described under this path.
*
* These parameters can be overridden at the operation level, but cannot be removed there.
* The list must not include duplicated parameters.
* A unique parameter is defined by a combination of a name and location.
* The list can use the Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters.
*
* @var Parameter[]
*/
public $parameters = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'path' => 'string',
'summary' => 'string',
];
/**
* @inheritdoc
*/
public static $_nested = [
Get::class => 'get',
Post::class => 'post',
Put::class => 'put',
Delete::class => 'delete',
Patch::class => 'patch',
Trace::class => 'trace',
Head::class => 'head',
Options::class => 'options',
Parameter::class => ['parameters'],
PathParameter::class => ['parameters'],
Server::class => ['servers'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
];
}
@@ -0,0 +1,26 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* A `@OA\Request` path parameter.
*
* @Annotation
*/
class PathParameter extends Parameter
{
/**
* @inheritdoc
* This takes 'path' as the default location.
*/
public $in = 'path';
/**
* @inheritdoc
*/
public $required = true;
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Post extends Operation
{
/**
* @inheritdoc
*/
public $method = 'post';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
+47
View File
@@ -0,0 +1,47 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* @Annotation
*/
class Property extends Schema
{
/**
* The key into Schema->properties array.
*
* @var string
*/
public $property = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_parents = [
AdditionalProperties::class,
Schema::class,
JsonContent::class,
XmlContent::class,
Property::class,
Items::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Discriminator::class => 'discriminator',
Items::class => 'items',
Property::class => ['properties', 'property'],
ExternalDocumentation::class => 'externalDocs',
Xml::class => 'xml',
AdditionalProperties::class => 'additionalProperties',
Attachable::class => ['attachables'],
];
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Put extends Operation
{
/**
* @inheritdoc
*/
public $method = 'put';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
@@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* A `@OA\Request` query parameter.
*
* @Annotation
*/
class QueryParameter extends Parameter
{
/**
* @inheritdoc
* This takes 'query' as the default location.
*/
public $in = 'query';
}
@@ -0,0 +1,98 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\XmlContent;
use OpenApi\Generator;
/**
* Describes a single request body.
*
* @see [OAI Request Body Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#requestBodyObject)
*
* @Annotation
*/
class RequestBody extends AbstractAnnotation
{
/**
* The relative or absolute path to a request body.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* Request body model name.
*
* @var string
*/
public $request = Generator::UNDEFINED;
/**
* A brief description of the parameter.
*
* This could contain examples of use.
*
* CommonMark syntax may be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Determines whether this parameter is mandatory.
*
* If the parameter location is "path", this property is required and its value must be true.
* Otherwise, the property may be included and its default value is false.
*
* @var bool
*/
public $required = Generator::UNDEFINED;
/**
* The content of the request body.
*
* The key is a media type or media type range and the value describes it. For requests that match multiple keys,
* only the most specific key is applicable. e.g. text/plain overrides text/*.
*
* @var array<MediaType|JsonContent|XmlContent>|MediaType|JsonContent|XmlContent|Attachable
*/
public $content = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'description' => 'string',
'required' => 'boolean',
'request' => 'string',
];
public static $_parents = [
Components::class,
Delete::class,
Get::class,
Head::class,
Operation::class,
Options::class,
Patch::class,
Post::class,
Trace::class,
Put::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
MediaType::class => ['content', 'mediaType'],
Attachable::class => ['attachables'],
];
}
+130
View File
@@ -0,0 +1,130 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Describes a single response from an API Operation, including design-time,
* static links to operations based on the response.
*
* @see [OAI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#response-object)
*
* @Annotation
*/
class Response extends AbstractAnnotation
{
/**
* The relative or absolute path to a response.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* The key into Operations->responses array.
*
* A HTTP status code or <code>default</code>.
*
* @var string|int
*/
public $response = Generator::UNDEFINED;
/**
* A short description of the response.
*
* CommonMark syntax may be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Maps a header name to its definition.
*
* RFC7230 states header names are case insensitive.
*
* If a response header is defined with the name "Content-Type", it shall be ignored.
*
* @see [RFC7230](https://tools.ietf.org/html/rfc7230#page-22)
*
* @var Header[]
*/
public $headers = Generator::UNDEFINED;
/**
* A map containing descriptions of potential response payloads.
*
* The key is a media type or media type range and the value describes it.
*
* For responses that match multiple keys, only the most specific key is applicable;
* e.g. <code>text/plain</code> overrides <code>text/*</code>.
*
* @var MediaType|JsonContent|XmlContent|Attachable|array<MediaType|JsonContent|XmlContent|Attachable>
*/
public $content = Generator::UNDEFINED;
/**
* A map of operations links that can be followed from the response.
*
* The key of the map is a short name for the link, following the naming constraints of the names for Component
* Objects.
*
* @var Link[]
*/
public $links = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'description' => 'string',
];
/**
* @inheritdoc
*/
public static $_nested = [
MediaType::class => ['content', 'mediaType'],
Header::class => ['headers', 'header'],
Link::class => ['links', 'link'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Components::class,
Operation::class,
Get::class,
Post::class,
Put::class,
Patch::class,
Delete::class,
Head::class,
Options::class,
Trace::class,
];
/**
* @inheritdoc
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
$valid = parent::validate($stack, $skip, $ref, $context);
if (Generator::isDefault($this->description) && Generator::isDefault($this->ref)) {
$this->_context->logger->warning($this->identity() . ' One of description or ref is required');
$valid = false;
}
return $valid;
}
}
+495
View File
@@ -0,0 +1,495 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* The definition of input and output data types.
*
* These types can be objects, but also primitives and arrays.
*
* This object is based on the [JSON Schema Specification](http://json-schema.org) and uses a predefined subset of it.
* On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
*
* @see [OAI Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schemaObject)
* @see [JSON Schema](http://json-schema.org/)
*
* @Annotation
*/
class Schema extends AbstractAnnotation
{
/**
* The relative or absolute path to the endpoint.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* The key into Components->schemas array.
*
* @var string
*/
public $schema = Generator::UNDEFINED;
/**
* Can be used to decorate a user interface with information about the data produced by this user interface.
*
* Preferably short; use <code>description</code> for more details.
*
* @var string
*/
public $title = Generator::UNDEFINED;
/**
* A description will provide explanation about the purpose of the instance described by this schema.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* The maximum number of properties allowed in an object instance.
* An object instance is valid against this property if its number of properties is less than, or equal to, the value of this attribute.
*
* @var int
*/
public $maxProperties = Generator::UNDEFINED;
/**
* The minimum number of properties allowed in an object instance.
* An object instance is valid against this property if its number of properties is greater than, or equal to, the value of this attribute.
*
* @var int
*/
public $minProperties = Generator::UNDEFINED;
/**
* An object instance is valid against this property if its property set contains all elements in this property's
* array value.
*
* @var string[]
*/
public $required = Generator::UNDEFINED;
/**
* A collection of properties to define for an object.
*
* Each property is represented as an instance of the <a href="#property">Property</a> class.
*
* @var Property[]
*/
public $properties = Generator::UNDEFINED;
/**
* The type of the schema/property.
*
* OpenApi v3.0: The value MUST be one of "string", "number", "integer", "boolean", "array" or "object".
*
* Since OpenApi v3.1 an array of types may be used.
*
* @var string|non-empty-array<string>
*/
public $type = Generator::UNDEFINED;
/**
* The extending format for the previously mentioned type. See Data Type Formats for further details.
*
* @var string
*/
public $format = Generator::UNDEFINED;
/**
* Required if type is "array". Describes the type of items in the array.
*
* @var Items
*/
public $items = Generator::UNDEFINED;
/**
* Determines the format of the array if type array is used.
*
* Possible values are:
* - csv: comma separated values foo,bar.
* - ssv: space separated values foo bar.
* - tsv: tab separated values foo\tbar.
* - pipes: pipe separated values foo|bar.
* - multi: corresponds to multiple parameter instances instead of multiple values for a single instance foo=bar&foo=baz.
* This is valid only for parameters of type <code>query</code> or <code>formData</code>.
* Default value is csv.
*
* @var string
*/
public $collectionFormat = Generator::UNDEFINED;
/**
* Sets a default value to the parameter. The type of the value depends on the defined type.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor101)
*
* @var mixed
*/
public $default = Generator::UNDEFINED;
/**
* The maximum value allowed for a numeric property. This value must be a number.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor17)
*
* @var int|float
*/
public $maximum = Generator::UNDEFINED;
/**
* A boolean indicating whether the maximum value is excluded from the set of valid values.
*
* When set to true, the maximum value is excluded, and when false or not specified, it is included.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor17)
*
* @var bool|int|float
*/
public $exclusiveMaximum = Generator::UNDEFINED;
/**
* The minimum value allowed for a numeric property. This value must be a number.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor21)
*
* @var int|float
*/
public $minimum = Generator::UNDEFINED;
/**
* A boolean indicating whether the minimum value is excluded from the set of valid values.
*
* When set to true, the minimum value is excluded, and when false or not specified, it is included.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor21)
*
* @var bool|int|float
*/
public $exclusiveMinimum = Generator::UNDEFINED;
/**
* The maximum length of a string property.
*
* A string instance is valid against this property if its length is less than, or equal to, the value of this attribute.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor26)
*
* @var int
*/
public $maxLength = Generator::UNDEFINED;
/**
* The minimum length of a string property.
*
* A string instance is valid against this property if its length is greater than, or equal to, the value of this attribute.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor29)
*
* @var int
*/
public $minLength = Generator::UNDEFINED;
/**
* A string instance is considered valid if the regular expression matches the instance successfully.
*
* @var string
*/
public $pattern = Generator::UNDEFINED;
/**
* The maximum number of items allowed in an array property.
*
* An array instance is valid against this property if its number of items is less than, or equal to, the value of this attribute.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor42)
*
* @var int
*/
public $maxItems = Generator::UNDEFINED;
/**
* The minimum number of items allowed in an array property.
*
* An array instance is valid against this property if its number of items is greater than, or equal to, the value of this attribute.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor45)
*
* @var int
*/
public $minItems = Generator::UNDEFINED;
/**
* A boolean value indicating whether all items in an array property must be unique.
*
* If this attribute is set to true, then all items in the array must be unique.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor49)
*
* @var bool
*/
public $uniqueItems = Generator::UNDEFINED;
/**
* A collection of allowable values for a property.
*
* A property instance is valid against this attribute if its value is one of the values specified in this collection.
*
* @see [JSON schema validation](http://json-schema.org/latest/json-schema-validation.html#anchor76)
*
* @var string[]|int[]|float[]|bool[]|\UnitEnum[]|class-string
*/
public $enum = Generator::UNDEFINED;
/**
* A numeric instance is valid against "multipleOf" if the result of the division of the instance by this
* property's value is an integer.
*
* @var int|float
*/
public $multipleOf = Generator::UNDEFINED;
/**
* Adds support for polymorphism.
*
* The discriminator is an object name that is used to differentiate between other schemas which may satisfy the
* payload description. See Composition and Inheritance for more details.
*
* @var Discriminator
*/
public $discriminator = Generator::UNDEFINED;
/**
* Declares the property as "read only".
*
* Relevant only for Schema "properties" definitions.
*
* This means that it may be sent as part of a response but should not be sent as part of the request.
* If the property is marked as readOnly being true and is in the required list, the required will take effect on
* the response only. A property must not be marked as both readOnly and writeOnly being true. Default value is
* false.
*
* @var bool
*/
public $readOnly = Generator::UNDEFINED;
/**
* Declares the property as "write only".
*
* Relevant only for Schema "properties" definitions.
* Therefore, it may be sent as part of a request but should not be sent as part of the response.
* If the property is marked as writeOnly being true and is in the required list, the required will take effect on
* the request only. A property must not be marked as both readOnly and writeOnly being true. Default value is
* false.
*
* @var bool
*/
public $writeOnly = Generator::UNDEFINED;
/**
* This may be used only on properties schemas.
*
* It has no effect on root schemas.
* Adds additional metadata to describe the XML representation of this property.
*
* @var Xml
*/
public $xml = Generator::UNDEFINED;
/**
* Additional external documentation for this schema.
*
* @var ExternalDocumentation
*/
public $externalDocs = Generator::UNDEFINED;
/**
* A free-form property to include an example of an instance for this schema.
*
* To represent examples that cannot naturally be represented in JSON or YAML, a string value can be used to
* contain the example with escaping where necessary.
*
* @var mixed
*/
public $example = Generator::UNDEFINED;
/**
* Allows sending a null value for the defined schema.
* Default value is false.
*
* This must not be used when using OpenApi version 3.1,
* instead make the "type" property an array and add "null" as a possible type.
*
* @var bool
*
* @see https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0
*/
public $nullable = Generator::UNDEFINED;
/**
* Specifies that a schema is deprecated and should be transitioned out of usage.
* Default value is false.
*
* @var bool
*/
public $deprecated = Generator::UNDEFINED;
/**
* An instance validates successfully against this property if it validates successfully against all schemas
* defined by this property's value.
*
* @var array<Schema|\OpenApi\Attributes\Schema>
*/
public $allOf = Generator::UNDEFINED;
/**
* An instance validates successfully against this property if it validates successfully against at least one
* schema defined by this property's value.
*
* @var array<Schema|\OpenApi\Attributes\Schema>
*/
public $anyOf = Generator::UNDEFINED;
/**
* An instance validates successfully against this property if it validates successfully against exactly one schema
* defined by this property's value.
*
* @var array<Schema|\OpenApi\Attributes\Schema>
*/
public $oneOf = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.29.
*/
public $not = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#anchor64.
*
* @var bool|AdditionalProperties
*/
public $additionalProperties = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.10.
*/
public $additionalItems = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.14.
*/
public $contains = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.19.
*/
public $patternProperties = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.21.
*/
public $dependencies = Generator::UNDEFINED;
/**
* http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.22.
*/
public $propertyNames = Generator::UNDEFINED;
/**
* http://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.1.3.
*
* @var mixed
*/
public $const = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'title' => 'string',
'description' => 'string',
'required' => '[string]',
'format' => 'string',
'collectionFormat' => ['csv', 'ssv', 'tsv', 'pipes', 'multi'],
'maximum' => 'number',
'exclusiveMaximum' => 'boolean|integer|number',
'minimum' => 'number',
'exclusiveMinimum' => 'boolean|integer|number',
'maxLength' => 'integer',
'minLength' => 'integer',
'pattern' => 'string',
'maxItems' => 'integer',
'minItems' => 'integer',
'uniqueItems' => 'boolean',
'multipleOf' => 'integer',
'allOf' => '[' . Schema::class . ']',
'oneOf' => '[' . Schema::class . ']',
'anyOf' => '[' . Schema::class . ']',
];
/**
* @inheritdoc
*/
public static $_nested = [
Discriminator::class => 'discriminator',
Items::class => 'items',
Property::class => ['properties', 'property'],
ExternalDocumentation::class => 'externalDocs',
Xml::class => 'xml',
AdditionalProperties::class => 'additionalProperties',
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Components::class,
Parameter::class,
PathParameter::class,
MediaType::class,
Header::class,
];
/**
* @inheritdoc
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$data = parent::jsonSerialize();
if (isset($data->const)) {
if ($this->_context->isVersion(OpenApi::VERSION_3_0_0)) {
$data->enum = [$data->const];
unset($data->const);
}
}
return $data;
}
/**
* @inheritdoc
*/
public function validate(array $stack = [], array $skip = [], string $ref = '', $context = null): bool
{
if ($this->type === 'array' && Generator::isDefault($this->items)) {
$this->_context->logger->warning('@OA\\Items() is required when ' . $this->identity() . ' has type "array" in ' . $this->_context);
return false;
}
return parent::validate($stack, $skip, $ref, $context);
}
}
@@ -0,0 +1,138 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* @see [OAI Security Scheme Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#securitySchemeObject).
*
* @Annotation
*/
class SecurityScheme extends AbstractAnnotation
{
/**
* The relative or absolute path to a security scheme.
*
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;
/**
* The key into OpenApi->security array.
*
* @var string
*/
public $securityScheme = Generator::UNDEFINED;
/**
* The type of the security scheme.
*
* @var string|non-empty-array<string>
*/
public $type = Generator::UNDEFINED;
/**
* A short description for security scheme.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* The name of the header or query parameter to be used.
*
* @var string
*/
public $name = Generator::UNDEFINED;
/**
* Required The location of the API key.
*
* @var string
*/
public $in = Generator::UNDEFINED;
/**
* The flow used by the OAuth2 security scheme.
*
* @var Flow[]
*/
public $flows = Generator::UNDEFINED;
/**
* A hint to the client to identify how the bearer token is formatted.
*
* Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes.
*
* @var string
*/
public $bearerFormat = Generator::UNDEFINED;
/**
* The name of the HTTP Authorization scheme.
*
* @see [RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1)
*
* @var string
*/
public $scheme = Generator::UNDEFINED;
/**
* OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL.
*
* @var string
*/
public $openIdConnectUrl = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['securityScheme', 'type'];
/**
* @inheritdoc
*/
public static $_types = [
'type' => ['http', 'apiKey', 'oauth2', 'openIdConnect'],
'description' => 'string',
'name' => 'string',
'bearerFormat' => 'string',
'in' => ['query', 'header', 'cookie'],
];
/**
* @inheritdoc
*/
public static $_nested = [
Flow::class => ['flows', 'flow'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_parents = [
Components::class,
];
/**
* @inheritdoc
*/
public function merge(array $annotations, bool $ignore = false): array
{
$unmerged = parent::merge($annotations, $ignore);
if ($this->type === 'oauth2') {
$this->name = Generator::UNDEFINED;
}
return $unmerged;
}
}
+87
View File
@@ -0,0 +1,87 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* An object representing a server.
*
* @see [OAI Server Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#server-object)
*
* @Annotation
*/
class Server extends AbstractAnnotation
{
/**
* An URL to the target host.
*
* This URL supports Server Variables and may be relative,
* to indicate that the host location is relative to the location where the OpenAPI document is being served.
* Variable substitutions will be made when a variable is named in {brackets}.
*
* @var string
*/
public $url = Generator::UNDEFINED;
/**
* An optional string describing the host designated by the URL.
*
* CommonMark syntax may be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* A map between a variable name and its value.
*
* The value is used for substitution in the server's URL template.
*
* @var ServerVariable[]
*/
public $variables = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
PathItem::class,
Operation::class,
Get::class,
Post::class,
Put::class,
Delete::class,
Patch::class,
Head::class,
Options::class,
Trace::class,
Link::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
ServerVariable::class => ['variables', 'serverVariable'],
Attachable::class => ['attachables'],
];
/**
* @inheritdoc
*/
public static $_required = ['url'];
/**
* @inheritdoc
*/
public static $_types = [
'url' => 'string',
'description' => 'string',
];
}
@@ -0,0 +1,87 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* An object representing a server variable for server URL template substitution.
*
* @see [OAI Server Variable Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#server-variable-object)
*
* @Annotation
*/
class ServerVariable extends AbstractAnnotation
{
/**
* The key into Server->variables array.
*
* @var string
*/
public $serverVariable = Generator::UNDEFINED;
/**
* An enumeration of values to be used if the substitution options are from a limited set.
*
* @var string[]|int[]|float[]|bool[]|\UnitEnum[]|class-string
*/
public $enum = Generator::UNDEFINED;
/**
* The default value to use for substitution, and to send, if an alternate value is not supplied.
*
* Unlike the Schema Object's default, this value must be provided by the consumer.
*
* @var string
*/
public $default = Generator::UNDEFINED;
/**
* A map between a variable name and its value.
*
* The value is used for substitution in the server's URL template.
*
* @var array
*/
public $variables = Generator::UNDEFINED;
/**
* An optional description for the server variable.
*
* CommonMark syntax MAY be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_parents = [
Server::class,
];
/**
* @inheritdoc
*/
public static $_required = ['default'];
/**
* @inheritdoc
*/
public static $_types = [
'default' => 'string',
'description' => 'string',
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
}
+66
View File
@@ -0,0 +1,66 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* @see [OAI Tag Object]( https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#tagObject).
*
* @Annotation
*/
class Tag extends AbstractAnnotation
{
/**
* The name of the tag.
*
* @var string
*/
public $name = Generator::UNDEFINED;
/**
* A short description for the tag. GFM syntax can be used for rich text representation.
*
* @var string
*/
public $description = Generator::UNDEFINED;
/**
* Additional external documentation for this tag.
*
* @var ExternalDocumentation
*/
public $externalDocs = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['name'];
/**
* @inheritdoc
*/
public static $_types = [
'name' => 'string',
'description' => 'string',
];
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
ExternalDocumentation::class => 'externalDocs',
Attachable::class => ['attachables'],
];
}
+25
View File
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
/**
* @Annotation
*/
class Trace extends Operation
{
/**
* @inheritdoc
*/
public $method = 'trace';
/**
* @inheritdoc
*/
public static $_parents = [
PathItem::class,
];
}
+43
View File
@@ -0,0 +1,43 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Acts like a `PathItem` with the main difference being that it requires `webhook` instead of `path`.
*
* @Annotation
*/
class Webhook extends PathItem
{
/**
* Key for the webhooks map.
*
* @var string
*/
public $webhook = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_required = ['webhook'];
/**
* @inheritdoc
*/
public static $_parents = [
OpenApi::class,
];
/**
* @inheritdoc
*/
public static $_types = [
'webhook' => 'string',
];
}
+95
View File
@@ -0,0 +1,95 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* @see [OAI XML Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#xmlObject).
*
* @Annotation
*/
class Xml extends AbstractAnnotation
{
/**
* Replaces the name of the element/attribute used for the described schema property.
*
* When defined within the Items Object (items), it will affect the name of the individual XML elements within the list.
* When defined alongside type being array (outside the items), it will affect the wrapping element
* and only if wrapped is <code>true</code>.
*
* If wrapped is <code>false</code>, it will be ignored.
*
* @var string
*/
public $name = Generator::UNDEFINED;
/**
* The URL of the namespace definition. Value SHOULD be in the form of a URL.
*
* @var string
*/
public $namespace = Generator::UNDEFINED;
/**
* The prefix to be used for the name.
*
* @var string
*/
public $prefix = Generator::UNDEFINED;
/**
* Declares whether the property definition translates to an attribute instead of an element.
*
* Default value is <code>false</code>.
*
* @var bool
*/
public $attribute = Generator::UNDEFINED;
/**
* MAY be used only for an array definition.
*
* Signifies whether the array is wrapped (for example <code>&lt;books>&lt;book/>&lt;book/>&lt;/books></code>)
* or unwrapped (<code>&lt;book/>&lt;book/></code>).
*
* Default value is false. The definition takes effect only when defined alongside type being array (outside the items).
*
* @var bool
*/
public $wrapped = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_types = [
'name' => 'string',
'namespace' => 'string',
'prefix' => 'string',
'attribute' => 'boolean',
'wrapped' => 'boolean',
];
/**
* @inheritdoc
*/
public static $_parents = [
AdditionalProperties::class,
Schema::class,
Property::class,
Schema::class,
Items::class,
XmlContent::class,
];
/**
* @inheritdoc
*/
public static $_nested = [
Attachable::class => ['attachables'],
];
}
@@ -0,0 +1,43 @@
<?php declare(strict_types=1);
/**
* @license Apache 2.0
*/
namespace OpenApi\Annotations;
use OpenApi\Generator;
/**
* Shorthand for a xml response.
*
* Use as `@OA\Schema` inside a `Response` and `MediaType`->`'application/xml'` will be generated.
*
* @Annotation
*/
class XmlContent extends Schema
{
/**
* @var array<string,Examples>
*/
public $examples = Generator::UNDEFINED;
/**
* @inheritdoc
*/
public static $_parents = [];
/**
* @inheritdoc
*/
public static $_nested = [
Discriminator::class => 'discriminator',
Items::class => 'items',
Property::class => ['properties', 'property'],
ExternalDocumentation::class => 'externalDocs',
Xml::class => 'xml',
AdditionalProperties::class => 'additionalProperties',
Examples::class => ['examples', 'example'],
Attachable::class => ['attachables'],
];
}