Passed
Push — master ( 700166...f06841 )
by Benjamin
03:07
created

Agent   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 25
c 6
b 0
f 0
lcom 1
cbo 2
dl 0
loc 154
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setMaxConcurrent() 0 6 2
A setOptions() 0 6 2
A setHeaders() 0 6 2
A setTimeout() 0 6 2
A newRequest() 0 4 1
B addRequest() 0 11 5
A getRequestByHandle() 0 8 3
C execute() 0 31 7
1
<?php
2
3
namespace CurlX;
4
5
class Agent
6
{
7
    protected $maxConcurrent = 0; //max. number of simultaneous connections allowed
8
    protected $options = []; //shared cURL options
9
    protected $headers = []; //shared cURL request headers
10
    protected $timeout = 5000; //timeout used for curl_multi_select function
11
    protected $post = [];
12
    protected $startTime;
13
    protected $endTime;
14
15
    // TODO: normalize headers key => value is key: value
16
17
    /**
18
     * @var RequestInterface[] $requests array of Requests
19
     */
20
    protected $requests;
21
22
    /**
23
     * @var callable[] $listeners array of listeners
24
     */
25
    protected $listeners = [];
26
    protected $mh;
27
28
    /**
29
     * Agent constructor.
30
     * @param int $max_concurrent max current requests
31
     */
32
    function __construct($max_concurrent = 10)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
33
    {
34
        $this->setMaxConcurrent($max_concurrent);
35
    }
36
37
    /**
38
     * Set the maximum number of concurrent requests
39
     * @param int $max_requests maximum concurrent requests
40
     */
41
    public function setMaxConcurrent($max_requests)
42
    {
43
        if ($max_requests > 0) {
44
            $this->maxConcurrent = $max_requests;
45
        }
46
    }
47
48
    /**
49
     * Set global cUrl options
50
     * @param array $options array of options
51
     */
52
    public function setOptions(array $options)
53
    {
54
        if(!empty($options)) {
55
            $this->options += $options;
56
        }
57
    }
58
59
    /**
60
     * Set global cUrl headers
61
     * @param array $headers headers
62
     */
63
    public function setHeaders(array $headers)
64
    {
65
        if (!empty($headers)) {
66
            $this->headers += $headers;
67
        }
68
    }
69
70
    /**
71
     * Set global timeout
72
     * If individual requests don't have a timeout value, this will be used
73
     * @param int $timeout timeout in msec
74
     */
75
    public function setTimeout($timeout)
76
    {
77
        if ($timeout > 0) {
78
            $this->timeout = $timeout; // to seconds
79
        }
80
    }
81
82
    /**
83
     * Adds a new request to the queue and returns it
84
     * this request will have its default options set to global options
85
     * @param null $url URL to send the request to
86
     * @return RequestInterface the newly added request object
87
     */
88
    public function newRequest($url = null)
89
    {
90
        return $this->addRequest(new Request($url), true);
91
    }
92
93
    /**
94
     * Add a request to the request queue
95
     * @param RequestInterface $request the request to add
96
     * @return RequestInterface
97
     */
98
    public function addRequest(RequestInterface $request, $setGlobals = false)
99
    {
100
        $this->requests = $request;
0 ignored issues
show
Documentation Bug introduced by
It seems like $request of type object<CurlX\RequestInterface> is incompatible with the declared type array<integer,object<CurlX\RequestInterface>> of property $requests.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
101
        if($setGlobals) {
102
            if(!empty($this->post)) $request->post = $this->post;
0 ignored issues
show
Bug introduced by
Accessing post on the interface CurlX\RequestInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
103
            if(!empty($this->headers)) $request->headers = $this->headers;
0 ignored issues
show
Bug introduced by
Accessing headers on the interface CurlX\RequestInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
104
            if(!empty($this->options)) $request->options = $this->options;
0 ignored issues
show
Bug introduced by
Accessing options on the interface CurlX\RequestInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
105
            $request->timeout = $this->timeout;
0 ignored issues
show
Bug introduced by
Accessing timeout on the interface CurlX\RequestInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
106
        }
107
        return $request;
108
    }
109
110
    /**
111
     * Returns the Request object for a give cUrl handle
112
     * @param mixed $handle
113
     * @return RequestInterface request with handle
114
     */
115
    private function getRequestByHandle($handle)
116
    {
117
        foreach($this->requests as $request) {
118
            if($request->handle === $handle) {
0 ignored issues
show
Bug introduced by
Accessing handle on the interface CurlX\RequestInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
119
                return $request;
120
            }
121
        }
122
    }
123
124
    /**
125
     * Execute the request queue
126
     */
127
    public function execute()
128
    {
129
        $this->mh = curl_multi_init();
130
131
        foreach($this->requests as $key => $request) {
132
            curl_multi_add_handle($this->mh, $request->handle);
0 ignored issues
show
Bug introduced by
Accessing handle on the interface CurlX\RequestInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
133
            $request->startTimer();
134
            if($key >= $this->maxConcurrent) break;
135
        }
136
137
        do{
138
            do{
139
                $mh_status = curl_multi_exec($this->mh, $active);
140
            } while($mh_status == CURLM_CALL_MULTI_PERFORM);
141
            if($mh_status != CURLM_OK) {
142
                break;
143
            }
144
145
            // a request just completed, find out which one
146
            while($completed = curl_multi_info_read($this->mh)) {
147
                $request = $this->getRequestByHandle($completed['handle']);
148
                $request->callback($completed);
149
                curl_multi_remove_handle($this->mh, $completed['handle']);
150
151
                // TODO: Add the next request to the queue
152
            }
153
154
            usleep(15);
155
        } while ($active);
156
        curl_multi_close($this->mh);
157
    }
158
}
159
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...