| @@ -3,14 +3,17 @@ | ||
| 3 | 3 | |
| 4 | 4 | use WP_Comment; |
| 5 | 5 | use WP_Comment_Query; |
| 6 | 6 | |
| 7 | -use Activitypub\Model\Blog_User; | |
| 7 | +use Activitypub\Webfinger; | |
| 8 | +use Activitypub\Comment as Comment_Utils; | |
| 9 | +use Activitypub\Model\Blog; | |
| 8 | 10 | use Activitypub\Collection\Users; |
| 9 | 11 | use Activitypub\Transformer\Base; |
| 10 | 12 | |
| 11 | 13 | use function Activitypub\is_single_user; |
| 12 | 14 | use function Activitypub\get_rest_url_by_path; |
| 15 | +use function Activitypub\get_comment_ancestors; | |
| 13 | 16 | |
| 14 | 17 | /** |
| 15 | 18 | * WordPress Comment Transformer |
| 16 | 19 | * |
| @@ -50,9 +53,9 @@ | ||
| 50 | 53 | public function to_object() { |
| 51 | 54 | $comment = $this->wp_object; |
| 52 | 55 | $object = parent::to_object(); |
| 53 | 56 | |
| 54 | - $object->set_url( \get_comment_link( $comment->comment_ID ) ); | |
| 57 | + $object->set_url( $this->get_id() ); | |
| 55 | 58 | $object->set_type( 'Note' ); |
| 56 | 59 | |
| 57 | 60 | $published = \strtotime( $comment->comment_date_gmt ); |
| 58 | 61 | $object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) ); |
| @@ -66,9 +69,9 @@ | ||
| 66 | 69 | array( |
| 67 | 70 | $this->get_locale() => $this->get_content(), |
| 68 | 71 | ) |
| 69 | 72 | ); |
| 70 | - $path = sprintf( 'users/%d/followers', intval( $comment->comment_author ) ); | |
| 73 | + $path = sprintf( 'actors/%d/followers', intval( $comment->comment_author ) ); | |
| 71 | 74 | |
| 72 | 75 | $object->set_to( |
| 73 | 76 | array( |
| 74 | 77 | 'https://www.w3.org/ns/activitystreams#Public', |
| @@ -87,9 +90,9 @@ | ||
| 87 | 90 | * @return string The User-URL. |
| 88 | 91 | */ |
| 89 | 92 | protected function get_attributed_to() { |
| 90 | 93 | if ( is_single_user() ) { |
| 91 | - $user = new Blog_User(); | |
| 94 | + $user = new Blog(); | |
| 92 | 95 | return $user->get_url(); |
| 93 | 96 | } |
| 94 | 97 | |
| 95 | 98 | return Users::get_by_id( $this->wp_object->user_id )->get_url(); |
| @@ -106,12 +109,12 @@ | ||
| 106 | 109 | // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited |
| 107 | 110 | $comment = $this->wp_object; |
| 108 | 111 | $content = $comment->comment_content; |
| 109 | 112 | |
| 110 | - $content = \wpautop( $content ); | |
| 113 | + $content = \apply_filters( 'comment_text', $content, $comment, array() ); | |
| 111 | 114 | $content = \preg_replace( '/[\n\r\t]/', '', $content ); |
| 112 | 115 | $content = \trim( $content ); |
| 113 | - $content = \apply_filters( 'the_content', $content, $comment ); | |
| 116 | + $content = \apply_filters( 'activitypub_the_content', $content, $comment ); | |
| 114 | 117 | |
| 115 | 118 | return $content; |
| 116 | 119 | } |
| 117 | 120 | |
| @@ -122,10 +125,15 @@ | ||
| 122 | 125 | */ |
| 123 | 126 | protected function get_in_reply_to() { |
| 124 | 127 | $comment = $this->wp_object; |
| 125 | 128 | |
| 126 | - $parent_comment = \get_comment( $comment->comment_parent ); | |
| 129 | + $parent_comment = null; | |
| 130 | + $in_reply_to = null; | |
| 127 | 131 | |
| 132 | + if ( $comment->comment_parent ) { | |
| 133 | + $parent_comment = \get_comment( $comment->comment_parent ); | |
| 134 | + } | |
| 135 | + | |
| 128 | 136 | if ( $parent_comment ) { |
| 129 | 137 | $comment_meta = \get_comment_meta( $parent_comment->comment_ID ); |
| 130 | 138 | |
| 131 | 139 | if ( ! empty( $comment_meta['source_id'][0] ) ) { |
| @@ -131,10 +139,10 @@ | ||
| 131 | 139 | if ( ! empty( $comment_meta['source_id'][0] ) ) { |
| 132 | 140 | $in_reply_to = $comment_meta['source_id'][0]; |
| 133 | 141 | } elseif ( ! empty( $comment_meta['source_url'][0] ) ) { |
| 134 | 142 | $in_reply_to = $comment_meta['source_url'][0]; |
| 135 | - } else { | |
| 136 | - $in_reply_to = $this->generate_id( $parent_comment ); | |
| 143 | + } elseif ( ! empty( $parent_comment->user_id ) ) { | |
| 144 | + $in_reply_to = Comment_Utils::generate_id( $parent_comment ); | |
| 137 | 145 | } |
| 138 | 146 | } else { |
| 139 | 147 | $in_reply_to = \get_permalink( $comment->comment_post_ID ); |
| 140 | 148 | } |
| @@ -151,30 +159,12 @@ | ||
| 151 | 159 | * @return string ActivityPub URI for comment |
| 152 | 160 | */ |
| 153 | 161 | protected function get_id() { |
| 154 | 162 | $comment = $this->wp_object; |
| 155 | - return $this->generate_id( $comment ); | |
| 163 | + return Comment_Utils::generate_id( $comment ); | |
| 156 | 164 | } |
| 157 | 165 | |
| 158 | 166 | /** |
| 159 | - * Generates an ActivityPub URI for a comment | |
| 160 | - * | |
| 161 | - * @param WP_Comment|int $comment A comment object or comment ID | |
| 162 | - * | |
| 163 | - * @return string ActivityPub URI for comment | |
| 164 | - */ | |
| 165 | - protected function generate_id( $comment ) { | |
| 166 | - $comment = get_comment( $comment ); | |
| 167 | - | |
| 168 | - return \add_query_arg( | |
| 169 | - array( | |
| 170 | - 'c' => $comment->comment_ID, | |
| 171 | - ), | |
| 172 | - \trailingslashit( site_url() ) | |
| 173 | - ); | |
| 174 | - } | |
| 175 | - | |
| 176 | - /** | |
| 177 | 167 | * Returns a list of Mentions, used in the Comment. |
| 178 | 168 | * |
| 179 | 169 | * @see https://docs.joinmastodon.org/spec/activitypub/#Mention |
| 180 | 170 | * |
| @@ -184,38 +174,14 @@ | ||
| 184 | 174 | $cc = array(); |
| 185 | 175 | |
| 186 | 176 | $mentions = $this->get_mentions(); |
| 187 | 177 | if ( $mentions ) { |
| 188 | - foreach ( $mentions as $mention => $url ) { | |
| 178 | + foreach ( $mentions as $url ) { | |
| 189 | 179 | $cc[] = $url; |
| 190 | 180 | } |
| 191 | 181 | } |
| 192 | 182 | |
| 193 | - $comment_query = new WP_Comment_Query( | |
| 194 | - array( | |
| 195 | - 'post_id' => $this->wp_object->comment_post_ID, | |
| 196 | - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query | |
| 197 | - 'meta_query' => array( | |
| 198 | - array( | |
| 199 | - 'key' => 'source_id', | |
| 200 | - 'compare' => 'EXISTS', | |
| 201 | - ), | |
| 202 | - ), | |
| 203 | - ) | |
| 204 | - ); | |
| 205 | - | |
| 206 | - if ( $comment_query->comments ) { | |
| 207 | - foreach ( $comment_query->comments as $comment ) { | |
| 208 | - if ( empty( $comment->comment_author_url ) ) { | |
| 209 | - continue; | |
| 210 | - } | |
| 211 | - $cc[] = \esc_url( $comment->comment_author_url ); | |
| 212 | - } | |
| 213 | - } | |
| 214 | - | |
| 215 | - $cc = \array_unique( $cc ); | |
| 216 | - | |
| 217 | - return $cc; | |
| 183 | + return array_unique( $cc ); | |
| 218 | 184 | } |
| 219 | 185 | |
| 220 | 186 | /** |
| 221 | 187 | * Returns a list of Tags, used in the Comment. |
| @@ -247,9 +213,61 @@ | ||
| 247 | 213 | * |
| 248 | 214 | * @return array The list of @-Mentions. |
| 249 | 215 | */ |
| 250 | 216 | protected function get_mentions() { |
| 217 | + \add_filter( 'activitypub_extract_mentions', array( $this, 'extract_reply_context' ) ); | |
| 218 | + | |
| 251 | 219 | return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_object->comment_content, $this->wp_object ); |
| 220 | + } | |
| 221 | + | |
| 222 | + /** | |
| 223 | + * Gets the ancestors of the comment, but only the ones that are ActivityPub comments. | |
| 224 | + * | |
| 225 | + * @return array The list of ancestors. | |
| 226 | + */ | |
| 227 | + protected function get_comment_ancestors() { | |
| 228 | + $ancestors = get_comment_ancestors( $this->wp_object ); | |
| 229 | + | |
| 230 | + // Now that we have the full tree of ancestors, only return the ones received from the fediverse | |
| 231 | + return array_filter( | |
| 232 | + $ancestors, | |
| 233 | + function ( $comment_id ) { | |
| 234 | + return \get_comment_meta( $comment_id, 'protocol', true ) === 'activitypub'; | |
| 235 | + } | |
| 236 | + ); | |
| 237 | + } | |
| 238 | + | |
| 239 | + /** | |
| 240 | + * Collect all other Users that participated in this comment-thread | |
| 241 | + * to send them a notification about the new reply. | |
| 242 | + * | |
| 243 | + * @param array $mentions The already mentioned ActivityPub users | |
| 244 | + * | |
| 245 | + * @return array The list of all Repliers. | |
| 246 | + */ | |
| 247 | + public function extract_reply_context( $mentions ) { | |
| 248 | + // Check if `$this->wp_object` is a WP_Comment | |
| 249 | + if ( 'WP_Comment' !== get_class( $this->wp_object ) ) { | |
| 250 | + return $mentions; | |
| 251 | + } | |
| 252 | + | |
| 253 | + $ancestors = $this->get_comment_ancestors(); | |
| 254 | + if ( ! $ancestors ) { | |
| 255 | + return $mentions; | |
| 256 | + } | |
| 257 | + | |
| 258 | + foreach ( $ancestors as $comment_id ) { | |
| 259 | + $comment = \get_comment( $comment_id ); | |
| 260 | + if ( $comment && ! empty( $comment->comment_author_url ) ) { | |
| 261 | + $acct = Webfinger::uri_to_acct( $comment->comment_author_url ); | |
| 262 | + if ( $acct && ! is_wp_error( $acct ) ) { | |
| 263 | + $acct = str_replace( 'acct:', '@', $acct ); | |
| 264 | + $mentions[ $acct ] = $comment->comment_author_url; | |
| 265 | + } | |
| 266 | + } | |
| 267 | + } | |
| 268 | + | |
| 269 | + return $mentions; | |
| 252 | 270 | } |
| 253 | 271 | |
| 254 | 272 | /** |
| 255 | 273 | * Returns the locale of the post. |