Completed
Push — master ( 5a6804...6e73eb )
by Byron
03:25
created

MicrosoftTranslator::createRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
ccs 12
cts 12
cp 1
rs 9.4285
cc 1
eloc 11
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\Translate;
10
use GuzzleHttp\Exception\RequestException;
11
use GuzzleHttp\Message\Response;
12
13
/**
14
 * Class MicrosoftTranslator
15
 * @package badams\MicrosoftTranslator
16
 */
17
class MicrosoftTranslator
18
{
19
    /**
20
     *
21
     */
22
    const AUTH_URL = 'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13';
23
24
    /**
25
     *
26
     */
27
    const BASE_URL = 'http://api.microsofttranslator.com/V2/Http.svc/';
28
29
    /**
30
     * @var \GuzzleHttp\ClientInterface
31
     */
32
    private $http;
33
34
    /**
35
     * @var string
36
     */
37
    private $scope = 'http://api.microsofttranslator.com';
38
39
    /**
40
     * @var string
41
     */
42
    private $grantType = 'client_credentials';
43
44
    /**
45
     * @var string
46
     */
47
    private $clientId;
48
49
    /**
50
     * @var string
51
     */
52
    private $clientSecret;
53
54
    /**
55
     * @var string
56
     */
57
    private $accessToken;
58
59
    /**
60
     * MicrosoftTranslator constructor.
61
     */
62 24
    public function __construct(\GuzzleHttp\ClientInterface $httpClient = null)
63
    {
64 24
        if (is_null($httpClient)) {
65 3
            $httpClient = new \GuzzleHttp\Client();
66 3
        }
67
68 24
        $this->http = $httpClient;
69 24
    }
70
71
    /**
72
     * @param $id
73
     * @param $secret
74
     */
75 9
    public function setClient($id, $secret)
76
    {
77 9
        $this->clientId = $id;
78 9
        $this->clientSecret = $secret;
79 9
    }
80
81
    /**
82
     * @return mixed
83
     * @throws AuthException
84
     */
85 18
    private function getAccessToken()
86
    {
87 18
        if (!$this->accessToken) {
88 18
            $params = array_merge([
89 18
                'grant_type' => $this->grantType,
90 18
                'scope' => $this->scope,
91 18
                'client_id' => $this->clientId,
92 18
                'client_secret' => $this->clientSecret
93 18
            ]);
94
95
            try {
96 18
                $response = $this->http->post(self::AUTH_URL, ['body' => $params]);
97 15
                $result = json_decode((string)$response->getBody());
98 18
            } catch (RequestException $e) {
99 3
                $result = json_decode((string)$e->getResponse()->getBody());
100 3
                throw new AuthException($result->error_description);
101
            }
102
103 15
            $this->accessToken = $result->access_token;
104 15
        }
105
106 15
        return $this->accessToken;
107
    }
108
109 15
    private function createRequest(ApiMethodInterface $method)
110
    {
111 15
        $reflection = new \ReflectionClass($method);
112
113 15
        return $this->http->createRequest(
114 15
            $method->getRequestMethod(),
115 15
            self::BASE_URL . $reflection->getShortName(),
116 15
            array_merge([
117 15
                'exceptions' => false,
118
                'headers' => [
119 15
                    'Authorization' => 'Bearer ' . $this->getAccessToken(),
120 15
                    'Content-Type' => 'text/xml',
121 15
                ],
122
123 15
            ], $method->getRequestOptions())
124 15
        );
125
    }
126
127
    /**
128
     * @param ApiMethodInterface $method
129
     * @return mixed
130
     * @throws ArgumentException
131
     * @throws QuotaExceededException
132
     * @throws TranslatorException
133
     */
134 15
    private function execute(ApiMethodInterface $method)
135
    {
136 15
        $response = $this->http->send($this->createRequest($method));
137
138 15
        if ($response->getStatusCode() != 200) {
139
            try {
140 12
                $this->processError($response);
0 ignored issues
show
Compatibility introduced by
$response of type object<GuzzleHttp\Message\ResponseInterface> is not a sub-type of object<GuzzleHttp\Message\Response>. It seems like you assume a concrete implementation of the interface GuzzleHttp\Message\ResponseInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
141 12
            } catch (TokenExpiredException $e) {
142 3
                $this->accessToken = null;
143 3
                return $this->execute($method);
144
            }
145
146 3
            throw new TranslatorException($response->getBody());
147
        }
148
149 6
        return $method->processResponse($response);
0 ignored issues
show
Compatibility introduced by
$response of type object<GuzzleHttp\Message\ResponseInterface> is not a sub-type of object<GuzzleHttp\Message\Response>. It seems like you assume a concrete implementation of the interface GuzzleHttp\Message\ResponseInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
150 15
    }
151
152
    /**
153
     * @param string $message
0 ignored issues
show
Bug introduced by
There is no parameter named $message. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
154
     * @throws ArgumentException
155
     * @throws QuotaExceededException
156
     * @throws TokenExpiredException
157
     * @throws TranslatorException
158
     */
159 12
    private function processError(Response $response)
160
    {
161 12
        $message = strip_tags($response->getBody());
162
163 12
        if (strpos($message, 'Argument Exception') === 0 && strpos($message, 'The incoming token has expired.')) {
164 3
            throw new TokenExpiredException($message);
165
        }
166
167 9
        if (strpos($message, 'TranslateApiException') === 0 && strpos($message, 'credentials has zero balance.')) {
168 3
            throw new QuotaExceededException($message);
169
        }
170
171 6
        if (strpos($message, 'Argument Exception') === 0) {
172 3
            throw new ArgumentException($message);
173
        }
174 3
    }
175
176
    /**
177
     * @param $text
178
     * @param $to
179
     * @param $from
180
     * @return null|string
181
     */
182 15
    public function translate($text, $to, $from = null)
183
    {
184 15
        return $this->execute(new Translate($text, $to, $from));
185
    }
186
}