Prechádzať zdrojové kódy

Compare generated routes and allow modifications

Marcel Pociot 8 rokov pred
rodič
commit
894367bc02

+ 37 - 19
src/Mpociot/ApiDoc/Commands/GenerateDocumentation.php

@@ -92,41 +92,49 @@ class GenerateDocumentation extends Command
     {
         $outputPath = $this->option('output');
         $targetFile = $outputPath.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR.'index.md';
+        $compareFile = $outputPath.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR.'.compare.md';
 
         $infoText = view('apidoc::partials.info')
             ->with('outputPath', $this->option('output'))
             ->with('showPostmanCollectionButton', ! $this->option('noPostmanCollection'));
 
         $parsedRouteOutput = $parsedRoutes->map(function ($routeGroup) {
-            return $routeGroup->map(function ($route) {
-                $route['output'] = (string) view('apidoc::partials.route')->with('parsedRoute', $route);
-
+            return $routeGroup->map(function($route){
+                $route['output'] = (string)view('apidoc::partials.route')->with('parsedRoute', $route);
                 return $route;
             });
         });
 
         $frontmatter = view('apidoc::partials.frontmatter');
-        /*
+        /**
          * In case the target file already exists, we should check if the documentation was modified
          * and skip the modified parts of the routes.
          */
-        if (file_exists($targetFile)) {
+        if (file_exists($targetFile) && file_exists($compareFile)) {
             $generatedDocumentation = file_get_contents($targetFile);
+            $compareDocumentation = file_get_contents($compareFile);
 
-            if (preg_match('/<!-- START_INFO -->(.*)<!-- END_INFO -->/is', $generatedDocumentation, $generatedInfoText)) {
-                $infoText = trim($generatedInfoText[1], "\n");
+            if (preg_match("/<!-- START_INFO -->(.*)<!-- END_INFO -->/is", $generatedDocumentation, $generatedInfoText)) {
+                $infoText = trim($generatedInfoText[1],"\n");
             }
 
-            if (preg_match('/---(.*)---\\s<!-- START_INFO -->/is', $generatedDocumentation, $generatedFrontmatter)) {
-                $frontmatter = trim($generatedFrontmatter[1], "\n");
+            if (preg_match("/---(.*)---\\s<!-- START_INFO -->/is", $generatedDocumentation, $generatedFrontmatter)) {
+                $frontmatter = trim($generatedFrontmatter[1],"\n");
             }
 
-            $parsedRouteOutput->transform(function ($routeGroup) use ($generatedDocumentation) {
-                return $routeGroup->transform(function ($route) use ($generatedDocumentation) {
-                    if (preg_match('/<!-- START_'.$route['id'].' -->(.*)<!-- END_'.$route['id'].' -->/is', $generatedDocumentation, $routeMatch) && ! $this->option('force')) {
-                        $route['output'] = $routeMatch[0];
+            $parsedRouteOutput->transform(function ($routeGroup) use($generatedDocumentation, $compareDocumentation) {
+                return $routeGroup->transform(function($route) use($generatedDocumentation, $compareDocumentation) {
+                    if (preg_match("/<!-- START_".$route['id']." -->(.*)<!-- END_".$route['id']." -->/is", $generatedDocumentation, $routeMatch)) {
+                        $routeDocumentationChanged = (preg_match("/<!-- START_".$route['id']." -->(.*)<!-- END_".$route['id']." -->/is", $compareDocumentation, $compareMatch) && $compareMatch[1] !== $routeMatch[1]);
+                        if ($routeDocumentationChanged === false ||  $this->option('force')) {
+                            if ($routeDocumentationChanged) {
+                                $this->warn('Discarded manual changes for route ['.implode(',', $route['methods']).'] '.$route['uri']);
+                            }
+                        } else {
+                            $this->warn('Skipping modified route ['.implode(',', $route['methods']).'] '.$route['uri']);
+                            $route['modified_output'] = $routeMatch[0];
+                        }
                     }
-
                     return $route;
                 });
             });
@@ -135,6 +143,7 @@ class GenerateDocumentation extends Command
         $documentarian = new Documentarian();
 
         $markdown = view('apidoc::documentarian')
+            ->with('writeCompareFile', false)
             ->with('frontmatter', $frontmatter)
             ->with('infoText', $infoText)
             ->with('outputPath', $this->option('output'))
@@ -145,8 +154,20 @@ class GenerateDocumentation extends Command
             $documentarian->create($outputPath);
         }
 
+        // Write output file
         file_put_contents($targetFile, $markdown);
 
+        // Write comparable markdown file
+        $compareMarkdown = view('apidoc::documentarian')
+            ->with('writeCompareFile', true)
+            ->with('frontmatter', $frontmatter)
+            ->with('infoText', $infoText)
+            ->with('outputPath', $this->option('output'))
+            ->with('showPostmanCollectionButton', ! $this->option('noPostmanCollection'))
+            ->with('parsedRoutes', $parsedRouteOutput);
+
+        file_put_contents($compareFile, $compareMarkdown);
+
         $this->info('Wrote index.md to: '.$outputPath);
 
         $this->info('Generating API HTML code');
@@ -274,8 +295,7 @@ class GenerateDocumentation extends Command
 
     /**
      * @param $route
-     *
-     * @return bool
+     * @return boolean
      */
     private function isRouteVisibleForDocumentation($route)
     {
@@ -284,14 +304,12 @@ class GenerateDocumentation extends Command
         $comment = $reflection->getMethod($method)->getDocComment();
         if ($comment) {
             $phpdoc = new DocBlock($comment);
-
             return collect($phpdoc->getTags())
-                ->filter(function ($tag) use ($route) {
+                ->filter(function($tag) use ($route){
                     return $tag->getName() === 'hideFromAPIDocumentation';
                 })
                 ->isEmpty();
         }
-
         return true;
     }
 

+ 3 - 2
src/Mpociot/ApiDoc/Generators/AbstractGenerator.php

@@ -47,7 +47,7 @@ abstract class AbstractGenerator
                 'description' => [],
             ];
             foreach ($rules as $rule) {
-                $this->parseRule($rule, $attributeData);
+                $this->parseRule($rule, $attributeData, $routeData['id']);
             }
             $routeData['parameters'][$attribute] = $attributeData;
         }
@@ -185,9 +185,10 @@ abstract class AbstractGenerator
      *
      * @return void
      */
-    protected function parseRule($rule, &$attributeData)
+    protected function parseRule($rule, &$attributeData, $seed)
     {
         $faker = Factory::create();
+        $faker->seed(crc32($seed));
 
         $parsedRule = $this->parseStringRule($rule);
         $parsedRule[0] = $this->normalizeRule($parsedRule[0]);

+ 3 - 1
tests/GenerateDocumentationTest.php

@@ -84,10 +84,12 @@ class GenerateDocumentationTest extends TestCase
         ]);
 
         $generatedMarkdown = file_get_contents(__DIR__.'/../public/docs/source/index.md');
+        $compareMarkdown = file_get_contents(__DIR__.'/../public/docs/source/.compare.md');
         $fixtureMarkdown = file_get_contents(__DIR__.'/Fixtures/index.md');
         $this->assertSame($generatedMarkdown, $fixtureMarkdown);
+        $this->assertSame($compareMarkdown, $fixtureMarkdown);
     }
-
+    
     public function testAddsBindingsToGetRouteRules()
     {
         RouteFacade::get('/api/test/{foo}', TestController::class.'@addRouteBindingsToRequestClass');