1: <?php declare(strict_types=1);
2:
3: namespace Salient\Http\Message;
4:
5: use Psr\Http\Message\MessageInterface as PsrMessageInterface;
6: use Psr\Http\Message\ServerRequestInterface as PsrServerRequestInterface;
7: use Salient\Contract\Http\Message\ServerRequestInterface;
8: use Salient\Core\Concern\ImmutableTrait;
9: use Salient\Utility\Exception\InvalidArgumentTypeException;
10: use Salient\Utility\Arr;
11:
12: /**
13: * @api
14: *
15: * @extends AbstractRequest<PsrServerRequestInterface>
16: */
17: class ServerRequest extends AbstractRequest implements ServerRequestInterface
18: {
19: use ImmutableTrait;
20:
21: /** @var mixed[] */
22: protected array $ServerParams;
23: /** @var mixed[] */
24: protected array $CookieParams = [];
25: /** @var mixed[] */
26: protected array $QueryParams = [];
27: /** @var mixed[] */
28: protected array $UploadedFiles = [];
29: /** @var mixed[]|object|null */
30: protected $ParsedBody;
31: /** @var mixed[] */
32: protected array $Attributes = [];
33:
34: /**
35: * @api
36: *
37: * @param mixed[] $serverParams
38: */
39: final public function __construct(
40: string $method,
41: $uri,
42: array $serverParams = [],
43: $body = null,
44: $headers = null,
45: ?string $requestTarget = null,
46: string $version = '1.1'
47: ) {
48: $this->ServerParams = $serverParams;
49:
50: parent::__construct($method, $uri, $body, $headers, $requestTarget, $version);
51: }
52:
53: /**
54: * @inheritDoc
55: */
56: public static function fromPsr7(PsrMessageInterface $message): ServerRequest
57: {
58: return $message instanceof static
59: ? $message
60: : (new static(
61: $message->getMethod(),
62: $message->getUri(),
63: $message->getServerParams(),
64: $message->getBody(),
65: $message->getHeaders(),
66: $message->getRequestTarget(),
67: $message->getProtocolVersion(),
68: ))
69: ->withCookieParams($message->getCookieParams())
70: ->withQueryParams($message->getQueryParams())
71: ->withUploadedFiles($message->getUploadedFiles())
72: ->withParsedBody($message->getParsedBody())
73: ->with('Attributes', $message->getAttributes());
74: }
75:
76: /**
77: * @inheritDoc
78: *
79: * @return mixed[]
80: */
81: public function getServerParams(): array
82: {
83: return $this->ServerParams;
84: }
85:
86: /**
87: * @inheritDoc
88: *
89: * @return mixed[]
90: */
91: public function getCookieParams(): array
92: {
93: return $this->CookieParams;
94: }
95:
96: /**
97: * @inheritDoc
98: *
99: * @return mixed[]
100: */
101: public function getQueryParams(): array
102: {
103: return $this->QueryParams;
104: }
105:
106: /**
107: * @inheritDoc
108: *
109: * @return mixed[]
110: */
111: public function getUploadedFiles(): array
112: {
113: return $this->UploadedFiles;
114: }
115:
116: /**
117: * @inheritDoc
118: *
119: * @return mixed[]|object|null
120: */
121: public function getParsedBody()
122: {
123: return $this->ParsedBody;
124: }
125:
126: /**
127: * @inheritDoc
128: *
129: * @return mixed[]
130: */
131: public function getAttributes(): array
132: {
133: return $this->Attributes;
134: }
135:
136: /**
137: * @inheritDoc
138: *
139: * @return mixed
140: */
141: public function getAttribute(string $name, $default = null)
142: {
143: return array_key_exists($name, $this->Attributes)
144: ? $this->Attributes[$name]
145: : $default;
146: }
147:
148: /**
149: * @inheritDoc
150: *
151: * @param mixed[] $cookies
152: */
153: public function withCookieParams(array $cookies): PsrServerRequestInterface
154: {
155: return $this->with('CookieParams', $cookies);
156: }
157:
158: /**
159: * @inheritDoc
160: *
161: * @param mixed[] $query
162: */
163: public function withQueryParams(array $query): PsrServerRequestInterface
164: {
165: return $this->with('QueryParams', $query);
166: }
167:
168: /**
169: * @inheritDoc
170: *
171: * @param mixed[] $uploadedFiles
172: */
173: public function withUploadedFiles(array $uploadedFiles): PsrServerRequestInterface
174: {
175: return $this->with('UploadedFiles', $uploadedFiles);
176: }
177:
178: /**
179: * @inheritDoc
180: *
181: * @param mixed[]|object|null $data
182: */
183: public function withParsedBody($data): PsrServerRequestInterface
184: {
185: return $this->with('ParsedBody', $this->filterParsedBody($data));
186: }
187:
188: /**
189: * @inheritDoc
190: */
191: public function withAttribute(string $name, $value): PsrServerRequestInterface
192: {
193: return $this->with('Attributes', Arr::set($this->Attributes, $name, $value));
194: }
195:
196: /**
197: * @inheritDoc
198: */
199: public function withoutAttribute(string $name): PsrServerRequestInterface
200: {
201: return $this->with('Attributes', Arr::unset($this->Attributes, $name));
202: }
203:
204: /**
205: * @template T
206: *
207: * @param T $data
208: * @return T
209: */
210: private function filterParsedBody($data)
211: {
212: if ($data !== null && !is_array($data) && !is_object($data)) {
213: throw new InvalidArgumentTypeException(
214: 1,
215: 'data',
216: 'mixed[]|object|null',
217: $data,
218: );
219: }
220: return $data;
221: }
222: }
223: