|
1 <?php |
|
2 |
|
3 /* |
|
4 * This file is part of the Symfony package. |
|
5 * |
|
6 * (c) Fabien Potencier <fabien@symfony.com> |
|
7 * |
|
8 * For the full copyright and license information, please view the LICENSE |
|
9 * file that was distributed with this source code. |
|
10 */ |
|
11 |
|
12 namespace Symfony\Component\HttpFoundation; |
|
13 |
|
14 use Symfony\Component\HttpFoundation\File\UploadedFile; |
|
15 |
|
16 /** |
|
17 * FileBag is a container for HTTP headers. |
|
18 * |
|
19 * @author Fabien Potencier <fabien@symfony.com> |
|
20 * @author Bulat Shakirzyanov <mallluhuct@gmail.com> |
|
21 * |
|
22 * @api |
|
23 */ |
|
24 class FileBag extends ParameterBag |
|
25 { |
|
26 static private $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); |
|
27 |
|
28 /** |
|
29 * Constructor. |
|
30 * |
|
31 * @param array $parameters An array of HTTP files |
|
32 * |
|
33 * @api |
|
34 */ |
|
35 public function __construct(array $parameters = array()) |
|
36 { |
|
37 $this->replace($parameters); |
|
38 } |
|
39 |
|
40 /** |
|
41 * (non-PHPdoc) |
|
42 * @see Symfony\Component\HttpFoundation\ParameterBag::replace() |
|
43 * |
|
44 * @api |
|
45 */ |
|
46 public function replace(array $files = array()) |
|
47 { |
|
48 $this->parameters = array(); |
|
49 $this->add($files); |
|
50 } |
|
51 |
|
52 /** |
|
53 * (non-PHPdoc) |
|
54 * @see Symfony\Component\HttpFoundation\ParameterBag::set() |
|
55 * |
|
56 * @api |
|
57 */ |
|
58 public function set($key, $value) |
|
59 { |
|
60 if (is_array($value) || $value instanceof UploadedFile) { |
|
61 parent::set($key, $this->convertFileInformation($value)); |
|
62 } else { |
|
63 throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); |
|
64 } |
|
65 } |
|
66 |
|
67 /** |
|
68 * (non-PHPdoc) |
|
69 * @see Symfony\Component\HttpFoundation\ParameterBag::add() |
|
70 * |
|
71 * @api |
|
72 */ |
|
73 public function add(array $files = array()) |
|
74 { |
|
75 foreach ($files as $key => $file) { |
|
76 $this->set($key, $file); |
|
77 } |
|
78 } |
|
79 |
|
80 /** |
|
81 * Converts uploaded files to UploadedFile instances. |
|
82 * |
|
83 * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information |
|
84 * |
|
85 * @return array A (multi-dimensional) array of UploadedFile instances |
|
86 */ |
|
87 protected function convertFileInformation($file) |
|
88 { |
|
89 if ($file instanceof UploadedFile) { |
|
90 return $file; |
|
91 } |
|
92 |
|
93 $file = $this->fixPhpFilesArray($file); |
|
94 if (is_array($file)) { |
|
95 $keys = array_keys($file); |
|
96 sort($keys); |
|
97 |
|
98 if ($keys == self::$fileKeys) { |
|
99 if (UPLOAD_ERR_NO_FILE == $file['error']) { |
|
100 $file = null; |
|
101 } else { |
|
102 $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']); |
|
103 } |
|
104 } else { |
|
105 $file = array_map(array($this, 'convertFileInformation'), $file); |
|
106 } |
|
107 } |
|
108 |
|
109 return $file; |
|
110 } |
|
111 |
|
112 /** |
|
113 * Fixes a malformed PHP $_FILES array. |
|
114 * |
|
115 * PHP has a bug that the format of the $_FILES array differs, depending on |
|
116 * whether the uploaded file fields had normal field names or array-like |
|
117 * field names ("normal" vs. "parent[child]"). |
|
118 * |
|
119 * This method fixes the array to look like the "normal" $_FILES array. |
|
120 * |
|
121 * It's safe to pass an already converted array, in which case this method |
|
122 * just returns the original array unmodified. |
|
123 * |
|
124 * @param array $data |
|
125 * @return array |
|
126 */ |
|
127 protected function fixPhpFilesArray($data) |
|
128 { |
|
129 if (!is_array($data)) { |
|
130 return $data; |
|
131 } |
|
132 |
|
133 $keys = array_keys($data); |
|
134 sort($keys); |
|
135 |
|
136 if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) { |
|
137 return $data; |
|
138 } |
|
139 |
|
140 $files = $data; |
|
141 foreach (self::$fileKeys as $k) { |
|
142 unset($files[$k]); |
|
143 } |
|
144 |
|
145 foreach (array_keys($data['name']) as $key) { |
|
146 $files[$key] = $this->fixPhpFilesArray(array( |
|
147 'error' => $data['error'][$key], |
|
148 'name' => $data['name'][$key], |
|
149 'type' => $data['type'][$key], |
|
150 'tmp_name' => $data['tmp_name'][$key], |
|
151 'size' => $data['size'][$key] |
|
152 )); |
|
153 } |
|
154 |
|
155 return $files; |
|
156 } |
|
157 } |