Quellcode durchsuchen

Remove support for sorting endpoints in Camel files

shalvah vor 2 Jahren
Ursprung
Commit
03e61db30c

+ 28 - 29
camel/Camel.php

@@ -143,52 +143,51 @@ class Camel
 
     /**
      * @param array[] $endpoints
-     * @param array $endpointGroupIndexes Mapping of endpoint IDs to their index within their group
      * @param array $defaultGroupsOrder The order for groups that users specified in their config file.
      *
      * @return array[]
      */
-    public static function groupEndpoints(array $endpoints, array $endpointGroupIndexes, array $defaultGroupsOrder = []): array
+    public static function groupEndpoints(array $endpoints, array $defaultGroupsOrder = []): array
     {
         $groupedEndpoints = collect($endpoints)->groupBy('metadata.groupName');
 
         if ($defaultGroupsOrder) {
+            // Sort groups based on config file order
             $groupsOrder = Utils::getTopLevelItemsFromMixedConfigList($defaultGroupsOrder);
             $groupedEndpoints = $groupedEndpoints->sortKeysUsing(self::getOrderListComparator($groupsOrder));
         } else {
             $groupedEndpoints = $groupedEndpoints->sortKeys(SORT_NATURAL);
         }
 
-        return $groupedEndpoints->map(function (Collection $endpointsInGroup) use ($defaultGroupsOrder, $endpointGroupIndexes) {
+        return $groupedEndpoints->map(function (Collection $endpointsInGroup) use ($defaultGroupsOrder) {
             /** @var Collection<(int|string),ExtractedEndpointData> $endpointsInGroup */
             $sortedEndpoints = $endpointsInGroup;
-            if (empty($endpointGroupIndexes)) {
-                $groupName = data_get($endpointsInGroup[0], 'metadata.groupName');
-                if ($defaultGroupsOrder && isset($defaultGroupsOrder[$groupName])) {
-                    $subGroupOrEndpointsOrder = Utils::getTopLevelItemsFromMixedConfigList($defaultGroupsOrder[$groupName]);
-                    $sortedEndpoints = $endpointsInGroup->sortBy(
-                        function (ExtractedEndpointData $e) use ($defaultGroupsOrder, $subGroupOrEndpointsOrder) {
-                            $endpointIdentifier = $e->httpMethods[0].' /'.$e->uri;
-                            $index = array_search($e->metadata->subgroup, $subGroupOrEndpointsOrder);
-
-                            if ($index !== false) {
-                                // This is a subgroup
-                                $endpointsOrderInSubgroup = $defaultGroupsOrder[$e->metadata->groupName][$e->metadata->subgroup] ?? null;
-                                if ($endpointsOrderInSubgroup) {
-                                    $indexInSubGroup = array_search($endpointIdentifier, $endpointsOrderInSubgroup);
-                                    $index = ($indexInSubGroup === false) ? $index : ($index + ($indexInSubGroup * 0.1));
-                                }
-                            } else {
-                                // This is an endpoint
-                                $index = array_search($endpointIdentifier, $subGroupOrEndpointsOrder);
-                            }
-                            return $index === false ? INF : $index;
-                        },
-                    );
-                }
-            } else {
+
+            $groupName = data_get($endpointsInGroup[0], 'metadata.groupName');
+
+            // Sort endpoints in group based on config file order
+            if ($defaultGroupsOrder && isset($defaultGroupsOrder[$groupName])) {
+                $subGroupOrEndpointsOrder = Utils::getTopLevelItemsFromMixedConfigList($defaultGroupsOrder[$groupName]);
                 $sortedEndpoints = $endpointsInGroup->sortBy(
-                    fn(ExtractedEndpointData $e) => $endpointGroupIndexes[$e->endpointId()] ?? INF,
+                    function (ExtractedEndpointData $e) use ($defaultGroupsOrder, $subGroupOrEndpointsOrder) {
+                        $endpointIdentifier = $e->httpMethods[0] . ' /' . $e->uri;
+
+                        // First, check if there's an ordering specified for the endpoint's subgroup
+                        $index = array_search($e->metadata->subgroup, $subGroupOrEndpointsOrder);
+
+                        if ($index !== false) {
+                            // There's a subgroup order; check if there's an endpoints order within that
+                            $endpointsOrderInSubgroup = $defaultGroupsOrder[$e->metadata->groupName][$e->metadata->subgroup] ?? null;
+                            if ($endpointsOrderInSubgroup) {
+                                $indexInSubGroup = array_search($endpointIdentifier, $endpointsOrderInSubgroup);
+                                $index = ($indexInSubGroup === false) ? $index : ($index + ($indexInSubGroup * 0.1));
+                            }
+                        } else {
+                            // No subgroup order; check if there's an ordering for this endpoint
+                            $index = array_search($endpointIdentifier, $subGroupOrEndpointsOrder);
+                        }
+                        return $index === false ? INF : $index;
+                    },
                 );
             }
 

+ 1 - 1
src/Extracting/InstantiatesExampleModels.php

@@ -32,7 +32,7 @@ trait InstantiatesExampleModels
             }
         }
         if ($type == null) {
-            throw new Exception("Couldn't detect a transformer model from your doc block. Did you remember to specify a model using @transformerModel?");
+            throw new \Exception("Couldn't detect a transformer model from your doc block. Did you remember to specify a model using @transformerModel?");
         }
 
         $configuredStrategies = $this->config->get('examples.models_source', ['factoryCreate', 'factoryMake', 'databaseFirst']);

+ 20 - 25
src/GroupedEndpoints/GroupedEndpointsFromApp.php

@@ -34,8 +34,6 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
     public static string $camelDir;
     public static string $cacheDir;
 
-    private array $endpointGroupIndexes = [];
-
     public function __construct(
         GenerateDocumentation $command, RouteMatcherInterface $routeMatcher,
         bool $preserveUserChanges, string $docsName = 'scribe'
@@ -68,18 +66,19 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
     {
         $latestEndpointsData = [];
         $cachedEndpoints = [];
-        $groups = [];
 
         if ($preserveUserChanges && is_dir(static::$camelDir) && is_dir(static::$cacheDir)) {
             $latestEndpointsData = Camel::loadEndpointsToFlatPrimitivesArray(static::$camelDir);
             $cachedEndpoints = Camel::loadEndpointsToFlatPrimitivesArray(static::$cacheDir, true);
-            $groups = Camel::loadEndpointsIntoGroups(static::$camelDir);
         }
 
         $routes = $routeMatcher->getRoutes($this->docConfig->get('routes', []), $this->docConfig->get('router'));
-        $endpoints = $this->extractEndpointsInfoFromLaravelApp($routes, $cachedEndpoints, $latestEndpointsData, $groups);
-        $groupedEndpoints = Camel::groupEndpoints($endpoints, $this->endpointGroupIndexes, $this->docConfig->get('groups.order', []));
-        $this->writeEndpointsToDisk($groupedEndpoints);
+        $endpoints = $this->extractEndpointsInfoFromLaravelApp($routes, $cachedEndpoints, $latestEndpointsData);
+
+        $groupsOrder = $this->docConfig->get('groups.order', []);
+        $groupedEndpoints = Camel::groupEndpoints($endpoints, $groupsOrder);
+
+        $this->writeEndpointsToDisk($groupedEndpoints, $groupsOrder);
         $groupedEndpoints = Camel::prepareGroupedEndpointsForOutput($groupedEndpoints);
         return $groupedEndpoints;
     }
@@ -88,12 +87,11 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
      * @param MatchedRoute[] $matches
      * @param array $cachedEndpoints
      * @param array $latestEndpointsData
-     * @param array[] $groups
      *
      * @return array
      * @throws \Exception
      */
-    private function extractEndpointsInfoFromLaravelApp(array $matches, array $cachedEndpoints, array $latestEndpointsData, array $groups): array
+    private function extractEndpointsInfoFromLaravelApp(array $matches, array $cachedEndpoints, array $latestEndpointsData): array
     {
         $extractor = $this->makeExtractor();
 
@@ -122,13 +120,8 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
                 c::info('Processing route: ' . c::getRouteRepresentation($route));
                 $currentEndpointData = $extractor->processRoute($route, $routeItem->getRules());
                 // If latest data is different from cached data, merge latest into current
-                [$currentEndpointData, $index] = $this->mergeAnyEndpointDataUpdates($currentEndpointData, $cachedEndpoints, $latestEndpointsData, $groups);
-
-                // We need to preserve order of endpoints, in case user did custom sorting
+                $currentEndpointData = $this->mergeAnyEndpointDataUpdates($currentEndpointData, $cachedEndpoints, $latestEndpointsData);
                 $parsedEndpoints[] = $currentEndpointData;
-                if ($index !== null) {
-                    $this->endpointGroupIndexes[$currentEndpointData->endpointId()] = $index;
-                }
                 c::success('Processed route: ' . c::getRouteRepresentation($route));
             } catch (\Exception $exception) {
                 $this->encounteredErrors = true;
@@ -144,25 +137,24 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
      * @param ExtractedEndpointData $endpointData
      * @param array[] $cachedEndpoints
      * @param array[] $latestEndpointsData
-     * @param array[] $groups
      *
-     * @return array The extracted endpoint data and the endpoint's index in the group file
+     * @return ExtractedEndpointData The extracted endpoint data
      */
-    private function mergeAnyEndpointDataUpdates(ExtractedEndpointData $endpointData, array $cachedEndpoints, array $latestEndpointsData, array $groups): array
+    private function mergeAnyEndpointDataUpdates(ExtractedEndpointData $endpointData, array $cachedEndpoints, array $latestEndpointsData): ExtractedEndpointData
     {
         // First, find the corresponding endpoint in cached and latest
         $thisEndpointCached = Arr::first($cachedEndpoints, function (array $endpoint) use ($endpointData) {
             return $endpoint['uri'] === $endpointData->uri && $endpoint['httpMethods'] === $endpointData->httpMethods;
         });
         if (!$thisEndpointCached) {
-            return [$endpointData, null];
+            return $endpointData;
         }
 
         $thisEndpointLatest = Arr::first($latestEndpointsData, function (array $endpoint) use ($endpointData) {
             return $endpoint['uri'] === $endpointData->uri && $endpoint['httpMethods'] == $endpointData->httpMethods;
         });
         if (!$thisEndpointLatest) {
-            return [$endpointData, null];
+            return $endpointData;
         }
 
         // Then compare cached and latest to see what sections changed.
@@ -188,12 +180,10 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
         foreach ($changed as $property) {
             $endpointData->$property = $thisEndpointLatest->$property;
         }
-        $index = Camel::getEndpointIndexInGroup($groups, $thisEndpointLatest);
-
-        return [$endpointData, $index];
+        return $endpointData;
     }
 
-    protected function writeEndpointsToDisk(array $grouped): void
+    protected function writeEndpointsToDisk(array $grouped, array $groupsOrder): void
     {
         Utils::deleteFilesMatching(static::$camelDir, function ($file) {
             /** @var $file array|\League\Flysystem\StorageAttributes */
@@ -215,8 +205,12 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
                 $group, 20, 2,
                 Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP | Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK
             );
+            $wasGroupOrderedInConfigFile = isset($groupsOrder[$group['name']]) || in_array($group['name'], $groupsOrder);
+
             if (count(Camel::$groupFileNames) == count($grouped)
-                && isset(Camel::$groupFileNames[$group['name']])) {
+                && isset(Camel::$groupFileNames[$group['name']])
+                && !$wasGroupOrderedInConfigFile
+            ) {
                 $fileName = Camel::$groupFileNames[$group['name']];
             } else {
                 // Format numbers as two digits so they are sorted properly when retrieving later
@@ -227,6 +221,7 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
 
             file_put_contents(static::$camelDir . "/$fileName", $yaml);
             file_put_contents(static::$cacheDir . "/$fileName", "## Autogenerated by Scribe. DO NOT MODIFY.\n\n" . $yaml);
+            Camel::$groupFileNames[$group['name']] = $fileName;
         }
     }
 

+ 0 - 48
tests/GenerateDocumentation/OutputTest.php

@@ -501,54 +501,6 @@ class OutputTest extends BaseLaravelTest
         $this->assertEquals("GET api/action2", $expectedEndpoints->getNode(5)->textContent);
     }
 
-    /** @test */
-    public function respects_endpoints_and_group_sort_order()
-    {
-        RouteFacade::get('/api/action1', [TestGroupController::class, 'action1']);
-        RouteFacade::get('/api/action1b', [TestGroupController::class, 'action1b']);
-        RouteFacade::get('/api/action2', [TestGroupController::class, 'action2']);
-        config(['scribe.routes.0.apply.response_calls.methods' => []]);
-
-        $this->generate();
-
-        // First: verify the current order of the groups and endpoints
-        $crawler = new Crawler(file_get_contents($this->htmlOutputPath()));
-        $h1s = $crawler->filter('h1');
-        $this->assertEquals('1. Group 1', trim($h1s->getNode(2)->textContent));
-        $this->assertEquals('2. Group 2', trim($h1s->getNode(3)->textContent));
-        $expectedEndpoints = $crawler->filter('h2');
-        $this->assertEquals("Some endpoint.", $expectedEndpoints->getNode(0)->textContent);
-        $this->assertEquals("Another endpoint.", $expectedEndpoints->getNode(1)->textContent);
-        $this->assertEquals("GET api/action2", $expectedEndpoints->getNode(2)->textContent);
-
-        // Now swap the endpoints
-        $group = Yaml::parseFile('.scribe/endpoints/00.yaml');
-        $this->assertEquals('api/action1', $group['endpoints'][0]['uri']);
-        $this->assertEquals('api/action1b', $group['endpoints'][1]['uri']);
-        $action1 = $group['endpoints'][0];
-        $group['endpoints'][0] = $group['endpoints'][1];
-        $group['endpoints'][1] = $action1;
-        file_put_contents('.scribe/endpoints/00.yaml', Yaml::dump(
-            $group, 20, 2,
-            Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP
-        ));
-        // And then the groups
-        rename('.scribe/endpoints/00.yaml', '.scribe/endpoints/temp.yaml');
-        rename('.scribe/endpoints/01.yaml', '.scribe/endpoints/00.yaml');
-        rename('.scribe/endpoints/temp.yaml', '.scribe/endpoints/1.yaml');
-
-        $this->generate();
-
-        $crawler = new Crawler(file_get_contents($this->htmlOutputPath()));
-        $h1s = $crawler->filter('h1');
-        $this->assertEquals('2. Group 2', trim($h1s->getNode(2)->textContent));
-        $this->assertEquals('1. Group 1', trim($h1s->getNode(3)->textContent));
-        $expectedEndpoints = $crawler->filter('h2');
-        $this->assertEquals("GET api/action2", $expectedEndpoints->getNode(0)->textContent);
-        $this->assertEquals("Another endpoint.", $expectedEndpoints->getNode(1)->textContent);
-        $this->assertEquals("Some endpoint.", $expectedEndpoints->getNode(2)->textContent);
-    }
-
     /** @test */
     public function will_auto_set_content_type_to_multipart_if_file_params_are_present()
     {