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