From 91e1cf3abe5f3f28ceaba0984f431b0eb46c8234 Mon Sep 17 00:00:00 2001 From: Shish Date: Sun, 25 Feb 2024 19:33:34 +0000 Subject: [PATCH] [graphql] take post metadata as arbitrary key-value pairs I don't want "tags" and "source" to be special things where we explicitly handle those and fail to handle anything else. Making all metadata fields {string:string} pairs seems nicer, and matches with HTTP POST syntax --- ext/graphql/main.php | 43 ++++++++++++++------------------ ext/graphql/test.php | 58 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/ext/graphql/main.php b/ext/graphql/main.php index f485ae0b..cdc75a68 100644 --- a/ext/graphql/main.php +++ b/ext/graphql/main.php @@ -19,23 +19,24 @@ class MetadataInput { public function __construct( #[\GQLA\Field] - public string $tags, + public string $key, #[\GQLA\Field] - public string $source, + public string $value, ) { } - #[\GQLA\Mutation] - public static function update_post_metadata(int $post_id, MetadataInput $metadata): Image + /** + * @param array $metadata + */ + #[\GQLA\Mutation(args: ["post_id" => "Int!", "metadata" => "[MetadataInput!]!"])] + public static function update_post_metadata(int $post_id, array $metadata): Image { - global $user; $image = Image::by_id_ex($post_id); - if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) { - send_event(new ImageInfoSetEvent($image, 0, [ - 'tags' => $metadata->tags, - 'source' => $metadata->source, - ])); + $pairs = []; + foreach ($metadata as $m) { + $pairs[$m->key] = $m->value; } + send_event(new ImageInfoSetEvent($image, 0, $pairs)); return Image::by_id_ex($post_id); } } @@ -161,8 +162,7 @@ class GraphQL extends Extension return ["error" => "User cannot create posts"]; } - $common_tags = $_POST['common_tags']; - $common_source = $_POST['common_source']; + $metadata = only_strings($_POST); $results = []; for ($n = 0; $n < 100; $n++) { @@ -173,7 +173,7 @@ class GraphQL extends Extension break; } try { - $results[] = ["image_ids" => self::handle_upload($n, $common_tags, $common_source)]; + $results[] = ["image_ids" => self::handle_upload($n, $metadata)]; } catch(\Exception $e) { $results[] = ["error" => $e->getMessage()]; } @@ -182,9 +182,10 @@ class GraphQL extends Extension } /** + * @param array $metadata * @return int[] */ - private static function handle_upload(int $n, string $common_tags, string $common_source): array + private static function handle_upload(int $n, array $metadata): array { global $database; if (!empty($_POST["url$n"])) { @@ -199,20 +200,12 @@ class GraphQL extends Extension case UPLOAD_ERR_INI_SIZE: throw new UploadException("File larger than PHP can handle"); default: - throw new UploadException("Mystery error: $ec"); + throw new UploadException("Mystery error: ".var_export($ec, true)); } } - $tags = trim($common_tags . " " . $_POST["tags$n"]); - $source = $common_source; - if (!empty($_POST["source$n"])) { - $source = $_POST["source$n"]; - } - $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, - ])); + $event = $database->with_savepoint(function () use ($tmpname, $filename, $n, $metadata) { + return send_event(new DataUploadEvent($tmpname, $filename, $n, $metadata)); }); return array_map(fn ($im) => $im->id, $event->images); diff --git a/ext/graphql/test.php b/ext/graphql/test.php index 93ace1e0..f8a79ca0 100644 --- a/ext/graphql/test.php +++ b/ext/graphql/test.php @@ -56,13 +56,65 @@ class GraphQLTest extends ShimmiePHPUnitTestCase ], 'width' => 640, 'owner' => [ - 'id' => 'user:'.$image->get_owner()->id, + 'id' => 'user:' . $image->get_owner()->id, 'name' => self::$user_name, ], ], - ] - , + ], ], ], $result, var_export($result, true)); } + + public function testMutation(): void + { + $this->log_in_as_user(); + $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test"); + + $result = $this->graphql("mutation { + update_post_metadata( + post_id: $image_id, + metadata: [ + {key: \"tags\", value: \"newtag\"}, + {key: \"source\", value: \"https://example.com\"} + ] + ) { + id + tags + source + } + }"); + + $this->assertEquals([ + 'data' => [ + 'update_post_metadata' => [ + 'id' => "post:$image_id", + 'tags' => [ + 'newtag', + ], + 'source' => "https://example.com", + ], + ], + ], $result, var_export($result, true)); + } + + public function testUpload(): void + { + global $database; + + $this->log_in_as_user(); + $_FILES = [ + 'data0' => [ + 'name' => 'puppy-hugs.jpg', + 'type' => 'image/jpeg', + 'tmp_name' => 'tests/bedroom_workshop.jpg', + 'error' => 0, + 'size' => 271386, + ], + ]; + $page = $this->post_page("graphql_upload", ["tags" => "foo", "tags0" => "bar"]); + $this->assertEquals(200, $page->code); + $this->assertEquals(1, $database->get_one("SELECT COUNT(*) FROM images")); + $id = $database->get_one("SELECT id FROM images"); + $this->assertEquals("{\"results\":[{\"image_ids\":[$id]}]}", $page->data); + } }