errorCode = $errorCode; $this->size = $size; $this->localFileName = $localFileName; $this->suggestedFileName = $suggestedFileName; $this->suggestedMediaType = $suggestedMediaType; } public function getErrorCode(): int { return $this->errorCode; } public function getSize(): int { return $this->size; } public function getLocalFileName(): ?string { return $this->localFileName; } public function getLocalMediaType(): ?MediaType { return MediaType::fromPath($this->localFileName); } public function getSuggestedFileName(): string { return $this->suggestedFileName; } public function getSuggestedMediaType(): MediaType { return $this->suggestedMediaType; } public function hasMoved(): bool { return $this->hasMoved; } public function getStream(): Stream { if($this->stream === null) { if($this->errorCode !== UPLOAD_ERR_OK) throw new RuntimeException('Can\'t open stream because of an upload error.'); if($this->hasMoved) throw new RuntimeException('Can\'t open stream because file has already been moved.'); $this->stream = FileStream::openRead($this->localFileName); } return $this->stream; } public function moveTo(string $path): void { if($this->hasMoved) throw new RuntimeException('This uploaded file has already been moved.'); if($this->errorCode !== UPLOAD_ERR_OK) throw new RuntimeException('Can\'t move file because of an upload error.'); if(empty($path)) throw new InvalidArgumentException('$path is not a valid path.'); if($this->stream !== null) $this->stream->close(); $this->hasMoved = PHP_SAPI === 'CLI' ? rename($this->localFileName, $path) : move_uploaded_file($this->localFileName, $path); if(!$this->hasMoved) throw new RuntimeException('Failed to move file to ' . $path); $this->localFileName = $path; } public function close(): void { if($this->stream !== null) $this->stream->close(); } public function __destruct() { $this->close(); } public static function createFromFILE(array $file): self { return new HttpUploadedFile( $file['error'] ?? UPLOAD_ERR_NO_FILE, $file['size'] ?? -1, $file['tmp_name'] ?? '', $file['name'] ?? '', $file['type'] ?? '' ); } public static function createFromFILES(array $files): array { if(empty($files)) return []; return self::createObjectInstances(self::normalizeFILES($files)); } private static function traverseFILES(array $files, string $keyName): array { $arr = []; foreach($files as $key => $val) { $key = "_{$key}"; if(is_array($val)) { $arr[$key] = self::traverseFILES($val, $keyName); } else { $arr[$key][$keyName] = $val; } } return $arr; } private static function normalizeFILES(array $files): array { $out = []; foreach($files as $key => $arr) { if(empty($arr)) continue; $key = '_' . $key; if(is_int($arr['error'])) { $out[$key] = $arr; continue; } if(is_array($arr['error'])) { $keys = array_keys($arr); foreach($keys as $keyName) { $out[$key] = array_merge_recursive($out[$key] ?? [], self::traverseFILES($arr[$keyName], $keyName)); } continue; } } return $out; } private static function createObjectInstances(array $files): array { $coll = []; foreach($files as $key => $val) { $key = substr($key, 1); if(isset($val['error'])) { $coll[$key] = self::createFromFILE($val); } else { $coll[$key] = self::createObjectInstances($val); } } return $coll; } }