PluginProbe
ActivityPub / 3.2.5
ActivityPub v3.2.5
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/transformer/class-comment.php +116 -243 9.2.03.2.5 View file →
@@ -1,27 +1,22 @@
1 1 <?php
2 -/**
3 - * WordPress Comment Transformer file.
4 - *
5 - * @package Activitypub
6 - */
2 +namespace Activitypub\Transformer;
7 3
8 -namespace Activitypub\Transformer;
4 +use WP_Comment;
5 +use WP_Comment_Query;
9 6
10 -use Activitypub\Collection\Actors;
11 -use Activitypub\Collection\Replies;
7 +use Activitypub\Webfinger;
12 8 use Activitypub\Comment as Comment_Utils;
13 9 use Activitypub\Model\Blog;
14 -use Activitypub\Sanitize;
15 -use Activitypub\Webfinger;
10 +use Activitypub\Collection\Users;
11 +use Activitypub\Transformer\Base;
16 12
13 +use function Activitypub\is_single_user;
14 +use function Activitypub\get_rest_url_by_path;
17 15 use function Activitypub\get_comment_ancestors;
18 -use function Activitypub\get_rest_url_by_path;
19 -use function Activitypub\is_single_user;
20 -use function Activitypub\was_comment_received;
21 16
22 17 /**
23 - * WordPress Comment Transformer.
18 + * WordPress Comment Transformer
24 19 *
25 20 * The Comment Transformer is responsible for transforming a WP_Comment object into different
26 21 * Object-Types.
27 22 *
@@ -30,21 +25,34 @@
30 25 * - Activitypub\Activity\Base_Object
31 26 */
32 27 class Comment extends Base {
33 28 /**
34 - * The User as Actor Object.
29 + * Returns the User-ID of the WordPress Comment.
35 30 *
36 - * @var \Activitypub\Activity\Actor
31 + * @return int The User-ID of the WordPress Comment
37 32 */
38 - private $actor_object = null;
33 + public function get_wp_user_id() {
34 + return $this->wp_object->user_id;
35 + }
39 36
40 37 /**
41 - * Transforms the WP_Comment object to an ActivityPub Object.
38 + * Change the User-ID of the WordPress Comment.
42 39 *
43 - * @return \Activitypub\Activity\Base_Object The ActivityPub Object.
40 + * @return int The User-ID of the WordPress Comment
44 41 */
42 + public function change_wp_user_id( $user_id ) {
43 + $this->wp_object->user_id = $user_id;
44 + }
45 +
46 + /**
47 + * Transforms the WP_Comment object to an ActivityPub Object
48 + *
49 + * @see \Activitypub\Activity\Base_Object
50 + *
51 + * @return \Activitypub\Activity\Base_Object The ActivityPub Object
52 + */
45 53 public function to_object() {
46 - $comment = $this->item;
54 + $comment = $this->wp_object;
47 55 $object = parent::to_object();
48 56
49 57 $object->set_url( $this->get_id() );
50 58 $object->set_type( 'Note' );
@@ -49,13 +57,13 @@
49 57 $object->set_url( $this->get_id() );
50 58 $object->set_type( 'Note' );
51 59
52 60 $published = \strtotime( $comment->comment_date_gmt );
53 - $object->set_published( \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, $published ) );
61 + $object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) );
54 62
55 63 $updated = \get_comment_meta( $comment->comment_ID, 'activitypub_comment_modified', true );
56 64 if ( $updated > $published ) {
57 - $object->set_updated( \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, $updated ) );
65 + $object->set_updated( \gmdate( 'Y-m-d\TH:i:s\Z', $updated ) );
58 66 }
59 67
60 68 $object->set_content_map(
61 69 array(
@@ -61,41 +69,21 @@
61 69 array(
62 70 $this->get_locale() => $this->get_content(),
63 71 )
64 72 );
73 + $path = sprintf( 'actors/%d/followers', intval( $comment->comment_author ) );
65 74
75 + $object->set_to(
76 + array(
77 + 'https://www.w3.org/ns/activitystreams#Public',
78 + get_rest_url_by_path( $path ),
79 + )
80 + );
81 +
66 82 return $object;
67 83 }
68 84
69 85 /**
70 - * Get the content visibility.
71 - *
72 - * @return string The content visibility.
73 - */
74 - public function get_content_visibility() {
75 - if ( $this->content_visibility ) {
76 - return $this->content_visibility;
77 - }
78 -
79 - $comment = $this->item;
80 - $post = \get_post( $comment->comment_post_ID );
81 -
82 - if ( ! $post ) {
83 - return ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC;
84 - }
85 -
86 - $content_visibility = \get_post_meta( $post->ID, 'activitypub_content_visibility', true );
87 -
88 - if ( ! $content_visibility ) {
89 - return ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC;
90 - }
91 -
92 - $this->content_visibility = $content_visibility;
93 -
94 - return $this->content_visibility;
95 - }
96 -
97 - /**
98 86 * Returns the User-URL of the Author of the Post.
99 87 *
100 88 * If `single_user` mode is enabled, the URL of the Blog-User is returned.
101 89 *
@@ -101,14 +89,14 @@
101 89 *
102 90 * @return string The User-URL.
103 91 */
104 92 protected function get_attributed_to() {
105 - // If the comment was received via ActivityPub, return the author URL.
106 - if ( was_comment_received( $this->item ) ) {
107 - return $this->item->comment_author_url;
93 + if ( is_single_user() ) {
94 + $user = new Blog();
95 + return $user->get_url();
108 96 }
109 97
110 - return $this->get_actor_object()->get_id();
98 + return Users::get_by_id( $this->wp_object->user_id )->get_url();
111 99 }
112 100
113 101 /**
114 102 * Returns the content for the ActivityPub Item.
@@ -117,54 +105,30 @@
117 105 *
118 106 * @return string The content.
119 107 */
120 108 protected function get_content() {
121 - $comment = $this->item;
122 - $content = $comment->comment_content;
123 - $mentions = '';
109 + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
110 + $comment = $this->wp_object;
111 + $content = $comment->comment_content;
124 112
125 - foreach ( $this->extract_reply_context() as $acct => $url ) {
126 - $mentions .= \sprintf(
127 - '<a rel="mention" class="u-url mention" href="%1$s" title="%2$s">%3$s</a> ',
128 - \esc_url( $url ),
129 - \esc_attr( $acct ),
130 - \esc_html( '@' . \strtok( $acct, '@' ) )
131 - );
132 - }
133 - $content = $mentions . $content;
134 -
135 - /**
136 - * Filter the content of the comment.
137 - *
138 - * @param string $content The content of the comment.
139 - * @param \WP_Comment $comment The comment object.
140 - * @param array $args The arguments.
141 - *
142 - * @return string The filtered content of the comment.
143 - */
144 113 $content = \apply_filters( 'comment_text', $content, $comment, array() );
145 - $content = Sanitize::clean_html( $content );
146 - $content = Sanitize::strip_whitespace( $content );
114 + $content = \preg_replace( '/[\n\r\t]/', '', $content );
115 + $content = \trim( $content );
116 + $content = \apply_filters( 'activitypub_the_content', $content, $comment );
147 117
148 - /**
149 - * Filter the content of the comment.
150 - *
151 - * @param string $content The content of the comment.
152 - * @param \WP_Comment $comment The comment object.
153 - *
154 - * @return string The filtered content of the comment.
155 - */
156 - return \apply_filters( 'activitypub_the_content', $content, $comment );
118 + return $content;
157 119 }
158 120
159 121 /**
160 122 * Returns the in-reply-to for the ActivityPub Item.
161 123 *
162 - * @return false|string|null The URL of the in-reply-to.
124 + * @return int The URL of the in-reply-to.
163 125 */
164 126 protected function get_in_reply_to() {
165 - $comment = $this->item;
127 + $comment = $this->wp_object;
128 +
166 129 $parent_comment = null;
130 + $in_reply_to = null;
167 131
168 132 if ( $comment->comment_parent ) {
169 133 $parent_comment = \get_comment( $comment->comment_parent );
170 134 }
@@ -169,10 +133,15 @@
169 133 $parent_comment = \get_comment( $comment->comment_parent );
170 134 }
171 135
172 136 if ( $parent_comment ) {
173 - $in_reply_to = Comment_Utils::get_source_id( $parent_comment->comment_ID );
174 - if ( ! $in_reply_to && ! empty( $parent_comment->user_id ) ) {
137 + $comment_meta = \get_comment_meta( $parent_comment->comment_ID );
138 +
139 + if ( ! empty( $comment_meta['source_id'][0] ) ) {
140 + $in_reply_to = $comment_meta['source_id'][0];
141 + } elseif ( ! empty( $comment_meta['source_url'][0] ) ) {
142 + $in_reply_to = $comment_meta['source_url'][0];
143 + } elseif ( ! empty( $parent_comment->user_id ) ) {
175 144 $in_reply_to = Comment_Utils::generate_id( $parent_comment );
176 145 }
177 146 } else {
178 147 $in_reply_to = \get_permalink( $comment->comment_post_ID );
@@ -189,39 +158,55 @@
189 158 *
190 159 * @return string ActivityPub URI for comment
191 160 */
192 161 protected function get_id() {
193 - $comment = $this->item;
162 + $comment = $this->wp_object;
194 163 return Comment_Utils::generate_id( $comment );
195 164 }
196 165
197 166 /**
198 - * Returns the User-Object of the Author of the Post.
167 + * Returns a list of Mentions, used in the Comment.
199 168 *
200 - * If `single_user` mode is enabled, the Blog-User is returned.
169 + * @see https://docs.joinmastodon.org/spec/activitypub/#Mention
201 170 *
202 - * @return \Activitypub\Activity\Actor The User-Object.
171 + * @return array The list of Mentions.
203 172 */
204 - protected function get_actor_object() {
205 - if ( $this->actor_object ) {
206 - return $this->actor_object;
173 + protected function get_cc() {
174 + $cc = array();
175 +
176 + $mentions = $this->get_mentions();
177 + if ( $mentions ) {
178 + foreach ( $mentions as $url ) {
179 + $cc[] = $url;
180 + }
207 181 }
208 182
209 - $blog_user = new Blog();
210 - $this->actor_object = $blog_user;
183 + return array_unique( $cc );
184 + }
211 185
212 - if ( is_single_user() ) {
213 - return $blog_user;
214 - }
186 + /**
187 + * Returns a list of Tags, used in the Comment.
188 + *
189 + * This includes Hash-Tags and Mentions.
190 + *
191 + * @return array The list of Tags.
192 + */
193 + protected function get_tag() {
194 + $tags = array();
215 195
216 - $user = Actors::get_by_id( $this->item->user_id );
217 -
218 - if ( $user && ! \is_wp_error( $user ) ) {
219 - $this->actor_object = $user;
220 - return $user;
196 + $mentions = $this->get_mentions();
197 + if ( $mentions ) {
198 + foreach ( $mentions as $mention => $url ) {
199 + $tag = array(
200 + 'type' => 'Mention',
201 + 'href' => \esc_url( $url ),
202 + 'name' => \esc_html( $mention ),
203 + );
204 + $tags[] = $tag;
205 + }
221 206 }
222 207
223 - return $blog_user;
208 + return \array_unique( $tags, SORT_REGULAR );
224 209 }
225 210
226 211 /**
227 212 * Helper function to get the @-Mentions from the comment content.
@@ -230,18 +215,9 @@
230 215 */
231 216 protected function get_mentions() {
232 217 \add_filter( 'activitypub_extract_mentions', array( $this, 'extract_reply_context' ) );
233 218
234 - /**
235 - * Filter the mentions in the comment.
236 - *
237 - * @param array $mentions The list of mentions.
238 - * @param string $content The content of the comment.
239 - * @param \WP_Comment $comment The comment object.
240 - *
241 - * @return array The filtered list of mentions.
242 - */
243 - return \apply_filters( 'activitypub_extract_mentions', array(), $this->item->comment_content, $this->item );
219 + return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_object->comment_content, $this->wp_object );
244 220 }
245 221
246 222 /**
247 223 * Gets the ancestors of the comment, but only the ones that are ActivityPub comments.
@@ -248,14 +224,14 @@
248 224 *
249 225 * @return array The list of ancestors.
250 226 */
251 227 protected function get_comment_ancestors() {
252 - $ancestors = get_comment_ancestors( $this->item );
228 + $ancestors = get_comment_ancestors( $this->wp_object );
253 229
254 - // Now that we have the full tree of ancestors, only return the ones received from the fediverse.
255 - return \array_filter(
230 + // Now that we have the full tree of ancestors, only return the ones received from the fediverse
231 + return array_filter(
256 232 $ancestors,
257 - static function ( $comment_id ) {
233 + function ( $comment_id ) {
258 234 return \get_comment_meta( $comment_id, 'protocol', true ) === 'activitypub';
259 235 }
260 236 );
261 237 }
@@ -263,15 +239,15 @@
263 239 /**
264 240 * Collect all other Users that participated in this comment-thread
265 241 * to send them a notification about the new reply.
266 242 *
267 - * @param array $mentions Optional. The already mentioned ActivityPub users. Default empty array.
243 + * @param array $mentions The already mentioned ActivityPub users
268 244 *
269 245 * @return array The list of all Repliers.
270 246 */
271 - public function extract_reply_context( $mentions = array() ) {
272 - // Check if `$this->item` is a WP_Comment.
273 - if ( 'WP_Comment' !== \get_class( $this->item ) ) {
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 ) ) {
274 250 return $mentions;
275 251 }
276 252
277 253 $ancestors = $this->get_comment_ancestors();
@@ -282,10 +258,10 @@
282 258 foreach ( $ancestors as $comment_id ) {
283 259 $comment = \get_comment( $comment_id );
284 260 if ( $comment && ! empty( $comment->comment_author_url ) ) {
285 261 $acct = Webfinger::uri_to_acct( $comment->comment_author_url );
286 - if ( $acct && ! \is_wp_error( $acct ) ) {
287 - $acct = \str_replace( 'acct:', '@', $acct );
262 + if ( $acct && ! is_wp_error( $acct ) ) {
263 + $acct = str_replace( 'acct:', '@', $acct );
288 264 $mentions[ $acct ] = $comment->comment_author_url;
289 265 }
290 266 }
291 267 }
@@ -293,127 +269,24 @@
293 269 return $mentions;
294 270 }
295 271
296 272 /**
297 - * Returns the updated date of the comment.
273 + * Returns the locale of the post.
298 274 *
299 - * @return string|null The updated date of the comment.
275 + * @return string The locale of the post.
300 276 */
301 - public function get_updated() {
302 - $updated = \get_comment_meta( $this->item->comment_ID, 'activitypub_comment_modified', true );
303 - $published = \get_comment_meta( $this->item->comment_ID, 'activitypub_comment_published', true );
277 + public function get_locale() {
278 + $comment_id = $this->wp_object->ID;
279 + $lang = \strtolower( \strtok( \get_locale(), '_-' ) );
304 280
305 - if ( $updated > $published ) {
306 - return \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, $updated );
307 - }
308 -
309 - return null;
310 - }
311 -
312 - /**
313 - * Returns the published date of the comment.
314 - *
315 - * @return string The published date of the comment.
316 - */
317 - public function get_published() {
318 - return \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, \strtotime( $this->item->comment_date_gmt ) );
319 - }
320 -
321 - /**
322 - * Returns the URL of the comment.
323 - *
324 - * @return string The URL of the comment.
325 - */
326 - public function get_url() {
327 - return $this->get_id();
328 - }
329 -
330 - /**
331 - * Returns the type of the comment.
332 - *
333 - * @return string The type of the comment.
334 - */
335 - public function get_type() {
336 - return 'Note';
337 - }
338 -
339 - /**
340 - * Get the context of the post.
341 - *
342 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
343 - *
344 - * @return string The context of the post.
345 - */
346 - protected function get_context() {
347 - if ( $this->item->comment_post_ID ) {
348 - return get_rest_url_by_path( \sprintf( 'posts/%d/context', $this->item->comment_post_ID ) );
349 - }
350 -
351 - return null;
352 - }
353 -
354 - /**
355 - * Get the replies Collection.
356 - *
357 - * @return array|null The replies collection on success or null on failure.
358 - */
359 - public function get_replies() {
360 - return Replies::get_collection( $this->item );
361 - }
362 -
363 - /**
364 - * Get the attachment for the comment.
365 - *
366 - * Extracts images from comment content and returns them as ActivityPub attachments.
367 - *
368 - * @return array The attachments array for ActivityPub.
369 - */
370 - protected function get_attachment() {
371 - $max_media = \get_option( 'activitypub_max_image_attachments', \ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS );
372 -
373 281 /**
374 - * Filters the maximum number of media attachments allowed in a comment.
282 + * Filter the locale of the comment.
375 283 *
376 - * @param int $max_media Maximum number of media attachments.
377 - * @param \WP_Comment $item The comment object.
378 - */
379 - $max_media = (int) \apply_filters( 'activitypub_max_image_attachments', $max_media, $this->item );
380 -
381 - if ( 0 === $max_media ) {
382 - return array();
383 - }
384 -
385 - $media = array(
386 - 'image' => array(),
387 - 'audio' => array(),
388 - 'video' => array(),
389 - );
390 -
391 - // Get comment content and parse for image embeds.
392 - $media = $this->parse_html_images( $media, $max_media, $this->item->comment_content );
393 - $media = $this->filter_unique_attachments( $media['image'] );
394 - $media = \array_slice( $media, 0, $max_media );
395 -
396 - /**
397 - * Filter the attachment IDs for a comment.
284 + * @param string $lang The locale of the comment.
285 + * @param int $comment_id The comment ID.
286 + * @param WP_Post $post The comment object.
398 287 *
399 - * @param array $media The media array.
400 - * @param \WP_Comment $item The comment object.
401 - *
402 - * @return array The filtered attachment IDs.
288 + * @return string The filtered locale of the comment.
403 289 */
404 - $media = \apply_filters( 'activitypub_comment_attachment_ids', $media, $this->item );
405 -
406 - // Transform to ActivityStreams format using Base class method.
407 - $attachments = \array_filter( \array_map( array( $this, 'transform_attachment' ), $media ) );
408 -
409 - /**
410 - * Filter the attachments for a comment.
411 - *
412 - * @param array $attachments The attachments.
413 - * @param \WP_Comment $item The comment object.
414 - *
415 - * @return array The filtered attachments.
416 - */
417 - return \apply_filters( 'activitypub_comment_attachments', $attachments, $this->item );
290 + return apply_filters( 'activitypub_comment_locale', $lang, $comment_id, $this->wp_object );
418 291 }
419 292 }