diff --git a/src/plugin/class-engine.php b/src/plugin/class-engine.php index ab13a269..e8ae2d62 100644 --- a/src/plugin/class-engine.php +++ b/src/plugin/class-engine.php @@ -4,25 +4,28 @@ class Engine { - private string $storage_post_type = 'liberated_data'; + public const string STORAGE_POST_TYPE = 'liberated_data'; 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'; require 'class-storage.php'; require 'class-schema.php'; require 'utils.php'; + require 'class-subject.php'; ( function () { - $transformer = new Transformer(); - - new Post_Type_UI( $this->storage_post_type, $transformer ); + new Transformer(); + new Post_Type_UI( self::STORAGE_POST_TYPE ); // 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 ); } )(); } } diff --git a/src/plugin/class-post-type-ui.php b/src/plugin/class-post-type-ui.php index 3e4af98d..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 ); @@ -100,7 +98,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-subject.php b/src/plugin/class-subject.php new file mode 100644 index 00000000..f944e59b --- /dev/null +++ b/src/plugin/class-subject.php @@ -0,0 +1,69 @@ +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; + } + + public function transformed_post_id(): int { + return absint( get_post_meta( $this->id, Transformer::META_KEY_LIBERATED_OUTPUT, true ) ); + } +} diff --git a/src/plugin/class-subjects-controller.php b/src/plugin/class-subjects-controller.php index fb45d548..d7a38723 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 ); } @@ -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 ee1d1a01..9e6fcd21 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 ); @@ -35,23 +36,15 @@ 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, $this->meta_key_for_transformed_post, true ); - if ( '' === $value ) { - return 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 ); + $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 ) ) { @@ -86,7 +79,8 @@ public function transform( int $liberated_post_id, 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/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 ); + } +} 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 ); + } +} diff --git a/tests/plugin/test-transformer.php b/tests/plugin/test-transformer.php index 7de63b52..1e04a05c 100644 --- a/tests/plugin/test-transformer.php +++ b/tests/plugin/test-transformer.php @@ -1,6 +1,8 @@ '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' ); @@ -32,11 +34,11 @@ 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 ); - delete_post_meta( 99, '_dl_transformed' ); + delete_post_meta( 99, Transformer::META_KEY_LIBERATED_OUTPUT ); } public function testGetPostTypeForTransformedPost() { @@ -52,17 +54,10 @@ public function testGetPostTypeForTransformedPost() { $this->assertEquals( 'product', $result ); } - public function testGetTransformedPost() { - add_post_meta( 99, '_dl_transformed', 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( $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 ) ); + $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 );