Passed
Push — main ( f2efe3...53dc0a )
by smiley
10:15
created

create_uri_from_globals()   C

Complexity

Conditions 13
Paths 240

Size

Total Lines 43
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 25
nc 240
nop 0
dl 0
loc 43
rs 5.2833
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @filesource   factory_helpers.php
4
 * @created      28.08.2018
5
 * @author       smiley <[email protected]>
6
 * @copyright    2018 smiley
7
 * @license      MIT
8
 */
9
10
namespace chillerlan\HTTP\Psr17;
11
12
use Psr\Http\Message\ServerRequestInterface;
13
use chillerlan\HTTP\Psr7\{ServerRequest, Stream, UriExtended};
14
use InvalidArgumentException;
15
use Psr\Http\Message\StreamInterface;
16
17
use function chillerlan\HTTP\Psr7\normalize_files;
18
use function explode, function_exists, getallheaders, is_scalar, method_exists, str_replace;
19
20
const PSR17_INCLUDES = true;
21
22
const STREAM_MODES_READ_WRITE = [
23
	'a+'  => true,
24
	'c+'  => true,
25
	'c+b' => true,
26
	'c+t' => true,
27
	'r+'  => true,
28
	'r+b' => true,
29
	'r+t' => true,
30
	'w+'  => true,
31
	'w+b' => true,
32
	'w+t' => true,
33
	'x+'  => true,
34
	'x+b' => true,
35
	'x+t' => true,
36
];
37
38
const STREAM_MODES_READ = STREAM_MODES_READ_WRITE + [
39
	'r'   => true,
40
	'rb'  => true,
41
	'rt'  => true,
42
];
43
44
const STREAM_MODES_WRITE = STREAM_MODES_READ_WRITE + [
45
	'a'   => true,
46
	'rw'  => true,
47
	'w'   => true,
48
	'wb'  => true,
49
];
50
51
/**
52
 * Return a ServerRequest populated with superglobals:
53
 * $_GET
54
 * $_POST
55
 * $_COOKIE
56
 * $_FILES
57
 * $_SERVER
58
 */
59
function create_server_request_from_globals():ServerRequestInterface{
60
61
	$serverRequest = new ServerRequest(
62
		$_SERVER['REQUEST_METHOD'] ?? ServerRequest::METHOD_GET,
63
		create_uri_from_globals(),
64
		function_exists('getallheaders') ? getallheaders() : [],
0 ignored issues
show
Bug introduced by
It seems like function_exists('getallh...tallheaders() : array() can also be of type true; however, parameter $headers of chillerlan\HTTP\Psr7\ServerRequest::__construct() does only seem to accept array|null, 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

64
		/** @scrutinizer ignore-type */ function_exists('getallheaders') ? getallheaders() : [],
Loading history...
65
		(new StreamFactory)->createStream(),
66
		isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1',
67
		$_SERVER
68
	);
69
70
	return $serverRequest
71
		->withCookieParams($_COOKIE)
72
		->withQueryParams($_GET)
73
		->withParsedBody($_POST)
74
		->withUploadedFiles(normalize_files($_FILES))
75
	;
76
}
77
78
/**
79
 * Get a Uri populated with values from $_SERVER.
80
 */
81
function create_uri_from_globals():UriExtended{
82
	$parts    = [];
83
	$hasPort  = false;
84
	$hasQuery = false;
85
86
	$parts['scheme'] = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http';
87
88
	if(isset($_SERVER['HTTP_HOST'])){
89
		$hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']);
90
		$parts['host']   = $hostHeaderParts[0];
91
92
		if(isset($hostHeaderParts[1])){
93
			$hasPort       = true;
94
			$parts['port'] = $hostHeaderParts[1];
95
		}
96
	}
97
	elseif(isset($_SERVER['SERVER_NAME'])){
98
		$parts['host'] = $_SERVER['SERVER_NAME'];
99
	}
100
	elseif(isset($_SERVER['SERVER_ADDR'])){
101
		$parts['host'] = $_SERVER['SERVER_ADDR'];
102
	}
103
104
	if(!$hasPort && isset($_SERVER['SERVER_PORT'])){
105
		$parts['port'] = $_SERVER['SERVER_PORT'];
106
	}
107
108
	if(isset($_SERVER['REQUEST_URI'])){
109
		$requestUriParts = explode('?', $_SERVER['REQUEST_URI']);
110
		$parts['path']   = $requestUriParts[0];
111
112
		if(isset($requestUriParts[1])){
113
			$hasQuery       = true;
114
			$parts['query'] = $requestUriParts[1];
115
		}
116
	}
117
118
	if(!$hasQuery && isset($_SERVER['QUERY_STRING'])){
119
		$parts['query'] = $_SERVER['QUERY_STRING'];
120
	}
121
122
	/** @noinspection PhpIncompatibleReturnTypeInspection */
123
	return UriExtended::fromParts($parts);
124
}
125
126
/**
127
 * Create a new writable stream from a string.
128
 *
129
 * The stream SHOULD be created with a temporary resource.
130
 *
131
 * @param string $content String content with which to populate the stream.
132
 * @param string $mode    one of \chillerlan\HTTP\Psr17\STREAM_MODES_WRITE
133
 * @param bool   $rewind  rewind the stream
134
 *
135
 * @return \Psr\Http\Message\StreamInterface
136
 */
137
function create_stream(string $content = '', string $mode = 'r+', bool $rewind = true):StreamInterface{
138
139
	if(!isset(STREAM_MODES_WRITE[$mode])){
140
		throw new InvalidArgumentException('invalid mode');
141
	}
142
143
	$stream = new Stream(fopen('php://temp', $mode));
144
145
	if($content !== ''){
146
		$stream->write($content);
147
	}
148
149
	if($rewind){
150
		$stream->rewind();
151
	}
152
153
	return $stream;
154
}
155
156
/**
157
 * @param mixed $in
158
 *
159
 * @return \Psr\Http\Message\StreamInterface
160
 */
161
function create_stream_from_input($in = null):StreamInterface{
162
	$in = $in ?? '';
163
164
	// not sure about this one, it might cause:
165
	// a) trouble if the given string accidentally matches a file path, and
166
	// b) security implications because of the above.
167
	// use with caution and never with user input!
168
#	if(\is_string($in) && \is_file($in) && \is_readable($in)){
169
#		return new Stream(\fopen($in, 'r'));
170
#	}
171
172
	if(is_scalar($in)){
173
		return create_stream((string)$in);
174
	}
175
176
	$type = gettype($in);
177
178
	if($type === 'resource'){
179
		return new Stream($in);
180
	}
181
	elseif($type === 'object'){
182
183
		if($in instanceof StreamInterface){
184
			return $in;
185
		}
186
		elseif(method_exists($in, '__toString')){
187
			return create_stream((string)$in);
188
		}
189
190
	}
191
192
	throw new InvalidArgumentException('Invalid resource type: '.$type);
193
}
194