diff --git a/core/extension.php b/core/extension.php index 30b9fd71..06aed427 100644 --- a/core/extension.php +++ b/core/extension.php @@ -341,7 +341,8 @@ abstract class DataHandlerExtension extends Extension // we can just send a TagSetEvent - in the future we might // want a dedicated MergeEvent? if(!empty($event->metadata['tags'])) { - send_event(new TagSetEvent($existing, array_merge($existing->get_tag_array(), $event->metadata['tags']))); + $tags = Tag::explode($existing->get_tag_list() . " " . $event->metadata['tags']); + send_event(new TagSetEvent($existing, $tags)); } $event->images[] = $existing; return; @@ -357,11 +358,9 @@ abstract class DataHandlerExtension extends Extension $image->tmp_file = $filename; $image->filesize = \Safe\filesize($filename); $image->hash = \Safe\md5_file($filename); - $image->filename = (($pos = strpos($event->metadata['filename'], '?')) !== false) ? substr($event->metadata['filename'], 0, $pos) : $event->metadata['filename']; - $image->set_mime(MimeType::get_for_file($filename, get_file_ext($event->metadata["filename"]) ?? null)); - if (empty($image->get_mime())) { - throw new UploadException("Unable to determine MIME for $filename"); - } + // DB limits to 255 char filenames + $image->filename = substr($event->filename, -250); + $image->set_mime($event->mime); try { send_event(new MediaCheckPropertiesEvent($image)); } catch (MediaException $e) { @@ -369,8 +368,8 @@ abstract class DataHandlerExtension extends Extension } $image->save_to_db(); // Ensure the image has a DB-assigned ID - // Let everybody else know, so that TagEdit can set tags, Ratings can set ratings, etc - $iae = send_event(new ImageAdditionEvent($image, $event->metadata)); + $iae = send_event(new ImageAdditionEvent($image)); + send_event(new ImageInfoSetEvent($image, $event->slot, $event->metadata)); // If everything is OK, then move the file to the archive $filename = warehouse_path(Image::IMAGE_DIR, $event->hash); diff --git a/core/imageboard/event.php b/core/imageboard/event.php index f7be1f2b..42bb8be2 100644 --- a/core/imageboard/event.php +++ b/core/imageboard/event.php @@ -10,14 +10,12 @@ namespace Shimmie2; class ImageAdditionEvent extends Event { /** - * Inserts a new image into the database with its associated - * information. - * - * @param mixed[] $metadata + * A new image is being added to the database - just the image, + * metadata will come later with ImageInfoSetEvent (and if that + * fails, then the image addition transaction will be rolled back) */ public function __construct( public Image $image, - public array $metadata, ) { parent::__construct(); } diff --git a/core/imageboard/misc.php b/core/imageboard/misc.php index fa07d453..d267aa39 100644 --- a/core/imageboard/misc.php +++ b/core/imageboard/misc.php @@ -27,10 +27,9 @@ function add_dir(string $base, array $extra_tags = []): array $tags = array_merge(path_to_tags($short_path), $extra_tags); try { $more_results = $database->with_savepoint(function () use ($full_path, $filename, $tags) { - $dae = send_event(new DataUploadEvent($full_path, [ + $dae = send_event(new DataUploadEvent($full_path, basename($full_path), 0, [ 'filename' => pathinfo($filename, PATHINFO_BASENAME), - 'tags' => $tags, - 'source' => null, + 'tags' => Tag::implode($tags), ])); $results = []; foreach($dae->images as $image) { diff --git a/core/testcase.php b/core/testcase.php index 1f847c5a..839c6f63 100644 --- a/core/testcase.php +++ b/core/testcase.php @@ -257,10 +257,9 @@ if(class_exists("\\PHPUnit\\Framework\\TestCase")) { // post things protected function post_image(string $filename, string $tags): int { - $dae = send_event(new DataUploadEvent($filename, [ + $dae = send_event(new DataUploadEvent($filename, basename($filename), 0, [ "filename" => $filename, - "tags" => Tag::explode($tags), - "source" => null, + "tags" => $tags, ])); if(count($dae->images) == 0) { throw new \Exception("Upload failed :("); diff --git a/core/util.php b/core/util.php index 56338e0f..05c58474 100644 --- a/core/util.php +++ b/core/util.php @@ -208,6 +208,22 @@ function format_text(string $string): string return $event->formatted; } +/** + * Take a map of string to string-or-array, return only the string-to-string subset + * + * @param array $map + * @return array + */ +function only_strings(array $map): array +{ + $out = []; + foreach ($map as $k => $v) { + if (is_string($v)) { + $out[$k] = $v; + } + } + return $out; +} /** * Generates the path to a file under the data folder based on the file's hash. * This process creates subfolders based on octet pairs from the file's hash. diff --git a/ext/artists/main.php b/ext/artists/main.php index dcb28021..9ea279ce 100644 --- a/ext/artists/main.php +++ b/ext/artists/main.php @@ -38,8 +38,9 @@ class Artists extends Extension public function onImageInfoSet(ImageInfoSetEvent $event): void { global $user; - if ($user->can(Permissions::EDIT_IMAGE_ARTIST) && isset($event->params["author"])) { - send_event(new AuthorSetEvent($event->image, $user, $event->params["author"])); + $author = $event->get_param("author"); + if ($user->can(Permissions::EDIT_IMAGE_ARTIST) && $author) { + send_event(new AuthorSetEvent($event->image, $user, $author)); } } diff --git a/ext/bulk_add_csv/main.php b/ext/bulk_add_csv/main.php index ec668da6..ce0a5680 100644 --- a/ext/bulk_add_csv/main.php +++ b/ext/bulk_add_csv/main.php @@ -56,9 +56,8 @@ class BulkAddCSV extends Extension { global $database; $database->with_savepoint(function () use ($tmpname, $filename, $tags, $source, $rating, $thumbfile) { - $event = send_event(new DataUploadEvent($tmpname, [ - 'filename' => pathinfo($filename, PATHINFO_BASENAME), - 'tags' => $tags, + $event = send_event(new DataUploadEvent($tmpname, basename($filename), 0, [ + 'tags' => Tag::implode($tags), 'source' => $source, 'rating' => $rating, ])); diff --git a/ext/bulk_import_export/main.php b/ext/bulk_import_export/main.php index 0b614024..5628c2f9 100644 --- a/ext/bulk_import_export/main.php +++ b/ext/bulk_import_export/main.php @@ -49,10 +49,8 @@ class BulkImportExport extends DataHandlerExtension file_put_contents($tmpfile, $stream); $database->with_savepoint(function () use ($item, $tmpfile, $event) { - $images = send_event(new DataUploadEvent($tmpfile, [ - 'filename' => pathinfo($item->filename, PATHINFO_BASENAME), + $images = send_event(new DataUploadEvent($tmpfile, basename($item->filename), 0, [ 'tags' => $item->new_tags, - 'source' => null, ]))->images; if (count($images) == 0) { diff --git a/ext/cron_uploader/main.php b/ext/cron_uploader/main.php index 5970c559..95158641 100644 --- a/ext/cron_uploader/main.php +++ b/ext/cron_uploader/main.php @@ -455,10 +455,8 @@ class CronUploader extends Extension */ private function add_image(string $tmpname, string $filename, array $tags): DataUploadEvent { - $event = send_event(new DataUploadEvent($tmpname, [ - 'filename' => pathinfo($filename, PATHINFO_BASENAME), - 'tags' => $tags, - 'source' => null, + $event = send_event(new DataUploadEvent($tmpname, basename($filename), 0, [ + 'tags' => Tag::implode($tags), ])); // Generate info message diff --git a/ext/danbooru_api/main.php b/ext/danbooru_api/main.php index 4211ecb3..7c380ccc 100644 --- a/ext/danbooru_api/main.php +++ b/ext/danbooru_api/main.php @@ -362,8 +362,7 @@ class DanbooruApi extends Extension try { $newimg = $database->with_savepoint(function () use ($file, $filename, $posttags, $source) { // Fire off an event which should process the new file and add it to the db - $dae = send_event(new DataUploadEvent($file, [ - 'filename' => pathinfo($filename, PATHINFO_BASENAME), + $dae = send_event(new DataUploadEvent($file, basename($filename), 0, [ 'tags' => $posttags, 'source' => $source, ])); diff --git a/ext/favorites/main.php b/ext/favorites/main.php index afdd58c3..7a681ab4 100644 --- a/ext/favorites/main.php +++ b/ext/favorites/main.php @@ -93,12 +93,13 @@ class Favorites extends Extension public function onImageInfoSet(ImageInfoSetEvent $event): void { global $user; + $action = $event->get_param("favorite_action"); if ( $user->can(Permissions::EDIT_FAVOURITES) && - in_array('favorite_action', $event->params) && - (($event->params['favorite_action'] == "set") || ($event->params['favorite_action'] == "unset")) + !is_null($action) && + ($action == "set" || $action == "unset") ) { - send_event(new FavoriteSetEvent($event->image->id, $user, ($event->params['favorite_action'] == "set"))); + send_event(new FavoriteSetEvent($event->image->id, $user, $action == "set")); } } diff --git a/ext/graphql/main.php b/ext/graphql/main.php index bc394af0..466c11c2 100644 --- a/ext/graphql/main.php +++ b/ext/graphql/main.php @@ -31,7 +31,7 @@ class MetadataInput global $user; $image = Image::by_id_ex($post_id); if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) { - send_event(new ImageInfoSetEvent($image, [ + send_event(new ImageInfoSetEvent($image, 0, [ 'tags' => $metadata->tags, 'source' => $metadata->source, ])); @@ -176,9 +176,8 @@ class GraphQL extends Extension if (!empty($_POST["source$n"])) { $source = $_POST["source$n"]; } - $event = $database->with_savepoint(function () use ($tmpname, $filename, $tags, $source) { - return send_event(new DataUploadEvent($tmpname, [ - 'filename' => $filename, + $event = $database->with_savepoint(function () use ($tmpname, $filename, $n, $tags, $source) { + return send_event(new DataUploadEvent($tmpname, $filename, $n, [ 'tags' => Tag::explode($tags), 'source' => $source, ])); diff --git a/ext/handle_archive/main.php b/ext/handle_archive/main.php index d940f862..061705ff 100644 --- a/ext/handle_archive/main.php +++ b/ext/handle_archive/main.php @@ -35,7 +35,7 @@ class ArchiveFileHandler extends DataHandlerExtension exec($cmd); if (file_exists($tmpdir)) { try { - $results = add_dir($tmpdir, $event->metadata['tags']); + $results = add_dir($tmpdir, Tag::explode($event->metadata['tags'])); foreach ($results as $r) { if(is_a($r, UploadError::class)) { $page->flash($r->name." failed: ".$r->error); diff --git a/ext/ouroboros_api/main.php b/ext/ouroboros_api/main.php index 91fb848b..6aae49fe 100644 --- a/ext/ouroboros_api/main.php +++ b/ext/ouroboros_api/main.php @@ -338,7 +338,7 @@ class OuroborosAPI extends Extension } } $meta = []; - $meta['tags'] = Tag::explode($post->tags); + $meta['tags'] = $post->tags; $meta['source'] = $post->source; if (Extension::is_enabled(RatingsInfo::KEY) !== false) { $meta['rating'] = $post->rating; @@ -358,12 +358,12 @@ class OuroborosAPI extends Extension $this->sendResponse(500, "Transloading failed: $e"); return; } - $meta['hash'] = md5_file($meta['file']); + $meta['hash'] = \Safe\md5_file($meta['file']); } else { // Use file $meta['file'] = $post->file['tmp_name']; $meta['filename'] = $post->file['name']; - $meta['hash'] = md5_file($meta['file']); + $meta['hash'] = \Safe\md5_file($meta['file']); } if (!empty($md5) && $md5 !== $meta['hash']) { $this->sendResponse(420, self::ERROR_POST_CREATE_MD5); @@ -390,10 +390,9 @@ class OuroborosAPI extends Extension } } } - $meta['extension'] = pathinfo($meta['filename'], PATHINFO_EXTENSION); try { $image = $database->with_savepoint(function () use ($meta) { - $dae = send_event(new DataUploadEvent($meta['file'], $meta)); + $dae = send_event(new DataUploadEvent($meta['file'], basename($meta['file']), 0, $meta)); return $dae->images[0]; }); $this->sendResponse(200, make_link('post/view/' . $image->id), true); diff --git a/ext/post_lock/main.php b/ext/post_lock/main.php index 5675af71..ec2a5705 100644 --- a/ext/post_lock/main.php +++ b/ext/post_lock/main.php @@ -22,13 +22,6 @@ class PostLock extends Extension /** @var PostLockTheme */ protected Themelet $theme; - public function onImageAddition(ImageAdditionEvent $event): void - { - if (!empty($event->metadata['locked'])) { - send_event(new LockSetEvent($event->image, $event->metadata['locked'])); - } - } - public function onImageInfoSet(ImageInfoSetEvent $event): void { global $page, $user; @@ -36,7 +29,7 @@ class PostLock extends Extension throw new PermissionDenied("Error: This image is locked and cannot be edited."); } if ($user->can(Permissions::EDIT_IMAGE_LOCK)) { - $locked = isset($event->params['locked']) && $event->params['locked'] == "on"; + $locked = $event->get_param('locked') == "on"; send_event(new LockSetEvent($event->image, $locked)); } } diff --git a/ext/post_lock/test.php b/ext/post_lock/test.php index e451651c..f4b2ec9e 100644 --- a/ext/post_lock/test.php +++ b/ext/post_lock/test.php @@ -14,24 +14,24 @@ class PostLockTest extends ShimmiePHPUnitTestCase // admin can lock $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["locked" => "on"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), 0, ["locked" => "on"])); // user can't edit locked post $this->log_in_as_user(); $this->assertException(PermissionDenied::class, function () use ($image_id) { - send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), 0, ["source" => "http://example.com"])); }); // admin can edit locked post $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), 0, ["source" => "http://example.com"])); // admin can unlock $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), [])); // "locked" is not set + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), 0, [])); // "locked" is not set // user can edit un-locked post $this->log_in_as_user(); - send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), 0, ["source" => "http://example.com"])); } } diff --git a/ext/post_owner/main.php b/ext/post_owner/main.php index 3514921c..3c871292 100644 --- a/ext/post_owner/main.php +++ b/ext/post_owner/main.php @@ -22,18 +22,14 @@ class PostOwner extends Extension /** @var PostOwnerTheme */ protected Themelet $theme; - public function onImageAddition(ImageAdditionEvent $event): void - { - // FIXME: send an event instead of implicit default owner? - } - public function onImageInfoSet(ImageInfoSetEvent $event): void { global $page, $user; - if ($user->can(Permissions::EDIT_IMAGE_OWNER) && isset($event->params['owner'])) { - $owner = User::by_name($event->params['owner']); - if ($owner instanceof User) { - send_event(new OwnerSetEvent($event->image, $owner)); + $owner = $event->get_param('owner'); + if ($user->can(Permissions::EDIT_IMAGE_OWNER) && !is_null($owner)) { + $owner_ob = User::by_name($owner); + if (!is_null($owner_ob)) { + send_event(new OwnerSetEvent($event->image, $owner_ob)); } else { throw new UserNotFound("Error: No user with that name was found."); } diff --git a/ext/post_owner/test.php b/ext/post_owner/test.php index 35c14c2e..2f049dc8 100644 --- a/ext/post_owner/test.php +++ b/ext/post_owner/test.php @@ -13,7 +13,7 @@ class PostOwnerTest extends ShimmiePHPUnitTestCase $image = Image::by_id_ex($image_id); $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent($image, ["owner" => self::$admin_name])); + send_event(new ImageInfoSetEvent($image, 0, ["owner" => self::$admin_name])); $this->log_in_as_user(); $this->get_page("post/view/$image_id"); diff --git a/ext/post_source/main.php b/ext/post_source/main.php index cdc42085..b1808453 100644 --- a/ext/post_source/main.php +++ b/ext/post_source/main.php @@ -32,19 +32,16 @@ class PostSource extends Extension } } - public function onImageAddition(ImageAdditionEvent $event): void - { - if(!empty($event->metadata['source'])) { - send_event(new SourceSetEvent($event->image, $event->metadata['source'])); - } - } - public function onImageInfoSet(ImageInfoSetEvent $event): void { - global $page, $user; - if ($user->can(Permissions::EDIT_IMAGE_SOURCE) && isset($event->params['source'])) { + global $config, $page, $user; + $source = $event->get_param('source'); + if(is_null($source) && $config->get_bool(UploadConfig::TLSOURCE)) { + $source = $event->get_param('url'); + } + if ($user->can(Permissions::EDIT_IMAGE_SOURCE) && !is_null($source)) { if (isset($event->params['tags']) ? !preg_match('/source[=|:]/', $event->params["tags"]) : true) { - send_event(new SourceSetEvent($event->image, $event->params['source'])); + send_event(new SourceSetEvent($event->image, $source)); } } } diff --git a/ext/post_source/test.php b/ext/post_source/test.php index 19fd0f7f..51260152 100644 --- a/ext/post_source/test.php +++ b/ext/post_source/test.php @@ -12,8 +12,8 @@ class PostSourceTest extends ShimmiePHPUnitTestCase $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); $image = Image::by_id_ex($image_id); - send_event(new ImageInfoSetEvent($image, ["source" => "example.com"])); - send_event(new ImageInfoSetEvent($image, ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent($image, 0, ["source" => "example.com"])); + send_event(new ImageInfoSetEvent($image, 0, ["source" => "http://example.com"])); $this->get_page("post/view/$image_id"); $this->assert_text("example.com"); diff --git a/ext/post_tags/main.php b/ext/post_tags/main.php index 452556ca..bb569e47 100644 --- a/ext/post_tags/main.php +++ b/ext/post_tags/main.php @@ -121,19 +121,20 @@ class PostTags extends Extension }); } - public function onImageAddition(ImageAdditionEvent $event): void - { - if(!empty($event->metadata['tags'])) { - send_event(new TagSetEvent($event->image, $event->metadata['tags'])); - } - } - public function onImageInfoSet(ImageInfoSetEvent $event): void { global $page, $user; - if ($user->can(Permissions::EDIT_IMAGE_TAG) && isset($event->params['tags'])) { + if ( + $user->can(Permissions::EDIT_IMAGE_TAG) && ( + isset($event->params['tags']) + || isset($event->params["tags{$event->slot}"]) + ) + ) { + $common_tags = $event->params['tags'] ?? ""; + $my_tags = $event->params["tags{$event->slot}"] ?? ""; + $tags = Tag::explode("$common_tags $my_tags"); try { - send_event(new TagSetEvent($event->image, Tag::explode($event->params['tags']))); + send_event(new TagSetEvent($event->image, $tags)); } catch (TagSetException $e) { if ($e->redirect) { $page->flash("{$e->getMessage()}, please see {$e->redirect}"); diff --git a/ext/post_titles/main.php b/ext/post_titles/main.php index 54bf8ade..11557780 100644 --- a/ext/post_titles/main.php +++ b/ext/post_titles/main.php @@ -55,9 +55,9 @@ class PostTitles extends Extension public function onImageInfoSet(ImageInfoSetEvent $event): void { global $user; - - if ($user->can(Permissions::EDIT_IMAGE_TITLE) && isset($event->params["title"])) { - send_event(new PostTitleSetEvent($event->image, $event->params["title"])); + $title = $event->get_param('title'); + if ($user->can(Permissions::EDIT_IMAGE_TITLE) && !is_null($title)) { + send_event(new PostTitleSetEvent($event->image, $title)); } } diff --git a/ext/rating/main.php b/ext/rating/main.php index 6627a136..04b04f7a 100644 --- a/ext/rating/main.php +++ b/ext/rating/main.php @@ -158,13 +158,6 @@ class Ratings extends Extension $sb->end_table(); } - public function onImageAddition(ImageAdditionEvent $event): void - { - if(!empty($event->metadata['rating'])) { - send_event(new RatingSetEvent($event->image, $event->metadata['rating'])); - } - } - public function onDisplayingImage(DisplayingImageEvent $event): void { global $page; @@ -216,8 +209,8 @@ class Ratings extends Extension public function onImageInfoSet(ImageInfoSetEvent $event): void { global $user; - if ($user->can(Permissions::EDIT_IMAGE_RATING) && isset($event->params["rating"])) { - $rating = $event->params["rating"]; + $rating = $event->get_param('rating'); + if ($user->can(Permissions::EDIT_IMAGE_RATING) && !is_null($rating)) { if (Ratings::rating_is_valid($rating)) { send_event(new RatingSetEvent($event->image, $rating)); } diff --git a/ext/upload/main.php b/ext/upload/main.php index c77509a6..a7e2219c 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -24,21 +24,22 @@ class DataUploadEvent extends Event * Some data is being uploaded. * This should be caught by a file handler. * - * @param array $metadata + * @param string $tmpname The name of a physical file on the local hard drive. + * @param string $filename The name of the file as it was uploaded. + * @param int $slot The slot number of the upload. + * @param array $metadata Key-value pairs of metadata, the + * upload form can contain both common and slot-specific fields such as + * "source" and "source12", in which case the slot-specific field will + * override the common one. */ public function __construct( public string $tmpname, + public string $filename, + public int $slot, public array $metadata, ) { parent::__construct(); - $this->set_tmpname($tmpname); - assert(is_string($metadata["filename"])); - assert(is_array($metadata["tags"])); - assert(is_string($metadata["source"]) || is_null($metadata["source"])); - - // DB limits to 255 char filenames - $metadata['filename'] = substr($metadata['filename'], 0, 255); } public function set_tmpname(string $tmpname, ?string $mime = null): void @@ -47,7 +48,7 @@ class DataUploadEvent extends Event $this->tmpname = $tmpname; $this->hash = \Safe\md5_file($tmpname); $this->size = \Safe\filesize($tmpname); - $mime = $mime ?? MimeType::get_for_file($tmpname, get_file_ext($this->metadata["filename"]) ?? null); + $mime = $mime ?? MimeType::get_for_file($tmpname, get_file_ext($this->filename)); if (empty($mime)) { throw new UploadException("Could not determine mime type"); } @@ -235,9 +236,7 @@ class Upload extends Extension }); foreach ($files as $name => $file) { $slot = int_escape(substr($name, 4)); - $tags = $this->tags_for_upload_slot($event->POST, $slot); - $source = $this->source_for_upload_slot($event->POST, $slot); - $results = array_merge($results, $this->try_upload($file, $tags, $source)); + $results = array_merge($results, $this->try_upload($file, $slot, only_strings($event->POST))); } $urls = array_filter($event->POST, function ($value, $key) { @@ -245,48 +244,13 @@ class Upload extends Extension }, ARRAY_FILTER_USE_BOTH); foreach ($urls as $name => $value) { $slot = int_escape(substr($name, 3)); - $tags = $this->tags_for_upload_slot($event->POST, $slot); - $source = $this->source_for_upload_slot($event->POST, $slot); - $results = array_merge($results, $this->try_transload($value, $tags, $source)); + $results = array_merge($results, $this->try_transload($value, $slot, only_strings($event->POST))); } $this->theme->display_upload_status($page, $results); } } - /** - * @param array $params - * @return string[] - */ - private function tags_for_upload_slot(array $params, int $id): array - { - # merge then explode, not explode then merge - else - # one of the merges may create a surplus "tagme" - return Tag::explode( - ($params["tags"] ?? "") . - " " . - ($params["tags$id"] ?? "") - ); - } - - /** - * @param array $params - */ - private function source_for_upload_slot(array $params, int $id): ?string - { - global $config; - if(!empty($params["source$id"])) { - return $params["source$id"]; - } - if(!empty($params['source'])) { - return $params['source']; - } - if($config->get_bool(UploadConfig::TLSOURCE) && !empty($params["url$id"])) { - return $params["url$id"]; - } - return null; - } - /** * Returns a descriptive error message for the specified PHP error code. * @@ -320,10 +284,10 @@ class Upload extends Extension /** * Handle an upload. * @param mixed[] $file - * @param string[] $tags + * @param array $metadata * @return UploadResult[] */ - private function try_upload(array $file, array $tags, ?string $source = null): array + private function try_upload(array $file, int $slot, array $metadata): array { global $page, $config, $database; @@ -332,10 +296,6 @@ class Upload extends Extension return []; } - if (empty($source)) { - $source = null; - } - $results = []; for ($i = 0; $i < count($file['name']); $i++) { @@ -352,12 +312,8 @@ class Upload extends Extension throw new UploadException($this->upload_error_message($error)); } - $new_images = $database->with_savepoint(function () use ($tmp_name, $name, $tags, $source) { - $event = send_event(new DataUploadEvent($tmp_name, [ - 'filename' => pathinfo($name, PATHINFO_BASENAME), - 'tags' => $tags, - 'source' => $source, - ])); + $new_images = $database->with_savepoint(function () use ($tmp_name, $name, $slot, $metadata) { + $event = send_event(new DataUploadEvent($tmp_name, basename($name), $slot, $metadata)); if (count($event->images) == 0) { throw new UploadException("MIME type not supported: " . $event->mime); } @@ -375,10 +331,10 @@ class Upload extends Extension } /** - * @param string[] $tags + * @param array $metadata * @return UploadResult[] */ - private function try_transload(string $url, array $tags, string $source = null): array + private function try_transload(string $url, int $slot, array $metadata): array { global $page, $config, $user, $database; @@ -398,13 +354,8 @@ class Upload extends Extension $h_filename = ($s_filename ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null); $filename = $h_filename ?: basename($url); - $metadata = []; - $metadata['filename'] = $filename; - $metadata['tags'] = $tags; - $metadata['source'] = $source; - - $new_images = $database->with_savepoint(function () use ($tmp_filename, $metadata) { - $event = send_event(new DataUploadEvent($tmp_filename, $metadata)); + $new_images = $database->with_savepoint(function () use ($tmp_filename, $filename, $slot, $metadata) { + $event = send_event(new DataUploadEvent($tmp_filename, $filename, $slot, $metadata)); if (count($event->images) == 0) { throw new UploadException("File type not supported: " . $event->mime); } diff --git a/ext/view/events/image_info_set_event.php b/ext/view/events/image_info_set_event.php index e5d982c5..3ad7ff2e 100644 --- a/ext/view/events/image_info_set_event.php +++ b/ext/view/events/image_info_set_event.php @@ -7,16 +7,43 @@ namespace Shimmie2; class ImageInfoSetEvent extends Event { public Image $image; + public int $slot; /** @var array */ public array $params; /** + * currently all post metadata is string => string - in the future + * we might want to have a more complex type system, but for now + * we just filter out non-string keys (eg, `only_strings($_POST)`) + * * @param array $params */ - public function __construct(Image $image, array $params) + public function __construct(Image $image, int $slot, array $params) { parent::__construct(); $this->image = $image; + $this->slot = $slot; $this->params = $params; } + + /** + * Get a slot-specific value, or a common value, or null. This allows + * a user to POST an update to multiple images at once, setting eg + * "source" to be a common default source and "source12" to be a + * specific source for image 12. + * + * Specifically we check for "empty" rather than "isset" because + * the upload form might have a "source" field that is empty, and + * we want to allow non-empty values to override empty ones. + */ + public function get_param(string $name): ?string + { + if(!empty($this->params["$name{$this->slot}"])) { + return $this->params["$name{$this->slot}"]; + } + if(!empty($this->params[$name])) { + return $this->params[$name]; + } + return null; + } } diff --git a/ext/view/main.php b/ext/view/main.php index 7b10f19a..44314825 100644 --- a/ext/view/main.php +++ b/ext/view/main.php @@ -66,12 +66,7 @@ class ViewPost extends Extension $image_id = int_escape($event->req_POST('image_id')); $image = Image::by_id_ex($image_id); if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) { - // currently all post metadata is string => string - in the future - // we might want to have a more complex type system, but for now - // we just filter out non-string keys - /** @var array */ - $kvs = array_filter($event->POST, 'is_string', ARRAY_FILTER_USE_KEY); - send_event(new ImageInfoSetEvent($image, $kvs)); + send_event(new ImageInfoSetEvent($image, 0, only_strings($event->POST))); $page->set_mode(PageMode::REDIRECT); if ($event->get_GET('search')) {