Completed
Push — master ( 514de1...070b21 )
by dotzero
01:54
created

Request::prepareHeaders()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace AmoCRM\Request;
4
5
use AmoCRM\Exception;
6
use AmoCRM\NetworkException;
7
8
/**
9
 * Class Request
10
 *
11
 * Класс отправляющий запросы к API amoCRM используя cURL
12
 *
13
 * @package AmoCRM\Request
14
 * @author dotzero <[email protected]>
15
 * @link http://www.dotzero.ru/
16
 * @link https://github.com/dotzero/amocrm-php
17
 *
18
 * For the full copyright and license information, please view the LICENSE
19
 * file that was distributed with this source code.
20
 */
21
class Request
22
{
23
    /**
24
     * @var bool Использовать устаревшую схему авторизации
25
     */
26
    protected $v1 = false;
27
28
    /**
29
     * @var bool Флаг вывода отладочной информации
30
     */
31
    private $debug = false;
32
33
    /**
34
     * @var ParamsBag|null Экземпляр ParamsBag для хранения аргументов
35
     */
36
    private $parameters = null;
37
38
    /**
39
     * Request constructor
40
     *
41
     * @param ParamsBag $parameters Экземпляр ParamsBag для хранения аргументов
42
     * @throws NetworkException
43
     */
44 133
    public function __construct(ParamsBag $parameters)
45
    {
46 133
        if (!function_exists('curl_init')) {
47
            throw new NetworkException('The cURL PHP extension was not loaded');
48
        }
49
50 133
        $this->parameters = $parameters;
51 133
    }
52
53
    /**
54
     * Установка флага вывода отладочной информации
55
     *
56
     * @param bool $flag Значение флага
57
     * @return $this
58
     */
59 2
    public function debug($flag = false)
60
    {
61 2
        $this->debug = (bool)$flag;
62
63 2
        return $this;
64
    }
65
66
    /**
67
     * Выполнить HTTP GET запрос и вернуть тело ответа
68
     *
69
     * @param string $url Запрашиваемый URL
70
     * @param array $parameters Список GET параметров
71
     * @param null|string $modified Значение заголовка IF-MODIFIED-SINCE
72
     * @return mixed
73
     * @throws Exception
74
     * @throws NetworkException
75
     */
76 1
    protected function getRequest($url, $parameters = [], $modified = null)
77
    {
78 1
        if (!empty($parameters)) {
79 1
            $this->parameters->addGet($parameters);
80 1
        }
81
82 1
        return $this->request($url, $modified);
83
    }
84
85
    /**
86
     * Выполнить HTTP POST запрос и вернуть тело ответа
87
     *
88
     * @param string $url Запрашиваемый URL
89
     * @param array $parameters Список POST параметров
90
     * @return mixed
91
     * @throws Exception
92
     * @throws NetworkException
93
     */
94 1
    protected function postRequest($url, $parameters = [])
95
    {
96 1
        if (!empty($parameters)) {
97 1
            $this->parameters->addPost($parameters);
98 1
        }
99
100 1
        return $this->request($url);
101
    }
102
103
    /**
104
     * Подготавливает список заголовков HTTP
105
     *
106
     * @param null|string $modified Значение заголовка IF-MODIFIED-SINCE
107
     * @return array
108
     */
109 2
    protected function prepareHeaders($modified = null)
110
    {
111 2
        $headers = ['Content-Type: application/json'];
112
113 2
        if ($modified !== null) {
114 2
            $headers[] = 'IF-MODIFIED-SINCE: ' . (new \DateTime($modified))->format(\DateTime::RFC1123);
115 1
        }
116
117 1
        return $headers;
118
    }
119
120
    /**
121
     * Подготавливает URL для HTTP запроса
122
     *
123
     * @param string $url Запрашиваемый URL
124
     * @return string
125
     */
126 2
    protected function prepareEndpoint($url)
127
    {
128 2
        if ($this->v1 === false) {
129 1
            $query = http_build_query(array_merge($this->parameters->getGet(), [
130 1
                'USER_LOGIN' => $this->parameters->getAuth('login'),
131 1
                'USER_HASH' => $this->parameters->getAuth('apikey'),
132 1
            ]));
133 1
        } else {
134 1
            $query = http_build_query(array_merge($this->parameters->getGet(), [
135 1
                'login' => $this->parameters->getAuth('login'),
136 1
                'api_key' => $this->parameters->getAuth('apikey'),
137 1
            ]));
138
        }
139
140 2
        return sprintf('https://%s.amocrm.ru%s?%s', $this->parameters->getAuth('domain'), $url, $query);
141
    }
142
143
    /**
144
     * Выполнить HTTP запрос и вернуть тело ответа
145
     *
146
     * @param string $url Запрашиваемый URL
147
     * @param null|string $modified Значение заголовка IF-MODIFIED-SINCE
148
     * @return mixed
149
     * @throws Exception
150
     * @throws NetworkException
151
     */
152
    protected function request($url, $modified = null)
153
    {
154
        $headers = $this->prepareHeaders($modified);
155
        $endpoint = $this->prepareEndpoint($url);
156
157
        $this->printDebug('url', $endpoint);
158
        $this->printDebug('headers', $headers);
159
160
        $ch = curl_init();
161
162
        curl_setopt($ch, CURLOPT_URL, $endpoint);
163
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
164
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
165
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
166
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
167
168
        if ($this->parameters->hasPost()) {
169
            $fields = json_encode([
170
                'request' => $this->parameters->getPost(),
171
            ]);
172
            curl_setopt($ch, CURLOPT_POST, true);
173
            curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
174
            $this->printDebug('post params', $fields);
175
        }
176
177
        $result = curl_exec($ch);
178
        $info = curl_getinfo($ch);
179
        $error = curl_error($ch);
180
        $errno = curl_errno($ch);
181
182
        curl_close($ch);
183
184
        $this->printDebug('curl_exec', $result);
185
        $this->printDebug('curl_getinfo', $info);
186
        $this->printDebug('curl_error', $error);
187
        $this->printDebug('curl_errno', $errno);
188
189
        if ($result === false && !empty($error)) {
190
            throw new NetworkException($error, $errno);
191
        }
192
193
        return $this->parseResponse($result, $info);
194
    }
195
196
    /**
197
     * Парсит HTTP ответ, валидирует и возвращает тело
198
     *
199
     * @param string $response HTTP ответ
200
     * @param array $info Результат функции curl_getinfo
201
     * @return mixed
202
     * @throws Exception
203
     */
204 5
    protected function parseResponse($response, $info)
205
    {
206 5
        $result = json_decode($response, true);
207
208 5
        if (!isset($result['response'])) {
209 1
            return false;
210 4
        } elseif (floor($info['http_code'] / 100) >= 3) {
211 3
            $code = 0;
212 3
            if (isset($result['response']['error_code']) && $result['response']['error_code'] > 0) {
213 1
                $code = $result['response']['error_code'];
214 1
            }
215 3
            if ($this->v1 === false) {
216 2
                throw new Exception($result['response']['error'], $code);
217
            } else {
218 1
                throw new Exception(json_encode($result['response']));
219
            }
220
        }
221
222 1
        return $result['response'];
223
    }
224
225
    /**
226
     * Вывода отладочной информации
227
     *
228
     * @param string $key Заголовок отладочной информации
229
     * @param mixed $value Значение отладочной информации
230
     * @param bool $return Возврат строки вместо вывода
231
     * @return mixed
232
     */
233 2
    protected function printDebug($key = '', $value = null, $return = false)
234
    {
235 2
        if ($this->debug !== true) {
236 1
            return false;
237
        }
238
239 1
        if (!is_string($value)) {
240 1
            $value = print_r($value, true);
241 1
        }
242
243 1
        $line = sprintf('[DEBUG] %s: %s', $key, $value);
244
245 1
        if ($return === false) {
246
            return print_r($line . PHP_EOL);
247
        }
248
249 1
        return $line;
250
    }
251
}
252