Completed
Push — master ( 1e173f...636f13 )
by Dmitry
02:05
created

Request   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 244
Duplicated Lines 6.56 %

Importance

Changes 0
Metric Value
dl 16
loc 244
rs 10
c 0
b 0
f 0
wmc 26

14 Methods

Rating   Name   Duplication   Size   Complexity  
A get_params() 0 3 1
A data() 0 8 2
A as_array() 0 3 2
A as_int() 0 3 2
A as_string() 0 3 4
A get_param_iat() 0 3 1
A __construct() 0 15 2
A get_json() 0 14 2
A token_encode() 15 15 2
A handle_request_exception() 0 8 2
A create_payload() 0 11 2
A alter_payload_for_jwt() 0 7 1
A send() 0 19 2
A own_private_key() 0 3 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace UAPAY;
4
5
use UAPAY\Log as Log;
6
use UAPAY\Exception;
7
use Firebase\JWT\JWT;
8
9
abstract class Request
10
{
11
    /**
12
     *      @var object
13
     */
14
    protected $client;
15
16
    /**
17
     *      @var array
18
     */
19
    protected $jwt=array(
20
        'using'         => false,
21
        'UAPAY_pubkey'  => '',
22
        'our_privkey'   => '',
23
    );
24
25
    /**
26
     *      @var array
27
     */
28
    protected $data;
29
30
    /**
31
     *      Constructor
32
     *
33
     *      @param array $options array of options
34
     *      @throws Exception\Data
35
     */
36
    public function __construct($options)
37
    {
38
        // api_url
39
        if ( ! isset($options['api_uri']))
40
        {
41
            throw new Exception\Data('parameter api_uri is not specified');
42
        }
43
44
        $jo = new JWTOptions($options);
45
        $this->jwt = $jo->get();
46
47
        // http client
48
        $this->client = new \GuzzleHttp\Client([
49
            'base_uri'      => $options['api_uri'],
50
            'timeout'       => 2.0,
51
        ]);
52
    }
53
54
    /**
55
     *      get/set data
56
     *
57
     *      @param array $value
58
     *      @return array
59
     */
60
    public function data($value=null)
61
    {
62
        if ($value !== null)
63
        {
64
            $this->data = $this->as_array($value);
65
        }
66
67
        return $this->data;
68
    }
69
70
    /**
71
     *      Cast to string
72
     *
73
     *      @param mixed $value
74
     *      @return string
75
     */
76
    protected function as_string($value=null)
77
    {
78
        return (is_scalar($value))?((is_bool($value))?(($value)?'true':'false'):"$value"):null;
79
    }
80
81
    /**
82
     *      Cast to integer
83
     *
84
     *      @param mixed $value
85
     *      @return integer
86
     */
87
    protected function as_int($value=null)
88
    {
89
        return (is_int($value))?$value:null;
90
    }
91
92
    /**
93
     *      Cast to array
94
     *
95
     *      @param mixed $value
96
     *      @return array
97
     */
98
    protected function as_array($value=null)
99
    {
100
        return (is_array($value))?$value:null;
101
    }
102
103
    /**
104
     *      Returns params set
105
     *
106
     *      @return array
107
     */
108
    public function get_params()
109
    {
110
        return array();
111
    }
112
113
    /**
114
     *      Returns iat param
115
     *
116
     *      @return integer
117
     */
118
    public function get_param_iat()
119
    {
120
        return time();
121
    }
122
123
    /**
124
     *      Returns the JSON representation of class
125
     *
126
     *      @return string
127
     */
128
    public function get_json()
129
    {
130
        $payload = $this->create_payload();
131
132
        if ($this->jwt['using'] === true)
133
        {
134
            $payload = $this->alter_payload_for_jwt($payload);
135
        }
136
        $json = json_encode($payload, JSON_UNESCAPED_SLASHES);
137
138
        Log::instance()->debug('build JSON:');
139
        Log::instance()->debug($json);
140
141
        return $json;
142
    }
143
144
    /**
145
     *      Create payload array
146
     *
147
     *      @return array
148
     */
149
    protected function create_payload()
150
    {
151
        $ar = array(
152
            'params' => $this->get_params()
153
        );
154
        if (isset($this->data))
155
        {
156
            $ar['data'] = $this->data;
157
        }
158
159
        return $ar;
160
    }
161
162
    /**
163
     *      Alter payload array with JWT-token
164
     *
165
     *      @param array $payload
166
     *      @return array
167
     */
168
    protected function alter_payload_for_jwt($payload)
169
    {
170
        $payload['iat'] = $this->get_param_iat();
171
172
        return array(
173
            'params' => $payload['params'],
174
            'token' => $this->token_encode($payload)
175
        );
176
    }
177
178
    /**
179
     *      Get private key for encode payload
180
     *
181
     *      @return string
182
     */
183
    protected function own_private_key()
184
    {
185
        return (new Key())->get($this->jwt['our_privkey'], 'private');
186
    }
187
188
    /**
189
     *      Encode payload and return token
190
     *
191
     *      @param array $payload
192
     *      @throws Exception\JSON
193
     *      @return string Token
194
     */
195 View Code Duplication
    protected function token_encode($payload)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
    {
197
        Log::instance()->debug('encode payload:');
198
        Log::instance()->debug(print_r($payload, true));
199
        try
200
        {
201
            $token = JWT::encode($payload, $this->own_private_key(), 'RS512');
202
        }
203
        catch (\Exception $e)
204
        {
205
            Log::instance()->error($e->getMessage().PHP_EOL.$e->getTraceAsString());
206
            throw new Exception\JSON('unable to create JWT token', $e);
207
        }
208
209
        return $token;
210
    }
211
212
    /**
213
     *      Send request to UAPAY
214
     *
215
     *      @return object Response
216
     */
217
    public function send()
218
    {
219
        Log::instance()->add('send request to '.$this->api_path);
220
        try
221
        {
222
            $httpresponse = $this->client->request('POST', $this->api_path, [
223
                'headers' => [
224
                    'User-Agent'    => 'php_UAPAY/1.0',
225
                    'Content-Type'  => 'application/json'
226
                ],
227
                'body' => $this->get_json()
228
            ]);
229
            $body = $httpresponse->getBody()->getContents();
230
            Log::instance()->debug('got response:'.PHP_EOL.$body);
231
            return new $this->response_class($body, $this->jwt);
232
        }
233
        catch (\GuzzleHttp\Exception\RequestException $e)
234
        {
235
            $this->handle_request_exception($e);
236
        }
237
    }
238
239
    /**
240
     *      Handle request exception
241
     *
242
     *      @param \GuzzleHttp\Exception\RequestException $e
243
     *      @throws Exception\Transfer
244
     */
245
    protected function handle_request_exception($e)
246
    {
247
        Log::instance()->debug('request:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->getRequest()));
248
        if ($e->hasResponse()) {
249
            Log::instance()->debug('response:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->getResponse()));
250
        }
251
252
        throw new Exception\Transfer('an error occured during a transfer');
253
    }
254
}
255