Completed
Branch dev (d5d70c)
by Raffael
11:00
created

DesktopClient::setOptions()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 4.909
c 0
b 0
f 0
cc 9
eloc 20
nc 9
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * balloon
7
 *
8
 * @copyright   Copryright (c) 2012-2018 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Balloon\App\DesktopClient;
13
14
use Psr\Log\LoggerInterface;
15
16
class DesktopClient
17
{
18
    /**
19
     * Github request url.
20
     *
21
     * @var string
22
     */
23
    protected $github_request_url = 'https://api.github.com/repos/gyselroth/balloon-client-desktop/releases/latest';
24
25
    /**
26
     * Github request timeout.
27
     *
28
     * @var int
29
     */
30
    protected $github_request_timeout = 10;
31
32
    /**
33
     * Github asset mapping.
34
     *
35
     * @var array
36
     */
37
    protected $github_asset_mapping = [
38
        'deb' => '#.*\.deb$#',
39
        'rpm' => '#.*\.rpm$#',
40
        'exe' => '#.*\.exe$#',
41
        'zip' => '#.*\.zip$#',
42
        'pkg' => '#.*\.pkg$#',
43
    ];
44
45
    /**
46
     * Github request useragent.
47
     *
48
     * @var string
49
     */
50
    protected $github_request_useragent = 'balloon server';
51
52
    /**
53
     * Formats.
54
     *
55
     * @var array
56
     */
57
    protected $formats = [];
58
59
    /**
60
     * Logger.
61
     *
62
     * @var LoggerInterface
63
     */
64
    protected $logger;
65
66
    /**
67
     * Constructor.
68
     *
69
     * @param LoggerInterface $logger
70
     * @param iterable        $config
71
     */
72
    public function __construct(LoggerInterface $logger, ?Iterable $config = null)
73
    {
74
        $this->logger = $logger;
75
        $this->setOptions($config);
76
    }
77
78
    /**
79
     * Set options.
80
     *
81
     * @param iterable $config
82
     *
83
     * @return DesktopClient
84
     */
85
    public function setOptions(?Iterable $config = null): self
86
    {
87
        if (null === $config) {
88
            return $this;
89
        }
90
91
        foreach ($config as $option => $value) {
92
            switch ($option) {
93
                case 'github_request_url':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
94
                case 'github_request_timeout':
95
                case 'github_request_useragent':
96
                    $this->{$option} = (string) $value;
97
98
                break;
99
                case 'github_request_timeout':
100
                    $this->github_request_timeout = (int) $value;
101
102
                break;
103
                case 'formats':
104
                case 'github_asset_mapping':
105
                    $this->{$option} = $value;
106
107
                break;
108
                default:
109
                    throw new Exception('invalid option '.$option.' given');
110
            }
111
        }
112
113
        return $this;
114
    }
115
116
    /**
117
     * Get url.
118
     *
119
     * @param string $format
120
     *
121
     * @return string
122
     */
123
    public function getUrl(string $format): string
124
    {
125
        if (isset($this->formats[$format])) {
126
            return $this->formats[$format];
127
        }
128
129
        return $this->getGithubUrl($format);
130
    }
131
132
    /**
133
     * Get github url.
134
     *
135
     * @param string $format
136
     *
137
     * @return string
138
     */
139
    protected function getGithubUrl(string $format): string
140
    {
141
        if (!isset($this->github_asset_mapping[$format])) {
142
            throw new Exception('unknown format '.$format.' requested');
143
        }
144
145
        $ch = curl_init();
146
        curl_setopt($ch, CURLOPT_URL, $this->github_request_url);
147
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->github_request_timeout);
148
        curl_setopt($ch, CURLOPT_USERAGENT, $this->github_request_useragent);
149
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
150
        $data = curl_exec($ch);
151
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
152
153
        $this->logger->debug('github request to ['.$this->github_request_url.'] resulted in ['.$code.']', [
154
            'category' => get_class($this),
155
        ]);
156
157
        if (200 !== $code) {
158
            throw new Exception('failed query github releases api');
159
        }
160
161
        $data = json_decode($data, true);
162
163
        if (!is_array($data) || !isset($data['assets']) || 0 === count($data['assets'])) {
164
            throw new Exception('no github release assets found');
165
        }
166
167
        foreach ($data['assets'] as $asset) {
168
            $this->logger->debug('check release asset ['.$asset['name'].'] for ['.$this->github_asset_mapping[$format].']', [
169
                'category' => get_class($this),
170
            ]);
171
172
            if (preg_match($this->github_asset_mapping[$format], $asset['name'])) {
173
                $this->logger->info('github asset ['.$asset['browser_download_url'].'] found', [
174
                    'category' => get_class($this),
175
                ]);
176
177
                return $asset['browser_download_url'];
178
            }
179
        }
180
181
        throw new Exception('no github release asset matches request format');
182
    }
183
}
184