Client::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
1
<?php namespace StarCraftApiClient;
2
3
use StarCraftApiClient\Requests\DataRequest;
4
use StarCraftApiClient\Requests\LadderRequest;
5
use StarCraftApiClient\Requests\ProfileRequest;
6
7
/**
8
 * Sloppy way to perform several requests to the battle.net StarCraft Api
9
 * in one go. Once you added one or more requests, start pulling from
10
 * battle.net via Client->run(). Individual results can be accessed via
11
 * a dot-style path e.g. [basetype.id.type].
12
 *
13
 * After requesting all data for one player like:
14
 * Client->addAllProfileRequests(123321, 'CoolGuy', 'eu') ...
15
 * ... Client->get('profile.123321.ladders') will give you just the ladders,
16
 * while Client->get('profile.123321') will return an array containing
17
 * profil, matches and ladders for this player.
18
 * Hence Client->get('profile') will give you all the requested
19
 * profile-type results as an array.
20
 *
21
 * The actual request object for individual requests is accessible via
22
 * Client->getRequest(...). To access e.g. CURL info of a request
23
 * Client->getRequest('profile.123321.ladders')->info()
24
 * will give you just that.
25
 *
26
 * FYI: You should keep the number of requests to perform within
27
 * a reasonable level. See https://dev.battle.net/ for details.
28
 *
29
 * @author neun
30
 * @since  2015-10-25
31
 */
32
class Client
33
{
34
    /**
35
     * @var string
36
     */
37
    private $apiToken;
38
39
    /**
40
     * @var string
41
     */
42
    private $language;
43
44
    /**
45
     * @var float
46
     */
47
    private $runtime;
48
49
    /**
50
     * @var array
51
     */
52
    private $curlOptions = [
53
        CURLOPT_RETURNTRANSFER => 1,
54
        CURLOPT_SSL_VERIFYHOST => 0,
55
        CURLOPT_SSL_VERIFYPEER => 0,
56
        CURLOPT_CONNECTTIMEOUT => 9,
57
        CURLOPT_FOLLOWLOCATION => 1
58
    ];
59
60
    /**
61
     * @var Requests\Request[]
62
     */
63
    private $requests;
64
65
    /**
66
     * @var array
67
     */
68
    private $results;
69
70
    public function __construct($apiToken, $language = 'en_GB')
71
    {
72
        $this->apiToken = $apiToken;
73
        $this->language = $language;
74
    }
75
76
    /**
77
     * @param int $id
78
     * @param string $name
79
     * @param string $region
80
     */
81
    public function addAllProfileRequests($id, $name, $region)
82
    {
83
        $this->addProfileRequest($id, $name, $region);
84
        $this->addProfileLaddersRequest($id, $name, $region);
85
        $this->addProfileMatchesRequest($id, $name, $region);
86
    }
87
88
    /**
89
     * @param int $id
90
     * @param string $name
91
     * @param string $region
92
     */
93
    public function addProfileRequest($id, $name, $region)
94
    {
95
        $this->requests['profile.'.$id.'.profile'] =
96
            new ProfileRequest($this, 'profile', $id, $name, $region);
97
    }
98
99
    /**
100
     * @param int $id
101
     * @param string $name
102
     * @param string $region
103
     */
104
    public function addProfileLaddersRequest($id, $name, $region)
105
    {
106
        $this->requests['profile.'.$id.'.ladders'] =
107
            new ProfileRequest($this, 'ladders', $id, $name, $region);
108
    }
109
110
    /**
111
     * @param int $id
112
     * @param string $name
113
     * @param string $region
114
     */
115
    public function addProfileMatchesRequest($id, $name, $region)
116
    {
117
        $this->requests['profile.'.$id.'.matches'] =
118
            new ProfileRequest($this, 'matches', $id, $name, $region);
119
    }
120
121
    /**
122
     * @param int $id
123
     * @param string $region
124
     */
125
    public function addLadderRequest($id, $region)
126
    {
127
        $this->requests['ladder.'.$id] =
128
            new LadderRequest($this, $id, $region);
129
    }
130
131
    /**
132
     * @param string $region
133
     */
134
    public function addAchievementsRequest($region)
135
    {
136
        $this->requests['data.achievements'] =
137
            new DataRequest($this, 'achievements', $region);
138
    }
139
140
    /**
141
     * @param string $region
142
     */
143
    public function addRewardsRequest($region)
144
    {
145
        $this->requests['data.rewards'] =
146
            new DataRequest($this, 'rewards', $region);
147
    }
148
149
    /**
150
     * @return void
151
     */
152
    public function run()
153
    {
154
        $start = -microtime(1);
155
        $mh = curl_multi_init();
156
157
        $chs = $this->hydrateCurlHandles($mh);
158
        $this->performCurlRequests($mh);
159
        $this->fetchCurlRequestData($chs, $mh);
160
161
        curl_multi_close($mh);
162
        $this->runtime = $start+microtime(1);
163
    }
164
165
    /**
166
     * @param resource $mh
167
     * @return resource[] $chs
168
     */
169
    private function hydrateCurlHandles($mh)
170
    {
171
        $chs = [];
172
        /** @var Requests\Request $request */
173
        foreach ($this->requests as $id => $request) {
174
            $chs[$id] = curl_init($request->url());
175
            curl_setopt_array($chs[$id], $this->curlOptions);
176
            curl_multi_add_handle($mh, $chs[$id]);
177
        }
178
179
        return $chs;
180
    }
181
182
    /**
183
     * @param resource $mh
184
     */
185
    private function performCurlRequests($mh)
186
    {
187
        do {
188
            usleep(11111);
189
            curl_multi_exec($mh, $active);
190
        } while ($active > 0);
191
    }
192
193
    /**
194
     * @param resource[] $chs
195
     * @param resource $mh
196
     */
197
    private function fetchCurlRequestData($chs, $mh)
198
    {
199
        foreach ($chs as $id => $ch) {
200
            $path = explode('.', $id);
201
            $response = curl_multi_getcontent($ch);
202
            $this->requests[$id]->setInfo(curl_getinfo($ch))->setResponse($response);
203
204
            $result = json_decode($response);
205
            if (isset($path[2])) {
206
                $this->results[$path[0]][$path[1]][$path[2]] = $result;
207
            } elseif (isset($path[1])) {
208
                $this->results[$path[0]][$path[1]] = $result;
209
            } else {
210
                $this->results[$path[0]] = $result;
211
            }
212
213
            curl_multi_remove_handle($mh, $ch);
214
        }
215
    }
216
217
    /**
218
     * Return indiviual results, collections of results
219
     * or all results entirely.
220
     *
221
     * @param string $path
222
     * @return Object
223
     */
224
    public function get($path = null)
225
    {
226
        if (null === $path) {
227
            $result = $this->results;
228
        } else {
229
            foreach (explode('.', $path) as $chunk) {
230
                $result = isset($result) ? $result[$chunk] : $this->results[$chunk];
231
            }
232
        }
233
234
        return isset($result) ? $result : null;
235
    }
236
237
    /**
238
     * Return the individual result objects, containing the
239
     * plain response, connection info etc.
240
     *
241
     * @param $path
242
     * @return Requests\Request[]|
243
     */
244
    public function getRequests($path = null)
245
    {
246
        $requests = [];
247
        if (null === $path) {
248
            $requests = $this->requests;
249
        } else {
250
            $requests[] = isset($this->requests[$path]) ? $this->requests[$path] : null;
251
        }
252
253
        return $requests;
254
    }
255
256
    /**
257
     * @return string $apiToken
258
     */
259
    public function apiToken()
260
    {
261
        return $this->apiToken;
262
    }
263
264
    /**
265
     * @return string $language
266
     */
267
    public function language()
268
    {
269
        return $this->language;
270
    }
271
272
    /**
273
     * @return float $runtime
274
     */
275
    public function runtime()
276
    {
277
        return $this->runtime;
278
    }
279
}
280