Drip::constructRequestUrl()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
namespace DrewM\Drip;
4
5
class Drip
6
{
7
    protected static $eventSubscriptions = [];
8
    protected static $receivedWebhook    = false;
9
    protected        $api_endpoint       = 'https://api.getdrip.com/v2';
10
    protected        $token              = false;
11
    protected        $accountID          = null;
12
    protected        $verify_ssl         = true;
13
14
    /**
15
     * Drip constructor.
16
     *
17
     * @param string      $token     API Token
18
     * @param string|null $accountID Drip account ID to operate on
19
     */
20
    public function __construct($token, $accountID = null)
21
    {
22
        $this->token = $token;
0 ignored issues
show
Documentation Bug introduced by
The property $token was declared of type boolean, but $token is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
23
24
        if ($accountID !== null) {
25
            $this->accountID = $accountID;
26
        }
27
    }
28
29
    public static function subscribeToWebhook($event, callable $callback)
30
    {
31
        if (!isset(self::$eventSubscriptions[$event])) {
32
            self::$eventSubscriptions[$event] = [];
33
        }
34
        self::$eventSubscriptions[$event][] = $callback;
35
36
        self::receiveWebhook();
37
    }
38
39
    public static function receiveWebhook($input = null)
40
    {
41
        if ($input === null) {
42
            if (self::$receivedWebhook !== false) {
43
                $input = self::$receivedWebhook;
44
            } else {
45
                $input = file_get_contents("php://input");
46
            }
47
        }
48
49
        if ($input) {
50
            return self::processWebhook($input);
51
        }
52
53
        return false;
54
    }
55
56
    protected static function processWebhook($input)
57
    {
58
        if ($input) {
59
            self::$receivedWebhook = $input;
60
            $result                = json_decode($input, true);
61
            if ($result && isset($result['event'])) {
62
                self::dispatchWebhookEvent($result['event'], $result['data']);
63
                return $result;
64
            }
65
        }
66
67
        return false;
68
    }
69
70
    protected static function dispatchWebhookEvent($event, $data)
71
    {
72
        if (isset(self::$eventSubscriptions[$event])) {
73
            foreach (self::$eventSubscriptions[$event] as $callback) {
74
                $callback($data);
75
            }
76
            // reset subscriptions
77
            self::$eventSubscriptions[$event] = [];
78
        }
79
        return false;
80
    }
81
82
    /**
83
     * Set account ID if it was not passed into the constructor
84
     *
85
     * @param string $accountID
86
     *
87
     * @return void
88
     */
89
    public function setAccountId($accountID)
90
    {
91
        $this->accountID = $accountID;
92
    }
93
94
    /**
95
     * Make a GET request
96
     *
97
     * @param string $api_method API method to call
98
     * @param array  $args       API arguments
99
     * @param int    $timeout    Connection timeout (seconds)
100
     *
101
     * @return Response
102
     * @throws DripException
103
     */
104
    public function get($api_method, $args = [], $timeout = 10)
105
    {
106
        return $this->makeRequest('get', $api_method, $args, $timeout);
107
    }
108
109
    /**
110
     * Make the HTTP request
111
     *
112
     * @param string $http_verb  HTTP method used: get, post, delete
113
     * @param string $api_method Drip API method to call
114
     * @param array  $args       Array of arguments to the API method
115
     * @param int    $timeout    Connection timeout (seconds)
116
     * @param string $url        Optional URL to override the constructed one
117
     *
118
     * @return Response
119
     * @throws DripException
120
     */
121
    protected function makeRequest($http_verb, $api_method, $args = [], $timeout = 10, $url = null)
122
    {
123
        $this->checkDependencies();
124
125
        $url = $this->constructRequestUrl($url, $api_method);
126
        $ch  = $this->createCurlSession($url, $timeout);
127
128
        switch ($http_verb) {
129
            case 'post':
130
                curl_setopt($ch, CURLOPT_POST, 1);
131
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($args));
132
                break;
133
134
            case 'get':
135
                curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($args));
136
                break;
137
138
            case 'delete':
139
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
140
                break;
141
        }
142
143
        return $this->executeRequest($ch);
144
    }
145
146
    /**
147
     * Check for required PHP functionality
148
     *
149
     * @return bool
150
     * @throws DripException
151
     */
152
    private function checkDependencies()
153
    {
154
        if (!function_exists('curl_init') || !function_exists('curl_setopt')) {
155
            throw new DripException("cURL support is required, but can't be found.", 1);
156
        }
157
158
        return true;
159
    }
160
161
    /**
162
     * @param string|null $url
163
     * @param string      $api_method
164
     *
165
     * @return string
166
     * @throws DripException
167
     */
168
    private function constructRequestUrl($url, $api_method)
169
    {
170
        if ($url !== null) {
171
            return $url;
172
        }
173
174
        if ($this->accountID === null) {
175
            throw new DripException("This method requires an account ID and none has been set.", 2);
176
        }
177
178
        return $this->api_endpoint . '/' . $this->accountID . '/' . $api_method;
179
    }
180
181
    /**
182
     * Create a new CURL session (common setup etc)
183
     *
184
     * @param string $url
185
     * @param int    $timeout
186
     *
187
     * @return resource
188
     * @throws DripException
189
     */
190
    private function createCurlSession($url, $timeout = 10)
191
    {
192
        $ch = curl_init();
193
194
        if (!$ch) {
195
            throw new DripException("Unable to initialise curl", 3);
196
        }
197
198
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
199
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
200
            'Accept: application/vnd.api+json',
201
            'Content-Type: application/vnd.api+json',
202
        ]);
203
        curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/Drip (github.com/drewm/drip)');
204
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
205
        curl_setopt($ch, CURLOPT_USERPWD, $this->token . ': ');
206
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
207
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
208
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
209
        curl_setopt($ch, CURLOPT_URL, $url);
210
211
        return $ch;
212
    }
213
214
    /**
215
     * Execute and handle the request result
216
     *
217
     * @param resource $ch Curl handle
218
     *
219
     * @return Response
220
     * @throws DripException
221
     */
222
    private function executeRequest(&$ch)
223
    {
224
        $result = curl_exec($ch);
225
226
        if (!curl_errno($ch)) {
227
            $info = curl_getinfo($ch);
228
            curl_close($ch);
229
            return new Response($info, $result);
230
        }
231
232
        $errno = curl_errno($ch);
233
        $error = curl_error($ch);
234
235
        curl_close($ch);
236
237
        throw new DripException($error, $errno);
238
    }
239
240
    /**
241
     * Make a GET request to a top-level method outside of this account
242
     *
243
     * @param string $api_method
244
     * @param array  $args
245
     * @param int    $timeout
246
     *
247
     * @return Response
248
     * @throws DripException
249
     */
250
    public function getGlobal($api_method, $args = [], $timeout = 10)
251
    {
252
        $url = $this->api_endpoint . '/' . $api_method;
253
        return $this->makeRequest('get', $api_method, $args, $timeout, $url);
254
    }
255
256
    /**
257
     * Make a POST request
258
     *
259
     * @param string $api_method API method
260
     * @param array  $args       Arguments to API method
261
     * @param int    $timeout    Connection timeout (seconds)
262
     *
263
     * @return Response
264
     * @throws DripException
265
     */
266
    public function post($api_method, $args = [], $timeout = 10)
267
    {
268
        return $this->makeRequest('post', $api_method, $args, $timeout);
269
    }
270
271
    /**
272
     * Make a DELETE request
273
     *
274
     * @param string $api_method API method
275
     * @param array  $args       Arguments to the API method
276
     * @param int    $timeout    Connection timeout (seconds)
277
     *
278
     * @return Response
279
     * @throws DripException
280
     */
281
    public function delete($api_method, $args = [], $timeout = 10)
282
    {
283
        return $this->makeRequest('delete', $api_method, $args, $timeout);
284
    }
285
286
    public function disableSSLVerification()
287
    {
288
        $this->verify_ssl = false;
289
    }
290
}
291