1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace Smeghead \PhpVariableHardUsage \Command ;
6+
7+ use Smeghead \PhpVariableHardUsage \Analyze \VariableAnalyzer ;
8+ use Smeghead \PhpVariableHardUsage \Parse \VariableParser ;
9+
10+ final class ScopesCommand extends AbstractCommand
11+ {
12+ /** @var list<string> */
13+ private array $ paths ;
14+
15+ /**
16+ * @param list<string> $paths ディレクトリまたはファイルのパスリスト
17+ */
18+ public function __construct (array $ paths )
19+ {
20+ $ this ->paths = $ paths ;
21+ }
22+
23+ public function execute (): void
24+ {
25+ $ phpFiles = [];
26+
27+ // 各パスを処理
28+ foreach ($ this ->paths as $ path ) {
29+ if (is_dir ($ path )) {
30+ // ディレクトリの場合は再帰的にPHPファイルを収集
31+ $ dirFiles = $ this ->findPhpFiles ($ path );
32+ $ phpFiles = array_merge ($ phpFiles , $ dirFiles );
33+ } elseif (is_file ($ path ) && pathinfo ($ path , PATHINFO_EXTENSION ) === 'php ' ) {
34+ // 単一のPHPファイルの場合
35+ $ phpFiles [] = $ path ;
36+ } else {
37+ fwrite (STDERR , "Invalid path: {$ path }\n" );
38+ }
39+ }
40+
41+ if (empty ($ phpFiles )) {
42+ fwrite (STDERR , "No PHP files found in specified paths \n" );
43+ return ;
44+ }
45+
46+ // 重複を削除
47+ $ phpFiles = array_unique ($ phpFiles );
48+
49+ $ results = [];
50+ foreach ($ phpFiles as $ file ) {
51+ try {
52+ $ content = file_get_contents ($ file );
53+ if ($ content === false ) {
54+ fwrite (STDERR , "Failed to read file: {$ file }\n" );
55+ continue ;
56+ }
57+
58+ $ parser = new VariableParser ();
59+ $ parseResult = $ parser ->parse ($ content );
60+ $ analyzer = new VariableAnalyzer ($ file , $ parseResult ->functions );
61+ $ results [] = $ analyzer ->analyze ();
62+ } catch (\Exception $ e ) {
63+ fwrite (STDERR , "Error analyzing {$ file }: {$ e ->getMessage ()}\n" );
64+ }
65+ }
66+
67+ // 複数ファイルの結果をまとめて表示
68+ $ this ->printResults ($ results );
69+ }
70+
71+ /**
72+ * @return list<string>
73+ */
74+ private function findPhpFiles (string $ directory ): array
75+ {
76+ $ result = [];
77+ $ files = new \RecursiveIteratorIterator (
78+ new \RecursiveDirectoryIterator ($ directory , \RecursiveDirectoryIterator::SKIP_DOTS )
79+ );
80+
81+ /** @var \SplFileInfo $file */
82+ foreach ($ files as $ file ) {
83+ if ($ file ->isFile () && $ file ->getExtension () === 'php ' ) {
84+ $ result [] = $ file ->getPathname ();
85+ }
86+ }
87+
88+ return $ result ;
89+ }
90+
91+ /**
92+ * @param list<\Smeghead\PhpVariableHardUsage\Analyze\AnalysisResult> $results
93+ */
94+ private function printResults (array $ results ): void
95+ {
96+ // スコープベースのレポートを生成
97+ $ allScopes = [];
98+ foreach ($ results as $ result ) {
99+ foreach ($ result ->scopes as $ scope ) {
100+ $ allScopes [] = [
101+ 'file ' => $ result ->filename ,
102+ 'namespace ' => $ scope ->namespace ,
103+ 'name ' => $ scope ->name ,
104+ 'variableHardUsage ' => $ scope ->getVariableHardUsage ()
105+ ];
106+ }
107+ }
108+
109+ // 酷使度でソート
110+ usort ($ allScopes , function ($ a , $ b ) {
111+ return $ b ['variableHardUsage ' ] <=> $ a ['variableHardUsage ' ];
112+ });
113+
114+ // 結果を表示
115+ echo json_encode (['scopes ' => $ allScopes ], JSON_PRETTY_PRINT ) . PHP_EOL ;
116+ }
117+ }
0 commit comments