Completed
Push — master ( c30967...3bd52a )
by Andrii
03:06
created

AbstractConnection::checkResponse()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.2098

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 5
cts 7
cp 0.7143
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 4
nop 1
crap 3.2098
1
<?php
2
/**
3
 * ActiveRecord for API
4
 *
5
 * @link      https://github.com/hiqdev/yii2-hiart
6
 * @package   yii2-hiart
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\hiart;
12
13
use Closure;
14
use hiqdev\hiart\stream\Request;
15
use Yii;
16
use yii\base\Component;
17
use yii\base\InvalidParamException;
18
use yii\helpers\Json;
19
20
/**
21
 * Abstract connection class.
22
 */
23
abstract class AbstractConnection extends Component implements ConnectionInterface
24
{
25
    const EVENT_AFTER_OPEN = 'afterOpen';
26
27
    /**
28
     * @var string to be specified in concrete implementation
29
     */
30
    public $queryBuilderClass;
31
32
    public $requestClass = Request::class;
33
34
    public $commandClass = Command::class;
35
36
    public $queryClass = Query::class;
37
38
    public $activeQueryClass = ActiveQuery::class;
39
40
    public static $dbname = 'hiart';
41
42
    public $name = 'hiart';
43
44
    public $userAgent = 'HiArt/0.x';
45
46
    public $baseUri;
47
48
    /**
49
     * @var array transport config will be used in Request for handler or proxy request
50
     */
51
    public $config = [];
52
53
    /**
54
     * @var object request handler common for all requests of this connection
55
     */
56
    protected $_handler;
57
58
    /**
59
     * @var AbstractQueryBuilder the query builder for this connection
60
     */
61
    protected $_builder;
62
63
    /**
64
     * @var array authorization config
65
     */
66
    protected $_auth = [];
67
68
    /**
69
     * @var bool is auth disabled
70
     */
71
    protected $_disabledAuth = false;
72
73
    /**
74
     * @var Closure callback to test if API response has error
75
     * The function signature: `function ($response)`
76
     * Must return `null`, if the response does not contain an error
77
     */
78
    protected $_errorChecker;
79
80
    /**
81
     * @param null $name
82
     * @return ConnectionInterface|AbstractConnection
83
     */
84 3
    public static function getDb($name = null, $class = ConnectionInterface::class)
85
    {
86 3
        if ($name) {
87
            return Yii::$app->get($name);
88
        }
89 3
        if (Yii::$container->hasSingleton($class)) {
90 2
            return Yii::$container->get($class);
91
        }
92
93 1
        return Yii::$app->get(static::$dbname);
94
    }
95
96 1
    public function setAuth($auth)
97
    {
98 1
        $this->_auth = $auth;
99 1
    }
100
101
    /**
102
     * Returns auth settings.
103
     * @return array
104
     */
105 2
    public function getAuth()
106
    {
107 2
        if ($this->_disabledAuth) {
108
            return [];
109
        }
110 2
        if ($this->_auth instanceof Closure) {
111
            $this->_auth = call_user_func($this->_auth, $this);
0 ignored issues
show
Documentation Bug introduced by
It seems like call_user_func($this->_auth, $this) of type * is incompatible with the declared type array of property $_auth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
112
        }
113
114 2
        return $this->_auth;
115
    }
116
117
    public function disableAuth()
118
    {
119
        $this->_disabledAuth = true;
120
    }
121
122
    public function enableAuth()
123
    {
124
        $this->_disabledAuth = false;
125
    }
126
127
    /**
128
     * Closes the connection when this component is being serialized.
129
     * @return array
130
     */
131
    public function __sleep()
132
    {
133
        return array_keys(get_object_vars($this));
134
    }
135
136
    /**
137
     * Returns the name of the DB driver for the current [[dsn]].
138
     * @return string name of the DB driver
139
     */
140
    public function getDriverName()
141
    {
142
        return 'hiart';
143
    }
144
145
    /**
146
     * Creates a command for execution.
147
     * @param array $config the configuration for the Command class
148
     * @return Command the DB command
149
     */
150 2
    public function createCommand(array $config = [])
151
    {
152 2
        $config['db'] = $this;
153
154 2
        return new $this->commandClass($config);
155
    }
156
157
    /**
158
     * @return AbstractQueryBuilder the query builder for this connection
159
     */
160 2
    public function getQueryBuilder()
161
    {
162 2
        if ($this->_builder === null) {
163 1
            $this->_builder = new $this->queryBuilderClass($this);
164
        }
165
166 2
        return $this->_builder;
167
    }
168
169
    /**
170
     * Handler is created and set by request.
171
     * @see setHandler
172
     * @return object
173
     */
174
    public function getHandler()
175
    {
176
        return $this->_handler;
177
    }
178
179
    /**
180
     * Requests use this function to keep request handler.
181
     * @param object $handler
182
     */
183
    public function setHandler($handler)
184
    {
185
        $this->_handler = $handler;
186
    }
187
188
    /**
189
     * @return boolean
190
     */
191
    public function isDisabledAuth()
192
    {
193
        return $this->_disabledAuth;
194
    }
195
196
    /**
197
     * @param boolean $disabledAuth
198
     */
199
    public function setDisabledAuth($disabledAuth)
200
    {
201
        $this->_disabledAuth = $disabledAuth;
202
    }
203
204
    /**
205
     * Disables auth and calls $closure.
206
     *
207
     * @param Closure $closure
208
     * @return mixed
209
     */
210
    public function callWithDisabledAuth(Closure $closure)
211
    {
212
        if ($this->isDisabledAuth()) {
213
            return call_user_func($closure);
214
        }
215
216
        try {
217
            $this->disableAuth();
218
            return call_user_func($closure);
219
        } finally {
220
            $this->enableAuth();
221
        }
222
    }
223
224
    /**
225
     * Try to decode error information if it is valid json, return it if not.
226
     * @param $body
227
     * @return mixed
228
     */
229
    protected function decodeErrorBody($body)
230
    {
231
        try {
232
            $decoded = Json::decode($body);
233
            if (isset($decoded['error'])) {
234
                $decoded['error'] = preg_replace('/\b\w+?Exception\[/',
235
                    "<span style=\"color: red;\">\\0</span>\n               ", $decoded['error']);
236
            }
237
238
            return $decoded;
239
        } catch (InvalidParamException $e) {
240
            return $body;
241
        }
242
    }
243
244
    /**
245
     * Setter for errorChecker.
246
     * @param Closure $checker
247
     */
248
    public function setErrorChecker($checker)
249
    {
250
        $this->_errorChecker = $checker;
251
    }
252
253
    /**
254
     * Checks response method and raises exception if error found.
255
     * @param ResponseInterface $response response data from API
256
     * @throws ResponseErrorException when response is invalid
257
     */
258 2
    public function checkResponse(ResponseInterface $response)
259
    {
260 2
        if (isset($this->_errorChecker)) {
261
            $error = call_user_func($this->_errorChecker, $response);
262
        } else {
263 2
            $error = $this->getResponseError($response);
264
        }
265
266 2
        if ($error) {
267
            throw new ResponseErrorException($error, $response);
268
        }
269 2
    }
270
271
    /**
272
     * Method checks whether the response is an error.
273
     *
274
     * @param ResponseInterface $response
275
     * @return false|string the error text or boolean `false`, when the response is not an error
276
     */
277
    abstract public function getResponseError(ResponseInterface $response);
278
279
    protected $baseUriChecked;
280
281
    /**
282
     * Return API base uri.
283
     * Adds trailing slash if uri is domain only.
284
     * @return string
285
     */
286 4
    public function getBaseUri()
287
    {
288 4
        if (empty($this->baseUriChecked)) {
289 3
            if (preg_match('#^https?://[^/]+$#', $this->baseUri)) {
290 1
                $this->baseUri .= '/';
291
            }
292 3
            $this->baseUriChecked = true;
293
        }
294
295 4
        return $this->baseUri;
296
    }
297
298 2
    public function getUserAgent()
299
    {
300 2
        return $this->userAgent;
301
    }
302
}
303