Browse Source

Cleanup: replace mergeResults with StaticData strategy

Shalvah 2 months ago
parent
commit
57bd39a2f1

+ 9 - 6
config/scribe.php

@@ -3,7 +3,7 @@
 use Knuckles\Scribe\Config;
 use Knuckles\Scribe\Config\{AuthIn,ExternalTheme};
 use Knuckles\Scribe\Extracting\Strategies;
-use function Knuckles\Scribe\Config\{mergeResults, removeStrategies, withConfiguredStrategy};
+use function Knuckles\Scribe\Config\{removeStrategies, withConfiguredStrategy};
 
 /**
  * For documentation, use your IDE's autocomplete features, or see https://scribe.knuckles.wtf/laravel/reference/config
@@ -33,14 +33,17 @@ return Config\Factory::make(
         ),
         strategies: Config\Extracting::strategies(
         // Use removeStrategies() to remove an included strategy.
-        // Use mergeResults() to override the data returned from a strategy. Use withConfiguredStrategy() to configure a strategy which supports it.
+        // Use withConfiguredStrategy() to configure a strategy which supports it.
             metadata: [...Config\Defaults::METADATA_STRATEGIES],
             urlParameters: [...Config\Defaults::URL_PARAMETERS_STRATEGIES],
             queryParameters: [...Config\Defaults::QUERY_PARAMETERS_STRATEGIES],
-            headers: mergeResults(Config\Defaults::HEADERS_STRATEGIES, with: [
-                'Content-Type' => 'application/json',
-                'Accept' => 'application/json',
-            ]),
+            headers: [
+                ...Config\Defaults::HEADERS_STRATEGIES,
+                Strategies\StaticData::withSettings(data: [
+                    'Content-Type' => 'application/json',
+                    'Accept' => 'application/json',
+                ]),
+            ],
             bodyParameters: [...Config\Defaults::BODY_PARAMETERS_STRATEGIES],
             responses: withConfiguredStrategy(
                 Config\Defaults::RESPONSES_STRATEGIES,

+ 9 - 6
config/scribe_old.php

@@ -2,7 +2,7 @@
 
 use Knuckles\Scribe\Extracting\Strategies;
 use Knuckles\Scribe\Config;
-use function Knuckles\Scribe\Config\{mergeResults, removeStrategies, withConfiguredStrategy};
+use function Knuckles\Scribe\Config\{removeStrategies, withConfiguredStrategy};
 
 return [
     // The HTML <title> for the generated documentation. If this is empty, Scribe will infer it from config('app.name').
@@ -203,7 +203,7 @@ INTRO
 
     // The strategies Scribe will use to extract information about your routes at each stage.
     // Use removeStrategies() to remove an included strategy.
-    // Use mergeResults() to override the data returned from a strategy. Use withConfiguredStrategy() to configure a strategy which supports it.
+    // Use withConfiguredStrategy() to configure a strategy which supports it.
     'strategies' => [
         'metadata' => [
             ...Config\Defaults::METADATA_STRATEGIES,
@@ -214,10 +214,13 @@ INTRO
         'queryParameters' => [
             ...Config\Defaults::QUERY_PARAMETERS_STRATEGIES,
         ],
-        'headers' => mergeResults(Config\Defaults::HEADERS_STRATEGIES, with: [
-            'Content-Type' => 'application/json',
-            'Accept' => 'application/json',
-        ]),
+        'headers' => [
+            ...Config\Defaults::HEADERS_STRATEGIES,
+            Strategies\StaticData::withSettings(data: [
+                'Content-Type' => 'application/json',
+                'Accept' => 'application/json',
+            ]),
+        ],
         'bodyParameters' => [
             ...Config\Defaults::BODY_PARAMETERS_STRATEGIES,
         ],

+ 1 - 25
src/Config/strategies.php

@@ -3,36 +3,12 @@
 namespace Knuckles\Scribe\Config;
 
 use Illuminate\Support\Arr;
-use Knuckles\Scribe\Extracting\Strategies\Strategy;
 
 // Strategies can be:
 // 1. (Original) A class name, e.g. Strategies\Responses\ResponseCalls::class
 // 2. (New) A tuple containing the class name as item 1, and its config array as item 2
 // 3. (New) A tuple containing "merge" as item 1, and the values to override array as item 2
 
-/**
- * Merge the results of all previous strategies with some static data.
- *
- * @param array $strategies
- * @param array $with
- * @param array $only The routes that should be overridden. Same format as the route matcher.
- * @param array $except The routes that should not be overridden. Same format as the route matcher.
- * @return array
- */
-function mergeResults(array $strategies, array $with, array $only = ['*'], array $except = []): array
-{
-    $mergeStrategy = Strategy::wrapWithSettings('merge', only: $only, except: $except, otherSettings: ['with' => $with]);
-    return addStrategies($strategies, [$mergeStrategy]);
-}
-
-/**
- * Add one or more strategies to a list of strategies. Only use this if you know the strategy isn't already in the list.
- */
-function addStrategies(array $strategies, array $newStrategies = []): array
-{
-    return array_merge($strategies, $newStrategies);
-}
-
 /**
  * Remove one or more strategies from a list of strategies.
  */
@@ -70,7 +46,7 @@ function withConfiguredStrategy(array $strategies, array $configurationTuple): a
 
     // If strategy wasn't in there, add it.
     if (!$strategyFound) {
-        $strategies = addStrategies($strategies, [$configurationTuple]);
+        $strategies = array_merge($strategies, [$configurationTuple]);
     }
     return $strategies;
 }

+ 11 - 6
src/Extracting/Extractor.php

@@ -14,7 +14,8 @@ use Illuminate\Support\Str;
 use Knuckles\Camel\Extraction\ResponseCollection;
 use Knuckles\Camel\Extraction\ResponseField;
 use Knuckles\Camel\Output\OutputEndpointData;
-use Knuckles\Scribe\Extracting\Strategies\Override;
+use Knuckles\Scribe\Extracting\Strategies\StaticData;
+use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
 use Knuckles\Scribe\Tools\DocumentationConfig;
 use Knuckles\Scribe\Tools\RoutePatternMatcher;
 
@@ -210,13 +211,17 @@ class Extractor
             if (is_array($strategyClassOrTuple)) {
                 [$strategyClass, &$settings] = $strategyClassOrTuple;
                 if ($strategyClass == 'override') {
-                    $strategyClass = Override::class;
-                    // Overrides can be short: ['override', ['key' => 'value']],
-                    // or extended ['override', ['with' => ['key' => 'value'], 'only' => ['GET *'], 'except' => []]],
-                    $settingsFormat = array_key_exists('with', $settings) ? 'extended' : 'short';
+                    c::warn("The 'override' strategy was renamed to 'static_data', and will stop working in the future. Please replace 'override' in your config file with 'static_data'.");
+                    $strategyClass = 'static_data';
+                }
+                if ($strategyClass == 'static_data') {
+                    $strategyClass = StaticData::class;
+                    // Static data can be short: ['static_data', ['key' => 'value']],
+                    // or extended ['static_data', ['data' => ['key' => 'value'], 'only' => ['GET *'], 'except' => []]],
+                    $settingsFormat = array_key_exists('data', $settings) ? 'extended' : 'short';
                     $settings = match($settingsFormat) {
                         'extended' => $settings,
-                        'short' => ['with' => $settings],
+                        'short' => ['data' => $settings],
                     };
                 }
             } else {

+ 0 - 13
src/Extracting/Strategies/Override.php

@@ -1,13 +0,0 @@
-<?php
-
-namespace Knuckles\Scribe\Extracting\Strategies;
-
-use Knuckles\Camel\Extraction\ExtractedEndpointData;
-
-class Override extends Strategy
-{
-    public function __invoke(ExtractedEndpointData $endpointData, array $settings = []): ?array
-    {
-        return $settings['with'];
-    }
-}

+ 1 - 1
src/Extracting/Strategies/Responses/ResponseCalls.php

@@ -301,7 +301,7 @@ class ResponseCalls extends Strategy
      * @return array
      */
     public static function withSettings(
-        array $only = ['GET *'],
+        array $only = [],
         array $except = [],
         array $config = [],
         array $queryParams = [],

+ 28 - 0
src/Extracting/Strategies/StaticData.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace Knuckles\Scribe\Extracting\Strategies;
+
+use Knuckles\Camel\Extraction\ExtractedEndpointData;
+
+/**
+ * A simple strategy that returns a set of static data.
+ */
+class StaticData extends Strategy
+{
+    public function __invoke(ExtractedEndpointData $endpointData, array $settings = []): ?array
+    {
+        return $settings['data'];
+    }
+
+    public static function withSettings(
+        array $only = [],
+        array $except = [],
+        array $data = [],
+    ): array
+    {
+        return static::wrapWithSettings(
+            static::class, only: $only, except: $except, otherSettings: compact(
+            'data',
+        ));
+    }
+}

+ 2 - 2
src/Extracting/Strategies/Strategy.php

@@ -41,9 +41,9 @@ abstract class Strategy
      *   Specify route names ("users.index", "users.*"), or method and path ("GET *", "POST /safe/*").
      * @return array{string,array} Tuple of strategy class FQN and specified settings.
      */
-    public static function wrapWithSettings(
+    protected static function wrapWithSettings(
         string $strategyName = self::class,
-        array $only = ['*'],
+        array $only = [],
         array $except = [],
         array $otherSettings = []
     ): array

+ 8 - 26
tests/GenerateDocumentation/OutputTest.php

@@ -6,7 +6,6 @@ use Illuminate\Support\Facades\Route as RouteFacade;
 use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Facades\View;
 use Illuminate\Support\Str;
-use Knuckles\Scribe\Config\Defaults;
 use Knuckles\Scribe\Tests\BaseLaravelTest;
 use Knuckles\Scribe\Tests\Fixtures\TestController;
 use Knuckles\Scribe\Tests\Fixtures\TestGroupController;
@@ -22,7 +21,6 @@ use Knuckles\Scribe\Tools\Utils;
 use Symfony\Component\DomCrawler\Crawler;
 use Symfony\Component\Yaml\Yaml;
 use Knuckles\Scribe\Extracting\Strategies;
-use function Knuckles\Scribe\Config\mergeResults;
 use function Knuckles\Scribe\Config\withConfiguredStrategy;
 
 class OutputTest extends BaseLaravelTest
@@ -140,9 +138,10 @@ class OutputTest extends BaseLaravelTest
             'postman.overrides' => [
                 'info.version' => '3.9.9',
             ],
-            'strategies.headers' => mergeResults(config('scribe.strategies.headers'), [
-                'Custom-Header' => 'NotSoCustom',
-            ]),
+            'strategies.headers' => [
+                ...config('scribe.strategies.headers'),
+                Strategies\StaticData::withSettings(data: ['Custom-Header' => 'NotSoCustom']),
+            ],
         ]);
         $this->enableResponseCalls();
 
@@ -201,9 +200,10 @@ class OutputTest extends BaseLaravelTest
             'openapi.overrides' => [
                 'info.version' => '3.9.9',
             ],
-            'strategies.headers' => mergeResults(Defaults::HEADERS_STRATEGIES, [
-                'Custom-Header' => 'NotSoCustom',
-            ]),
+            'strategies.headers' =>  [
+                ...config('scribe.strategies.headers'),
+                Strategies\StaticData::withSettings(data: ['Custom-Header' => 'NotSoCustom']),
+            ],
         ]);
         $this->enableResponseCalls();
 
@@ -218,24 +218,6 @@ class OutputTest extends BaseLaravelTest
         $this->assertEquals($fixtureSpec, $generatedSpec);
     }
 
-    /** @test */
-    public function can_append_custom_http_headers()
-    {
-        RouteFacade::get('/api/headers', [TestController::class, 'checkCustomHeaders']);
-        $this->setConfig([
-            'strategies.headers' => mergeResults(Defaults::HEADERS_STRATEGIES, [
-                    'Authorization' => 'customAuthToken',
-                    'Custom-Header' => 'NotSoCustom',
-                ]
-            ),
-        ]);
-        $this->generate();
-
-        $endpointDetails = Yaml::parseFile('.scribe/endpoints/00.yaml')['endpoints'][0];
-        $this->assertEquals("customAuthToken", $endpointDetails['headers']["Authorization"]);
-        $this->assertEquals("NotSoCustom", $endpointDetails['headers']["Custom-Header"]);
-    }
-
     /** @test */
     public function can_parse_utf8_response()
     {

+ 30 - 3
tests/Unit/ExtractorTest.php

@@ -207,7 +207,7 @@ class ExtractorTest extends BaseLaravelTest
         $this->config['strategies']['headers'] = [
             Strategies\Headers\GetFromHeaderAttribute::class,
             [
-                'override', $headers
+                'static_data', $headers
             ],
         ];
         $parsed = $this->process($route);
@@ -228,14 +228,41 @@ class ExtractorTest extends BaseLaravelTest
         ];
         $this->config['strategies']['headers'] = [
             Strategies\Headers\GetFromHeaderAttribute::class,
-            ['override', ['with' => $headers, 'only' => ['GET *']]],
+            ['static_data', ['data' => $headers, 'only' => ['GET *']]],
         ];
         $parsed = $this->process($route);
         $this->assertArraySubset($parsed->headers, $headers);
 
         $this->config['strategies']['headers'] = [
             Strategies\Headers\GetFromHeaderAttribute::class,
-            ['override', ['with' => $headers, 'only' => [], 'except' => ['GET *']]],
+            ['static_data', ['data' => $headers, 'only' => [], 'except' => ['GET *']]],
+        ];
+        $parsed = $this->process($route);
+        $this->assertEmpty($parsed->headers);
+    }
+
+    /** @test */
+    public function overrides_headers_based_on_full_strategy_config()
+    {
+        $route = $this->createRoute('GET', '/get', 'dummy');
+        $this->config['strategies']['headers'] = [Strategies\Headers\GetFromHeaderAttribute::class];
+        $parsed = $this->process($route);
+        $this->assertEmpty($parsed->headers);
+
+        $headers = [
+            'accept' => 'application/json',
+            'Content-Type' => 'application/json+vnd',
+        ];
+        $this->config['strategies']['headers'] = [
+            Strategies\Headers\GetFromHeaderAttribute::class,
+            Strategies\StaticData::withSettings(only: ['GET *'], data: $headers),
+        ];
+        $parsed = $this->process($route);
+        $this->assertArraySubset($parsed->headers, $headers);
+
+        $this->config['strategies']['headers'] = [
+            Strategies\Headers\GetFromHeaderAttribute::class,
+            Strategies\StaticData::withSettings(except: ['GET *'], data: $headers),
         ];
         $parsed = $this->process($route);
         $this->assertEmpty($parsed->headers);