Test Setup Failed
Push — develop ( 04b246...d52f7e )
by Nikita
10:40
created

MarketplaceService   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 13
eloc 33
c 1
b 0
f 1
dl 0
loc 86
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A loadRemote() 0 13 2
A __construct() 0 3 1
A getModule() 0 3 1
A getList() 0 10 2
A findModule() 0 13 3
A downloadModule() 0 20 4
1
<?php
2
3
namespace Gameap\Services\Modules;
4
5
use Gameap\Exceptions\GameapException;
6
use Gameap\Exceptions\InvalidArgumentValueException;
7
use Gameap\Exceptions\Services\ResponseException;
8
use GuzzleHttp\Client;
9
use GuzzleHttp\Exception\GuzzleException;
10
use Illuminate\Support\Facades\Config;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
14
class MarketplaceService
15
{
16
    public const CONFIG_REPOSITORIES_NAME = 'app.modules_repositories';
17
18
    /** @var Client */
19
    private $client;
20
21
    public function __construct(Client $client)
22
    {
23
        $this->client = $client;
24
    }
25
26
    public function getList(): iterable
27
    {
28
        $repositories = Config::get(self::CONFIG_REPOSITORIES_NAME);
29
30
        $modules = [];
31
        foreach ($repositories as $repository) {
32
            $modules[] = $this->loadRemote($repository . '/index.json');
33
        }
34
35
        return array_merge(...$modules);
36
    }
37
38
    public function findModule(string $moduleID): ?array
39
    {
40
        $repositories = Config::get(self::CONFIG_REPOSITORIES_NAME);
41
42
        foreach ($repositories as $repository) {
43
            $modules = $this->loadRemote($repository . '/index.json');
44
45
            if (array_key_exists($moduleID, $modules)) {
46
                return $this->getModule($repository, $moduleID);
47
            }
48
        }
49
50
        return null;
51
    }
52
53
    public function getModule(string $repository, string $moduleID): array
54
    {
55
        return $this->loadRemote($repository . '/modules/' . $moduleID . '.json');
56
    }
57
58
    public function downloadModule(string $moduleID, string $version): string
59
    {
60
        $module = $this->findModule($moduleID);
61
62
        if (!array_key_exists($version, $module['versions'])) {
63
            throw new InvalidArgumentValueException('Invalid module version');
64
        }
65
66
        $mirrors = $module['versions'][$version]['mirrors'];
67
68
        $filePath = tempnam(sys_get_temp_dir(), $moduleID);
69
        foreach ($mirrors as $mirror) {
70
            $result = $this->client->request(Request::METHOD_GET, $mirror, ['sink' => $filePath]);
71
72
            if ($result->getStatusCode() === Response::HTTP_OK) {
73
                return $filePath;
74
            }
75
        }
76
77
        throw new GameapException('Unable to download module');
78
    }
79
80
    /**
81
     * @param string $uri
82
     * @return array
83
     * @throws ResponseException
84
     * @throws GuzzleException
85
     * @throws \JsonException
86
     */
87
    private function loadRemote(string $uri): array
88
    {
89
        $response = $this->client->request(
90
            Request::METHOD_GET,
91
            $uri,
92
            ['headers' => ['Accept: application/json']]
93
        );
94
95
        if ($response->getStatusCode() !== Response::HTTP_OK) {
96
            throw new ResponseException('Unexpected HTTP status code: ' . $response->getStatusCode());
97
        }
98
99
        return json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
100
    }
101
}
102