Completed
Pull Request — master (#109)
by
unknown
01:23
created

ChurnCommand   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 12

Importance

Changes 0
Metric Value
wmc 13
lcom 2
cbo 12
dl 0
loc 171
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A configure() 0 8 1
A execute() 0 19 3
B getProcessResults() 0 21 5
A displayResults() 0 21 1
A setupProcessor() 0 5 1
A createFileManager() 0 4 1
1
<?php declare(strict_types = 1);
2
3
namespace Churn\Commands;
4
5
use Churn\Results\ResultCollection;
6
use Illuminate\Support\Collection;
7
use Churn\Factories\ProcessFactory;
8
use Churn\Managers\FileManager;
9
use Churn\Results\ResultsParser;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Helper\Table;
12
use Symfony\Component\Console\Input\InputArgument;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Churn\Configuration\Config;
17
use Symfony\Component\Yaml\Yaml;
18
19
class ChurnCommand extends Command
20
{
21
    /**
22
     * The config values.
23
     * @var Config
24
     */
25
    private $config;
26
27
    /**
28
     * The process factory.
29
     * @var ProcessFactory
30
     */
31
    private $processFactory;
32
33
    /**
34
     * Th results parser.
35
     * @var ResultsParser
36
     */
37
    private $resultsParser;
38
39
    /**
40
     * Collection of files to run the processes on.
41
     * @var FileCollection
42
     */
43
    private $filesCollection;
44
45
    /**
46
     * Collection of processes currently running.
47
     * @var Collection
48
     */
49
    private $runningProcesses;
50
51
    /**
52
     * Array of completed processes.
53
     * @var array
54
     */
55
    private $completedProcessesArray;
56
57
    /**
58
     * The start time.
59
     * @var float
60
     */
61
    private $startTime;
62
63
    /**
64
     * Keeps track of how many files were processed.
65
     * @var integer
66
     */
67
    private $filesCount;
68
69
    /**
70
     * ChurnCommand constructor.
71
     */
72
    public function __construct()
73
    {
74
        parent::__construct();
75
76
        $this->resultsParser = new ResultsParser();
77
    }
78
79
    /**
80
     * Configure the command
81
     * @return void
82
     */
83
    protected function configure(): void
84
    {
85
        $this->setName('run')
86
            ->addArgument('paths', InputArgument::IS_ARRAY, 'Path to source to check.')
87
            ->addOption('configuration', 'c', InputOption::VALUE_OPTIONAL, 'Path to the configuration file', 'churn.yml')  // @codingStandardsIgnoreLine
88
            ->setDescription('Check files')
89
            ->setHelp('Checks the churn on the provided path argument(s).');
90
    }
91
92
    /**
93
     * Execute the command
94
     * @param  InputInterface  $input  Input.
95
     * @param  OutputInterface $output Output.
96
     * @return void
97
     */
98
    protected function execute(InputInterface $input, OutputInterface $output): void
99
    {
100
        $this->startTime = microtime(true);
101
        $this->setupProcessor($input->getOption('configuration'));
102
103
        $this->filesCollection = $this->createFileManager()->getPhpFiles($input->getArgument('paths'));
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createFileManager...->getArgument('paths')) of type object<Churn\Collections\FileCollection> is incompatible with the declared type object<Churn\Commands\FileCollection> of property $filesCollection.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
104
        $this->filesCount = $this->filesCollection->count();
105
        $this->runningProcesses = new Collection;
106
        $this->completedProcessesArray = [];
107
        while ($this->filesCollection->hasFiles() || $this->runningProcesses->count()) {
108
            $this->getProcessResults();
109
        }
110
        $completedProcesses = new Collection($this->completedProcessesArray);
111
112
        $results = $this->resultsParser
113
            ->parse($completedProcesses)
114
            ->normalizeAgainst($this->config);
115
        $this->displayResults($output, $results);
116
    }
117
118
    /**
119
     * Gets the output from processes and stores them in the completedProcessArray member.
120
     * @return void
121
     */
122
    private function getProcessResults(): void
123
    {
124
        for ($index = $this->runningProcesses->count(); $this->filesCollection->hasFiles() > 0 && $index < $this->config->getParallelJobs(); $index++) {
125
            $file = $this->filesCollection->getNextFile();
126
127
            $process = $this->processFactory->createGitCommitProcess($file);
128
            $process->start();
129
            $this->runningProcesses->put($process->getKey(), $process);
130
131
            $process = $this->processFactory->createCyclomaticComplexityProcess($file);
132
            $process->start();
133
            $this->runningProcesses->put($process->getKey(), $process);
134
        }
135
136
        foreach ($this->runningProcesses as $file => $process) {
137
            if ($process->isSuccessful()) {
138
                $this->runningProcesses->forget($process->getKey());
139
                $this->completedProcessesArray[$process->getFileName()][$process->getType()] = $process;
140
            }
141
        }
142
    }
143
144
    /**
145
     * Displays the results in a table.
146
     * @param  OutputInterface  $output  Output.
147
     * @param  ResultCollection $results Results Collection.
148
     * @return void
149
     */
150
    protected function displayResults(OutputInterface $output, ResultCollection $results): void
151
    {
152
        $totalTime = microtime(true) - $this->startTime;
153
        echo "\n
154
    ___  _   _  __  __  ____  _  _     ____  _   _  ____
155
   / __)( )_( )(  )(  )(  _ \( \( )___(  _ \( )_( )(  _ \
156
  ( (__  ) _ (  )(__)(  )   / )  ((___))___/ ) _ (  )___/
157
   \___)(_) (_)(______)(_)\_)(_)\_)   (__)  (_) (_)(__)      https://github.com/bmitch/churn-php\n\n";
158
159
        $table = new Table($output);
160
        $table->setHeaders(['File', 'Times Changed', 'Complexity', 'Score']);
161
        $table->addRows($results->toArray());
162
163
        $table->render();
164
165
        echo "  "
166
            . $this->filesCount
167
            . " files analysed in {$totalTime} seconds using "
168
            . $this->config->getParallelJobs()
169
            . " parallel jobs.\n\n";
170
    }
171
172
    /**
173
     * @param string $configFile Relative path churn.yml configuration file.
174
     * @return void
175
     */
176
    private function setupProcessor(string $configFile): void
177
    {
178
        $this->config = Config::create(Yaml::parse(@file_get_contents($configFile)) ?? []);
179
        $this->processFactory = new ProcessFactory($this->config);
180
    }
181
182
    /**
183
     * @return FileManager
184
     */
185
    private function createFileManager(): FileManager
186
    {
187
        return new FileManager($this->config->getFileExtensions(), $this->config->getFilesToIgnore());
188
    }
189
}
190