PluginProbe
ActivityPub / 4.0.2
ActivityPub v4.0.2
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
activitypub / includes / transformer / class-comment.php

class-comment.php in ActivityPub 4.0.2, at includes/transformer/class-comment.php

312 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WordPress Comment Transformer file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Transformer;
9
10 use Activitypub\Webfinger;
11 use Activitypub\Comment as Comment_Utils;
12 use Activitypub\Model\Blog;
13 use Activitypub\Collection\Users;
14
15 use function Activitypub\is_single_user;
16 use function Activitypub\get_rest_url_by_path;
17 use function Activitypub\get_comment_ancestors;
18
19 /**
20 * WordPress Comment Transformer.
21 *
22 * The Comment Transformer is responsible for transforming a WP_Comment object into different
23 * Object-Types.
24 *
25 * Currently supported are:
26 *
27 * - Activitypub\Activity\Base_Object
28 */
29 class Comment extends Base {
30 /**
31 * Returns the User-ID of the WordPress Comment.
32 *
33 * @return int The User-ID of the WordPress Comment
34 */
35 public function get_wp_user_id() {
36 return $this->wp_object->user_id;
37 }
38
39 /**
40 * Change the User-ID of the WordPress Comment.
41 *
42 * @param int $user_id The new user ID.
43 */
44 public function change_wp_user_id( $user_id ) {
45 $this->wp_object->user_id = $user_id;
46 }
47
48 /**
49 * Transforms the WP_Comment object to an ActivityPub Object.
50 *
51 * @see \Activitypub\Activity\Base_Object
52 *
53 * @return \Activitypub\Activity\Base_Object The ActivityPub Object.
54 */
55 public function to_object() {
56 $comment = $this->wp_object;
57 $object = parent::to_object();
58
59 $object->set_url( $this->get_id() );
60 $object->set_type( 'Note' );
61
62 $published = \strtotime( $comment->comment_date_gmt );
63 $object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) );
64
65 $updated = \get_comment_meta( $comment->comment_ID, 'activitypub_comment_modified', true );
66 if ( $updated > $published ) {
67 $object->set_updated( \gmdate( 'Y-m-d\TH:i:s\Z', $updated ) );
68 }
69
70 $object->set_content_map(
71 array(
72 $this->get_locale() => $this->get_content(),
73 )
74 );
75 $path = sprintf( 'actors/%d/followers', intval( $comment->comment_author ) );
76
77 $object->set_to(
78 array(
79 'https://www.w3.org/ns/activitystreams#Public',
80 get_rest_url_by_path( $path ),
81 )
82 );
83
84 return $object;
85 }
86
87 /**
88 * Returns the User-URL of the Author of the Post.
89 *
90 * If `single_user` mode is enabled, the URL of the Blog-User is returned.
91 *
92 * @return string The User-URL.
93 */
94 protected function get_attributed_to() {
95 if ( is_single_user() ) {
96 $user = new Blog();
97 return $user->get_id();
98 }
99
100 return Users::get_by_id( $this->wp_object->user_id )->get_id();
101 }
102
103 /**
104 * Returns the content for the ActivityPub Item.
105 *
106 * The content will be generated based on the user settings.
107 *
108 * @return string The content.
109 */
110 protected function get_content() {
111 $comment = $this->wp_object;
112 $content = $comment->comment_content;
113
114 /**
115 * Filter the content of the comment.
116 *
117 * @param string $content The content of the comment.
118 * @param \WP_Comment $comment The comment object.
119 * @param array $args The arguments.
120 *
121 * @return string The filtered content of the comment.
122 */
123 $content = \apply_filters( 'comment_text', $content, $comment, array() );
124 $content = \preg_replace( '/[\n\r\t]/', '', $content );
125 $content = \trim( $content );
126
127 /**
128 * Filter the content of the comment.
129 *
130 * @param string $content The content of the comment.
131 * @param \WP_Comment $comment The comment object.
132 *
133 * @return string The filtered content of the comment.
134 */
135 return \apply_filters( 'activitypub_the_content', $content, $comment );
136 }
137
138 /**
139 * Returns the in-reply-to for the ActivityPub Item.
140 *
141 * @return false|string|null The URL of the in-reply-to.
142 */
143 protected function get_in_reply_to() {
144 $comment = $this->wp_object;
145 $parent_comment = null;
146
147 if ( $comment->comment_parent ) {
148 $parent_comment = \get_comment( $comment->comment_parent );
149 }
150
151 if ( $parent_comment ) {
152 $in_reply_to = Comment_Utils::get_source_id( $parent_comment->comment_ID );
153 if ( ! $in_reply_to && ! empty( $parent_comment->user_id ) ) {
154 $in_reply_to = Comment_Utils::generate_id( $parent_comment );
155 }
156 } else {
157 $in_reply_to = \get_permalink( $comment->comment_post_ID );
158 }
159
160 return $in_reply_to;
161 }
162
163 /**
164 * Returns the ID of the ActivityPub Object.
165 *
166 * @see https://www.w3.org/TR/activitypub/#obj-id
167 * @see https://github.com/tootsuite/mastodon/issues/13879
168 *
169 * @return string ActivityPub URI for comment
170 */
171 protected function get_id() {
172 $comment = $this->wp_object;
173 return Comment_Utils::generate_id( $comment );
174 }
175
176 /**
177 * Returns a list of Mentions, used in the Comment.
178 *
179 * @see https://docs.joinmastodon.org/spec/activitypub/#Mention
180 *
181 * @return array The list of Mentions.
182 */
183 protected function get_cc() {
184 $cc = array();
185
186 $mentions = $this->get_mentions();
187 if ( $mentions ) {
188 foreach ( $mentions as $url ) {
189 $cc[] = $url;
190 }
191 }
192
193 return array_unique( $cc );
194 }
195
196 /**
197 * Returns a list of Tags, used in the Comment.
198 *
199 * This includes Hash-Tags and Mentions.
200 *
201 * @return array The list of Tags.
202 */
203 protected function get_tag() {
204 $tags = array();
205
206 $mentions = $this->get_mentions();
207 if ( $mentions ) {
208 foreach ( $mentions as $mention => $url ) {
209 $tag = array(
210 'type' => 'Mention',
211 'href' => \esc_url( $url ),
212 'name' => \esc_html( $mention ),
213 );
214 $tags[] = $tag;
215 }
216 }
217
218 return \array_unique( $tags, SORT_REGULAR );
219 }
220
221 /**
222 * Helper function to get the @-Mentions from the comment content.
223 *
224 * @return array The list of @-Mentions.
225 */
226 protected function get_mentions() {
227 \add_filter( 'activitypub_extract_mentions', array( $this, 'extract_reply_context' ) );
228
229 /**
230 * Filter the mentions in the comment.
231 *
232 * @param array $mentions The list of mentions.
233 * @param string $content The content of the comment.
234 * @param \WP_Comment $comment The comment object.
235 *
236 * @return array The filtered list of mentions.
237 */
238 return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_object->comment_content, $this->wp_object );
239 }
240
241 /**
242 * Gets the ancestors of the comment, but only the ones that are ActivityPub comments.
243 *
244 * @return array The list of ancestors.
245 */
246 protected function get_comment_ancestors() {
247 $ancestors = get_comment_ancestors( $this->wp_object );
248
249 // Now that we have the full tree of ancestors, only return the ones received from the fediverse.
250 return array_filter(
251 $ancestors,
252 function ( $comment_id ) {
253 return \get_comment_meta( $comment_id, 'protocol', true ) === 'activitypub';
254 }
255 );
256 }
257
258 /**
259 * Collect all other Users that participated in this comment-thread
260 * to send them a notification about the new reply.
261 *
262 * @param array $mentions The already mentioned ActivityPub users.
263 *
264 * @return array The list of all Repliers.
265 */
266 public function extract_reply_context( $mentions ) {
267 // Check if `$this->wp_object` is a WP_Comment.
268 if ( 'WP_Comment' !== get_class( $this->wp_object ) ) {
269 return $mentions;
270 }
271
272 $ancestors = $this->get_comment_ancestors();
273 if ( ! $ancestors ) {
274 return $mentions;
275 }
276
277 foreach ( $ancestors as $comment_id ) {
278 $comment = \get_comment( $comment_id );
279 if ( $comment && ! empty( $comment->comment_author_url ) ) {
280 $acct = Webfinger::uri_to_acct( $comment->comment_author_url );
281 if ( $acct && ! is_wp_error( $acct ) ) {
282 $acct = str_replace( 'acct:', '@', $acct );
283 $mentions[ $acct ] = $comment->comment_author_url;
284 }
285 }
286 }
287
288 return $mentions;
289 }
290
291 /**
292 * Returns the locale of the post.
293 *
294 * @return string The locale of the post.
295 */
296 public function get_locale() {
297 $comment_id = $this->wp_object->ID;
298 $lang = \strtolower( \strtok( \get_locale(), '_-' ) );
299
300 /**
301 * Filter the locale of the comment.
302 *
303 * @param string $lang The locale of the comment.
304 * @param int $comment_id The comment ID.
305 * @param \WP_Post $post The comment object.
306 *
307 * @return string The filtered locale of the comment.
308 */
309 return apply_filters( 'activitypub_comment_locale', $lang, $comment_id, $this->wp_object );
310 }
311 }
312