diff --git a/ext/image/main.php b/ext/image/main.php index e361f93a..a0acad93 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -152,9 +152,7 @@ class ImageIO extends Extension $event->image = $im; return; } else { - $error = "Post {$existing->id} ". - "already has hash {$image->hash}:

".$this->theme->build_thumb_html($existing); - throw new ImageAdditionException($error); + throw new ImageAdditionException(">>{$existing->id} already has hash {$image->hash}"); } } @@ -216,9 +214,7 @@ class ImageIO extends Extension $duplicate = Image::by_hash($image->hash); if (!is_null($duplicate) && $duplicate->id != $id) { - $error = "Post {$duplicate->id} " . - "already has hash {$image->hash}:

" . $this->theme->build_thumb_html($duplicate); - throw new ImageReplaceException($error); + throw new ImageReplaceException(">>{$duplicate->id} already has hash {$image->hash}"); } if (strlen(trim($image->source ?? '')) == 0) { diff --git a/ext/upload/main.php b/ext/upload/main.php index 96a23467..bc53e1d0 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -58,12 +58,31 @@ class UploadException extends SCoreException { } -class UploadError +abstract class UploadResult { public function __construct( - public string $name, + public string $name + ) { + } +} + +class UploadError extends UploadResult +{ + public function __construct( + string $name, public string $error ) { + parent::__construct($name); + } +} + +class UploadSuccess extends UploadResult +{ + public function __construct( + string $name, + public int $image_id + ) { + parent::__construct($name); } } @@ -211,15 +230,14 @@ class Upload extends Extension if($event->method == "GET") { $this->theme->display_replace_page($page, $image_id); } elseif($event->method == "POST") { - $image_ids = []; - $errors = []; + $results = []; if (!empty($_POST["url"])) { - [$image_ids, $errors] = $this->try_transload($_POST["url"], [], $_POST['source'] ?? null, $image_id); + $results = $this->try_transload($_POST["url"], [], $_POST['source'] ?? null, $image_id); } elseif (count($_FILES) > 0) { - [$image_ids, $errors] = $this->try_upload($_FILES["data"], [], $_POST['source'] ?? null, $image_id); + $results = $this->try_upload($_FILES["data"], [], $_POST['source'] ?? null, $image_id); } $cache->delete("thumb-block:{$image_id}"); - $this->theme->display_upload_status($page, $image_ids, $errors); + $this->theme->display_upload_status($page, $results); } } elseif ($event->page_matches("upload")) { if (!$user->can(Permissions::CREATE_IMAGE)) { @@ -234,8 +252,7 @@ class Upload extends Extension if($event->method == "GET") { $this->theme->display_page($page); } elseif($event->method == "POST") { - $all_image_ids = []; - $all_errors = []; + $results = []; $files = array_filter($_FILES, function ($file) { return !empty($file['name']); @@ -244,9 +261,7 @@ class Upload extends Extension $slot = int_escape(substr($name, 4)); $tags = $this->tags_for_upload_slot($slot); $source = $this->source_for_upload_slot($slot); - [$image_ids, $errors] = $this->try_upload($file, $tags, $source); - $all_image_ids = array_merge($all_image_ids, $image_ids); - $all_errors = array_merge($all_errors, $errors); + $results = array_merge($results, $this->try_upload($file, $tags, $source)); } $urls = array_filter($_POST, function ($value, $key) { @@ -256,12 +271,10 @@ class Upload extends Extension $slot = int_escape(substr($name, 3)); $tags = $this->tags_for_upload_slot($slot); $source = $this->source_for_upload_slot($slot); - [$image_ids, $errors] = $this->try_transload($value, $tags, $source); - $all_image_ids = array_merge($all_image_ids, $image_ids); - $all_errors = array_merge($all_errors, $errors); + $results = array_merge($results, $this->try_transload($value, $tags, $source)); } - $this->theme->display_upload_status($page, $all_image_ids, $all_errors); + $this->theme->display_upload_status($page, $results); } } } @@ -316,6 +329,7 @@ class Upload extends Extension * Handle an upload. * @param mixed[] $file * @param string[] $tags + * @return UploadResult[] */ private function try_upload(array $file, array $tags, ?string $source = null, ?int $replace_id = null): array { @@ -330,55 +344,50 @@ class Upload extends Extension $source = null; } - $image_ids = []; - $errors = []; + $results = []; - $num_files = count($file['name']); - $limit = $config->get_int(UploadConfig::COUNT); - try { - if ($num_files > $limit) { - throw new UploadException("Upload limited to $limit files at a time"); + for ($i = 0; $i < count($file['name']); $i++) { + $name = $file['name'][$i]; + $error = $file['error'][$i]; + $tmp_name = $file['tmp_name'][$i]; + + if (empty($name)) { + continue; } - - for ($i = 0; $i < $num_files; $i++) { - if (empty($file['name'][$i])) { - continue; + try { + // check if the upload was successful + if ($error !== UPLOAD_ERR_OK) { + throw new UploadException($this->upload_error_message($error)); } - try { - // check if the upload was successful - if ($file['error'][$i] !== UPLOAD_ERR_OK) { - throw new UploadException($this->upload_error_message($file['error'][$i])); - } - $metadata = []; - $metadata['filename'] = pathinfo($file['name'][$i], PATHINFO_BASENAME); - $metadata['tags'] = $tags; - $metadata['source'] = $source; + $metadata = []; + $metadata['filename'] = pathinfo($name, PATHINFO_BASENAME); + $metadata['tags'] = $tags; + $metadata['source'] = $source; - $event = new DataUploadEvent($file['tmp_name'][$i], $metadata, $replace_id); - send_event($event); - if ($event->image_id == -1) { - throw new UploadException("MIME type not supported: " . $event->mime); - } - $image_ids[] = $event->image_id; - $page->add_http_header("X-Shimmie-Post-ID: " . $event->image_id); - } catch (UploadException $ex) { - $errors[] = new UploadError($file['name'][$i], $ex->getMessage()); + $event = new DataUploadEvent($tmp_name, $metadata, $replace_id); + send_event($event); + if ($event->image_id == -1) { + throw new UploadException("MIME type not supported: " . $event->mime); } + $results[] = new UploadSuccess($name, $event->image_id); + $page->add_http_header("X-Shimmie-Post-ID: " . $event->image_id); + } catch (UploadException $ex) { + $results[] = new UploadError($name, $ex->getMessage()); } - } catch (UploadException $ex) { - $errors[] = new UploadError('unknown', $ex->getMessage()); } - return [$image_ids, $errors]; + return $results; } + /** + * @return UploadResult[] + */ private function try_transload(string $url, array $tags, string $source = null, ?int $replace_id = null): array { global $page, $config, $user; - $image_ids = []; - $errors = []; + $results = []; $tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload"); try { @@ -415,15 +424,15 @@ class Upload extends Extension if ($event->image_id == -1) { throw new UploadException("File type not supported: " . $event->mime); } - $image_ids[] = $event->image_id; + $results[] = new UploadSuccess($url, $event->image_id); } catch (UploadException $ex) { - $errors[] = new UploadError($url, $ex->getMessage()); + $results[] = new UploadError($url, $ex->getMessage()); } finally { if (file_exists($tmp_filename)) { unlink($tmp_filename); } } - return [$image_ids, $errors]; + return $results; } } diff --git a/ext/upload/theme.php b/ext/upload/theme.php index 43a45fa5..fd7ca130 100644 --- a/ext/upload/theme.php +++ b/ext/upload/theme.php @@ -268,31 +268,33 @@ class UploadTheme extends Themelet } /** - * @param int[] $image_ids - * @param UploadError[] $errors + * @param UploadResult[] $results */ - public function display_upload_status(Page $page, array $image_ids, array $errors): void + public function display_upload_status(Page $page, array $results): void { global $user; + /** @var UploadSuccess[] */ + $successes = array_filter($results, fn ($r) => is_a($r, UploadSuccess::class)); + + /** @var UploadError[] */ + $errors = array_filter($results, fn ($r) => is_a($r, UploadError::class)); + if (count($errors) > 0) { $page->set_title("Upload Status"); $page->set_heading("Upload Status"); $page->add_block(new NavBlock()); foreach($errors as $error) { - $message = $error->error; - // this message has intentional HTML in it... - $message = str_contains($message, "already has hash") ? $message : html_escape($message); - $page->add_block(new Block($error->name, $message)); + $page->add_block(new Block($error->name, format_text($error->error))); } - } elseif (count($image_ids) == 0) { + } elseif (count($successes) == 0) { $page->set_title("No images uploaded"); $page->set_heading("No images uploaded"); $page->add_block(new NavBlock()); $page->add_block(new Block("No images uploaded", "Upload attempted, but nothing succeeded and nothing failed?")); - } elseif (count($image_ids) == 1) { + } elseif (count($successes) == 1) { $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(make_link("post/view/{$image_ids[0]}")); + $page->set_redirect(make_link("post/view/{$successes[0]->image_id}")); } else { $page->set_mode(PageMode::REDIRECT); $page->set_redirect(search_link(["poster={$user->name}"]));