Passed
Push — master ( d33d35...37f9e4 )
by Dominik
01:18
created

ReportCommand::groupDependenciesByLicense()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 14
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
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\Simple\NullCache;
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
    const LINES_BEFORE_DEPENDENCY_VERSIONS = 2;
24
25
    protected static $defaultName = 'report';
26
27
    protected function configure()
28
    {
29
        $this->setDefinition(new InputDefinition([
30
            new InputOption(
31
                'project-path',
32
                'p',
33
                InputOption::VALUE_OPTIONAL,
34
                'Path to directory of composer.json file',
35
                realpath('.')
36
            ),
37
            new InputOption(
38
                'composer',
39
                'c',
40
                InputOption::VALUE_OPTIONAL,
41
                'Path to composer executable',
42
                realpath('./vendor/bin/composer')
43
            ),
44
            new InputOption(
45
                'no-cache',
46
                null,
47
                InputOption::VALUE_NONE,
48
                'Disables caching of license lookups'
49
            ),
50
        ]));
51
    }
52
53
    protected function execute(InputInterface $input, OutputInterface $output)
54
    {
55
        $dependencies = $this->dependencyLoader->loadDependencies(
56
            $input->getOption('composer'),
57
            $input->getOption('project-path')
58
        );
59
60
        $groupedByName = $this->groupDependenciesByLicense($dependencies);
61
62
        $shouldCache = ! $input->getOption('no-cache');
63
        $licenses = $this->lookUpLicenses(array_keys($groupedByName), $output, $shouldCache);
64
65
        /** @var License $license */
66
        $this->outputFormattedLicenses($output, $licenses, $groupedByName);
67
    }
68
69
    /**
70
     * @param Dependency[] $dependencies
71
     *
72
     * @return array
73
     */
74
    private function groupDependenciesByLicense(array $dependencies)
75
    {
76
        $grouped = [];
77
78
        foreach ($dependencies as $dependency) {
79
            [$license] = $dependency->getLicenses();
80
81
            if (! isset($grouped[$license])) {
82
                $grouped[$license] = [];
83
            }
84
            $grouped[$license][] = $dependency;
85
        }
86
87
        return $grouped;
88
    }
89
90
    private function lookUpLicenses(array $licenses, OutputInterface $output, $useCache = true)
91
    {
92
        if ( ! $useCache) {
93
            $this->licenseLookup->setCache(new NullCache);
94
        }
95
96
        $lookedUp = [];
97
        foreach ($licenses as $license) {
98
            $output->writeln("Looking up $license ...");
99
            $lookedUp[$license] = $this->licenseLookup->lookUp($license);
100
        }
101
102
        return $lookedUp;
103
    }
104
105
    /**
106
     * @param OutputInterface $output
107
     * @param License[]       $licenses
108
     * @param array           $groupedByName
109
     */
110
    protected function outputFormattedLicenses(OutputInterface $output, array $licenses, array $groupedByName): void
111
    {
112
        foreach ($licenses as $license) {
113
            $usageCount = count($groupedByName[$license->getShortName()]);
114
            $headline = sprintf(PHP_EOL . "Count %d - %s (%s)", $usageCount, $license->getShortName(),
115
                $license->getSource());
116
            $output->writeln($headline);
117
            $licenseTable = new Table($output);
118
            $licenseTable->setHeaders(['CAN', 'CAN NOT', 'MUST']);
119
120
            $can = $license->getCan();
121
            $cannot = $license->getCannot();
122
            $must = $license->getMust();
123
            $columnWidth = max(count($can), count($cannot), count($must));
124
125
            $can = array_pad($can, $columnWidth, null);
126
            $cannot = array_pad($cannot, $columnWidth, null);
127
            $must = array_pad($must, $columnWidth, null);
128
129
            $inlineHeading = function ($key) {
130
                return is_string($key) ? $key : '';
131
            };
132
133
            $can = array_map_keys($can, $inlineHeading);
134
            $cannot = array_map_keys($cannot, $inlineHeading);
135
            $must = array_map_keys($must, $inlineHeading);
136
137
            for ($i = 0; $i < $columnWidth; $i++) {
138
                $licenseTable->addRow([
139
                    'CAN'    => $can[$i],
140
                    'CANNOT' => $cannot[$i],
141
                    'MUST'   => $must[$i],
142
                ]);
143
            }
144
            $licenseTable->render();
145
        }
146
    }
147
}
148