public function processUpload($directoryId = null, string $cabin = '', array $file = [], array $attribution = []) : array
{
// First step: Validate our file data
switch ($file['error']) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
throw new UploadError(\__('File is too large'));
case UPLOAD_ERR_PARTIAL:
throw new UploadError(\__('Partial file received'));
case UPLOAD_ERR_NO_TMP_DIR:
throw new UploadError(\__('Temporary directory does not exist'));
case UPLOAD_ERR_CANT_WRITE:
throw new UploadError(\__('Cannot write to temporary directory'));
case UPLOAD_ERR_OK:
// Continue
break;
}
if ($file['name'] === '..') {
throw new UploadError(\__('Invalid file name'));
}
if (\preg_match('#([^/]+)\\.([a-zA-Z0-9]+)$#', $file['name'], $matches)) {
$name = $matches[1];
$ext = $matches[2];
} elseif (\preg_match('#([^/\\.]+)$#', $file['name'], $matches)) {
$name = $matches[1];
$ext = 'txt';
} else {
throw new UploadError(\__('Invalid file name'));
}
// Actually upload the file.
$destination = $this->moveUploadedFile($file['tmp_name']);
$fullpath = AIRSHIP_UPLOADS . $destination;
// Get the MIME type and checksum
$type = $this->getMimeType($fullpath);
$state = State::instance();
$checksum = HaliteFile::checksum($fullpath, $state->keyring['cache.hash_key']);
// Begin transaction
$this->db->beginTransaction();
// Get a unique file name
$filename = $this->getUniqueFileName($name, $ext, $directoryId, $cabin);
// Insert the new record
$store = ['filename' => $filename, 'type' => $type, 'realname' => $destination, 'checksum' => $checksum, 'uploaded_by' => (int) ($attribution['uploaded_by'] ?? $this->getActiveUserId())];
if ($directoryId) {
$store['directory'] = (int) $directoryId;
} else {
$store['cabin'] = (string) $cabin;
}
if (!empty($attribution['author'])) {
$store['author'] = $attribution['author'];
}
$newId = $this->db->insertGet('airship_files', $store, 'fileid');
// Did our INSERT query fail?
if (!$this->db->commit()) {
// Clean up orphaned file, it was a database error.
\unlink($fullpath);
$this->db->rollBack();
throw new UploadError(\__('A database error occurred trying to save %s', 'default', $destination));
}
// Return metadata
return ['fileid' => $newId, 'name' => $filename, 'type' => $type, 'csum' => $checksum];
}