Skip to content

Commit 439d45d

Browse files
committed
Changed class elements order
1 parent 170177d commit 439d45d

13 files changed

+236
-235
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"psr/http-factory": "^1.1"
1919
},
2020
"require-dev": {
21-
"polymorphine/dev": "0.5.*"
21+
"polymorphine/dev": "0.6.*"
2222
},
2323
"autoload": {
2424
"psr-4": {

src/Response.php

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,6 @@ class Response implements ResponseInterface
2121
use StatusCodesTrait;
2222
use MessageMethodsTrait;
2323

24-
private int $status;
25-
private string $reason;
26-
27-
/**
28-
* @param int $statusCode Normally one of the status codes defined by RFC 7231 section 6
29-
* @param ?StreamInterface $body
30-
* @param array $headers Associative array of header strings or arrays of header strings
31-
* @param array $params Associative array with following keys and its default values
32-
* when key is not present or its value is null:
33-
* - version - http protocol version (default: '1.1')
34-
* - reason - reason phrase normally associated with $statusCode, so by
35-
* default it will be resolved from it.
36-
*
37-
* @see https://tools.ietf.org/html/rfc7231#section-6
38-
* @see StatusCodesTrait
39-
*/
40-
public function __construct(
41-
int $statusCode,
42-
?StreamInterface $body = null,
43-
array $headers = [],
44-
array $params = []
45-
) {
46-
$this->status = $this->validStatusCode($statusCode);
47-
$this->body = $body ?? Stream::fromBodyString('');
48-
$this->reason = $this->validReasonPhrase($params['reason'] ?? '');
49-
$this->version = isset($params['version']) ? $this->validProtocolVersion($params['version']) : '1.1';
50-
$this->loadHeaders($headers);
51-
}
52-
5324
public static function text(string $text, int $statusCode = 200): self
5425
{
5526
return new self($statusCode, Stream::fromBodyString($text), ['Content-Type' => 'text/plain']);
@@ -107,6 +78,35 @@ public static function notFound(?StreamInterface $body = null): self
10778
return new self(404, $body);
10879
}
10980

81+
private int $status;
82+
private string $reason;
83+
84+
/**
85+
* @param int $statusCode Normally one of the status codes defined by RFC 7231 section 6
86+
* @param ?StreamInterface $body
87+
* @param array $headers Associative array of header strings or arrays of header strings
88+
* @param array $params Associative array with following keys and its default values
89+
* when key is not present or its value is null:
90+
* - version - http protocol version (default: '1.1')
91+
* - reason - reason phrase normally associated with $statusCode, so by
92+
* default it will be resolved from it.
93+
*
94+
* @see https://tools.ietf.org/html/rfc7231#section-6
95+
* @see StatusCodesTrait
96+
*/
97+
public function __construct(
98+
int $statusCode,
99+
?StreamInterface $body = null,
100+
array $headers = [],
101+
array $params = []
102+
) {
103+
$this->status = $this->validStatusCode($statusCode);
104+
$this->body = $body ?? Stream::fromBodyString('');
105+
$this->reason = $this->validReasonPhrase($params['reason'] ?? '');
106+
$this->version = isset($params['version']) ? $this->validProtocolVersion($params['version']) : '1.1';
107+
$this->loadHeaders($headers);
108+
}
109+
110110
public function getStatusCode(): int
111111
{
112112
return $this->status;

src/ServerRequest.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@
2020

2121
class ServerRequest extends Request implements ServerRequestInterface
2222
{
23+
public static function fromServerData(ServerData $data): self
24+
{
25+
return new self($data->method(), $data->uri(), $data->body(), $data->headers(), $data->params());
26+
}
27+
28+
public static function fromGlobals(array $override = []): self
29+
{
30+
return self::fromServerData(new ServerData([
31+
'server' => isset($override['server']) ? $override['server'] + $_SERVER : $_SERVER,
32+
'get' => isset($override['get']) ? $override['get'] + $_GET : $_GET,
33+
'post' => isset($override['post']) ? $override['post'] + $_POST : $_POST,
34+
'cookie' => isset($override['cookie']) ? $override['cookie'] + $_COOKIE : $_COOKIE,
35+
'files' => isset($override['files']) ? $override['files'] + $_FILES : $_FILES
36+
]));
37+
}
38+
2339
private array $server;
2440
private array $cookie;
2541
private array $query;
@@ -60,22 +76,6 @@ public function __construct(
6076
parent::__construct($method, $uri, $body, $headers, $params);
6177
}
6278

63-
public static function fromServerData(ServerData $data): self
64-
{
65-
return new self($data->method(), $data->uri(), $data->body(), $data->headers(), $data->params());
66-
}
67-
68-
public static function fromGlobals(array $override = []): self
69-
{
70-
return self::fromServerData(new ServerData([
71-
'server' => isset($override['server']) ? $override['server'] + $_SERVER : $_SERVER,
72-
'get' => isset($override['get']) ? $override['get'] + $_GET : $_GET,
73-
'post' => isset($override['post']) ? $override['post'] + $_POST : $_POST,
74-
'cookie' => isset($override['cookie']) ? $override['cookie'] + $_COOKIE : $_COOKIE,
75-
'files' => isset($override['files']) ? $override['files'] + $_FILES : $_FILES
76-
]));
77-
}
78-
7979
public function getServerParams(): array
8080
{
8181
return $this->server;

src/Stream.php

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,33 @@
1919

2020
class Stream implements StreamInterface
2121
{
22+
public static function fromBodyString(string $body): self
23+
{
24+
$stream = new self(fopen('php://temp', 'w+b'));
25+
$stream->write($body);
26+
$stream->rewind();
27+
28+
return $stream;
29+
}
30+
31+
public static function fromResourceUri(string $streamUri, string $mode = 'r'): self
32+
{
33+
set_error_handler(fn () => self::handleResourceError($mode), E_WARNING);
34+
$resource = fopen($streamUri, $mode);
35+
restore_error_handler();
36+
37+
return new self($resource);
38+
}
39+
40+
private static function handleResourceError(string $mode): void
41+
{
42+
restore_error_handler();
43+
if (preg_match('/^[acrwx](?:\+?[tb]?|[tb]?\+?)$/', $mode)) {
44+
throw new RuntimeException('Invalid stream reference');
45+
}
46+
throw new InvalidArgumentException('Invalid stream resource mode');
47+
}
48+
2249
private $resource;
2350

2451
private ?array $metaData;
@@ -40,30 +67,6 @@ public function __construct($resource)
4067
$this->resource = $resource;
4168
}
4269

43-
public static function fromResourceUri(string $streamUri, $mode = 'r'): self
44-
{
45-
set_error_handler(function () use ($mode) {
46-
restore_error_handler();
47-
if (preg_match('/^[acrwx](?:\+?[tb]?|[tb]?\+?)$/', $mode)) {
48-
throw new RuntimeException('Invalid stream reference');
49-
}
50-
throw new InvalidArgumentException('Invalid stream resource mode');
51-
}, E_WARNING);
52-
$resource = fopen($streamUri, $mode);
53-
restore_error_handler();
54-
55-
return new self($resource);
56-
}
57-
58-
public static function fromBodyString(string $body): self
59-
{
60-
$stream = new self(fopen('php://temp', 'w+b'));
61-
$stream->write($body);
62-
$stream->rewind();
63-
64-
return $stream;
65-
}
66-
6770
public function __toString(): string
6871
{
6972
try {

src/UploadedFile.php

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919

2020
class UploadedFile implements UploadedFileInterface
2121
{
22+
/**
23+
* @param array $file Associative array with keys corresponding to $_FILES[name] array
24+
* for single uploaded file
25+
*
26+
* @see https://www.php.net/manual/en/features.file-upload.post-method.php
27+
*/
28+
public static function fromFileArray(array $file): self
29+
{
30+
$stream = Stream::fromResourceUri($file['tmp_name']);
31+
return new self($stream, $file['size'], $file['error'], $file['name'], $file['type']);
32+
}
33+
2234
protected StreamInterface $stream;
2335
protected bool $isMoved = false;
2436

@@ -55,20 +67,6 @@ public function __construct(
5567
$this->clientMediaType = $clientMediaType;
5668
}
5769

58-
/**
59-
* @param array $file Associative array with keys corresponding to $_FILES[name] array
60-
* for single uploaded file
61-
*
62-
* @return UploadedFile
63-
*
64-
* @see https://www.php.net/manual/en/features.file-upload.post-method.php
65-
*/
66-
public static function fromFileArray(array $file): self
67-
{
68-
$stream = Stream::fromResourceUri($file['tmp_name']);
69-
return new self($stream, $file['size'], $file['error'], $file['name'], $file['type']);
70-
}
71-
7270
public function getStream(): StreamInterface
7371
{
7472
$this->checkFileAccess();

src/Uri.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ class Uri implements UriInterface
2121
public const CHARSET_PATH = '^a-z0-9A-Z.\-_~&=+;,$!\'()*%:\/@';
2222
public const CHARSET_QUERY = '^a-z0-9A-Z.\-_~&=+;,$!\'()*%:\/@?';
2323

24+
public static function fromString(string $uri = ''): self
25+
{
26+
$segments = parse_url($uri);
27+
if ($segments === false) {
28+
throw new InvalidArgumentException('Malformed URI string: `$uri`');
29+
}
30+
31+
return new self($segments);
32+
}
33+
2434
protected array $supportedSchemes = [
2535
'http' => ['port' => 80],
2636
'https' => ['port' => 443]
@@ -54,16 +64,6 @@ public function __construct(array $segments = [])
5464
$this->fragment = isset($segments['fragment']) ? $this->encode($segments['fragment'], self::CHARSET_QUERY) : '';
5565
}
5666

57-
public static function fromString(string $uri = ''): self
58-
{
59-
$segments = parse_url($uri);
60-
if ($segments === false) {
61-
throw new InvalidArgumentException('Malformed URI string: `$uri`');
62-
}
63-
64-
return new self($segments);
65-
}
66-
6767
public function __toString(): string
6868
{
6969
return $this->uri ??= $this->buildUriString();

tests/MessageMethodsTest.php

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,6 @@
2020

2121
class MessageMethodsTest extends TestCase
2222
{
23-
public static function invalidHeaderNames(): array
24-
{
25-
return [
26-
'empty name' => [''],
27-
'spaced name' => ['header name'],
28-
'invalid name char "@"' => ['email@example']
29-
];
30-
}
31-
32-
public function invalidHeaderValues(): array
33-
{
34-
return [
35-
'null value' => [null],
36-
'bool value' => [true],
37-
'toString object' => [new FakeStream()],
38-
'int within array' => [['valid header', 9001]],
39-
'illegal char' => ["some value\xFF"],
40-
'invalid linebreak \n' => ["some\n value"],
41-
'invalid linebreak \r' => ["some\r value"],
42-
'invalid linebreak \n\r' => ["some\n\r value"],
43-
'no whitespace after linebreak' => ["some\r\nvalue"]
44-
];
45-
}
46-
4723
public function test_Instantiation()
4824
{
4925
$this->assertInstanceOf(MessageInterface::class, $this->message());
@@ -278,6 +254,30 @@ public function test_WithAddedHeader_SettingInvalidHeaderName_ThrowsException(st
278254
$this->message()->withAddedHeader($name, 'valid value');
279255
}
280256

257+
public static function invalidHeaderNames(): iterable
258+
{
259+
return [
260+
'empty name' => [''],
261+
'spaced name' => ['header name'],
262+
'invalid name char "@"' => ['email@example']
263+
];
264+
}
265+
266+
public static function invalidHeaderValues(): iterable
267+
{
268+
return [
269+
'null value' => [null],
270+
'bool value' => [true],
271+
'toString object' => [new FakeStream()],
272+
'int within array' => [['valid header', 9001]],
273+
'illegal char' => ["some value\xFF"],
274+
'invalid linebreak \n' => ["some\n value"],
275+
'invalid linebreak \r' => ["some\r value"],
276+
'invalid linebreak \n\r' => ["some\n\r value"],
277+
'no whitespace after linebreak' => ["some\r\nvalue"]
278+
];
279+
}
280+
281281
private function message(array $headers = [], $version = null): MessageMethodsClass
282282
{
283283
return $version

tests/RequestTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,6 @@
2121

2222
class RequestTest extends TestCase
2323
{
24-
public static function mutatorMethods(): array
25-
{
26-
return [
27-
'withRequestTarget' => [fn (Request $original) => $original->withRequestTarget('*')],
28-
'withUri' => [fn (Request $original) => $original->withUri(Uri::fromString('/some/path'))],
29-
'withMethod' => [fn (Request $original) => $original->withMethod('POST')]
30-
];
31-
}
32-
3324
public function test_Instantiation()
3425
{
3526
$this->assertInstanceOf(RequestInterface::class, $this->request());
@@ -135,6 +126,15 @@ public function test_WithUri_ResolvesHostHeader()
135126
$this->assertSame('uri-example.com', $request->withUri($uri)->getHeaderLine('host'), $fail);
136127
}
137128

129+
public static function mutatorMethods(): iterable
130+
{
131+
return [
132+
'withRequestTarget' => [fn (Request $original) => $original->withRequestTarget('*')],
133+
'withUri' => [fn (Request $original) => $original->withUri(Uri::fromString('/some/path'))],
134+
'withMethod' => [fn (Request $original) => $original->withMethod('POST')]
135+
];
136+
}
137+
138138
private function request(
139139
string $method = 'GET',
140140
array $headers = [],

0 commit comments

Comments
 (0)