CurlClient   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 5
Bugs 2 Features 2
Metric Value
wmc 15
c 5
b 2
f 2
lcom 0
cbo 1
dl 0
loc 117
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B makeCall() 0 46 5
C parseHttpHeaders() 0 29 7
A processRequestHeaders() 0 16 3
1
<?php
2
3
/**
4
 * This file is part of the PHP SDK library for the Superdesk Content API.
5
 *
6
 * Copyright 2015 Sourcefabric z.u. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú.
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace Superdesk\ContentApiSdk\Client;
16
17
use Superdesk\ContentApiSdk\ContentApiSdk;
18
use Superdesk\ContentApiSdk\Exception\ClientException;
19
20
/**
21
 * Request service that implements functionality for basic http requests using
22
 * curl.
23
 */
24
class CurlClient implements ClientInterface
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function makeCall(
30
        $url,
31
        array $headers = array(),
32
        array $options = array(),
33
        $method = 'GET',
34
        $content = null
35
    ) {
36
        $curlOptions = array(
37
            CURLOPT_URL => $url,
38
            CURLOPT_HTTPHEADER => $this->processRequestHeaders($headers),
39
            CURLOPT_FOLLOWLOCATION => true,
40
            CURLOPT_HEADER => true,
41
            CURLOPT_TIMEOUT => 30,
42
            CURLOPT_USERAGENT => ContentApiSdk::USERAGENT,
43
            CURLOPT_RETURNTRANSFER => true,
44
        );
45
46
        if (strtoupper($method) == 'POST') {
47
            $curlOptions[CURLOPT_POST] = true;
48
            $curlOptions[CURLOPT_POSTFIELDS] = $content;
49
        }
50
51
        $curlHandler = curl_init();
52
        if (!$curlHandler) {
53
            throw new ClientException('Could not instantiate cURL.');
54
        }
55
56
        curl_setopt_array($curlHandler, $curlOptions);
57
        $response = curl_exec($curlHandler);
58
59
        if ($response === false) {
60
            throw new ClientException(sprintf('%s (%s)', 'A cURL error occured.', curl_error($curlHandler)), curl_errno($curlHandler));
61
        }
62
63
        $header_size = curl_getinfo($curlHandler, CURLINFO_HEADER_SIZE);
64
65
        $responseArray = array(
66
            'headers' => $this->parseHttpHeaders(mb_substr($response, 0, $header_size)),
67
            'status' => (int) curl_getinfo($curlHandler, CURLINFO_HTTP_CODE),
68
            'body' => (mb_strlen($response) > $header_size) ? mb_substr($response, $header_size) : ''
69
        );
70
71
        curl_close($curlHandler);
72
73
        return $responseArray;
74
    }
75
76
    /**
77
     * Parse header string from Curl request and returns an array. Based on:
78
     *     http://php.net/manual/en/function.http-parse-headers.php#112986
79
     *     http://php.net/manual/en/function.http-parse-headers.php#112987
80
     *
81
     * @param  string $headerString
82
     *
83
     * @return array
84
     */
85
    private function parseHttpHeaders($headerString)
86
    {
87
        $headers = array();
88
        $key = '';
89
90
        foreach (explode("\n", $headerString) as $i => $h) {
91
            $h = explode(':', $h, 2);
92
93
            if (isset($h[1])) {
94
                if (!isset($headers[$h[0]])) {
95
                    $headers[$h[0]] = trim($h[1]);
96
                } elseif (is_array($headers[$h[0]])) {
97
                    $headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1])));
98
                } else {
99
                    $headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1])));
100
                }
101
102
                $key = $h[0];
103
            } else {
104
                if (substr($h[0], 0, 1) == "\t") {
105
                    $headers[$key] .= "\r\n\t" . trim($h[0]);
106
                } elseif (!$key) {
107
                    $headers[0] = trim($h[0]);
108
                }
109
            }
110
        }
111
112
        return $headers;
113
    }
114
115
    /**
116
     * Convert headers in key => value format, to cURL accepted header format.
117
     *
118
     * @param  string[] $headers Headers in key => value format, if key is
119
     *                           numeric only the value will be stored in the
120
     *                           new array.
121
     *
122
     * @return string[]
123
     */
124
    private function processRequestHeaders(array $headers)
125
    {
126
        $curlHeaders = array();
127
128
        foreach ($headers as $name => $value) {
129
            if (!is_numeric($name)) {
130
                $header = sprintf('%s: %s', $name, $value);
131
            } else {
132
                $header = $value;
133
            }
134
135
            $curlHeaders[] = $header;
136
        }
137
138
        return $curlHeaders;
139
    }
140
}
141