1818
1919namespace FastForward \DevTools \Console \Command ;
2020
21+ use FastForward \DevTools \Composer \Json \ComposerJsonInterface ;
22+ use Random \Engine ;
23+ use Twig \Environment ;
24+ use function Safe \getcwd ;
25+ use Composer \Command \BaseCommand ;
2126use FastForward \DevTools \Composer \Json \ComposerJson ;
27+ use FastForward \DevTools \Filesystem \FilesystemInterface ;
28+ use FastForward \DevTools \Process \ProcessBuilderInterface ;
29+ use FastForward \DevTools \Process \ProcessQueueInterface ;
30+ use FastForward \DevTools \Template \EngineInterface ;
2231use Symfony \Component \Console \Attribute \AsCommand ;
2332use Symfony \Component \Console \Input \InputInterface ;
2433use Symfony \Component \Console \Input \InputOption ;
2534use Symfony \Component \Console \Output \OutputInterface ;
26- use Symfony \Component \Filesystem \Filesystem ;
27- use Symfony \Component \Filesystem \Path ;
28- use Symfony \Component \Process \Process ;
2935
30- use function Safe \file_get_contents ;
3136use function array_map ;
3237use function implode ;
3338use function ltrim ;
4247 description: 'Generates API documentation. ' ,
4348 help: 'This command generates API documentation using phpDocumentor. ' ,
4449)]
45- final class DocsCommand extends AbstractCommand
50+ final class DocsCommand extends BaseCommand
4651{
4752 /**
48- * @param ComposerJson $composerJson
49- * @param Filesystem $filesystem
53+ * Creates a new DocsCommand instance.
54+ *
55+ * @param ProcessBuilderInterface $processBuilder the process builder for executing phpDocumentor
56+ * @param ProcessQueueInterface $processQueue the process queue for managing execution
57+ * @param Environment $renderer
58+ * @param FilesystemInterface $filesystem the filesystem for handling file operations
59+ * @param ComposerJsonInterface $composerJson the composer.json handler for accessing project metadata
5060 */
5161 public function __construct (
52- private readonly ComposerJson $ composerJson ,
53- Filesystem $ filesystem
62+ private readonly ProcessBuilderInterface $ processBuilder ,
63+ private readonly ProcessQueueInterface $ processQueue ,
64+ private readonly Environment $ renderer ,
65+ private readonly FilesystemInterface $ filesystem ,
66+ private readonly ComposerJsonInterface $ composerJson ,
5467 ) {
55- return parent ::__construct ($ filesystem );
68+ parent ::__construct ();
5669 }
5770
5871 /**
@@ -85,6 +98,12 @@ protected function configure(): void
8598 mode: InputOption::VALUE_OPTIONAL ,
8699 description: 'Path to the template directory for the generated HTML documentation. ' ,
87100 default: 'vendor/fast-forward/phpdoc-bootstrap-template ' ,
101+ )
102+ ->addOption (
103+ name: 'cache-dir ' ,
104+ mode: InputOption::VALUE_OPTIONAL ,
105+ description: 'Path to the cache directory for phpDocumentor. ' ,
106+ default: 'tmp/cache/phpdoc ' ,
88107 );
89108 }
90109
@@ -103,28 +122,34 @@ protected function execute(InputInterface $input, OutputInterface $output): int
103122 {
104123 $ output ->writeln ('<info>Generating API documentation...</info> ' );
105124
106- $ source = $ this ->getAbsolutePath ($ input ->getOption ('source ' ));
125+ $ source = $ this ->filesystem -> getAbsolutePath ($ input ->getOption ('source ' ));
107126
108127 if (! $ this ->filesystem ->exists ($ source )) {
109128 $ output ->writeln (\sprintf ('<error>Source directory not found: %s</error> ' , $ source ));
110129
111130 return self ::FAILURE ;
112131 }
113132
114- $ target = $ this ->getAbsolutePath ($ input ->getOption ('target ' ));
115- $ template = $ input ->getOption ('template ' );
133+ $ target = $ this ->filesystem -> getAbsolutePath ($ input ->getOption ('target ' ));
134+ $ cacheDir = $ this -> filesystem -> getAbsolutePath ( $ input ->getOption ('cache-dir ' ) );
116135
117- $ htmlConfig = $ this ->createPhpDocumentorConfig (source: $ source , target: $ target , template: $ template );
136+ $ config = $ this ->createPhpDocumentorConfig (
137+ source: $ source ,
138+ target: $ target ,
139+ template: $ input ->getOption ('template ' ),
140+ cacheDir: $ cacheDir
141+ );
118142
119- $ command = new Process ([
120- $ this ->getAbsolutePath ('vendor/bin/phpdoc ' ),
121- '--config ' ,
122- $ htmlConfig ,
123- '--markers ' ,
124- 'TODO,FIXME,BUG,HACK ' ,
125- ]);
143+ $ phpdoc = $ this ->processBuilder
144+ ->withArgument ('--config ' , $ config )
145+ ->withArgument ('--ansi ' )
146+ ->withArgument ('--no-progress ' )
147+ ->withArgument ('--markers ' , 'TODO,FIXME,BUG,HACK ' )
148+ ->build ('vendor/bin/phpdoc ' );
149+
150+ $ this ->processQueue ->add ($ phpdoc );
126151
127- return parent :: runProcess ( $ command , $ output );
152+ return $ this -> processQueue -> run ( $ output );
128153 }
129154
130155 /**
@@ -133,46 +158,34 @@ protected function execute(InputInterface $input, OutputInterface $output): int
133158 * @param string $source the source directory for the generated documentation
134159 * @param string $target the output directory for the generated documentation
135160 * @param string $template the phpDocumentor template name or path
161+ * @param string $cacheDir the cache directory for phpDocumentor
136162 *
137163 * @return string the absolute path to the generated configuration
138164 */
139- private function createPhpDocumentorConfig (string $ source , string $ target , string $ template ): string
165+ private function createPhpDocumentorConfig (string $ source , string $ target , string $ template, string $ cacheDir ): string
140166 {
141- $ workingDirectory = $ this ->getCurrentWorkingDirectory ();
142-
143- $ templateFile = parent ::getDevToolsFile ('resources/phpdocumentor.xml ' );
144-
145- $ configDirectory = $ this ->getAbsolutePath ('tmp/cache/phpdoc ' );
146- $ configFile = $ configDirectory . '/phpdocumentor.xml ' ;
147-
148- if (! $ this ->filesystem ->exists ($ configDirectory )) {
149- $ this ->filesystem ->mkdir ($ configDirectory );
150- }
151-
167+ $ workingDirectory = \getcwd ();
152168 $ psr4Namespaces = $ this ->composerJson ->getAutoload ();
153- $ paths = implode ("\n" , array_map (
154- fn (string $ path ): string => \sprintf (
155- '<path>%s</path> ' ,
156- ltrim (str_replace ($ workingDirectory , '' , $ path ), '/ ' )
157- ),
158- $ psr4Namespaces ,
159- ));
169+ $ guidePath = $ this ->filesystem ->makePathRelative ($ source );
170+ $ defaultPackageName = array_key_first ($ psr4Namespaces ) ?: '' ;
160171
161- $ guidePath = Path::makeRelative ($ source , $ workingDirectory );
172+ $ content = $ this ->renderer ->render ('phpdocumentor.xml ' , [
173+ 'title ' => $ this ->composerJson ->getPackageName (),
174+ 'template ' => $ template ,
175+ 'target ' => $ target ,
176+ 'cacheDir ' => $ cacheDir ,
177+ 'workingDirectory ' => $ workingDirectory ,
178+ 'paths ' => $ psr4Namespaces ,
179+ 'guidePath ' => $ guidePath ,
180+ 'defaultPackageName ' => rtrim ($ defaultPackageName , '\\' ),
181+ ]);
162182
163- $ defaultPackageName = array_key_first ($ psr4Namespaces ) ?: '' ;
164- $ templateContents = file_get_contents ($ templateFile );
165-
166- $ this ->filesystem ->dumpFile ($ configFile , strtr ($ templateContents , [
167- '%%TITLE%% ' => $ this ->composerJson ->getPackageDescription (),
168- '%%TEMPLATE%% ' => $ template ,
169- '%%TARGET%% ' => $ target ,
170- '%%WORKING_DIRECTORY%% ' => $ workingDirectory ,
171- '%%PATHS%% ' => $ paths ,
172- '%%GUIDE_PATH%% ' => $ guidePath ,
173- '%%DEFAULT_PACKAGE_NAME%% ' => $ defaultPackageName ,
174- ]));
175-
176- return $ configFile ;
183+ $ this ->filesystem ->dumpFile (
184+ filename: 'phpdocumentor.xml ' ,
185+ content: $ content ,
186+ path: $ cacheDir ,
187+ );
188+
189+ return $ this ->filesystem ->getAbsolutePath ('phpdocumentor.xml ' , $ cacheDir );
177190 }
178191}
0 commit comments