Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions docs/reference/attributes.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/reference/spec-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -1523,6 +1523,8 @@ without it the schema has no component key and is reported as missing one.
<dd><p>The media type of string content encoding</p></dd>
<dt><strong>contentEncoding</strong> : <span style="font-family: monospace;">string|null</span></dt>
<dd><p>The encoding used for string content (e.g. base64)</p></dd>
<dt><strong>contentSchema</strong> : <span style="font-family: monospace;">Schema|null</span></dt>
<dd><p>Schema for the decoded content described by contentMediaType</p></dd>
<dt><strong>minimum</strong> : <span style="font-family: monospace;">int|float|null</span></dt>
<dd><p>Minimum numeric value (inclusive)</p></dd>
<dt><strong>maximum</strong> : <span style="font-family: monospace;">int|float|null</span></dt>
Expand Down Expand Up @@ -1657,6 +1659,8 @@ schemas with constrained additional properties:
<dd><p>The media type of string content encoding</p></dd>
<dt><strong>contentEncoding</strong> : <span style="font-family: monospace;">string|null</span></dt>
<dd><p>The encoding used for string content (e.g. base64)</p></dd>
<dt><strong>contentSchema</strong> : <span style="font-family: monospace;">Schema|null</span></dt>
<dd><p>Schema for the decoded content described by contentMediaType</p></dd>
<dt><strong>minimum</strong> : <span style="font-family: monospace;">int|float|null</span></dt>
<dd><p>Minimum numeric value (inclusive)</p></dd>
<dt><strong>maximum</strong> : <span style="font-family: monospace;">int|float|null</span></dt>
Expand Down Expand Up @@ -1799,6 +1803,8 @@ Since Items extends Schema, the implicit `OA\Property` shortcut applies — no e
<dd><p>The media type of string content encoding</p></dd>
<dt><strong>contentEncoding</strong> : <span style="font-family: monospace;">string|null</span></dt>
<dd><p>The encoding used for string content (e.g. base64)</p></dd>
<dt><strong>contentSchema</strong> : <span style="font-family: monospace;">Schema|null</span></dt>
<dd><p>Schema for the decoded content described by contentMediaType</p></dd>
<dt><strong>minimum</strong> : <span style="font-family: monospace;">int|float|null</span></dt>
<dd><p>Minimum numeric value (inclusive)</p></dd>
<dt><strong>maximum</strong> : <span style="font-family: monospace;">int|float|null</span></dt>
Expand Down
3 changes: 3 additions & 0 deletions src/Annotations/AbstractAnnotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ public function __construct(array $properties)
$nestedContext = new Context(['nested' => $this], $this->_context);
foreach ($properties as $property => $value) {
if (property_exists($this, $property)) {
if ($value instanceof AbstractAnnotation) {
$value = $this->nested($value, $nestedContext);
}
$this->{$property} = $value;
if (is_array($value)) {
foreach ($value as $key => $annotation) {
Expand Down
86 changes: 86 additions & 0 deletions src/Annotations/JsonSchemaTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,24 @@ trait JsonSchemaTrait
*/
public $contains = Undefined::UNDEFINED;

/**
* @var int
* @since OpenAPI 3.1.0
*/
public $minContains = Undefined::UNDEFINED;

/**
* @var int
* @since OpenAPI 3.1.0
*/
public $maxContains = Undefined::UNDEFINED;

/**
* @var array
* @since OpenAPI 3.1.0
*/
public $prefixItems = Undefined::UNDEFINED;

/**
* @var array
*/
Expand All @@ -145,11 +163,29 @@ trait JsonSchemaTrait
*/
public $unevaluatedProperties = Undefined::UNDEFINED;

/**
* @var mixed
* @since OpenAPI 3.1.0
*/
public $unevaluatedItems = Undefined::UNDEFINED;

/**
* @var mixed
*/
public $dependencies = Undefined::UNDEFINED;

/**
* @var array
* @since OpenAPI 3.1.0
*/
public $dependentRequired = Undefined::UNDEFINED;

/**
* @var array
* @since OpenAPI 3.1.0
*/
public $dependentSchemas = Undefined::UNDEFINED;

/**
* @var mixed
*/
Expand All @@ -160,6 +196,36 @@ trait JsonSchemaTrait
* @since OpenAPI 3.1.0
*/
public $const = Undefined::UNDEFINED;

/**
* @var mixed
* @since OpenAPI 3.1.0
*/
public $if = Undefined::UNDEFINED;

/**
* Applied when `if` succeeds.
*
* @var mixed
* @since OpenAPI 3.1.0
*/
public $then = Undefined::UNDEFINED;

/**
* Applied when `if` fails.
*
* @var mixed
* @since OpenAPI 3.1.0
*/
public $else = Undefined::UNDEFINED;

/**
* Schema for the decoded content described by `contentMediaType`.
*
* @var mixed
* @since OpenAPI 3.1.0
*/
public $contentSchema = Undefined::UNDEFINED;
}

/*
Expand Down Expand Up @@ -189,11 +255,21 @@ trait JsonSchemaTrait
bool|AdditionalProperties|null $additionalProperties = null,
array|null $additionalItems = null,
array|null $contains = null,
int|null $minContains = null,
int|null $maxContains = null,
array|null $prefixItems = null,
array|null $patternProperties = null,
array|null $unevaluatedProperties = null,
mixed $unevaluatedItems = Undefined::UNDEFINED,
mixed $dependencies = Undefined::UNDEFINED,
array|null $dependentRequired = null,
array|null $dependentSchemas = null,
mixed $propertyNames = Undefined::UNDEFINED,
mixed $const = Undefined::UNDEFINED,
mixed $if = Undefined::UNDEFINED,
mixed $then = Undefined::UNDEFINED,
mixed $else = Undefined::UNDEFINED,
mixed $contentSchema = Undefined::UNDEFINED,


** PARENT-PARAMS:
Expand All @@ -214,10 +290,20 @@ trait JsonSchemaTrait
'additionalProperties' => $additionalProperties ?? Undefined::UNDEFINED,
'additionalItems' => $additionalItems ?? Undefined::UNDEFINED,
'contains' => $contains ?? Undefined::UNDEFINED,
'minContains' => $minContains ?? Undefined::UNDEFINED,
'maxContains' => $maxContains ?? Undefined::UNDEFINED,
'prefixItems' => $prefixItems ?? Undefined::UNDEFINED,
'patternProperties' => $patternProperties ?? Undefined::UNDEFINED,
'unevaluatedProperties' => $unevaluatedProperties ?? Undefined::UNDEFINED,
'unevaluatedItems' => $unevaluatedItems,
'dependencies' => $dependencies,
'dependentRequired' => $dependentRequired ?? Undefined::UNDEFINED,
'dependentSchemas' => $dependentSchemas ?? Undefined::UNDEFINED,
'propertyNames' => $propertyNames,
'const' => $const,
'if' => $if,
'then' => $then,
'else' => $else,
'contentSchema' => $contentSchema,

*/
28 changes: 27 additions & 1 deletion src/Annotations/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ class Schema extends AbstractAnnotation
'allOf' => '[' . Schema::class . ']',
'oneOf' => '[' . Schema::class . ']',
'anyOf' => '[' . Schema::class . ']',
'prefixItems' => '[' . Schema::class . ']',
'minContains' => 'integer',
'maxContains' => 'integer',
'contentEncoding' => 'string',
'contentMediaType' => 'string',
];
Expand Down Expand Up @@ -365,6 +368,14 @@ public function jsonSerialize(): \stdClass

if ($this->_context->isVersion('3.0.x')) {
unset($data->examples);
foreach ([
'contains', 'minContains', 'maxContains', 'prefixItems',
'patternProperties', 'propertyNames', 'unevaluatedProperties', 'unevaluatedItems',
'dependentRequired', 'dependentSchemas', 'if', 'then', 'else',
'contentMediaType', 'contentEncoding', 'contentSchema',
] as $keyword) {
unset($data->{$keyword});
}
if (isset($data->const)) {
$data->enum = [$data->const];
unset($data->const);
Expand All @@ -388,7 +399,10 @@ public function validate(?Analysis $analysis = null, string $version = OpenApi::
{
$isValid = parent::validate($analysis, $version, $context);

if ($this->hasType('array') && Undefined::isDefault($this->items)) {
if ($this->hasType('array') && Undefined::isDefault($this->items)
&& (OpenApi::versionMatch($version, '3.0.x')
|| (Undefined::isDefault($this->prefixItems) && Undefined::isDefault($this->contains)))) {
// 3.1 array schemas may describe their items via prefixItems or contains; 3.0 requires items
$this->_context->logger->warning('@OA\\Items() is required when ' . $this->identity() . ' has type "array" in ' . $this->_context);

$isValid = false;
Expand All @@ -399,6 +413,18 @@ public function validate(?Analysis $analysis = null, string $version = OpenApi::
$this->_context->logger->warning(static::shorten(static::class) . '::examples is only allowed as of 3.1.0 in ' . $this->_context);
$isValid = false;
}

// the same keywords the spec compiler warns about; the rest drop silently
foreach (['prefixItems', 'unevaluatedProperties', 'unevaluatedItems'] as $keyword) {
if (!Undefined::isDefault($this->{$keyword})) {
$this->_context->logger->warning($this->identity() . ': ' . $keyword . ' is not supported in OpenAPI 3.0 in ' . $this->_context);
$isValid = false;
}
}
if (!Undefined::isDefault($this->if) || !Undefined::isDefault($this->then) || !Undefined::isDefault($this->else)) {
$this->_context->logger->warning($this->identity() . ': if/then/else is not supported in OpenAPI 3.0 in ' . $this->_context);
$isValid = false;
}
}

// the keyword takes values, so an annotation other than `@OA\Examples` is serialised whole
Expand Down
20 changes: 20 additions & 0 deletions src/Attributes/AdditionalProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,21 @@ public function __construct(
bool|AdditionalProperties|null $additionalProperties = null,
array|null $additionalItems = null,
array|null $contains = null,
int|null $minContains = null,
int|null $maxContains = null,
array|null $prefixItems = null,
array|null $patternProperties = null,
array|null $unevaluatedProperties = null,
mixed $unevaluatedItems = Undefined::UNDEFINED,
mixed $dependencies = Undefined::UNDEFINED,
array|null $dependentRequired = null,
array|null $dependentSchemas = null,
mixed $propertyNames = Undefined::UNDEFINED,
mixed $const = Undefined::UNDEFINED,
mixed $if = Undefined::UNDEFINED,
mixed $then = Undefined::UNDEFINED,
mixed $else = Undefined::UNDEFINED,
mixed $contentSchema = Undefined::UNDEFINED,

// abstract annotation
?array $x = null,
Expand Down Expand Up @@ -123,11 +133,21 @@ public function __construct(
'additionalProperties' => $additionalProperties ?? Undefined::UNDEFINED,
'additionalItems' => $additionalItems ?? Undefined::UNDEFINED,
'contains' => $contains ?? Undefined::UNDEFINED,
'minContains' => $minContains ?? Undefined::UNDEFINED,
'maxContains' => $maxContains ?? Undefined::UNDEFINED,
'prefixItems' => $prefixItems ?? Undefined::UNDEFINED,
'patternProperties' => $patternProperties ?? Undefined::UNDEFINED,
'unevaluatedProperties' => $unevaluatedProperties ?? Undefined::UNDEFINED,
'unevaluatedItems' => $unevaluatedItems,
'dependencies' => $dependencies,
'dependentRequired' => $dependentRequired ?? Undefined::UNDEFINED,
'dependentSchemas' => $dependentSchemas ?? Undefined::UNDEFINED,
'propertyNames' => $propertyNames,
'const' => $const,
'if' => $if,
'then' => $then,
'else' => $else,
'contentSchema' => $contentSchema,

// abstract annotation
'x' => $x ?? Undefined::UNDEFINED,
Expand Down
20 changes: 20 additions & 0 deletions src/Attributes/Items.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,21 @@ public function __construct(
bool|AdditionalProperties|null $additionalProperties = null,
array|null $additionalItems = null,
array|null $contains = null,
int|null $minContains = null,
int|null $maxContains = null,
array|null $prefixItems = null,
array|null $patternProperties = null,
array|null $unevaluatedProperties = null,
mixed $unevaluatedItems = Undefined::UNDEFINED,
mixed $dependencies = Undefined::UNDEFINED,
array|null $dependentRequired = null,
array|null $dependentSchemas = null,
mixed $propertyNames = Undefined::UNDEFINED,
mixed $const = Undefined::UNDEFINED,
mixed $if = Undefined::UNDEFINED,
mixed $then = Undefined::UNDEFINED,
mixed $else = Undefined::UNDEFINED,
mixed $contentSchema = Undefined::UNDEFINED,

// abstract annotation
?array $x = null,
Expand Down Expand Up @@ -123,11 +133,21 @@ public function __construct(
'additionalProperties' => $additionalProperties ?? Undefined::UNDEFINED,
'additionalItems' => $additionalItems ?? Undefined::UNDEFINED,
'contains' => $contains ?? Undefined::UNDEFINED,
'minContains' => $minContains ?? Undefined::UNDEFINED,
'maxContains' => $maxContains ?? Undefined::UNDEFINED,
'prefixItems' => $prefixItems ?? Undefined::UNDEFINED,
'patternProperties' => $patternProperties ?? Undefined::UNDEFINED,
'unevaluatedProperties' => $unevaluatedProperties ?? Undefined::UNDEFINED,
'unevaluatedItems' => $unevaluatedItems,
'dependencies' => $dependencies,
'dependentRequired' => $dependentRequired ?? Undefined::UNDEFINED,
'dependentSchemas' => $dependentSchemas ?? Undefined::UNDEFINED,
'propertyNames' => $propertyNames,
'const' => $const,
'if' => $if,
'then' => $then,
'else' => $else,
'contentSchema' => $contentSchema,

// abstract annotation
'x' => $x ?? Undefined::UNDEFINED,
Expand Down
20 changes: 20 additions & 0 deletions src/Attributes/JsonContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,21 @@ public function __construct(
bool|AdditionalProperties|null $additionalProperties = null,
array|null $additionalItems = null,
array|null $contains = null,
int|null $minContains = null,
int|null $maxContains = null,
array|null $prefixItems = null,
array|null $patternProperties = null,
array|null $unevaluatedProperties = null,
mixed $unevaluatedItems = Undefined::UNDEFINED,
mixed $dependencies = Undefined::UNDEFINED,
array|null $dependentRequired = null,
array|null $dependentSchemas = null,
mixed $propertyNames = Undefined::UNDEFINED,
mixed $const = Undefined::UNDEFINED,
mixed $if = Undefined::UNDEFINED,
mixed $then = Undefined::UNDEFINED,
mixed $else = Undefined::UNDEFINED,
mixed $contentSchema = Undefined::UNDEFINED,

// abstract annotation
?array $x = null,
Expand Down Expand Up @@ -147,11 +157,21 @@ public function __construct(
'additionalProperties' => $additionalProperties ?? Undefined::UNDEFINED,
'additionalItems' => $additionalItems ?? Undefined::UNDEFINED,
'contains' => $contains ?? Undefined::UNDEFINED,
'minContains' => $minContains ?? Undefined::UNDEFINED,
'maxContains' => $maxContains ?? Undefined::UNDEFINED,
'prefixItems' => $prefixItems ?? Undefined::UNDEFINED,
'patternProperties' => $patternProperties ?? Undefined::UNDEFINED,
'unevaluatedProperties' => $unevaluatedProperties ?? Undefined::UNDEFINED,
'unevaluatedItems' => $unevaluatedItems,
'dependencies' => $dependencies,
'dependentRequired' => $dependentRequired ?? Undefined::UNDEFINED,
'dependentSchemas' => $dependentSchemas ?? Undefined::UNDEFINED,
'propertyNames' => $propertyNames,
'const' => $const,
'if' => $if,
'then' => $then,
'else' => $else,
'contentSchema' => $contentSchema,

// abstract annotation
'x' => $x ?? Undefined::UNDEFINED,
Expand Down
Loading