From 873aa71e85b4262f293616b6c006f25177711334 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 14:25:09 +0400 Subject: [PATCH 1/9] store storage post type in a public constant so that other plugins can read it --- src/plugin/class-engine.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugin/class-engine.php b/src/plugin/class-engine.php index ab13a269..09c3d9de 100644 --- a/src/plugin/class-engine.php +++ b/src/plugin/class-engine.php @@ -4,7 +4,7 @@ class Engine { - private string $storage_post_type = 'liberated_data'; + public const string STORAGE_POST_TYPE = 'liberated_data'; public function __construct() { require 'class-post-type-ui.php'; @@ -17,12 +17,12 @@ public function __construct() { ( function () { $transformer = new Transformer(); - new Post_Type_UI( $this->storage_post_type, $transformer ); + new Post_Type_UI( self::STORAGE_POST_TYPE, $transformer ); // REST API - new Subjects_Controller( $this->storage_post_type ); + new Subjects_Controller( self::STORAGE_POST_TYPE ); - new Storage( $this->storage_post_type ); + new Storage( self::STORAGE_POST_TYPE ); } )(); } } From 36ce3b6c847b637383e0548d0d37f0b5ed9c72fd Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 14:34:58 +0400 Subject: [PATCH 2/9] define Subject class & SubjectType enum --- src/plugin/class-engine.php | 3 ++ src/plugin/class-subject.php | 65 ++++++++++++++++++++++++++++++++ src/plugin/enum-subject-type.php | 13 +++++++ 3 files changed, 81 insertions(+) create mode 100644 src/plugin/class-subject.php create mode 100644 src/plugin/enum-subject-type.php diff --git a/src/plugin/class-engine.php b/src/plugin/class-engine.php index 09c3d9de..01174c6f 100644 --- a/src/plugin/class-engine.php +++ b/src/plugin/class-engine.php @@ -7,12 +7,15 @@ class Engine { public const string STORAGE_POST_TYPE = 'liberated_data'; public function __construct() { + require 'enum-subject-type.php'; + require 'class-post-type-ui.php'; require 'class-transformer.php'; require 'class-subjects-controller.php'; require 'class-storage.php'; require 'class-schema.php'; require 'utils.php'; + require 'class-subject.php'; ( function () { $transformer = new Transformer(); diff --git a/src/plugin/class-subject.php b/src/plugin/class-subject.php new file mode 100644 index 00000000..972e5a19 --- /dev/null +++ b/src/plugin/class-subject.php @@ -0,0 +1,65 @@ +id = $post->ID; + $this->author_id = $post->post_author; + $this->source_html = $post->post_content_filtered; + $this->source_url = $post->guid; + + $this->type = get_post_meta( $post->ID, 'subject_type', true ); + $this->title = get_post_meta( $post->ID, 'raw_title', true ); + $this->date = get_post_meta( $post->ID, 'raw_date', true ); + $this->content = get_post_meta( $post->ID, 'raw_content', true ); + } + + public function id(): int { + return $this->id; + } + + public function author_id(): int { + return $this->author_id; + } +} diff --git a/src/plugin/enum-subject-type.php b/src/plugin/enum-subject-type.php new file mode 100644 index 00000000..4692de7e --- /dev/null +++ b/src/plugin/enum-subject-type.php @@ -0,0 +1,13 @@ +value ); + } +} From e5b728e20f0027c5db0dccfdcf31ca2c58181663 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 13:38:44 +0400 Subject: [PATCH 3/9] introduce TransformersRegistry class to use in registration of transformers --- src/plugin/class-engine.php | 1 + src/plugin/class-transformersregistry.php | 125 ++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/plugin/class-transformersregistry.php diff --git a/src/plugin/class-engine.php b/src/plugin/class-engine.php index 01174c6f..78e0017e 100644 --- a/src/plugin/class-engine.php +++ b/src/plugin/class-engine.php @@ -9,6 +9,7 @@ class Engine { public function __construct() { require 'enum-subject-type.php'; + require 'class-transformersregistry.php'; require 'class-post-type-ui.php'; require 'class-transformer.php'; require 'class-subjects-controller.php'; diff --git a/src/plugin/class-transformersregistry.php b/src/plugin/class-transformersregistry.php new file mode 100644 index 00000000..1ac88f44 --- /dev/null +++ b/src/plugin/class-transformersregistry.php @@ -0,0 +1,125 @@ +value ] ) ) { + self::$handlers[ $type->value ] = array(); + } + + self::$handlers[ $type->value ][ $identifier['slug'] ] = array( + 'slug' => $identifier['slug'], + 'description' => $identifier['desc'], + 'handler' => $handler, + ); + } + + /** + * Check if handlers exist for a type + * + * @param SubjectType $type The subject type to check for. + * @return bool True if handlers exist + */ + public static function has( SubjectType $type ): bool { + return isset( self::$handlers[ $type->value ] ) && ! empty( self::$handlers[ $type->value ] ); + } + + /** + * Check if there is a "compete" i.e., multiple handlers for a type + * + * @param SubjectType $type The subject type to check for. + * @return bool True if handlers exist + */ + public static function is_compete( SubjectType $type ): bool { + return isset( self::$handlers[ $type->value ] ) && count( self::$handlers[ $type->value ] ) > 1; + } + + /** + * Execute all handlers for a type + * + * @param SubjectType $type The subject type to handle. + * @param Subject $subject Data to pass to handlers. + * @return void + * @throws Exception If no handler has been registered or user choice hasn't been set when multiples are registered. + */ + public static function handle( SubjectType $type, Subject $subject ): void { + if ( ! self::has( $type ) ) { + throw new Exception( sprintf( 'no handler registered for type: %s', esc_html( $type->value ) ) ); + } + + if ( self::is_compete( $type ) ) { + $choice = self::get_user_choice( $type ); + if ( ! empty( $choice ) ) { + $chosen = self::$handlers[ $type->value ][ $choice ]; + } else { + throw new Exception( 'handle() invoked without user choice on compete' ); + } + } else { + $chosen = current( self::$handlers[ $type->value ] ); + } + + $transformed_post_id = $chosen['handler']( $subject ); + + if ( $transformed_post_id ) { + update_post_meta( $subject->id(), Transformer::META_KEY_LIBERATED_OUTPUT, $transformed_post_id ); + update_post_meta( $transformed_post_id, Transformer::META_KEY_LIBERATED_SOURCE, $subject->id() ); + } + } + + /** + * Remove all handlers for a type + * + * @param SubjectType $type The type to clear handlers for. + * @return void + */ + public static function clear( SubjectType $type ): void { + if ( isset( self::$handlers[ $type->value ] ) ) { + unset( self::$handlers[ $type->value ] ); + } + } + + /** + * Set user choice for what transformer to run for a subject type when multiples are registered + * + * @param SubjectType $type The subject type for which choice is to be saved. + * @param string $transformer_slug Identifying slug of the chosen transformer. + * @return void + */ + public static function set_user_choice( SubjectType $type, string $transformer_slug ): void { + update_user_meta( get_current_user_id(), self::$user_choice_meta_key_prefix . $type->value, $transformer_slug ); + } + + /** + * Retrieves the user choice for what transformer to run for a subject type when multiples are registered + * + * @param SubjectType $type The subject type for which choice is to be retrieved. + * @return string $transformer_slug Identifying slug of the chosen transformer. + */ + public static function get_user_choice( SubjectType $type ): string { + return get_user_meta( get_current_user_id(), self::$user_choice_meta_key_prefix . $type->value, true ); + } +} From c00469df69dbd9ad6c3535045484bd9e6d3890f9 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 14:46:07 +0400 Subject: [PATCH 4/9] dl_data_saved hook now provides data as a Subject instance --- src/plugin/class-subjects-controller.php | 4 ++-- src/plugin/class-transformer.php | 5 +++-- tests/plugin/test-transformer.php | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/plugin/class-subjects-controller.php b/src/plugin/class-subjects-controller.php index fb45d548..ac2585b6 100644 --- a/src/plugin/class-subjects-controller.php +++ b/src/plugin/class-subjects-controller.php @@ -292,7 +292,7 @@ public function create_item( $request ): WP_REST_Response|WP_Error { $subject_type = $this->get_subject_type( $request ); update_post_meta( $item['ID'], 'subject_type', $subject_type ); - do_action( 'dl_data_saved', $item['ID'], 'create' ); + do_action( 'dl_data_saved', Subject::from_post( $item['ID'] ), 'create' ); return $this->prepare_item_for_response( $item, $request, $subject_type ); } @@ -316,7 +316,7 @@ public function update_item( $request ): WP_REST_Response|WP_Error { update_post_meta( $item['ID'], $key, $value ); } - do_action( 'dl_data_saved', $item['ID'], 'update' ); + do_action( 'dl_data_saved', Subject::from_post( $item['ID'] ), 'update' ); return $this->prepare_item_for_response( $item, $request ); } diff --git a/src/plugin/class-transformer.php b/src/plugin/class-transformer.php index ee1d1a01..570e1055 100644 --- a/src/plugin/class-transformer.php +++ b/src/plugin/class-transformer.php @@ -44,12 +44,13 @@ public function get_transformed_post_id( $liberated_post_id ): int|null { return absint( $value ); } - public function transform( int $liberated_post_id, string $verb ): bool { + public function transform( Subject $subject, string $verb ): bool { if ( apply_filters( 'skip_native_transformation', false ) ) { return true; } - $liberated_post = get_post( $liberated_post_id ); + $liberated_post_id = $subject->id(); + $liberated_post = get_post( $liberated_post_id ); $transformed_post_id = get_post_meta( $liberated_post->ID, $this->meta_key_for_transformed_post, true ); diff --git a/tests/plugin/test-transformer.php b/tests/plugin/test-transformer.php index 7de63b52..a4885951 100644 --- a/tests/plugin/test-transformer.php +++ b/tests/plugin/test-transformer.php @@ -1,6 +1,7 @@ transformer->transform( $this->post_id_in_db, 'whatever' ); // verb isn't currently used + $result = $this->transformer->transform( Subject::from_post( $this->post_id_in_db ), 'whatever' ); // verb isn't currently used $transformed_post_id = absint( get_post_meta( $this->post_id_in_db, '_dl_transformed', true ) ); From 2915d18ae848bbcd01ece3b334c98c03be03e1a0 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 15:03:01 +0400 Subject: [PATCH 5/9] establish both side relationship between liberated and transformed data; expose meta key for fields via constant --- src/plugin/class-subjects-controller.php | 2 +- src/plugin/class-transformer.php | 10 ++++++---- tests/plugin/test-transformer.php | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/plugin/class-subjects-controller.php b/src/plugin/class-subjects-controller.php index ac2585b6..d7a38723 100644 --- a/src/plugin/class-subjects-controller.php +++ b/src/plugin/class-subjects-controller.php @@ -382,7 +382,7 @@ public function prepare_item_for_response( $item, $request ): WP_REST_Response|W 'authorId' => $item['post_author'] ?? '', 'sourceUrl' => $item['guid'] ?? '', 'sourceHtml' => $item['post_content_filtered'] ?? '', - 'transformedId' => absint( get_post_meta( $item['ID'], '_dl_transformed', true ) ), + 'transformedId' => absint( get_post_meta( $item['ID'], Transformer::META_KEY_LIBERATED_OUTPUT, true ) ), ); foreach ( array_keys( Schema::get()[ $subject_type ]['fields'] ) as $field_name ) { diff --git a/src/plugin/class-transformer.php b/src/plugin/class-transformer.php index 570e1055..bcd4b1c7 100644 --- a/src/plugin/class-transformer.php +++ b/src/plugin/class-transformer.php @@ -5,7 +5,8 @@ use WP_Post; class Transformer { - private string $meta_key_for_transformed_post = '_dl_transformed'; + public const string META_KEY_LIBERATED_SOURCE = '_data_liberation_source'; + public const string META_KEY_LIBERATED_OUTPUT = '_data_liberation_output'; public function __construct() { add_action( 'dl_data_saved', array( $this, 'transform' ), 10, 2 ); @@ -36,7 +37,7 @@ private function get_post_type_for_transformed_post( int|WP_Post $liberated_post } public function get_transformed_post_id( $liberated_post_id ): int|null { - $value = get_post_meta( $liberated_post_id, $this->meta_key_for_transformed_post, true ); + $value = get_post_meta( $liberated_post_id, self::META_KEY_LIBERATED_OUTPUT, true ); if ( '' === $value ) { return null; } @@ -52,7 +53,7 @@ public function transform( Subject $subject, string $verb ): bool { $liberated_post_id = $subject->id(); $liberated_post = get_post( $liberated_post_id ); - $transformed_post_id = get_post_meta( $liberated_post->ID, $this->meta_key_for_transformed_post, true ); + $transformed_post_id = get_post_meta( $liberated_post->ID, self::META_KEY_LIBERATED_OUTPUT, true ); $title = get_post_meta( $liberated_post->ID, 'parsed_title', true ); if ( empty( $title ) ) { @@ -87,7 +88,8 @@ public function transform( Subject $subject, string $verb ): bool { return false; } - add_post_meta( $liberated_post->ID, $this->meta_key_for_transformed_post, $inserted_post_id ); + update_post_meta( $inserted_post_id, self::META_KEY_LIBERATED_SOURCE, $liberated_post->ID ); + update_post_meta( $liberated_post->ID, self::META_KEY_LIBERATED_OUTPUT, $inserted_post_id ); return true; } } diff --git a/tests/plugin/test-transformer.php b/tests/plugin/test-transformer.php index a4885951..7df19042 100644 --- a/tests/plugin/test-transformer.php +++ b/tests/plugin/test-transformer.php @@ -37,7 +37,7 @@ protected function tearDown(): void { wp_delete_post( $transformed_post_id, true ); wp_delete_post( $this->post_id_in_db, true ); - delete_post_meta( 99, '_dl_transformed' ); + delete_post_meta( 99, Transformer::META_KEY_LIBERATED_OUTPUT ); } public function testGetPostTypeForTransformedPost() { @@ -54,7 +54,7 @@ public function testGetPostTypeForTransformedPost() { } public function testGetTransformedPost() { - add_post_meta( 99, '_dl_transformed', 999 ); + add_post_meta( 99, Transformer::META_KEY_LIBERATED_OUTPUT, 999 ); $this->assertEquals( 999, $this->transformer->get_transformed_post_id( 99 ) ); $this->assertEquals( null, $this->transformer->get_transformed_post_id( 88 ) ); @@ -63,7 +63,7 @@ public function testGetTransformedPost() { public function testTransform(): void { $result = $this->transformer->transform( Subject::from_post( $this->post_id_in_db ), 'whatever' ); // verb isn't currently used - $transformed_post_id = absint( get_post_meta( $this->post_id_in_db, '_dl_transformed', true ) ); + $transformed_post_id = absint( get_post_meta( $this->post_id_in_db, Transformer::META_KEY_LIBERATED_OUTPUT, true ) ); $this->assertEquals( $this->post_id_in_db + 1, $transformed_post_id ); $this->assertTrue( $result ); From 04b9e86c69be474d3e778ff80f5eb7d37c1382c1 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 21 Nov 2024 23:02:32 +0400 Subject: [PATCH 6/9] tiny improvement in test --- tests/plugin/test-transformer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/plugin/test-transformer.php b/tests/plugin/test-transformer.php index 7df19042..7cddae88 100644 --- a/tests/plugin/test-transformer.php +++ b/tests/plugin/test-transformer.php @@ -1,5 +1,6 @@ 'draft', 'post_content_filtered' => '

Content 1

Content 2

', 'guid' => 'https://example.com/x', - 'post_type' => 'liberated_data', + 'post_type' => Engine::STORAGE_POST_TYPE, ) ); update_post_meta( $this->post_id_in_db, 'subject_type', 'blog-post' ); From 8cd7785c02c46b5a243bf65a397bfa8918c9f486 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 18:19:18 +0400 Subject: [PATCH 7/9] remove get_transformed_post_id() since now meta key is exposed --- src/plugin/class-post-type-ui.php | 2 +- src/plugin/class-transformer.php | 9 --------- tests/plugin/test-transformer.php | 9 +-------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/plugin/class-post-type-ui.php b/src/plugin/class-post-type-ui.php index 3e4af98d..a607791f 100644 --- a/src/plugin/class-post-type-ui.php +++ b/src/plugin/class-post-type-ui.php @@ -100,7 +100,7 @@ function () { global $post; $post_id = $post->ID; - $transformed_post_id = $this->transformer->get_transformed_post_id( $post_id ); + $transformed_post_id = get_post_meta( $post_id, Transformer::META_KEY_LIBERATED_OUTPUT, true ); if ( $transformed_post_id ) { echo '
PostID: ' . esc_html( $transformed_post_id ) . '
'; diff --git a/src/plugin/class-transformer.php b/src/plugin/class-transformer.php index bcd4b1c7..9e6fcd21 100644 --- a/src/plugin/class-transformer.php +++ b/src/plugin/class-transformer.php @@ -36,15 +36,6 @@ private function get_post_type_for_transformed_post( int|WP_Post $liberated_post return apply_filters( 'post_type_for_transformed_post', $post_type, $liberated_post ); } - public function get_transformed_post_id( $liberated_post_id ): int|null { - $value = get_post_meta( $liberated_post_id, self::META_KEY_LIBERATED_OUTPUT, true ); - if ( '' === $value ) { - return null; - } - - return absint( $value ); - } - public function transform( Subject $subject, string $verb ): bool { if ( apply_filters( 'skip_native_transformation', false ) ) { return true; diff --git a/tests/plugin/test-transformer.php b/tests/plugin/test-transformer.php index 7cddae88..1e04a05c 100644 --- a/tests/plugin/test-transformer.php +++ b/tests/plugin/test-transformer.php @@ -34,7 +34,7 @@ protected function setUp(): void { protected function tearDown(): void { parent::tearDown(); - $transformed_post_id = $this->transformer->get_transformed_post_id( $this->post_id_in_db ); + $transformed_post_id = get_post_meta( $this->post_id_in_db, Transformer::META_KEY_LIBERATED_OUTPUT, true ); wp_delete_post( $transformed_post_id, true ); wp_delete_post( $this->post_id_in_db, true ); @@ -54,13 +54,6 @@ public function testGetPostTypeForTransformedPost() { $this->assertEquals( 'product', $result ); } - public function testGetTransformedPost() { - add_post_meta( 99, Transformer::META_KEY_LIBERATED_OUTPUT, 999 ); - - $this->assertEquals( 999, $this->transformer->get_transformed_post_id( 99 ) ); - $this->assertEquals( null, $this->transformer->get_transformed_post_id( 88 ) ); - } - public function testTransform(): void { $result = $this->transformer->transform( Subject::from_post( $this->post_id_in_db ), 'whatever' ); // verb isn't currently used From c055907039f5e802ab1cd72b2c20369142f45261 Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 18:22:44 +0400 Subject: [PATCH 8/9] Post_Type_UI doesn't need a Transformer instance now --- src/plugin/class-engine.php | 5 ++--- src/plugin/class-post-type-ui.php | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/plugin/class-engine.php b/src/plugin/class-engine.php index 78e0017e..e8ae2d62 100644 --- a/src/plugin/class-engine.php +++ b/src/plugin/class-engine.php @@ -19,9 +19,8 @@ public function __construct() { require 'class-subject.php'; ( function () { - $transformer = new Transformer(); - - new Post_Type_UI( self::STORAGE_POST_TYPE, $transformer ); + new Transformer(); + new Post_Type_UI( self::STORAGE_POST_TYPE ); // REST API new Subjects_Controller( self::STORAGE_POST_TYPE ); diff --git a/src/plugin/class-post-type-ui.php b/src/plugin/class-post-type-ui.php index a607791f..f1a9b787 100644 --- a/src/plugin/class-post-type-ui.php +++ b/src/plugin/class-post-type-ui.php @@ -4,11 +4,9 @@ class Post_Type_UI { private string $post_type; - private Transformer $transformer; - public function __construct( $custom_post_type, Transformer $transformer ) { - $this->post_type = $custom_post_type; - $this->transformer = $transformer; + public function __construct( $custom_post_type ) { + $this->post_type = $custom_post_type; $this->remove_add_new_option( $this->post_type ); From 63aaa79d818d844f1bf77bec54d267f7f49682aa Mon Sep 17 00:00:00 2001 From: ashfame Date: Thu, 26 Dec 2024 18:32:21 +0400 Subject: [PATCH 9/9] provide method on Subject to get to the transformed post id --- src/plugin/class-subject.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugin/class-subject.php b/src/plugin/class-subject.php index 972e5a19..f944e59b 100644 --- a/src/plugin/class-subject.php +++ b/src/plugin/class-subject.php @@ -62,4 +62,8 @@ public function id(): int { public function author_id(): int { return $this->author_id; } + + public function transformed_post_id(): int { + return absint( get_post_meta( $this->id, Transformer::META_KEY_LIBERATED_OUTPUT, true ) ); + } }