Skip to content

Commit 6e273de

Browse files
committed
PR feedback and improving example URL logic
1 parent 3412e31 commit 6e273de

1 file changed

Lines changed: 53 additions & 18 deletions

File tree

Annotations/AnnotationGenerator.php

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Piwik\Piwik;
2020
use Piwik\Plugin\Manager;
2121
use Piwik\SettingsPiwik;
22+
use Piwik\Url;
2223
use Piwik\Validators\BaseValidator;
2324
use Piwik\Validators\NotEmpty;
2425
use PHPStan\PhpDocParser\Lexer\Lexer;
@@ -131,7 +132,8 @@ protected function buildAnnotationForMethod(array $rules, string $pluginName, \R
131132
// Skip methods which have been marked as internal or auto annotations disabled
132133
if (
133134
$existing !== false && (stripos($existing, 'OA-AUTO:OFF') !== false
134-
|| stripos($existing, '@internal') !== false)
135+
|| stripos($existing, '@internal') !== false
136+
|| stripos($existing, '@hide') !== false)
135137
) {
136138
return [];
137139
}
@@ -167,7 +169,7 @@ protected function getParamInfoFromDocBlock(string $docBlock): array
167169
$params[$name] = [
168170
'type' => (string) $param->type,
169171
// Normalise the description. E.g. remove linebreaks and indentation
170-
'desc' => trim(preg_replace(['/^\h+/m', '/\R+/u',], ['', ' '], $param->description)),
172+
'description' => trim(preg_replace(['/^\h+/m', '/\R+/u',], ['', ' '], $param->description)),
171173
'byRef' => $param->isReference,
172174
'variadic' => $param->isVariadic,
173175
];
@@ -231,19 +233,18 @@ protected function buildParameterAnnotationData(string $paramName, array $paramM
231233
}
232234

233235
$isRequired = !key_exists('default', $paramMetadata) || $paramMetadata['default'] instanceof NoDefaultValue;
234-
$description = $paramDocInfo['desc'] ?? '';
236+
$description = $paramDocInfo['description'] ?? '';
235237
$example = '';
236238
// Check the description for the example value
237-
if (preg_match('/\[@example\s*=\s*(?:"([^"]+)"|([^\]]+))\]/', $description, $m)) {
238-
// If it's quoted, group 1. Otherwise, group 2
239+
if (preg_match('/\[@example\s*=\s*([^\n]+)\]/', $description, $m)) {
239240
if ($m[1] !== '') {
240241
$example = $m[1];
241-
} else {
242-
$example = $m[2];
243242
}
244243
// Remove the example from the description and trim any excess whitespace
245244
$description = trim(str_replace($m[0], '', $description));
245+
// Trim any excess whitespace and surrounding quotes from the example
246246
$example = trim($example);
247+
$example = trim($example, '"');
247248
}
248249

249250
return [
@@ -340,15 +341,42 @@ protected function getApplicableDemoExampleUrls(string $pluginName, string $meth
340341
'date' => 'today',
341342
];
342343

344+
$parametersToReplace = [];
343345
if (!empty($paramsData['custom'])) {
344346
foreach ($paramsData['custom'] as $customParam) {
347+
$paramName = strval($customParam['name']);
345348
if (isset($customParam['example']) && $customParam['example'] !== '') {
346-
$parametersToSet[$customParam['name']] = $customParam['example'];
349+
$example = $customParam['example'];
350+
351+
$decodedExample = [];
352+
// If the type is array, try decoding it
353+
if (in_array('array', array_keys($customParam['types']))) {
354+
$decodedExample = json_decode($example, true);
355+
}
356+
357+
// Check if the example is an array and needs special handling.
358+
$queryString = !empty($decodedExample) ? Http::buildQuery([$paramName => $decodedExample]) : '';
359+
if (stripos($queryString, urlencode($customParam['name'] . '[')) === 0) {
360+
// Mark the param to be replaced and change the value to a placeholder
361+
$parametersToReplace[$paramName] = $queryString;
362+
$example = 'PlaceholderValue';
363+
}
364+
365+
// Add the URL encoded param and value to the collection
366+
$parametersToSet[$paramName] = urlencode($example);
347367
}
348368
}
349369
}
350370
$className = Request::getClassNameAPI($pluginName);
351371
$exampleUrl = $this->generator->getExampleUrl($className, $methodName, $parametersToSet);
372+
373+
// Replace the placeholders with the actual array params now that we have an example URL
374+
if (!empty($exampleUrl) && !empty($parametersToReplace)) {
375+
foreach ($parametersToReplace as $name => $encodedValue) {
376+
$exampleUrl = str_replace('&' . $name . '=PlaceholderValue', '&' . $encodedValue, $exampleUrl);
377+
}
378+
}
379+
352380
if (empty($exampleUrl)) {
353381
// If we couldn't get an example URL from the generator, try getting one from metadata
354382
$exampleUrl = $this->getReportExampleUrlFromMetadata($pluginName, $methodName);
@@ -526,7 +554,7 @@ protected function determineResponses(array $rules, string $plugin, string $meth
526554
}
527555

528556
$successRef = null;
529-
$successArray = ['code' => 200, 'desc' => ''];
557+
$successArray = ['code' => 200, 'description' => ''];
530558
if (isset($rules['plugins'][$plugin]['successResponseByMethod'][$method])) {
531559
$successRef = $rules['plugins'][$plugin]['successResponseByMethod'][$method];
532560
}
@@ -564,7 +592,7 @@ protected function determineResponses(array $rules, string $plugin, string $meth
564592
}
565593

566594
if (!empty($responseInfo['description'])) {
567-
$successArray['desc'] = $responseInfo['description'];
595+
$successArray['description'] = $responseInfo['description'];
568596
}
569597

570598
$responseSchema = !empty($responseInfo['type']) ? $this->buildSchemaObjectArray($responseInfo['type']) : [];
@@ -636,8 +664,8 @@ protected function determineResponses(array $rules, string $plugin, string $meth
636664
$successArray['mediaTypes'] = $mediaTypes;
637665

638666
// If there are media types we shouldn't need the unknown type description
639-
if (!empty($successArray['desc']) && $successArray['desc'] === 'Response of unknown type') {
640-
$successArray['desc'] = '';
667+
if (!empty($successArray['description']) && $successArray['description'] === 'Response of unknown type') {
668+
$successArray['description'] = '';
641669
}
642670
} else {
643671
// Make sure the schema is included in there are no examples
@@ -652,7 +680,7 @@ protected function determineResponses(array $rules, string $plugin, string $meth
652680
$descriptionLinks = !empty($descriptionLinks) ? 'Example links: ' . $descriptionLinks : $descriptionLinks;
653681

654682
// Append the links to the description with a prefix linebreak. If there's no description, skip the break
655-
$successArray['desc'] .= (!empty($successArray['desc']) && !empty($descriptionLinks) ? '</br>' : '') . $descriptionLinks;
683+
$successArray['description'] .= (!empty($successArray['description']) && !empty($descriptionLinks) ? '</br>' : '') . $descriptionLinks;
656684

657685
$responses[] = $successArray;
658686

@@ -937,7 +965,7 @@ protected function buildSchemaObjectArray(string $type, string $subType = '', st
937965

938966
protected function wrapStringWithQuotes(string $string, string $type, string $quoteCharacter = '"'): string
939967
{
940-
if (in_array($type, ['integer', 'boolean'])) {
968+
if (in_array($type, ['integer', 'boolean', 'array'])) {
941969
return $string;
942970
}
943971

@@ -996,21 +1024,28 @@ protected function compileOperationLines(string $path, string $opId, string $plu
9961024
if (!empty($param['description'])) {
9971025
$paramMap[] = 'description="' . $param['description'] . '"';
9981026
}
999-
$paramMap[] = $this->buildSchemaObjectArrays($param['types'], strval($param['default']), strval($param['example']));
1027+
$exampleString = $param['example'];
1028+
if (in_array('array', array_keys($param['types']))) {
1029+
// The annotation expects example objects and not arrays, so replace [] with {}
1030+
$exampleString = str_replace(['[', ']'], ['{', '}'], $exampleString);
1031+
// Escape quotes differently for the annotation examples
1032+
$exampleString = str_replace('\"', '""', $exampleString);
1033+
}
1034+
$paramMap[] = $this->buildSchemaObjectArrays($param['types'], strval($param['default']), strval($exampleString));
10001035
$operationValuesMap[] = ['@OA\Parameter' => $paramMap];
10011036
}
10021037
foreach ($responses as $response) {
10031038
// Don't use the reference if there are media type examples
10041039
if (isset($response['ref']) && empty($response['mediaTypes'])) {
10051040
$code = $response['code'];
10061041
$codeFormatted = is_numeric($code) ? (string)$code : '"' . $code . '"';
1007-
$description = !empty($response['desc']) && strpos($response['desc'], 'Example links: [') !== false
1008-
? ', description="' . $response['desc'] . '"' : '';
1042+
$description = !empty($response['description']) && strpos($response['description'], 'Example links: [') !== false
1043+
? ', description="' . $response['description'] . '"' : '';
10091044
$operationValuesMap[] = '@OA\Response(response=' . $codeFormatted . $description . ', ref="' . $response['ref'] . '")';
10101045
} else {
10111046
$responsePropertyArray = [
10121047
'response=200',
1013-
'description="' . ($response['desc'] ?? 'OK') . '"',
1048+
'description="' . ($response['description'] ?? 'OK') . '"',
10141049
];
10151050
if (!empty($response['schema'])) {
10161051
$responsePropertyArray = array_merge($responsePropertyArray, $response['schema']);

0 commit comments

Comments
 (0)