Completed
Push — master ( 470970...a080c6 )
by
unknown
05:31
created

CurlAdapter::setOpts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 3
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
namespace FacebookAds\Http\Adapter;
26
27
use FacebookAds\Exception\Exception;
28
use FacebookAds\Http\Adapter\Curl\AbstractCurl;
29
use FacebookAds\Http\Adapter\Curl\Curl;
30
use FacebookAds\Http\Adapter\Curl\CurlInterface;
31
use FacebookAds\Http\Client;
32
use FacebookAds\Http\Headers;
33
use FacebookAds\Http\RequestInterface;
34
use FacebookAds\Http\ResponseInterface;
35
36
class CurlAdapter extends AbstractAdapter {
37
38
  /**
39
   * @var CurlInterface
40
   */
41
  protected $curl;
42
43
  /**
44
   * @var \ArrayObject
45
   */
46
  protected $opts;
47
48
  /**
49
   * @param Client $client
50
   * @param CurlInterface $curl
51
   */
52 4
  public function __construct(Client $client, CurlInterface $curl = null) {
53 4
    parent::__construct($client);
54 4
    $this->curl = $curl ?: AbstractCurl::createOptimalVersion();
55 4
    $this->curl->init();
56 4
  }
57
58
  /**
59
   * @return Curl
60
   */
61 2
  public function getCurl() {
62 2
    return $this->curl;
63
  }
64
65
  /**
66
   * @return \ArrayObject
67
   */
68 2
  public function getOpts() {
69 2
    if ($this->opts === null) {
70 2
      $this->opts = new \ArrayObject(array(
71 2
        CURLOPT_CONNECTTIMEOUT => 10,
72 2
        CURLOPT_TIMEOUT => 60,
73 2
        CURLOPT_RETURNTRANSFER => true,
74 2
        CURLOPT_HEADER => true,
75 2
        CURLOPT_CAINFO => $this->getCaBundlePath(),
76 2
      ));
77 2
    }
78
79 2
    return $this->opts;
80
  }
81
82
  /**
83
   * @param \ArrayObject $opts
84
   */
85 1
  public function setOpts(\ArrayObject $opts) {
86 1
    $this->opts = $opts;
87 1
  }
88
89
  /**
90
   * @return int
91
   */
92 1
  protected function getheaderSize() {
93 1
    return $this->getCurl()->getInfo(CURLINFO_HEADER_SIZE);
94
  }
95
96
  /**
97
   * Extracts the headers and the body into a two-part array
98
   * @param string $raw_response
99
   * @return array
100
   */
101 1
  protected function extractResponseHeadersAndBody($raw_response) {
102 1
    $header_size = $this->getheaderSize();
103
104 1
    $raw_headers = mb_substr($raw_response, 0, $header_size);
105 1
    $raw_body = mb_substr($raw_response, $header_size);
106
107 1
    return array(trim($raw_headers), trim($raw_body));
108
  }
109
110
  /**
111
   * @param Headers $headers
112
   * @param string $raw_headers
113
   */
114 1
  protected function parseHeaders(Headers $headers, $raw_headers) {
115 1
    $raw_headers = str_replace("\r\n", "\n", $raw_headers);
116
117
    // There will be multiple headers if a 301 was followed
118
    // or a proxy was followed, etc
119 1
    $header_collection = explode("\n\n", trim($raw_headers));
120
    // We just want the last response (at the end)
121 1
    $raw_headers = array_pop($header_collection);
122
123 1
    $header_components = explode("\n", $raw_headers);
124 1
    foreach ($header_components as $line) {
125 1
      if (strpos($line, ': ') === false) {
126 1
        $headers['http_code'] = $line;
127 1
      } else {
128 1
        list ($key, $value) = explode(': ', $line);
129 1
        $headers[$key] = $value;
130
      }
131 1
    }
132 1
  }
133
134
  /**
135
   * @param RequestInterface $request
136
   * @return ResponseInterface
137
   * @throws Exception
138
   */
139 1
  public function sendRequest(RequestInterface $request) {
140 1
    $response = $this->getClient()->createResponse();
141 1
    $this->getCurl()->reset();
142
    $curlopts = array(
143 1
      CURLOPT_URL => $request->getUrl(),
144 1
    );
145
146 1
    $method = $request->getMethod();
147
    if ($method !== RequestInterface::METHOD_GET
148 1
      && $method !== RequestInterface::METHOD_POST) {
149 1
      $curlopts[CURLOPT_CUSTOMREQUEST] = $method;
150 1
    }
151
152 1
    $curlopts = $this->getOpts()->getArrayCopy() + $curlopts;
153
154 1
    if ($request->getHeaders()->count()) {
155 1
      $headers = array();
156 1
      foreach ($request->getHeaders() as $header => $value) {
157 1
        $headers[] = "{$header}: {$value}";
158 1
      }
159 1
      $curlopts[CURLOPT_HTTPHEADER] = $headers;
160 1
    }
161
162 1
    $postfields = array();
163
    if ($method === RequestInterface::METHOD_POST
164 1
      && $request->getFileParams()->count()
165 1
    ) {
166 1
      $postfields = array_merge(
167 1
        $postfields,
168 1
        array_map(
169 1
          array($this->getCurl(), 'preparePostFileField'),
170 1
          $request->getFileParams()->getArrayCopy()));
171 1
    }
172
    if ($method !== RequestInterface::METHOD_GET
173 1
      && $request->getBodyParams()->count()) {
174
      $postfields
175 1
        = array_merge($postfields, $request->getBodyParams()->export());
176 1
    }
177
178 1
    if (!empty($postfields)) {
179 1
      $curlopts[CURLOPT_POSTFIELDS] = $postfields;
180 1
    }
181
182 1
    $this->getCurl()->setoptArray($curlopts);
183 1
    $raw_response = $this->getCurl()->exec();
184
185 1
    $status_code = $this->getCurl()->getInfo(CURLINFO_HTTP_CODE);
186 1
    $curl_errno = $this->getCurl()->errno();
187 1
    $curl_error = $curl_errno ? $this->getCurl()->error() : null;
188
189 1
    $response_parts = $this->extractResponseHeadersAndBody($raw_response);
190
191 1
    $response->setStatusCode($status_code);
192 1
    $this->parseHeaders($response->getHeaders(), $response_parts[0]);
193 1
    $response->setBody($response_parts[1]);
194
195 1
    if ($curl_errno) {
196 1
      throw new Exception($curl_error, $curl_errno);
197
    }
198
199 1
    return $response;
200
  }
201
}
202