Passed
Pull Request — master (#22)
by
unknown
02:18
created

ReportCommand::groupDependenciesByLicense()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 7
c 2
b 0
f 1
dl 0
loc 14
ccs 0
cts 8
cp 0
rs 10
cc 3
nc 3
nop 1
crap 12
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Dominikb\ComposerLicenseChecker;
6
7
use Dominikb\ComposerLicenseChecker\Contracts\DependencyLoaderAware;
8
use Dominikb\ComposerLicenseChecker\Contracts\LicenseLookupAware;
9
use Dominikb\ComposerLicenseChecker\Traits\DependencyLoaderAwareTrait;
10
use Dominikb\ComposerLicenseChecker\Traits\LicenseLookupAwareTrait;
11
use Symfony\Component\Cache\Adapter\NullAdapter;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Helper\Table;
14
use Symfony\Component\Console\Input\InputDefinition;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Input\InputOption;
17
use Symfony\Component\Console\Output\OutputInterface;
18
19
class ReportCommand extends Command implements LicenseLookupAware, DependencyLoaderAware
20
{
21
    use LicenseLookupAwareTrait, DependencyLoaderAwareTrait;
22
23
    protected static $defaultName = 'report';
24
25
    protected function configure()
26
    {
27
        $this->setDefinition(new InputDefinition([
28
            new InputOption(
29
                'project-path',
30
                'p',
31
                InputOption::VALUE_OPTIONAL,
32
                'Path to directory of composer.json file',
33
                realpath('.')
34
            ),
35
            new InputOption(
36
                'composer',
37
                'c',
38
                InputOption::VALUE_OPTIONAL,
39
                'Path to composer executable',
40
                realpath('./vendor/bin/composer')
41
            ),
42
            new InputOption(
43
                'no-cache',
44
                null,
45
                InputOption::VALUE_NONE,
46
                'Disables caching of license lookups'
47
            ),
48
            new InputOption(
49
                'show-packages',
50
                null,
51
                InputOption::VALUE_NONE,
52
                'Shows the packages for each license.'
53
            ),
54
            new InputOption(
55
                'grouped',
56
                null,
57
                InputOption::VALUE_NONE,
58
                'Display the packages grouped.'
59
            ),
60
            new InputOption(
61
                'filter',
62
                null,
63
                InputOption::VALUE_REQUIRED,
64
                'Filter for specific licences.'
65
            ),
66
        ]));
67
    }
68
69
    protected function execute(InputInterface $input, OutputInterface $output): int
70
    {
71
        $dependencies = $this->dependencyLoader->loadDependencies(
72
            $input->getOption('composer'),
73
            $input->getOption('project-path')
74
        );
75
76
        $groupedByName = $this->groupDependenciesByLicense($dependencies);
77
78
        $shouldCache = ! $input->getOption('no-cache');
79
        $licenses = $this->lookUpLicenses(array_keys($groupedByName), $output, $shouldCache);
80
81
        /* @var License $license */
82
        $this->outputFormattedLicenses($output, $input, $licenses, $groupedByName);
83
84
        return 0;
85
    }
86
87
    /**
88
     * @param  Dependency[]  $dependencies
89
     * @return array
90
     */
91
    private function groupDependenciesByLicense(array $dependencies): array
92
    {
93
        $grouped = [];
94
95
        foreach ($dependencies as $dependency) {
96
            [$license] = $dependency->getLicenses();
97
98
            if (! isset($grouped[$license])) {
99
                $grouped[$license] = [];
100
            }
101
            $grouped[$license][] = $dependency;
102
        }
103
104
        return $grouped;
105
    }
106
107
    private function lookUpLicenses(array $licenses, OutputInterface $output, $useCache = true): array
108
    {
109
        if (! $useCache) {
110
            $this->licenseLookup->setCache(new NullAdapter);
111
        }
112
113
        $lookedUp = [];
114
        foreach ($licenses as $license) {
115
            $output->writeln("Looking up $license ...");
116
            $lookedUp[$license] = $this->licenseLookup->lookUp($license);
117
        }
118
119
        return $lookedUp;
120
    }
121
122
    /**
123
     * @param  OutputInterface  $output
124
     * @param  InputInterface  $input
125
     * @param  License[]  $licenses
126
     * @param  array  $groupedByName
127
     */
128
    protected function outputFormattedLicenses(OutputInterface $output, InputInterface $input, array $licenses, array $groupedByName): void
129
    {
130
        foreach ($licenses as $license) {
131
132
            if ($input->getOption('filter')) {
133
                $licenses = explode(',', $input->getOption('filter'));
134
                $licenses = array_map(function ($licence) {
135
                    return trim($licence);
136
                }, $licenses);
137
138
                if (!in_array($license->getShortName(), $licenses)) {
139
                    $output->writeln(sprintf("Skipped %s", $license->getShortName()), OutputInterface::VERBOSITY_VERY_VERBOSE);
140
                    continue;
141
                }
142
            }
143
144
            $dependencies = $groupedByName[$license->getShortName()];
145
146
            $usageCount = count($dependencies);
147
            $headline = sprintf(PHP_EOL.'Count %d - %s (%s)', $usageCount, $license->getShortName(),
148
                $license->getSource());
149
            $output->writeln($headline);
150
            $licenseTable = new Table($output);
151
            $licenseTable->setHeaders(['CAN', 'CAN NOT', 'MUST']);
152
153
            $can = $license->getCan();
154
            $cannot = $license->getCannot();
155
            $must = $license->getMust();
156
            $columnWidth = max(count($can), count($cannot), count($must));
157
158
            $can = array_pad($can, $columnWidth, null);
159
            $cannot = array_pad($cannot, $columnWidth, null);
160
            $must = array_pad($must, $columnWidth, null);
161
162
            $inlineHeading = function ($key) {
163
                return is_string($key) ? $key : '';
164
            };
165
166
            $can = array_map_keys($can, $inlineHeading);
167
            $cannot = array_map_keys($cannot, $inlineHeading);
168
            $must = array_map_keys($must, $inlineHeading);
169
170
            for ($i = 0; $i < $columnWidth; $i++) {
171
                $licenseTable->addRow([
172
                    'CAN'    => $can[$i],
173
                    'CANNOT' => $cannot[$i],
174
                    'MUST'   => $must[$i],
175
                ]);
176
            }
177
            $licenseTable->render();
178
179
            if ($input->getOption('show-packages') || $output->isVerbose()) {
180
                $output->writeln('');
181
182
                if ($input->getOption('grouped')) {
183
                    $output->write('packages: ');
184
                    $packages = [];
185
                    foreach ($dependencies as $dependency) {
186
                        $packages[] = $dependency->getName();
187
                    }
188
189
                    $output->write(implode(', ', $packages));
190
                    continue;
191
                }
192
193
                foreach ($dependencies as $dependency) {
194
                    $output->writeln(sprintf('%s (%s)', $dependency->getName(), $dependency->getVersion()));
195
                }
196
            }
197
        }
198
    }
199
}
200