Passed
Push — master ( d048db...e350b2 )
by Shahrad
01:41
created
examples/bulk-request/breakdown-large-request.php 1 patch
Indentation   +124 added lines, -124 removed lines patch added patch discarded remove patch
@@ -17,117 +17,117 @@  discard block
 block discarded – undo
17 17
 $client = new \EasyHttp\Client();
18 18
 $endpoint = 'https://scanner.tradingview.com/america/scan';
19 19
 $post = [
20
-	'filter' => [
21
-		[
22
-			'left' => "exchange",
23
-			'operation' => "in_range",
24
-			'right' => [
25
-				'AMEX',
26
-				'NASDAQ',
27
-				'NYSE'
28
-			],
29
-		],
30
-		[
31
-			'left' => "is_primary",
32
-			'operation' => "equal",
33
-			'right' => true,
34
-		],
35
-		[
36
-			'left' => "change",
37
-			'operation' => "nempty",
38
-		]
39
-	],
40
-	'options' => [
41
-		'lang' => "en",
42
-		'active_symbols_only' => true,
43
-	],
44
-	'markets' => [
45
-		"america"
46
-	],
47
-	'columns' => [
48
-		"logoid",
49
-		"name",
50
-		"change|1",
51
-		"change|5",
52
-		"change|15",
53
-		"change|60",
54
-		"change|240",
55
-		"change",
56
-		"change|1W",
57
-		"change|1M",
58
-		"Perf.3M",
59
-		"Perf.6M",
60
-		"Perf.YTD",
61
-		"Perf.Y",
62
-		"Volatility.D",
63
-		"description",
64
-		"type",
65
-		"subtype",
66
-		"update_mode",
67
-		"currency",
68
-		"fundamental_currency_code",
69
-		"Recommend.All",
70
-		"RSI",
71
-		"RSI[1]",
72
-		"Stoch.K",
73
-		"Stoch.D",
74
-		"Stoch.K[1]",
75
-		"Stoch.D[1]",
76
-		"CCI20",
77
-		"CCI20[1]",
78
-		"AO",
79
-		"AO[1]",
80
-		"AO[2]",
81
-		"Mom",
82
-		"Mom[1]",
83
-		"MACD.macd",
84
-		"MACD.signal",
85
-		"Rec.Stoch.RSI",
86
-		"Stoch.RSI.K",
87
-		"Rec.WR",
88
-		"W.R",
89
-		"Rec.BBPower",
90
-		"BBPower",
91
-		"Rec.UO",
92
-		"UO",
93
-		"EMA10",
94
-		"close",
95
-		"SMA10",
96
-		"EMA20",
97
-		"SMA20",
98
-		"EMA30",
99
-		"SMA30",
100
-		"EMA50",
101
-		"SMA50",
102
-		"EMA100",
103
-		"SMA100",
104
-		"EMA200",
105
-		"SMA200",
106
-		"Rec.Ichimoku",
107
-		"Ichimoku.BLine",
108
-		"Rec.VWMA",
109
-		"VWMA",
110
-		"Rec.HullMA9",
111
-		"HullMA9"
112
-	],
113
-	'sort' => [
114
-		'sortBy' => "change",
115
-		'sortOrder' => "desc"
116
-	]
20
+    'filter' => [
21
+        [
22
+            'left' => "exchange",
23
+            'operation' => "in_range",
24
+            'right' => [
25
+                'AMEX',
26
+                'NASDAQ',
27
+                'NYSE'
28
+            ],
29
+        ],
30
+        [
31
+            'left' => "is_primary",
32
+            'operation' => "equal",
33
+            'right' => true,
34
+        ],
35
+        [
36
+            'left' => "change",
37
+            'operation' => "nempty",
38
+        ]
39
+    ],
40
+    'options' => [
41
+        'lang' => "en",
42
+        'active_symbols_only' => true,
43
+    ],
44
+    'markets' => [
45
+        "america"
46
+    ],
47
+    'columns' => [
48
+        "logoid",
49
+        "name",
50
+        "change|1",
51
+        "change|5",
52
+        "change|15",
53
+        "change|60",
54
+        "change|240",
55
+        "change",
56
+        "change|1W",
57
+        "change|1M",
58
+        "Perf.3M",
59
+        "Perf.6M",
60
+        "Perf.YTD",
61
+        "Perf.Y",
62
+        "Volatility.D",
63
+        "description",
64
+        "type",
65
+        "subtype",
66
+        "update_mode",
67
+        "currency",
68
+        "fundamental_currency_code",
69
+        "Recommend.All",
70
+        "RSI",
71
+        "RSI[1]",
72
+        "Stoch.K",
73
+        "Stoch.D",
74
+        "Stoch.K[1]",
75
+        "Stoch.D[1]",
76
+        "CCI20",
77
+        "CCI20[1]",
78
+        "AO",
79
+        "AO[1]",
80
+        "AO[2]",
81
+        "Mom",
82
+        "Mom[1]",
83
+        "MACD.macd",
84
+        "MACD.signal",
85
+        "Rec.Stoch.RSI",
86
+        "Stoch.RSI.K",
87
+        "Rec.WR",
88
+        "W.R",
89
+        "Rec.BBPower",
90
+        "BBPower",
91
+        "Rec.UO",
92
+        "UO",
93
+        "EMA10",
94
+        "close",
95
+        "SMA10",
96
+        "EMA20",
97
+        "SMA20",
98
+        "EMA30",
99
+        "SMA30",
100
+        "EMA50",
101
+        "SMA50",
102
+        "EMA100",
103
+        "SMA100",
104
+        "EMA200",
105
+        "SMA200",
106
+        "Rec.Ichimoku",
107
+        "Ichimoku.BLine",
108
+        "Rec.VWMA",
109
+        "VWMA",
110
+        "Rec.HullMA9",
111
+        "HullMA9"
112
+    ],
113
+    'sort' => [
114
+        'sortBy' => "change",
115
+        'sortOrder' => "desc"
116
+    ]
117 117
 ];
118 118
 
119 119
 $start = microtime(true);
120 120
 $Response = $client->post($endpoint, [
121
-	'headers' => [
122
-		'Content-Type' => 'application/json',
123
-		'Accept' => 'application/json',
124
-	],
125
-	'body' => array_merge($post, [
126
-		'range' => [
127
-			0,
128
-			2000
129
-		]
130
-	]),
121
+    'headers' => [
122
+        'Content-Type' => 'application/json',
123
+        'Accept' => 'application/json',
124
+    ],
125
+    'body' => array_merge($post, [
126
+        'range' => [
127
+            0,
128
+            2000
129
+        ]
130
+    ]),
131 131
 ]);
132 132
 $Data = json_decode($Response->getBody(), true);
133 133
 $Memory = \EasyHttp\Utils\Toolkit::bytesToHuman(memory_get_usage());
@@ -139,22 +139,22 @@  discard block
 block discarded – undo
139 139
 // Initializes the request
140 140
 $requests = [];
141 141
 for ($i = 0; $i < 2000; $i += 500) {
142
-	$requests[] = [
143
-		'method' => 'POST',
144
-		'uri' => $endpoint,
145
-		'options' => [
146
-			'headers' => [
147
-				'Content-Type' => 'application/json',
148
-				'Accept' => 'application/json',
149
-			],
150
-			'body' => array_merge($post, [
151
-				'range' => [
152
-					$i,
153
-					$i + 500
154
-				]
155
-			]),
156
-		]
157
-	];
142
+    $requests[] = [
143
+        'method' => 'POST',
144
+        'uri' => $endpoint,
145
+        'options' => [
146
+            'headers' => [
147
+                'Content-Type' => 'application/json',
148
+                'Accept' => 'application/json',
149
+            ],
150
+            'body' => array_merge($post, [
151
+                'range' => [
152
+                    $i,
153
+                    $i + 500
154
+                ]
155
+            ]),
156
+        ]
157
+    ];
158 158
 }
159 159
 
160 160
 // --------------------- ====== --------------------- //
@@ -162,7 +162,7 @@  discard block
 block discarded – undo
162 162
 $start = microtime(true);
163 163
 $responses = $client->bulk($requests);
164 164
 foreach ($responses as $response) {
165
-	$Data = json_decode($response->getBody(), true);
165
+    $Data = json_decode($response->getBody(), true);
166 166
 }
167 167
 $Memory = \EasyHttp\Utils\Toolkit::bytesToHuman(memory_get_usage());
168 168
 echo '<pre>' . "Bulk Request - Total time: " . (microtime(true) - $start) . " - Memory: $Memory" . '</pre>';
169 169
\ No newline at end of file
Please login to merge, or discard this patch.
examples/download/download-large-file.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -13,7 +13,7 @@
 block discarded – undo
13 13
 
14 14
 
15 15
 if ($Result->save(__DIR__ . '/uploads/google.png')) {
16
-	echo 'File saved successfully';
16
+    echo 'File saved successfully';
17 17
 } else {
18
-	echo 'File not saved';
18
+    echo 'File not saved';
19 19
 }
20 20
\ No newline at end of file
Please login to merge, or discard this patch.
examples/upload/josh_sean.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -2,15 +2,15 @@
 block discarded – undo
2 2
 
3 3
 function generateUpToDateMimeArray(string $url): array
4 4
 {
5
-	$s = array();
6
-	foreach (@explode("\n", @file_get_contents($url)) as $x) {
7
-		if (isset($x[0]) && $x[0] !== '#' && preg_match_all('#([^\s]+)#', $x, $out) && isset($out[1]) && ($c = count($out[1])) > 1) {
8
-			for ($i = 1; $i < $c; $i++) {
9
-				$s[$out[1][$i]] = $out[1][0];
10
-			}
11
-		}
12
-	}
13
-	return $s;
5
+    $s = array();
6
+    foreach (@explode("\n", @file_get_contents($url)) as $x) {
7
+        if (isset($x[0]) && $x[0] !== '#' && preg_match_all('#([^\s]+)#', $x, $out) && isset($out[1]) && ($c = count($out[1])) > 1) {
8
+            for ($i = 1; $i < $c; $i++) {
9
+                $s[$out[1][$i]] = $out[1][0];
10
+            }
11
+        }
12
+    }
13
+    return $s;
14 14
 }
15 15
 
16 16
 $data = generateUpToDateMimeArray('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types');
Please login to merge, or discard this patch.
examples/upload/send-file-to-telegram.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -8,13 +8,13 @@
 block discarded – undo
8 8
 $chat_id = '259760855';
9 9
 
10 10
 $response = (new \EasyHttp\Client())->post('https://api.telegram.org/bot' . $your_token . '/sendPhoto', [
11
-	'query' => [
12
-		'chat_id' => $chat_id,
13
-		'caption' => 'Привет!',
14
-	],
15
-	'multipart' => \EasyHttp\FormData::create([
16
-		'photo' => getcwd() . '/../docs/uploads/download.png'
17
-	])
11
+    'query' => [
12
+        'chat_id' => $chat_id,
13
+        'caption' => 'Привет!',
14
+    ],
15
+    'multipart' => \EasyHttp\FormData::create([
16
+        'photo' => getcwd() . '/../docs/uploads/download.png'
17
+    ])
18 18
 ]);
19 19
 
20 20
 
Please login to merge, or discard this patch.
examples/upload/upload-multiple-files.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -5,8 +5,8 @@
 block discarded – undo
5 5
 // =============================== ***** =============================== //
6 6
 
7 7
 $result = (new \EasyHttp\Client())->upload('https://httpbin.org/post', [
8
-	'photo1' => getcwd() . '/../docs/uploads/result-of-breakdown-example.png',
9
-	'photo2' => getcwd() . '/../docs/uploads/download.png',
8
+    'photo1' => getcwd() . '/../docs/uploads/result-of-breakdown-example.png',
9
+    'photo2' => getcwd() . '/../docs/uploads/download.png',
10 10
 ]);
11 11
 
12 12
 echo '<pre>' . \EasyHttp\Utils\Toolkit::prettyJson($result->getBody()) . '</pre>';
Please login to merge, or discard this patch.
src/Client.php 2 patches
Indentation   +327 added lines, -327 removed lines patch added patch discarded remove patch
@@ -21,332 +21,332 @@
 block discarded – undo
21 21
 class Client
22 22
 {
23 23
 
24
-	use ClientTrait;
25
-
26
-	/**
27
-	 * The temp directory to download files - default is $_SERVER['TEMP']
28
-	 *
29
-	 * @var ?string
30
-	 */
31
-	private ?string $tempDir;
32
-
33
-	/**
34
-	 * The Max count of chunk to download file
35
-	 *
36
-	 * @var int
37
-	 */
38
-	public int $maxChunkCount = 10;
39
-
40
-	/**
41
-	 * The constructor of the client
42
-	 */
43
-	public function __construct()
44
-	{
45
-		$this->tempDir = $_SERVER['TEMP'] ?? null;
46
-		$this->setHasSelfSignedCertificate(true);
47
-	}
48
-
49
-	/**
50
-	 * Set has self-signed certificate
51
-	 *
52
-	 * This is used to set the curl option CURLOPT_SSL_VERIFYPEER
53
-	 * and CURLOPT_SSL_VERIFYHOST to false. This is useful when you are
54
-	 * in local environment, or you have self-signed certificate.
55
-	 *
56
-	 * @param bool $has
57
-	 *
58
-	 * @return void
59
-	 */
60
-	public function setHasSelfSignedCertificate(bool $has): void
61
-	{
62
-		putenv('HAS_SELF_SIGNED_CERT=' . ($has ? 'true' : 'false'));
63
-	}
64
-
65
-	/**
66
-	 * Set the temporary directory path to save the downloaded files
67
-	 *
68
-	 * @param string $path
69
-	 *
70
-	 * @return void
71
-	 */
72
-	public function setTempPath(string $path): void
73
-	{
74
-		if (!file_exists($path)) {
75
-			throw new InvalidArgumentException(
76
-				sprintf('The path "%s" does not exist', $path)
77
-			);
78
-		}
79
-		$this->tempDir = $path;
80
-	}
81
-
82
-	/**
83
-	 * This method is used to send a http request to a given url.
84
-	 *
85
-	 * @param string $method
86
-	 * @param string $uri
87
-	 * @param array|HttpOptions $options
88
-	 *
89
-	 * @return HttpResponse
90
-	 */
91
-	public function request(string $method, string $uri, array|HttpOptions $options = []): HttpResponse
92
-	{
93
-		$CurlHandle = Middleware::create_curl_handler($method, $uri, $options);
94
-		if (!$CurlHandle) {
95
-			throw new RuntimeException('An error occurred while creating the curl handler');
96
-		}
97
-
98
-		$result = new HttpResponse();
99
-		$result->setCurlHandle($CurlHandle);
100
-
101
-		$response = curl_exec($CurlHandle);
102
-		if (curl_errno($CurlHandle) || !$response) {
103
-			$result->setErrorCode(curl_errno($CurlHandle));
104
-			$result->setErrorMessage(curl_error($CurlHandle) ?? ErrorCode::getMessage(curl_errno($CurlHandle)));
105
-			return $result;
106
-		}
107
-
108
-		$result->setStatusCode(curl_getinfo($CurlHandle, CURLINFO_HTTP_CODE));
109
-		$result->setHeaderSize(curl_getinfo($CurlHandle, CURLINFO_HEADER_SIZE));
110
-		$result->setHeaders(substr((string)$response, 0, $result->getHeaderSize()));
111
-		$result->setBody(substr((string)$response, $result->getHeaderSize()));
112
-
113
-		curl_close($CurlHandle);
114
-
115
-		return $result;
116
-	}
117
-
118
-	/**
119
-	 * Send multiple requests to a given url.
120
-	 *
121
-	 * @param array $requests [{method, uri, options}, ...]
122
-	 *
123
-	 * @return array<HttpResponse>
124
-	 */
125
-	public function bulk(array $requests): array
126
-	{
127
-		$result = [];
128
-		$handlers = [];
129
-		$multi_handler = curl_multi_init();
130
-		foreach ($requests as $request) {
131
-
132
-			$CurlHandle = Middleware::create_curl_handler(
133
-				$request['method'] ?? null,
134
-				$request['uri'],
135
-				$request['options'] ?? []
136
-			);
137
-			if (!$CurlHandle) {
138
-				throw new RuntimeException(
139
-					'An error occurred while creating the curl handler'
140
-				);
141
-			}
142
-			$handlers[] = $CurlHandle;
143
-			curl_multi_add_handle($multi_handler, $CurlHandle);
144
-
145
-		}
146
-
147
-		$active = null;
148
-		do {
149
-			$mrc = curl_multi_exec($multi_handler, $active);
150
-		} while ($mrc == CURLM_CALL_MULTI_PERFORM);
151
-
152
-		while ($active && $mrc == CURLM_OK) {
153
-			if (curl_multi_select($multi_handler) != -1) {
154
-				do {
155
-					$mrc = curl_multi_exec($multi_handler, $active);
156
-				} while ($mrc == CURLM_CALL_MULTI_PERFORM);
157
-			}
158
-		}
159
-
160
-		foreach ($handlers as $handler) {
161
-			curl_multi_remove_handle($multi_handler, $handler);
162
-		}
163
-		curl_multi_close($multi_handler);
164
-
165
-		foreach ($handlers as $handler) {
166
-			$content = curl_multi_getcontent($handler);
167
-			$response = new HttpResponse();
168
-
169
-			if (curl_errno($handler)) {
170
-				$response->setErrorCode(curl_errno($handler));
171
-				$response->setErrorMessage(
172
-					curl_error($handler) ??
173
-					ErrorCode::getMessage(curl_errno($handler))
174
-				);
175
-			}
176
-
177
-			$response->setCurlHandle($handler);
178
-			$response->setStatusCode(curl_getinfo($handler, CURLINFO_HTTP_CODE));
179
-			$response->setHeaderSize(curl_getinfo($handler, CURLINFO_HEADER_SIZE));
180
-			$response->setHeaders(substr($content, 0, $response->getHeaderSize()));
181
-			$response->setBody(substr($content, $response->getHeaderSize()));
182
-
183
-			$result[] = $response;
184
-		}
185
-
186
-		return $result;
187
-	}
188
-
189
-	/**
190
-	 * Download large files.
191
-	 *
192
-	 * This method is used to download large files with creating multiple requests.
193
-	 *
194
-	 * Change `max_chunk_count` variable to change the number of chunks. (default: 10)
195
-	 *
196
-	 * @param string $url The direct url to the file.
197
-	 * @param array|HttpOptions $options The options to use.
198
-	 *
199
-	 * @return DownloadResult
200
-	 */
201
-	public function download(string $url, array|HttpOptions $options = []): DownloadResult
202
-	{
203
-		if (empty($this->tempDir)) {
204
-			throw new RuntimeException(
205
-				'The temp directory is not set. Please set the temp directory using the `setTempDir` method.'
206
-			);
207
-		}
208
-
209
-		if (!file_exists($this->tempDir)) {
210
-			if (mkdir($this->tempDir, 0777, true) === false) {
211
-				throw new RuntimeException(
212
-					'The temp directory is not writable. Please set the temp directory using the `setTempDir` method.'
213
-				);
214
-			}
215
-		}
216
-
217
-		if (gettype($options) === 'array') {
218
-			$options = new HttpOptions($options);
219
-		}
220
-
221
-		$fileSize = $this->get_file_size($url);
222
-		$chunkSize = $this->get_chunk_size($fileSize);
223
-
224
-		$result = new DownloadResult();
225
-
226
-		$result->id = uniqid();
227
-		$result->chunksPath = $this->tempDir . '/' . $result->id . '/';
228
-		mkdir($result->chunksPath, 0777, true);
229
-
230
-		$result->fileSize = $fileSize;
231
-		$result->chunkSize = $chunkSize;
232
-		$result->chunks = ceil($fileSize / $chunkSize);
233
-
234
-		$result->startTime = time();
235
-
236
-		$requests = [];
237
-		for ($i = 0; $i < $result->chunks; $i++) {
238
-			$range = $i * $chunkSize . '-' . ($i + 1) * $chunkSize;
239
-			if ($i + 1 === $result->chunks) {
240
-				$range = $i * $chunkSize . '-' . $fileSize;
241
-			}
242
-			$requests[] = [
243
-				'method' => 'GET',
244
-				'uri' => $url,
245
-				'options' => array_merge($options->toArray(), [
246
-					'CurlOptions' => [
247
-						CURLOPT_RANGE => $range
248
-					],
249
-				])
250
-			];
251
-		}
252
-
253
-		foreach ($this->bulk($requests) as $response) {
254
-			$result->addChunk(
255
-				Toolkit::randomString(16),
256
-				$response->getBody(),
257
-				$response->getInfoFromCurl()->TOTAL_TIME
258
-			);
259
-		}
260
-
261
-		$result->endTime = time();
262
-
263
-		return $result;
264
-	}
265
-
266
-	/**
267
-	 * Upload single or multiple files
268
-	 *
269
-	 * This method is sending file with request method of POST and
270
-	 * Content-Type of multipart/form-data.
271
-	 *
272
-	 * @param string $url The direct url to the file.
273
-	 * @param array $filePath The path to the file.
274
-	 * @param array|HttpOptions $options The options to use.
275
-	 *
276
-	 * @return HttpResponse
277
-	 */
278
-	public function upload(string $url, array $filePath, array|HttpOptions $options = []): HttpResponse
279
-	{
280
-		if (gettype($options) === 'array') {
281
-			$options = new HttpOptions($options);
282
-		}
283
-
284
-		$multipart = [];
285
-
286
-		foreach ($filePath as $key => $file) {
287
-			$multipart[$key] = new \CURLFile(
288
-				realpath($file),
289
-				$this->get_file_type($file)
290
-			);
291
-		}
292
-
293
-		$options->setMultipart($multipart);
294
-		return $this->post($url, $options);
295
-	}
296
-
297
-	/**
298
-	 * Get filetype with the extension.
299
-	 *
300
-	 * @param string $filename The absolute path to the file.
301
-	 * @return string eg. image/jpeg
302
-	 */
303
-	public static function get_file_type(string $filename): string
304
-	{
305
-		return MimeType::TYPES[pathinfo($filename, PATHINFO_EXTENSION)] ?? 'application/octet-stream';
306
-	}
307
-
308
-	/**
309
-	 * Get file size.
310
-	 *
311
-	 * @param string $url The direct url to the file.
312
-	 * @return int
313
-	 */
314
-	public function get_file_size(string $url): int
315
-	{
316
-		if (file_exists($url)) {
317
-			return filesize($url);
318
-		}
319
-
320
-		$response = $this->get($url, [
321
-			'headers' => [
322
-				'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
323
-			],
324
-			'CurlOptions' => [
325
-				CURLOPT_NOBODY => true,
326
-			]
327
-		]);
328
-
329
-		return (int)$response->getHeaderLine('Content-Length') ?? 0;
330
-	}
331
-
332
-	/**
333
-	 * Get the size of each chunk.
334
-	 *
335
-	 * For default, we're dividing filesize to 10 as max size of each chunk.
336
-	 * If the file size was smaller than 2MB, we'll use the filesize as single chunk.
337
-	 *
338
-	 * @param int $fileSize The file size.
339
-	 * @return int
340
-	 */
341
-	private function get_chunk_size(int $fileSize): int
342
-	{
343
-		$maxChunkSize = $fileSize / $this->maxChunkCount;
344
-
345
-		if ($fileSize <= 2 * 1024 * 1024) {
346
-			return $fileSize;
347
-		}
348
-
349
-		return min($maxChunkSize, $fileSize);
350
-	}
24
+    use ClientTrait;
25
+
26
+    /**
27
+     * The temp directory to download files - default is $_SERVER['TEMP']
28
+     *
29
+     * @var ?string
30
+     */
31
+    private ?string $tempDir;
32
+
33
+    /**
34
+     * The Max count of chunk to download file
35
+     *
36
+     * @var int
37
+     */
38
+    public int $maxChunkCount = 10;
39
+
40
+    /**
41
+     * The constructor of the client
42
+     */
43
+    public function __construct()
44
+    {
45
+        $this->tempDir = $_SERVER['TEMP'] ?? null;
46
+        $this->setHasSelfSignedCertificate(true);
47
+    }
48
+
49
+    /**
50
+     * Set has self-signed certificate
51
+     *
52
+     * This is used to set the curl option CURLOPT_SSL_VERIFYPEER
53
+     * and CURLOPT_SSL_VERIFYHOST to false. This is useful when you are
54
+     * in local environment, or you have self-signed certificate.
55
+     *
56
+     * @param bool $has
57
+     *
58
+     * @return void
59
+     */
60
+    public function setHasSelfSignedCertificate(bool $has): void
61
+    {
62
+        putenv('HAS_SELF_SIGNED_CERT=' . ($has ? 'true' : 'false'));
63
+    }
64
+
65
+    /**
66
+     * Set the temporary directory path to save the downloaded files
67
+     *
68
+     * @param string $path
69
+     *
70
+     * @return void
71
+     */
72
+    public function setTempPath(string $path): void
73
+    {
74
+        if (!file_exists($path)) {
75
+            throw new InvalidArgumentException(
76
+                sprintf('The path "%s" does not exist', $path)
77
+            );
78
+        }
79
+        $this->tempDir = $path;
80
+    }
81
+
82
+    /**
83
+     * This method is used to send a http request to a given url.
84
+     *
85
+     * @param string $method
86
+     * @param string $uri
87
+     * @param array|HttpOptions $options
88
+     *
89
+     * @return HttpResponse
90
+     */
91
+    public function request(string $method, string $uri, array|HttpOptions $options = []): HttpResponse
92
+    {
93
+        $CurlHandle = Middleware::create_curl_handler($method, $uri, $options);
94
+        if (!$CurlHandle) {
95
+            throw new RuntimeException('An error occurred while creating the curl handler');
96
+        }
97
+
98
+        $result = new HttpResponse();
99
+        $result->setCurlHandle($CurlHandle);
100
+
101
+        $response = curl_exec($CurlHandle);
102
+        if (curl_errno($CurlHandle) || !$response) {
103
+            $result->setErrorCode(curl_errno($CurlHandle));
104
+            $result->setErrorMessage(curl_error($CurlHandle) ?? ErrorCode::getMessage(curl_errno($CurlHandle)));
105
+            return $result;
106
+        }
107
+
108
+        $result->setStatusCode(curl_getinfo($CurlHandle, CURLINFO_HTTP_CODE));
109
+        $result->setHeaderSize(curl_getinfo($CurlHandle, CURLINFO_HEADER_SIZE));
110
+        $result->setHeaders(substr((string)$response, 0, $result->getHeaderSize()));
111
+        $result->setBody(substr((string)$response, $result->getHeaderSize()));
112
+
113
+        curl_close($CurlHandle);
114
+
115
+        return $result;
116
+    }
117
+
118
+    /**
119
+     * Send multiple requests to a given url.
120
+     *
121
+     * @param array $requests [{method, uri, options}, ...]
122
+     *
123
+     * @return array<HttpResponse>
124
+     */
125
+    public function bulk(array $requests): array
126
+    {
127
+        $result = [];
128
+        $handlers = [];
129
+        $multi_handler = curl_multi_init();
130
+        foreach ($requests as $request) {
131
+
132
+            $CurlHandle = Middleware::create_curl_handler(
133
+                $request['method'] ?? null,
134
+                $request['uri'],
135
+                $request['options'] ?? []
136
+            );
137
+            if (!$CurlHandle) {
138
+                throw new RuntimeException(
139
+                    'An error occurred while creating the curl handler'
140
+                );
141
+            }
142
+            $handlers[] = $CurlHandle;
143
+            curl_multi_add_handle($multi_handler, $CurlHandle);
144
+
145
+        }
146
+
147
+        $active = null;
148
+        do {
149
+            $mrc = curl_multi_exec($multi_handler, $active);
150
+        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
151
+
152
+        while ($active && $mrc == CURLM_OK) {
153
+            if (curl_multi_select($multi_handler) != -1) {
154
+                do {
155
+                    $mrc = curl_multi_exec($multi_handler, $active);
156
+                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
157
+            }
158
+        }
159
+
160
+        foreach ($handlers as $handler) {
161
+            curl_multi_remove_handle($multi_handler, $handler);
162
+        }
163
+        curl_multi_close($multi_handler);
164
+
165
+        foreach ($handlers as $handler) {
166
+            $content = curl_multi_getcontent($handler);
167
+            $response = new HttpResponse();
168
+
169
+            if (curl_errno($handler)) {
170
+                $response->setErrorCode(curl_errno($handler));
171
+                $response->setErrorMessage(
172
+                    curl_error($handler) ??
173
+                    ErrorCode::getMessage(curl_errno($handler))
174
+                );
175
+            }
176
+
177
+            $response->setCurlHandle($handler);
178
+            $response->setStatusCode(curl_getinfo($handler, CURLINFO_HTTP_CODE));
179
+            $response->setHeaderSize(curl_getinfo($handler, CURLINFO_HEADER_SIZE));
180
+            $response->setHeaders(substr($content, 0, $response->getHeaderSize()));
181
+            $response->setBody(substr($content, $response->getHeaderSize()));
182
+
183
+            $result[] = $response;
184
+        }
185
+
186
+        return $result;
187
+    }
188
+
189
+    /**
190
+     * Download large files.
191
+     *
192
+     * This method is used to download large files with creating multiple requests.
193
+     *
194
+     * Change `max_chunk_count` variable to change the number of chunks. (default: 10)
195
+     *
196
+     * @param string $url The direct url to the file.
197
+     * @param array|HttpOptions $options The options to use.
198
+     *
199
+     * @return DownloadResult
200
+     */
201
+    public function download(string $url, array|HttpOptions $options = []): DownloadResult
202
+    {
203
+        if (empty($this->tempDir)) {
204
+            throw new RuntimeException(
205
+                'The temp directory is not set. Please set the temp directory using the `setTempDir` method.'
206
+            );
207
+        }
208
+
209
+        if (!file_exists($this->tempDir)) {
210
+            if (mkdir($this->tempDir, 0777, true) === false) {
211
+                throw new RuntimeException(
212
+                    'The temp directory is not writable. Please set the temp directory using the `setTempDir` method.'
213
+                );
214
+            }
215
+        }
216
+
217
+        if (gettype($options) === 'array') {
218
+            $options = new HttpOptions($options);
219
+        }
220
+
221
+        $fileSize = $this->get_file_size($url);
222
+        $chunkSize = $this->get_chunk_size($fileSize);
223
+
224
+        $result = new DownloadResult();
225
+
226
+        $result->id = uniqid();
227
+        $result->chunksPath = $this->tempDir . '/' . $result->id . '/';
228
+        mkdir($result->chunksPath, 0777, true);
229
+
230
+        $result->fileSize = $fileSize;
231
+        $result->chunkSize = $chunkSize;
232
+        $result->chunks = ceil($fileSize / $chunkSize);
233
+
234
+        $result->startTime = time();
235
+
236
+        $requests = [];
237
+        for ($i = 0; $i < $result->chunks; $i++) {
238
+            $range = $i * $chunkSize . '-' . ($i + 1) * $chunkSize;
239
+            if ($i + 1 === $result->chunks) {
240
+                $range = $i * $chunkSize . '-' . $fileSize;
241
+            }
242
+            $requests[] = [
243
+                'method' => 'GET',
244
+                'uri' => $url,
245
+                'options' => array_merge($options->toArray(), [
246
+                    'CurlOptions' => [
247
+                        CURLOPT_RANGE => $range
248
+                    ],
249
+                ])
250
+            ];
251
+        }
252
+
253
+        foreach ($this->bulk($requests) as $response) {
254
+            $result->addChunk(
255
+                Toolkit::randomString(16),
256
+                $response->getBody(),
257
+                $response->getInfoFromCurl()->TOTAL_TIME
258
+            );
259
+        }
260
+
261
+        $result->endTime = time();
262
+
263
+        return $result;
264
+    }
265
+
266
+    /**
267
+     * Upload single or multiple files
268
+     *
269
+     * This method is sending file with request method of POST and
270
+     * Content-Type of multipart/form-data.
271
+     *
272
+     * @param string $url The direct url to the file.
273
+     * @param array $filePath The path to the file.
274
+     * @param array|HttpOptions $options The options to use.
275
+     *
276
+     * @return HttpResponse
277
+     */
278
+    public function upload(string $url, array $filePath, array|HttpOptions $options = []): HttpResponse
279
+    {
280
+        if (gettype($options) === 'array') {
281
+            $options = new HttpOptions($options);
282
+        }
283
+
284
+        $multipart = [];
285
+
286
+        foreach ($filePath as $key => $file) {
287
+            $multipart[$key] = new \CURLFile(
288
+                realpath($file),
289
+                $this->get_file_type($file)
290
+            );
291
+        }
292
+
293
+        $options->setMultipart($multipart);
294
+        return $this->post($url, $options);
295
+    }
296
+
297
+    /**
298
+     * Get filetype with the extension.
299
+     *
300
+     * @param string $filename The absolute path to the file.
301
+     * @return string eg. image/jpeg
302
+     */
303
+    public static function get_file_type(string $filename): string
304
+    {
305
+        return MimeType::TYPES[pathinfo($filename, PATHINFO_EXTENSION)] ?? 'application/octet-stream';
306
+    }
307
+
308
+    /**
309
+     * Get file size.
310
+     *
311
+     * @param string $url The direct url to the file.
312
+     * @return int
313
+     */
314
+    public function get_file_size(string $url): int
315
+    {
316
+        if (file_exists($url)) {
317
+            return filesize($url);
318
+        }
319
+
320
+        $response = $this->get($url, [
321
+            'headers' => [
322
+                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
323
+            ],
324
+            'CurlOptions' => [
325
+                CURLOPT_NOBODY => true,
326
+            ]
327
+        ]);
328
+
329
+        return (int)$response->getHeaderLine('Content-Length') ?? 0;
330
+    }
331
+
332
+    /**
333
+     * Get the size of each chunk.
334
+     *
335
+     * For default, we're dividing filesize to 10 as max size of each chunk.
336
+     * If the file size was smaller than 2MB, we'll use the filesize as single chunk.
337
+     *
338
+     * @param int $fileSize The file size.
339
+     * @return int
340
+     */
341
+    private function get_chunk_size(int $fileSize): int
342
+    {
343
+        $maxChunkSize = $fileSize / $this->maxChunkCount;
344
+
345
+        if ($fileSize <= 2 * 1024 * 1024) {
346
+            return $fileSize;
347
+        }
348
+
349
+        return min($maxChunkSize, $fileSize);
350
+    }
351 351
 
352 352
 }
353 353
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -107,8 +107,8 @@  discard block
 block discarded – undo
107 107
 
108 108
 		$result->setStatusCode(curl_getinfo($CurlHandle, CURLINFO_HTTP_CODE));
109 109
 		$result->setHeaderSize(curl_getinfo($CurlHandle, CURLINFO_HEADER_SIZE));
110
-		$result->setHeaders(substr((string)$response, 0, $result->getHeaderSize()));
111
-		$result->setBody(substr((string)$response, $result->getHeaderSize()));
110
+		$result->setHeaders(substr((string) $response, 0, $result->getHeaderSize()));
111
+		$result->setBody(substr((string) $response, $result->getHeaderSize()));
112 112
 
113 113
 		curl_close($CurlHandle);
114 114
 
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
 			]
327 327
 		]);
328 328
 
329
-		return (int)$response->getHeaderLine('Content-Length') ?? 0;
329
+		return (int) $response->getHeaderLine('Content-Length') ?? 0;
330 330
 	}
331 331
 
332 332
 	/**
Please login to merge, or discard this patch.
src/Contracts/ConnectionContract.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -12,16 +12,16 @@
 block discarded – undo
12 12
 interface ConnectionContract
13 13
 {
14 14
 
15
-	public function send(string $data): void;
15
+    public function send(string $data): void;
16 16
 
17
-	public function close(): void;
17
+    public function close(): void;
18 18
 
19
-	public function getUniqueSocketId(): int;
19
+    public function getUniqueSocketId(): int;
20 20
 
21
-	public function getPeerName(): string;
21
+    public function getPeerName(): string;
22 22
 
23
-	public function broadCast(string $data): void;
23
+    public function broadCast(string $data): void;
24 24
 
25
-	public function broadCastMany(array $data, int $delay): void;
25
+    public function broadCastMany(array $data, int $delay): void;
26 26
 
27 27
 }
Please login to merge, or discard this patch.
src/Enums/CurlInfo.php 1 patch
Indentation   +210 added lines, -210 removed lines patch added patch discarded remove patch
@@ -12,215 +12,215 @@
 block discarded – undo
12 12
 class CurlInfo
13 13
 {
14 14
 
15
-	/**
16
-	 * @var string
17
-	 */
18
-	public string $URL;
19
-
20
-	/**
21
-	 * @var string
22
-	 */
23
-	public string $CONTENT_TYPE;
24
-
25
-	/**
26
-	 * @var int
27
-	 */
28
-	public int $HTTP_CODE;
29
-
30
-	/**
31
-	 * @var int
32
-	 */
33
-	public int $HEADER_SIZE;
34
-
35
-	/**
36
-	 * @var int
37
-	 */
38
-	public int $REQUEST_SIZE;
39
-
40
-	/**
41
-	 * @var int
42
-	 */
43
-	public int $FILETIME;
44
-
45
-	/**
46
-	 * @var int
47
-	 */
48
-	public int $SSL_VERIFY_RESULT;
49
-
50
-	/**
51
-	 * @var int
52
-	 */
53
-	public int $REDIRECT_COUNT;
54
-
55
-	/**
56
-	 * @var float
57
-	 */
58
-	public float $TOTAL_TIME;
59
-
60
-	/**
61
-	 * @var float
62
-	 */
63
-	public float $NAMELOOKUP_TIME;
64
-
65
-	/**
66
-	 * @var float
67
-	 */
68
-	public float $CONNECT_TIME;
69
-
70
-	/**
71
-	 * @var float
72
-	 */
73
-	public float $PRETRANSFER_TIME;
74
-
75
-	/**
76
-	 * @var int
77
-	 */
78
-	public int $SIZE_UPLOAD;
79
-
80
-	/**
81
-	 * @var int
82
-	 */
83
-	public int $SIZE_DOWNLOAD;
84
-
85
-	/**
86
-	 * @var int
87
-	 */
88
-	public int $SPEED_DOWNLOAD;
89
-
90
-	/**
91
-	 * @var int
92
-	 */
93
-	public int $SPEED_UPLOAD;
94
-
95
-	/**
96
-	 * @var int
97
-	 */
98
-	public int $DOWNLOAD_CONTENT_LENGTH;
99
-
100
-	/**
101
-	 * @var int
102
-	 */
103
-	public int $UPLOAD_CONTENT_LENGTH;
104
-
105
-	/**
106
-	 * @var float
107
-	 */
108
-	public float $STARTTRANSFER_TIME;
109
-
110
-	/**
111
-	 * @var int
112
-	 */
113
-	public int $REDIRECT_TIME;
114
-
115
-	/**
116
-	 * @var string
117
-	 */
118
-	public string $REDIRECT_URL;
119
-
120
-	/**
121
-	 * @var string
122
-	 */
123
-	public string $PRIMARY_IP;
124
-
125
-	/**
126
-	 * @var array
127
-	 */
128
-	public array $CERTINFO;
129
-
130
-	/**
131
-	 * @var int
132
-	 */
133
-	public int $PRIMARY_PORT;
134
-
135
-	/**
136
-	 * @var string
137
-	 */
138
-	public string $LOCAL_IP;
139
-
140
-	/**
141
-	 * @var int
142
-	 */
143
-	public int $LOCAL_PORT;
144
-
145
-	/**
146
-	 * @var int
147
-	 */
148
-	public int $HTTP_VERSION;
149
-
150
-	/**
151
-	 * @var int
152
-	 */
153
-	public int $PROTOCOL;
154
-
155
-	/**
156
-	 * @var int
157
-	 */
158
-	public int $SSL_VERIFYRESULT;
159
-
160
-	/**
161
-	 * @var string
162
-	 */
163
-	public string $SCHEME;
164
-
165
-	/**
166
-	 * @var int
167
-	 */
168
-	public int $APPCONNECT_TIME_US;
169
-
170
-	/**
171
-	 * @var int
172
-	 */
173
-	public int $CONNECT_TIME_US;
174
-
175
-	/**
176
-	 * @var int
177
-	 */
178
-	public int $NAMELOOKUP_TIME_US;
179
-
180
-	/**
181
-	 * @var int
182
-	 */
183
-	public int $PRETRANSFER_TIME_US;
184
-
185
-	/**
186
-	 * @var int
187
-	 */
188
-	public int $REDIRECT_TIME_US;
189
-
190
-	/**
191
-	 * @var int
192
-	 */
193
-	public int $STARTTRANSFER_TIME_US;
194
-
195
-	/**
196
-	 * @var int
197
-	 */
198
-	public int $TOTAL_TIME_US;
199
-
200
-	/**
201
-	 * The Constructor
202
-	 *
203
-	 * @param array $curlInfo
204
-	 * @return void
205
-	 */
206
-	public function __construct(array $curlInfo = [])
207
-	{
208
-		$this->set($curlInfo);
209
-	}
210
-
211
-	/**
212
-	 * Set CurlInfo
213
-	 *
214
-	 * @param array $curlInfo
215
-	 * @return void
216
-	 */
217
-	public function set(array $curlInfo): void
218
-	{
219
-		foreach ($curlInfo as $key => $value) {
220
-			if (property_exists($this, strtoupper($key))) {
221
-				$this->{strtoupper($key)} = $value;
222
-			}
223
-		}
224
-	}
15
+    /**
16
+     * @var string
17
+     */
18
+    public string $URL;
19
+
20
+    /**
21
+     * @var string
22
+     */
23
+    public string $CONTENT_TYPE;
24
+
25
+    /**
26
+     * @var int
27
+     */
28
+    public int $HTTP_CODE;
29
+
30
+    /**
31
+     * @var int
32
+     */
33
+    public int $HEADER_SIZE;
34
+
35
+    /**
36
+     * @var int
37
+     */
38
+    public int $REQUEST_SIZE;
39
+
40
+    /**
41
+     * @var int
42
+     */
43
+    public int $FILETIME;
44
+
45
+    /**
46
+     * @var int
47
+     */
48
+    public int $SSL_VERIFY_RESULT;
49
+
50
+    /**
51
+     * @var int
52
+     */
53
+    public int $REDIRECT_COUNT;
54
+
55
+    /**
56
+     * @var float
57
+     */
58
+    public float $TOTAL_TIME;
59
+
60
+    /**
61
+     * @var float
62
+     */
63
+    public float $NAMELOOKUP_TIME;
64
+
65
+    /**
66
+     * @var float
67
+     */
68
+    public float $CONNECT_TIME;
69
+
70
+    /**
71
+     * @var float
72
+     */
73
+    public float $PRETRANSFER_TIME;
74
+
75
+    /**
76
+     * @var int
77
+     */
78
+    public int $SIZE_UPLOAD;
79
+
80
+    /**
81
+     * @var int
82
+     */
83
+    public int $SIZE_DOWNLOAD;
84
+
85
+    /**
86
+     * @var int
87
+     */
88
+    public int $SPEED_DOWNLOAD;
89
+
90
+    /**
91
+     * @var int
92
+     */
93
+    public int $SPEED_UPLOAD;
94
+
95
+    /**
96
+     * @var int
97
+     */
98
+    public int $DOWNLOAD_CONTENT_LENGTH;
99
+
100
+    /**
101
+     * @var int
102
+     */
103
+    public int $UPLOAD_CONTENT_LENGTH;
104
+
105
+    /**
106
+     * @var float
107
+     */
108
+    public float $STARTTRANSFER_TIME;
109
+
110
+    /**
111
+     * @var int
112
+     */
113
+    public int $REDIRECT_TIME;
114
+
115
+    /**
116
+     * @var string
117
+     */
118
+    public string $REDIRECT_URL;
119
+
120
+    /**
121
+     * @var string
122
+     */
123
+    public string $PRIMARY_IP;
124
+
125
+    /**
126
+     * @var array
127
+     */
128
+    public array $CERTINFO;
129
+
130
+    /**
131
+     * @var int
132
+     */
133
+    public int $PRIMARY_PORT;
134
+
135
+    /**
136
+     * @var string
137
+     */
138
+    public string $LOCAL_IP;
139
+
140
+    /**
141
+     * @var int
142
+     */
143
+    public int $LOCAL_PORT;
144
+
145
+    /**
146
+     * @var int
147
+     */
148
+    public int $HTTP_VERSION;
149
+
150
+    /**
151
+     * @var int
152
+     */
153
+    public int $PROTOCOL;
154
+
155
+    /**
156
+     * @var int
157
+     */
158
+    public int $SSL_VERIFYRESULT;
159
+
160
+    /**
161
+     * @var string
162
+     */
163
+    public string $SCHEME;
164
+
165
+    /**
166
+     * @var int
167
+     */
168
+    public int $APPCONNECT_TIME_US;
169
+
170
+    /**
171
+     * @var int
172
+     */
173
+    public int $CONNECT_TIME_US;
174
+
175
+    /**
176
+     * @var int
177
+     */
178
+    public int $NAMELOOKUP_TIME_US;
179
+
180
+    /**
181
+     * @var int
182
+     */
183
+    public int $PRETRANSFER_TIME_US;
184
+
185
+    /**
186
+     * @var int
187
+     */
188
+    public int $REDIRECT_TIME_US;
189
+
190
+    /**
191
+     * @var int
192
+     */
193
+    public int $STARTTRANSFER_TIME_US;
194
+
195
+    /**
196
+     * @var int
197
+     */
198
+    public int $TOTAL_TIME_US;
199
+
200
+    /**
201
+     * The Constructor
202
+     *
203
+     * @param array $curlInfo
204
+     * @return void
205
+     */
206
+    public function __construct(array $curlInfo = [])
207
+    {
208
+        $this->set($curlInfo);
209
+    }
210
+
211
+    /**
212
+     * Set CurlInfo
213
+     *
214
+     * @param array $curlInfo
215
+     * @return void
216
+     */
217
+    public function set(array $curlInfo): void
218
+    {
219
+        foreach ($curlInfo as $key => $value) {
220
+            if (property_exists($this, strtoupper($key))) {
221
+                $this->{strtoupper($key)} = $value;
222
+            }
223
+        }
224
+    }
225 225
 
226 226
 }
227 227
\ No newline at end of file
Please login to merge, or discard this patch.
src/Middleware.php 3 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -100,7 +100,7 @@
 block discarded – undo
100 100
 		curl_setopt($cHandler, CURLOPT_TIMEOUT, $options->getTimeout());
101 101
 
102 102
 		# If self-signed certs are allowed, set it.
103
-		if ((bool)getenv('HAS_SELF_SIGNED_CERT') === true) {
103
+		if ((bool) getenv('HAS_SELF_SIGNED_CERT') === true) {
104 104
 			curl_setopt($cHandler, CURLOPT_SSL_VERIFYPEER, false);
105 105
 			curl_setopt($cHandler, CURLOPT_SSL_VERIFYHOST, false);
106 106
 		}
Please login to merge, or discard this patch.
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -128,7 +128,9 @@
 block discarded – undo
128 128
 
129 129
 			$headers = [];
130 130
 			foreach ($options->getHeaders() as $header => $value) {
131
-				if (Toolkit::insensitiveString($header, 'content-type')) continue;
131
+				if (Toolkit::insensitiveString($header, 'content-type')) {
132
+				    continue;
133
+				}
132 134
 				$headers[] = $header . ': ' . $value;
133 135
 			}
134 136
 			$headers[] = 'Content-Type: multipart/form-data';
Please login to merge, or discard this patch.
Indentation   +187 added lines, -187 removed lines patch added patch discarded remove patch
@@ -17,192 +17,192 @@
 block discarded – undo
17 17
 class Middleware
18 18
 {
19 19
 
20
-	/**
21
-	 * Create curl handler.
22
-	 *
23
-	 * @param ?string $method
24
-	 * @param string $uri
25
-	 * @param array|HttpOptions $options
26
-	 *
27
-	 * @return \CurlHandle|false
28
-	 */
29
-	public static function create_curl_handler(?string $method, string $uri, array|HttpOptions $options = []): \CurlHandle|false
30
-	{
31
-		$handler = curl_init();
32
-		if (is_resource($handler) || !$handler) {
33
-			return false;
34
-		}
35
-
36
-		if (gettype($options) === 'array') {
37
-			$options = new HttpOptions($options);
38
-		}
39
-
40
-		if (count($options->getQuery()) > 0) {
41
-			if (!str_contains($uri, '?')) {
42
-				$uri .= '?';
43
-			}
44
-			$uri .= $options->getQueryString();
45
-		}
46
-
47
-		curl_setopt($handler, CURLOPT_URL, $uri);
48
-
49
-		self::set_curl_options($method, $handler, $options);
50
-
51
-		return $handler;
52
-	}
53
-
54
-	/**
55
-	 * Setup curl options based on the given method and our options.
56
-	 *
57
-	 * @param \CurlHandle $cHandler
58
-	 * @param ?string $method
59
-	 * @param HttpOptions $options
60
-	 *
61
-	 * @return void
62
-	 */
63
-	public static function set_curl_options(?string $method, \CurlHandle $cHandler, HttpOptions $options): void
64
-	{
65
-		curl_setopt($cHandler, CURLOPT_HEADER, true);
66
-		curl_setopt($cHandler, CURLOPT_CUSTOMREQUEST, $method ?? 'GET');
67
-
68
-		# Fetch the header
69
-		$fetchedHeaders = [];
70
-		foreach ($options->getHeaders() as $header => $value) {
71
-			$fetchedHeaders[] = $header . ': ' . $value;
72
-		}
73
-
74
-		# Set headers
75
-		curl_setopt($cHandler, CURLOPT_HTTPHEADER, $fetchedHeaders ?? []);
76
-
77
-		# Add body if we have one.
78
-		if ($options->getBody()) {
79
-			curl_setopt($cHandler, CURLOPT_CUSTOMREQUEST, $method ?? 'POST');
80
-			curl_setopt($cHandler, CURLOPT_POSTFIELDS, $options->getBody());
81
-			curl_setopt($cHandler, CURLOPT_POST, true);
82
-		}
83
-
84
-		# Check for a proxy
85
-		if ($options->getProxy() != null) {
86
-			curl_setopt($cHandler, CURLOPT_PROXY, $options->getProxy()->getHost());
87
-			curl_setopt($cHandler, CURLOPT_PROXYUSERPWD, $options->getProxy()->getAuth());
88
-			if ($options->getProxy()->type !== null) {
89
-				curl_setopt($cHandler, CURLOPT_PROXYTYPE, $options->getProxy()->type);
90
-			}
91
-		}
92
-
93
-		curl_setopt($cHandler, CURLOPT_RETURNTRANSFER, true);
94
-		curl_setopt($cHandler, CURLOPT_FOLLOWLOCATION, true);
95
-
96
-		# Add and override the custom curl options.
97
-		foreach ($options->getCurlOptions() as $option => $value) {
98
-			curl_setopt($cHandler, $option, $value);
99
-		}
100
-
101
-		# if we have a timeout, set it.
102
-		curl_setopt($cHandler, CURLOPT_TIMEOUT, $options->getTimeout());
103
-
104
-		# If self-signed certs are allowed, set it.
105
-		if ((bool)getenv('HAS_SELF_SIGNED_CERT') === true) {
106
-			curl_setopt($cHandler, CURLOPT_SSL_VERIFYPEER, false);
107
-			curl_setopt($cHandler, CURLOPT_SSL_VERIFYHOST, false);
108
-		}
109
-
110
-		(new Middleware())->handle_media($cHandler, $options);
111
-	}
112
-
113
-	/**
114
-	 * Handle the media
115
-	 *
116
-	 * @param \CurlHandle $handler
117
-	 * @param HttpOptions $options
118
-	 * @return void
119
-	 */
120
-	private function handle_media(\CurlHandle $handler, HttpOptions $options): void
121
-	{
122
-		if (count($options->getMultipart()) > 0) {
123
-			curl_setopt($handler, CURLOPT_POST, true);
124
-			curl_setopt($handler, CURLOPT_CUSTOMREQUEST, 'POST');
125
-
126
-			$form_data = new FormData();
127
-			foreach ($options->getMultipart() as $key => $value) {
128
-				$form_data->addFile($key, $value);
129
-			}
130
-
131
-			$headers = [];
132
-			foreach ($options->getHeaders() as $header => $value) {
133
-				if (Toolkit::insensitiveString($header, 'content-type')) continue;
134
-				$headers[] = $header . ': ' . $value;
135
-			}
136
-			$headers[] = 'Content-Type: multipart/form-data';
137
-
138
-			curl_setopt($handler, CURLOPT_HTTPHEADER, $headers);
139
-			curl_setopt($handler, CURLOPT_POSTFIELDS, $form_data->getFiles());
140
-		}
141
-	}
142
-
143
-	/**
144
-	 * @param mixed $socket
145
-	 * @param int $len
146
-	 * @return string|null
147
-	 * @throws ConnectionException
148
-	 */
149
-	public static function stream_read(mixed $socket, int $len): string|null
150
-	{
151
-		if (!is_resource($socket)) {
152
-			throw new ConnectionException(sprintf(
153
-				'%s is not a valid resource. Datatype: %s', $socket, gettype($socket)
154
-			));
155
-		}
156
-
157
-		$data = '';
158
-		while (($dataLen = strlen($data)) < $len) {
159
-			$buff = fread($socket, $len - $dataLen);
160
-
161
-			if ($buff === false) {
162
-				return null;
163
-			}
164
-
165
-			if ($buff === '') {
166
-				$metadata = stream_get_meta_data($socket);
167
-				throw new ConnectionException(
168
-					sprintf('Empty read; connection dead?  Stream state: %s', json_encode($metadata)),
169
-					CommonsContract::CLIENT_EMPTY_READ
170
-				);
171
-			}
172
-			$data .= $buff;
173
-		}
174
-
175
-		return $data;
176
-	}
177
-
178
-	/**
179
-	 * @param mixed $socket
180
-	 * @param string $data
181
-	 * @return bool
182
-	 * @throws ConnectionException
183
-	 */
184
-	public static function stream_write(mixed $socket, string $data): bool
185
-	{
186
-		if (!is_resource($socket)) {
187
-			throw new ConnectionException(sprintf(
188
-				'%s is not a valid resource. Datatype: %s', $socket, gettype($socket)
189
-			));
190
-		}
191
-
192
-		$written = fwrite($socket, $data);
193
-
194
-		if ($written < strlen($data)) {
195
-			throw new ConnectionException(
196
-				sprintf('Could only write %s out of %s bytes.', $written, strlen($data)),
197
-				CommonsContract::CLIENT_COULD_ONLY_WRITE_LESS
198
-			);
199
-		}
200
-
201
-		return true;
202
-	}
203
-
204
-	/**
205
-	 * Stream connect
206
-	 */
20
+    /**
21
+     * Create curl handler.
22
+     *
23
+     * @param ?string $method
24
+     * @param string $uri
25
+     * @param array|HttpOptions $options
26
+     *
27
+     * @return \CurlHandle|false
28
+     */
29
+    public static function create_curl_handler(?string $method, string $uri, array|HttpOptions $options = []): \CurlHandle|false
30
+    {
31
+        $handler = curl_init();
32
+        if (is_resource($handler) || !$handler) {
33
+            return false;
34
+        }
35
+
36
+        if (gettype($options) === 'array') {
37
+            $options = new HttpOptions($options);
38
+        }
39
+
40
+        if (count($options->getQuery()) > 0) {
41
+            if (!str_contains($uri, '?')) {
42
+                $uri .= '?';
43
+            }
44
+            $uri .= $options->getQueryString();
45
+        }
46
+
47
+        curl_setopt($handler, CURLOPT_URL, $uri);
48
+
49
+        self::set_curl_options($method, $handler, $options);
50
+
51
+        return $handler;
52
+    }
53
+
54
+    /**
55
+     * Setup curl options based on the given method and our options.
56
+     *
57
+     * @param \CurlHandle $cHandler
58
+     * @param ?string $method
59
+     * @param HttpOptions $options
60
+     *
61
+     * @return void
62
+     */
63
+    public static function set_curl_options(?string $method, \CurlHandle $cHandler, HttpOptions $options): void
64
+    {
65
+        curl_setopt($cHandler, CURLOPT_HEADER, true);
66
+        curl_setopt($cHandler, CURLOPT_CUSTOMREQUEST, $method ?? 'GET');
67
+
68
+        # Fetch the header
69
+        $fetchedHeaders = [];
70
+        foreach ($options->getHeaders() as $header => $value) {
71
+            $fetchedHeaders[] = $header . ': ' . $value;
72
+        }
73
+
74
+        # Set headers
75
+        curl_setopt($cHandler, CURLOPT_HTTPHEADER, $fetchedHeaders ?? []);
76
+
77
+        # Add body if we have one.
78
+        if ($options->getBody()) {
79
+            curl_setopt($cHandler, CURLOPT_CUSTOMREQUEST, $method ?? 'POST');
80
+            curl_setopt($cHandler, CURLOPT_POSTFIELDS, $options->getBody());
81
+            curl_setopt($cHandler, CURLOPT_POST, true);
82
+        }
83
+
84
+        # Check for a proxy
85
+        if ($options->getProxy() != null) {
86
+            curl_setopt($cHandler, CURLOPT_PROXY, $options->getProxy()->getHost());
87
+            curl_setopt($cHandler, CURLOPT_PROXYUSERPWD, $options->getProxy()->getAuth());
88
+            if ($options->getProxy()->type !== null) {
89
+                curl_setopt($cHandler, CURLOPT_PROXYTYPE, $options->getProxy()->type);
90
+            }
91
+        }
92
+
93
+        curl_setopt($cHandler, CURLOPT_RETURNTRANSFER, true);
94
+        curl_setopt($cHandler, CURLOPT_FOLLOWLOCATION, true);
95
+
96
+        # Add and override the custom curl options.
97
+        foreach ($options->getCurlOptions() as $option => $value) {
98
+            curl_setopt($cHandler, $option, $value);
99
+        }
100
+
101
+        # if we have a timeout, set it.
102
+        curl_setopt($cHandler, CURLOPT_TIMEOUT, $options->getTimeout());
103
+
104
+        # If self-signed certs are allowed, set it.
105
+        if ((bool)getenv('HAS_SELF_SIGNED_CERT') === true) {
106
+            curl_setopt($cHandler, CURLOPT_SSL_VERIFYPEER, false);
107
+            curl_setopt($cHandler, CURLOPT_SSL_VERIFYHOST, false);
108
+        }
109
+
110
+        (new Middleware())->handle_media($cHandler, $options);
111
+    }
112
+
113
+    /**
114
+     * Handle the media
115
+     *
116
+     * @param \CurlHandle $handler
117
+     * @param HttpOptions $options
118
+     * @return void
119
+     */
120
+    private function handle_media(\CurlHandle $handler, HttpOptions $options): void
121
+    {
122
+        if (count($options->getMultipart()) > 0) {
123
+            curl_setopt($handler, CURLOPT_POST, true);
124
+            curl_setopt($handler, CURLOPT_CUSTOMREQUEST, 'POST');
125
+
126
+            $form_data = new FormData();
127
+            foreach ($options->getMultipart() as $key => $value) {
128
+                $form_data->addFile($key, $value);
129
+            }
130
+
131
+            $headers = [];
132
+            foreach ($options->getHeaders() as $header => $value) {
133
+                if (Toolkit::insensitiveString($header, 'content-type')) continue;
134
+                $headers[] = $header . ': ' . $value;
135
+            }
136
+            $headers[] = 'Content-Type: multipart/form-data';
137
+
138
+            curl_setopt($handler, CURLOPT_HTTPHEADER, $headers);
139
+            curl_setopt($handler, CURLOPT_POSTFIELDS, $form_data->getFiles());
140
+        }
141
+    }
142
+
143
+    /**
144
+     * @param mixed $socket
145
+     * @param int $len
146
+     * @return string|null
147
+     * @throws ConnectionException
148
+     */
149
+    public static function stream_read(mixed $socket, int $len): string|null
150
+    {
151
+        if (!is_resource($socket)) {
152
+            throw new ConnectionException(sprintf(
153
+                '%s is not a valid resource. Datatype: %s', $socket, gettype($socket)
154
+            ));
155
+        }
156
+
157
+        $data = '';
158
+        while (($dataLen = strlen($data)) < $len) {
159
+            $buff = fread($socket, $len - $dataLen);
160
+
161
+            if ($buff === false) {
162
+                return null;
163
+            }
164
+
165
+            if ($buff === '') {
166
+                $metadata = stream_get_meta_data($socket);
167
+                throw new ConnectionException(
168
+                    sprintf('Empty read; connection dead?  Stream state: %s', json_encode($metadata)),
169
+                    CommonsContract::CLIENT_EMPTY_READ
170
+                );
171
+            }
172
+            $data .= $buff;
173
+        }
174
+
175
+        return $data;
176
+    }
177
+
178
+    /**
179
+     * @param mixed $socket
180
+     * @param string $data
181
+     * @return bool
182
+     * @throws ConnectionException
183
+     */
184
+    public static function stream_write(mixed $socket, string $data): bool
185
+    {
186
+        if (!is_resource($socket)) {
187
+            throw new ConnectionException(sprintf(
188
+                '%s is not a valid resource. Datatype: %s', $socket, gettype($socket)
189
+            ));
190
+        }
191
+
192
+        $written = fwrite($socket, $data);
193
+
194
+        if ($written < strlen($data)) {
195
+            throw new ConnectionException(
196
+                sprintf('Could only write %s out of %s bytes.', $written, strlen($data)),
197
+                CommonsContract::CLIENT_COULD_ONLY_WRITE_LESS
198
+            );
199
+        }
200
+
201
+        return true;
202
+    }
203
+
204
+    /**
205
+     * Stream connect
206
+     */
207 207
 
208 208
 }
209 209
\ No newline at end of file
Please login to merge, or discard this patch.