Completed
Push — master ( 94d679...094d27 )
by Benjamin
02:02
created

Agent::__set()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
1
<?php
2
3
namespace CurlX;
4
5
/**
6
 * Class Agent
7
 * @package CurlX
8
 *
9
 * @property int $max_concurrent The maximum number of simultaneous connections allowed
10
 * @property int $maxConcurrent The maximum number of simultaneous connections allowed
11
 * @property string $url default url for requests
12
 * @property array $post array of default post data for requests
13
 * @property float $time running time of the agent
14
 * @property int $timeout default timeout (in msec) for requests
15
 * @property array $options default cUrl options for requests
16
 * @property array $headers default headers for requests
17
 * @property resource $handle cUrl Multi Handle
18
 * @property callable[] $listeners array of registered listeners which will be registered to newly created requests
19
 * @property array $response responses of the individual requests
20
 */
21
class Agent
22
{
23
    /**
24
     * @var array results
25
     */
26
    protected $result;
27
28
    /**
29
     * @var array responses
30
     */
31
    protected $response;
32
33
    /**
34
     * @var int The maximum number of simultaneous connections allowed
35
     */
36
    protected $maxConcurrent = 0;
37
38
    /**
39
     * @var RequestInterface[] array of Requests
40
     */
41
    protected $requests;
42
43
    /**
44
     * @var Request default request
45
     */
46
    protected $defaultRequest;
47
48
    /**
49
     * @var resource cUrl Multi Handle
50
     */
51
    protected $mh;
52
53
    /**
54
     * Agent constructor.
55
     * @param int $max_concurrent max current requests
56
     */
57
    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...
58
    {
59
        $this->setMaxConcurrent($max_concurrent);
60
        $this->defaultRequest = new Request();
61
    }
62
63
    /**
64
     * Magic setter function
65
     * @param string $name attribute to set
66
     * @param mixed $value the new value
67
     * @return void
68
     */
69
    public function __set($name, $value)
70
    {
71
        $c = Request::camelize($name);
72
        $m = "set$c";
73
        if (method_exists($this, $m)) {
74
            $this->$m($value);
75
        } else {
76
            $this->defaultRequest->__set($name, $value);
77
        }
78
    }
79
80
    /**
81
     * Magic getter function
82
     * @param string $name of the attribute to get
83
     * @return mixed the attribute's value
84
     */
85
    public function __get($name)
86
    {
87
        $c = Request::camelize($name);
88
        $m = "get$c";
89
        if (method_exists($this, $m)) {
90
            return $this->$m();
91
        } else {
92
            return $this->defaultRequest->__get($name);
93
        }
94
    }
95
96
    /**
97
     * Set the maximum number of concurrent requests
98
     * @param int $max_requests maximum concurrent requests
99
     */
100
    public function setMaxConcurrent($max_requests)
101
    {
102
        if ($max_requests > 0) {
103
            $this->maxConcurrent = $max_requests;
104
        }
105
    }
106
107
    /**
108
     * Get the currently set value of maxConcurrent
109
     * @return int maximum number of concurrent requests
110
     */
111
    public function getMaxConcurrent()
112
    {
113
        return $this->maxConcurrent;
114
    }
115
116
    /**
117
     * Adds a new request to the queue and returns it
118
     * this request will have its default options set to global options
119
     * @param null $url URL to send the request to
120
     * @return RequestInterface the newly added request object
121
     */
122
    public function newRequest($url = null)
123
    {
124
        $request = clone $this->defaultRequest;
125
        $request->url = $url;
126
        return $this->addRequest($request);
127
    }
128
129
    /**
130
     * Add a request to the request queue
131
     * @param RequestInterface $request the request to add
132
     * @return RequestInterface
133
     */
134
    public function addRequest(RequestInterface $request)
135
    {
136
        $this->requests[] = $request;
137
        return $request;
138
    }
139
140
    /**
141
     * Returns the Request object for a give cUrl handle
142
     * @param mixed $handle
143
     * @return RequestInterface request with handle
144
     */
145
    private function getRequestByHandle($handle)
146
    {
147
        foreach ($this->requests as $request) {
148
            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...
149
                return $request;
150
            }
151
        }
152
    }
153
154
    /**
155
     * Execute the request queue
156
     */
157
    public function execute()
158
    {
159
        $this->mh = curl_multi_init();
160
161
        foreach ($this->requests as $key => $request) {
162
            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...
163
            $request->startTimer();
164
            if ($key >= $this->maxConcurrent) {
165
                break;
166
            }
167
        }
168
169
        do {
170
            do {
171
                $mh_status = curl_multi_exec($this->mh, $active);
172
            } while ($mh_status == CURLM_CALL_MULTI_PERFORM);
173
            if ($mh_status != CURLM_OK) {
174
                break;
175
            }
176
177
            // a request just completed, find out which one
178
            while ($completed = curl_multi_info_read($this->mh)) {
179
                $request = $this->getRequestByHandle($completed['handle']);
180
                $request->callback($completed);
181
                curl_multi_remove_handle($this->mh, $completed['handle']);
182
183
                // TODO: Add the next request to the queue
184
            }
185
186
            usleep(15);
187
        } while ($active);
188
        curl_multi_close($this->mh);
189
    }
190
}
191