Passed
Push — main ( 404000...b70a85 )
by smiley
01:56
created

File::normalizeNestedFileSpec()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 10
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 16
rs 9.9332
1
<?php
2
/**
3
 * Class File
4
 *
5
 * @created      28.03.2021
6
 * @author       smiley <[email protected]>
7
 * @copyright    2021 smiley
8
 * @license      MIT
9
 */
10
11
namespace chillerlan\HTTP\Psr7;
12
13
use InvalidArgumentException;
14
use Psr\Http\Message\UploadedFileInterface;
15
use function array_keys, is_array;
16
17
/**
18
 *
19
 */
20
class File{
21
22
	/**
23
	 * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
24
	 */
25
	public const MIMETYPES = [
26
		'3gp'     => 'video/3gpp',
27
		'7z'      => 'application/x-7z-compressed',
28
		'aac'     => 'audio/x-aac',
29
		'ai'      => 'application/postscript',
30
		'aif'     => 'audio/x-aiff',
31
		'asc'     => 'text/plain',
32
		'asf'     => 'video/x-ms-asf',
33
		'atom'    => 'application/atom+xml',
34
		'avi'     => 'video/x-msvideo',
35
		'bmp'     => 'image/bmp',
36
		'bz2'     => 'application/x-bzip2',
37
		'cer'     => 'application/pkix-cert',
38
		'crl'     => 'application/pkix-crl',
39
		'crt'     => 'application/x-x509-ca-cert',
40
		'css'     => 'text/css',
41
		'csv'     => 'text/csv',
42
		'cu'      => 'application/cu-seeme',
43
		'deb'     => 'application/x-debian-package',
44
		'doc'     => 'application/msword',
45
		'docx'    => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
46
		'dvi'     => 'application/x-dvi',
47
		'eot'     => 'application/vnd.ms-fontobject',
48
		'eps'     => 'application/postscript',
49
		'epub'    => 'application/epub+zip',
50
		'etx'     => 'text/x-setext',
51
		'flac'    => 'audio/flac',
52
		'flv'     => 'video/x-flv',
53
		'gif'     => 'image/gif',
54
		'gz'      => 'application/gzip',
55
		'htm'     => 'text/html',
56
		'html'    => 'text/html',
57
		'ico'     => 'image/x-icon',
58
		'ics'     => 'text/calendar',
59
		'ini'     => 'text/plain',
60
		'iso'     => 'application/x-iso9660-image',
61
		'jar'     => 'application/java-archive',
62
		'jpe'     => 'image/jpeg',
63
		'jpeg'    => 'image/jpeg',
64
		'jpg'     => 'image/jpeg',
65
		'js'      => 'text/javascript',
66
		'json'    => 'application/json',
67
		'latex'   => 'application/x-latex',
68
		'log'     => 'text/plain',
69
		'm4a'     => 'audio/mp4',
70
		'm4v'     => 'video/mp4',
71
		'mid'     => 'audio/midi',
72
		'midi'    => 'audio/midi',
73
		'mov'     => 'video/quicktime',
74
		'mkv'     => 'video/x-matroska',
75
		'mp3'     => 'audio/mpeg',
76
		'mp4'     => 'video/mp4',
77
		'mp4a'    => 'audio/mp4',
78
		'mp4v'    => 'video/mp4',
79
		'mpe'     => 'video/mpeg',
80
		'mpeg'    => 'video/mpeg',
81
		'mpg'     => 'video/mpeg',
82
		'mpg4'    => 'video/mp4',
83
		'oga'     => 'audio/ogg',
84
		'ogg'     => 'audio/ogg',
85
		'ogv'     => 'video/ogg',
86
		'ogx'     => 'application/ogg',
87
		'pbm'     => 'image/x-portable-bitmap',
88
		'pdf'     => 'application/pdf',
89
		'pgm'     => 'image/x-portable-graymap',
90
		'png'     => 'image/png',
91
		'pnm'     => 'image/x-portable-anymap',
92
		'ppm'     => 'image/x-portable-pixmap',
93
		'ppt'     => 'application/vnd.ms-powerpoint',
94
		'pptx'    => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
95
		'ps'      => 'application/postscript',
96
		'qt'      => 'video/quicktime',
97
		'rar'     => 'application/x-rar-compressed',
98
		'ras'     => 'image/x-cmu-raster',
99
		'rss'     => 'application/rss+xml',
100
		'rtf'     => 'application/rtf',
101
		'sgm'     => 'text/sgml',
102
		'sgml'    => 'text/sgml',
103
		'svg'     => 'image/svg+xml',
104
		'swf'     => 'application/x-shockwave-flash',
105
		'tar'     => 'application/x-tar',
106
		'tif'     => 'image/tiff',
107
		'tiff'    => 'image/tiff',
108
		'torrent' => 'application/x-bittorrent',
109
		'ttf'     => 'application/x-font-ttf',
110
		'txt'     => 'text/plain',
111
		'wav'     => 'audio/x-wav',
112
		'webm'    => 'video/webm',
113
		'wma'     => 'audio/x-ms-wma',
114
		'wmv'     => 'video/x-ms-wmv',
115
		'woff'    => 'application/x-font-woff',
116
		'wsdl'    => 'application/wsdl+xml',
117
		'xbm'     => 'image/x-xbitmap',
118
		'xls'     => 'application/vnd.ms-excel',
119
		'xlsx'    => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
120
		'xml'     => 'application/xml',
121
		'xpm'     => 'image/x-xpixmap',
122
		'xwd'     => 'image/x-xwindowdump',
123
		'yaml'    => 'text/yaml',
124
		'yml'     => 'text/yaml',
125
		'zip'     => 'application/zip',
126
	];
127
128
	/**
129
	 * Return an UploadedFile instance array.
130
	 *
131
	 * @param array $files A array which respect $_FILES structure
132
	 *
133
	 * @return array
134
	 * @throws \InvalidArgumentException for unrecognized values
135
	 */
136
	public static function normalize(array $files):array{
137
		$normalized = [];
138
139
		foreach($files as $key => $value){
140
141
			if($value instanceof UploadedFileInterface){
142
				$normalized[$key] = $value;
143
			}
144
			elseif(is_array($value) && isset($value['tmp_name'])){
145
				$normalized[$key] = self::createUploadedFileFromSpec($value);
146
			}
147
			elseif(is_array($value)){
148
				$normalized[$key] = self::normalize($value);
149
			}
150
			else{
151
				throw new InvalidArgumentException('Invalid value in files specification');
152
			}
153
154
		}
155
156
		return $normalized;
157
	}
158
159
	/**
160
	 * Create and return an UploadedFile instance from a $_FILES specification.
161
	 *
162
	 * If the specification represents an array of values, this method will
163
	 * delegate to normalizeNestedFileSpec() and return that return value.
164
	 *
165
	 * @param array $value $_FILES struct
166
	 *
167
	 * @return array|\Psr\Http\Message\UploadedFileInterface
168
	 */
169
	public static function createUploadedFileFromSpec(array $value){
170
171
		if(is_array($value['tmp_name'])){
172
			return self::normalizeNestedFileSpec($value);
173
		}
174
175
		return new UploadedFile($value['tmp_name'], (int)$value['size'], (int)$value['error'], $value['name'], $value['type']);
176
	}
177
178
	/**
179
	 * Normalize an array of file specifications.
180
	 *
181
	 * Loops through all nested files and returns a normalized array of
182
	 * UploadedFileInterface instances.
183
	 *
184
	 * @param array $files
185
	 *
186
	 * @return \Psr\Http\Message\UploadedFileInterface[]
187
	 */
188
	public static function normalizeNestedFileSpec(array $files):array{
189
		$normalized = [];
190
191
		foreach(array_keys($files['tmp_name']) as $key){
192
			$spec = [
193
				'tmp_name' => $files['tmp_name'][$key],
194
				'size'     => $files['size'][$key],
195
				'error'    => $files['error'][$key],
196
				'name'     => $files['name'][$key],
197
				'type'     => $files['type'][$key],
198
			];
199
200
			$normalized[$key] = self::createUploadedFileFromSpec($spec);
201
		}
202
203
		return $normalized;
204
	}
205
206
}
207