Completed
Pull Request — master (#18)
by Stéphane
34:14 queued 14:42
created

CurlHandle::prepare()   C

Complexity

Conditions 11
Paths 204

Size

Total Lines 57
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 42
CRAP Score 11.1457

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 0
loc 57
ccs 42
cts 47
cp 0.8936
rs 5.9074
cc 11
eloc 41
nc 204
nop 1
crap 11.1457

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of the bee4/transport package.
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 *
7
 * @copyright Bee4 2015
8
 * @author  Stephane HULARD <[email protected]>
9
 * @package Bee4\Transport\Handle
10
 */
11
12
namespace Bee4\Transport\Handle;
13
14
use Bee4\Transport\Message\Request\AbstractRequest;
15
use Bee4\Transport\Configuration;
16
use Bee4\Transport\Exception\Curl\ExceptionFactory;
17
use Bee4\Transport\Exception\RuntimeException;
18
19
/**
20
 * Define cURL handle wrapper
21
 * @package Bee4\Transport\Handle
22
 */
23
class CurlHandle implements HandleInterface
24
{
25
    /**
26
     * cURL resource handle
27
     * @var resource
28
     */
29
    protected $handle;
30
31
    /**
32
     * Option collection used for the current request
33
     * @var array
34
     */
35
    protected $options = [];
36
37
    /**
38
     * Initialize cURL resource
39
     */
40 9
    public function __construct()
41
    {
42
        // @codeCoverageIgnoreStart
43
        if (!extension_loaded('curl')) {
44
            throw new RuntimeException('The PHP cURL extension must be installed!');
45
        }
46
        // @codeCoverageIgnoreEnd
47
48 9
        $this->setDefaults();
49 9
        $this->open();
50 9
    }
51
52
    /**
53
     * Set default CURL options
54
     */
55 14
    private function setDefaults()
56
    {
57 14
        $this->options = [
58 14
            CURLOPT_RETURNTRANSFER => true,
59 14
            CURLOPT_FOLLOWLOCATION => true,
60 14
            CURLOPT_HEADER => true,
61 14
            CURLINFO_HEADER_OUT => true
62 14
        ];
63 14
    }
64
65
    /**
66
     * Handle destructor
67
     * @codeCoverageIgnore
68
     */
69
    public function __destruct()
70
    {
71
        $this->close();
72
    }
73
74
    /**
75
     * Open the curl handle to be used
76
     * @return Handle
77
     */
78 9
    public function open()
79
    {
80 9
        if (!is_resource($this->handle)) {
81 9
            $this->handle = curl_init();
82 9
        }
83 9
        return $this;
84
    }
85
86
    /**
87
     * Close currently opened handle
88
     * @return Handle
89
     */
90 1
    public function close()
91
    {
92 1
        if (is_resource($this->handle)) {
93 1
            curl_close($this->handle);
94 1
        }
95 1
        $this->handle = null;
96 1
        return $this;
97
    }
98
99
    /**
100
     * Prepare the handle to be configured
101
     * @param Configuration\Configuration $config
0 ignored issues
show
Bug introduced by
There is no parameter named $config. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
102
     */
103 11
    public function prepare(AbstractRequest $request)
104
    {
105 11
        $config = $request->getOptions();
106
107 11
        $this->options[CURLOPT_URL] = (string)$config->url;
0 ignored issues
show
Documentation introduced by
The property url does not exist on object<Bee4\Transport\Co...guration\Configuration>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
108 11
        $this->options[CURLOPT_UPLOAD] = (bool)$config->upload;
0 ignored issues
show
Documentation introduced by
The property upload does not exist on object<Bee4\Transport\Co...guration\Configuration>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
109 11
        $this->options[CURLOPT_HTTPHEADER] = $request->getHeaderLines();
110
111 11
        if ($config instanceof Configuration\HttpConfiguration) {
112 9
            switch ($config->method) {
0 ignored issues
show
Documentation introduced by
The property method does not exist on object<Bee4\Transport\Co...tion\HttpConfiguration>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
113 9
                case 'GET':
114 4
                    $this->options[CURLOPT_HTTPGET] = true;
115 4
                    break;
116 6
                case 'PUT':
117 2
                    if (is_resource($config->body)) {
0 ignored issues
show
Documentation introduced by
The property body does not exist on object<Bee4\Transport\Co...tion\HttpConfiguration>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
118 1
                        $this->options[CURLOPT_PUT] = true;
119 1
                    } else {
120 1
                        $this->options[CURLOPT_CUSTOMREQUEST] = 'PUT';
121
                    }
122 2
                    break;
123 4
                default:
124 4
                    $this->options[CURLOPT_CUSTOMREQUEST] = $config->method;
0 ignored issues
show
Documentation introduced by
The property method does not exist on object<Bee4\Transport\Co...tion\HttpConfiguration>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
125 9
            }
126
127 9
            if ($config->redirectsAllowed()) {
128 9
                $this->options[CURLOPT_AUTOREFERER] = $config->allowRedirectsReferer();
129 9
                $this->options[CURLOPT_MAXREDIRS] = $config->allowRedirectsMax();
130 9
            } else {
131
                $this->options[CURLOPT_FOLLOWLOCATION] = false;
132
            }
133
134 9
            if (null !== $config->accept_encoding) {
0 ignored issues
show
Documentation introduced by
The property accept_encoding does not exist on object<Bee4\Transport\Co...tion\HttpConfiguration>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
135
                $this->options[CURLOPT_ENCODING] = $config->accept_encoding;
0 ignored issues
show
Documentation introduced by
The property accept_encoding does not exist on object<Bee4\Transport\Co...tion\HttpConfiguration>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
136
            }
137 9
        }
138 11
        if ($config instanceof Configuration\FtpConfiguration) {
139 1
            $this->options[CURLOPT_FTP_USE_EPSV] = $config->passive;
0 ignored issues
show
Documentation introduced by
The property passive does not exist on object<Bee4\Transport\Co...ation\FtpConfiguration>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
140 1
            $this->options[CURLOPT_QUOTE] = $config->commandsRequest();
141 1
            $this->options[CURLOPT_POSTQUOTE] = $config->commandsPost();
142 1
        }
143 11
        if ($config instanceof Configuration\SshConfiguration) {
144
            $this->options[CURLOPT_POSTQUOTE] = $config->commandsPost();
145
        }
146
147 11
        if ($config->hasBody()) {
148 8
            $body = $config->body;
0 ignored issues
show
Documentation introduced by
The property body does not exist on object<Bee4\Transport\Co...guration\Configuration>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
149 8
            if (is_resource($body)) {
150 1
                $this->options[CURLOPT_INFILE] = $body;
151 1
                $md = stream_get_meta_data($body);
152 1
                $this->options[CURLOPT_INFILESIZE] = filesize($md['uri']);
153 1
            } else {
154 7
                $this->options[CURLOPT_POSTFIELDS] = $body;
155
            }
156 8
        } else {
157 4
            $this->options[CURLOPT_NOBODY] = true;
158
        }
159 11
    }
160
161
    /**
162
     * Execute current handle and return result
163
     * @throws RuntimeException
164
     * @throws CurlException
165
     * @return string
166
     */
167 13
    public function execute()
168
    {
169 13
        if (!is_resource($this->handle)) {
170 1
            throw new RuntimeException('Curl handle has been closed, just open it before execute...');
171
        }
172
173 12
        curl_setopt_array($this->handle, array_filter($this->options));
174 12
        $return = curl_exec($this->handle);
175 12
        $this->infos = curl_getinfo($this->handle);
0 ignored issues
show
Bug introduced by
The property infos does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
176
177 12
        if ($return === false) {
178 2
            throw ExceptionFactory::build(
179 2
                curl_errno($this->handle),
180 2
                curl_error($this->handle)
181 2
            );
182
        }
183
184 10
        return $return;
185
    }
186
187
    /**
188
     * Check PHP version and reset handle option if possible
189
     * @return boolean
190
     */
191 5
    public function reset()
192
    {
193 5
        if (is_resource($this->handle) && function_exists('curl_reset')) {
194 5
            curl_reset($this->handle);
195 5
            $this->setDefaults();
196 5
            return true;
197
        } else {
198
            trigger_error('You must upgrade to PHP5.5 to use `curl_reset`', E_USER_NOTICE);
199
        }
200
201
        return false;
202
    }
203
204
    /**
205
     * Retrieve ExecutionInfos details
206
     * @return ExecutionInfos
207
     */
208 11
    public function infos()
209
    {
210 11
        return (new ExecutionInfos($this))
0 ignored issues
show
Documentation Bug introduced by
The method status does not exist on object<Bee4\Transport\Handle\ExecutionInfos>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
211 11
            ->status(curl_getinfo($this->handle, CURLINFO_HTTP_CODE))
212 11
            ->headers(curl_getinfo($this->handle, CURLINFO_HEADER_OUT))
213 11
            ->effectiveUrl(curl_getinfo($this->handle, CURLINFO_EFFECTIVE_URL))
214 11
            ->transactionTime(curl_getinfo($this->handle, CURLINFO_TOTAL_TIME));
215
    }
216
}
217