55namespace Rector \Console \Command ;
66
77use Composer \Semver \Semver ;
8+ use Nette \Utils \Strings ;
89use Rector \Composer \InstalledPackageResolver ;
10+ use Rector \Configuration \Option ;
11+ use Rector \Configuration \Parameter \SimpleParameterProvider ;
912use Rector \Contract \Rector \RectorInterface ;
1013use Rector \VersionBonding \Contract \ComposerPackageConstraintInterface ;
14+ use Rector \VersionBonding \ValueObject \ComposerBoundRuleConfiguration ;
15+ use ReflectionObject ;
1116use Symfony \Component \Console \Command \Command ;
1217use Symfony \Component \Console \Input \InputInterface ;
1318use Symfony \Component \Console \Output \OutputInterface ;
@@ -38,20 +43,32 @@ protected function configure(): void
3843 protected function execute (InputInterface $ input , OutputInterface $ output ): int
3944 {
4045 $ tableRows = $ this ->createTableRows ();
46+ $ configurationTableRows = $ this ->createConfigurationTableRows ();
4147
42- if ($ tableRows === []) {
48+ if ($ tableRows === [] && $ configurationTableRows === [] ) {
4349 $ this ->symfonyStyle ->warning ('No composer package bound rule is loaded ' );
4450
4551 return Command::SUCCESS ;
4652 }
4753
48- $ this ->symfonyStyle ->title ('Composer package bound rules ' );
49- $ this ->symfonyStyle ->table (['Rule ' , 'Package ' , 'Requires ' , 'Installed ' , 'Active ' ], $ tableRows );
54+ if ($ tableRows !== []) {
55+ $ this ->symfonyStyle ->title ('Composer package bound rules ' );
56+ $ this ->symfonyStyle ->table (['Rule ' , 'Package ' , 'Requires ' , 'Installed ' , 'Active ' ], $ tableRows );
57+ }
58+
59+ if ($ configurationTableRows !== []) {
60+ $ this ->symfonyStyle ->title ('Composer package bound rule configuration ' );
61+ $ this ->symfonyStyle ->table (
62+ ['Rule ' , 'Package ' , 'Requires ' , 'Installed ' , 'Active ' , 'Configuration ' ],
63+ $ configurationTableRows
64+ );
65+ }
5066
51- $ activeCount = count (array_filter ($ tableRows , static fn (array $ tableRow ): bool => $ tableRow [4 ] === 'yes ' ));
67+ $ allTableRows = [...$ tableRows , ...$ configurationTableRows ];
68+ $ activeCount = count (array_filter ($ allTableRows , static fn (array $ tableRow ): bool => $ tableRow [4 ] === 'yes ' ));
5269
5370 $ this ->symfonyStyle ->note (
54- sprintf ('%d of %d composer package bound rules are active ' , $ activeCount , count ($ tableRows ))
71+ sprintf ('%d of %d composer package bound items are active ' , $ activeCount , count ($ allTableRows ))
5572 );
5673
5774 return Command::SUCCESS ;
@@ -77,7 +94,7 @@ private function createTableRows(): array
7794 $ isActive = $ installedVersion !== null && Semver ::satisfies ($ installedVersion , $ constraint );
7895
7996 $ tableRows [] = [
80- $ rector ::class,
97+ $ this -> printShortClassName ( $ rector ::class) ,
8198 $ packageName ,
8299 $ constraint ,
83100 $ installedVersion ?? '- ' ,
@@ -93,4 +110,86 @@ private function createTableRows(): array
93110
94111 return $ tableRows ;
95112 }
113+
114+ /**
115+ * @return array<array{string, string, string, string, string, string}>
116+ */
117+ private function createConfigurationTableRows (): array
118+ {
119+ $ composerBoundRuleConfigurations = SimpleParameterProvider ::provideArrayParameter (
120+ Option::COMPOSER_BOUND_RULE_CONFIGURATIONS
121+ );
122+
123+ $ tableRows = [];
124+
125+ foreach ($ composerBoundRuleConfigurations as $ composerBoundRuleConfiguration ) {
126+ if (! $ composerBoundRuleConfiguration instanceof ComposerBoundRuleConfiguration) {
127+ continue ;
128+ }
129+
130+ $ packageName = $ composerBoundRuleConfiguration ->getPackageName ();
131+ $ installedVersion = $ this ->installedPackageResolver ->resolvePackageVersion ($ packageName );
132+
133+ $ tableRows [] = [
134+ $ this ->printShortClassName ($ composerBoundRuleConfiguration ->getRectorClass ()),
135+ $ packageName ,
136+ $ composerBoundRuleConfiguration ->getVersionConstraint (),
137+ $ installedVersion ?? '- ' ,
138+ $ composerBoundRuleConfiguration ->isActive () ? 'yes ' : 'no ' ,
139+ $ this ->printConfiguration ($ composerBoundRuleConfiguration ->getConfiguration ()),
140+ ];
141+ }
142+
143+ return $ tableRows ;
144+ }
145+
146+ /**
147+ * @param mixed[] $configuration
148+ */
149+ private function printConfiguration (array $ configuration ): string
150+ {
151+ $ printedItems = [];
152+
153+ foreach ($ configuration as $ key => $ value ) {
154+ $ printedValue = $ this ->printConfigurationValue ($ value );
155+
156+ $ printedItems [] = is_string ($ key ) ? $ key . ': ' . $ printedValue : $ printedValue ;
157+ }
158+
159+ return implode (PHP_EOL , $ printedItems );
160+ }
161+
162+ private function printConfigurationValue (mixed $ value ): string
163+ {
164+ if (is_object ($ value )) {
165+ $ printedPropertyValues = [];
166+
167+ $ reflectionObject = new ReflectionObject ($ value );
168+ foreach ($ reflectionObject ->getProperties () as $ reflectionProperty ) {
169+ $ printedPropertyValues [] = $ this ->printConfigurationValue ($ reflectionProperty ->getValue ($ value ));
170+ }
171+
172+ return $ this ->printShortClassName ($ value ::class) . '( ' . implode (', ' , $ printedPropertyValues ) . ') ' ;
173+ }
174+
175+ if (is_array ($ value )) {
176+ $ printedItems = array_map (
177+ $ this ->printConfigurationValue (...),
178+ $ value
179+ );
180+
181+ return '[ ' . implode (', ' , $ printedItems ) . '] ' ;
182+ }
183+
184+ if (is_bool ($ value )) {
185+ return $ value ? 'true ' : 'false ' ;
186+ }
187+
188+ return (string ) $ value ;
189+ }
190+
191+ private function printShortClassName (string $ className ): string
192+ {
193+ return Strings ::after ($ className , '\\' , -1 ) ?? $ className ;
194+ }
96195}
0 commit comments