Skip to content

Commit 643f69a

Browse files
committed
CLI-1745: fix: resolve pointers in requestBody and property schemas for API commands.
1 parent 064b748 commit 643f69a

File tree

2 files changed

+65
-37
lines changed

2 files changed

+65
-37
lines changed

src/Command/Api/ApiBaseCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ private function castParamType(array $paramSpec, array|string|bool|int $value):
245245
if (in_array('integer', $types, true) && ctype_digit($value)) {
246246
return $this->doCastParamType('integer', $value);
247247
}
248-
} elseif ($paramSpec['type'] === 'array') {
248+
} elseif ($this->getParamType($paramSpec) === 'array') {
249249
if (is_array($value) && count($value) === 1) {
250250
return $this->castParamToArray($paramSpec, $value[0]);
251251
}

src/Command/Api/ApiCommandHelper.php

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,20 @@ private function addApiCommandParameters(array $schema, array $acquiaCloudSpec,
8686

8787
// Parameters to be used in the request body.
8888
if (array_key_exists('requestBody', $schema)) {
89+
// Resolve $ref in requestBody if present.
90+
if (array_key_exists('$ref', $schema['requestBody'])) {
91+
$parts = explode('/', $schema['requestBody']['$ref']);
92+
$paramKey = end($parts);
93+
$schema['requestBody'] = $acquiaCloudSpec['components']['requestBodies'][$paramKey];
94+
}
8995
[
9096
$bodyInputDefinition,
9197
$requestBodyParamUsageSuffix,
9298
] = $this->addApiCommandParametersForRequestBody($schema, $acquiaCloudSpec);
9399
$requestBodySchema = $this->getRequestBodyFromParameterSchema($schema, $acquiaCloudSpec);
94100
/** @var \Symfony\Component\Console\Input\InputOption|InputArgument $parameterDefinition */
95101
foreach ($bodyInputDefinition as $parameterDefinition) {
96-
$parameterSpecification = $this->getPropertySpecFromRequestBodyParam($requestBodySchema, $parameterDefinition);
102+
$parameterSpecification = $this->getPropertySpecFromRequestBodyParam($requestBodySchema, $parameterDefinition, $acquiaCloudSpec);
97103
$command->addPostParameter($parameterDefinition->getName(), $parameterSpecification);
98104
}
99105
$usage .= $requestBodyParamUsageSuffix;
@@ -125,6 +131,12 @@ private function addApiCommandParametersForRequestBody(array $schema, array $acq
125131
$requestBodySchema['properties'] = [];
126132
}
127133
foreach ($requestBodySchema['properties'] as $propKey => $paramDefinition) {
134+
// Resolve $ref inside individual property definitions.
135+
if (array_key_exists('$ref', $paramDefinition)) {
136+
$parts = explode('/', $paramDefinition['$ref']);
137+
$paramKey = end($parts);
138+
$paramDefinition = $this->getParameterSchemaFromSpec($paramKey, $acquiaCloudSpec);
139+
}
128140
$isRequired = array_key_exists('required', $requestBodySchema) && in_array($propKey, $requestBodySchema['required'], true);
129141
$propKey = self::renameParameter($propKey);
130142

@@ -169,44 +181,50 @@ private function addPostArgumentUsageToExample(mixed $requestBody, mixed $propKe
169181
{
170182
$requestBodyContent = $this->getRequestBodyContent($requestBody, $acquiaCloudSpec);
171183

184+
// Example may live directly on the content-type object, or nested inside schema (e.g. $ref-resolved requestBodies).
172185
if (array_key_exists('example', $requestBodyContent)) {
173186
$example = $requestBodyContent['example'];
174-
$prefix = $type === 'argument' ? '' : "--$propKey=";
175-
if (array_key_exists($propKey, $example)) {
176-
if (!array_key_exists('type', $paramDefinition)) {
177-
return $usage;
178-
}
179-
switch ($paramDefinition['type']) {
180-
case 'object':
181-
$usage .= $prefix . '"' . json_encode($example[$propKey], JSON_THROW_ON_ERROR) . '"" ';
182-
break;
183-
184-
case 'array':
185-
$isMultidimensional = count($example[$propKey]) !== count($example[$propKey], COUNT_RECURSIVE);
186-
if (!$isMultidimensional) {
187-
foreach ($example[$propKey] as $value) {
188-
$usage .= $prefix . "\"$value\" ";
189-
}
190-
} else {
191-
// @todo Pretty sure prevents the user from using the arguments.
192-
// Probably a bug. How can we allow users to specify a multidimensional array as an
193-
// argument?
194-
$value = json_encode($example[$propKey], JSON_THROW_ON_ERROR);
187+
} elseif (array_key_exists('schema', $requestBodyContent) && array_key_exists('example', $requestBodyContent['schema'])) {
188+
$example = $requestBodyContent['schema']['example'];
189+
} else {
190+
return $usage;
191+
}
192+
193+
$prefix = $type === 'argument' ? '' : "--$propKey=";
194+
if (array_key_exists($propKey, $example)) {
195+
if (!array_key_exists('type', $paramDefinition)) {
196+
return $usage;
197+
}
198+
switch ($paramDefinition['type']) {
199+
case 'object':
200+
$usage .= $prefix . '"' . json_encode($example[$propKey], JSON_THROW_ON_ERROR) . '" ';
201+
break;
202+
203+
case 'array':
204+
$isMultidimensional = count($example[$propKey]) !== count($example[$propKey], COUNT_RECURSIVE);
205+
if (!$isMultidimensional) {
206+
foreach ($example[$propKey] as $value) {
195207
$usage .= $prefix . "\"$value\" ";
196208
}
197-
break;
198-
199-
case 'string':
200-
case 'boolean':
201-
case 'integer':
202-
if (is_array($example[$propKey])) {
203-
$value = reset($example[$propKey]);
204-
} else {
205-
$value = $example[$propKey];
206-
}
209+
} else {
210+
// @todo Pretty sure prevents the user from using the arguments.
211+
// Probably a bug. How can we allow users to specify a multidimensional array as an
212+
// argument?
213+
$value = json_encode($example[$propKey], JSON_THROW_ON_ERROR);
207214
$usage .= $prefix . "\"$value\" ";
208-
break;
209-
}
215+
}
216+
break;
217+
218+
case 'string':
219+
case 'boolean':
220+
case 'integer':
221+
if (is_array($example[$propKey])) {
222+
$value = reset($example[$propKey]);
223+
} else {
224+
$value = $example[$propKey];
225+
}
226+
$usage .= $prefix . "\"$value\" ";
227+
break;
210228
}
211229
}
212230
return $usage;
@@ -482,10 +500,20 @@ private function getRequestBodyFromParameterSchema(array $schema, array $acquiaC
482500
return $requestBodySchema;
483501
}
484502

485-
private function getPropertySpecFromRequestBodyParam(array $requestBodySchema, mixed $parameterDefinition): mixed
503+
private function getPropertySpecFromRequestBodyParam(array $requestBodySchema, mixed $parameterDefinition, array $acquiaCloudSpec = []): mixed
486504
{
487505
$name = self::restoreRenamedParameter($parameterDefinition->getName());
488-
return $requestBodySchema['properties'][$name] ?? null;
506+
$spec = $requestBodySchema['properties'][$name] ?? null;
507+
508+
// Resolve $ref in the property spec so downstream code (e.g. castParamType) always
509+
// receives a fully resolved spec with a 'type' key rather than a bare $ref object.
510+
if (is_array($spec) && array_key_exists('$ref', $spec)) {
511+
$parts = explode('/', $spec['$ref']);
512+
$paramKey = end($parts);
513+
$spec = $this->getParameterSchemaFromSpec($paramKey, $acquiaCloudSpec);
514+
}
515+
516+
return $spec;
489517
}
490518

491519
/**

0 commit comments

Comments
 (0)