Skip to content

Commit c848df6

Browse files
Refactoring the commands.
1 parent 1681315 commit c848df6

6 files changed

Lines changed: 280 additions & 72 deletions

File tree

src/Application.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Parser;
1414
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\ScoreCalculator;
1515
use Phauthentic\CognitiveCodeAnalysis\Business\DirectoryScanner;
16+
use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade;
1617
use Phauthentic\CognitiveCodeAnalysis\Command\ChurnCommand;
1718
use Phauthentic\CognitiveCodeAnalysis\Command\CognitiveMetricsCommand;
18-
use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade;
1919
use Phauthentic\CognitiveCodeAnalysis\Command\EventHandler\ProgressBarHandler;
2020
use Phauthentic\CognitiveCodeAnalysis\Command\EventHandler\VerboseHandler;
21+
use Phauthentic\CognitiveCodeAnalysis\Command\Handler\ChurnReportHandler;
22+
use Phauthentic\CognitiveCodeAnalysis\Command\Handler\CognitiveMetricsReportHandler;
2123
use Phauthentic\CognitiveCodeAnalysis\Command\Presentation\ChurnTextRenderer;
2224
use Phauthentic\CognitiveCodeAnalysis\Command\Presentation\CognitiveMetricTextRenderer;
2325
use Phauthentic\CognitiveCodeAnalysis\Config\ConfigLoader;
@@ -115,6 +117,20 @@ private function registerServices(): void
115117
new Reference(NodeTraverserInterface::class),
116118
])
117119
->setPublic(true);
120+
121+
$this->containerBuilder->register(ChurnReportHandler::class, ChurnReportHandler::class)
122+
->setArguments([
123+
new Reference(MetricsFacade::class),
124+
new Reference(OutputInterface::class),
125+
])
126+
->setPublic(true);
127+
128+
$this->containerBuilder->register(CognitiveMetricsReportHandler::class, CognitiveMetricsReportHandler::class)
129+
->setArguments([
130+
new Reference(MetricsFacade::class),
131+
new Reference(OutputInterface::class),
132+
])
133+
->setPublic(true);
118134
}
119135

120136
private function bootstrap(): void
@@ -200,13 +216,15 @@ private function registerCommands(): void
200216
new Reference(MetricsFacade::class),
201217
new Reference(CognitiveMetricTextRenderer::class),
202218
new Reference(BaselineService::class),
219+
new Reference(CognitiveMetricsReportHandler::class),
203220
])
204221
->setPublic(true);
205222

206223
$this->containerBuilder->register(ChurnCommand::class, ChurnCommand::class)
207224
->setArguments([
208225
new Reference(MetricsFacade::class),
209226
new Reference(ChurnTextRenderer::class),
227+
new Reference(ChurnReportHandler::class),
210228
])
211229
->setPublic(true);
212230
}

src/Command/ChurnCommand.php

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace Phauthentic\CognitiveCodeAnalysis\Command;
66

7-
use Exception;
87
use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade;
8+
use Phauthentic\CognitiveCodeAnalysis\Command\Handler\ChurnReportHandler;
99
use Phauthentic\CognitiveCodeAnalysis\Command\Presentation\ChurnTextRenderer;
1010
use Symfony\Component\Console\Attribute\AsCommand;
1111
use Symfony\Component\Console\Command\Command;
@@ -18,12 +18,11 @@
1818
*/
1919
#[AsCommand(
2020
name: 'churn',
21-
description: ''
21+
description: 'Calculates the churn based on version control history.',
2222
)]
2323
class ChurnCommand extends Command
2424
{
2525
private const ARGUMENT_PATH = 'path';
26-
2726
public const OPTION_CONFIG_FILE = 'config';
2827
public const OPTION_VCS = 'vcs';
2928
public const OPTION_SINCE = 'since';
@@ -36,7 +35,8 @@ class ChurnCommand extends Command
3635
*/
3736
public function __construct(
3837
private MetricsFacade $metricsFacade,
39-
private ChurnTextRenderer $renderer
38+
private ChurnTextRenderer $renderer,
39+
private ChurnReportHandler $reportHandler
4040
) {
4141
parent::__construct();
4242
}
@@ -109,8 +109,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
109109
since: $input->getOption(self::OPTION_SINCE),
110110
);
111111

112-
if ($this->shouldGenerateReport($input)) {
113-
return $this->generateReport($classes, $input, $output);
112+
$reportType = $input->getOption(self::OPTION_REPORT_TYPE);
113+
$reportFile = $input->getOption(self::OPTION_REPORT_FILE);
114+
115+
if ($reportType !== null || $reportFile !== null) {
116+
return $this->reportHandler->handle($classes, $reportType, $reportFile);
114117
}
115118

116119
$this->renderer->renderChurnTable(
@@ -119,36 +122,4 @@ classes: $classes
119122

120123
return self::SUCCESS;
121124
}
122-
123-
/**
124-
* @param array<string, array<string, mixed>> $classes
125-
* @param InputInterface $input
126-
* @param OutputInterface $output
127-
* @return int
128-
*/
129-
private function generateReport(array $classes, InputInterface $input, OutputInterface $output): int
130-
{
131-
try {
132-
$this->metricsFacade->exportChurnReport(
133-
classes: $classes,
134-
reportType: $input->getOption(self::OPTION_REPORT_TYPE),
135-
filename: $input->getOption(self::OPTION_REPORT_FILE)
136-
);
137-
138-
return self::SUCCESS;
139-
} catch (Exception $exception) {
140-
$output->writeln(sprintf(
141-
'<error>Error generating report: %s</error>',
142-
$exception->getMessage()
143-
));
144-
145-
return self::FAILURE;
146-
}
147-
}
148-
149-
private function shouldGenerateReport(InputInterface $input): bool
150-
{
151-
return $input->getOption(self::OPTION_REPORT_FILE)
152-
&& $input->getOption(self::OPTION_REPORT_TYPE);
153-
}
154125
}

src/Command/CognitiveMetricsCommand.php

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
namespace Phauthentic\CognitiveCodeAnalysis\Command;
66

77
use Exception;
8-
use JsonException;
98
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\BaselineService;
109
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection;
1110
use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade;
12-
use Phauthentic\CognitiveCodeAnalysis\CognitiveAnalysisException;
11+
use Phauthentic\CognitiveCodeAnalysis\Command\Handler\CognitiveMetricsReportHandler;
1312
use Phauthentic\CognitiveCodeAnalysis\Command\Presentation\CognitiveMetricTextRenderer;
1413
use Symfony\Component\Console\Attribute\AsCommand;
1514
use Symfony\Component\Console\Command\Command;
@@ -36,7 +35,8 @@ class CognitiveMetricsCommand extends Command
3635
public function __construct(
3736
private MetricsFacade $metricsFacade,
3837
private CognitiveMetricTextRenderer $renderer,
39-
private BaselineService $baselineService
38+
private BaselineService $baselineService,
39+
private CognitiveMetricsReportHandler $reportHandler
4040
) {
4141
parent::__construct();
4242
}
@@ -110,14 +110,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
110110
$reportFile = $input->getOption(self::OPTION_REPORT_FILE);
111111

112112
if ($reportType !== null || $reportFile !== null) {
113-
if ($this->isOneReportOptionMissing($reportType, $reportFile, $output)) {
114-
return Command::FAILURE;
115-
}
116-
if (!$this->isValidReportType($reportType, $output)) {
117-
return Command::FAILURE;
118-
}
119-
$this->metricsFacade->exportMetricsReport($metricsCollection, $reportType, $reportFile);
120-
return Command::SUCCESS;
113+
return $this->reportHandler->handle($metricsCollection, $reportType, $reportFile);
121114
}
122115

123116
$this->renderer->render($metricsCollection, $this->metricsFacade->getConfig());
@@ -158,25 +151,4 @@ private function loadConfiguration(string $configFile, OutputInterface $output):
158151
return false;
159152
}
160153
}
161-
162-
private function isOneReportOptionMissing(?string $reportType, ?string $reportFile, OutputInterface $output): bool
163-
{
164-
if (($reportType !== null && $reportFile === null) || ($reportType === null && $reportFile !== null)) {
165-
$output->writeln('<error>Both report type and file must be provided.</error>');
166-
return true;
167-
}
168-
169-
return false;
170-
}
171-
172-
private function isValidReportType(?string $reportType, OutputInterface $output): bool
173-
{
174-
if (!in_array($reportType, ['json', 'csv', 'html'])) {
175-
$message = sprintf('Invalid report type `%s` provided. Only `json`, `csv`, and `html` are accepted.', $reportType);
176-
$output->writeln('<error>' . $message . '</error>');
177-
return false;
178-
}
179-
180-
return true;
181-
}
182154
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phauthentic\CognitiveCodeAnalysis\Command\Handler;
6+
7+
use Exception;
8+
use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade;
9+
use Symfony\Component\Console\Command\Command;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
12+
/**
13+
*
14+
*/
15+
class ChurnReportHandler
16+
{
17+
public function __construct(
18+
private MetricsFacade $metricsFacade,
19+
private OutputInterface $output
20+
) {
21+
}
22+
23+
/**
24+
* Handles report option validation and report generation.
25+
*
26+
* @param array<string, array<string, mixed>> $classes
27+
*/
28+
public function handle(
29+
array $classes,
30+
?string $reportType,
31+
?string $reportFile,
32+
): int {
33+
if ($this->hasIncompleteReportOptions($reportType, $reportFile)) {
34+
$this->output->writeln('<error>Both report type and file must be provided.</error>');
35+
36+
return Command::FAILURE;
37+
}
38+
39+
if (!$this->isValidReportType($reportType)) {
40+
return $this->handleInvalidReportType($reportType);
41+
}
42+
43+
try {
44+
$this->metricsFacade->exportChurnReport(
45+
classes: $classes,
46+
reportType: (string)$reportType,
47+
filename: (string)$reportFile
48+
);
49+
50+
return Command::SUCCESS;
51+
} catch (Exception $exception) {
52+
return $this->handleExceptions($exception);
53+
}
54+
}
55+
56+
private function hasIncompleteReportOptions(?string $reportType, ?string $reportFile): bool
57+
{
58+
return ($reportType === null && $reportFile !== null) || ($reportType !== null && $reportFile === null);
59+
}
60+
61+
private function isValidReportType(?string $reportType): bool
62+
{
63+
return in_array($reportType, ['json', 'csv', 'html']);
64+
}
65+
66+
/**
67+
* @param Exception $exception
68+
* @return int
69+
*/
70+
private function handleExceptions(Exception $exception): int
71+
{
72+
$this->output->writeln(sprintf(
73+
'<error>Error generating report: %s</error>',
74+
$exception->getMessage()
75+
));
76+
77+
return Command::FAILURE;
78+
}
79+
80+
/**
81+
* @param string|null $reportType
82+
* @return int
83+
*/
84+
private function handleInvalidReportType(?string $reportType): int
85+
{
86+
$this->output->writeln(sprintf(
87+
'<error>Invalid report type `%s` provided. Only `json`, `csv`, and `html` are accepted.</error>',
88+
$reportType
89+
));
90+
91+
return Command::FAILURE;
92+
}
93+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Phauthentic\CognitiveCodeAnalysis\Command\Handler;
6+
7+
use Exception;
8+
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection;
9+
use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade;
10+
use Symfony\Component\Console\Command\Command;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
13+
class CognitiveMetricsReportHandler
14+
{
15+
public function __construct(
16+
private MetricsFacade $metricsFacade,
17+
private OutputInterface $output
18+
) {
19+
}
20+
21+
/**
22+
* Handles report option validation and report generation.
23+
*/
24+
public function handle(
25+
CognitiveMetricsCollection $metricsCollection,
26+
?string $reportType,
27+
?string $reportFile,
28+
): int {
29+
if ($this->hasIncompleteReportOptions($reportType, $reportFile)) {
30+
$this->output->writeln('<error>Both report type and file must be provided.</error>');
31+
32+
return Command::FAILURE;
33+
}
34+
35+
if (!$this->isValidReportType($reportType)) {
36+
return $this->handleInvalidReporType($reportType);
37+
}
38+
39+
try {
40+
$this->metricsFacade->exportMetricsReport(
41+
metricsCollection: $metricsCollection,
42+
reportType: (string)$reportType,
43+
filename: (string)$reportFile
44+
);
45+
46+
return Command::SUCCESS;
47+
} catch (Exception $exception) {
48+
return $this->handleExceptions($exception);
49+
}
50+
}
51+
52+
private function hasIncompleteReportOptions(?string $reportType, ?string $reportFile): bool
53+
{
54+
return ($reportType === null && $reportFile !== null) || ($reportType !== null && $reportFile === null);
55+
}
56+
57+
private function isValidReportType(?string $reportType): bool
58+
{
59+
return in_array($reportType, ['json', 'csv', 'html']);
60+
}
61+
62+
/**
63+
* @param Exception $exception
64+
* @return int
65+
*/
66+
private function handleExceptions(Exception $exception): int
67+
{
68+
$this->output->writeln(sprintf(
69+
'<error>Error generating report: %s</error>',
70+
$exception->getMessage()
71+
));
72+
73+
return Command::FAILURE;
74+
}
75+
76+
/**
77+
* @param string|null $reportType
78+
* @return int
79+
*/
80+
public function handleInvalidReporType(?string $reportType): int
81+
{
82+
$this->output->writeln(sprintf(
83+
'<error>Invalid report type `%s` provided. Only `json`, `csv`, and `html` are accepted.</error>',
84+
$reportType
85+
));
86+
87+
return Command::FAILURE;
88+
}
89+
}

0 commit comments

Comments
 (0)