Passed
Push — trunk ( 45f743...c781e9 )
by Christian
11:43 queued 13s
created

GetJSFilesPerAreaCommand   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 77
c 1
b 0
f 0
dl 0
loc 118
rs 10
wmc 17

2 Methods

Rating   Name   Duplication   Size   Complexity  
C execute() 0 48 16
A configure() 0 49 1
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\DevOps\StaticAnalyze\Coverage\Command;
4
5
use Composer\Console\Input\InputOption;
6
use Shopware\Core\Framework\Log\Package;
7
use Symfony\Component\Console\Attribute\AsCommand;
8
use Symfony\Component\Console\Command\Command;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
/**
14
 * @internal
15
 */
16
#[AsCommand(
17
    name: 'coverage:js-files-per-area',
18
    description: 'Output all JS Files of the Shopware-namespace aggregated by area.
19
20
  In order for this command to work properly, you need to dump the composer autoloader before running it:
21
  $ composer dump-autoload -o'
22
)]
23
#[Package('core')]
24
class GetJSFilesPerAreaCommand extends Command
25
{
26
    public const OPTION_SEPARATED = 'separated';
27
    public const OPTION_DELIMITER = 'delimiter';
28
    public const OPTION_AREA = 'area';
29
    public const OPTION_RELATIVE = 'relative';
30
    public const OPTION_PREFIX_RELATIVE = 'prefix-relative';
31
    public const OPTION_IGNORE_FILES = 'ignore-files';
32
    private const ARGUMENT_PATH = 'path';
33
34
    protected function configure(): void
35
    {
36
        $this->addArgument(
37
            self::ARGUMENT_PATH,
38
            InputArgument::REQUIRED,
39
            'Absolute path to the JS files'
40
        );
41
42
        $this->addOption(
43
            self::OPTION_SEPARATED,
44
            's',
45
            InputOption::VALUE_NONE,
46
            'Output files separated'
47
        );
48
49
        $this->addOption(
50
            self::OPTION_DELIMITER,
51
            'd',
52
            InputOption::VALUE_OPTIONAL,
53
            'Delimiter used for separated output',
54
            '|'
55
        );
56
57
        $this->addOption(
58
            self::OPTION_AREA,
59
            'a',
60
            InputOption::VALUE_REQUIRED,
61
            'Specify the area for the output'
62
        );
63
64
        $this->addOption(
65
            self::OPTION_RELATIVE,
66
            'r',
67
            InputOption::VALUE_NONE,
68
            'Output paths relative to <path>'
69
        );
70
71
        $this->addOption(
72
            self::OPTION_PREFIX_RELATIVE,
73
            'p',
74
            InputOption::VALUE_REQUIRED,
75
            'Prefix the relative path'
76
        );
77
78
        $this->addOption(
79
            self::OPTION_IGNORE_FILES,
80
            'i',
81
            InputOption::VALUE_REQUIRED,
82
            'Ignore files from search'
83
        );
84
    }
85
86
    protected function execute(InputInterface $input, OutputInterface $output): int
87
    {
88
        $path = $input->getArgument('path');
89
        $areaToFile = [];
90
        $areaToFile['unknown'] = [];
91
        $ignoredFiles = $input->getOption(self::OPTION_IGNORE_FILES) ? explode(',', $input->getOption(self::OPTION_IGNORE_FILES)) : [];
92
93
        $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
94
        /**
95
         * @var \RecursiveIteratorIterator<\RecursiveDirectoryIterator> $files
96
         * @var \Symfony\Component\Finder\SplFileInfo $file
97
         */
98
        foreach ($files as $file) {
99
            $fileName = $file->getFilename();
100
            $filePath = $file->getRealPath();
101
            if ((\str_ends_with($fileName, '.js') || \str_ends_with($fileName, '.ts')) && !\str_ends_with($fileName, '.spec.js')) {
102
                if (\count($ignoredFiles) > 0) {
103
                    if (\in_array($filePath, $ignoredFiles, true)) {
104
                        continue;
105
                    }
106
                }
107
                $fileContent = \file_get_contents($filePath) ?: '';
108
                $matchCount = preg_match('/^.*@package (.*)$/m', $fileContent, $matches);
109
                $filePath = $input->getOption(self::OPTION_RELATIVE) ? $input->getOption(self::OPTION_PREFIX_RELATIVE) . str_replace($path, '', $filePath) : $filePath;
110
                if ($matchCount > 0) {
111
                    if (!\array_key_exists($matches[1], $areaToFile) || !\is_array($areaToFile[$matches[1]])) {
112
                        $areaToFile[$matches[1]] = [];
113
                    }
114
                    $areaToFile[$matches[1]][] = $filePath;
115
                } else {
116
                    $areaToFile['unknown'][] = $filePath;
117
                }
118
            }
119
        }
120
121
        if ($input->getOption(self::OPTION_AREA)) {
122
            $output->write(
123
                $input->getOption(self::OPTION_SEPARATED)
124
                    ? \implode($input->getOption(self::OPTION_DELIMITER) ?: '|', $areaToFile[$input->getOption(self::OPTION_AREA)])
125
                    : var_export($areaToFile[$input->getOption(self::OPTION_AREA)], true)
126
            );
127
        } else {
128
            $output->write(
129
                var_export($areaToFile, true)
130
            );
131
        }
132
133
        return 0;
134
    }
135
}
136