Completed
Push — master ( 3da775...1e6bd3 )
by Robbie
9s
created

SupportedAddonsLoader::doRequest()   C

Complexity

Conditions 12
Paths 8

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 22
nc 8
nop 0
dl 0
loc 43
rs 5.1612
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BringYourOwnIdeas\Maintenance\Util;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use GuzzleHttp\Psr7\Request;
8
use Psr\SimpleCache\CacheInterface;
9
use RuntimeException;
10
use SilverStripe\Core\Extensible;
11
use SilverStripe\Core\Convert;
12
use BringYourOwnIdeas\Maintenance\Model\Package;
13
use SilverStripe\Core\Injector\Injector;
14
15
/**
16
 * Handles fetching supported addon details from addons.silverstripe.org
17
 */
18
class SupportedAddonsLoader
19
{
20
    use Extensible;
21
22
    private static $dependencies = [
0 ignored issues
show
introduced by
The private property $dependencies is not used, and could be removed.
Loading history...
23
        'GuzzleClient' => '%$GuzzleHttp\Client',
24
    ];
25
26
    /**
27
     * @var Client
28
     */
29
    protected $guzzleClient;
30
31
    /**
32
     * @var CacheInterface
33
     */
34
    protected $cache;
35
36
    /**
37
     * @return Client
38
     */
39
    public function getGuzzleClient()
40
    {
41
        return $this->guzzleClient;
42
    }
43
44
    /**
45
     * @param Client $guzzleClient
46
     * @return $this
47
     */
48
    public function setGuzzleClient(Client $guzzleClient)
49
    {
50
        $this->guzzleClient = $guzzleClient;
51
        return $this;
52
    }
53
54
    /**
55
     * @return CacheInterface
56
     */
57
    public function getCache()
58
    {
59
        if (!$this->cache) {
60
            $this->cache = Injector::inst()->get(CacheInterface::class . '.supportedAddons');
61
        }
62
63
        return $this->cache;
64
    }
65
66
    /**
67
     * @param CacheInterface $cache
68
     */
69
    public function setCache($cache)
70
    {
71
        $this->cache = $cache;
72
    }
73
74
    /**
75
     * Return the list of supported addons as provided by addons.silverstripe.org
76
     *
77
     * @return array
78
     */
79
    public function getAddonNames()
80
    {
81
        if (($addons = $this->getCache()->get('addons')) !== false) {
82
            return $addons;
83
        }
84
85
        return $this->doRequest();
86
    }
87
88
    /**
89
     * Perform an HTTP request for supported addon names
90
     *
91
     * @return array
92
     * @throws RuntimeException When the API responds with something that's not a list of addons
93
     */
94
    protected function doRequest()
95
    {
96
        $request = new Request('GET', 'addons.silverstripe.org/api/supported-addons');
97
98
        $failureMessage = 'Could not obtain information about supported addons. ';
99
100
        try {
101
            $response = $this->getGuzzleClient()->send($request, ['http_errors' => false]);
102
        } catch (GuzzleException $exception) {
103
            throw new RuntimeException($failureMessage);
104
        }
105
106
        if ($response->getStatusCode() !== 200) {
107
            throw new RuntimeException($failureMessage . 'Error code ' . $response->getStatusCode());
108
        }
109
110
        if (!in_array('application/json', $response->getHeader('Content-Type'))) {
111
            throw new RuntimeException($failureMessage . 'Response is not JSON');
112
        }
113
114
        $responseBody = Convert::json2array($response->getBody()->getContents());
115
116
        if (empty($responseBody)) {
117
            throw new RuntimeException($failureMessage . 'Response could not be parsed');
118
        }
119
120
        if (!isset($responseBody['success']) || !$responseBody['success'] || !isset($responseBody['addons'])) {
121
            throw new RuntimeException($failureMessage . 'Response returned unsuccessfully');
122
        }
123
124
        // Handle caching if requested
125
        if ($cacheControl = $response->getHeader('Cache-Control')) {
126
            // Combine separate header rows
127
            $cacheControl = implode(', ', $cacheControl);
128
129
            if (strpos($cacheControl, 'no-store') === false &&
130
                preg_match('/(?:max-age=)(\d+)/i', $cacheControl, $matches)) {
131
                $duration = (int) $matches[1];
132
                $this->getCache()->set('addons', $responseBody['addons'], $duration);
133
            }
134
        }
135
136
        return $responseBody['addons'] ?: [];
137
    }
138
139
    /**
140
     * Create a request with some standard headers
141
     *
142
     * @param string $uri
143
     * @param string $method
144
     * @return Request
145
     */
146
    protected function createRequest($uri, $method = 'GET')
147
    {
148
        $headers = [];
149
        $version = $this->resolveVersion();
150
        if (!empty($version)) {
151
            $headers['Silverstripe-Framework-Version'] = $version;
152
        }
153
154
        return new Request($method, $uri, $headers);
155
    }
156
157
    /**
158
     * Resolve the framework version of SilverStripe.
159
     *
160
     * @return string|null
161
     */
162
    protected function resolveVersion()
163
    {
164
        $frameworkPackage = Package::get()->find('Name', 'silverstripe/framework');
165
        if (!$frameworkPackage) {
0 ignored issues
show
introduced by
$frameworkPackage is of type SilverStripe\ORM\DataObject, thus it always evaluated to true.
Loading history...
166
            return null;
167
        }
168
        return $frameworkPackage->Version;
169
    }
170
}
171