diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index ded8f7b..9b9f044 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -26,6 +26,20 @@ 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; + + /** + * 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 * @@ -522,11 +536,56 @@ 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; + } + + 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. * @@ -675,4 +734,49 @@ class Base_Object { return \wp_json_encode( $array, \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT ); } + + /** + * skips next setter if( false ); + * + * @param bool $b + * + */ + public function if( $b ) { + $this->_skip_next = ! $b; + 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, + ); + } } diff --git a/includes/transformer/class-base.php b/includes/transformer/class-base.php index cb89ee2..b5fec37 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. * @@ -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,70 @@ abstract class Base { */ abstract public function transform(); + /** + * Retrieves a post meta field for the configured post. + * + * @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( $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; + } + + /** + * 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 + if ( null === $time ) { + return null; + } + $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 +169,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 +363,9 @@ abstract class Base { * @return string The User-URL. */ protected function get_attributed_to() { - if ( is_single_user() ) { + // 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(); } @@ -590,9 +713,9 @@ 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(), + $this->get_locale() => $this->get_content(), // todo is this a valid assumption? ); } } 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();