MultiCurl   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 35
c 1
b 0
f 0
dl 0
loc 119
rs 10
wmc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A makeRequests() 0 7 2
A __construct() 0 17 2
B addRequest() 0 34 7
A formatHeaders() 0 9 2
1
<?php
2
3
namespace Smoren\MultiCurl;
4
5
use RuntimeException;
6
7
/**
8
 * MultiCurl wrapper for making parallel HTTP requests
9
 * @author <[email protected]> Smoren
10
 */
11
class MultiCurl
12
{
13
    /**
14
     * @var int max parallel connections count
15
     */
16
    protected $maxConnections;
17
    /**
18
     * @var array<int, mixed> common CURL options for every request
19
     */
20
    protected $commonOptions = [];
21
    /**
22
     * @var array<string, string> common headers for every request
23
     */
24
    protected $commonHeaders = [];
25
    /**
26
     * @var array<string, array<int, mixed>> map of CURL options including headers by custom request ID
27
     */
28
    protected $requestsConfigMap = [];
29
30
    /**
31
     * MultiCurl constructor
32
     * @param int $maxConnections max parallel connections count
33
     * @param array<int, mixed> $commonOptions common CURL options for every request
34
     * @param array<string, string> $commonHeaders common headers for every request
35
     */
36
    public function __construct(
37
        int $maxConnections = 100,
38
        array $commonOptions = [],
39
        array $commonHeaders = []
40
    ) {
41
        $this->maxConnections = $maxConnections;
42
        $this->commonOptions = [
43
            CURLOPT_URL => '',
44
            CURLOPT_RETURNTRANSFER => 1,
45
            CURLOPT_ENCODING => ''
46
        ];
47
48
        foreach($commonOptions as $key => $value) {
49
            $this->commonOptions[$key] = $value;
50
        }
51
52
        $this->commonHeaders = $commonHeaders;
53
    }
54
55
    /**
56
     * Executes all the requests and returns their results map
57
     * @param bool $dataOnly if true: return only response body data, exclude status code and headers
58
     * @param bool $okOnly if true: return only responses with (200 <= status code < 300)
59
     * @return array<string, mixed> responses mapped by custom request IDs
60
     * @throws RuntimeException
61
     */
62
    public function makeRequests(bool $dataOnly = false, bool $okOnly = false): array
63
    {
64
        $runner = new MultiCurlRunner($this->requestsConfigMap, $this->maxConnections);
65
        $runner->run();
66
        $this->requestsConfigMap = [];
67
68
        return $dataOnly ? $runner->getResultData($okOnly) : $runner->getResult($okOnly);
69
    }
70
71
    /**
72
     * Adds new request to execute
73
     * @param string $requestId custom request ID
74
     * @param string $url URL for request
75
     * @param mixed $body body data (will be json encoded if array)
76
     * @param array<int, mixed> $options CURL request options
77
     * @param array<string, string> $headers request headers
78
     * @return self
79
     */
80
    public function addRequest(
81
        string $requestId,
82
        string $url,
83
        $body = null,
84
        array $options = [],
85
        array $headers = []
86
    ): self {
87
        foreach($this->commonOptions as $key => $value) {
88
            if(!array_key_exists($key, $options)) {
89
                $options[$key] = $value;
90
            }
91
        }
92
93
        foreach($this->commonHeaders as $key => $value) {
94
            if(!array_key_exists($key, $headers)) {
95
                $headers[$key] = $value;
96
            }
97
        }
98
99
        if(is_array($body)) {
100
            $body = json_encode($body);
101
        }
102
103
        if($body !== null) {
104
            /** @var string|numeric $body */
105
            $options[CURLOPT_POSTFIELDS] = strval($body);
106
        }
107
108
        $options[CURLOPT_HTTPHEADER] = $this->formatHeaders($headers);
109
        $options[CURLOPT_URL] = $url;
110
111
        $this->requestsConfigMap[$requestId] = $options;
112
113
        return $this;
114
    }
115
116
    /**
117
     * Formats headers from associative array
118
     * @param array<string, string> $headers request headers associative array
119
     * @return array<string> headers array to pass to curl_setopt_array
120
     */
121
    protected function formatHeaders(array $headers): array
122
    {
123
        $result = [];
124
125
        foreach($headers as $key => $value) {
126
            $result[] = "{$key}: {$value}";
127
        }
128
129
        return $result;
130
    }
131
}
132