Selaa lähdekoodia

Nest array and object parameters in docs web page

shalvah 4 vuotta sitten
vanhempi
commit
878b3ef8bf

+ 4 - 6
resources/views/components/field-details.blade.php

@@ -1,6 +1,4 @@
-
-    <code><b>{{ $name }}</b></code>&nbsp; @if($type)<small>{{ $type }}</small>@endif @if(!$required)
-        <i>optional</i>@endif
-    <br>
-    {!! $description !!}
-
+<code><b>{{ $name }}</b></code>&nbsp; @if($type)<small>{{ $type }}</small>@endif @if(!$required)
+    <i>optional</i>@endif
+<br>
+{!! $description !!}

+ 46 - 0
resources/views/partials/body-parameters.blade.php

@@ -0,0 +1,46 @@
+
+@foreach($parameters as $name => $parameter)
+@if(!empty($parameter['fields']))
+<p>
+<details>
+<summary>
+@component('scribe::components.field-details', [
+  'name' => $name,
+  'type' => $parameter['type'] ?? 'string',
+  'required' => $parameter['required'] ?? true,
+  'description' => $parameter['description'],
+])
+@endcomponent
+</summary>
+<br>
+@foreach($parameter['fields'] as $subfieldName => $subfield)
+@if(!empty($subfield['fields']))
+@component('scribe::partials.body-parameters', ['parameters' => [$subfield['name'] => $subfield]])
+@endcomponent
+@else
+<p>
+@component('scribe::components.field-details', [
+  'name' => $subfieldName,
+  'type' => $subfield['type'] ?? 'string',
+  'required' => $subfield['required'] ?? true,
+  'description' => $subfield['description'],
+])
+@endcomponent
+</p>
+@endif
+@endforeach
+</details>
+</p>
+@else
+<p>
+@component('scribe::components.field-details', [
+  'name' => $name,
+  'type' => $parameter['type'] ?? 'string',
+  'required' => $parameter['required'] ?? true,
+  'description' => $parameter['description'],
+])
+@endcomponent
+</p>
+@endif
+@endforeach
+

+ 8 - 9
resources/views/partials/endpoint.blade.php

@@ -41,6 +41,7 @@
 @if(count($route['urlParameters']))
 <h4 class="fancy-heading-panel"><b>URL Parameters</b></h4>
 @foreach($route['urlParameters'] as $attribute => $parameter)
+<p>
 @component('scribe::components.field-details', [
   'name' => $attribute,
   'type' => $parameter['type'] ?? 'string',
@@ -48,11 +49,13 @@
   'description' => $parameter['description'],
 ])
 @endcomponent
+</p>
 @endforeach
 @endif
 @if(count($route['queryParameters']))
 <h4 class="fancy-heading-panel"><b>Query Parameters</b></h4>
 @foreach($route['queryParameters'] as $attribute => $parameter)
+<p>
 @component('scribe::components.field-details', [
   'name' => $attribute,
   'type' => $parameter['type'] ?? 'string',
@@ -60,24 +63,19 @@
   'description' => $parameter['description'],
 ])
 @endcomponent
+</p>
 @endforeach
 @endif
-@if(count($route['bodyParameters']))
+@if(count($route['nestedBodyParameters']))
 <h4 class="fancy-heading-panel"><b>Body Parameters</b></h4>
-@foreach($route['bodyParameters'] as $attribute => $parameter)
-@component('scribe::components.field-details', [
-  'name' => $attribute,
-  'type' => $parameter['type'] ?? 'string',
-  'required' => $parameter['required'] ?? true,
-  'description' => $parameter['description'],
-])
+@component('scribe::partials.body-parameters', ['parameters' => $route['nestedBodyParameters']])
 @endcomponent
-@endforeach
 @endif
 
 @if(count($route['responseFields'] ?? []))
 <h4 class="fancy-heading-panel"><b>Response Fields</b></h4>
 @foreach($route['responseFields'] as $name => $field)
+<p>
 @component('scribe::components.field-details', [
   'name' => $name,
   'type' => $field['type'],
@@ -85,5 +83,6 @@
   'description' => $field['description'],
 ])
 @endcomponent
+</p>
 @endforeach
 @endif

+ 35 - 21
src/Extracting/Generator.php

@@ -129,6 +129,9 @@ class Generator
         $responseFields = $this->fetchResponseFields($controller, $method, $route, $routeRules, $parsedRoute);
         $parsedRoute['responseFields'] = $responseFields;
 
+
+        $parsedRoute['nestedBodyParameters'] = $this->nestArrayAndObjectFields($parsedRoute['bodyParameters']);
+
         self::$routeBeingProcessed = null;
 
         return $parsedRoute;
@@ -323,27 +326,6 @@ class Generator
         }
     }
 
-    /**
-     * For each array notation parameter (eg user.*, item.*.name, object.*.*, user[])
-     * add a key that represents a "concrete" number (eg user.0, item.0.name, object.0.0, user.0 with the same value.
-     * That way, we always have an array of length 1 for each array key
-     *
-     * @param string $paramName
-     * @param mixed $paramExample
-     * @param array $cleanParams The array that holds the result
-     *
-     * @return void
-     */
-    protected static function generateConcreteKeysForArrayParameters($paramName, $paramExample, array &$cleanParams = [])
-    {
-        if (Str::contains($paramName, '[')) {
-            // Replace usages of [] with dot notation
-            $paramName = str_replace(['][', '[', ']', '..'], ['.', '.', '', '.*.'], $paramName);
-        }
-        // Then generate a sample item for the dot notation
-        Arr::set($cleanParams, str_replace(['.*', '*.'], ['.0', '0.'], $paramName), $paramExample);
-    }
-
     public function addAuthField(array $parsedRoute): array
     {
         $parsedRoute['auth'] = null;
@@ -408,4 +390,36 @@ class Generator
             $filePath, $fileName, mime_content_type($filePath), 0, false
         );
     }
+
+    /**
+     * Transform body parameters such that object fields have a `fields` property containing a list of all subfields
+     * Subfields will be removed from the main parameter map
+     * For instance, if $parameters is ['dad' => [], 'dad.cars' => [], 'dad.age' => []],
+     * normalise this into ['dad' => [..., 'fields' => ['dad.cars' => [], 'dad.age' => []]]
+     */
+    public static function nestArrayAndObjectFields(array $parameters)
+    {
+        $finalParameters = [];
+        foreach ($parameters as $name => $parameter) {
+            if (Str::contains($name, '.')) { // Likely an object field
+                // Get the various pieces of the name
+                $parts = array_reverse(explode('.', $name));
+
+                $fieldName = array_shift($parts);
+
+                $baseName = join('.fields.', array_reverse($parts));
+                // The type should be indicated in the source object by now; we don't need it in the name
+                $normalisedBaseName = str_replace('[]', '.fields', $baseName);
+
+                $dotPath = preg_replace('/\.fields$/', '', $normalisedBaseName) . '.fields.' . $fieldName;
+                Arr::set($finalParameters, $dotPath, $parameter);
+            } else { // A regular field
+                $parameter['fields'] = [];
+                $finalParameters[$name] = $parameter;
+            }
+
+        }
+
+        return $finalParameters;
+    }
 }