extractResponseHeadersAndBody()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Maztech\HttpClients;
4
5
use Maztech\Http\GraphRawResponse;
6
use Maztech\Exceptions\InstagramSDKException;
7
8
/**
9
 * Class InstagramCurlHttpClient
10
 *
11
 * @package Instagram
12
 */
13
class InstagramCurlHttpClient implements InstagramHttpClientInterface
14
{
15
    /**
16
     * @var string The client error message
17
     */
18
    protected $curlErrorMessage = '';
19
20
    /**
21
     * @var int The curl client error code
22
     */
23
    protected $curlErrorCode = 0;
24
25
    /**
26
     * @var string|boolean The raw response from the server
27
     */
28
    protected $rawResponse;
29
30
    /**
31
     * @var InstagramCurl Procedural curl as object
32
     */
33
    protected $instagramCurl;
34
35
    /**
36
     * @param InstagramCurl|null Procedural curl as object
0 ignored issues
show
Bug introduced by
The type Maztech\HttpClients\Procedural was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
     */
38
    public function __construct(InstagramCurl $instagramCurl = null)
39
    {
40
        $this->instagramCurl = $instagramCurl ?: new InstagramCurl();
41
    }
42
43
    /**
44
     * @inheritdoc
45
     */
46
    public function send($url, $method, $body, array $headers, $timeOut)
47
    {
48
        $this->openConnection($url, $method, $body, $headers, $timeOut);
49
        $this->sendRequest();
50
51
        if ($curlErrorCode = $this->instagramCurl->errno()) {
52
            throw new InstagramSDKException($this->instagramCurl->error(), $curlErrorCode);
53
        }
54
55
        // Separate the raw headers from the raw body
56
        list($rawHeaders, $rawBody) = $this->extractResponseHeadersAndBody();
57
58
        $this->closeConnection();
59
60
        return new GraphRawResponse($rawHeaders, $rawBody);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new Maztech\Http\...($rawHeaders, $rawBody) returns the type Maztech\Http\GraphRawResponse which is incompatible with the return type mandated by Maztech\HttpClients\Inst...ClientInterface::send() of Instagram\Http\GraphRawResponse.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
61
    }
62
63
    /**
64
     * Opens a new curl connection.
65
     *
66
     * @param string $url     The endpoint to send the request to.
67
     * @param string $method  The request method.
68
     * @param string $body    The body of the request.
69
     * @param array  $headers The request headers.
70
     * @param int    $timeOut The timeout in seconds for the request.
71
     */
72
    public function openConnection($url, $method, $body, array $headers, $timeOut)
73
    {
74
        $options = [
75
            CURLOPT_CUSTOMREQUEST => $method,
76
            CURLOPT_HTTPHEADER => $this->compileRequestHeaders($headers),
77
            CURLOPT_URL => $url,
78
            CURLOPT_CONNECTTIMEOUT => 10,
79
            CURLOPT_TIMEOUT => $timeOut,
80
            CURLOPT_RETURNTRANSFER => true, // Return response as string
81
            CURLOPT_HEADER => true, // Enable header processing
82
            CURLOPT_SSL_VERIFYHOST => 2,
83
            CURLOPT_SSL_VERIFYPEER => true,
84
            CURLOPT_CAINFO => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
85
        ];
86
87
        if ($method !== "GET") {
88
            $options[CURLOPT_POSTFIELDS] = $body;
89
        }
90
91
        $this->instagramCurl->init();
92
        $this->instagramCurl->setoptArray($options);
93
    }
94
95
    /**
96
     * Closes an existing curl connection
97
     */
98
    public function closeConnection()
99
    {
100
        $this->instagramCurl->close();
101
    }
102
103
    /**
104
     * Send the request and get the raw response from curl
105
     */
106
    public function sendRequest()
107
    {
108
        $this->rawResponse = $this->instagramCurl->exec();
109
    }
110
111
    /**
112
     * Compiles the request headers into a curl-friendly format.
113
     *
114
     * @param array $headers The request headers.
115
     *
116
     * @return array
117
     */
118
    public function compileRequestHeaders(array $headers)
119
    {
120
        $return = [];
121
122
        foreach ($headers as $key => $value) {
123
            $return[] = $key . ': ' . $value;
124
        }
125
126
        return $return;
127
    }
128
129
    /**
130
     * Extracts the headers and the body into a two-part array
131
     *
132
     * @return array
133
     */
134
    public function extractResponseHeadersAndBody()
135
    {
136
        $parts = explode("\r\n\r\n", $this->rawResponse);
0 ignored issues
show
Bug introduced by
It seems like $this->rawResponse can also be of type boolean; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
        $parts = explode("\r\n\r\n", /** @scrutinizer ignore-type */ $this->rawResponse);
Loading history...
137
        $rawBody = array_pop($parts);
138
        $rawHeaders = implode("\r\n\r\n", $parts);
139
140
        return [trim($rawHeaders), trim($rawBody)];
141
    }
142
}
143