Passed
Push — feature/add-gacela-cli ( 2018fc )
by Chema
05:13 queued 15s
created

CommandArgumentsParser   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 78
ccs 28
cts 28
cp 1
rs 10
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A allPossiblePsr4Combinations() 0 14 3
A foundPsr4() 0 8 1
A __construct() 0 3 1
A parse() 0 22 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\CodeGenerator\Domain\CommandArguments;
6
7
use InvalidArgumentException;
8
use function count;
9
10
final class CommandArgumentsParser implements CommandArgumentsParserInterface
11
{
12
    /** @var array{autoload: array{psr-4?:array<string,string>}} */
13
    private array $composerJson;
14
15
    /**
16
     * @param array{autoload: array{psr-4?:array<string,string>}} $composerJson
17
     */
18 9
    public function __construct(array $composerJson)
19
    {
20 9
        $this->composerJson = $composerJson;
21
    }
22
23
    /**
24
     * @param string $desiredNamespace The location of the new module. For example: App/TestModule
25
     *
26
     * @throws InvalidArgumentException
27
     */
28 9
    public function parse(string $desiredNamespace): CommandArguments
29
    {
30 9
        if (!isset($this->composerJson['autoload'])) {
31 1
            throw CommandArgumentsException::noAutoloadFound();
32
        }
33
34 8
        if (!isset($this->composerJson['autoload']['psr-4'])) {
35 1
            throw CommandArgumentsException::noAutoloadPsr4Found();
36
        }
37
38 7
        $psr4 = $this->composerJson['autoload']['psr-4'];
39 7
        $allPsr4Combinations = $this->allPossiblePsr4Combinations($desiredNamespace);
40
41 7
        foreach ($allPsr4Combinations as $psr4Combination) {
42 7
            $psr4Key = $psr4Combination . '\\';
43
44 7
            if (isset($psr4[$psr4Key])) {
45 6
                return $this->foundPsr4($psr4Key, $psr4[$psr4Key], $desiredNamespace);
46
            }
47
        }
48
49 1
        throw CommandArgumentsException::noAutoloadPsr4MatchFound($desiredNamespace, array_keys($psr4));
50
    }
51
52
    /**
53
     * Combine all possible psr-4 combinations and return them ordered by longer to shorter.
54
     * This way we'll be able to find the longer match first.
55
     * For example: App/TestModule/TestSubModule will produce an array such as:
56
     * [
57
     *   'App/TestModule/TestSubModule',
58
     *   'App/TestModule',
59
     *   'App',
60
     * ]
61
     *
62
     * @return list<string>
63
     */
64 7
    private function allPossiblePsr4Combinations(string $desiredNamespace): array
65
    {
66 7
        $result = [];
67
68 7
        foreach (explode('/', $desiredNamespace) as $explodedArg) {
69 7
            if (empty($result)) {
70 7
                $result[] = $explodedArg;
71
            } else {
72 7
                $prevValue = $result[count($result) - 1];
73 7
                $result[] = $prevValue . '\\' . $explodedArg;
74
            }
75
        }
76
77 7
        return array_reverse($result);
1 ignored issue
show
Bug Best Practice introduced by
The expression return array_reverse($result) returns the type array which is incompatible with the documented return type Gacela\CodeGenerator\Domain\CommandArguments\list.
Loading history...
78
    }
79
80 6
    private function foundPsr4(string $psr4Key, string $psr4Value, string $desiredNamespace): CommandArguments
81
    {
82 6
        $rootDir = mb_substr($psr4Value, 0, -1);
83 6
        $rootNamespace = mb_substr($psr4Key, 0, -1);
84 6
        $targetDirectory = str_replace(['/', $rootNamespace, '\\'], ['\\', $rootDir, '/'], $desiredNamespace);
85 6
        $namespace = str_replace([$rootDir, '/'], [$rootNamespace, '\\'], $targetDirectory);
86
87 6
        return new CommandArguments($namespace, $targetDirectory);
88
    }
89
}
90