Completed
Push — master ( 6d8a2a...3743ea )
by Byron
02:34
created

MicrosoftTranslator::detect()   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 1
crap 1
1
<?php
2
namespace badams\MicrosoftTranslator;
3
4
use badams\MicrosoftTranslator\Exceptions\ArgumentException;
5
use badams\MicrosoftTranslator\Exceptions\AuthException;
6
use badams\MicrosoftTranslator\Exceptions\QuotaExceededException;
7
use badams\MicrosoftTranslator\Exceptions\TokenExpiredException;
8
use badams\MicrosoftTranslator\Exceptions\TranslatorException;
9
use badams\MicrosoftTranslator\Methods\Detect;
10
use badams\MicrosoftTranslator\Methods\Speak;
11
use badams\MicrosoftTranslator\Methods\Translate;
12
use GuzzleHttp\Exception\RequestException;
13
use GuzzleHttp\Message\ResponseInterface;
14
15
/**
16
 * Class MicrosoftTranslator
17
 * @package badams\MicrosoftTranslator
18
 */
19
class MicrosoftTranslator
20
{
21
    /**
22
     *
23
     */
24
    const AUTH_URL = 'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13';
25
26
    /**
27
     *
28
     */
29
    const BASE_URL = 'http://api.microsofttranslator.com/V2/Http.svc/';
30
31
    /**
32
     * @var \GuzzleHttp\ClientInterface
33
     */
34
    private $http;
35
36
    /**
37
     * @var string
38
     */
39
    private $scope = 'http://api.microsofttranslator.com';
40
41
    /**
42
     * @var string
43
     */
44
    private $grantType = 'client_credentials';
45
46
    /**
47
     * @var string
48
     */
49
    private $clientId;
50
51
    /**
52
     * @var string
53
     */
54
    private $clientSecret;
55
56
    /**
57
     * @var string
58
     */
59
    private $accessToken;
60
61
    /**
62
     * MicrosoftTranslator constructor.
63
     */
64 30
    public function __construct(\GuzzleHttp\ClientInterface $httpClient = null)
65
    {
66 30
        if (is_null($httpClient)) {
67 3
            $httpClient = new \GuzzleHttp\Client();
68 3
        }
69
70 30
        $this->http = $httpClient;
71 30
    }
72
73
    /**
74
     * @param $id
75
     * @param $secret
76
     */
77 15
    public function setClient($id, $secret)
78
    {
79 15
        $this->clientId = $id;
80 15
        $this->clientSecret = $secret;
81 15
    }
82
83
    /**
84
     * @return mixed
85
     * @throws AuthException
86
     */
87 24
    private function getAccessToken()
88
    {
89 24
        if (!$this->accessToken) {
90 24
            $params = array_merge([
91 24
                'grant_type' => $this->grantType,
92 24
                'scope' => $this->scope,
93 24
                'client_id' => $this->clientId,
94 24
                'client_secret' => $this->clientSecret
95 24
            ]);
96
97
            try {
98 24
                $response = $this->http->post(self::AUTH_URL, ['body' => $params]);
99 21
                $result = json_decode((string)$response->getBody());
100 24
            } catch (RequestException $e) {
101 3
                $result = json_decode((string)$e->getResponse()->getBody());
102 3
                throw new AuthException($result->error_description);
103
            }
104
105 21
            $this->accessToken = $result->access_token;
106 21
        }
107
108 21
        return $this->accessToken;
109
    }
110
111 21
    private function createRequest(ApiMethodInterface $method)
112
    {
113 21
        $reflection = new \ReflectionClass($method);
114
115 21
        return $this->http->createRequest(
116 21
            $method->getRequestMethod(),
117 21
            self::BASE_URL . $reflection->getShortName(),
118 21
            array_merge([
119 21
                'exceptions' => false,
120
                'headers' => [
121 21
                    'Authorization' => 'Bearer ' . $this->getAccessToken(),
122 21
                    'Content-Type' => 'text/xml',
123 21
                ],
124
125 21
            ], $method->getRequestOptions())
126 21
        );
127
    }
128
129
    /**
130
     * @param ApiMethodInterface $method
131
     * @return mixed
132
     * @throws ArgumentException
133
     * @throws QuotaExceededException
134
     * @throws TranslatorException
135
     */
136 21
    private function execute(ApiMethodInterface $method)
137
    {
138 21
        $response = $this->http->send($this->createRequest($method));
139
140 21
        if ($response->getStatusCode() != 200) {
141
            try {
142 12
                $this->processError($response);
143 12
            } catch (TokenExpiredException $e) {
144 3
                $this->accessToken = null;
145 3
                return $this->execute($method);
146
            }
147
148 3
            throw new TranslatorException($response->getBody());
149
        }
150
151 12
        return $method->processResponse($response);
152
    }
153
154
    /**
155
     * @param ResponseInterface $response
156
     * @throws ArgumentException
157
     * @throws QuotaExceededException
158
     * @throws TokenExpiredException
159
     */
160 12
    private function processError(ResponseInterface $response)
161
    {
162 12
        $message = strip_tags($response->getBody());
163
164 12
        if (strpos($message, 'Argument Exception') === 0 && strpos($message, 'The incoming token has expired.')) {
165 3
            throw new TokenExpiredException($message);
166
        }
167
168 9
        if (strpos($message, 'TranslateApiException') === 0 && strpos($message, 'credentials has zero balance.')) {
169 3
            throw new QuotaExceededException($message);
170
        }
171
172 6
        if (strpos($message, 'Argument Exception') === 0) {
173 3
            throw new ArgumentException($message);
174
        }
175 3
    }
176
177
    /**
178
     * @param $text
179
     * @param $to
180
     * @param $from
181
     * @return null|string
182
     */
183 15
    public function translate($text, $to, $from = null)
184
    {
185 15
        return $this->execute(new Translate($text, $to, $from));
186
    }
187
188
    /**
189
     * @param $text
190
     * @return null|string
191
     * @throws TranslatorException
192
     */
193 3
    public function detect($text)
194
    {
195 3
        return $this->execute(new Detect($text));
196
    }
197
198
    /**
199
     * @param $text
200
     * @param $language
201
     * @param string $format
202
     * @param string $options
203
     * @return mixed
204
     * @throws TranslatorException
205
     */
206 3
    public function speak($text, $language, $format = Speak::FORMAT_MP3, $options = Speak::OPTION_MAX_QUALITY)
207
    {
208 3
        return $this->execute(new Speak($text, $language, $format, $options));
209
    }
210
}