diff --git a/README.md b/README.md index 22fb483..8adc07d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ **Tags:** OStatus, fediverse, activitypub, activitystream **Requires at least:** 4.7 **Tested up to:** 4.9.8 -**Stable tag:** 0.0.1 +**Stable tag:** 0.0.2 **Requires PHP:** 5.3 **License:** MIT **License URI:** http://opensource.org/licenses/MIT @@ -23,6 +23,11 @@ If you want to have a **decentralized social network**, please use [Mastodon](ht ## Changelog ## + +### 0.0.2 ### + +* refactorins +* functional inbox ### 0.0.1 ### diff --git a/activitypub.php b/activitypub.php index 547c188..0b6ef1a 100644 --- a/activitypub.php +++ b/activitypub.php @@ -3,7 +3,7 @@ * Plugin Name: ActivityPub * Plugin URI: https://github.com/pfefferle/wordpress-activitypub/ * Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format. - * Version: 0.0.1 + * Version: 0.0.2 * Author: Matthias Pfefferle * Author URI: https://notiz.blog/ * License: MIT @@ -16,6 +16,7 @@ * Initialize plugin */ function activitypub_init() { + require_once dirname( __FILE__ ) . '/includes/class-activitypub-post.php'; require_once dirname( __FILE__ ) . '/includes/functions.php'; require_once dirname( __FILE__ ) . '/includes/class-activitypub.php'; diff --git a/includes/class-activitypub-inbox.php b/includes/class-activitypub-inbox.php index 5496bab..2eccdf3 100644 --- a/includes/class-activitypub-inbox.php +++ b/includes/class-activitypub-inbox.php @@ -1,6 +1,6 @@ WP_REST_Server::EDITABLE, - 'callback' => array( 'Activitypub_Inbox', 'shared_edit' ), + 'callback' => array( 'Activitypub_Inbox', 'shared_inbox' ), ), ) ); @@ -22,31 +22,45 @@ class Activitypub_Inbox { 'activitypub/1.0', '/users/(?P\d+)/inbox', array( array( 'methods' => WP_REST_Server::EDITABLE, - 'callback' => array( 'Activitypub_Inbox', 'user_edit' ), + 'callback' => array( 'Activitypub_Inbox', 'user_inbox' ), 'args' => self::request_parameters(), ), ) ); } - public static function user_edit( $request ) { + public static function user_inbox( $request ) { $author_id = $request->get_param( 'id' ); $author = get_user_by( 'ID', $author_id ); $data = json_decode( $request->get_body(), true ); + do_action( 'activitypub_inbox', $data ); + if ( ! is_array( $data ) || ! array_key_exists( 'type', $data ) ) { return new WP_Error( 'rest_invalid_data', __( 'Invalid payload', 'activitypub' ), array( 'status' => 422 ) ); } - return new WP_REST_Response( $data ); + return new WP_REST_Response(); } - public static function shared_edit( $request ) { + /** + * The shared inbox + * + * @param [type] $request [description] + * + * @return WP_Error not yet implemented + */ + public static function shared_inbox( $request ) { // Create the response object return new WP_Error( 'rest_not_implemented', __( 'This method is not yet implemented', 'activitypub' ), array( 'status' => 501 ) ); } + /** + * The supported parameters + * + * @return array list of parameters + */ public static function request_parameters() { $params = array(); diff --git a/includes/class-activitypub-outbox.php b/includes/class-activitypub-outbox.php index 80415cd..df596af 100644 --- a/includes/class-activitypub-outbox.php +++ b/includes/class-activitypub-outbox.php @@ -32,7 +32,7 @@ class Activitypub_Outbox { ) ); } - $page = $request->get_param( 'page' ); + $page = $request->get_param( 'page', 0 ); /* * Action triggerd prior to the ActivityPub profile being created and sent to the client @@ -41,37 +41,7 @@ class Activitypub_Outbox { $json = new stdClass(); - $json->{'@context'} = array( - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - array( - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'sensitive' => 'as:sensitive', - 'movedTo' => array( - '@id' => 'as:movedTo', - '@type' => '@id', - ), - 'Hashtag' => 'as:Hashtag', - 'ostatus' => 'http://ostatus.org#', - 'atomUri' => 'ostatus:atomUri', - 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', - 'conversation' => 'ostatus:conversation', - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'focalPoint' => array( - '@container' => '@list', - '@id' => 'toot:focalPoint', - ), - 'featured' => array( - '@id' => 'toot:featured', - '@type' => '@id', - ), - 'schema' => 'http://schema.org#', - 'PropertyValue' => 'schema:PropertyValue', - 'value' => 'schema:value', - ), - ); - + $json->{'@context'} = get_activitypub_context(); $json->id = home_url( add_query_arg( NULL, NULL ) ); $json->generator = 'http://wordpress.org/?v=' . get_bloginfo_rss( 'version' ); $json->actor = get_author_posts_url( $author_id ); @@ -82,8 +52,9 @@ class Activitypub_Outbox { $json->totalItems = intval( $count_posts->publish ); $posts = get_posts( array( + 'posts_per_page' => 10, 'author' => $author_id, - 'offset' => $page, + 'offset' => $page * 10, ) ); $json->first = add_query_arg( 'page', 0, $json->partOf ); @@ -94,7 +65,8 @@ class Activitypub_Outbox { } foreach ( $posts as $post ) { - $json->orderedItems[] = self::post_to_json( $post ); // phpcs:ignore + $activitypub_post = new Activitypub_Post( $post ); + $json->orderedItems[] = $activitypub_post->to_json_array(); // phpcs:ignore } // filter output diff --git a/includes/class-activitypub-post.php b/includes/class-activitypub-post.php new file mode 100644 index 0000000..43851ed --- /dev/null +++ b/includes/class-activitypub-post.php @@ -0,0 +1,114 @@ +post = $post; + } + + public function to_json_array( $with_context = false ) { + $post = $this->post; + + $json = new stdClass(); + + if ( $with_context ) { + $json->{'@context'} = get_activitypub_context(); + } + + $json->published = date( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date ) ); + $json->id = $post->guid . '&activitypub'; + $json->type = 'Create'; + $json->actor = get_author_posts_url( $post->post_author ); + $json->to = array( 'https://www.w3.org/ns/activitystreams#Public' ); + $json->cc = array( 'https://www.w3.org/ns/activitystreams#Public' ); + + $json->object = array( + 'id' => $post->guid, + 'type' => $this->get_object_type(), + 'published' => date( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date ) ), + 'to' => array( 'https://www.w3.org/ns/activitystreams#Public' ), + 'cc' => array( 'https://www.w3.org/ns/activitystreams#Public' ), + 'attributedTo' => get_author_posts_url( $post->post_author ), + 'summary' => null, + 'inReplyTo' => null, + 'content' => esc_html( $post->post_content ), + 'contentMap' => array( + strstr( get_locale(), '_', true ) => esc_html( $post->post_content ) , + ), + 'attachment' => array(), + 'tag' => array(), + ); + + return apply_filters( 'activitypub_json_post', $json ); + } + + /** + * Returns the as2 object-type for a given post + * + * @param string $type the object-type + * @param Object $post the post-object + * + * @return string the object-type + */ + public function get_object_type() { + $post_type = get_post_type( $this->post ); + switch ( $post_type ) { + case 'post': + $post_format = get_post_format( $this->post ); + switch ( $post_format ) { + case 'aside': + case 'status': + case 'quote': + case 'note': + $object_type = 'Note'; + break; + case 'gallery': + case 'image': + $object_type = 'Image'; + break; + case 'video': + $object_type = 'Video'; + break; + case 'audio': + $object_type = 'Audio'; + break; + default: + $object_type = 'Article'; + break; + } + break; + case 'page': + $object_type = 'Page'; + break; + case 'attachment': + $mime_type = get_post_mime_type(); + $media_type = preg_replace( '/(\/[a-zA-Z]+)/i', '', $mime_type ); + switch ( $media_type ) { + case 'audio': + $object_type = 'Audio'; + break; + case 'video': + $object_type = 'Video'; + break; + case 'image': + $object_type = 'Image'; + break; + } + break; + default: + $object_type = 'Article'; + break; + } + + return $object_type; + } +} diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index ba73d05..94db1d5 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -1,6 +1,17 @@ query_vars['activitypub'] ) ) { + if ( isset( $wp_query->query_vars['as2'] ) ) { return $json_template; } @@ -65,7 +76,7 @@ class Activitypub { * won't mangle it. */ public static function add_query_vars( $vars ) { - $vars[] = 'activitypub'; + $vars[] = 'as2'; return $vars; } @@ -74,6 +85,6 @@ class Activitypub { * Add our rewrite endpoint to permalinks and pages. */ public static function add_rewrite_endpoint() { - add_rewrite_endpoint( 'activitypub', EP_AUTHORS | EP_PERMALINK | EP_PAGES ); + add_rewrite_endpoint( 'as2', EP_AUTHORS | EP_PERMALINK | EP_PAGES ); } } diff --git a/includes/functions.php b/includes/functions.php index bbe3bed..2f3269e 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -1,91 +1,40 @@ published = date( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date ) ); - $json->id = $post->guid . '&activitypub'; - $json->type = 'Create'; - $json->actor = get_author_posts_url( $post->post_author ); - $json->to = array( 'https://www.w3.org/ns/activitystreams#Public' ); - $json->cc = array( 'https://www.w3.org/ns/activitystreams#Public' ); - - $json->object = array( - 'id' => $post->guid, - 'type' => activitypub_object_type( $post ), - 'published' => date( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date ) ), - 'to' => array( 'https://www.w3.org/ns/activitystreams#Public' ), - 'cc' => array( 'https://www.w3.org/ns/activitystreams#Public' ), - 'attributedTo' => get_author_posts_url( $post->post_author ), - 'summary' => null, - 'inReplyTo' => null, - 'content' => esc_html( $post->post_content ), - 'contentMap' => array( - strstr( get_locale(), '_', true ) => esc_html( $post->post_content ) , +/** + * Returns the ActivityPub default JSON-context + * + * @return array the activitypub context + */ +function get_activitypub_context() { + $context = array( + 'https://www.w3.org/ns/activitystreams', + 'https://w3id.org/security/v1', + array( + 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', + 'sensitive' => 'as:sensitive', + 'movedTo' => array( + '@id' => 'as:movedTo', + '@type' => '@id', + ), + 'Hashtag' => 'as:Hashtag', + 'ostatus' => 'http://ostatus.org#', + 'atomUri' => 'ostatus:atomUri', + 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', + 'conversation' => 'ostatus:conversation', + 'toot' => 'http://joinmastodon.org/ns#', + 'Emoji' => 'toot:Emoji', + 'focalPoint' => array( + '@container' => '@list', + '@id' => 'toot:focalPoint', + ), + 'featured' => array( + '@id' => 'toot:featured', + '@type' => '@id', + ), + 'schema' => 'http://schema.org#', + 'PropertyValue' => 'schema:PropertyValue', + 'value' => 'schema:value', ), - 'attachment' => array(), - 'tag' => array(), ); - return $json; -} - -/** - * Returns the as2 object for a given post - * - * @param string $type the object type - * @param Object $post the post object - * @return string the object type - */ -function activitypub_object_type( $post ) { - $post_type = get_post_type( $post ); - switch ( $post_type ) { - case 'post': - $post_format = get_post_format( $post ); - switch ( $post_format ) { - case 'aside': - case 'status': - case 'quote': - case 'note': - $object_type = 'Note'; - break; - case 'gallery': - case 'image': - $object_type = 'Image'; - break; - case 'video': - $object_type = 'Video'; - break; - case 'audio': - $object_type = 'Audio'; - break; - default: - $object_type = 'Article'; - break; - } - break; - case 'page': - $object_type = 'Page'; - break; - case 'attachment': - $mime_type = get_post_mime_type(); - $media_type = preg_replace( '/(\/[a-zA-Z]+)/i', '', $mime_type ); - switch ( $media_type ) { - case 'audio': - $object_type = 'Audio'; - break; - case 'video': - $object_type = 'Video'; - break; - case 'image': - $object_type = 'Image'; - break; - } - break; - default: - $object_type = 'Article'; - break; - } - return $object_type; + return apply_filters( 'activitypub_json_context', $context ); } diff --git a/languages/activitypub.pot b/languages/activitypub.pot index 0a41622..ca41fa1 100644 --- a/languages/activitypub.pot +++ b/languages/activitypub.pot @@ -2,9 +2,9 @@ # This file is distributed under the MIT. msgid "" msgstr "" -"Project-Id-Version: ActivityPub 1.0.0\n" +"Project-Id-Version: ActivityPub 0.0.2\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/activitypub\n" -"POT-Creation-Date: 2018-09-24 18:46:07+00:00\n" +"POT-Creation-Date: 2018-09-30 20:50:08+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -13,6 +13,14 @@ msgstr "" "Language-Team: LANGUAGE \n" "X-Generator: grunt-wp-i18n1.0.2\n" +#: includes/class-activitypub-inbox.php:41 +msgid "Invalid payload" +msgstr "" + +#: includes/class-activitypub-inbox.php:56 +msgid "This method is not yet implemented" +msgstr "" + #: includes/class-activitypub-outbox.php:28 #: includes/class-activitypub-outbox.php:30 msgid "User not found" diff --git a/readme.txt b/readme.txt index e6d2d23..437f7bd 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://notiz.blog/donate/ Tags: OStatus, fediverse, activitypub, activitystream Requires at least: 4.7 Tested up to: 4.9.8 -Stable tag: 0.0.1 +Stable tag: 0.0.2 Requires PHP: 5.3 License: MIT License URI: http://opensource.org/licenses/MIT @@ -23,6 +23,11 @@ If you want to have a **decentralized social network**, please use [Mastodon](ht == Changelog == + += 0.0.2 = + +* refactorins +* functional inbox = 0.0.1 = diff --git a/templates/json-author.php b/templates/json-author.php index 5e174c2..f5f328b 100644 --- a/templates/json-author.php +++ b/templates/json-author.php @@ -3,37 +3,7 @@ $author_id = get_the_author_meta( 'ID' ); $json = new stdClass(); -$json->{'@context'} = array( - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - array( - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'sensitive' => 'as:sensitive', - 'movedTo' => array( - '@id' => 'as:movedTo', - '@type' => '@id', - ), - 'Hashtag' => 'as:Hashtag', - 'ostatus' => 'http://ostatus.org#', - 'atomUri' => 'ostatus:atomUri', - 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', - 'conversation' => 'ostatus:conversation', - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'focalPoint' => array( - '@container' => '@list', - '@id' => 'toot:focalPoint', - ), - 'featured' => array( - '@id' => 'toot:featured', - '@type' => '@id', - ), - 'schema' => 'http://schema.org#', - 'PropertyValue' => 'schema:PropertyValue', - 'value' => 'schema:value', - ), -); - +$json->{'@context'} = get_activitypub_context(); $json->id = get_author_posts_url( $author_id ); $json->type = 'Person'; $json->name = get_the_author_meta( 'display_name', $author_id ); @@ -56,11 +26,8 @@ if ( has_header_image() ) { $json->inbox = get_rest_url( null, "/activitypub/1.0/users/$author_id/inbox" ); $json->outbox = get_rest_url( null, "/activitypub/1.0/users/$author_id/outbox" ); -//$json->following = get_rest_url( null, "/activitypub/1.0/users/$author_id/following" ); -//$json->followers = get_rest_url( null, "/activitypub/1.0/users/$author_id/followers" ); -//$json->featured = get_rest_url( null, "/activitypub/1.0/users/$author_id/featured" ); -//$json->manuallyApprovesFollowers = apply_filters( 'activitypub_manually_approves_followers', __return_false() ); // phpcs:ignore +$json->manuallyApprovesFollowers = apply_filters( 'activitypub_json_manually_approves_followers', __return_false() ); // phpcs:ignore if ( method_exists( 'Magic_Sig', 'get_public_key' ) ) { // phpcs:ignore diff --git a/templates/json-post.php b/templates/json-post.php index 43f17c0..1365fba 100644 --- a/templates/json-post.php +++ b/templates/json-post.php @@ -1,43 +1,10 @@ {'@context'} = array( - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - array( - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'sensitive' => 'as:sensitive', - 'movedTo' => array( - '@id' => 'as:movedTo', - '@type' => '@id', - ), - 'Hashtag' => 'as:Hashtag', - 'ostatus' => 'http://ostatus.org#', - 'atomUri' => 'ostatus:atomUri', - 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', - 'conversation' => 'ostatus:conversation', - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'focalPoint' => array( - '@container' => '@list', - '@id' => 'toot:focalPoint', - ), - 'featured' => array( - '@id' => 'toot:featured', - '@type' => '@id', - ), - 'schema' => 'http://schema.org#', - 'PropertyValue' => 'schema:PropertyValue', - 'value' => 'schema:value', - ), -); - -$post = activitypub_post_to_json( $post, $json ); +$activitypub_post = new Activitypub_Post( $post ); // filter output -$json = apply_filters( 'activitypub_json_post_array', $json ); +$json = apply_filters( 'activitypub_json_post_array', $activitypub_post->to_json_array( true ) ); /* * Action triggerd prior to the ActivityPub profile being created and sent to the client