Passed
Push — master ( 0deb8f...f54565 )
by Goffy
04:13
created

StreamClient   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 104
rs 10
c 0
b 0
f 0
wmc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 34 5
A setupRequest() 0 4 1
B fileGetContents() 0 32 6
A __construct() 0 3 1
1
<?php
2
3
namespace XoopsModules\Wggithub\Github\Http;
4
5
6
/**
7
 * Client which use the file_get_contents() with a HTTP context options.
8
 *
9
 * @author  Miloslav Hůla (https://github.com/milo)
10
 */
11
class StreamClient extends AbstractClient
12
{
13
	/** @var array|NULL */
14
	private $sslOptions;
15
16
17
	/**
18
	 * @param  array  SSL context options {@link http://php.net/manual/en/context.ssl.php}
0 ignored issues
show
Bug introduced by
The type XoopsModules\Wggithub\Github\Http\SSL 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...
19
	 */
20
	public function __construct(array $sslOptions = NULL)
21
	{
22
		$this->sslOptions = $sslOptions;
23
	}
24
25
26
	protected function setupRequest(Request $request)
27
	{
28
		parent::setupRequest($request);
29
		$request->setHeader('Connection', 'close');
30
	}
31
32
33
	/**
34
	 * @return Response
35
	 *
36
	 * @throws BadResponseException
37
	 */
38
	protected function process(Request $request)
39
	{
40
		$headerStr = [];
41
		foreach ($request->getHeaders() as $name => $value) {
42
			foreach ((array) $value as $v) {
43
				$headerStr[] = "$name: $v";
44
			}
45
		}
46
47
		$options = [
48
			'http' => [
49
				'method' => $request->getMethod(),
50
				'header' => implode("\r\n", $headerStr) . "\r\n",
51
				'follow_location' => 0,  # Github sets the Location header for 201 code too and redirection is not required for us
52
				'protocol_version' => 1.1,
53
				'ignore_errors' => TRUE,
54
			],
55
			'ssl' => [
56
				'verify_peer' => TRUE,
57
				'cafile' => realpath(__DIR__ . '/../../ca-chain.crt'),
58
				'disable_compression' => TRUE,  # Effective since PHP 5.4.13
59
			],
60
		];
61
62
		if (($content = $request->getContent()) !== NULL) {
63
			$options['http']['content'] = $content;
64
		}
65
66
		if ($this->sslOptions) {
67
			$options['ssl'] = $this->sslOptions + $options['ssl'];
68
		}
69
70
		list($code, $headers, $content) = $this->fileGetContents($request->getUrl(), $options);
71
		return new Response($code, $headers, $content);
72
	}
73
74
75
	/**
76
	 * @internal
77
	 * @param  string
78
	 * @param  array
79
	 * @return array
80
	 *
81
	 * @throws BadResponseException
82
	 */
83
	protected function fileGetContents($url, array $contextOptions)
84
	{
85
		$context = stream_context_create($contextOptions);
86
87
		$e = NULL;
88
		set_error_handler(function($severity, $message, $file, $line) use (& $e) {
89
			$e = new \ErrorException($message, 0, $severity, $file, $line, $e);
90
		}, E_WARNING);
91
92
		$content = file_get_contents($url, FALSE, $context);
93
		restore_error_handler();
94
95
		if (!isset($http_response_header)) {
96
			throw new BadResponseException('Missing HTTP headers, request failed.', 0, $e);
0 ignored issues
show
Bug introduced by
The type XoopsModules\Wggithub\Gi...tp\BadResponseException 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...
97
		}
98
99
		if (!isset($http_response_header[0]) || !preg_match('~^HTTP/1[.]. (\d{3})~i', $http_response_header[0], $m)) {
100
			throw new BadResponseException('HTTP status code is missing.', 0, $e);
101
		}
102
		unset($http_response_header[0]);
103
104
		$headers = [];
105
		foreach ($http_response_header as $header) {
106
			if (in_array(substr($header, 0, 1), [' ', "\t"], TRUE)) {
107
				$headers[$last] .= ' ' . trim($header);  # RFC2616, 2.2
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $last does not seem to be defined for all execution paths leading up to this point.
Loading history...
108
			} else {
109
				list($name, $value) = explode(':', $header, 2) + [NULL, NULL];
110
				$headers[$last = trim($name)] = trim($value);
111
			}
112
		}
113
114
		return [$m[1], $headers, $content];
115
	}
116
117
}
118