Completed
Push — master ( 60656c...dd3387 )
by Byron
04:15 queued 02:12
created

MicrosoftTranslator::getLanguagesForSpeak()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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