[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
This commit is contained in:
Shish 2024-02-25 19:33:34 +00:00 committed by Shish
parent b9c7d632fd
commit 91e1cf3abe
2 changed files with 73 additions and 28 deletions

View file

@ -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<MetadataInput> $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<string, string> $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);

View file

@ -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);
}
}