1919use Piwik \Piwik ;
2020use Piwik \Plugin \Manager ;
2121use Piwik \SettingsPiwik ;
22+ use Piwik \Url ;
2223use Piwik \Validators \BaseValidator ;
2324use Piwik \Validators \NotEmpty ;
2425use 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