33namespace Dukecity \CommandSchedulerBundle \Service ;
44
55use Exception ;
6- use Symfony \Bundle \FrameworkBundle \Console \Application ;
6+ use Symfony \Component \Console \Command \Command ;
7+ use Symfony \Component \Console \Descriptor \JsonDescriptor ;
78use Symfony \Component \Console \Exception \CommandNotFoundException ;
8- use Symfony \Component \Console \Input \ArrayInput ;
9- use Symfony \Component \Console \Output \StreamOutput ;
10- use Symfony \Component \ErrorHandler \Debug ;
9+ use Symfony \Component \Console \Output \BufferedOutput ;
1110use Symfony \Component \HttpKernel \KernelInterface ;
1211
1312/**
@@ -45,12 +44,17 @@ public function isNamespacingValid(array $excludedNamespaces, array $includedNam
4544 );
4645 }
4746
48-
47+ /**
48+ * @param string[] $namespaces
49+ */
4950 public function setExcludedNamespaces (array $ namespaces = []): void
5051 {
5152 $ this ->excludedNamespaces = $ namespaces ;
5253 }
5354
55+ /**
56+ * @param string[] $namespaces
57+ */
5458 public function setIncludedNamespaces (array $ namespaces = []): void
5559 {
5660 $ this ->includedNamespaces = $ namespaces ;
@@ -59,65 +63,30 @@ public function setIncludedNamespaces(array $namespaces = []): void
5963 /**
6064 * Get all available commands from symfony
6165 *
62- * @throws Exception
66+ * @return string[] Command names
6367 */
64- public function getAvailableCommands (string $ format = " xml " , string $ env = " prod " ): string | array
68+ public function getAvailableCommands (): array
6569 {
66- $ application = new Application ($ this ->kernel );
67- $ application ->setAutoExit (false );
68-
69- $ input = new ArrayInput (
70- [
71- 'command ' => 'list ' ,
72- '--format ' => $ format ,
73- '--env ' => $ env ,
74- ]
75- );
76-
77- try {
78- # needed for PHPUnit > 10
79- # https://github.com/sebastianbergmann/phpunit/issues/5721
80- if ($ this ->kernel ->getEnvironment () !== 'test ' )
81- {
82- Debug::enable ();
83- }
84-
85- $ output = new StreamOutput (fopen ('php://memory ' , 'wb+ ' ));
86- $ application ->run ($ input , $ output );
87-
88- rewind ($ output ->getStream ());
89-
90- if ($ format === "xml " )
91- {return stream_get_contents ($ output ->getStream ());}
92-
93- if ($ format === "json " )
94- {return json_decode (
95- stream_get_contents ($ output ->getStream ()),
96- true ,
97- 512 ,
98- JSON_THROW_ON_ERROR
99- );}
100-
101- throw new \InvalidArgumentException ('Only xml and json are allowed ' );
102- } catch (\Throwable ) {
103- throw new \RuntimeException ('Listing of commands could not be read ' );
104- }
70+ return $ this ->kernel
71+ ->getContainer ()
72+ ->get ('console.command_loader ' )
73+ ->getNames ();
10574 }
10675
10776 /**
10877 * Execute the console command "list" and parse the output to have all available command.
10978 *
11079 * @return array<string, string[]> ["Namespace1" => ["Command1", "Command2"]]
11180 *
112- * @throws Exception
81+ * @throws \InvalidArgumentException
11382 */
114- public function getCommands (string $ env = " prod " ): array
83+ public function getCommands (): array
11584 {
11685 if (!$ this ->isNamespacingValid ($ this ->excludedNamespaces , $ this ->includedNamespaces )) {
11786 throw new \InvalidArgumentException ('Cannot combine excludedNamespaces with includedNamespaces ' );
11887 }
11988
120- return $ this ->extractCommands ($ this ->getAvailableCommands (" json " , $ env ));
89+ return $ this ->extractCommands ($ this ->getAvailableCommands ());
12190 }
12291
12392
@@ -127,17 +96,16 @@ public function getCommands(string $env="prod"): array
12796 * @return array<string, array<string, mixed>>
12897 * @throws Exception
12998 */
130- public function getAllowedCommandDetails (string $ env = " prod " ): array
99+ public function getAllowedCommandDetails (): array
131100 {
132- # var_dump($this->getCommands($env));
133- return $ this ->getCommandDetails ($ this ->getCommands ($ env ));
101+ return $ this ->getCommandDetails ($ this ->getAvailableCommands ());
134102 }
135103
136104
137105 /**
138106 * Is the command-List wrapped in namespaces?
139107 *
140- * @param array<string, array<string, string>> $commands
108+ * @param array<string, array<string, string>>|string[] $commands
141109 * @return string[]
142110 */
143111 public function reduceNamespacedCommands (array $ commands ): array
@@ -166,25 +134,29 @@ public function reduceNamespacedCommands(array $commands): array
166134 }
167135
168136 /**
137+ * @param string[] $commands
169138 * @return array<string, array<string, mixed>>
170139 * @throws Exception
171140 */
172141 public function getCommandDetails (array $ commands ): array
173142 {
174- $ availableCommands = $ this ->getAvailableCommands ("json " );
175143 $ result = [];
176- #$command->getDefinition();
177144
178- # Is the command-List wrapped in namespaces?
179- $ commands = $ this -> reduceNamespacedCommands ( $ commands );
145+ $ commandLoader = $ this -> kernel -> getContainer ()-> get ( ' console.command_loader ' );
146+ $ jsonDescriptor = new JsonDescriptor ( );
180147
181- foreach ($ availableCommands ["commands " ] as $ command )
182- {
183- #var_dump($command);
184- if (in_array ($ command ["name " ], $ commands , true ))
185- {
186- $ result [$ command ["name " ]] = $ command ;
148+ foreach ($ commands as $ commandName ) {
149+ if (!$ commandLoader ->has ($ commandName )) {
150+ continue ;
187151 }
152+
153+ /** @var Command $command */
154+ $ command = $ commandLoader ->get ($ commandName );
155+
156+ $ buffer = new BufferedOutput ();
157+ $ jsonDescriptor ->describe ($ buffer , $ command );
158+
159+ $ result [$ commandName ] = json_decode ($ buffer ->fetch (), true );
188160 }
189161
190162 if (count ($ result )===0 )
@@ -193,48 +165,29 @@ public function getCommandDetails(array $commands): array
193165 return $ result ;
194166 }
195167
196-
197-
198-
199168 /**
200169 * Extract an array of available Symfony commands from the JSON output.
201170 *
202- * @param array< string, array<int, mixed>> $commands
171+ * @param string[] $commands Command names
203172 * @return array<string, array<int|string, mixed>|string>
204- * ["namespaces]
205- * [0]
206- * ["id"] => cache
207- * ["commands"] => ["cache:clear", "cache:warmup", ...]
173+ * ["namespaces"][0]
208174 */
209175 private function extractCommands (array $ commands ): array
210176 {
211- if (count ($ commands ) === 0 ) {
212- return [];
213- }
214-
215177 $ commandsList = [];
216178
217- try {
218- foreach ($ commands ["namespaces " ] as $ namespace ) {
219- $ namespaceId = (string ) $ namespace ["id " ];
220-
221- # Blacklisting and Whitelisting
222- if ((count ($ this ->excludedNamespaces ) > 0 && in_array ($ namespaceId , $ this ->excludedNamespaces , true ))
223- ||
224- (count ($ this ->includedNamespaces ) > 0 && !in_array ($ namespaceId , $ this ->includedNamespaces , true ))
225- ) {
226- continue ;
227- }
179+ foreach ($ commands as $ commandName ) {
180+ $ namespaceId = explode (': ' , $ commandName )[0 ];
228181
229- # Add Command Name to array
230- foreach ($ namespace ["commands " ] as $ command ) {
231-
232- $ commandsList [$ namespaceId ][$ command ] = $ command ;
233- }
182+ # Blacklisting and Whitelisting
183+ if ((count ($ this ->excludedNamespaces ) > 0 && in_array ($ namespaceId , $ this ->excludedNamespaces , true ))
184+ ||
185+ (count ($ this ->includedNamespaces ) > 0 && !in_array ($ namespaceId , $ this ->includedNamespaces , true ))
186+ ) {
187+ continue ;
234188 }
235- } catch (Exception ) {
236- // return an empty CommandList
237- $ commandsList = ['ERROR: please check php bin/console list --format=json ' => 'error ' ];
189+
190+ $ commandsList [$ namespaceId ][$ commandName ] = $ commandName ;
238191 }
239192
240193 return $ commandsList ;
0 commit comments