Replies Collection, settings, other fixes
This commit is contained in:
parent
51643142aa
commit
8e1c9ff6bb
11 changed files with 246 additions and 173 deletions
|
@ -86,6 +86,19 @@ function init() {
|
|||
}
|
||||
\add_action( 'plugins_loaded', '\Activitypub\init' );
|
||||
|
||||
/**
|
||||
* Add plugin settings link
|
||||
*/
|
||||
function plugin_settings_link( $links ) {
|
||||
$settings_link[] = \sprintf( '<a href="%1s">%2s</a>',
|
||||
\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
|
||||
*/
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
|
|
|
@ -164,44 +164,31 @@ class Admin {
|
|||
// Public Reply
|
||||
$reply_button = '<button type="button" data-comment-id="%d" data-post-id="%d" data-action="%s" class="%s button-link" aria-expanded="false" aria-label="%s" data-recipients="%s" data-summary="%s">%s</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' ),
|
||||
wp_enqueue_script(
|
||||
'activitypub_client',
|
||||
plugin_dir_url( __FILE__ ) . '/activitypub.js',
|
||||
array( 'jquery' ),
|
||||
filemtime( plugin_dir_path( __FILE__ ) . '/activitypub.js' ),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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'] );
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
|
|
|
@ -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',
|
||||
),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
$comment = \get_comment( get_query_var('ap_comment_id') );
|
||||
$comment = \get_comment( \get_query_var( 'ap_comment_id' ) );
|
||||
|
||||
$activitypub_comment = new \Activitypub\Model\Comment( $comment );
|
||||
$json = \array_merge( array( '@context' => \Activitypub\get_context() ), $activitypub_comment->to_array() );
|
||||
|
|
84
templates/replies-json.php
Normal file
84
templates/replies-json.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
$post = \get_post();
|
||||
|
||||
$page = \get_query_var( 'page' );
|
||||
$args = array(
|
||||
'status' => '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' );
|
Loading…
Reference in a new issue