@@ -55,16 +55,20 @@ public static function fromGlobals(): ServerRequestInterface
5555
5656 private static function createUriFromGlobals (): UriInterface
5757 {
58- $ scheme = (! empty ($ _SERVER ['HTTPS ' ]) && $ _SERVER ['HTTPS ' ] !== 'off ' ) ? 'https ' : 'http ' ;
58+ $ scheme = (isset ($ _SERVER ['HTTPS ' ]) && $ _SERVER ['HTTPS ' ] !== 'off ' ) ? 'https ' : 'http ' ;
5959 $ host = $ _SERVER ['HTTP_HOST ' ] ?? ($ _SERVER ['SERVER_NAME ' ] ?? 'localhost ' );
6060 $ uri = $ _SERVER ['REQUEST_URI ' ] ?? '/ ' ;
6161
6262 return new Uri ("$ scheme:// $ host$ uri " );
6363 }
6464
65+ /**
66+ * @return array<string, string|string[]>
67+ */
6568 private static function getAllHeaders (): array
6669 {
6770 if (function_exists ('getallHeaders ' )) {
71+ /** @var array<string, string>|false $headers */
6872 $ headers = getallHeaders ();
6973
7074 if ($ headers !== false ) {
@@ -81,50 +85,76 @@ private static function getAllHeaders(): array
8185 }
8286
8387 /**
84- * Parses server array to header array.
85- * Used as fallback when getallheaders() is unavailable.
88+ * Parses a server array to a header array.
89+ * Used as a fallback when getallheaders() is unavailable.
90+ *
91+ * @param array<array-key, mixed> $server
92+ * @return array<string, string|string[]>
8693 */
8794 public static function parseServerHeaders (array $ server ): array
8895 {
8996 $ headers = [];
9097
98+ /**
99+ * @var scalar $value
100+ */
91101 foreach ($ server as $ key => $ value ) {
92- if (str_starts_with ($ key , 'HTTP_ ' )) {
93- $ header = strtolower (str_replace ('_ ' , '- ' , substr ($ key , 5 )));
94- $ headers [$ header ] = [$ value ];
95- } elseif (in_array ($ key , ['CONTENT_TYPE ' , 'CONTENT_LENGTH ' ], true )) {
96- $ header = strtolower (str_replace ('_ ' , '- ' , $ key ));
97- $ headers [$ header ] = [$ value ];
102+ if (is_string ($ key ) && is_string ($ value )) {
103+ if (str_starts_with ($ key , 'HTTP_ ' )) {
104+ $ header = strtolower (str_replace ('_ ' , '- ' , substr ($ key , 5 )));
105+ $ headers [$ header ] = [$ value ];
106+ } elseif (in_array ($ key , ['CONTENT_TYPE ' , 'CONTENT_LENGTH ' ], true )) {
107+ $ header = strtolower (str_replace ('_ ' , '- ' , $ key ));
108+ $ headers [$ header ] = [$ value ];
109+ }
98110 }
99111 }
100112
101113 return $ headers ;
102114 }
103115
104116 /**
105- * Normalizes $_FILES to UploadedFileInterface instances
117+ * Normalizes $_FILES to UploadedFileInterface instances.
118+ *
119+ * @param array<array-key, mixed> $files
120+ * @return array<array-key, UploadedFileInterface|array<array-key, UploadedFileInterface>>
106121 */
107122 private static function normalizeUploadedFiles (array $ files ): array
108123 {
124+ /** @var array<string, UploadedFileInterface|array<array-key, UploadedFileInterface>> $normalized */
109125 $ normalized = [];
110126
111127 foreach ($ files as $ field => $ value ) {
112128 if ($ value instanceof UploadedFileInterface) {
113129 $ normalized [$ field ] = $ value ;
114- } elseif (isset ($ value ['tmp_name ' ])) {
115- if (is_array ($ value ['tmp_name ' ])) {
116- foreach ($ value ['tmp_name ' ] as $ idx => $ tmpName ) {
117- $ normalized [$ field ][$ idx ] = self ::createUploadedFile ([
118- 'tmp_name ' => $ tmpName ,
119- 'name ' => $ value ['name ' ][$ idx ] ?? null ,
120- 'type ' => $ value ['type ' ][$ idx ] ?? null ,
121- 'size ' => $ value ['size ' ][$ idx ] ?? 0 ,
122- 'error ' => $ value ['error ' ][$ idx ] ?? 0 ,
123- ]);
130+ continue ;
131+ }
132+
133+ if (!is_array ($ value ) || !isset ($ value ['tmp_name ' ])) {
134+ continue ;
135+ }
136+
137+ if (is_array ($ value ['tmp_name ' ])) {
138+ /** @var array<array-key, string> $tmpNames */
139+ $ tmpNames = $ value ['tmp_name ' ];
140+
141+ foreach ($ tmpNames as $ idx => $ tmpName ) {
142+ if (!isset ($ normalized [$ field ]) || !is_array ($ normalized [$ field ])) {
143+ /** @var array<array-key, UploadedFileInterface> $normalizedField */
144+ $ normalized [$ field ] = [];
124145 }
125- } else {
126- $ normalized [$ field ] = self ::createUploadedFile ($ value );
146+
147+ $ normalized [$ field ][$ idx ] = self ::createUploadedFile ([
148+ 'tmp_name ' => $ tmpName ,
149+ 'name ' => isset ($ value ['name ' ][$ idx ]) ? (string ) $ value ['name ' ][$ idx ] : null ,
150+ 'type ' => isset ($ value ['type ' ][$ idx ]) ? (string ) $ value ['type ' ][$ idx ] : null ,
151+ 'size ' => (int ) ($ value ['size ' ][$ idx ] ?? 0 ),
152+ 'error ' => (int ) ($ value ['error ' ][$ idx ] ?? 0 ),
153+ ]);
127154 }
155+ } else {
156+ /** @var array{tmp_name: string, name?: string, type?: string, size?: int, error?: int} $value */
157+ $ normalized [$ field ] = self ::createUploadedFile ($ value );
128158 }
129159 }
130160
@@ -133,28 +163,30 @@ private static function normalizeUploadedFiles(array $files): array
133163
134164 private static function createUploadedFile (array $ file ): UploadedFileInterface
135165 {
136- $ resource = @fopen ($ file ['tmp_name ' ], 'rb ' );
166+ $ tmpName = isset ($ file ['tmp_name ' ]) ? (string ) $ file ['tmp_name ' ] : '' ;
167+ $ resource = @fopen ($ tmpName , 'rb ' );
137168 if ($ resource === false ) {
138169 // @codeCoverageIgnoreStart
139170 // This can only fail under OS-level conditions (missing file, permissions),
140171 // which cannot be reliably simulated in unit tests.
141- throw new RuntimeException ('Failed to open uploaded file: ' . $ file [ ' tmp_name ' ] );
172+ throw new RuntimeException ('Failed to open uploaded file: ' . $ tmpName );
142173 // @codeCoverageIgnoreEnd
143174 }
144175
145176 $ stream = new Stream ($ resource );
177+
146178 return new UploadedFile (
147179 $ stream ,
148180 (int ) $ file ['size ' ],
149181 (int ) $ file ['error ' ],
150- $ file ['name ' ] ?? null ,
151- $ file ['type ' ] ?? null
182+ isset ( $ file ['name ' ]) ? ( string ) $ file [ ' name ' ] : null ,
183+ isset ( $ file ['type ' ]) ? ( string ) $ file [ ' type ' ] : null
152184 );
153185 }
154186
155187 private static function getProtocolVersion (): string
156188 {
157- if (! empty ($ _SERVER ['SERVER_PROTOCOL ' ]) && str_starts_with ($ _SERVER ['SERVER_PROTOCOL ' ], 'HTTP/ ' )) {
189+ if (isset ($ _SERVER ['SERVER_PROTOCOL ' ]) && str_starts_with ($ _SERVER ['SERVER_PROTOCOL ' ], 'HTTP/ ' )) {
158190 return substr ($ _SERVER ['SERVER_PROTOCOL ' ], 5 );
159191 }
160192
0 commit comments