Skip to content

Commit

Permalink
Set examples for nested file parameters properly
Browse files Browse the repository at this point in the history
  • Loading branch information
shalvah committed Jun 29, 2021
1 parent 8b93252 commit 6354b55
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 52 deletions.
37 changes: 26 additions & 11 deletions camel/Output/OutputEndpointData.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,13 @@ public function __construct(array $parameters = [])

$this->boundUri = u::getUrlWithBoundParameters($this->uri, $this->cleanUrlParameters);

[$files, $regularParameters] = collect($this->cleanBodyParameters)
->partition(
function ($example) {
// We'll only check two levels: a file, or an array of files
return is_array($example) && isset($example[0])
? $example[0] instanceof UploadedFile
: $example instanceof UploadedFile;
}
);
[$files, $regularParameters] = static::getFileParameters($this->cleanBodyParameters);

if (count($files)) {
$this->headers['Content-Type'] = 'multipart/form-data';
}
$this->fileParameters = $files->toArray();
$this->cleanBodyParameters = $regularParameters->toArray();
$this->fileParameters = $files;
$this->cleanBodyParameters = $regularParameters;
}

/**
Expand Down Expand Up @@ -168,4 +161,26 @@ public function hasHeadersOrQueryOrBodyParams(): bool
|| !empty($this->cleanQueryParameters)
|| !empty($this->cleanBodyParameters);
}

public static function getFileParameters(array $parameters): array
{
$files = [];
$regularParameters = [];
foreach ($parameters as $name => $example) {
if ($example instanceof UploadedFile) {
$files[$name] = $example;
} else if (is_array($example)) {
[$subFiles, $subRegulars] = static::getFileParameters($example);
foreach ($subFiles as $subName => $subExample) {
$files[$name][$subName] = $subExample;
}
foreach ($subRegulars as $subName => $subExample) {
$regularParameters[$name][$subName] = $subExample;
}
} else {
$regularParameters[$name] = $example;
}
}
return [$files, $regularParameters];
}
}
83 changes: 53 additions & 30 deletions resources/views/components/field-details.blade.php
Original file line number Diff line number Diff line change
@@ -1,36 +1,59 @@
<b><code>{{ $name }}</code></b>&nbsp;&nbsp;@if($type)<small>{{ $type }}</small>@endif @if(!$required)
<i>optional</i>@endif &nbsp;
@if(($isInput ?? true) && empty($hasChildren))
@php
$isList = Str::endsWith($type, '[]');
$fullName =str_replace('[]', '.0', $name);
$baseType = $isList ? substr($type, 0, -2) : $type;
// Ignore the first '[]': the frontend will take care of it
while (\Str::endsWith($baseType, '[]')) {
$fullName .= '.0';
$baseType = substr($baseType, 0, -2);
}
switch($baseType) {
case 'number':
case 'integer':
$inputType = 'number';
break;
case 'file':
$inputType = 'file';
break;
default:
$inputType = 'text';
}
@endphp
@if($type === 'boolean')
<label data-endpoint="{{ $endpointId }}" hidden><input type="radio" name="{{ $fullName }}" value="{{$component === 'body' ? 'true' : 1}}" data-endpoint="{{ $endpointId }}" data-component="{{ $component }}" @if($required)required @endif><code>true</code></label>
<label data-endpoint="{{ $endpointId }}" hidden><input type="radio" name="{{ $fullName }}" value="{{$component === 'body' ? 'false' : 0}}" data-endpoint="{{ $endpointId }}" data-component="{{ $component }}" @if($required)required @endif><code>false</code></label>
@elseif($isList)
<input type="{{ $inputType }}" name="{{ $fullName.".0" }}" data-endpoint="{{ $endpointId }}" data-component="{{ $component }}" @if($required)required @endif hidden>
<input type="{{ $inputType }}" name="{{ $fullName.".1" }}" data-endpoint="{{ $endpointId }}" data-component="{{ $component }}" hidden>
@else
<input type="{{ $inputType }}" name="{{ $fullName }}" data-endpoint="{{ $endpointId }}" data-component="{{ $component }}" @if($required)required @endif hidden>
@endif
@php
$isList = Str::endsWith($type, '[]');
$fullName =str_replace('[]', '.0', $name);
$baseType = $isList ? substr($type, 0, -2) : $type;
// Ignore the first '[]': the frontend will take care of it
while (\Str::endsWith($baseType, '[]')) {
$fullName .= '.0';
$baseType = substr($baseType, 0, -2);
}
switch($baseType) {
case 'number':
case 'integer':
$inputType = 'number';
break;
case 'file':
$inputType = 'file';
break;
default:
$inputType = 'text';
}
@endphp
@if($type === 'boolean')
<label data-endpoint="{{ $endpointId }}" hidden>
<input type="radio" name="{{ $fullName }}"
value="{{$component === 'body' ? 'true' : 1}}"
data-endpoint="{{ $endpointId }}"
data-component="{{ $component }}" @if($required)required @endif
>
<code>true</code>
</label>
<label data-endpoint="{{ $endpointId }}" hidden>
<input type="radio" name="{{ $fullName }}"
value="{{$component === 'body' ? 'false' : 0}}"
data-endpoint="{{ $endpointId }}"
data-component="{{ $component }}" @if($required)required @endif
>
<code>false</code>
</label>
@elseif($isList)
<input type="{{ $inputType }}"
name="{{ $fullName.".0" }}"
data-endpoint="{{ $endpointId }}"
data-component="{{ $component }}" @if($required)required @endif hidden>
<input type="{{ $inputType }}"
name="{{ $fullName.".1" }}"
data-endpoint="{{ $endpointId }}"
data-component="{{ $component }}" hidden>
@else
<input type="{{ $inputType }}"
name="{{ $fullName }}"
data-endpoint="{{ $endpointId }}"
data-component="{{ $component }}" @if($required)required @endif hidden>
@endif
@endif
<br>
{!! Parsedown::instance()->text($description) !!}
17 changes: 7 additions & 10 deletions src/Extracting/Extractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Knuckles\Camel\Extraction\ResponseField;
use Knuckles\Camel\Output\OutputEndpointData;
use Knuckles\Scribe\Extracting\Strategies\Strategy;
use Knuckles\Scribe\Tools\DocumentationConfig;

Expand Down Expand Up @@ -102,19 +103,15 @@ public function processRoute(Route $route, array $routeRules = []): ExtractedEnd
// Set content type if the user forgot to set it
$endpointData->headers['Content-Type'] = 'application/json';
}
// We need to do all this so response calls can work correctly
[$files, $regularParameters] = collect($endpointData->cleanBodyParameters)
->partition(
function ($example) {
return $example instanceof UploadedFile
|| (is_array($example) && ($example[0] ?? null) instanceof UploadedFile);
}
);
// We need to do all this so response calls can work correctly,
// even though they're only needed for output
// Note that this
[$files, $regularParameters] = OutputEndpointData::getFileParameters($endpointData->cleanBodyParameters);
if (count($files)) {
$endpointData->headers['Content-Type'] = 'multipart/form-data';
}
$endpointData->fileParameters = $files->toArray();
$endpointData->cleanBodyParameters = $regularParameters->toArray();
$endpointData->fileParameters = $files;
$endpointData->cleanBodyParameters = $regularParameters;

$this->fetchResponses($endpointData, $routeRules);

Expand Down
2 changes: 1 addition & 1 deletion tests/Fixtures/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
],
"body": {
"mode": "raw",
"raw": "[{\"first_name\":\"John\",\"last_name\":\"Doe\",\"contacts\":[{\"first_name\":\"Janelle\",\"last_name\":\"Monáe\"},[]],\"roles\":[\"Admin\"]},{\"first_name\":\"John\",\"last_name\":\"Doe\",\"contacts\":[{\"first_name\":\"Janelle\",\"last_name\":\"Monáe\"},[]],\"roles\":[\"Admin\"]}]"
"raw": "[{\"first_name\":\"John\",\"last_name\":\"Doe\",\"contacts\":[{\"first_name\":\"Janelle\",\"last_name\":\"Monáe\"}],\"roles\":[\"Admin\"]},{\"first_name\":\"John\",\"last_name\":\"Doe\",\"contacts\":[{\"first_name\":\"Janelle\",\"last_name\":\"Monáe\"}],\"roles\":[\"Admin\"]}]"
},
"description": "",
"auth": {
Expand Down

0 comments on commit 6354b55

Please sign in to comment.