Completed
Push — master ( 58efe7...cda9ba )
by Byron
02:12
created

MicrosoftTranslator::getTranslationsArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 5
crap 1
1
<?php
2
/**
3
 * This file is part of the badams\MicrosoftTranslator library
4
 *
5
 * @license http://opensource.org/licenses/MIT
6
 * @link https://github.com/badams/microsoft-translator
7
 * @package badams/microsoft-translator
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace badams\MicrosoftTranslator;
14
15
use badams\MicrosoftTranslator\Exceptions\ArgumentException;
16
use badams\MicrosoftTranslator\Exceptions\AuthException;
17
use badams\MicrosoftTranslator\Exceptions\QuotaExceededException;
18
use badams\MicrosoftTranslator\Exceptions\TokenExpiredException;
19
use badams\MicrosoftTranslator\Exceptions\TranslatorException;
20
use badams\MicrosoftTranslator\Methods\Detect;
21
use badams\MicrosoftTranslator\Methods\GetLanguageNames;
22
use badams\MicrosoftTranslator\Methods\GetLanguagesForSpeak;
23
use badams\MicrosoftTranslator\Methods\GetLanguagesForTranslate;
24
use badams\MicrosoftTranslator\Methods\GetTranslations;
25
use badams\MicrosoftTranslator\Methods\GetTranslationsArray;
26
use badams\MicrosoftTranslator\Methods\Speak;
27
use badams\MicrosoftTranslator\Methods\Translate;
28
use badams\MicrosoftTranslator\Responses\GetTranslationsResponse;
29
use GuzzleHttp\Exception\RequestException;
30
31
/**
32
 * Class MicrosoftTranslator
33
 * @package badams\MicrosoftTranslator
34
 */
35
class MicrosoftTranslator
36
{
37
    /**
38
     *
39
     */
40
    const AUTH_URL = 'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13';
41
42
    /**
43
     *
44
     */
45
    const BASE_URL = 'http://api.microsofttranslator.com/V2/Http.svc/';
46
47
    /**
48
     * @var \GuzzleHttp\ClientInterface
49
     */
50
    private $http;
51
52
    /**
53
     * @var string
54
     */
55
    private $scope = 'http://api.microsofttranslator.com';
56
57
    /**
58
     * @var string
59
     */
60
    private $grantType = 'client_credentials';
61
62
    /**
63
     * @var string
64
     */
65
    private $clientId;
66
67
    /**
68
     * @var string
69
     */
70
    private $clientSecret;
71
72
    /**
73
     * @var string
74
     */
75
    private $accessToken;
76
77
    /**
78
     * MicrosoftTranslator constructor.
79
     */
80 51
    public function __construct(\GuzzleHttp\ClientInterface $httpClient = null)
81
    {
82 51
        if (is_null($httpClient)) {
83 3
            $httpClient = new \GuzzleHttp\Client();
84 3
        }
85
86 51
        $this->http = $httpClient;
87 51
    }
88
89
    /**
90
     * @param $id
91
     * @param $secret
92
     */
93 36
    public function setClient($id, $secret)
94
    {
95 36
        $this->clientId = $id;
96 36
        $this->clientSecret = $secret;
97 36
    }
98
99
    /**
100
     * @return mixed
101
     * @throws AuthException
102
     */
103 45
    private function getAccessToken()
104 15
    {
105 45
        if (!$this->accessToken) {
106 45
            $params = array_merge([
107 45
                'grant_type' => $this->grantType,
108 45
                'scope' => $this->scope,
109 45
                'client_id' => $this->clientId,
110 45
                'client_secret' => $this->clientSecret
111 45
            ]);
112
113
            try {
114 45
                $response = $this->http->post(self::AUTH_URL, ['body' => $params]);
115 42
                $result = json_decode((string)$response->getBody());
116 45
            } catch (RequestException $e) {
117 3
                $result = json_decode((string)$e->getResponse()->getBody());
118 3
                throw new AuthException($result->error_description);
119 3
            }
120
121 42
            $this->accessToken = $result->access_token;
122 42
        }
123
124 42
        return $this->accessToken;
125
    }
126
127
    /**
128
     * @param ApiMethodInterface $method
129
     * @return \GuzzleHttp\Message\Request|\GuzzleHttp\Message\RequestInterface
130
     * @throws AuthException
131
     */
132 42
    private function createRequest(ApiMethodInterface $method)
133
    {
134 42
        $reflection = new \ReflectionClass($method);
135
136 42
        return $this->http->createRequest(
137 42
            $method->getRequestMethod(),
138 42
            self::BASE_URL . $reflection->getShortName(),
139 42
            array_merge([
140 42
                'exceptions' => false,
141
                'headers' => [
142 42
                    'Authorization' => 'Bearer ' . $this->getAccessToken(),
143 42
                    'Content-Type' => 'text/xml',
144 42
                ],
145
146 42
            ], $method->getRequestOptions())
147 42
        );
148
    }
149
150
    /**
151
     * @param ApiMethodInterface $method
152
     * @return mixed
153
     * @throws ArgumentException
154
     * @throws QuotaExceededException
155
     * @throws TranslatorException
156
     */
157 42
    private function execute(ApiMethodInterface $method)
158
    {
159 42
        $response = $this->http->send($this->createRequest($method));
160
161 42
        if ($response->getStatusCode() != 200) {
162
            try {
163 12
                $message = strip_tags($response->getBody());
164 12
                $this->assertNoArgumentException($message);
165 6
                $this->assertNoTranslateExceptionAndZeroBalance($message);
166 12
            } catch (TokenExpiredException $e) {
167 3
                $this->accessToken = null;
168 3
                return $this->execute($method);
169
            }
170
171 3
            throw new TranslatorException($response->getBody());
172
        }
173
174 33
        return $method->processResponse($response);
175
    }
176
177
    /**
178
     * @param string $message
179
     * @throws QuotaExceededException
180
     */
181 6
    private function assertNoTranslateExceptionAndZeroBalance($message)
182
    {
183 6
        if (strpos($message, 'TranslateApiException') === 0
184 6
            && strpos($message, 'credentials has zero balance.')
185 6
        ) {
186 3
            throw new QuotaExceededException($message);
187
        }
188 3
    }
189
190
    /**
191
     * @param string $message
192
     * @throws ArgumentException
193
     * @throws TokenExpiredException
194
     */
195 12
    private function assertNoArgumentException($message)
196
    {
197 12
        if (strpos($message, 'Argument Exception') === 0) {
198 6
            if (strpos($message, 'The incoming token has expired.')) {
199 3
                throw new TokenExpiredException($message);
200
            }
201
202 3
            throw new ArgumentException($message);
203
        }
204 6
    }
205
206
    /**
207
     * @param $text
208
     * @param $to
209
     * @param $from
210
     * @return null|string
211
     */
212 15
    public function translate($text, $to, $from = null)
213
    {
214 15
        return $this->execute(new Translate($text, $to, $from));
215
    }
216
217
    /**
218
     * @param $text
219
     * @return null|Language
220
     * @throws TranslatorException
221
     */
222 3
    public function detect($text)
223
    {
224 3
        return $this->execute(new Detect($text));
225
    }
226
227
    /**
228
     * @param $text
229
     * @param $language
230
     * @param string $format
231
     * @param string $options
232
     * @return mixed
233
     * @throws TranslatorException
234
     */
235 3
    public function speak($text, $language, $format = Speak::FORMAT_MP3, $options = Speak::OPTION_MAX_QUALITY)
236
    {
237 3
        return $this->execute(new Speak($text, $language, $format, $options));
238
    }
239
240
    /**
241
     * @return Language[]
242
     * @throws TranslatorException
243
     */
244 3
    public function getLanguagesForSpeak()
245
    {
246 3
        return $this->execute(new GetLanguagesForSpeak());
247
    }
248
249
    /**
250
     * @param $languageCodes
251
     * @param string $locale
252
     * @return mixed
253
     * @throws TranslatorException
254
     */
255 6
    public function getLanguageNames($languageCodes, $locale = Language::ENGLISH)
256
    {
257 6
        return $this->execute(new GetLanguageNames($locale, $languageCodes));
258
    }
259
260
    /**
261
     * @return Language[]
262
     * @throws TranslatorException
263
     */
264 3
    public function getLanguagesForTranslate()
265
    {
266 3
        return $this->execute(new GetLanguagesForTranslate());
267
    }
268
269
    /**
270
     * @param $text
271
     * @param $to
272
     * @param $from
273
     * @param null $maxTranslations
274
     * @param TranslateOptions|null $options
275
     * @return GetTranslationsResponse
276
     * @throws TranslatorException
277
     */
278 6
    public function getTranslations($text, $to, $from, $maxTranslations = 5, TranslateOptions $options = null)
279
    {
280 6
        return $this->execute(new GetTranslations($text, $to, $from, $maxTranslations, $options));
281
    }
282
283
    /**
284
     * @param $texts
285
     * @param $to
286
     * @param $from
287
     * @param int $maxTranslations
288
     * @param TranslateOptions|null $options
289
     * @return GetTranslationsResponse[]
290
     * @throws TranslatorException
291
     */
292 3
    public function getTranslationsArray($texts, $to, $from, $maxTranslations = 5, TranslateOptions $options = null)
293
    {
294 3
        return $this->execute(new GetTranslationsArray($texts, $to, $from, $maxTranslations, $options));
295
    }
296
}