RateModuleCommand::getCheckCallback()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 6
rs 10
1
<?php
2
3
namespace SilverStripe\ModuleRatingsPlugin\Command;
4
5
use Composer\Command\BaseCommand;
6
use InvalidArgumentException;
7
use SilverStripe\ModuleRatings\Check;
8
use SilverStripe\ModuleRatings\CheckSuite;
9
use Symfony\Component\Console\Helper\ProgressBar;
10
use Symfony\Component\Console\Helper\Table;
11
use Symfony\Component\Console\Helper\TableSeparator;
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
17
class RateModuleCommand extends BaseCommand
18
{
19
    protected function configure()
20
    {
21
        $this
22
            ->setName('rate-module')
23
            ->setDescription('Assesses a module\'s quality and provides a rating')
24
            ->setDefinition([
25
                new InputArgument(
26
                    'module-path',
27
                    InputArgument::REQUIRED,
28
                    'The path to the module folder, relative to the current working directory'
29
                ),
30
                new InputOption(
31
                    'slug',
32
                    null,
33
                    InputOption::VALUE_OPTIONAL,
34
                    "The module's GitHub repository slug, e.g. silverstripe/silverstripe-blog - used for API checks"
35
                ),
36
            ])->setHelp(<<<TEXT
37
This command will assess the provided module based on a selection of pre-defined quality checks, and provide a rating
38
out of 100.
39
40
You must provide the <info>module-path</info> to map the path from the current working directory to the source code
41
of the module, and you may optionally provide the <info>slug</info> argument which will enable API based status checks.
42
43
Note that without providing <info>slug</info> the module will never be able to achieve a 100% score.
44
TEXT
45
        );
46
    }
47
48
    protected function execute(InputInterface $input, OutputInterface $output)
49
    {
50
        // Ensure autoloader is included
51
        $vendorDir = $this->getComposer()->getConfig()->get('vendor-dir');
52
        require_once $vendorDir . '/autoload.php';
53
54
        $modulePath = $input->getArgument('module-path');
55
        if (empty($modulePath) || !file_exists($modulePath)) {
0 ignored issues
show
Bug introduced by
It seems like $modulePath can also be of type string[]; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
        if (empty($modulePath) || !file_exists(/** @scrutinizer ignore-type */ $modulePath)) {
Loading history...
56
            throw new InvalidArgumentException('Provided module path "' . $modulePath . '" does not exist!');
0 ignored issues
show
Bug introduced by
Are you sure $modulePath of type null|string|string[] can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

56
            throw new InvalidArgumentException('Provided module path "' . /** @scrutinizer ignore-type */ $modulePath . '" does not exist!');
Loading history...
57
        }
58
59
        // Make path absolute
60
        $modulePath = realpath($modulePath);
0 ignored issues
show
Bug introduced by
It seems like $modulePath can also be of type string[]; however, parameter $path of realpath() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

60
        $modulePath = realpath(/** @scrutinizer ignore-type */ $modulePath);
Loading history...
61
62
        $checkSuite = new CheckSuite();
63
64
        $checkSuite->setModuleRoot($modulePath);
65
        if ($slug = $input->getOption('slug')) {
66
            $checkSuite->setRepositorySlug($slug);
67
        }
68
69
        // Get a callback we can use to monitor the check suite progress
70
        $progressBar = new ProgressBar($output, count($checkSuite->getChecks()));
71
        $progressBar->setFormatDefinition('checksuite', '  %current%/%max% [%bar%] %message%');
72
        $progressBar->setFormat('checksuite');
73
        $progressBar->setMessage('Loading check suite...');
74
        $progressBar->start();
75
        $callback = $this->getCheckCallback($progressBar);
76
77
        $checkSuite->run($callback);
78
79
        $progressBar->finish();
80
        $progressBar->clear();
81
82
        $tableRows = $checkSuite->getCheckDetails();
83
        $tableRows[] = new TableSeparator();
84
        $tableRows[] = ['TOTAL SCORE (normalised)', $checkSuite->getScore(), '100'];
85
86
        $table = new Table($output);
87
        $table
88
            ->setHeaders(['Check description', 'Points', 'Maximum'])
89
            ->setRows($tableRows);
90
        $table->render();
91
    }
92
93
    protected function getCheckCallback(ProgressBar $progressBar)
94
    {
95
        return function (Check $check, callable $delegate) use ($progressBar) {
96
            $progressBar->setMessage('Running check: ' . $check->getKey());
97
            $delegate();
98
            $progressBar->advance();
99
        };
100
    }
101
}
102