migrate dispatch, migrate comment model to transform
This commit is contained in:
parent
f808ff33cb
commit
133c16dc3e
3 changed files with 265 additions and 491 deletions
|
@ -2,10 +2,12 @@
|
||||||
namespace Activitypub;
|
namespace Activitypub;
|
||||||
|
|
||||||
use WP_Post;
|
use WP_Post;
|
||||||
|
use WP_Comment;
|
||||||
use Activitypub\Activity\Activity;
|
use Activitypub\Activity\Activity;
|
||||||
use Activitypub\Collection\Users;
|
use Activitypub\Collection\Users;
|
||||||
use Activitypub\Collection\Followers;
|
use Activitypub\Collection\Followers;
|
||||||
use Activitypub\Transformer\Post;
|
use Activitypub\Transformer\Post;
|
||||||
|
use Activitypub\Transformer\Comment;
|
||||||
|
|
||||||
use function Activitypub\is_single_user;
|
use function Activitypub\is_single_user;
|
||||||
use function Activitypub\is_user_disabled;
|
use function Activitypub\is_user_disabled;
|
||||||
|
@ -25,6 +27,7 @@ class Activity_Dispatcher {
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity' ), 10, 2 );
|
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity' ), 10, 2 );
|
||||||
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity_or_announce' ), 10, 2 );
|
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity_or_announce' ), 10, 2 );
|
||||||
|
\add_action( 'activitypub_send_comment_activity', array( self::class, 'send_comment_activity' ), 10, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,200 +127,29 @@ class Activity_Dispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send "delete" activities.
|
* Send Activities to followers and mentioned users.
|
||||||
*
|
*
|
||||||
* @param str $activitypub_url
|
* @param WP_Comment $wp_comment The ActivityPub Comment.
|
||||||
* @param int $user_id
|
* @param string $type The Activity-Type.
|
||||||
*/
|
*/
|
||||||
public static function send_delete_url_activity( $activitypub_url, $user_id ) {
|
public static function send_comment_activity( WP_Comment $wp_comment, $type ) {
|
||||||
// get latest version of post
|
|
||||||
$actor = \get_author_posts_url( $user_id );
|
|
||||||
$deleted = \current_time( 'Y-m-d\TH:i:s\Z', true );
|
|
||||||
|
|
||||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Delete', \Activitypub\Model\Activity::TYPE_SIMPLE );
|
$object = Comment::transform( $wp_comment )->to_object();
|
||||||
$activitypub_activity->set_id( $activitypub_url . '#delete' );
|
|
||||||
$activitypub_activity->set_actor( $actor );
|
|
||||||
$activitypub_activity->set_object(
|
|
||||||
array(
|
|
||||||
'id' => $activitypub_url,
|
|
||||||
'type' => 'Tombstone',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$activitypub_activity->set_deleted( $deleted );
|
|
||||||
|
|
||||||
foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $to ) {
|
$activity = new Activity();
|
||||||
$activitypub_activity->set_to( $to );
|
$activity->set_type( $type );
|
||||||
$activity = $activitypub_activity->to_json(); // phpcs:ignore
|
$activity->set_object( $object );
|
||||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$follower_inboxes = Followers::get_inboxes( $wp_comment->user_id );
|
||||||
* Send "create" activities for comments
|
$mentioned_inboxes = Mention::get_inboxes( $activity->get_cc() );
|
||||||
*
|
|
||||||
* @param \Activitypub\Model\Comment $activitypub_comment
|
|
||||||
*/
|
|
||||||
public static function send_comment_activity( $activitypub_comment_id ) {
|
|
||||||
//ONLY FOR LOCAL USERS ?
|
|
||||||
$activitypub_comment = \get_comment( $activitypub_comment_id );
|
|
||||||
$user_id = $activitypub_comment->user_id;
|
|
||||||
$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() );
|
|
||||||
|
|
||||||
$inboxes = \Activitypub\get_follower_inboxes( $user_id );
|
$inboxes = array_merge( $follower_inboxes, $mentioned_inboxes );
|
||||||
|
$inboxes = array_unique( $inboxes );
|
||||||
|
|
||||||
$followers_url = \get_rest_url( null, '/activitypub/1.0/users/' . intval( $user_id ) . '/followers' );
|
$json = $activity->to_json();
|
||||||
foreach ( $activitypub_activity->get_cc() as $cc ) {
|
|
||||||
if ( $cc === $followers_url ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$inbox = \Activitypub\get_inbox_by_actor( $cc );
|
|
||||||
if ( ! $inbox || \is_wp_error( $inbox ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// init array if empty
|
|
||||||
if ( ! isset( $inboxes[ $inbox ] ) ) {
|
|
||||||
$inboxes[ $inbox ] = array();
|
|
||||||
}
|
|
||||||
$inboxes[ $inbox ][] = $cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( $inboxes as $inbox => $to ) {
|
foreach ( $inboxes as $inbox ) {
|
||||||
$to = array_values( array_unique( $to ) );
|
safe_remote_post( $inbox, $json, $wp_comment->user_id );
|
||||||
$activitypub_activity->set_to( $to );
|
|
||||||
$activity = $activitypub_activity->to_json();
|
|
||||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forward replies to followers
|
|
||||||
*
|
|
||||||
* @param \Activitypub\Model\Comment $activitypub_comment
|
|
||||||
*/
|
|
||||||
public static function inbox_forward_activity( $activitypub_comment_id ) {
|
|
||||||
$activitypub_comment = \get_comment( $activitypub_comment_id );
|
|
||||||
|
|
||||||
//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
|
|
||||||
$parent_comment = \get_comment( $activitypub_comment->comment_parent );
|
|
||||||
if ( ! is_null( $parent_comment ) ) {
|
|
||||||
$user_id = $parent_comment->user_id;
|
|
||||||
} else {
|
|
||||||
$original_post = \get_post( $activitypub_comment->comment_post_ID );
|
|
||||||
$user_id = $original_post->post_author;
|
|
||||||
}
|
|
||||||
|
|
||||||
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( $cc, $replyto ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send "update" activities.
|
|
||||||
*
|
|
||||||
* @param \Activitypub\Model\Comment $activitypub_comment
|
|
||||||
*/
|
|
||||||
public static function send_update_comment_activity( $activitypub_comment_id ) {
|
|
||||||
$activitypub_comment = \get_comment( $activitypub_comment_id );
|
|
||||||
$updated = \get_comment_meta( $activitypub_comment_id, 'ap_last_modified', true );
|
|
||||||
|
|
||||||
$user_id = $activitypub_comment->user_id;
|
|
||||||
if ( ! $user_id ) { // Prevent sending received/anonymous comments.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$activitypub_comment = new \Activitypub\Model\Comment( $activitypub_comment );
|
|
||||||
$activitypub_comment->set_update( $updated );
|
|
||||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Update', \Activitypub\Model\Activity::TYPE_FULL );
|
|
||||||
$activitypub_activity->from_comment( $activitypub_comment->to_array() );
|
|
||||||
$activitypub_activity->set_update( $updated );
|
|
||||||
|
|
||||||
$inboxes = \Activitypub\get_follower_inboxes( $user_id );
|
|
||||||
$followers_url = \get_rest_url( null, '/activitypub/1.0/users/' . intval( $user_id ) . '/followers' );
|
|
||||||
|
|
||||||
foreach ( $activitypub_activity->get_cc() as $cc ) {
|
|
||||||
if ( $cc === $followers_url ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$inbox = \Activitypub\get_inbox_by_actor( $cc );
|
|
||||||
if ( ! $inbox || \is_wp_error( $inbox ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// init array if empty
|
|
||||||
if ( ! isset( $inboxes[ $inbox ] ) ) {
|
|
||||||
$inboxes[ $inbox ] = array();
|
|
||||||
}
|
|
||||||
$inboxes[ $inbox ][] = $cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( $inboxes as $inbox => $to ) {
|
|
||||||
$to = array_values( array_unique( $to ) );
|
|
||||||
$activitypub_activity->set_to( $to );
|
|
||||||
$activity = $activitypub_activity->to_json();
|
|
||||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send "delete" activities.
|
|
||||||
*
|
|
||||||
* @param \Activitypub\Model\Comment $activitypub_comment
|
|
||||||
*/
|
|
||||||
public static function send_delete_comment_activity( $activitypub_comment_id ) {
|
|
||||||
// get comment
|
|
||||||
$activitypub_comment = \get_comment( $activitypub_comment_id );
|
|
||||||
$user_id = $activitypub_comment->user_id;
|
|
||||||
// Prevent sending received/anonymous comments
|
|
||||||
if ( ! $user_id ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$deleted = \wp_date( 'Y-m-d\TH:i:s\Z', \strtotime( $activitypub_comment->comment_date_gmt ) );
|
|
||||||
|
|
||||||
$activitypub_comment = new \Activitypub\Model\Comment( $activitypub_comment );
|
|
||||||
$activitypub_comment->set_deleted( $deleted );
|
|
||||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Delete', \Activitypub\Model\Activity::TYPE_FULL );
|
|
||||||
$activitypub_activity->from_comment( $activitypub_comment->to_array() );
|
|
||||||
$activitypub_activity->set_deleted( $deleted );
|
|
||||||
|
|
||||||
$inboxes = \Activitypub\get_follower_inboxes( $user_id );
|
|
||||||
$followers_url = \get_rest_url( null, '/activitypub/1.0/users/' . intval( $user_id ) . '/followers' );
|
|
||||||
|
|
||||||
foreach ( $activitypub_activity->get_cc() as $cc ) {
|
|
||||||
if ( $cc === $followers_url ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$inbox = \Activitypub\get_inbox_by_actor( $cc );
|
|
||||||
if ( ! $inbox || \is_wp_error( $inbox ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// init array if empty
|
|
||||||
if ( ! isset( $inboxes[ $inbox ] ) ) {
|
|
||||||
$inboxes[ $inbox ] = array();
|
|
||||||
}
|
|
||||||
$inboxes[ $inbox ][] = $cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( $inboxes as $inbox => $to ) {
|
|
||||||
$to = array_values( array_unique( $to ) );
|
|
||||||
$activitypub_activity->set_to( $to );
|
|
||||||
$activity = $activitypub_activity->to_json();
|
|
||||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,305 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Activitypub\Model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ActivityPub Comment Class
|
|
||||||
*
|
|
||||||
* @author Django Doucet
|
|
||||||
*/
|
|
||||||
class Comment {
|
|
||||||
private $comment;
|
|
||||||
private $id;
|
|
||||||
private $comment_author_url;
|
|
||||||
private $post_author;
|
|
||||||
private $in_reply_to;
|
|
||||||
private $content_warning;
|
|
||||||
private $permalink;
|
|
||||||
private $context;
|
|
||||||
private $to_recipients;
|
|
||||||
private $tags;
|
|
||||||
private $update;
|
|
||||||
private $deleted;
|
|
||||||
private $replies;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the class
|
|
||||||
*/
|
|
||||||
public function __construct( $comment = null ) {
|
|
||||||
$this->comment = $comment;
|
|
||||||
$this->id = $this->generate_comment_id();
|
|
||||||
$this->comment_author_url = \get_author_posts_url( $this->comment->user_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 ) {
|
|
||||||
$var = \strtolower( \substr( $method, 4 ) );
|
|
||||||
|
|
||||||
if ( \strncasecmp( $method, 'get', 3 ) === 0 ) {
|
|
||||||
return $this->$var;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
|
|
||||||
$this->$var = $params[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function to_array() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
|
|
||||||
$array = array(
|
|
||||||
'id' => $this->id,
|
|
||||||
'type' => 'Note',
|
|
||||||
'published' => \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $comment->comment_date_gmt ) ),
|
|
||||||
'attributedTo' => $this->comment_author_url,
|
|
||||||
'summary' => $this->content_warning,
|
|
||||||
'inReplyTo' => $this->in_reply_to,
|
|
||||||
'content' => $this->get_content(),
|
|
||||||
'contentMap' => array(
|
|
||||||
\strstr( \get_locale(), '_', true ) => $this->get_content(),
|
|
||||||
),
|
|
||||||
'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' ),
|
|
||||||
'cc' => array( 'https://www.w3.org/ns/activitystreams#Public' ),
|
|
||||||
'tag' => $this->tags,
|
|
||||||
);
|
|
||||||
if ( $this->replies ) {
|
|
||||||
$array['replies'] = $this->replies;
|
|
||||||
}
|
|
||||||
if ( $this->update ) {
|
|
||||||
$array['updated'] = $this->update;
|
|
||||||
}
|
|
||||||
if ( $this->deleted ) {
|
|
||||||
$array['deleted'] = $this->deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
return \apply_filters( 'activitypub_comment', $array );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function to_json() {
|
|
||||||
return \wp_json_encode( $this->to_array(), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generate_comment_author_link() {
|
|
||||||
return \get_author_posts_url( $this->comment->comment_author );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generate_comment_id() {
|
|
||||||
return \Activitypub\set_ap_comment_id( $this->comment->comment_ID );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generate_permalink() {
|
|
||||||
return \get_comment_link( $this->comment );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* What is status being replied to
|
|
||||||
* Comment ID or Post ID
|
|
||||||
*/
|
|
||||||
public function generate_parent_url() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
$parent_comment = \get_comment( $comment->comment_parent );
|
|
||||||
if ( $comment->comment_parent ) {
|
|
||||||
//is parent remote?
|
|
||||||
$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,
|
|
||||||
'replytocom' => $comment->comment_parent,
|
|
||||||
),
|
|
||||||
trailingslashit( site_url() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else { //parent is_post
|
|
||||||
// Backwards compatibility
|
|
||||||
$pretty_permalink = \get_post_meta( $comment->comment_post_ID, 'activitypub_canonical_url', true );
|
|
||||||
if ( $pretty_permalink ) {
|
|
||||||
$in_reply_to = $pretty_permalink;
|
|
||||||
} else {
|
|
||||||
$in_reply_to = add_query_arg(
|
|
||||||
array(
|
|
||||||
'p' => $comment->comment_post_ID,
|
|
||||||
),
|
|
||||||
trailingslashit( site_url() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $in_reply_to;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generate_context() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
// support pretty_permalinks
|
|
||||||
$pretty_permalink = \get_post_meta( $comment->comment_post_ID, 'activitypub_canonical_url', 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 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}?
|
|
||||||
* So it can be inserted into reply textbox, and removed or modified at will
|
|
||||||
*/
|
|
||||||
public function generate_content_warning() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
$content_warning = null;
|
|
||||||
|
|
||||||
// Temporarily generate Summary from parent
|
|
||||||
$parent_comment = \get_comment( $comment->comment_parent );
|
|
||||||
if ( $parent_comment ) {
|
|
||||||
//get (received) comment
|
|
||||||
$ap_object = \unserialize( \get_comment_meta( $comment->comment_parent, 'ap_object', true ) );
|
|
||||||
if ( isset( $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 ) ) {
|
|
||||||
$content_warning = \Activitypub\add_summary( $summary );
|
|
||||||
} */
|
|
||||||
return $content_warning;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Who is being replied to
|
|
||||||
*/
|
|
||||||
public function get_content() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
|
|
||||||
if ( isset( $this->content ) ) {
|
|
||||||
return $this->content;
|
|
||||||
}
|
|
||||||
|
|
||||||
$comment_content = $comment->comment_content;
|
|
||||||
|
|
||||||
$filtered_content = \apply_filters( 'the_content', $comment_content, $comment );
|
|
||||||
$decoded_content = \html_entity_decode( $filtered_content, \ENT_QUOTES, 'UTF-8' );
|
|
||||||
|
|
||||||
$content = \trim( \preg_replace( '/[\n\r\t]/', '', $decoded_content ) );
|
|
||||||
|
|
||||||
$this->content = $content;
|
|
||||||
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mention user being replied to
|
|
||||||
*/
|
|
||||||
public function generate_tags() {
|
|
||||||
if ( $this->tags ) {
|
|
||||||
return $this->tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tags = array();
|
|
||||||
|
|
||||||
$mentions = apply_filters( 'activitypub_extract_mentions', array(), $this->comment->comment_content, $this );
|
|
||||||
if ( $mentions ) {
|
|
||||||
foreach ( $mentions as $mention => $url ) {
|
|
||||||
$tag = array(
|
|
||||||
'type' => 'Mention',
|
|
||||||
'href' => $url,
|
|
||||||
'name' => $mention,
|
|
||||||
);
|
|
||||||
$tags[] = $tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->tags = $tags;
|
|
||||||
|
|
||||||
return $tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate updated datetime
|
|
||||||
*/
|
|
||||||
public function generate_update() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
$updated = null;
|
|
||||||
if ( \get_comment_meta( $comment->comment_ID, 'ap_last_modified', true ) ) {
|
|
||||||
$updated = \wp_date( 'Y-m-d\TH:i:s\Z', \get_comment_meta( $comment->comment_ID, 'ap_last_modified', true ) );
|
|
||||||
}
|
|
||||||
return $updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate deleted datetime
|
|
||||||
*/
|
|
||||||
public function generate_trash() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
$deleted = null;
|
|
||||||
if ( 'trash' === $comment->status ) {
|
|
||||||
$deleted = \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $comment->comment_date_gmt ) );
|
|
||||||
}
|
|
||||||
return $deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate replies collections
|
|
||||||
*/
|
|
||||||
public function generate_replies() {
|
|
||||||
$comment = $this->comment;
|
|
||||||
$replies = array();
|
|
||||||
$args = array(
|
|
||||||
'post_id' => $comment->comment_post_ID,
|
|
||||||
'parent' => $comment->comment_ID,
|
|
||||||
'status' => 'approve',
|
|
||||||
'hierarchical' => false,
|
|
||||||
);
|
|
||||||
$comments_list = \get_comments( $args );
|
|
||||||
|
|
||||||
if ( $comments_list ) {
|
|
||||||
$items = array();
|
|
||||||
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,
|
|
||||||
'replytocom' => $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 ),
|
|
||||||
'items' => $items,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $replies;
|
|
||||||
}
|
|
||||||
}
|
|
247
includes/transformer/class-comment.php
Normal file
247
includes/transformer/class-comment.php
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
<?php
|
||||||
|
namespace Activitypub\Transformer;
|
||||||
|
|
||||||
|
use WP_Comment;
|
||||||
|
use Activitypub\Collection\Users;
|
||||||
|
use Activitypub\Model\Blog_User;
|
||||||
|
use Activitypub\Activity\Base_Object;
|
||||||
|
use Activitypub\Hashtag;
|
||||||
|
|
||||||
|
use function Activitypub\esc_hashtag;
|
||||||
|
use function Activitypub\is_single_user;
|
||||||
|
use function Activitypub\get_rest_url_by_path;
|
||||||
|
use function Activitypub\set_ap_comment_id;
|
||||||
|
use function Activitypub\get_in_reply_to;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WordPress Comment Transformer
|
||||||
|
*
|
||||||
|
* The Comment Transformer is responsible for transforming a WP_Comment object into different
|
||||||
|
* Object-Types.
|
||||||
|
*
|
||||||
|
* Currently supported are:
|
||||||
|
*
|
||||||
|
* - Activitypub\Activity\Base_Object
|
||||||
|
*/
|
||||||
|
class Comment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WP_Comment object.
|
||||||
|
*
|
||||||
|
* @var WP_Comment
|
||||||
|
*/
|
||||||
|
protected $wp_comment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static function to Transform a WP_Comment Object.
|
||||||
|
*
|
||||||
|
* This helps to chain the output of the Transformer.
|
||||||
|
*
|
||||||
|
* @param WP_Comment $wp_comment The WP_Comment object
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function transform( WP_Comment $wp_comment ) {
|
||||||
|
return new static( $wp_comment );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param WP_Comment $wp_comment
|
||||||
|
*/
|
||||||
|
public function __construct( WP_Comment $wp_comment ) {
|
||||||
|
$this->wp_comment = $wp_comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms the WP_Comment object to an ActivityPub Object
|
||||||
|
*
|
||||||
|
* @see \Activitypub\Activity\Base_Object
|
||||||
|
*
|
||||||
|
* @return \Activitypub\Activity\Base_Object The ActivityPub Object
|
||||||
|
*/
|
||||||
|
public function to_object() {
|
||||||
|
$wp_comment = $this->wp_comment;
|
||||||
|
$object = new Base_Object();
|
||||||
|
|
||||||
|
$object->set_id( set_ap_comment_id( $wp_comment ) );
|
||||||
|
$object->set_url( \get_comment_link( $wp_comment->ID ) );
|
||||||
|
$object->set_context( \get_permalink( $wp_comment->comment_post_ID ) );
|
||||||
|
$object->set_type( 'Note' );
|
||||||
|
|
||||||
|
$published = \strtotime( $wp_comment->comment_date_gmt );
|
||||||
|
$object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) );
|
||||||
|
|
||||||
|
$updated = \get_comment_meta( $wp_comment->comment_ID, 'ap_last_modified', true );
|
||||||
|
if ( $updated > $published ) {
|
||||||
|
$object->set_updated( \gmdate( 'Y-m-d\TH:i:s\Z', $updated ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$object->set_attributed_to( $this->get_attributed_to() );
|
||||||
|
$object->set_in_reply_to( $this->get_in_reply_to() );
|
||||||
|
$object->set_content( $this->get_content() );
|
||||||
|
$object->set_content_map(
|
||||||
|
array(
|
||||||
|
\strstr( \get_locale(), '_', true ) => $this->get_content(),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$path = sprintf( 'users/%d/followers', intval( $wp_comment->comment_author ) );
|
||||||
|
|
||||||
|
$object->set_to(
|
||||||
|
array(
|
||||||
|
'https://www.w3.org/ns/activitystreams#Public',
|
||||||
|
get_rest_url_by_path( $path ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$object->set_cc( $this->get_cc() );
|
||||||
|
$object->set_tag( $this->get_tags() );
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the User-URL of the Author of the Post.
|
||||||
|
*
|
||||||
|
* If `single_user` mode is enabled, the URL of the Blog-User is returned.
|
||||||
|
*
|
||||||
|
* @return string The User-URL.
|
||||||
|
*/
|
||||||
|
protected function get_attributed_to() {
|
||||||
|
if ( is_single_user() ) {
|
||||||
|
$user = new Blog_User();
|
||||||
|
return $user->get_url();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Users::get_by_id( $this->wp_comment->user_id )->get_url();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of Mentions, used in the Comment.
|
||||||
|
*
|
||||||
|
* @see https://docs.joinmastodon.org/spec/activitypub/#Mention
|
||||||
|
*
|
||||||
|
* @return array The list of Mentions.
|
||||||
|
*/
|
||||||
|
protected function get_cc() {
|
||||||
|
$cc = array();
|
||||||
|
|
||||||
|
$mentions = $this->get_mentions();
|
||||||
|
if ( $mentions ) {
|
||||||
|
foreach ( $mentions as $mention => $url ) {
|
||||||
|
$cc[] = $url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of Tags, used in the Comment.
|
||||||
|
*
|
||||||
|
* This includes Hash-Tags and Mentions.
|
||||||
|
*
|
||||||
|
* @return array The list of Tags.
|
||||||
|
*/
|
||||||
|
protected function get_tags() {
|
||||||
|
// TODO Delete Or Modify
|
||||||
|
$tags = array();
|
||||||
|
|
||||||
|
$comment_tags = self::get_hashtags();
|
||||||
|
if ( $comment_tags ) {
|
||||||
|
foreach ( $comment_tags as $comment_tag ) {
|
||||||
|
$tag_link = \get_tag_link( $comment_tag );
|
||||||
|
if ( ! $tag_link ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$tag = array(
|
||||||
|
'type' => 'Hashtag',
|
||||||
|
'href' => \esc_url( $tag_link ),
|
||||||
|
'name' => esc_hashtag( $comment_tag ),
|
||||||
|
);
|
||||||
|
$tags[] = $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$mentions = $this->get_mentions();
|
||||||
|
if ( $mentions ) {
|
||||||
|
foreach ( $mentions as $mention => $url ) {
|
||||||
|
$tag = array(
|
||||||
|
'type' => 'Mention',
|
||||||
|
'href' => \esc_url( $url ),
|
||||||
|
'name' => \esc_html( $mention ),
|
||||||
|
);
|
||||||
|
$tags[] = $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content for the ActivityPub Item.
|
||||||
|
*
|
||||||
|
* The content will be generated based on the user settings.
|
||||||
|
*
|
||||||
|
* @return string The content.
|
||||||
|
*/
|
||||||
|
protected function get_content() {
|
||||||
|
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||||
|
$wp_comment = $this->wp_comment;
|
||||||
|
$content = $wp_comment->comment_content;
|
||||||
|
|
||||||
|
$content = \wpautop( $content );
|
||||||
|
$content = \preg_replace( '/[\n\r\t]/', '', $content );
|
||||||
|
$content = \trim( $content );
|
||||||
|
|
||||||
|
$content = \apply_filters( 'the_content', $content, $wp_comment );
|
||||||
|
$content = \html_entity_decode( $content, \ENT_QUOTES, 'UTF-8' );
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to get the @-Mentions from the comment content.
|
||||||
|
*
|
||||||
|
* @return array The list of @-Mentions.
|
||||||
|
*/
|
||||||
|
protected function get_mentions() {
|
||||||
|
return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_comment->comment_content, $this->wp_comment );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to get the #HashTags from the comment content.
|
||||||
|
*
|
||||||
|
* @return array The list of @-Mentions.
|
||||||
|
*/
|
||||||
|
protected function get_hashtags() {
|
||||||
|
$wp_comment = $this->wp_comment;
|
||||||
|
$content = $this->get_content();
|
||||||
|
|
||||||
|
$tags = [];
|
||||||
|
//TODO fix hashtag
|
||||||
|
if ( \preg_match_all( '/' . ACTIVITYPUB_HASHTAGS_REGEXP . '/i', $content, $match ) ) {
|
||||||
|
$tags = \implode( ', ', $match[1] );
|
||||||
|
}
|
||||||
|
\error_log( "get_hashtags: tags: " . \print_r( $tags, true ) );
|
||||||
|
$hashtags = [];
|
||||||
|
preg_match_all("/(#\w+)/u", $content, $matches);
|
||||||
|
if ($matches) {
|
||||||
|
$hashtagsArray = array_count_values($matches[0]);
|
||||||
|
$hashtags = array_keys($hashtagsArray);
|
||||||
|
}
|
||||||
|
\error_log( "get_hashtags: hashtags: " . \print_r( $hashtags, true ) );
|
||||||
|
return $hashtags;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to get the InReplyTo parent Comment URI.
|
||||||
|
*
|
||||||
|
* @return array The in_reply_to URI.
|
||||||
|
*/
|
||||||
|
protected function get_in_reply_to() {
|
||||||
|
$wp_comment = $this->wp_comment;
|
||||||
|
$in_reply_to = get_in_reply_to( $wp_comment );
|
||||||
|
error_log( 'get_in_reply_to: ' . print_r( $in_reply_to, true ) );
|
||||||
|
return $in_reply_to;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue