diff --git a/activitypub.php b/activitypub.php index c6a51fd..f30ef42 100644 --- a/activitypub.php +++ b/activitypub.php @@ -90,14 +90,15 @@ function init() { * Add plugin settings link */ function plugin_settings_link( $links ) { - $settings_link[] = \sprintf( '%2s', - \menu_page_url( 'activitypub', false ), - \__( 'Settings', 'activitypub' ) + $settings_link[] = \sprintf( + '%2s', + \menu_page_url( 'activitypub', false ), + \__( 'Settings', 'activitypub' ) ); - + return \array_merge( $settings_link, $links ); } -\add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), '\Activitypub\plugin_settings_link' ); +\add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), '\Activitypub\plugin_settings_link' ); /** * Add rewrite rules diff --git a/includes/class-activity-dispatcher.php b/includes/class-activity-dispatcher.php index 76d762d..d698020 100644 --- a/includes/class-activity-dispatcher.php +++ b/includes/class-activity-dispatcher.php @@ -74,7 +74,7 @@ class Activity_Dispatcher { $user_id = $activitypub_post->get_post_author(); $deleted = \current_time( 'Y-m-d\TH:i:s\Z', true ); if ( $permalink ) { - $activitypub_post->set_id( $permalink ); + $activitypub_post->set_id( $permalink ); } $activitypub_post->set_deleted( $deleted ); @@ -110,7 +110,7 @@ class Activity_Dispatcher { $activitypub_activity->set_to( $to );//all users at shared inbox $activity = $activitypub_activity->to_json(); // phpcs:ignore \Activitypub\safe_remote_post( $inbox, $activity, $user_id ); - + $mentioned_actors[] = $to; } @@ -136,7 +136,7 @@ class Activity_Dispatcher { //original author should NOT recieve a copy of their own post $replyto[] = $activitypub_comment->comment_author_url; - $activitypub_activity = unserialize( get_comment_meta( $activitypub_comment->comment_ID, 'ap_object', true ) ); + $activitypub_activity = \unserialize( get_comment_meta( $activitypub_comment->comment_ID, 'ap_object', true ) ); //will be forwarded to the parent_comment->author or post_author followers collection $parent_comment = \get_comment( $activitypub_comment->comment_parent ); diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index c3d1062..8640d68 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -165,22 +165,16 @@ class Activitypub { */ public static function postprocess_comment( $comment_id, $comment_approved, $commentdata ) { //Admin users comments bypass transition_comment_status (auto approved) - - if ( $commentdata['comment_type'] === 'activitypub' ) { - if ( ( $comment_approved === 1 ) && + $user = \get_userdata( $commentdata['user_id'] ); + if ( 'activitypub' === $commentdata['comment_type'] ) { + if ( + ( 1 === $comment_approved ) && ! empty( $commentdata['user_id'] ) && - ( $user = \get_userdata( $commentdata['user_id'] ) ) && // get the user data - \in_array( 'administrator', $user->roles ) // check the roles + \in_array( 'administrator', $user->roles ) ) { // Only for Admins $mentions = \get_comment_meta( $comment_id, 'mentions', true ); \wp_schedule_single_event( \time(), 'activitypub_send_comment_activity', array( $comment_id ) ); - - } else { - // TODO check that this is unused - // TODO comment test as anon / no auth_url, no fetchable status? - // TODO comment test as registered - // TODO comment test as anyother site settings } } } @@ -191,9 +185,9 @@ class Activitypub { * Fires immediately after a comment is updated in the database. * Fires immediately before comment status transition hooks are fired. (useful only for admin) */ - public static function edit_comment( $comment_ID, $data ) { + public static function edit_comment( $comment_id, $data ) { if ( ! is_null( $data['user_id'] ) ) { - \wp_schedule_single_event( \time(), 'activitypub_send_update_comment_activity', array( $comment_ID ) ); + \wp_schedule_single_event( \time(), 'activitypub_send_update_comment_activity', array( $comment_id ) ); } } @@ -204,7 +198,6 @@ class Activitypub { * @param int $comment */ public static function schedule_comment_activity( $new_status, $old_status, $activitypub_comment ) { - // TODO format $activitypub_comment = new \Activitypub\Model\Comment( $comment ); if ( 'approved' === $new_status && 'approved' !== $old_status ) { //should only federate replies from local actors //should only federate replies to federated actors @@ -230,7 +223,7 @@ class Activitypub { } elseif ( $old_status === $new_status ) { //TODO Test with non-admin user \wp_schedule_single_event( \time(), 'activitypub_send_update_comment_activity', array( $activitypub_comment->comment_ID ) ); - } else { } + } } /** diff --git a/includes/class-admin.php b/includes/class-admin.php index e88694b..17476b3 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -163,16 +163,16 @@ class Admin { //TODO revise for non-js reply action // Public Reply $reply_button = ''; - $actions['reply'] = sprintf( + $actions['reply'] = \sprintf( $reply_button, $comment->comment_ID, $comment->comment_post_ID, 'replyto', 'vim-r comment-inline', - esc_attr__( 'Reply to this comment' ), + \esc_attr__( 'Reply to this comment', 'activitypub' ), $recipients, $summary, - __( 'Reply', 'activitypub' ) + \__( 'Reply', 'activitypub' ) ); return $actions; @@ -182,11 +182,11 @@ class Admin { if ( 'edit-comments.php' !== $hook ) { return; } - wp_enqueue_script( + \wp_enqueue_script( 'activitypub_client', - plugin_dir_url( __FILE__ ) . '/activitypub.js', + \plugin_dir_url( __FILE__ ) . '/activitypub.js', array( 'jquery' ), - filemtime( plugin_dir_path( __FILE__ ) . '/activitypub.js' ), + \filemtime( \plugin_dir_path( __FILE__ ) . '/activitypub.js' ), true ); } diff --git a/includes/functions.php b/includes/functions.php index 174f353..c331246 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -252,10 +252,8 @@ function get_follower_inboxes( $user_id ) { } /** - * - * @param $mentions array of mentioned actors, each mention is an array of actor URI (href), and webfinger (name) - * - * @return array of (shared) inboxes + * @param $mentions array of mentioned actors, each mention is an array of actor URI (href), and webfinger (name). + * @return array of (shared) inboxes. */ function get_mentioned_inboxes( $mentions ) { $inboxes = array(); @@ -265,7 +263,7 @@ function get_mentioned_inboxes( $mentions ) { if ( ! $inbox || \is_wp_error( $inbox ) ) { continue; } - + if ( ! isset( $inboxes[ $inbox ] ) ) { $inboxes[ $inbox ] = array(); } @@ -361,8 +359,8 @@ function url_to_authorid( $url ) { /** * Verify if in_replyto_url is a local comment, * Or if it is a previously received remote comment - * (For threading comments locally) - * + * (For threading comments locally) + * * @param string activitypub object id URI * @return int comment_id */ @@ -373,7 +371,7 @@ function url_to_commentid( $in_replyto_url ) { //rewrite for activitypub object id simplification $url_maybe_id = \wp_parse_url( $in_replyto_url ); - if ( site_url() === $url_maybe_id['scheme'] . '://' . $url_maybe_id['host'] && !empty( $url_maybe_id['query'] )) { + if ( site_url() === $url_maybe_id['scheme'] . '://' . $url_maybe_id['host'] && ! empty( $url_maybe_id['query'] ) ) { //is local post or comment \parse_str( $url_maybe_id['query'], $reply_query ); if ( isset( $reply_query['ap_comment_id'] ) ) { @@ -455,7 +453,7 @@ function get_recipients( $object_id, $post = null ) { if ( ! empty( $ap_object['object']['tag'] ) ) { $author_post_url = \get_author_posts_url( $ap_object['user_id'] ); foreach ( $ap_object['object']['tag'] as $tag ) { - if ( $author_post_url == $tag['href'] ) { + if ( $author_post_url === $tag['href'] ) { continue; } if ( in_array( 'Mention', $tag ) ) { @@ -481,7 +479,7 @@ function get_summary( $comment_id ) { /** * Parse content for tags to transform - * + * * @param string $content to search * @return array content, mentions (for storage in post_meta) */ @@ -542,16 +540,16 @@ function webfinger_short_tag( $webfinger ) { */ function url_to_webfinger( $user_url ) { $user_url = \untrailingslashit( $user_url ); - $user_url_array = explode( '/', $user_url ); - $user_name = end( $user_url_array ); - $url_host = parse_url( $user_url, PHP_URL_HOST ); + $user_url_array = \explode( '/', $user_url ); + $user_name = \end( $user_url_array ); + $url_host = \wp_parse_url( $user_url, PHP_URL_HOST ); $webfinger = '@' . $user_name . '@' . $url_host; return $webfinger; } /** * @param $comment or $comment_id - * @return ActivityPub URI of comment + * @return ActivityPub URI of comment * * AP Object ID must be unique * @@ -560,12 +558,12 @@ function url_to_webfinger( $user_url ) { */ function set_ap_comment_id( $comment ) { $comment = \get_comment( $comment ); - $ap_comment_id = add_query_arg( + $ap_comment_id = \add_query_arg( array( 'p' => $comment->comment_post_ID, 'ap_comment_id' => $comment->comment_ID, ), - trailingslashit( site_url() ) + \trailingslashit( site_url() ) ); return $ap_comment_id; } diff --git a/includes/model/class-comment.php b/includes/model/class-comment.php index 2ef5e1d..0ac697a 100644 --- a/includes/model/class-comment.php +++ b/includes/model/class-comment.php @@ -18,16 +18,16 @@ class Comment { $this->comment = $comment; $this->id = $this->generate_comment_id(); $this->comment_author_url = \get_author_posts_url( $this->comment->user_id ); - $this->safe_comment_id = $this->generate_comment_id(); - $this->inReplyTo = $this->generate_parent_url(); - $this->contentWarning = $this->generate_content_warning(); - $this->permalink = $this->generate_permalink(); - $this->context = $this->generate_context(); - $this->to_recipients = $this->generate_mention_recipients(); - $this->tags = $this->generate_tags(); - $this->update = $this->generate_update(); - $this->deleted = $this->generate_trash(); - $this->replies = $this->generate_replies(); + $this->safe_comment_id = $this->generate_comment_id(); + $this->in_reply_to = $this->generate_parent_url(); + $this->content_warning = $this->generate_content_warning(); + $this->permalink = $this->generate_permalink(); + $this->context = $this->generate_context(); + $this->to_recipients = $this->generate_mention_recipients(); + $this->tags = $this->generate_tags(); + $this->update = $this->generate_update(); + $this->deleted = $this->generate_trash(); + $this->replies = $this->generate_replies(); } public function __call( $method, $params ) { @@ -48,10 +48,10 @@ class Comment { $array = array( 'id' => $this->safe_comment_id, 'type' => 'Note', - 'published' => \date( 'Y-m-d\TH:i:s\Z', \strtotime( $comment->comment_date_gmt ) ), + 'published' => \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $comment->comment_date_gmt ) ), 'attributedTo' => $this->comment_author_url, - 'summary' => $this->contentWarning, - 'inReplyTo' => $this->inReplyTo, + 'summary' => $this->content_warning, + 'inReplyTo' => $this->in_reply_to, 'content' => $comment->comment_content, 'contentMap' => array( \strstr( \get_locale(), '_', true ) => $comment->comment_content, @@ -105,9 +105,9 @@ class Comment { $parent_comment = \get_comment( $comment->comment_parent ); if ( $comment->comment_parent ) { //is parent remote? - $inReplyTo = \get_comment_meta( $comment->comment_parent, 'source_url', true ); - if ( ! $inReplyTo ) { - $inReplyTo = add_query_arg( + $in_reply_to = \get_comment_meta( $comment->comment_parent, 'source_url', true ); + if ( ! $in_reply_to ) { + $in_reply_to = add_query_arg( array( 'p' => $comment->comment_post_ID, 'ap_comment_id' => $comment->comment_parent, @@ -119,9 +119,9 @@ class Comment { // Backwards compatibility $pretty_permalink = \get_post_meta( $comment->comment_post_ID, '_activitypub_permalink_compat', true ); // TODO finalize meta if ( $pretty_permalink ) { - $inReplyTo = $pretty_permalink; + $in_reply_to = $pretty_permalink; } else { - $inReplyTo = add_query_arg( + $in_reply_to = add_query_arg( array( 'p' => $comment->comment_post_ID, ), @@ -129,7 +129,7 @@ class Comment { ); } } - return $inReplyTo; + return $in_reply_to; } public function generate_context() { @@ -159,7 +159,7 @@ class Comment { */ public function generate_content_warning() { $comment = $this->comment; - $contentWarning = null; + $content_warning = null; // Temporarily generate Summary from parent $parent_comment = \get_comment( $comment->comment_parent ); @@ -167,15 +167,15 @@ class Comment { //get (received) comment $ap_object = \unserialize( \get_comment_meta( $comment->comment_parent, 'ap_object', true ) ); if ( isset( $ap_object['object']['summary'] ) ) { - $contentWarning = $ap_object['object']['summary']; + $content_warning = $ap_object['object']['summary']; } } // TODO Replace auto generate with Summary shortcode /*summary = \get_comment_meta( $this->comment->comment_ID, 'summary', true ) ; if ( !empty( $summary ) ) { - $contentWarning = \Activitypub\add_summary( $summary ); + $content_warning = \Activitypub\add_summary( $summary ); } */ - return $contentWarning; + return $content_warning; } /** @@ -227,8 +227,8 @@ class Comment { public function generate_trash() { $comment = $this->comment; $deleted = null; - if ( 'trash' == $comment->status ) { - $deleted = \date( 'Y-m-d\TH:i:s\Z', \strtotime( $comment->comment_date_gmt ) ); + if ( 'trash' === $comment->status ) { + $deleted = \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $comment->comment_date_gmt ) ); } return $deleted; } @@ -238,7 +238,7 @@ class Comment { */ public function generate_replies() { $comment = $this->comment; - $replies = []; + $replies = array(); $args = array( 'post_id' => $comment->comment_post_ID, 'parent' => $comment->comment_ID, @@ -252,7 +252,7 @@ class Comment { foreach ( $comments_list as $comment ) { // remote replies $source_url = \get_comment_meta( $comment->comment_ID, 'source_url', true ); - if ( ! empty( $source_url ) ){ + if ( ! empty( $source_url ) ) { $items[] = $source_url; } else { // local replies @@ -266,7 +266,7 @@ class Comment { $items[] = $comment_url; } } - + $replies = (object) array( 'type' => 'Collection', 'id' => \add_query_arg( array( 'replies' => '' ), $this->id ), diff --git a/includes/model/class-post.php b/includes/model/class-post.php index c16e2e0..c7780e8 100644 --- a/includes/model/class-post.php +++ b/includes/model/class-post.php @@ -30,7 +30,7 @@ class Post { $this->tags = $this->generate_tags(); $this->object_type = $this->generate_object_type(); $this->replies = $this->generate_replies(); - $this->updated = $this->generate_updated(); + $this->updated = $this->generate_updated(); $this->delete = $this->get_deleted(); } @@ -70,14 +70,14 @@ class Post { $array['replies'] = $this->replies; } if ( $this->deleted ) { - $array['deleted'] = \date( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) ); + $array['deleted'] = \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) ); $deleted_post_slug = \get_post_meta( $post->ID, '_activitypub_permalink_compat', true ); if ( $deleted_post_slug ) { $array['id'] = $deleted_post_slug; } } if ( $this->updated ) { - $array['updated'] = \date( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) ); + $array['updated'] = \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) ); } return \apply_filters( 'activitypub_post', $array ); } @@ -87,10 +87,10 @@ class Post { } public function generate_id() { - $post = $this->post; - $pretty_permalink = \get_post_meta( $post->ID, '_activitypub_permalink_compat', true ); + $post = $this->post; + $pretty_permalink = \get_post_meta( $post->ID, '_activitypub_permalink_compat', true ); - if( ! empty( $pretty_permalink ) ) { + if ( ! empty( $pretty_permalink ) ) { $object_id = $pretty_permalink; } else { $object_id = \add_query_arg( // @@ -203,13 +203,12 @@ class Post { trailingslashit( site_url() ) ); $items[] = $comment_url; - } else { - $ap_object = \unserialize(\get_comment_meta( $comment->comment_ID, 'ap_object', true )); + } else { + $ap_object = \unserialize( \get_comment_meta( $comment->comment_ID, 'ap_object', true ) ); $comment_url = \get_comment_meta( $comment->comment_ID, 'source_url', true ); - if ( ! empty( $comment_url ) ){ - $items[] = \get_comment_meta( $comment->comment_ID, 'source_url', true ); + if ( ! empty( $comment_url ) ) { + $items[] = \get_comment_meta( $comment->comment_ID, 'source_url', true ); } - } } @@ -437,10 +436,8 @@ class Post { public function get_deleted() { $post = $this->post; $deleted = null; - if ( 'trash' == $post->post_status ) { - - $deleted = \date( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) ); - \error_log( 'trash: ' . print_r( $deleted, true ) ); + if ( 'trash' === $post->post_status ) { + $deleted = \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) ); } return $deleted; } diff --git a/includes/rest/class-inbox.php b/includes/rest/class-inbox.php index d83f85b..2106b47 100644 --- a/includes/rest/class-inbox.php +++ b/includes/rest/class-inbox.php @@ -407,23 +407,23 @@ class Inbox { * @param int $user_id The id of the local blog-user */ public static function handle_create( $object, $user_id ) { + $comment_post_id = 0; + $comment_parent = 0; + $comment_parent_id = 0; $meta = \Activitypub\get_remote_metadata_by_actor( $object['actor'] ); $avatar_url = null; $audience = \Activitypub\get_audience( $object ); - //Determine comment_post_ID and/or comment_parent - $comment_post_ID = $comment_parent = $comment_parent_ID = 0; if ( isset( $object['object']['inReplyTo'] ) ) { + $comment_parent_id = \Activitypub\url_to_commentid( \esc_url_raw( $object['object']['inReplyTo'] ) ); - $comment_parent_ID = \Activitypub\url_to_commentid( \esc_url_raw( $object['object']['inReplyTo'] ) ); - - if ( ! is_null( $comment_parent_ID ) ) { + if ( ! is_null( $comment_parent_id ) ) { //inReplyTo a known local comment - $comment_parent = \get_comment( $comment_parent_ID ); - $comment_post_ID = $comment_parent->comment_post_ID; + $comment_parent = \get_comment( $comment_parent_id ); + $comment_post_id = $comment_parent->comment_post_ID; } else { //inReplyTo a known post - $comment_post_ID = \url_to_postid( $object['object']['inReplyTo'] ); + $comment_post_id = \url_to_postid( $object['object']['inReplyTo'] ); } } @@ -441,18 +441,18 @@ class Inbox { //Only create WP_Comment for public replies to local posts if ( ( 'public' === $audience ) || ( 'unlisted' === $audience ) - && ( ! empty( $comment_post_ID ) - || ! empty( $comment_parent_ID ) + && ( ! empty( $comment_post_id ) + || ! empty( $comment_parent_id ) ) ) { $commentdata = array( - 'comment_post_ID' => $comment_post_ID, + 'comment_post_ID' => $comment_post_id, 'comment_author' => $name, 'comment_author_url' => \esc_url_raw( $object['actor'] ), 'comment_content' => \wp_filter_kses( $object['object']['content'] ), 'comment_type' => 'activitypub', 'comment_author_email' => '', - 'comment_parent' => $comment_parent_ID, + 'comment_parent' => $comment_parent_id, 'comment_meta' => array( 'ap_object' => \serialize( $object ), 'source_url' => \esc_url_raw( $object['object']['id'] ), @@ -462,7 +462,7 @@ class Inbox { ); // disable flood control - //\remove_action( 'check_comment_flood', 'check_comment_flood_db', 10 ); + \remove_action( 'check_comment_flood', 'check_comment_flood_db', 10 ); // do not require email for AP entries \add_filter( 'pre_option_require_name_email', '__return_false' ); @@ -472,7 +472,7 @@ class Inbox { \remove_filter( 'pre_option_require_name_email', '__return_false' ); // re-add flood control - //\add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 ); + \add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 ); } } @@ -489,20 +489,18 @@ class Inbox { $audience = \Activitypub\get_audience( $object ); //Determine comment_ID - $object_comment_ID = \Activitypub\url_to_commentid( \esc_url_raw( $object['object']['id'] ) ); - if ( ! is_null( $object_comment_ID ) ) { + $object_comment_id = \Activitypub\url_to_commentid( \esc_url_raw( $object['object']['id'] ) ); + if ( ! is_null( $object_comment_id ) ) { //found a local comment id - $commentdata = \get_comment( $object_comment_ID, ARRAY_A ); + $commentdata = \get_comment( $object_comment_id, ARRAY_A ); - //$commentdata['comment_ID'] = \esc_url_raw( $object_comment_ID ); + //$commentdata['comment_ID'] = \esc_url_raw( $object_comment_id ); $commentdata['comment_content'] = \wp_filter_kses( $object['object']['content'] ); $commentdata['comment_meta']['ap_published'] = \wp_date( 'Y-m-d H:i:s', strtotime( $object['object']['published'] ) ); $commentdata['comment_meta']['ap_last_modified'] = $object['object']['updated']; $commentdata['comment_meta']['ap_object'] = \serialize( $object ); - //apply_filters( 'wp_update_comment_data', $data, $comment, $commentarr ); - // disable flood control \remove_action( 'check_comment_flood', 'check_comment_flood_db', 10 ); @@ -533,11 +531,11 @@ class Inbox { return; } //Determine comment_ID - $object_comment_ID = \Activitypub\url_to_commentid( \esc_url_raw( $object['object']['id'] ) ); - if ( ! is_null( $object_comment_ID ) ) { + $object_comment_id = \Activitypub\url_to_commentid( \esc_url_raw( $object['object']['id'] ) ); + if ( ! is_null( $object_comment_id ) ) { //found a local comment id - $commentdata = \get_comment( $object_comment_ID, ARRAY_A ); + $commentdata = \get_comment( $object_comment_id, ARRAY_A ); // disable flood control \remove_action( 'check_comment_flood', 'check_comment_flood_db', 10 ); @@ -548,7 +546,7 @@ class Inbox { // Should we trash or send back to moderation $state = \wp_trash_comment( $commentdata['comment_ID'], true ); - //\remove_filter( 'pre_option_require_name_email', '__return_false' ); + \remove_filter( 'pre_option_require_name_email', '__return_false' ); // re-add flood control \add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 ); diff --git a/includes/rest/class-webfinger.php b/includes/rest/class-webfinger.php index d6a11a1..705fbe8 100644 --- a/includes/rest/class-webfinger.php +++ b/includes/rest/class-webfinger.php @@ -134,7 +134,7 @@ class Webfinger { $webfinger = substr( $webfinger, 1 ); } $url_host = \explode( '@', $webfinger ); - $webfinger_query = 'https://' . \end( $url_host ) . '/.well-known/webfinger?resource=acct%3A' . \urlencode( $webfinger ); + $webfinger_query = 'https://' . \end( $url_host ) . '/.well-known/webfinger?resource=acct%3A' . \rawurlencode( $webfinger ); $response = \wp_safe_remote_get( $webfinger_query ); if ( ! is_wp_error( $response ) ) { @@ -144,7 +144,7 @@ class Webfinger { if ( ! property_exists( $link, 'type' ) ) { continue; } - if ( isset( $link->type ) && $link->type === 'application/activity+json' ) { + if ( isset( $link->type ) && 'application/activity+json' === $link->type ) { $activity_profile['href'] = $link->href; $activity_profile['name'] = $webfinger; }