1818use Symfony \Component \Console \Input \InputInterface ;
1919use Symfony \Component \Console \Output \OutputInterface ;
2020
21+ use function array_column ;
2122use function assert ;
2223use function basename ;
2324use function filter_var ;
@@ -37,6 +38,21 @@ abstract class Command extends SymfonyCommand
3738{
3839 private const WRAP_WIDTH = 78 ;
3940
41+ private const CUSTOM_HELP_TAGS = [
42+ [
43+ 'pattern ' => '/<code>(.*)<\/(?:code)?>/Us ' ,
44+ 'replacement ' => '<fg=bright-blue>$1</> ' ,
45+ ],
46+ [
47+ 'pattern ' => '/<file>(.*)<\/(?:file)?>/Us ' ,
48+ 'replacement ' => '<fg=bright-magenta>$1</> ' ,
49+ ],
50+ [
51+ 'pattern ' => '/<link>(.*)<\/(?:link)?>/Us ' ,
52+ 'replacement ' => '<fg=cyan;options=underscore>$1</> ' ,
53+ ],
54+ ];
55+
4056 private ?EventDispatcher $ eventDispatcher = null ;
4157 private readonly ExtraConfiguration $ extra ;
4258
@@ -82,20 +98,24 @@ final protected function execute(InputInterface $input, OutputInterface $output)
8298 return $ exitCode + $ this ->eventDispatcher ->dispatchScript ((string ) $ this ->getName ());
8399 }
84100
85- public function setHelp ( string $ help ): static
101+ public function getHelp ( ): string
86102 {
87- $ name = (string ) $ this ->getName ();
88-
89- // The Symfony method Command::getParsedHelp() already does this, but
90- // we do it here to account for proper line wrapping in wrapHelp().
91- $ placeholders = ['%command.name% ' , '%command.full_name% ' ];
92-
93- // phpcs:ignore SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable
94- $ replacements = [$ name , trim (basename (($ _SERVER ['PHP_SELF ' ] ?? '' )) . ' ' . $ name )];
95-
96- $ help = str_replace ($ placeholders , $ replacements , $ help ?: $ this ->getDescription ());
103+ return $ this ->wrapHelp (
104+ $ this ->replaceHelpTokens (
105+ parent ::getHelp (),
106+ (string ) $ this ->getName (),
107+ ),
108+ );
109+ }
97110
98- return parent ::setHelp ($ this ->wrapHelp ($ help ));
111+ public function getHelpForComposer (): string
112+ {
113+ return $ this ->wrapHelp (
114+ $ this ->replaceHelpTokens (
115+ parent ::getHelp (),
116+ $ this ->getExtra ()->getPrefixedCommandName (),
117+ ),
118+ );
99119 }
100120
101121 private function wrapHelp (string $ message ): string
@@ -187,4 +207,26 @@ private function buildComposerExtraConfiguration(): ExtraConfiguration
187207 memoryLimit: $ commandConfig ['memory-limit ' ] ?? $ config ['memory-limit ' ] ?? null ,
188208 );
189209 }
210+
211+ private function replaceHelpTokens (string $ helpText , string $ commandName ): string
212+ {
213+ // The Symfony method Command::getParsedHelp() already does this, but
214+ // we do it here to account for proper line wrapping in wrapHelp().
215+ $ placeholders = ['%command.name% ' , '%command.full_name% ' ];
216+
217+ // phpcs:ignore SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable
218+ $ replacements = [$ commandName , trim (basename (($ _SERVER ['PHP_SELF ' ] ?? '' )) . ' ' . $ commandName )];
219+
220+ $ helpText = str_replace ($ placeholders , $ replacements , $ helpText ?: $ this ->getDescription ());
221+
222+ // We could use OutputFormatterStyle for this, but when running in the
223+ // context of a Composer plugin, we're not able to apply those styles
224+ // to the Composer console application, so we must use replacements
225+ // instead.
226+ return (string ) preg_replace (
227+ array_column (self ::CUSTOM_HELP_TAGS , 'pattern ' ),
228+ array_column (self ::CUSTOM_HELP_TAGS , 'replacement ' ),
229+ $ helpText ,
230+ );
231+ }
190232}
0 commit comments