Completed
Push — master ( 145a7f...613e75 )
by Ibrahim
02:02
created

Caller::attemptCurl()   D

Complexity

Conditions 10
Paths 30

Size

Total Lines 41
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 41
rs 4.8196
cc 10
eloc 24
nc 30
nop 4

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Yabacon\Paystack\Helpers;
4
5
use \Closure;
6
use \Yabacon\Paystack\Contracts\RouteInterface;
7
8
class Caller
9
{
10
    private $use_guzzle=false;
11
    private $secret_key;
12
13
    public function __construct($paystackObj)
14
    {
15
        $this->secret_key = $paystackObj->secret_key;
16
        $this->use_guzzle = $paystackObj->use_guzzle;
17
    }
18
19
    public function moveArgsToSentargs(
20
        $interface,
21
        &$payload,
22
        &$sentargs
23
    ) {
24
        // check if interface supports args
25
        if (array_key_exists(RouteInterface:: ARGS_KEY, $interface)) {
26
            // to allow args to be specified in the payload, filter them out and put them in sentargs
27
            $sentargs = (!$sentargs) ? [ ] : $sentargs; // Make sure $sentargs is not null
28
            $args = $interface[RouteInterface::ARGS_KEY];
29
            while (list($key, $value) = each($payload)) {
30
                // check that a value was specified
31
                // with a key that was expected as an arg
32
                if (in_array($key, $args)) {
33
                    $sentargs[$key] = $value;
34
                    unset($payload[$key]);
35
                }
36
            }
37
        }
38
    }
39
40
    public function putArgsIntoEndpoint(&$endpoint, $sentargs)
41
    {
42
        // substitute sentargs in endpoint
43
        while (list($key, $value) = each($sentargs)) {
44
            $endpoint = str_replace('{' . $key . '}', $value, $endpoint);
45
        }
46
    }
47
    
48
    private function attemptGuzzle($method, $endpoint, $headers, $body)
49
    {
50
        if ($this->use_guzzle &&
51
            class_exists('\\GuzzleHttp\\Exception\\BadResponseException') &&
52
            class_exists('\\GuzzleHttp\\Exception\\ClientException') &&
53
            class_exists('\\GuzzleHttp\\Exception\\ConnectException') &&
54
            class_exists('\\GuzzleHttp\\Exception\\RequestException') &&
55
            class_exists('\\GuzzleHttp\\Exception\\ServerException') &&
56
            class_exists('\\GuzzleHttp\\Exception\\TooManyRedirectsException') &&
57
            class_exists('\\GuzzleHttp\\Client') &&
58
            class_exists('\\GuzzleHttp\\Psr7\\Request')) {
59
            $request = new \GuzzleHttp\Psr7\Request(strtoupper($method), $endpoint, $headers, $body);
60
            $client = new \GuzzleHttp\Client();
61
            try {
62
                $response = $client->send($request);
63
            } catch (\Exception $e) {
64
                if (($e instanceof \GuzzleHttp\Exception\BadResponseException
65
                    || $e instanceof \GuzzleHttp\Exception\ClientException
66
                    || $e instanceof \GuzzleHttp\Exception\ConnectException
67
                    || $e instanceof \GuzzleHttp\Exception\RequestException
68
                    || $e instanceof \GuzzleHttp\Exception\ServerException
69
                    || $e instanceof \GuzzleHttp\Exception\TooManyRedirectsException
70
                    ) && $e->hasResponse()) {
71
                    $response = $e->getResponse();
72
                } else {
73
                    throw $e;
74
                }
75
            }
76
            return $response;
77
        } else {
78
            return false;
79
        }
80
    }
81
82
    public function callEndpoint($interface, $payload = [ ], $sentargs = [ ])
83
    {
84
        $endpoint = Router::PAYSTACK_API_ROOT . $interface[RouteInterface::ENDPOINT_KEY];
85
        $method = $interface[RouteInterface::METHOD_KEY];
86
87
        $this->moveArgsToSentargs($interface, $payload, $sentargs);
88
        $this->putArgsIntoEndpoint($endpoint, $sentargs);
89
 
90
        $headers = ["Authorization"=>"Bearer " . $this->secret_key ];
91
        $body = '';
92
        if (($method === RouteInterface::POST_METHOD)
93
            || ($method === RouteInterface::PUT_METHOD)
94
        ) {
95
            $headers["Content-Type"] = "application/json";
96
            $body = json_encode($payload);
97
        } elseif ($method === RouteInterface::GET_METHOD) {
98
            $endpoint = $endpoint . '?' . http_build_query($payload);
99
        }
100
        // Use Guzzle if found, else use Curl
101
        $guzzleResponse = $this->attemptGuzzle($method, $endpoint, $headers, $body);
102
        if ($guzzleResponse !== false) {
103
            return $guzzleResponse;
104
        }
105
        
106
        return $this->attemptCurl($method, $endpoint, $headers, $body);
107
    }
108
109
    private function attemptCurl($method, $endpoint, $headers, $body)
110
    {
111
        //open connection
112
        $ch = \curl_init();
113
        \curl_setopt($ch, \CURLOPT_URL, $endpoint);
114
115
        if ($method === RouteInterface::POST_METHOD || $method === RouteInterface::PUT_METHOD) {
116
            ($method === RouteInterface:: POST_METHOD) && \curl_setopt($ch, \CURLOPT_POST, true);
117
            ($method === RouteInterface ::PUT_METHOD) && \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, "PUT");
118
119
            \curl_setopt($ch, \CURLOPT_POSTFIELDS, $body);
120
        }
121
        //flatten the headers
122
        $flattened_headers = [];
123
        while (list($key, $value) = each($headers)) {
124
            $flattened_headers[] = $key . ": " . $value;
125
        }
126
        \curl_setopt($ch, \CURLOPT_HTTPHEADER, $flattened_headers);
127
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, 1);
128
        \curl_setopt($ch, \CURLOPT_SSLVERSION, 6);
129
130
        $response = \curl_exec($ch);
131
        
132
        if (\curl_errno($ch)) {   // should be 0
133
            // curl ended with an error
134
            $cerr = \curl_error($ch);
135
            \curl_close($ch);
136
            throw new \Exception("Curl failed with response: '" . $cerr . "'.");
137
        }
138
139
        // Decode JSON from Paystack:
140
        $resp = \json_decode($response);
141
        \curl_close($ch);
142
143
        if (json_last_error() !== JSON_ERROR_NONE || !$resp->status) {
144
            throw new \Exception("Paystack Request failed with response: '" .
145
            ((json_last_error() === JSON_ERROR_NONE) ? $resp->message : $response) . "'.");
146
        }
147
148
        return $resp;
149
    }
150
}
151