Browse Source

* You can now put groups at the bottom of the list by using the "*" to determine where in the ordering all unspecified groups will be placed (#731)

Josh Capener 1 year ago
parent
commit
ea52307bd4
3 changed files with 81 additions and 2 deletions
  1. 20 1
      camel/Camel.php
  2. 2 1
      config/scribe.php
  3. 59 0
      tests/GenerateDocumentation/OutputTest.php

+ 20 - 1
camel/Camel.php

@@ -121,7 +121,26 @@ class Camel
 
         // First, sort groups
         $groupsOrder = Utils::getTopLevelItemsFromMixedConfigList($configFileOrder);
-        $groupedEndpoints = collect($groupedEndpoints)->sortKeysUsing(self::getOrderListComparator($groupsOrder));
+        $groupsCollection = collect($groupedEndpoints);
+        $wildcardPosition = array_search('*', $groupsOrder);
+        if ($wildcardPosition !== false) {
+            $promotedGroups = array_splice($groupsOrder, 0, $wildcardPosition);
+            $demotedGroups = array_splice($groupsOrder, 1);
+
+            $promotedOrderedGroups = $groupsCollection->filter(fn ($group, $groupName) => in_array($groupName, $promotedGroups))
+                ->sortKeysUsing(self::getOrderListComparator($promotedGroups));
+            $demotedOrderedGroups = $groupsCollection->filter(fn ($group, $groupName) => in_array($groupName, $demotedGroups))
+                ->sortKeysUsing(self::getOrderListComparator($demotedGroups));
+
+            $nonWildcardGroups = array_merge($promotedGroups, $demotedGroups);
+            $wildCardOrderedGroups = $groupsCollection->filter(fn ($group, $groupName) => !in_array($groupName, $nonWildcardGroups))
+                ->sortKeysUsing(self::getOrderListComparator($demotedGroups));
+
+            $groupedEndpoints = $promotedOrderedGroups->merge($wildCardOrderedGroups)
+                ->merge($demotedOrderedGroups);
+        } else {
+            $groupedEndpoints = $groupsCollection->sortKeysUsing(self::getOrderListComparator($groupsOrder));
+        }
 
         return $groupedEndpoints->map(function (array $group, string $groupName) use ($configFileOrder) {
             $sortedEndpoints = collect($group['endpoints']);

+ 2 - 1
config/scribe.php

@@ -317,7 +317,8 @@ INTRO
          * By default, Scribe will sort groups alphabetically, and endpoints in the order their routes are defined.
          * You can override this by listing the groups, subgroups and endpoints here in the order you want them.
          *
-         * Any groups, subgroups or endpoints you don't list here will be added as usual after the ones here.
+         * Any groups, subgroups or endpoints you don't list here will be added as usual after the ones here unless you
+         * use the "*" character as this specifies the position of all unspecified groups
          * If an endpoint/subgroup is listed under a group it doesn't belong in, it will be ignored.
          * Note: you must include the initial '/' when writing an endpoint.
          */

+ 59 - 0
tests/GenerateDocumentation/OutputTest.php

@@ -349,6 +349,65 @@ class OutputTest extends BaseLaravelTest
         $this->assertEquals("POST api/action13b", $thirdGroupEndpointsAndSubgroups->getNode(7)->textContent);
     }
 
+    /** @test */
+    public function sorts_groups_and_endpoints_in_the_specified_order_with_wildcard()
+    {
+        config(['scribe.groups.order' => [
+            '10. Group 10',
+            '*',
+            '13. Group 13' => [
+                'SG B' => [
+                    'POST /api/action13d',
+                    'GET /api/action13a',
+                ],
+                'SG A',
+                'PUT /api/action13c',
+            ],
+        ]]);
+
+        RouteFacade::get('/api/action1', [TestGroupController::class, 'action1']);
+        RouteFacade::get('/api/action1b', [TestGroupController::class, 'action1b']);
+        RouteFacade::get('/api/action2', [TestGroupController::class, 'action2']);
+        RouteFacade::get('/api/action10', [TestGroupController::class, 'action10']);
+        RouteFacade::get('/api/action13a', [TestGroupController::class, 'action13a']);
+        RouteFacade::post('/api/action13b', [TestGroupController::class, 'action13b']);
+        RouteFacade::put('/api/action13c', [TestGroupController::class, 'action13c']);
+        RouteFacade::post('/api/action13d', [TestGroupController::class, 'action13d']);
+        RouteFacade::get('/api/action13e', [TestGroupController::class, 'action13e']);
+
+        $this->generate();
+
+        $crawler = new Crawler(file_get_contents($this->htmlOutputPath()));
+        $headings = $crawler->filter('h1')->getIterator();
+        $this->assertCount(6, $headings); // intro, auth, four groups
+        [$_, $_, $firstGroup, $secondGroup, $thirdGroup, $fourthGroup] = $headings;
+
+        $this->assertEquals('10. Group 10', $firstGroup->textContent);
+        $this->assertEquals('1. Group 1', $secondGroup->textContent);
+        $this->assertEquals('2. Group 2', $thirdGroup->textContent);
+        $this->assertEquals('13. Group 13', $fourthGroup->textContent);
+
+        $firstGroupEndpointsAndSubgroups = $crawler->filter('h2[id^="'.Str::slug($firstGroup->textContent).'"]');
+        $this->assertEquals(1, $firstGroupEndpointsAndSubgroups->count());
+        $this->assertEquals("GET api/action10", $firstGroupEndpointsAndSubgroups->getNode(0)->textContent);
+
+        $secondGroupEndpointsAndSubgroups = $crawler->filter('h2[id^="'.Str::slug($secondGroup->textContent).'"]');
+        $this->assertEquals(2, $secondGroupEndpointsAndSubgroups->count());
+        $this->assertEquals("GET api/action1", $secondGroupEndpointsAndSubgroups->getNode(0)->textContent);
+        $this->assertEquals("GET api/action1b", $secondGroupEndpointsAndSubgroups->getNode(1)->textContent);
+
+        $fourthGroupEndpointsAndSubgroups = $crawler->filter('h2[id^="'.Str::slug($fourthGroup->textContent).'"]');
+        $this->assertEquals(8, $fourthGroupEndpointsAndSubgroups->count());
+        $this->assertEquals("SG B", $fourthGroupEndpointsAndSubgroups->getNode(0)->textContent);
+        $this->assertEquals("POST api/action13d", $fourthGroupEndpointsAndSubgroups->getNode(1)->textContent);
+        $this->assertEquals("GET api/action13a", $fourthGroupEndpointsAndSubgroups->getNode(2)->textContent);
+        $this->assertEquals("SG A", $fourthGroupEndpointsAndSubgroups->getNode(3)->textContent);
+        $this->assertEquals("GET api/action13e", $fourthGroupEndpointsAndSubgroups->getNode(4)->textContent);
+        $this->assertEquals("PUT api/action13c", $fourthGroupEndpointsAndSubgroups->getNode(5)->textContent);
+        $this->assertEquals("SG C", $fourthGroupEndpointsAndSubgroups->getNode(6)->textContent);
+        $this->assertEquals("POST api/action13b", $fourthGroupEndpointsAndSubgroups->getNode(7)->textContent);
+    }
+
     /** @test */
     public function merges_and_correctly_sorts_user_defined_endpoints()
     {