Skip to content

Commit 59e9f88

Browse files
committed
feat: add modes as several commands.
1 parent 8a8730b commit 59e9f88

File tree

8 files changed

+256
-51
lines changed

8 files changed

+256
-51
lines changed

src/Command.php

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,63 +4,15 @@
44

55
namespace Smeghead\PhpVariableHardUsage;
66

7-
use Smeghead\PhpVariableHardUsage\Analyze\VariableAnalyzer;
8-
use Smeghead\PhpVariableHardUsage\Parse\VariableParser;
9-
107
final class Command
118
{
12-
private const VERSION = '0.0.3';
13-
149
/**
1510
* @param list<string> $argv
1611
*/
1712
public function run(array $argv): void
1813
{
19-
if (count($argv) < 2) {
20-
$this->printHelp();
21-
return;
22-
}
23-
24-
$option = $argv[1];
25-
26-
if ($option === '--help') {
27-
$this->printHelp();
28-
return;
29-
}
30-
31-
if ($option === '--version') {
32-
$this->printVersion();
33-
return;
34-
}
35-
36-
$filePath = $argv[1];
37-
if (!file_exists($filePath)) {
38-
echo "File not found: $filePath\n";
39-
return;
40-
}
41-
42-
$parser = new VariableParser();
43-
$content = file_get_contents($filePath);
44-
if ($content === false) {
45-
echo "Failed to read file: $filePath\n";
46-
return;
47-
}
48-
$parseResult = $parser->parse($content);
49-
$analyzer = new VariableAnalyzer($filePath, $parseResult->functions);
50-
$result = $analyzer->analyze();
51-
echo $result->format();
52-
}
53-
54-
private function printHelp(): void
55-
{
56-
echo "Usage: php bin/php-variable-hard-usage [source_file]\n";
57-
echo "Options:\n";
58-
echo " --help Display help information\n";
59-
echo " --version Show the version of the tool\n";
60-
}
61-
62-
private function printVersion(): void
63-
{
64-
echo "PHP Variable Hard Usage Analyzer, version " . self::VERSION . "\n";
14+
$factory = new CommandFactory();
15+
$command = $factory->createCommand($argv);
16+
$command->execute();
6517
}
6618
}

src/Command/AbstractCommand.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Smeghead\PhpVariableHardUsage\Command;
6+
7+
abstract class AbstractCommand implements CommandInterface
8+
{
9+
private const VERSION = '0.0.3';
10+
11+
protected function printVersion(): void
12+
{
13+
echo "PHP Variable Hard Usage Analyzer, version " . self::VERSION . "\n";
14+
}
15+
16+
protected function printHelp(): void
17+
{
18+
echo "Usage: php bin/php-variable-hard-usage [command] [options]\n";
19+
echo "Commands:\n";
20+
echo " single <file> Analyze a single file\n";
21+
echo " scopes <directory> Analyze PHP files in a directory\n";
22+
echo "Options:\n";
23+
echo " --help Display help information\n";
24+
echo " --version Show the version of the tool\n";
25+
}
26+
}

src/Command/CommandInterface.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Smeghead\PhpVariableHardUsage\Command;
6+
7+
interface CommandInterface
8+
{
9+
public function execute(): void;
10+
}

src/Command/HelpCommand.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Smeghead\PhpVariableHardUsage\Command;
6+
7+
final class HelpCommand extends AbstractCommand
8+
{
9+
public function execute(): void
10+
{
11+
$this->printHelp();
12+
}
13+
}

src/Command/ScopesCommand.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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+
private string $directory;
13+
14+
public function __construct(string $directory)
15+
{
16+
$this->directory = $directory;
17+
}
18+
19+
public function execute(): void
20+
{
21+
if (!is_dir($this->directory)) {
22+
fwrite(STDERR, "Directory not found: {$this->directory}\n");
23+
return;
24+
}
25+
26+
$phpFiles = $this->findPhpFiles($this->directory);
27+
if (empty($phpFiles)) {
28+
fwrite(STDERR, "No PHP files found in: {$this->directory}\n");
29+
return;
30+
}
31+
32+
$results = [];
33+
foreach ($phpFiles as $file) {
34+
try {
35+
$content = file_get_contents($file);
36+
if ($content === false) {
37+
fwrite(STDERR, "Failed to read file: {$file}\n");
38+
continue;
39+
}
40+
41+
$parser = new VariableParser();
42+
$parseResult = $parser->parse($content);
43+
$analyzer = new VariableAnalyzer($file, $parseResult->functions);
44+
$results[] = $analyzer->analyze();
45+
} catch (\Exception $e) {
46+
fwrite(STDERR, "Error analyzing {$file}: {$e->getMessage()}\n");
47+
}
48+
}
49+
50+
// 複数ファイルの結果をまとめて表示
51+
$this->printResults($results);
52+
}
53+
54+
/**
55+
* @return list<string>
56+
*/
57+
private function findPhpFiles(string $directory): array
58+
{
59+
$result = [];
60+
$files = new \RecursiveIteratorIterator(
61+
new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS)
62+
);
63+
64+
/** @var \SplFileInfo $file */
65+
foreach ($files as $file) {
66+
if ($file->isFile() && $file->getExtension() === 'php') {
67+
$result[] = $file->getPathname();
68+
}
69+
}
70+
71+
return $result;
72+
}
73+
74+
/**
75+
* @param list<\Smeghead\PhpVariableHardUsage\Analyze\AnalysisResult> $results
76+
*/
77+
private function printResults(array $results): void
78+
{
79+
// スコープベースのレポートを生成
80+
$allScopes = [];
81+
foreach ($results as $result) {
82+
foreach ($result->scopes as $scope) {
83+
$allScopes[] = [
84+
'file' => $result->filename,
85+
'namespace' => $scope->namespace,
86+
'name' => $scope->name,
87+
'variableHardUsage' => $scope->getVariableHardUsage()
88+
];
89+
}
90+
}
91+
92+
// 酷使度でソート
93+
usort($allScopes, function ($a, $b) {
94+
return $b['variableHardUsage'] <=> $a['variableHardUsage'];
95+
});
96+
97+
// 結果を表示
98+
echo json_encode(['scopes' => $allScopes], JSON_PRETTY_PRINT) . PHP_EOL;
99+
}
100+
}

src/Command/SingleCommand.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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 SingleCommand extends AbstractCommand
11+
{
12+
private string $filePath;
13+
14+
public function __construct(string $filePath)
15+
{
16+
$this->filePath = $filePath;
17+
}
18+
19+
public function execute(): void
20+
{
21+
if (!file_exists($this->filePath)) {
22+
fwrite(STDERR, "File not found: {$this->filePath}\n");
23+
return;
24+
}
25+
26+
$parser = new VariableParser();
27+
$content = file_get_contents($this->filePath);
28+
if ($content === false) {
29+
fwrite(STDERR, "Failed to read file: {$this->filePath}\n");
30+
return;
31+
}
32+
33+
$parseResult = $parser->parse($content);
34+
$analyzer = new VariableAnalyzer($this->filePath, $parseResult->functions);
35+
$result = $analyzer->analyze();
36+
echo $result->format();
37+
}
38+
}

src/Command/VersionCommand.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Smeghead\PhpVariableHardUsage\Command;
6+
7+
final class VersionCommand extends AbstractCommand
8+
{
9+
public function execute(): void
10+
{
11+
$this->printVersion();
12+
}
13+
}

src/CommandFactory.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Smeghead\PhpVariableHardUsage;
6+
7+
use Smeghead\PhpVariableHardUsage\Command\CommandInterface;
8+
use Smeghead\PhpVariableHardUsage\Command\HelpCommand;
9+
use Smeghead\PhpVariableHardUsage\Command\SingleCommand;
10+
use Smeghead\PhpVariableHardUsage\Command\ScopesCommand;
11+
use Smeghead\PhpVariableHardUsage\Command\VersionCommand;
12+
13+
final class CommandFactory
14+
{
15+
/**
16+
* @param list<string> $argv
17+
*/
18+
public function createCommand(array $argv): CommandInterface
19+
{
20+
if (count($argv) < 2) {
21+
return new HelpCommand();
22+
}
23+
24+
$arg = $argv[1];
25+
26+
if ($arg === '--help') {
27+
return new HelpCommand();
28+
}
29+
30+
if ($arg === '--version') {
31+
return new VersionCommand();
32+
}
33+
34+
if ($arg === 'single') {
35+
if (count($argv) < 3) {
36+
fwrite(STDERR, "Usage: php bin/php-variable-hard-usage single <file>\n");
37+
return new HelpCommand();
38+
}
39+
return new SingleCommand($argv[2]);
40+
}
41+
42+
if ($arg === 'scopes') {
43+
if (count($argv) < 3) {
44+
fwrite(STDERR, "Usage: php bin/php-variable-hard-usage scopes <directory>\n");
45+
return new HelpCommand();
46+
}
47+
return new ScopesCommand($argv[2]);
48+
}
49+
50+
// 後方互換性のため、コマンドが指定されていない場合は単一ファイルモードとして扱う
51+
return new SingleCommand($argv[1]);
52+
}
53+
}

0 commit comments

Comments
 (0)