From 31c09cd329ee01896b311ac87a6af05f98a5b820 Mon Sep 17 00:00:00 2001 From: "Author: ruru4143" Date: Fri, 8 Dec 2023 14:04:22 +0100 Subject: [PATCH 1/9] fix #8, transformer not found --- includes/transformer/class-transformer-factory.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/transformer/class-transformer-factory.php b/includes/transformer/class-transformer-factory.php index 65b07da..70c42e4 100644 --- a/includes/transformer/class-transformer-factory.php +++ b/includes/transformer/class-transformer-factory.php @@ -278,6 +278,11 @@ class Transformer_Factory { $transformer_mapping = \get_option( 'activitypub_transformer_mapping', self::DEFAULT_TRANSFORMER_MAPPING ); $transformer_name = $transformer_mapping[ $post_type ]; $transformer_class = $this->get_transformers( $transformer_name ); + + if ( null === $transformer_class ) { + wp_die("transformer '". $transformer_name . "' not found", '', ["response" => 404]); + } + $transformer_instance = new $transformer_class(); $transformer_instance->set_wp_post( $wp_object ); return $transformer_instance->transform(); From ca940bfc4e0c1033a98a3ca5228cbb779247509a Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Sat, 9 Dec 2023 02:01:13 +0100 Subject: [PATCH 2/9] smoother build process --- includes/activity/class-base-object.php | 16 ++++ includes/transformer/class-base.php | 103 +++++++++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index ded8f7b..cd3fb63 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -453,6 +453,10 @@ class Base_Object { return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } + if ( $var === 'skip_next' ) { + return; // skip_next should never be retrieved publicly + } + return $this->$var; } @@ -522,6 +526,11 @@ class Base_Object { return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } + if ( $this->skip_next ) { + $this->skip_next = false; + return $this; + } + $this->$key = $value; return $this; @@ -675,4 +684,11 @@ class Base_Object { return \wp_json_encode( $array, \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT ); } + + public function if( bool $b ) { + $this->skip_next = ! $b; + return $this; + } + + } diff --git a/includes/transformer/class-base.php b/includes/transformer/class-base.php index cb89ee2..248fb6d 100644 --- a/includes/transformer/class-base.php +++ b/includes/transformer/class-base.php @@ -33,6 +33,13 @@ abstract class Base { */ protected $wp_post; + /** + * Time format string for date or gmdate + * + * @var string + */ + protected $timeformat; + /** * Get the name used for registering the transformer with the ActivityPub plugin. * @@ -68,6 +75,48 @@ abstract class Base { */ abstract public function transform(); + /** + * Retrieves a post meta field for the configured post. + * + * @param string $key Optional. The meta key to retrieve. By default, + * returns data for all keys. Default empty. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @return mixed An array of values if `$single` is false. + * The value of the meta field if `$single` is true. + * False for an invalid `$post_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing post ID is passed. + */ + public function get_post_meta( string $key = '', $single = false, $default = null ) { + // todo test what if not present + // empty string or empty array, then return default + return \get_post_meta( $this->wp_post->ID, $key, $single ); + } + + /** + * Retrieves a post meta field for the configured post. + * + * @param string $key The meta key of the time value to retrieve. + * @return string formatted time + */ + public function get_post_meta_time( string $key ) { + $time = $this->get_post_meta( $key, true ); // todo what if not exists + $time = \strtotime( $time ); + return \gmdate( $this->timeformat, $time ); + } + + /** + * Retrieves if comments are enabled of the configured post. + * + * @return bool True if the comments are open. + */ + public function get_comments_open() { + return comments_open( $this->wp_post->ID ); + } + + + /** * Getter function for this wp_post. * @@ -98,6 +147,56 @@ abstract class Base { $this->wp_post = $wp_post; } + /** + * Setter for $timeformat. + * + * This configures a timeformat string for converting timestaps into dates + * + * @param string $timeformat The time format string. + * @return void + */ + public function set_timeformat( string $timeformat ) { + $this->timeformat = $timeformat; + } + + /** + * Get published time in configured format + * + * This queries the published time from the wp_object and returns it in the configured format + * + * @return string + */ + public function get_published() { + $published = \strtotime( $this->wp_post->post_date_gmt ); + return \gmdate( 'Y-m-d\TH:i:s\Z', $published ); + } + + + /** + * Get updated time in configured format + * + * This queries the update time from the wp_object and returns it in the configured format + * + * @return string + */ + public function get_updated() { + $updated = \strtotime( $this->wp_post->post_modified_gmt ); + return \gmdate( 'Y-m-d\TH:i:s\Z', $updated ); + } + + /** + * TODO review and write description + * + * @return array + */ + public function get_followers_stream() { + $path = sprintf( 'users/%d/followers', intval( $this->wp_post->post_author ) ); + return array( + 'https://www.w3.org/ns/activitystreams#Public', + get_rest_url_by_path( $path ), + ); + } + /** * Get the supported WP post types that the transformer can use as an input. * @@ -242,7 +341,7 @@ abstract class Base { * @return string The User-URL. */ protected function get_attributed_to() { - if ( is_single_user() ) { + if ( is_single_user() ) { // todo what is if this setting gets changed $user = new Blog_User(); return $user->get_url(); } @@ -590,7 +689,7 @@ abstract class Base { * * @return array the contenmap */ - protected function get_content_map() { + protected function get_basic_content_map() { return array( $this->get_locale() => $this->get_content(), ); From 25ecff16e7f7972a5a7b12f7e563af8c9a27fd7a Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 19:43:50 +0100 Subject: [PATCH 3/9] adding todo's --- includes/transformer/class-base.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/transformer/class-base.php b/includes/transformer/class-base.php index 248fb6d..5a9ad96 100644 --- a/includes/transformer/class-base.php +++ b/includes/transformer/class-base.php @@ -25,7 +25,7 @@ use function Activitypub\site_supports_blocks; * * */ -abstract class Base { +abstract class Base { // todo renmae to Base_tranformer /** * The WP_Post object. * @@ -341,6 +341,8 @@ abstract class Base { * @return string The User-URL. */ protected function get_attributed_to() { + // todo is this descriptive enough? what if for some people the event should be attributed to the venue? + // i would maybe prefer something like "get post author??" if ( is_single_user() ) { // todo what is if this setting gets changed $user = new Blog_User(); return $user->get_url(); @@ -691,7 +693,7 @@ abstract class Base { */ protected function get_basic_content_map() { return array( - $this->get_locale() => $this->get_content(), + $this->get_locale() => $this->get_content(), // todo is this a valid assumption? ); } } From 6cbe66d121695eafab9aa83807b3f62830c5148d Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 19:44:44 +0100 Subject: [PATCH 4/9] renamed $skip_next to $_skip_next --- includes/activity/class-base-object.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index cd3fb63..15cf799 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -26,6 +26,13 @@ use function Activitypub\snake_to_camel_case; * @see https://www.w3.org/TR/activitystreams-core/#object */ class Base_Object { + /** + * if this is set, the next setter call doesn't change anything + * + * @var bool + */ + protected $_skip_next; + /** * The object's unique global identifier * @@ -453,10 +460,6 @@ class Base_Object { return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } - if ( $var === 'skip_next' ) { - return; // skip_next should never be retrieved publicly - } - return $this->$var; } @@ -526,8 +529,8 @@ class Base_Object { return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } - if ( $this->skip_next ) { - $this->skip_next = false; + if ( $this->_skip_next ) { + $this->_skip_next = false; return $this; } @@ -686,7 +689,7 @@ class Base_Object { } public function if( bool $b ) { - $this->skip_next = ! $b; + $this->_skip_next = ! $b; return $this; } From af667379394d5d6077d107ad82f385e6f9d75ab8 Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 23:21:02 +0100 Subject: [PATCH 5/9] added languagemap sugar --- includes/activity/class-base-object.php | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index 15cf799..e8fca38 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -33,6 +33,13 @@ class Base_Object { */ protected $_skip_next; + /** + * if this is set, the language maps will be set automatically with this language if not set yet todo nicer description + * + * @var string + */ + protected $_default_language_code_for_language_maps; + /** * The object's unique global identifier * @@ -534,11 +541,51 @@ class Base_Object { return $this; } + if ( 'content' === $key || 'summary' === $key || 'name' === $key ) { // todo nicer? + $this->set_basic_language_map( $key, $value ); // todo skip setter if language map is already set + } + $this->$key = $value; return $this; } + /** + * Setter for the languageMap default language + * + * @param string $languagecode languageocde for default + * + */ + public function set_default_language_for_maps( $languagecode ) { + $this->_default_language_code_for_language_maps = $languagecode; + return $this; + } + + /** + * Generic languageMap setter. + * + * @param string $key The key for the language map. + * @param string $value The value to set. + * + */ + public function set_basic_language_map( $key, $value ) { + // todo better name, implement usage for content, summary and name + $mapkey = $key . '_map'; + + if ( ! isset( $this->_default_language_code_for_language_maps ) ) { + return new WP_Error( '_default_language_code_for_language_maps must be set before calling set_languageMap', __( '_default_language_code_for_language_maps must be set before calling set_languageMap', 'activitypub' ), array( 'status' => 404 ) ); + } + if ( ! $this->has( $mapkey ) ) { + return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); + } + + $this->$mapkey = array( + $this->_default_language_code_for_language_maps => $value, + ); + + return $this; + } + /** * Generic adder. * From 6a51a303f762d4400d0c8a5e186bc83aca0ae505 Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 23:21:20 +0100 Subject: [PATCH 6/9] added if header --- includes/activity/class-base-object.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index e8fca38..dd3d093 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -735,7 +735,13 @@ class Base_Object { return \wp_json_encode( $array, \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT ); } - public function if( bool $b ) { + /** + * skips next setter if( false ); + * + * @param bool $b + * + */ + public function if( $b ) { $this->_skip_next = ! $b; return $this; } From b78bbbe372916508f3a5e6025c590c9715cc5f4a Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 23:21:47 +0100 Subject: [PATCH 7/9] better post metadata and property getter --- includes/transformer/class-base.php | 37 ++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/includes/transformer/class-base.php b/includes/transformer/class-base.php index 5a9ad96..4f626a0 100644 --- a/includes/transformer/class-base.php +++ b/includes/transformer/class-base.php @@ -78,20 +78,39 @@ abstract class Base { // todo renmae to Base_tranformer /** * Retrieves a post meta field for the configured post. * - * @param string $key Optional. The meta key to retrieve. By default, - * returns data for all keys. Default empty. - * @param bool $single Optional. Whether to return a single value. - * This parameter has no effect if `$key` is not specified. - * Default false. + * @param string $key The meta key to retrieve. By default, + * returns data for all keys. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @param mixed $default_value Optional. if the key doesn't exists, it returns the default value. + * Default null. * @return mixed An array of values if `$single` is false. * The value of the meta field if `$single` is true. * False for an invalid `$post_id` (non-numeric, zero, or negative value). * An empty string if a valid but non-existing post ID is passed. */ - public function get_post_meta( string $key = '', $single = false, $default = null ) { - // todo test what if not present - // empty string or empty array, then return default - return \get_post_meta( $this->wp_post->ID, $key, $single ); + public function get_post_meta( $key, $single = false, $default_value = null ) { + if ( \metadata_exists( 'post', $this->wp_post->ID, $key ) ) { + return \get_post_meta( $this->wp_post->ID, $key, $single ); + } + return $default_value; + } + + /** + * Retrieves a post property field for the configured post. + * + * @param string $key The property key to retrieve. By default, + * returns data for all keys. + * @param mixed $default_value Optional. if the key doesn't exists, it returns the default value. + * Default null. + * @return mixed The value of the property. + */ + public function get_post_property( $key, $default_value = null ) { + if ( isset( $this->wp_post->$key ) ) { + return $this->wp_post->$key; + } + return $default_value; } /** From 5cc9c358115763855fce11250d6f5de1800e029d Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 23:22:07 +0100 Subject: [PATCH 8/9] added null check fro post_meta_time getter --- includes/transformer/class-base.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/includes/transformer/class-base.php b/includes/transformer/class-base.php index 4f626a0..b5fec37 100644 --- a/includes/transformer/class-base.php +++ b/includes/transformer/class-base.php @@ -121,6 +121,9 @@ abstract class Base { // todo renmae to Base_tranformer */ public function get_post_meta_time( string $key ) { $time = $this->get_post_meta( $key, true ); // todo what if not exists + if ( null === $time ) { + return null; + } $time = \strtotime( $time ); return \gmdate( $this->timeformat, $time ); } From a626dfce4e438abf73f0686b615dd8f0b4a11e50 Mon Sep 17 00:00:00 2001 From: ruru4143 Date: Mon, 11 Dec 2023 23:22:19 +0100 Subject: [PATCH 9/9] added completness check --- includes/activity/class-base-object.php | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index dd3d093..9b9f044 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -746,5 +746,37 @@ class Base_Object { return $this; } + public function check_jsonld_completeness() { + // Just a debugging helper function + $vars = get_object_vars( $this ); + $total_var_count = count( $vars ); + $unset_var_array = array(); + + foreach ( $vars as $key => $value ) { + // ignore all _prefixed keys. + if ( '_' === substr( $key, 0, 1 ) ) { + --$total_var_count; + continue; + } + + // if value is empty, try to get it from a getter. + if ( ! $value ) { + $value = call_user_func( array( $this, 'get_' . $key ) ); + } + + // if value is still empty, ignore it for the array and continue. + if ( ! isset( $value ) ) { + $unset_var_array[] = $key; + } + } + $unset_var_count = count( $unset_var_array ); + + return array( + 'total_var_count' => $total_var_count, + 'unset_var_count' => $unset_var_count, + 'set_var_count' => $total_var_count - $unset_var_count, + 'unset_vars' => $unset_var_array, + ); + } }