diff --git a/activitypub.php b/activitypub.php
index b5aa607..c6a51fd 100644
--- a/activitypub.php
+++ b/activitypub.php
@@ -86,6 +86,19 @@ function init() {
}
\add_action( 'plugins_loaded', '\Activitypub\init' );
+/**
+ * Add plugin settings link
+ */
+function plugin_settings_link( $links ) {
+ $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 rewrite rules
*/
diff --git a/includes/class-activity-dispatcher.php b/includes/class-activity-dispatcher.php
index 4d42c24..76d762d 100644
--- a/includes/class-activity-dispatcher.php
+++ b/includes/class-activity-dispatcher.php
@@ -15,7 +15,7 @@ class Activity_Dispatcher {
public static function init() {
\add_action( 'activitypub_send_post_activity', array( '\Activitypub\Activity_Dispatcher', 'send_post_activity' ) );
\add_action( 'activitypub_send_update_activity', array( '\Activitypub\Activity_Dispatcher', 'send_update_activity' ) );
- \add_action( 'activitypub_send_delete_activity', array( '\Activitypub\Activity_Dispatcher', 'send_delete_activity' ) );
+ \add_action( 'activitypub_send_delete_activity', array( '\Activitypub\Activity_Dispatcher', 'send_delete_activity', 2 ) );
\add_action( 'activitypub_send_comment_activity', array( '\Activitypub\Activity_Dispatcher', 'send_comment_activity' ) );
\add_action( 'activitypub_send_update_comment_activity', array( '\Activitypub\Activity_Dispatcher', 'send_update_comment_activity' ) );
@@ -49,11 +49,6 @@ class Activity_Dispatcher {
* @param \Activitypub\Model\Post $activitypub_post
*/
public static function send_update_activity( $activitypub_post ) {
- // save permalink for delete
- $post_id = \url_to_postid( $activitypub_post->get_id() );
- //shouldn't this go in schedule_*_activity? yeah
- \update_post_meta( $post_id, '_ap_deleted_slug', $activitypub_post->get_id() );
-
// get latest version of post
$user_id = $activitypub_post->get_post_author();
$updated = \wp_date( 'Y-m-d\TH:i:s\Z', \strtotime( $activitypub_post->get_updated() ) );
@@ -74,10 +69,13 @@ class Activity_Dispatcher {
*
* @param \Activitypub\Model\Post $activitypub_post
*/
- public static function send_delete_activity( $activitypub_post ) {
+ public static function send_delete_activity( $activitypub_post, $permalink = null ) {
// get latest version of post
$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_deleted( $deleted );
$activitypub_activity = new \Activitypub\Model\Activity( 'Delete', \Activitypub\Model\Activity::TYPE_FULL );
@@ -101,27 +99,27 @@ class Activity_Dispatcher {
//ONLY FOR LOCAL USERS ?
$activitypub_comment = \get_comment( $activitypub_comment_id );
$user_id = $activitypub_comment->user_id;
- $replyto = get_comment_meta( $activitypub_comment->comment_parent, 'comment_author_url', true );// must include in replyto
- $mentions = get_comment_meta( $activitypub_comment_id, 'mentions', true );//might be tagged
+ $mentions[] = \get_comment_meta( $activitypub_comment_id, 'mentions', true );// mention[href, name]
$activitypub_comment = new \Activitypub\Model\Comment( $activitypub_comment );
$activitypub_activity = new \Activitypub\Model\Activity( 'Create', \Activitypub\Model\Activity::TYPE_FULL );
$activitypub_activity->from_comment( $activitypub_comment->to_array() );
+ $mentioned_actors = array();
foreach ( \Activitypub\get_mentioned_inboxes( $mentions ) as $inbox => $to ) {
$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;
}
- //will this reset the activities?
foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $cc ) {
$activitypub_activity->set_cc( $cc );//set_cc
$activity = $activitypub_activity->to_json(); // phpcs:ignore
- // Send reply to followers, skip if replying to followers (avoid duplicate replies)
- if ( in_array( $cc, $replyto ) || in_array( $cc, $mentions ) ) {
+ // Send reply to followers, skip if mentioned followers (avoid duplicate replies)
+ if ( in_array( $cc, $mentioned_actors ) ) {
continue;
}
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
@@ -136,12 +134,11 @@ class Activity_Dispatcher {
public static function inbox_forward_activity( $activitypub_comment_id ) {
$activitypub_comment = \get_comment( $activitypub_comment_id );
- //original author should NOT recieve a copy of ther own post
+ //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 ) );
//will be forwarded to the parent_comment->author or post_author followers collection
- //TODO verify that ... what?
$parent_comment = \get_comment( $activitypub_comment->comment_parent );
if ( ! is_null( $parent_comment ) ) {
$user_id = $parent_comment->user_id;
@@ -150,18 +147,16 @@ class Activity_Dispatcher {
$user_id = $original_post->post_author;
}
- //remove user_id from $activitypub_comment
- unset( $activitypub_activity['user_id'] );
-
- foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $to ) {
+ unset( $activitypub_activity['user_id'] ); // remove user_id from $activitypub_comment
+ foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $cc ) {
//Forward reply to followers, skip sender
- if ( in_array( $to, $replyto ) || ( $replyto == $to ) ) {
+ if ( in_array( $cc, $replyto ) ) {
continue;
}
- $activitypub_activity['object']['to'] = $to;
- $activitypub_activity['to'] = $to;
+ $activitypub_activity['object']['cc'] = $cc;
+ $activitypub_activity['cc'] = $cc;
$activity = \wp_json_encode( $activitypub_activity, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT );
\Activitypub\forward_remote_post( $inbox, $activity, $user_id );
diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php
index 9a26173..c3d1062 100644
--- a/includes/class-activitypub.php
+++ b/includes/class-activitypub.php
@@ -42,7 +42,7 @@ class Activitypub {
* @return string The new path to the JSON template.
*/
public static function render_json_template( $template ) {
- if ( ! \is_author() && ! \is_singular() && ! \is_home() && ! \Activitypub\is_ap_comment() ) {
+ if ( ! \is_author() && ! \is_singular() && ! \is_home() && ! \Activitypub\is_ap_comment() && ! \Activitypub\is_ap_replies() ) {
return $template;
}
@@ -169,12 +169,11 @@ class Activitypub {
if ( $commentdata['comment_type'] === 'activitypub' ) {
if ( ( $comment_approved === 1 ) &&
! empty( $commentdata['user_id'] ) &&
- ( $user = get_userdata( $commentdata['user_id'] ) ) && // get the user data
- in_array( 'administrator', $user->roles ) // check the roles
+ ( $user = \get_userdata( $commentdata['user_id'] ) ) && // get the user data
+ \in_array( 'administrator', $user->roles ) // check the roles
) {
- // Only for Admins?
+ // Only for Admins
$mentions = \get_comment_meta( $comment_id, 'mentions', true );
- //\ActivityPub\Activity_Dispatcher::send_comment_activity( $comment_id ); // performance > followers collection
\wp_schedule_single_event( \time(), 'activitypub_send_comment_activity', array( $comment_id ) );
} else {
@@ -193,7 +192,6 @@ class Activitypub {
* Fires immediately before comment status transition hooks are fired. (useful only for admin)
*/
public static function edit_comment( $comment_ID, $data ) {
- // advantage of ap_published is it would be set once, (does preprocess fire on edit?)
if ( ! is_null( $data['user_id'] ) ) {
\wp_schedule_single_event( \time(), 'activitypub_send_update_comment_activity', array( $comment_ID ) );
}
diff --git a/includes/class-admin.php b/includes/class-admin.php
index 13e57c9..e88694b 100644
--- a/includes/class-admin.php
+++ b/includes/class-admin.php
@@ -164,44 +164,31 @@ class Admin {
// Public Reply
$reply_button = '';
$actions['reply'] = sprintf(
- $reply_button,
- $comment->comment_ID,
- $comment->comment_post_ID,
- 'replyto',
- 'vim-r comment-inline',
+ $reply_button,
+ $comment->comment_ID,
+ $comment->comment_post_ID,
+ 'replyto',
+ 'vim-r comment-inline',
esc_attr__( 'Reply to this comment' ),
$recipients,
$summary,
- __( 'Reply', 'activitypub' )
+ __( 'Reply', 'activitypub' )
);
-
- // Private
- // $actions['private_reply'] = sprintf(
- // $format,
- // $comment->comment_ID,
- // $comment->comment_post_ID,
- // 'private_replyto',
- // 'vim-r comment-inline',
- // esc_attr__( 'Reply in private to this comment' ),
- // $recipients,
- // $summary,
- // __( 'Private reply', 'activitypub' )
- // );
return $actions;
}
public static function scripts_reply_comments( $hook ) {
- if ('edit-comments.php' !== $hook) {
+ if ( 'edit-comments.php' !== $hook ) {
return;
}
- wp_enqueue_script( 'activitypub_client',
- plugin_dir_url(__FILE__) . '/activitypub.js',
- array('jquery'),
- filemtime( plugin_dir_path(__FILE__) . '/activitypub.js' ),
- true
+ wp_enqueue_script(
+ 'activitypub_client',
+ plugin_dir_url( __FILE__ ) . '/activitypub.js',
+ array( 'jquery' ),
+ filemtime( plugin_dir_path( __FILE__ ) . '/activitypub.js' ),
+ true
);
}
-
}
diff --git a/includes/functions.php b/includes/functions.php
index 13368f1..174f353 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -251,6 +251,12 @@ function get_follower_inboxes( $user_id ) {
return $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();
@@ -259,7 +265,7 @@ function get_mentioned_inboxes( $mentions ) {
if ( ! $inbox || \is_wp_error( $inbox ) ) {
continue;
}
- // init array if empty
+
if ( ! isset( $inboxes[ $inbox ] ) ) {
$inboxes[ $inbox ] = array();
}
@@ -355,7 +361,10 @@ function url_to_authorid( $url ) {
/**
* Verify if in_replyto_url is a local comment,
* Or if it is a previously received remote comment
- * return int comment_id
+ * (For threading comments locally)
+ *
+ * @param string activitypub object id URI
+ * @return int comment_id
*/
function url_to_commentid( $in_replyto_url ) {
if ( empty( $in_replyto_url ) ) {
@@ -364,16 +373,12 @@ 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'] ) {
+ 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'] ) && is_int( $reply_query['ap_comment_id'] ) ) {
+ if ( isset( $reply_query['ap_comment_id'] ) ) {
//is local comment
return $reply_query['ap_comment_id'];
- } else {
- //not a comment
- return null;
}
} else {
//is remote url
@@ -396,14 +401,14 @@ function url_to_commentid( $in_replyto_url ) {
}
return $found_comment_ids[0];
}
- return null;
}
+ return null;
}
/**
* Verify if url is a wp_ap_comment,
* Or if it is a previously received remote comment
- * return int comment_id
+ * @return int comment_id
*/
function is_ap_comment() {
$comment_id = get_query_var( 'ap_comment_id', null );
@@ -418,11 +423,10 @@ function is_ap_comment() {
}
/**
- * Verify if url is a /replies endoint,
- * return int true
+ * Verify if url has a replies query,
+ * @return bool
*/
function is_ap_replies() {
- global $wp;
$replies = get_query_var( 'replies' );
if ( $replies ) {
return $replies;
@@ -476,8 +480,10 @@ function get_summary( $comment_id ) {
}
/**
- * parse content for tags to transform
+ * Parse content for tags to transform
+ *
* @param string $content to search
+ * @return array content, mentions (for storage in post_meta)
*/
function transform_tags( $content ) {
//#tags
@@ -544,21 +550,8 @@ function url_to_webfinger( $user_url ) {
}
/**
- * Transform comment url, replace #fragment with ?query
- *
- * AP Object ID must be unique
- *
- * https://www.w3.org/TR/activitypub/#obj-id
- * https://github.com/tootsuite/mastodon/issues/13879
- */
-function normalize_comment_url( $comment ) {
- $comment_id = explode( '#comment-', \get_comment_link( $comment ) );
- $comment_id = $comment_id[0] . '?ap_comment_id=' . $comment_id[1];
- return $comment_id;
-}
-
-/**
- * Set ap_comment_id
+ * @param $comment or $comment_id
+ * @return ActivityPub URI of comment
*
* AP Object ID must be unique
*
@@ -566,20 +559,16 @@ function normalize_comment_url( $comment ) {
* https://github.com/tootsuite/mastodon/issues/13879
*/
function set_ap_comment_id( $comment ) {
+ $comment = \get_comment( $comment );
$ap_comment_id = add_query_arg(
array(
'p' => $comment->comment_post_ID,
- 'ap_comment_id' => $comment->comment_ID, //should probably rename to ap_comment or something
+ 'ap_comment_id' => $comment->comment_ID,
),
trailingslashit( site_url() )
);
return $ap_comment_id;
}
-/* comment_id_to_url( $comment_id ) {
- //get remote from post_id from comment meta
- //get local normalized comment_link
- }
-*/
/**
* Determine AP audience of incoming object
@@ -591,7 +580,7 @@ function get_audience( $object ) {
return 'public';
}
if ( in_array( AS_PUBLIC, $object['cc'] ) ) {
- return 'unlisted';//is unlisted even relevant?
+ return 'unlisted';
}
if ( ! in_array( AS_PUBLIC, $object['to'] ) && ! in_array( AS_PUBLIC, $object['cc'] ) ) {
$author_post_url = get_author_posts_url( $object['user_id'] );
diff --git a/includes/model/class-comment.php b/includes/model/class-comment.php
index cd5802d..2ef5e1d 100644
--- a/includes/model/class-comment.php
+++ b/includes/model/class-comment.php
@@ -23,7 +23,7 @@ class Comment {
$this->contentWarning = $this->generate_content_warning();
$this->permalink = $this->generate_permalink();
$this->context = $this->generate_context();
- $this->cc_recipients = $this->generate_recipients();
+ $this->to_recipients = $this->generate_mention_recipients();
$this->tags = $this->generate_tags();
$this->update = $this->generate_update();
$this->deleted = $this->generate_trash();
@@ -59,9 +59,10 @@ class Comment {
'context' => $this->context,
//'source' => \get_comment_link( $comment ), //non-conforming, see https://www.w3.org/TR/activitypub/#source-property
'url' => \get_comment_link( $comment ), //link for mastodon
- 'to' => array( 'https://www.w3.org/ns/activitystreams#Public' ), //audience logic
- 'cc' => $this->cc_recipients,
+ 'to' => $this->to_recipients,
+ 'cc' => array( 'https://www.w3.org/ns/activitystreams#Public' ),
'tag' => $this->tags,
+ 'replies' => $this->replies,
);
if ( $this->replies ) {
$array['replies'] = $this->replies;
@@ -85,7 +86,7 @@ class Comment {
}
public function generate_comment_id() {
- return \Activitypub\set_ap_comment_id( $this->comment );
+ return \Activitypub\set_ap_comment_id( $this->comment->comment_ID );
}
public function generate_permalink() {
@@ -96,7 +97,7 @@ class Comment {
}
/**
- * What is status is being replied to
+ * What is status being replied to
* Comment ID or Post ID
*/
public function generate_parent_url() {
@@ -114,31 +115,43 @@ class Comment {
trailingslashit( site_url() )
);
}
- } else {
- $inReplyTo = add_query_arg(
- array(
- 'p' => $comment->comment_post_ID,
- ),
- trailingslashit( site_url() )
- );
+ } else { //parent is_post
+ // Backwards compatibility
+ $pretty_permalink = \get_post_meta( $comment->comment_post_ID, '_activitypub_permalink_compat', true ); // TODO finalize meta
+ if ( $pretty_permalink ) {
+ $inReplyTo = $pretty_permalink;
+ } else {
+ $inReplyTo = add_query_arg(
+ array(
+ 'p' => $comment->comment_post_ID,
+ ),
+ trailingslashit( site_url() )
+ );
+ }
}
return $inReplyTo;
}
public function generate_context() {
$comment = $this->comment;
- $inReplyTo = add_query_arg(
- array(
- 'p' => $comment->comment_post_ID,
- ),
- trailingslashit( site_url() )
- );
- return $inReplyTo;
+ // support pretty_permalinks
+ $pretty_permalink = \get_post_meta( $comment->comment_post_ID, '_activitypub_permalink_compat', true );
+ if ( $pretty_permalink ) {
+ $context = $pretty_permalink;
+ } else {
+ $context = add_query_arg(
+ array(
+ 'p' => $comment->comment_post_ID,
+ ),
+ trailingslashit( site_url() )
+ );
+ }
+ return $context;
}
/**
* Generate courtesy Content Warning
- * If peer used CW let's just copy it
+ * If parent status used CW let's just copy it
* TODO: Move to preprocess_comment / row_actions
* Add option for wrapping CW in Details/Summary markup
* Figure out some CW syntax: [shortcode-style], {brackets-style}?
@@ -148,7 +161,7 @@ class Comment {
$comment = $this->comment;
$contentWarning = null;
- // TODO Replace auto CW, with Title field or CW shortcode
+ // Temporarily generate Summary from parent
$parent_comment = \get_comment( $comment->comment_parent );
if ( $parent_comment ) {
//get (received) comment
@@ -157,9 +170,10 @@ class Comment {
$contentWarning = $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 ); //TODO
+ $contentWarning = \Activitypub\add_summary( $summary );
} */
return $contentWarning;
}
@@ -167,9 +181,7 @@ class Comment {
/**
* Who is being replied to
*/
- public function generate_recipients() {
- //TODO Add audience logic get parent audience
- //TODO shouldn't mentions go in 'to'?
+ public function generate_mention_recipients() {
$recipients = array( AS_PUBLIC );
$mentions = \get_comment_meta( $this->comment->comment_ID, 'mentions', true );
if ( ! empty( $mentions ) ) {
@@ -226,40 +238,41 @@ class Comment {
*/
public function generate_replies() {
$comment = $this->comment;
+ $replies = [];
$args = array(
'post_id' => $comment->comment_post_ID,
'parent' => $comment->comment_ID,
- 'author__in' => $comment->user_id,
'status' => 'approve',
'hierarchical' => false,
);
- $children = \get_comments( $args );
- $replies = null;
- if ( $children ) {
+ $comments_list = \get_comments( $args );
+
+ if ( $comments_list ) {
$items = array();
- foreach ( $children as $child_comment ) {
- $comment_url = \add_query_arg(
- array(
- 'p' => $child_comment->comment_post_ID,
- 'ap_comment_id' => $child_comment->comment_ID,
- ),
- trailingslashit( site_url() )
- );
- $items[] = $comment_url;
+ foreach ( $comments_list as $comment ) {
+ // remote replies
+ $source_url = \get_comment_meta( $comment->comment_ID, 'source_url', true );
+ if ( ! empty( $source_url ) ){
+ $items[] = $source_url;
+ } else {
+ // local replies
+ $comment_url = \add_query_arg( //
+ array(
+ 'p' => $comment->comment_post_ID,
+ 'ap_comment_id' => $comment->comment_ID,
+ ),
+ trailingslashit( site_url() )
+ );
+ $items[] = $comment_url;
+ }
}
+
$replies = (object) array(
'type' => 'Collection',
'id' => \add_query_arg( array( 'replies' => '' ), $this->id ),
'first' => (object) array(
'type' => 'CollectionPage',
'partOf' => \add_query_arg( array( 'replies' => '' ), $this->id ),
- 'next' => \add_query_arg(
- array(
- 'replies' => '',
- 'page' => 1,
- ),
- $this->id
- ),
'items' => $items,
),
);
diff --git a/includes/model/class-post.php b/includes/model/class-post.php
index 0bae523..c16e2e0 100644
--- a/includes/model/class-post.php
+++ b/includes/model/class-post.php
@@ -30,9 +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->slug = \get_permalink( $this->id );
- $this->updated = null;
+ $this->updated = $this->generate_updated();
$this->delete = $this->get_deleted();
}
@@ -73,9 +71,10 @@ class Post {
}
if ( $this->deleted ) {
$array['deleted'] = \date( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_modified_gmt ) );
- // TODO if using slugs instead of ids _ap_deleted_slug
- //$deleted_post_slug = \get_post_meta( $post->ID, '_ap_deleted_slug', true );
- //$array['id'] = $deleted_post_slug;
+ $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 ) );
@@ -89,15 +88,19 @@ class Post {
public function generate_id() {
$post = $this->post;
- $permalink = \add_query_arg( //
- array(
- 'p' => $post->ID,
- ),
- trailingslashit( site_url() )
- );
+ $pretty_permalink = \get_post_meta( $post->ID, '_activitypub_permalink_compat', true );
- // replace 'trashed' for delete activity
- return \str_replace( '__trashed', '', $permalink );
+ if( ! empty( $pretty_permalink ) ) {
+ $object_id = $pretty_permalink;
+ } else {
+ $object_id = \add_query_arg( //
+ array(
+ 'p' => $post->ID,
+ ),
+ trailingslashit( site_url() )
+ );
+ }
+ return $object_id;
}
public function generate_attachments() {
@@ -180,10 +183,9 @@ class Post {
public function generate_replies() {
$replies = null;
- //\error_log( 'generate_replies: $post' . print_r( $this->post, true ) );
if ( $this->post->comment_count > 0 ) {
$args = array(
- 'post_id' => $this->post->ID, // Use post_id, not post_ID
+ 'post_id' => $this->post->ID,
'hierarchical' => false,
'status' => 'approve',
);
@@ -193,7 +195,6 @@ class Post {
foreach ( $comments as $comment ) {
// include self replies
if ( $this->post->post_author === $comment->user_id ) {
- //$comment_url = $comment->comment_ID;
$comment_url = \add_query_arg( //
array(
'p' => $this->post->ID,
@@ -201,24 +202,23 @@ class Post {
),
trailingslashit( site_url() )
);
- //\error_log( 'generate_replies: $comment' . print_r( $comment, true ) );
$items[] = $comment_url;
+ } 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 );
+ }
+
}
}
- //\error_log( 'generate_replies: $comments' . print_r( $comments, true ) );
+
$replies = (object) array(
'type' => 'Collection',
'id' => \add_query_arg( array( 'replies' => '' ), $this->id ),
'first' => (object) array(
'type' => 'CollectionPage',
'partOf' => \add_query_arg( array( 'replies' => '' ), $this->id ),
- 'next' => \add_query_arg(
- array(
- 'replies' => '',
- 'page' => 1,
- ),
- $this->id
- ),
'items' => $items,
),
);
diff --git a/includes/rest/class-inbox.php b/includes/rest/class-inbox.php
index 61e4eb8..d83f85b 100644
--- a/includes/rest/class-inbox.php
+++ b/includes/rest/class-inbox.php
@@ -427,13 +427,6 @@ class Inbox {
}
}
- //not all implementaions use url
- if ( isset( $object['object']['id'] ) ) {
- $source_url = \esc_url_raw( $object['object']['id'] );
- } else {
- $source_url = \esc_url_raw( $object['object']['url'] );
- }
-
// if no name is set use peer username
if ( ! empty( $meta['name'] ) ) {
$name = \esc_attr( $meta['name'] );
@@ -446,10 +439,10 @@ class Inbox {
}
//Only create WP_Comment for public replies to local posts
- if ( ( in_array( AS_PUBLIC, $object['to'] )
- || in_array( AS_PUBLIC, $object['cc'] ) )
+ if ( ( 'public' === $audience )
+ || ( 'unlisted' === $audience )
&& ( ! empty( $comment_post_ID )
- || ! empty( $comment_parent )
+ || ! empty( $comment_parent_ID )
) ) {
$commentdata = array(
@@ -462,7 +455,7 @@ class Inbox {
'comment_parent' => $comment_parent_ID,
'comment_meta' => array(
'ap_object' => \serialize( $object ),
- 'source_url' => $source_url,
+ 'source_url' => \esc_url_raw( $object['object']['id'] ),
'avatar_url' => $avatar_url,
'protocol' => 'activitypub',
),
diff --git a/includes/rest/class-webfinger.php b/includes/rest/class-webfinger.php
index 09af42a..d6a11a1 100644
--- a/includes/rest/class-webfinger.php
+++ b/includes/rest/class-webfinger.php
@@ -126,6 +126,7 @@ class Webfinger {
* WebFinger Lookup to find user uri
*
* @param string $resource the WebFinger resource
+ * @return array ['href', 'name']. ex: href=https://domain.tld/user/webfinger, name=webfinger@domain.tld
*/
public static function webfinger_lookup( $webfinger ) {
$activity_profile = null;
diff --git a/templates/comment-json.php b/templates/comment-json.php
index 13ba9cd..1749620 100644
--- a/templates/comment-json.php
+++ b/templates/comment-json.php
@@ -1,5 +1,5 @@
\Activitypub\get_context() ), $activitypub_comment->to_array() );
diff --git a/templates/replies-json.php b/templates/replies-json.php
new file mode 100644
index 0000000..6135ad8
--- /dev/null
+++ b/templates/replies-json.php
@@ -0,0 +1,84 @@
+ 'approve',
+ 'number' => '10',
+ 'offset' => $page,
+ 'type' => 'activitypub',
+ 'post_id' => $post->ID,
+ 'order' => 'ASC',
+);
+$comments = get_comments( $args );
+
+$replies_request = \add_query_arg( $_SERVER['QUERY_STRING'], '', $post->guid );
+$collection_id = \remove_query_arg(['page', 'ap_comment_id'], $replies_request );
+
+$json = new \stdClass();
+$json->{'@context'} = 'https://www.w3.org/ns/activitystreams';
+$json->id = $collection_id;
+
+$collectionPage = new \stdClass();
+$collectionPage->type = 'CollectionPage';
+$collectionPage->partOf = $collection_id;
+$collectionPage->totalItems = \count( $comments ); // phpcs:ignore
+
+if ( $page && ( ( \ceil ( $collectionPage->totalItems / 10 ) ) > $page ) ) { // phpcs:ignore
+ $collectionPage->first = \add_query_arg( 'page', 1, $collectionPage->partOf ); // phpcs:ignore TODO
+ $collectionPage->next = \add_query_arg( 'page', $page + 1, $collectionPage->partOf ); // phpcs:ignore
+ $collectionPage->last = \add_query_arg( 'page', \ceil ( $collectionPage->totalItems / 10 ), $collectionPage->partOf ); // phpcs:ignore
+}
+
+foreach ( $comments as $comment ) {
+ $remote_url = \get_comment_meta( $comment->comment_ID, 'source_url', true );
+ if ( $remote_url ) { //
+ $collectionPage->items[] = $remote_url;
+ } else {
+ $activitypub_comment = new \Activitypub\Model\Comment( $comment );
+ $activitypub_activity = new \Activitypub\Model\Activity( 'Create', \Activitypub\Model\Activity::TYPE_NONE );
+ $activitypub_activity->from_post( $activitypub_comment->to_array() );
+ $collectionPage->items[] = $activitypub_activity->to_array(); // phpcs:ignore
+ }
+}
+
+if ( ! \get_query_var( 'collection_page' ) ) {
+ $json->type = 'Collection';
+ //if +10, embed first
+ $json->first = $collectionPage;
+} else {
+ $json = $collectionPage;
+
+}
+
+// filter output
+$json = \apply_filters( 'activitypub_json_replies_array', $json );
+
+/*
+ * Action triggerd prior to the ActivityPub profile being created and sent to the client
+ */
+\do_action( 'activitypub_json_replies_pre' );
+
+$options = 0;
+// JSON_PRETTY_PRINT added in PHP 5.4
+if ( \get_query_var( 'pretty' ) ) {
+ $options |= \JSON_PRETTY_PRINT; // phpcs:ignore
+}
+
+$options |= \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT;
+
+/*
+ * Options to be passed to json_encode()
+ *
+ * @param int $options The current options flags
+ */
+$options = \apply_filters( 'activitypub_json_replies_options', $options );
+
+\header( 'Content-Type: application/activity+json' );
+echo \wp_json_encode( $json, $options );
+
+/*
+ * Action triggerd after the ActivityPub profile has been created and sent to the client
+ */
+\do_action( 'activitypub_json_replies_comment' );