Passed
Branch 1.0.x (7d3940)
by Koldo
02:45
created

AdditionalPackages   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 34.29%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 37
c 1
b 0
f 0
dl 0
loc 70
ccs 12
cts 35
cp 0.3429
rs 10
wmc 9

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B ask() 0 57 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Antidot\Installer\Question;
6
7
use Composer\IO\IOInterface;
8
use InvalidArgumentException;
9
use Throwable;
10
11
use function array_key_first;
12
use function array_keys;
13
use function file_get_contents;
14
use function json_decode;
15
use function preg_match;
16
use function sprintf;
17
18
use const JSON_THROW_ON_ERROR;
19
20
class AdditionalPackages
21
{
22
    private const PACKAGIST_API = 'https://packagist.org/packages/';
23
    private IOInterface $io;
24
25 2
    public function __construct(IOInterface $io)
26
    {
27 2
        $this->io = $io;
28 2
    }
29
30
    /**
31
     * @return array<string, string>
32
     */
33 1
    public function ask(): array
34
    {
35 1
        $packages = [];
36
37
        do {
38 1
            $installAnotherPackage = $this->io->askConfirmation(
39 1
                'Do you want no add any package from packagist? [Y/<info>N</info>]: ',
40 1
                false
41
            );
42
            try {
43 1
                if (true === $installAnotherPackage) {
44
                    $packageName = $this->io->ask('Add package name "vendor/package": ', null);
45
                    /** @var string $response */
46
                    $response = file_get_contents(self::PACKAGIST_API . $packageName . '.json');
47
                    /** @var array<string, mixed> $packageInfo */
48
                    $packageInfo = json_decode(
49
                        $response,
50
                        true,
51
                        48,
52
                        JSON_THROW_ON_ERROR
53
                    );
54
                    if (isset($packageInfo['status']) && 'error' === $packageInfo['status']) {
55
                        throw new InvalidArgumentException('Invalid package name %s given.');
56
                    }
57
58
                    /** @
59
                     * @var array<string> $versions
60
                     * @psalm-suppress MixedArrayAccess
61
                     * @psalm-suppress MixedArgument
62
                     */
63
                    $versions = array_keys($packageInfo['package']['versions']);
64
                    /** @var string $packageVersion */
65
                    $packageVersion = $this->io->select(
66
                        sprintf(
67
                            'Select version for package %s: [<info>%s</info>] ',
68
                            $packageName,
69
                            $versions[array_key_first($versions)] ?? '*'
70
                        ),
71
                        $versions,
72
                        $versions[array_key_first($versions)] ?? '*'
73
                    );
74
75
                    if (null !== $packageName) {
76
                        $prefix = '';
77
                        if (preg_match('`^(?:v)?\d+\.\d+\.\d+(?:\.\d+)?$`', $packageVersion)) {
78
                            $prefix = '^';
79
                        }
80 1
                        $packages[$packageName] = $prefix . $versions[$packageVersion];
81
                    }
82
                }
83
            } catch (Throwable $exception) {
84
                $installAnotherPackage = true;
85
                $this->io->writeError('<error>' . $exception->getMessage() . '</error>');
86
            }
87 1
        } while (true === $installAnotherPackage);
88
89 1
        return $packages;
90
    }
91
}
92