Completed
Push — master ( f81184...3aae6e )
by Andrii
04:04
created

Request   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 76.6%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
c 1
b 0
f 0
lcom 1
cbo 4
dl 0
loc 88
ccs 36
cts 47
cp 0.766
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A send() 0 17 2
A prepareContextOptions() 0 19 2
A convertContextOptions() 0 15 3
A composeHeaderLines() 0 15 4
1
<?php
2
/**
3
 * Tools to use API as ActiveRecord for Yii2
4
 *
5
 * @link      https://github.com/hiqdev/yii2-hiart
6
 * @package   yii2-hiart
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\hiart\stream;
12
13
use hiqdev\hiart\AbstractRequest;
14
use hiqdev\hiart\RequestErrorException;
15
use yii\helpers\ArrayHelper;
16
use yii\helpers\Inflector;
17
18
/**
19
 * PHP stream request implementation.
20
 *
21
 * @author Andrii Vasyliev <[email protected]>
22
 */
23
class Request extends AbstractRequest
24
{
25
    protected $responseClass = Response::class;
26
27
    public $defaultOptions = [
28
        'http' => [
29
            'ignore_errors' => true,
30
        ],
31
        'ssl' => [
32
            'verify_peer' => false,
33
        ],
34
    ];
35
36 2
    public function send($options = [])
37
    {
38
        try {
39 2
            $this->build();
40 2
            $context = stream_context_create($this->prepareContextOptions($options));
41 2
            $stream = fopen($this->getFullUri(), 'rb', false, $context);
42 2
            $responseContent = stream_get_contents($stream);
43
            // see http://php.net/manual/en/reserved.variables.httpresponseheader.php
44 2
            $responseHeaders = $http_response_header;
45 2
            fclose($stream);
46 2
        } catch (\Exception $e) {
47
            $errorInfo = ['request' => $this];
48
            throw new RequestErrorException($e->getMessage(), $errorInfo, $e->getCode(), $e);
0 ignored issues
show
Documentation introduced by
$errorInfo is of type array<string,this<hiqdev...rt\\stream\\Request>"}>, but the function expects a object<hiqdev\hiart\RequestInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$e is of type object<Exception>, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
49
        }
50
51 2
        return new $this->responseClass($this, $responseContent, $responseHeaders);
52
    }
53
54 2
    protected function prepareContextOptions($options)
55
    {
56
        $requestOptions = [
57
            'http' => [
58 2
                'protocol_version' => $this->version,
59 2
                'method' => $this->method,
60 2
                'header' => static::composeHeaderLines($this->headers),
61 2
            ],
62 2
        ];
63
64 2
        if (isset($this->body)) {
65
            $requestOptions['http']['content'] = $this->body;
66
        }
67
68 2
        $dbOptions = $this->convertContextOptions($this->getDb()->config);
0 ignored issues
show
Bug introduced by
Accessing config on the interface hiqdev\hiart\ConnectionInterface 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...
69 2
        $sendOptions = $this->convertContextOptions($options);
70
71 2
        return ArrayHelper::merge($this->defaultOptions, $dbOptions, $requestOptions, $sendOptions);
72
    }
73
74
    /**
75
     * Composes stream context options from raw options.
76
     * @param array $options raw options
77
     * @return array stream context options
78
     */
79 2
    protected function convertContextOptions(array $options)
80
    {
81 2
        $contextOptions = [];
82 2
        foreach ($options as $key => $value) {
83
            $section = 'http';
84
            if (strpos($key, 'ssl') === 0) {
85
                $section = 'ssl';
86
                $key = substr($key, 3);
87
            }
88
            $key = Inflector::underscore($key);
89
            $contextOptions[$section][$key] = $value;
90 2
        }
91
92 2
        return $contextOptions;
93
    }
94
95 2
    public static function composeHeaderLines($headers)
96
    {
97 2
        $result = [];
98 2
        foreach ($headers as $name => $values) {
99 2
            $name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $name)));
100 2
            if (is_string($values)) {
101 2
                $values = [$values];
102 2
            }
103 2
            foreach ($values as $value) {
104 2
                $result[] = "$name: $value";
105 2
            }
106 2
        }
107
108 2
        return $result;
109
    }
110
}
111