loadFilesArray($files); $this->iterator = new ArrayIterator($files); } /** * Returns all file uploads. * * @return FileUpload[] */ public function all() { return $this->iterator->getArrayCopy(); } /** * Returns true if there is a file upload entry with this name. * * @param string $name * * @return bool */ public function has($name) { return $this->iterator->offsetExists($name); } /** * Get an file upload entry. * * @param string $name * @param mixed|null $default * * @return FileUpload|mixed */ public function get($name, $default = null) { return $this->has($name) ? $this->iterator->offsetGet($name) : $default; } /** * Returns true if all upload files are valid. * * @return bool true=all upload files are valid */ public function allValid() { foreach ($this->all() as $name => $upload) { if (!$upload->isValid()) { return false; } } return true; } /** * Returns true if at least one file upload has an error. * * @return bool true=there is at least one error */ public function hasErrors() { foreach ($this->all() as $name => $upload) { if ($upload->hasError()) { return true; } } return false; } /** * Return the current element * * @return mixed FileUpload Object, null on failure */ public function current() { return $this->iterator->current(); } /** * Move forward to next element * * @return void */ public function next() { $this->iterator->next(); } /** * Return the key of the current element * * @return mixed on success, or null on failure. */ public function key() { return $this->iterator->key(); } /** * Checks if current position is valid * * @return boolean true on success or false on failure. */ public function valid() { return $this->iterator->valid(); } /** * Rewind the Iterator to the first element * * @return void Any returned value is ignored. */ public function rewind() { $this->iterator->rewind(); } /** * @param $fileEntries * * @return bool true=is alternate Array */ protected function isAlternateArray($fileEntries) { if ( !isset($fileEntries[array_keys($fileEntries)[0]]['tmp_name']) || is_array($fileEntries[array_keys($fileEntries)[0]]['tmp_name']) ) { return true; } return false; } /** * @param array $fileEntries * * @return FileUpload[] $files */ protected function loadFilesArray($fileEntries) { if (empty($fileEntries)) { return []; } if ($this->isAlternateArray($fileEntries)) { return $this->convertFilesArray($fileEntries); } $files = []; foreach ($fileEntries as $name => $upload) { if (empty($upload['tmp_name'])) { continue; } if (!is_array($upload['tmp_name'])) { $files[$name] = FileUpload::fromFilesArray($upload); continue; } } return $files; } /** * Recursively builds the array with FileUpload instances from alternative array format. * * tested up to 3rd level nesting * * @param array $files * * @return array */ protected function convertFilesArray(array $files) { $totalUploads = []; foreach ($files as $name => $file) { $keys = array_keys($file); if (count(array_intersect($keys, ['name', 'tmp_name'])) === 2) { $uploads = []; foreach ($file['tmp_name'] as $k => $v) { $upload = [ 'tmp_name' => array_key_exists('tmp_name', $file) ? $file['tmp_name'][$k] : null, 'name' => array_key_exists('name', $file) ? $file['name'][$k] : null, 'type' => array_key_exists('type', $file) ? $file['type'][$k] : null, 'size' => array_key_exists('size', $file) ? $file['size'][$k] : null, 'error' => array_key_exists('error', $file) ? $file['error'][$k] : null, ]; if (!empty($upload['tmp_name'])) { $uploads[$k] = FileUpload::fromFilesArray($upload); } } $totalUploads[$name] = $uploads; } else { if (!(isset($file['tmp_name']) && $file['tmp_name'] === '')) { $totalUploads[$name] = $this->convertFilesArray($file); } } } return $totalUploads; } }