From 1166e999515f80ef57b92fdee9da642292d78d6c Mon Sep 17 00:00:00 2001 From: Nicolas Jaussaud Date: Tue, 19 May 2026 19:41:43 +0200 Subject: [PATCH 1/4] Field Type Registry: Share custom types across instances --- src/DataView/FieldTypeRegistry.php | 20 ++++++++-------- tests/phpunit/data-view.php | 37 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/DataView/FieldTypeRegistry.php b/src/DataView/FieldTypeRegistry.php index 867084c..baddcdd 100644 --- a/src/DataView/FieldTypeRegistry.php +++ b/src/DataView/FieldTypeRegistry.php @@ -14,17 +14,17 @@ class FieldTypeRegistry { * * @var array */ - protected array $types = []; + protected static array $types = []; public function __construct() { - $this->register_default_types(); + if ( empty( static::$types ) ) $this->register_default_types(); } /** * Register the default field types. */ protected function register_default_types(): void { - $this->types = [ + static::$types = [ 'string' => [ 'dataset' => DataSet::TYPE_STRING, 'sanitizer' => 'sanitize_text_field', @@ -91,7 +91,7 @@ protected function register_default_types(): void { */ public function get_dataset_type( string $type ): string { $this->validate_type( $type ); - return $this->types[ $type ]['dataset']; + return static::$types[ $type ]['dataset']; } /** @@ -103,7 +103,7 @@ public function get_dataset_type( string $type ): string { */ public function get_sanitizer( string $type ): callable { $this->validate_type( $type ); - return $this->types[ $type ]['sanitizer']; + return static::$types[ $type ]['sanitizer']; } /** @@ -115,7 +115,7 @@ public function get_sanitizer( string $type ): callable { */ public function get_schema( string $type ): array { $this->validate_type( $type ); - return $this->types[ $type ]['schema']; + return static::$types[ $type ]['schema']; } /** @@ -127,7 +127,7 @@ public function get_schema( string $type ): array { */ public function get_input_type( string $type ): string { $this->validate_type( $type ); - return $this->types[ $type ]['input']; + return static::$types[ $type ]['input']; } /** @@ -137,7 +137,7 @@ public function get_input_type( string $type ): string { * @return bool True if type is registered. */ public function has_type( string $type ): bool { - return isset( $this->types[ $type ] ); + return isset( static::$types[ $type ] ); } /** @@ -155,7 +155,7 @@ public function register_type( string $name, array $config ): void { ); } } - $this->types[ $name ] = $config; + static::$types[ $name ] = $config; } /** @@ -167,7 +167,7 @@ public function register_type( string $name, array $config ): void { protected function validate_type( string $type ): void { if ( ! $this->has_type( $type ) ) { throw new \InvalidArgumentException( - sprintf( 'Unknown field type "%s". Available types: %s', $type, implode( ', ', array_keys( $this->types ) ) ) + sprintf( 'Unknown field type "%s". Available types: %s', $type, implode( ', ', array_keys( static::$types ) ) ) ); } } diff --git a/tests/phpunit/data-view.php b/tests/phpunit/data-view.php index 4926629..120a89d 100644 --- a/tests/phpunit/data-view.php +++ b/tests/phpunit/data-view.php @@ -54,6 +54,43 @@ public function test_field_type_registry_has_default_types(): void { $this->assertTrue( $registry->has_type( 'datetime' ) ); } + public function test_field_type_registry_has_shared_custom_types(): void { + $registry_1 = new FieldTypeRegistry(); + $registry_2 = new FieldTypeRegistry(); + + $registry_1->register_type( 'custom_type_1', [ + 'dataset' => DataSet::TYPE_STRING, + 'sanitizer' => fn( $value ) => ( $value ), + 'schema' => [], + 'input' => 'hidden', + ] ); + + $registry_2->register_type( 'custom_type_2', [ + 'dataset' => DataSet::TYPE_INTEGER, + 'sanitizer' => fn( $value ) => ( $value ), + 'schema' => [], + 'input' => 'hidden', + ] ); + + foreach( [ + $registry_1, + $registry_2 + ] as $registry ) { + $this->assertTrue( $registry->has_type( 'custom_type_1' ) ); + $this->assertTrue( $registry->has_type( 'custom_type_2' ) ); + + // Check defaults are not erased by custom + $this->assertTrue( $registry->has_type( 'string' ) ); + $this->assertTrue( $registry->has_type( 'text' ) ); + $this->assertTrue( $registry->has_type( 'email' ) ); + $this->assertTrue( $registry->has_type( 'url' ) ); + $this->assertTrue( $registry->has_type( 'integer' ) ); + $this->assertTrue( $registry->has_type( 'boolean' ) ); + $this->assertTrue( $registry->has_type( 'date' ) ); + $this->assertTrue( $registry->has_type( 'datetime' ) ); + } + } + public function test_field_type_registry_maps_to_dataset_types(): void { $registry = new FieldTypeRegistry(); From dd8c84a3b65c908924f425f6adf50d924c8c651a Mon Sep 17 00:00:00 2001 From: Nicolas Jaussaud Date: Tue, 26 May 2026 15:32:25 +0200 Subject: [PATCH 2/4] Field Type Registry: Revert shared custom types and give possibility to set custom FieldTypeRegistry in DataView --- src/DataView/DataView.php | 4 ++-- src/DataView/FieldTypeRegistry.php | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/DataView/DataView.php b/src/DataView/DataView.php index 0ea5ef2..e418e62 100644 --- a/src/DataView/DataView.php +++ b/src/DataView/DataView.php @@ -70,8 +70,8 @@ class DataView { * - ui: array - WordPress admin UI configuration * - capability: string - required capability (default: 'manage_options') */ - public function __construct( array $config ) { - $this->registry = new FieldTypeRegistry(); + public function __construct( array $config, ?FieldTypeRegistry $registry = null ) { + $this->registry = $registry ?? new FieldTypeRegistry(); $this->label_generator = new LabelGenerator(); $this->schema_generator = new SchemaGenerator( $this->registry ); diff --git a/src/DataView/FieldTypeRegistry.php b/src/DataView/FieldTypeRegistry.php index baddcdd..4e605b2 100644 --- a/src/DataView/FieldTypeRegistry.php +++ b/src/DataView/FieldTypeRegistry.php @@ -14,17 +14,17 @@ class FieldTypeRegistry { * * @var array */ - protected static array $types = []; + protected array $types = []; public function __construct() { - if ( empty( static::$types ) ) $this->register_default_types(); + if ( empty( $this->types ) ) $this->register_default_types(); } /** * Register the default field types. */ protected function register_default_types(): void { - static::$types = [ + $this->types = [ 'string' => [ 'dataset' => DataSet::TYPE_STRING, 'sanitizer' => 'sanitize_text_field', @@ -91,7 +91,7 @@ protected function register_default_types(): void { */ public function get_dataset_type( string $type ): string { $this->validate_type( $type ); - return static::$types[ $type ]['dataset']; + return $this->types[ $type ]['dataset']; } /** @@ -103,7 +103,7 @@ public function get_dataset_type( string $type ): string { */ public function get_sanitizer( string $type ): callable { $this->validate_type( $type ); - return static::$types[ $type ]['sanitizer']; + return $this->types[ $type ]['sanitizer']; } /** @@ -115,7 +115,7 @@ public function get_sanitizer( string $type ): callable { */ public function get_schema( string $type ): array { $this->validate_type( $type ); - return static::$types[ $type ]['schema']; + return $this->types[ $type ]['schema']; } /** @@ -127,7 +127,7 @@ public function get_schema( string $type ): array { */ public function get_input_type( string $type ): string { $this->validate_type( $type ); - return static::$types[ $type ]['input']; + return $this->types[ $type ]['input']; } /** @@ -137,7 +137,7 @@ public function get_input_type( string $type ): string { * @return bool True if type is registered. */ public function has_type( string $type ): bool { - return isset( static::$types[ $type ] ); + return isset( $this->types[ $type ] ); } /** @@ -155,7 +155,7 @@ public function register_type( string $name, array $config ): void { ); } } - static::$types[ $name ] = $config; + $this->types[ $name ] = $config; } /** @@ -167,7 +167,7 @@ public function register_type( string $name, array $config ): void { protected function validate_type( string $type ): void { if ( ! $this->has_type( $type ) ) { throw new \InvalidArgumentException( - sprintf( 'Unknown field type "%s". Available types: %s', $type, implode( ', ', array_keys( static::$types ) ) ) + sprintf( 'Unknown field type "%s". Available types: %s', $type, implode( ', ', array_keys( $this->types ) ) ) ); } } From 63327927000846f32867bdd028012101b390090e Mon Sep 17 00:00:00 2001 From: Nicolas Jaussaud Date: Tue, 26 May 2026 15:33:02 +0200 Subject: [PATCH 3/4] Tests: Field Type Registry - Update tests according to last changes --- tests/phpunit/data-view.php | 43 +++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/tests/phpunit/data-view.php b/tests/phpunit/data-view.php index 120a89d..ff79edf 100644 --- a/tests/phpunit/data-view.php +++ b/tests/phpunit/data-view.php @@ -54,7 +54,7 @@ public function test_field_type_registry_has_default_types(): void { $this->assertTrue( $registry->has_type( 'datetime' ) ); } - public function test_field_type_registry_has_shared_custom_types(): void { + public function test_field_type_registry_has_custom_types(): void { $registry_1 = new FieldTypeRegistry(); $registry_2 = new FieldTypeRegistry(); @@ -72,13 +72,16 @@ public function test_field_type_registry_has_shared_custom_types(): void { 'input' => 'hidden', ] ); + $this->assertTrue( $registry_1->has_type( 'custom_type_1' ) ); + $this->assertTrue( $registry_2->has_type( 'custom_type_2' ) ); + + $this->assertFalse( $registry_1->has_type( 'custom_type_2' ) ); + $this->assertFalse( $registry_2->has_type( 'custom_type_1' ) ); + foreach( [ $registry_1, $registry_2 ] as $registry ) { - $this->assertTrue( $registry->has_type( 'custom_type_1' ) ); - $this->assertTrue( $registry->has_type( 'custom_type_2' ) ); - // Check defaults are not erased by custom $this->assertTrue( $registry->has_type( 'string' ) ); $this->assertTrue( $registry->has_type( 'text' ) ); @@ -91,6 +94,38 @@ public function test_field_type_registry_has_shared_custom_types(): void { } } + public function test_dataview_can_use_field_registery_with_custom_types(): void { + $registry = new FieldTypeRegistry(); + $registry->register_type( 'custom_type', [ + 'dataset' => DataSet::TYPE_STRING, + 'sanitizer' => fn( $value ) => ( $value ), + 'schema' => [], + 'input' => 'hidden', + ] ); + + $config = [ + 'slug' => 'dv_test_custom_field_type', + 'label' => 'Item', + 'fields' => [ + 'name' => 'custom_type', + 'title' => 'string', + ] + ]; + + try { + $view_default_registry = new DataView( $config ); + $this->fail( 'Expected InvalidArgumentException was not thrown' ); + } catch ( \InvalidArgumentException $e ) { + $this->assertStringStartsWith( + 'Unknown field type "custom_type"', + $e->getMessage() + ); + } + + $view_custom_registry = new DataView( $config, $registry ); + $this->assertInstanceOf( DataView::class, $view_custom_registry ); + } + public function test_field_type_registry_maps_to_dataset_types(): void { $registry = new FieldTypeRegistry(); From 19c11c4890990bd74a74fb27b06d7b66ac002bca Mon Sep 17 00:00:00 2001 From: Nicolas Jaussaud Date: Wed, 27 May 2026 16:50:37 +0200 Subject: [PATCH 4/4] Field Type Registry: Remove uneeded condition in constructor (added for previous approach) --- src/DataView/FieldTypeRegistry.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataView/FieldTypeRegistry.php b/src/DataView/FieldTypeRegistry.php index 4e605b2..867084c 100644 --- a/src/DataView/FieldTypeRegistry.php +++ b/src/DataView/FieldTypeRegistry.php @@ -17,7 +17,7 @@ class FieldTypeRegistry { protected array $types = []; public function __construct() { - if ( empty( $this->types ) ) $this->register_default_types(); + $this->register_default_types(); } /**