1515use Inhere \Console \Util \Helper ;
1616use InvalidArgumentException ;
1717use ReflectionException ;
18+ use RuntimeException ;
1819use SplFileInfo ;
1920use function class_exists ;
2021use function implode ;
@@ -266,7 +267,7 @@ public function dispatch(string $name, bool $detachedRun = false)
266267 }
267268
268269 $ cmdId = $ name ;
269- $ this ->debugf ( 'begin dispatch the input command: %s ' , $ name );
270+ $ this ->debugf ('begin dispatch the input command: %s ' , $ name );
270271
271272 // format is: `group action`
272273 if (strpos ($ name , ' ' ) > 0 ) {
@@ -309,7 +310,7 @@ public function dispatch(string $name, bool $detachedRun = false)
309310 }
310311
311312 // is controller/group
312- return $ this ->runAction ($ info[ ' group ' ], $ info [ ' action ' ], $ info [ ' handler ' ] , $ cmdOptions , $ detachedRun );
313+ return $ this ->runAction ($ info , $ cmdOptions , $ detachedRun );
313314 }
314315
315316 /**
@@ -355,21 +356,64 @@ protected function runCommand(string $name, $handler, array $options)
355356 /**
356357 * Execute an action in a group command(controller)
357358 *
358- * @param string $group The group name
359- * @param string $action Command method, no suffix
360- * @param mixed $handler The controller class or object
359+ * @param array $info Matched route info
361360 * @param array $options
362361 * @param bool $detachedRun
363362 *
364363 * @return mixed
365364 * @throws ReflectionException
366365 */
367- protected function runAction (string $ group , string $ action , $ handler , array $ options , bool $ detachedRun = false )
366+ protected function runAction (array $ info , array $ options , bool $ detachedRun = false )
368367 {
368+ $ controller = $ this ->createController ($ info );
369+
370+ if ($ desc = $ options ['description ' ] ?? '' ) {
371+ $ controller ::setDescription ($ desc );
372+ }
373+
374+ if ($ detachedRun ) {
375+ $ controller ->setDetached ();
376+ }
377+
378+ // Command method, no suffix
379+ return $ controller ->run ($ info ['action ' ]);
380+ }
381+
382+ /**
383+ * @param string $name
384+ *
385+ * @return Controller
386+ */
387+ public function getController (string $ name ): Controller
388+ {
389+ $ info = $ this ->router ->getControllerInfo ($ name );
390+ if (!$ info ) {
391+ throw new RuntimeException ('the group controller not exist. name: ' . $ name );
392+ }
393+
394+ $ info ['group ' ] = $ name ;
395+ return $ this ->createController ($ info );
396+ }
397+
398+ /**
399+ * @param array $info
400+ *
401+ * @return Controller
402+ */
403+ protected function createController (array $ info ): Controller
404+ {
405+ $ group = $ info ['group ' ]; // The group name
406+ if (isset ($ this ->groupObjects [$ group ])) {
407+ $ this ->debugf ('load the "%s" controller object form cache ' , $ group );
408+ return $ this ->groupObjects [$ group ];
409+ }
410+
411+ $ this ->debugf ('create the "%s" controller object and cache it ' , $ group );
412+
369413 /** @var Controller $handler */
414+ $ handler = $ info ['handler ' ]; // The controller class or object
370415 if (is_string ($ handler )) {
371416 $ class = $ handler ;
372-
373417 if (!class_exists ($ class )) {
374418 Helper::throwInvalidArgument ('The console controller class [%s] not exists! ' , $ class );
375419 }
@@ -387,17 +431,11 @@ protected function runAction(string $group, string $action, $handler, array $opt
387431
388432 // force set name and description
389433 $ handler ::setName ($ group );
390- if ($ desc = $ options ['description ' ] ?? '' ) {
391- $ handler ::setDescription ($ desc );
392- }
393-
394434 $ handler ->setApp ($ this );
395435 $ handler ->setDelimiter ($ this ->delimiter );
396436
397- if ($ detachedRun ) {
398- $ handler ->setDetached ();
399- }
400-
401- return $ handler ->run ($ action );
437+ // cache object
438+ $ this ->groupObjects [$ group ] = $ handler ;
439+ return $ handler ;
402440 }
403441}
0 commit comments