Skip to content

Commit 05eff05

Browse files
committed
Updates php-nextgen and psr-18
1 parent e9046a6 commit 05eff05

35 files changed

Lines changed: 523 additions & 788 deletions

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpNextgenClientCodegen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public void processOpts() {
121121

122122
supportingFiles.add(new SupportingFile("ApiException.mustache", toSrcPath(invokerPackage, srcBasePath), "ApiException.php"));
123123
supportingFiles.add(new SupportingFile("Configuration.mustache", toSrcPath(invokerPackage, srcBasePath), "Configuration.php"));
124+
supportingFiles.add(new SupportingFile("FormDataProcessor.mustache", toSrcPath(invokerPackage, srcBasePath), "FormDataProcessor.php"));
124125
supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toSrcPath(invokerPackage, srcBasePath), "ObjectSerializer.php"));
125126
supportingFiles.add(new SupportingFile("ModelInterface.mustache", toSrcPath(modelPackage, srcBasePath), "ModelInterface.php"));
126127
supportingFiles.add(new SupportingFile("HeaderSelector.mustache", toSrcPath(invokerPackage, srcBasePath), "HeaderSelector.php"));
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
<?php
2+
/**
3+
* FormDataProcessor
4+
* PHP version 8.1
5+
*
6+
* @category Class
7+
* @package {{invokerPackage}}
8+
* @author OpenAPI Generator team
9+
* @link https://openapi-generator.tech
10+
*/
11+
12+
{{>partial_header}}
13+
/**
14+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
15+
* https://openapi-generator.tech
16+
* Do not edit the class manually.
17+
*/
18+
19+
namespace {{invokerPackage}};
20+
21+
use ArrayAccess;
22+
use DateTime;
23+
use GuzzleHttp\Psr7\Utils;
24+
use Psr\Http\Message\StreamInterface;
25+
use SplFileObject;
26+
use {{modelPackage}}\ModelInterface;
27+
28+
class FormDataProcessor
29+
{
30+
/**
31+
* Tags whether payload passed to ::prepare() contains one or more
32+
* SplFileObject or stream values.
33+
*/
34+
public bool $has_file = false;
35+
36+
/**
37+
* Take value and turn it into an array suitable for inclusion in
38+
* the http body (form parameter). If it's a string, pass through unchanged
39+
* If it's a datetime object, format it in ISO8601
40+
*
41+
* @param array<string|bool|array|DateTime|ArrayAccess|SplFileObject> $values the value of the form parameter
42+
*
43+
* @return array [key => value] of formdata
44+
*/
45+
public function prepare(array $values): array
46+
{
47+
$this->has_file = false;
48+
$result = [];
49+
50+
foreach ($values as $k => $v) {
51+
if ($v === null) {
52+
continue;
53+
}
54+
55+
$result[$k] = $this->makeFormSafe($v);
56+
}
57+
58+
return $result;
59+
}
60+
61+
/**
62+
* Flattens a multi-level array of data and generates a single-level array
63+
* compatible with formdata - a single-level array where the keys use bracket
64+
* notation to signify nested data.
65+
*
66+
* credit: https://github.com/FranBar1966/FlatPHP
67+
*/
68+
public static function flatten(array $source, string $start = ''): array
69+
{
70+
$opt = [
71+
'prefix' => '[',
72+
'suffix' => ']',
73+
'suffix-end' => true,
74+
'prefix-list' => '[',
75+
'suffix-list' => ']',
76+
'suffix-list-end' => true,
77+
];
78+
79+
if ($start === '') {
80+
$currentPrefix = '';
81+
$currentSuffix = '';
82+
$currentSuffixEnd = false;
83+
} elseif (array_is_list($source)) {
84+
$currentPrefix = $opt['prefix-list'];
85+
$currentSuffix = $opt['suffix-list'];
86+
$currentSuffixEnd = $opt['suffix-list-end'];
87+
} else {
88+
$currentPrefix = $opt['prefix'];
89+
$currentSuffix = $opt['suffix'];
90+
$currentSuffixEnd = $opt['suffix-end'];
91+
}
92+
93+
$currentName = $start;
94+
$result = [];
95+
96+
foreach ($source as $key => $val) {
97+
$currentName .= $currentPrefix . $key;
98+
99+
if (is_array($val) && !empty($val)) {
100+
$currentName .= $currentSuffix;
101+
$result += self::flatten($val, $currentName);
102+
} else {
103+
if ($currentSuffixEnd) {
104+
$currentName .= $currentSuffix;
105+
}
106+
107+
$result[$currentName] = ObjectSerializer::toString($val);
108+
}
109+
110+
$currentName = $start;
111+
}
112+
113+
return $result;
114+
}
115+
116+
/**
117+
* formdata must be limited to scalars or arrays of scalar values,
118+
* or a resource for a file upload. Here we iterate through all available
119+
* data and identify how to handle each scenario
120+
*
121+
* @param string|bool|array|DateTime|ArrayAccess|SplFileObject $value
122+
*/
123+
protected function makeFormSafe(mixed $value)
124+
{
125+
if ($value instanceof SplFileObject) {
126+
return $this->processFiles([$value])[0];
127+
}
128+
129+
if (is_resource($value)) {
130+
$this->has_file = true;
131+
132+
return $value;
133+
}
134+
135+
if ($value instanceof ModelInterface) {
136+
return $this->processModel($value);
137+
}
138+
139+
if (is_array($value) || is_object($value)) {
140+
$data = [];
141+
142+
foreach ($value as $k => $v) {
143+
$data[$k] = $this->makeFormSafe($v);
144+
}
145+
146+
return $data;
147+
}
148+
149+
return ObjectSerializer::toString($value);
150+
}
151+
152+
/**
153+
* We are able to handle nested ModelInterface. We do not simply call
154+
* json_decode(json_encode()) because any given model may have binary data
155+
* or other data that cannot be serialized to a JSON string
156+
*/
157+
protected function processModel(ModelInterface $model): array
158+
{
159+
$result = [];
160+
161+
foreach ($model::openAPITypes() as $name => $type) {
162+
$value = $model->offsetGet($name);
163+
164+
if ($value === null) {
165+
continue;
166+
}
167+
168+
if (str_contains($type, '\SplFileObject')) {
169+
$file = is_array($value) ? $value : [$value];
170+
$result[$name] = $this->processFiles($file);
171+
172+
continue;
173+
}
174+
175+
if ($value instanceof ModelInterface) {
176+
$result[$name] = $this->processModel($value);
177+
178+
continue;
179+
}
180+
181+
if (is_array($value) || is_object($value)) {
182+
$result[$name] = $this->makeFormSafe($value);
183+
184+
continue;
185+
}
186+
187+
$result[$name] = ObjectSerializer::toString($value);
188+
}
189+
190+
return $result;
191+
}
192+
193+
/**
194+
* Handle file data
195+
*/
196+
protected function processFiles(array $files): array
197+
{
198+
$this->has_file = true;
199+
200+
$result = [];
201+
202+
foreach ($files as $i => $file) {
203+
if (is_array($file)) {
204+
$result[$i] = $this->processFiles($file);
205+
206+
continue;
207+
}
208+
209+
if ($file instanceof StreamInterface) {
210+
$result[$i] = $file;
211+
212+
continue;
213+
}
214+
215+
if ($file instanceof SplFileObject) {
216+
$result[$i] = $this->tryFopen($file);
217+
}
218+
}
219+
220+
return $result;
221+
}
222+
223+
private function tryFopen(SplFileObject $file)
224+
{
225+
return Utils::tryFopen($file->getRealPath(), 'rb');
226+
}
227+
}

modules/openapi-generator/src/main/resources/php-nextgen/ObjectSerializer.mustache

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
namespace {{invokerPackage}};
2020

21-
use ArrayAccess;
2221
use DateTimeInterface;
2322
use DateTime;
2423
use GuzzleHttp\Psr7\Utils;
@@ -316,37 +315,6 @@ class ObjectSerializer
316315
return self::toString($value);
317316
}
318317
319-
/**
320-
* Take value and turn it into an array suitable for inclusion in
321-
* the http body (form parameter). If it's a string, pass through unchanged
322-
* If it's a datetime object, format it in ISO8601
323-
*
324-
* @param string|bool|array|DateTime|ArrayAccess|\SplFileObject $value the value of the form parameter
325-
*
326-
* @return array [key => value] of formdata
327-
*/
328-
public static function toFormValue(
329-
string $key,
330-
string|bool|array|DateTime|ArrayAccess|\SplFileObject $value,
331-
): array {
332-
if ($value instanceof \SplFileObject) {
333-
return [$key => $value->getRealPath()];
334-
} elseif (is_array($value) || $value instanceof ArrayAccess) {
335-
$flattened = [];
336-
$result = [];
337-
338-
self::flattenArray(json_decode(json_encode($value), true), $flattened);
339-
340-
foreach ($flattened as $k => $v) {
341-
$result["{$key}{$k}"] = self::toString($v);
342-
}
343-
344-
return $result;
345-
} else {
346-
return [$key => self::toString($value)];
347-
}
348-
}
349-
350318
/**
351319
* Take value and turn it into a string suitable for inclusion in
352320
* the parameter. If it's a string, pass through unchanged
@@ -612,58 +580,4 @@ class ObjectSerializer
612580

613581
return $qs ? (string) substr($qs, 0, -1) : '';
614582
}
615-
616-
/**
617-
* Flattens an array of Model object and generates an array compatible
618-
* with formdata - a single-level array where the keys use bracket
619-
* notation to signify nested data.
620-
*
621-
* credit: https://github.com/FranBar1966/FlatPHP
622-
*/
623-
private static function flattenArray(
624-
ArrayAccess|array $source,
625-
array &$destination,
626-
string $start = '',
627-
) {
628-
$opt = [
629-
'prefix' => '[',
630-
'suffix' => ']',
631-
'suffix-end' => true,
632-
'prefix-list' => '[',
633-
'suffix-list' => ']',
634-
'suffix-list-end' => true,
635-
];
636-
637-
if (!is_array($source)) {
638-
$source = (array) $source;
639-
}
640-
641-
if (array_is_list($source)) {
642-
$currentPrefix = $opt['prefix-list'];
643-
$currentSuffix = $opt['suffix-list'];
644-
$currentSuffixEnd = $opt['suffix-list-end'];
645-
} else {
646-
$currentPrefix = $opt['prefix'];
647-
$currentSuffix = $opt['suffix'];
648-
$currentSuffixEnd = $opt['suffix-end'];
649-
}
650-
651-
$currentName = $start;
652-
653-
foreach ($source as $key => $val) {
654-
$currentName .= $currentPrefix.$key;
655-
656-
if (is_array($val) && !empty($val)) {
657-
$currentName .= "{$currentSuffix}";
658-
self::flattenArray($val, $destination, $currentName);
659-
} else {
660-
if ($currentSuffixEnd) {
661-
$currentName .= $currentSuffix;
662-
}
663-
$destination[$currentName] = self::toString($val);
664-
}
665-
666-
$currentName = $start;
667-
}
668-
}
669583
}

modules/openapi-generator/src/main/resources/php-nextgen/api.mustache

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use GuzzleHttp\Promise\PromiseInterface;
2929
use {{invokerPackage}}\ApiException;
3030
use {{invokerPackage}}\Configuration;
3131
use {{invokerPackage}}\HeaderSelector;
32+
use {{invokerPackage}}\FormDataProcessor;
3233
use {{invokerPackage}}\ObjectSerializer;
3334

3435
/**
@@ -749,25 +750,19 @@ use {{invokerPackage}}\ObjectSerializer;
749750
{{/pathParams}}
750751

751752
{{#formParams}}
753+
{{#-first}}
752754
// form params
753-
if (${{paramName}} !== null) {
754-
{{#isFile}}
755-
$multipart = true;
756-
$formParams['{{baseName}}'] = [];
757-
$paramFiles = is_array(${{paramName}}) ? ${{paramName}} : [${{paramName}}];
758-
foreach ($paramFiles as $paramFile) {
759-
$formParams['{{baseName}}'][] = $paramFile instanceof \Psr\Http\Message\StreamInterface
760-
? $paramFile
761-
: \GuzzleHttp\Psr7\Utils::tryFopen(
762-
ObjectSerializer::toFormValue('{{baseName}}', $paramFile)['{{baseName}}'],
763-
'rb'
764-
);
765-
}
766-
{{/isFile}}
767-
{{^isFile}}
768-
$formParams = array_merge($formParams, ObjectSerializer::toFormValue('{{baseName}}', ${{paramName}}));
769-
{{/isFile}}
770-
}
755+
$formDataProcessor = new FormDataProcessor();
756+
757+
$formData = $formDataProcessor->prepare([
758+
{{/-first}}
759+
'{{paramName}}' => ${{paramName}},
760+
{{#-last}}
761+
]);
762+
763+
$formParams = $formDataProcessor->flatten($formData);
764+
$multipart = $formDataProcessor->has_file;
765+
{{/-last}}
771766
{{/formParams}}
772767

773768
$headers = $this->headerSelector->selectHeaders(

0 commit comments

Comments
 (0)