allows('id')->andReturn($id); $source->allows('fieldsFor')->andReturn($fields); return $source; } private function stubPostTypes(): void { Functions\when('get_post_types')->justReturn([ 'post' => 'post', 'page' => 'page', 'attachment' => 'attachment', 'et_pb_layout' => 'et_pb_layout', 'lit_person' => 'lit_person', ]); } public function testPostTypeNamesExcludeInternalTypesAndAreSorted(): void { $this->stubPostTypes(); $schema = new ContentSchema([], null, ['et_pb_layout']); self::assertSame(['lit_person', 'page', 'post'], $schema->postTypeNames()); self::assertTrue($schema->isManaged('page')); self::assertFalse($schema->isManaged('et_pb_layout')); } public function testFieldsAreMergedByPriorityAndSorted(): void { $pods = $this->source('pods', [new FieldDefinition('role', 'Funktion', 'string', 'pods', 'writable', true)]); $meta = $this->source('sample', [ new FieldDefinition('role', 'role', 'unknown', 'sample', 'unknown'), new FieldDefinition('city', 'city', 'unknown', 'sample', 'unknown'), ]); $schema = new ContentSchema([$pods, $meta]); $fields = $schema->fields('lit_person'); self::assertSame(['city', 'role'], array_keys($fields)); self::assertSame('pods', $fields['role']->source); self::assertTrue($fields['role']->required); self::assertSame($pods, $schema->sourceOf($fields['role'])); self::assertSame($meta, $schema->sourceOf($fields['city'])); } public function testDescribeIncludesTaxonomiesCountsDiviAndOptionalFields(): void { $this->stubPostTypes(); Functions\when('get_post_type_object')->justReturn((object) [ 'hierarchical' => true, 'labels' => (object) ['name' => 'Seiten', 'singular_name' => 'Seite'], ]); Functions\when('get_all_post_type_supports')->justReturn(['title' => true, 'editor' => true]); Functions\when('wp_count_posts')->justReturn((object) ['publish' => 3, 'draft' => 2, 'trash' => 9]); Functions\when('get_object_taxonomies')->justReturn([ (object) ['name' => 'category', 'show_ui' => true, 'hierarchical' => true, 'labels' => (object) ['name' => 'Kategorien']], (object) ['name' => 'post_format', 'show_ui' => false, 'hierarchical' => false, 'labels' => (object) ['name' => 'Formate']], ]); $schema = new ContentSchema( [$this->source('meta', [ new FieldDefinition('footnotes', 'footnotes', 'string', 'meta', 'writable'), new FieldDefinition('zz_hidden', 'Verborgen', 'string', 'pods', FieldDefinition::HIDDEN), ])], static fn (string $type): bool => $type === 'page', ['et_pb_layout'] ); $withoutFields = $schema->describe('page', false); $withFields = $schema->describe('page', true); self::assertSame('Seiten', $withoutFields['label']); self::assertSame('Seite', $withoutFields['singular_label']); self::assertTrue($withoutFields['hierarchical']); self::assertSame(['title', 'editor'], $withoutFields['supports']); self::assertTrue($withoutFields['divi']); self::assertSame(5, $withoutFields['count']); self::assertSame([['name' => 'category', 'label' => 'Kategorien', 'hierarchical' => true]], $withoutFields['taxonomies']); self::assertArrayNotHasKey('fields', $withoutFields); self::assertSame('footnotes', $withFields['fields'][0]['key']); self::assertCount(1, $withFields['fields'], 'hidden (restricted) fields are not described (M4)'); self::assertNull($schema->describe('et_pb_layout', false)); } public function testMediaFieldKeysCoverFileFieldsAndMediaRelations(): void { Functions\when('get_post_types')->justReturn(['page' => 'page', 'lit_person' => 'lit_person']); $source = Mockery::mock(FieldSource::class); $source->allows('id')->andReturn('pods'); $source->allows('fieldsFor')->andReturnUsing(static fn (string $type): array => $type === 'lit_person' ? [ new FieldDefinition('photo', 'Foto', 'file', 'pods', 'writable'), new FieldDefinition('logo', 'Logo', 'relation', 'pods', 'writable', false, false, null, [ 'object_type' => 'media', 'name' => null, ]), new FieldDefinition('role', 'Funktion', 'string', 'pods', 'writable'), ] : [new FieldDefinition('photo', 'Foto', 'file', 'pods', 'writable')]); self::assertSame(['logo', 'photo'], (new ContentSchema([$source]))->mediaFieldKeys()); } public function testWordPressExcludesItsOwnPostTypesAndIntegrationsAddTheirs(): void { $this->stubPostTypes(); self::assertSame( ['et_pb_layout', 'lit_person', 'page', 'post'], (new ContentSchema([]))->postTypeNames(), 'without an integration the Divi layouts are an ordinary post type' ); self::assertSame( ['page', 'post'], (new ContentSchema([], null, ['et_pb_layout', 'lit_person']))->postTypeNames() ); self::assertSame( [ 'attachment', 'nav_menu_item', 'revision', 'wp_block', 'wp_template', 'wp_template_part', 'wp_navigation', 'wp_global_styles', 'wp_font_family', 'wp_font_face', ], ContentSchema::EXCLUDED ); } public function testTheBuilderIsNeverOnWithoutACheck(): void { self::assertFalse((new ContentSchema([]))->diviEnabled('page')); $schema = new ContentSchema([], static fn (string $type): bool => $type === 'page'); self::assertTrue($schema->diviEnabled('page')); self::assertFalse($schema->diviEnabled('post')); } }