소스 검색

Merge pull request #597 from mpociot/feature/array-object-support

Add better support for arrays and objects in bodyparameters
Shalvah 5 년 전
부모
커밋
623722a0fa

+ 2 - 1
resources/views/partials/example-requests/bash.blade.php

@@ -1,5 +1,6 @@
 ```bash
-curl -X {{$route['methods'][0]}} {{$route['methods'][0] == 'GET' ? '-G ' : ''}}"{{ rtrim($baseUrl, '/')}}/{{ ltrim($route['boundUri'], '/') }}@if(count($route['cleanQueryParameters']))?@foreach($route['cleanQueryParameters'] as $parameter => $value)
+curl -X {{$route['methods'][0]}} \
+    {{$route['methods'][0] == 'GET' ? '-G ' : ''}}"{{ rtrim($baseUrl, '/')}}/{{ ltrim($route['boundUri'], '/') }}@if(count($route['cleanQueryParameters']))?@foreach($route['cleanQueryParameters'] as $parameter => $value)
 {{ urlencode($parameter) }}={{ urlencode($value) }}@if(!$loop->last)&@endif
 @endforeach
 @endif" @if(count($route['headers']))\

+ 12 - 9
resources/views/partials/example-requests/javascript.blade.php

@@ -1,13 +1,16 @@
 ```javascript
-const url = new URL("{{ rtrim($baseUrl, '/') }}/{{ ltrim($route['boundUri'], '/') }}");
+const url = new URL(
+    "{{ rtrim($baseUrl, '/') }}/{{ ltrim($route['boundUri'], '/') }}"
+);
 @if(count($route['cleanQueryParameters']))
 
-    let params = {
-    @foreach($route['cleanQueryParameters'] as $parameter => $value)
-        "{{ $parameter }}": "{{ $value }}",
-    @endforeach
-    };
-    Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
+let params = {
+@foreach($route['cleanQueryParameters'] as $parameter => $value)
+    "{{ $parameter }}": "{{ $value }}",
+@endforeach
+};
+Object.keys(params)
+    .forEach(key => url.searchParams.append(key, params[key]));
 @endif
 
 let headers = {
@@ -20,8 +23,8 @@ let headers = {
 @if(!array_key_exists('Content-Type', $route['headers']))
     "Content-Type": "application/json",
 @endif
-}
-@if(count($route['bodyParameters']))
+};
+@if(count($route['cleanBodyParameters']))
 
 let body = {!! json_encode($route['cleanBodyParameters'], JSON_PRETTY_PRINT) !!}
 @endif

+ 10 - 15
resources/views/partials/example-requests/php.blade.php

@@ -1,29 +1,24 @@
 ```php
 
 $client = new \GuzzleHttp\Client();
-$response = $client->{{ strtolower($route['methods'][0]) }}("{{ rtrim($baseUrl, '/') . '/' . ltrim($route['boundUri'], '/') }}", [
+$response = $client->{{ strtolower($route['methods'][0]) }}(
+  "{{ rtrim($baseUrl, '/') . '/' . ltrim($route['boundUri'], '/') }}",
+  [
 @if(!empty($route['headers']))
-    'headers' => [
-    @foreach($route['headers'] as $header => $value)
-        "{{$header}}" => "{{$value}}",
-    @endforeach
-    ],
+    'headers' => {!! \Mpociot\ApiDoc\Tools\Utils::printPhpValue($route['headers'], 4) !!},
 @endif
 @if(!empty($route['cleanQueryParameters']))
     'query' => [
-    @foreach($route['cleanQueryParameters'] as $parameter => $value)
-        "{{$parameter}}" => "{{$value}}",
-    @endforeach
+@foreach($route['cleanQueryParameters'] as $parameter => $value)
+      "{{$parameter}}" => "{{$value}}",
+@endforeach
     ],
 @endif
 @if(!empty($route['cleanBodyParameters']))
-    'json' => [
-    @foreach($route['cleanBodyParameters'] as $parameter => $value)
-        "{{$parameter}}" => "{{$value}}",
-    @endforeach
-    ],
+    'json' => {!! \Mpociot\ApiDoc\Tools\Utils::printPhpValue($route['cleanBodyParameters'], 4) !!},
 @endif
-]);
+  ]
+);
 $body = $response->getBody();
 print_r(json_decode((string) $body));
 ```

+ 3 - 9
resources/views/partials/example-requests/python.blade.php

@@ -4,18 +4,12 @@ import json
 
 url = '{{ rtrim($baseUrl, '/') }}/{{ ltrim($route['boundUri'], '/') }}'
 @if(count($route['cleanBodyParameters']))
-payload = {
-@foreach($route['cleanBodyParameters'] as $parameter => $value)
-    '{{ $parameter }}': '{{ $value }}'@if(!($loop->last)),
-@endif
-@endforeach
-
-}
+payload = {!! json_encode($route['cleanBodyParameters'], JSON_PRETTY_PRINT) !!}
 @endif
 @if(count($route['cleanQueryParameters']))
 params = {
 @foreach($route['cleanQueryParameters'] as $parameter => $value)
-	'{{ $parameter }}': '{{ $value }}'@if(!($loop->last)),
+  '{{ $parameter }}': '{{ $value }}'@if(!($loop->last)),
 @endif
 @endforeach
 
@@ -23,7 +17,7 @@ params = {
 @endif
 headers = {
 @foreach($route['headers'] as $header => $value)
-	'{{$header}}': '{{$value}}'@if(!($loop->last)),
+  '{{$header}}': '{{$value}}'@if(!($loop->last)),
 @endif
 @endforeach
 

+ 33 - 17
src/Tools/Utils.php

@@ -2,7 +2,6 @@
 
 namespace Mpociot\ApiDoc\Tools;
 
-use Illuminate\Support\Str;
 use Illuminate\Routing\Route;
 use League\Flysystem\Filesystem;
 use League\Flysystem\Adapter\Local;
@@ -11,11 +10,11 @@ use Symfony\Component\Console\Output\OutputInterface;
 
 class Utils
 {
-    public static function getFullUrl(Route $route, array $bindings = []): string
+    public static function getFullUrl(Route $route, array $urlParameters = []): string
     {
         $uri = $route->uri();
 
-        return self::replaceUrlParameterBindings($uri, $bindings);
+        return self::replaceUrlParameterPlaceholdersWithValues($uri, $urlParameters);
     }
 
     /**
@@ -44,28 +43,31 @@ class Utils
 
     /**
      * Transform parameters in URLs into real values (/users/{user} -> /users/2).
-     * Uses bindings specified by caller, otherwise just uses '1'.
+     * Uses @urlParam values specified by caller, otherwise just uses '1'.
      *
      * @param string $uri
-     * @param array $bindings
+     * @param array $urlParameters Dictionary of url params and example values
      *
      * @return mixed
      */
-    public static function replaceUrlParameterBindings(string $uri, array $bindings)
+    public static function replaceUrlParameterPlaceholdersWithValues(string $uri, array $urlParameters)
     {
-        foreach ($bindings as $path => $binding) {
-            // So we can support partial bindings like
-            // 'bindings' => [
-            //  'foo/{type}' => 4,
-            //  'bar/{type}' => 2
-            //],
-            if (Str::is("*$path*", $uri)) {
-                preg_match('/({.+?})/', $path, $parameter);
-                $uri = str_replace("{$parameter['1']}", $binding, $uri);
+        $matches = preg_match_all('/{.+?}/i', $uri, $parameterPaths);
+        if (! $matches) {
+            return $uri;
+        }
+
+        foreach ($parameterPaths[0] as $parameterPath) {
+            $key = trim($parameterPath, '{?}');
+            if (isset($urlParameters[$key])) {
+                $example = $urlParameters[$key];
+                $uri = str_replace($parameterPath, $example, $uri);
             }
         }
-        // Replace any unbound parameters with '1'
-        $uri = preg_replace('/{(.+?)}/', '1', $uri);
+        // Remove unbound optional parameters with nothing
+        $uri = preg_replace('#{([^/]+\?)}#', '', $uri);
+        // Replace any unbound non-optional parameters with '1'
+        $uri = preg_replace('#{([^/]+)}#', '1', $uri);
 
         return $uri;
     }
@@ -90,4 +92,18 @@ class Utils
         $fs = new Filesystem($adapter);
         $fs->deleteDir($dir);
     }
+
+    public static function printPhpValue($value, $indentationLevel = 0)
+    {
+        $output = var_export($value, true);
+        // Padding with x spaces so they align
+        $split = explode("\n", $output);
+        $result = '';
+        $padWith = str_repeat(' ', $indentationLevel);
+        foreach ($split as $index => $line) {
+            $result .= ($index == 0 ? '' : "\n$padWith").$line;
+        }
+
+        return $result;
+    }
 }

+ 18 - 6
tests/Fixtures/TestController.php

@@ -72,8 +72,10 @@ class TestController extends Controller
      * @bodyParam room_id string The id of the room.
      * @bodyParam forever boolean Whether to ban the user forever. Example: false
      * @bodyParam another_one number Just need something here.
-     * @bodyParam yet_another_param object required
-     * @bodyParam even_more_param array
+     * @bodyParam yet_another_param object required Some object params.
+     * @bodyParam yet_another_param.name string required Subkey in the object param.
+     * @bodyParam even_more_param array Some array params.
+     * @bodyParam even_more_param.* float Subkey in the array param.
      * @bodyParam book.name string
      * @bodyParam book.author_id integer
      * @bodyParam book[pages_count] integer
@@ -165,13 +167,23 @@ class TestController extends Controller
         ];
     }
 
-    public function echoesUrlPathParameters($param)
+    /**
+     * @group Other😎
+     *
+     * @urlParam param required Example: 4
+     * @urlParam param2
+     * @urlParam param4 No-example.
+     *
+     * @queryParam something
+     */
+    public function echoesUrlParameters($param, $param2, $param3 = null, $param4 = null)
     {
-        return [
-            'param' => $param,
-        ];
+        return compact('param', 'param2', 'param3', 'param4');
     }
 
+    /**
+     * @urlparam $id Example: 3
+     */
     public function shouldFetchRouteResponseWithEchoedSettings($id)
     {
         return [