> */ private function fieldsByKey(): array { Functions\when('get_registered_meta_keys')->alias(static function (string $type, string $sub = ''): array { if ($sub === '') { return ['footnotes' => ['type' => 'string', 'single' => true, 'show_in_rest' => true]]; } return [ '_internal' => ['type' => 'integer', 'single' => true, 'show_in_rest' => false], 'tags_list' => ['type' => 'array', 'single' => false, 'description' => 'Liste'], ]; }); Functions\when('is_protected_meta')->alias(static fn (string $key): bool => str_starts_with($key, '_')); $fields = (new RegisteredMetaSource())->fieldsFor('event'); return array_column(array_map(static fn (FieldDefinition $f): array => $f->toArray(), $fields), null, 'key'); } public function testDescribesGlobalAndSubtypeMetaKeys(): void { $fields = $this->fieldsByKey(); self::assertSame(['footnotes', '_internal', 'tags_list'], array_keys($fields)); self::assertSame('string', $fields['footnotes']['type']); self::assertSame(FieldDefinition::WRITABLE, $fields['footnotes']['status']); self::assertSame('meta', $fields['footnotes']['source']); self::assertFalse($fields['footnotes']['multiple']); } public function testProtectedMetaHiddenFromRestIsReadonly(): void { $fields = $this->fieldsByKey(); self::assertSame(FieldDefinition::READONLY, $fields['_internal']['status']); self::assertSame('integer', $fields['_internal']['type']); } public function testNonSingleMetaIsMultiple(): void { $fields = $this->fieldsByKey(); self::assertTrue($fields['tags_list']['multiple']); self::assertSame('Liste', $fields['tags_list']['description']); } public function testReadUsesSingleOrMultipleMeta(): void { Functions\expect('get_post_meta')->once()->with(5, 'footnotes', true)->andReturn('x'); Functions\expect('get_post_meta')->once()->with(5, 'tags_list', false)->andReturn(['a', 'b']); $source = new RegisteredMetaSource(); self::assertSame('x', $source->read(5, new FieldDefinition('footnotes', 'footnotes', 'string', 'meta', 'writable'))); self::assertSame( ['a', 'b'], $source->read(5, new FieldDefinition('tags_list', 'tags_list', 'array', 'meta', 'writable', false, true)) ); } public function testWriteUpdatesReplacesListsAndDeletesNull(): void { $single = new FieldDefinition('footnotes', 'footnotes', 'string', 'meta', 'writable'); $multi = new FieldDefinition('tags_list', 'tags_list', 'array', 'meta', 'writable', false, true); $gone = new FieldDefinition('old', 'old', 'string', 'meta', 'writable'); Functions\expect('update_post_meta')->once()->with(5, 'footnotes', 'neu'); Functions\expect('delete_post_meta')->once()->with(5, 'tags_list'); Functions\expect('add_post_meta')->once()->with(5, 'tags_list', 'a'); Functions\expect('add_post_meta')->once()->with(5, 'tags_list', 'b'); Functions\expect('delete_post_meta')->once()->with(5, 'old'); (new RegisteredMetaSource())->write( 5, 'event', ['footnotes' => 'neu', 'tags_list' => ['a', 'b'], 'old' => null], ['footnotes' => $single, 'tags_list' => $multi, 'old' => $gone] ); } public function testUnchangedValueIsNotAFailure(): void { $field = new FieldDefinition('count', 'count', 'integer', 'meta', 'writable'); Functions\expect('update_post_meta')->once()->with(5, 'count', 3)->andReturn(false); Functions\expect('get_post_meta')->once()->with(5, 'count', false)->andReturn(['3']); (new RegisteredMetaSource())->write(5, 'event', ['count' => 3], ['count' => $field]); self::addToAssertionCount(1); } public function testFailedUpdateThrows(): void { $field = new FieldDefinition('count', 'count', 'integer', 'meta', 'writable'); Functions\when('update_post_meta')->justReturn(false); Functions\when('get_post_meta')->justReturn(['2']); $this->expectException(RuntimeException::class); (new RegisteredMetaSource())->write(5, 'event', ['count' => 3], ['count' => $field]); } public function testFailedDeleteOfAnExistingKeyThrows(): void { $field = new FieldDefinition('old', 'old', 'string', 'meta', 'writable'); Functions\when('delete_post_meta')->justReturn(false); Functions\expect('metadata_exists')->once()->with('post', 5, 'old')->andReturn(true); $this->expectException(RuntimeException::class); (new RegisteredMetaSource())->write(5, 'event', ['old' => null], ['old' => $field]); } public function testDeletingAMissingKeyIsNotAFailure(): void { $field = new FieldDefinition('old', 'old', 'string', 'meta', 'writable'); Functions\when('delete_post_meta')->justReturn(false); Functions\expect('metadata_exists')->once()->with('post', 5, 'old')->andReturn(false); (new RegisteredMetaSource())->write(5, 'event', ['old' => null], ['old' => $field]); self::addToAssertionCount(1); } public function testFailedAddOfAListItemThrows(): void { $multi = new FieldDefinition('tags_list', 'tags_list', 'array', 'meta', 'writable', false, true); Functions\when('delete_post_meta')->justReturn(true); Functions\when('add_post_meta')->justReturn(false); $this->expectException(RuntimeException::class); (new RegisteredMetaSource())->write(5, 'event', ['tags_list' => ['a']], ['tags_list' => $multi]); } }