Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
39 | class FilesDataHandler |
||
40 | { |
||
41 | /** |
||
42 | * @var Request |
||
43 | */ |
||
44 | protected $request; |
||
45 | |||
46 | /** |
||
47 | * @var CollectionInterface | FileSubmissionInterface[] |
||
48 | */ |
||
49 | protected $file_objects; |
||
50 | |||
51 | /** |
||
52 | * @var bool |
||
53 | */ |
||
54 | protected $initialized = false; |
||
55 | |||
56 | /** |
||
57 | * FilesDataHandler constructor. |
||
58 | * @param Request $request |
||
59 | */ |
||
60 | public function __construct(Request $request) |
||
61 | { |
||
62 | $this->request = $request; |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * @since 4.9.80.p |
||
67 | * @return CollectionInterface | FileSubmissionInterface[] |
||
68 | * @throws UnexpectedValueException |
||
69 | * @throws InvalidArgumentException |
||
70 | */ |
||
71 | protected function getFileObjects() |
||
72 | { |
||
73 | $this->initialize(); |
||
74 | return $this->file_objects; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Sets up the file objects from the request's $_FILES data. |
||
79 | * @since 4.9.80.p |
||
80 | * @throws UnexpectedValueException |
||
81 | * @throws InvalidArgumentException |
||
82 | * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
||
83 | */ |
||
84 | protected function initialize() |
||
85 | { |
||
86 | if ($this->initialized) { |
||
87 | return; |
||
88 | } |
||
89 | $this->file_objects = new Collection( |
||
90 | // collection interface |
||
91 | 'EventEspresso\core\services\request\files\FileSubmissionInterface', |
||
92 | // collection name |
||
93 | 'submitted_files' |
||
94 | ); |
||
95 | $files_raw_data = $this->request->filesParams(); |
||
96 | if (empty($files_raw_data)) { |
||
97 | return; |
||
98 | } |
||
99 | if ($this->isStrangeFilesArray($files_raw_data)) { |
||
100 | $data = $this->fixFilesDataArray($files_raw_data); |
||
101 | } else { |
||
102 | $data = $files_raw_data; |
||
103 | } |
||
104 | $this->createFileObjects($data); |
||
105 | $this->initialized = true; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Detects if $_FILES is a weird multi-dimensional array that needs fixing or not. |
||
110 | * @since 4.9.80.p |
||
111 | * @param $files_data |
||
112 | * @return bool |
||
113 | * @throws UnexpectedValueException |
||
114 | */ |
||
115 | protected function isStrangeFilesArray($files_data) |
||
148 | |||
149 | /** |
||
150 | * Takes into account that $_FILES does a weird thing when you have hierarchical form names (eg `<input type="file" |
||
151 | * name="my[hierarchical][form]">`): it leaves the top-level form part alone, but replaces the SECOND part with |
||
152 | * "name", "size", "tmp_name", etc. So that file's data is located at "my[name][hierarchical][form]", |
||
153 | * "my[size][hierarchical][form]", "my[tmp_name][hierarchical][form]", etc. It's really weird. |
||
154 | * @since 4.9.80.p |
||
155 | * @param $files_data |
||
156 | * @return array |
||
157 | */ |
||
158 | protected function fixFilesDataArray($files_data) |
||
176 | |||
177 | /** |
||
178 | * Recursively explores the array until it finds a leaf node, and tacks `$type` as a final index in front of it. |
||
179 | * @since 4.9.80.p |
||
180 | * @param $data array|string |
||
181 | * @param $type 'name', 'tmp_name', 'size', or 'error' |
||
182 | * @param $name string |
||
183 | * @return array|string |
||
184 | */ |
||
185 | protected function organizeFilesData($data, $type) |
||
202 | |||
203 | /** |
||
204 | * Takes the organized $_FILES array (where all file info is located at the same spot as you'd expect an input |
||
205 | * to be in $_GET or $_POST, with all the file's data located side-by-side in an array) and creates a |
||
206 | * multi-dimensional array of FileSubmissionInterface objects. Stores it in `$this->file_objects`. |
||
207 | * @since 4.9.80.p |
||
208 | * @param array $organized_files $_FILES but organized like $_POST |
||
209 | * @param array $name_parts_so_far for multidimensional HTML form names, |
||
210 | * @throws UnexpectedValueException |
||
211 | * @throws InvalidArgumentException |
||
212 | */ |
||
213 | protected function createFileObjects($organized_files, $name_parts_so_far = []) |
||
248 | |||
249 | /** |
||
250 | * Takes the input name parts, like `['my', 'great', 'file', 'input1']` |
||
251 | * and returns the HTML name for it, "my[great][file][input1]" |
||
252 | * @since 4.9.80.p |
||
253 | * @param $parts |
||
254 | * @throws UnexpectedValueException |
||
255 | */ |
||
256 | protected function inputNameFromParts($parts) |
||
271 | |||
272 | /** |
||
273 | * Gets the input by the indicated $name_parts. |
||
274 | * Eg if you're looking for an input named "my[great][file][input1]", $name_parts |
||
275 | * should be `['my', 'great', 'file', 'input1']`. |
||
276 | * Alternatively, you could use `FileDataHandler::getFileObject('my[great][file][input1]');` |
||
277 | * @since 4.9.80.p |
||
278 | * @param $name_parts |
||
279 | * @throws UnexpectedValueException |
||
280 | * @return FileSubmissionInterface |
||
281 | */ |
||
282 | public function getFileObjectFromNameParts($name_parts) |
||
286 | |||
287 | /** |
||
288 | * Gets the FileSubmissionInterface corresponding to the HTML name provided. |
||
289 | * @since 4.9.80.p |
||
290 | * @param $html_name |
||
291 | * @return mixed |
||
292 | * @throws InvalidArgumentException |
||
293 | * @throws UnexpectedValueException |
||
294 | */ |
||
295 | public function getFileObject($html_name) |
||
299 | } |
||
300 | // End of file FilesDataHandler.php |
||
302 |