Skip to content

Commit

Permalink
added feature/nullable (#834)
Browse files Browse the repository at this point in the history
Co-authored-by: Shalvah <[email protected]>
  • Loading branch information
MertcanDinler and shalvah authored Oct 3, 2024
1 parent 8274a80 commit 4d4a44e
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 5 deletions.
1 change: 1 addition & 0 deletions camel/Extraction/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Parameter extends BaseDTO
public string $type = 'string';
public array $enumValues = [];
public bool $exampleWasSpecified = false;
public bool $nullable = false;

public function __construct(array $parameters = [])
{
Expand Down
2 changes: 2 additions & 0 deletions src/Attributes/GenericParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public function __construct(
public ?bool $required = true,
public mixed $example = null, /* Pass 'No-example' to omit the example */
public mixed $enum = null, // Can pass a list of values, or a native PHP enum
public ?bool $nullable = false,
) {
}

Expand All @@ -26,6 +27,7 @@ public function toArray()
"required" => $this->required,
"example" => $this->example,
"enumValues" => $this->getEnumValues(),
'nullable' => $this->nullable,
];
}

Expand Down
3 changes: 2 additions & 1 deletion src/Attributes/ResponseField.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public function __construct(
public ?string $description = '',
public ?bool $required = true,
public mixed $example = null, /* Pass 'No-example' to omit the example */
public mixed $enum = null, // Can pass a list of values, or a native PHP enum
public mixed $enum = null, // Can pass a list of values, or a native PHP enum,
public ?bool $nullable = false,
) {
}
}
9 changes: 9 additions & 0 deletions src/Extracting/ParsesValidationRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function getParametersFromValidationRules(array $validationRules, array $
'type' => null,
'example' => self::$MISSING_VALUE,
'description' => $description,
'nullable' => false,
];
$dependentRules[$parameter] = [];

Expand All @@ -69,6 +70,11 @@ public function getParametersFromValidationRules(array $validationRules, array $
}

$parameterData['name'] = $parameter;

if ($parameterData['required'] === true){
$parameterData['nullable'] = false;
}

$parameters[$parameter] = $parameterData;
} catch (Throwable $e) {
if ($e instanceof ScribeException) {
Expand Down Expand Up @@ -531,6 +537,9 @@ protected function parseRule($rule, array &$parameterData, bool $independentOnly
case 'different':
$parameterData['description'] .= " The value and <code>{$arguments[0]}</code> must be different.";
break;
case 'nullable':
$parameterData['nullable'] = true;
break;
case 'exists':
$parameterData['description'] .= " The <code>{$arguments[1]}</code> of an existing record in the {$arguments[0]} table.";
break;
Expand Down
4 changes: 4 additions & 0 deletions src/Extracting/Strategies/GetParamsFromAttributeStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ protected function normalizeParameterData(array $data): array
$data['example'] = null;
}

if ($data['required']){
$data['nullable'] = false;
}

$data['description'] = trim($data['description'] ?? '');
return $data;
}
Expand Down
8 changes: 8 additions & 0 deletions src/Writing/OpenAPISpecWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ public function generateFieldData($field): array
'type' => 'string',
'format' => 'binary',
'description' => $field->description ?: '',
'nullable' => $field->nullable,
];
} else if (Utils::isArrayType($field->type)) {
$baseType = Utils::getBaseTypeFromArrayType($field->type);
Expand All @@ -500,6 +501,10 @@ public function generateFieldData($field): array
$baseItem['enum'] = $field->enumValues;
}

if ($field->nullable) {
$baseItem['nullable'] = true;
}

$fieldData = [
'type' => 'array',
'description' => $field->description ?: '',
Expand All @@ -509,6 +514,7 @@ public function generateFieldData($field): array
'name' => '',
'type' => $baseType,
'example' => ($field->example ?: [null])[0],
'nullable' => $field->nullable,
])
: $baseItem,
];
Expand All @@ -535,6 +541,7 @@ public function generateFieldData($field): array
'type' => 'object',
'description' => $field->description ?: '',
'example' => $field->example,
'nullable'=> $field->nullable,
'properties' => $this->objectIfEmpty(collect($field->__fields)->mapWithKeys(function ($subfield, $subfieldName) {
return [$subfieldName => $this->generateFieldData($subfield)];
})->all()),
Expand All @@ -544,6 +551,7 @@ public function generateFieldData($field): array
'type' => static::normalizeTypeName($field->type),
'description' => $field->description ?: '',
'example' => $field->example,
'nullable' => $field->nullable,
];
if (!empty($field->enumValues)) {
$schema['enum'] = $field->enumValues;
Expand Down
14 changes: 11 additions & 3 deletions tests/Fixtures/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ paths:
type: string
description: 'Name of image.'
example: cat.jpg
nullable: false
image:
type: string
format: binary
description: 'The image.'
nullable: false
required:
- name
- image
Expand Down Expand Up @@ -95,6 +97,7 @@ paths:
type: string
description: 'The id of the location.'
example: consequatur
nullable: false
-
in: query
name: user_id
Expand All @@ -105,6 +108,7 @@ paths:
type: string
description: 'The id of the user.'
example: me
nullable: false
-
in: query
name: page
Expand All @@ -115,6 +119,7 @@ paths:
type: string
description: 'The page number.'
example: '4'
nullable: false
-
in: query
name: filters
Expand All @@ -125,6 +130,7 @@ paths:
type: string
description: 'The filters.'
example: consequatur
nullable: false
-
in: query
name: url_encoded
Expand All @@ -135,6 +141,7 @@ paths:
type: string
description: 'Used for testing that URL parameters will be URL-encoded where needed.'
example: '+ []&='
nullable: false
-
in: header
name: Custom-Header
Expand Down Expand Up @@ -192,6 +199,7 @@ paths:
type: string
description: ''
example: consequatur
nullable: false
-
in: header
name: Custom-Header
Expand Down Expand Up @@ -293,9 +301,9 @@ paths:
items:
type: object
properties:
first_name: { type: string, description: 'The first name of the user.', example: John }
last_name: { type: string, description: 'The last name of the user.', example: Doe }
contacts: { type: array, description: 'Contact info', example: [ [ ] ], items: { type: object, properties: { first_name: { type: string, description: 'The first name of the contact.', example: Janelle }, last_name: { type: string, description: 'The last name of the contact.', example: Monáe } }, required: [ first_name, last_name ] } }
first_name: { type: string, description: 'The first name of the user.', example: John, nullable: false }
last_name: { type: string, description: 'The last name of the user.', example: Doe, nullable: false}
contacts: { type: array, description: 'Contact info', example: [ [ ] ], items: { type: object, properties: { first_name: { type: string, description: 'The first name of the contact.', example: Janelle, nullable: false }, last_name: { type: string, description: 'The last name of the contact.', example: Monáe, nullable: false } }, required: [ first_name, last_name ] } }
roles: { type: array, description: 'The name of the role.', example: [ Admin ], items: { type: string } }
required:
- first_name
Expand Down
1 change: 1 addition & 0 deletions tests/GenerateDocumentation/OutputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ public function will_not_overwrite_manually_modified_content_unless_force_flag_i
'enumValues' => [],
'custom' => [],
'exampleWasSpecified' => false,
'nullable' => false,
];
$group['endpoints'][0]['urlParameters']['a_param'] = $extraParam;
file_put_contents($firstGroupFilePath, Yaml::dump(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,85 +32,115 @@ public function can_fetch_from_bodyparam_attribute()
'required' => true,
'description' => 'The id of the user.',
'example' => 9,
'nullable' => false,
],
'room_id' => [
'type' => 'string',
'required' => false,
'description' => 'The id of the room.',
'nullable' => false,
],
'forever' => [
'type' => 'boolean',
'required' => false,
'description' => 'Whether to ban the user forever.',
'example' => false,
'nullable' => false,
],
'another_one' => [
'type' => 'number',
'required' => false,
'description' => 'Just need something here.',
'nullable' => false,
],
'yet_another_param' => [
'type' => 'object',
'required' => true,
'description' => 'Some object params.',
'nullable' => false,
],
'yet_another_param.name' => [
'type' => 'string',
'description' => '',
'required' => true,
'nullable' => false,
],
'even_more_param' => [
'type' => 'number[]',
'description' => 'A list of numbers',
'required' => false,
'nullable' => false,
],
'book' => [
'type' => 'object',
'description' => 'Book information',
'required' => false,
'nullable' => false,
],
'book.name' => [
'type' => 'string',
'description' => '',
'required' => true,
'nullable' => false,
],
'book.author_id' => [
'type' => 'integer',
'description' => '',
'required' => true,
'nullable' => false,
],
'book.pages_count' => [
'type' => 'integer',
'description' => '',
'required' => true,
'nullable' => false,
],
'ids' => [
'type' => 'integer[]',
'description' => '',
'required' => true,
'nullable' => false,
],
'state' => [
'type' => 'string',
'description' => '',
'required' => true,
'enumValues' => ["active", "pending"]
'enumValues' => ["active", "pending"],
'nullable' => false,
],
'users' => [
'type' => 'object[]',
'description' => 'Users\' details',
'required' => false,
'nullable' => false,
],
'users[].first_name' => [
'type' => 'string',
'description' => 'The first name of the user.',
'required' => false,
'example' => 'John',
'nullable' => false,
],
'users[].last_name' => [
'type' => 'string',
'description' => 'The last name of the user.',
'required' => false,
'example' => 'Doe',
'nullable' => false,
],
'note' => [
'type' => 'string',
'description' => '',
'required' => false,
'example' => 'This is a note.',
'nullable' => true,
],
'required_note' => [
'type' => 'string',
'description' => '',
'required' => true,
'example' => 'This is a note.',
'nullable' => false,
],
], $results);
}
Expand Down Expand Up @@ -226,6 +256,8 @@ class BodyParamAttributeTestController
#[BodyParam("users", "object[]", "Users' details", required: false)]
#[BodyParam("users[].first_name", "string", "The first name of the user.", example: "John", required: false)]
#[BodyParam("users[].last_name", "string", "The last name of the user.", example: "Doe", required: false)]
#[BodyParam("note", example: "This is a note.", required: false, nullable: true)]
#[BodyParam("required_note", example: "This is a note.", required: true, nullable: true)]
public function methodWithAttributes()
{

Expand Down
Loading

0 comments on commit 4d4a44e

Please sign in to comment.