PluginProbe
Stream – Activity Log & Audit Trail / 3.2.0
Stream – Activity Log & Audit Trail v3.2.0
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / connectors / class-connector-comments.php

class-connector-comments.php in Stream – Activity Log & Audit Trail 3.2.0, at connectors/class-connector-comments.php

630 lines 17.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WP_Stream;
3
4 class Connector_Comments extends Connector {
5 /**
6 * Connector slug
7 *
8 * @var string
9 */
10 public $name = 'comments';
11
12 /**
13 * Actions registered for this connector
14 *
15 * @var array
16 */
17 public $actions = array(
18 'comment_flood_trigger',
19 'wp_insert_comment',
20 'edit_comment',
21 'before_delete_post',
22 'deleted_post',
23 'delete_comment',
24 'trash_comment',
25 'untrash_comment',
26 'spam_comment',
27 'unspam_comment',
28 'transition_comment_status',
29 'comment_duplicate_trigger',
30 );
31
32 /**
33 * Catch and store the post ID during post deletion
34 *
35 * @var int
36 */
37 protected $delete_post = 0;
38
39 /**
40 * Return translated connector label
41 *
42 * @return string Translated connector label
43 */
44 public function get_label() {
45 return esc_html__( 'Comments', 'stream' );
46 }
47
48 /**
49 * Return translated action labels
50 *
51 * @return array Action label translations
52 */
53 public function get_action_labels() {
54 return array(
55 'created' => esc_html__( 'Created', 'stream' ),
56 'edited' => esc_html__( 'Edited', 'stream' ),
57 'replied' => esc_html__( 'Replied', 'stream' ),
58 'approved' => esc_html__( 'Approved', 'stream' ),
59 'unapproved' => esc_html__( 'Unapproved', 'stream' ),
60 'trashed' => esc_html__( 'Trashed', 'stream' ),
61 'untrashed' => esc_html__( 'Restored', 'stream' ),
62 'spammed' => esc_html__( 'Marked as Spam', 'stream' ),
63 'unspammed' => esc_html__( 'Unmarked as Spam', 'stream' ),
64 'deleted' => esc_html__( 'Deleted', 'stream' ),
65 'duplicate' => esc_html__( 'Duplicate', 'stream' ),
66 'flood' => esc_html__( 'Throttled', 'stream' ),
67 );
68 }
69
70 /**
71 * Return translated context labels
72 *
73 * @return array Context label translations
74 */
75 public function get_context_labels() {
76 return array(
77 'comments' => esc_html__( 'Comments', 'stream' ),
78 );
79 }
80
81 /**
82 * Return translated comment type labels
83 *
84 * @return array Comment type label translations
85 */
86 public function get_comment_type_labels() {
87 return apply_filters(
88 'wp_stream_comments_comment_type_labels',
89 array(
90 'comment' => esc_html__( 'Comment', 'stream' ),
91 'trackback' => esc_html__( 'Trackback', 'stream' ),
92 'pingback' => esc_html__( 'Pingback', 'stream' ),
93 )
94 );
95 }
96
97 /**
98 * Return the comment type label for a given comment ID
99 *
100 * @param int $comment_id ID of the comment
101 *
102 * @return string The comment type label
103 */
104 public function get_comment_type_label( $comment_id ) {
105 $comment_type = get_comment_type( $comment_id );
106
107 if ( empty( $comment_type ) ) {
108 $comment_type = 'comment';
109 }
110
111 $comment_type_labels = $this->get_comment_type_labels();
112
113 $label = isset( $comment_type_labels[ $comment_type ] ) ? $comment_type_labels[ $comment_type ] : $comment_type;
114
115 return $label;
116 }
117
118 /**
119 * Add action links to Stream drop row in admin list screen
120 *
121 * @filter wp_stream_action_links_{connector}
122 *
123 * @param array $links Previous links registered
124 * @param object $record Stream record
125 *
126 * @return array Action links
127 */
128 public function action_links( $links, $record ) {
129 if ( $record->object_id ) {
130 if ( $comment = get_comment( $record->object_id ) ) {
131 $approve_nonce = wp_create_nonce( "approve-comment_$comment->comment_ID" );
132
133 $links[ esc_html__( 'Edit', 'stream' ) ] = admin_url( "comment.php?action=editcomment&c=$comment->comment_ID" );
134
135 if ( 1 === $comment->comment_approved ) {
136 $links[ esc_html__( 'Unapprove', 'stream' ) ] = admin_url(
137 sprintf(
138 'comment.php?action=unapprovecomment&c=%s&_wpnonce=%s',
139 $record->object_id,
140 $approve_nonce
141 )
142 );
143 } elseif ( empty( $comment->comment_approved ) ) {
144 $links[ esc_html__( 'Approve', 'stream' ) ] = admin_url(
145 sprintf(
146 'comment.php?action=approvecomment&c=%s&_wpnonce=%s',
147 $record->object_id,
148 $approve_nonce
149 )
150 );
151 }
152 }
153 }
154
155 return $links;
156 }
157
158 /**
159 * Fetches the comment author and returns the specified field.
160 *
161 * This also takes into consideration whether or not the blog requires only
162 * name and e-mail or that users be logged in to comment. In either case it
163 * will try to see if the e-mail provided does belong to a registered user.
164 *
165 * @param object|int $comment A comment object or comment ID
166 * @param string $field What field you want to return
167 *
168 * @return int|string $output User ID or user display name
169 */
170 public function get_comment_author( $comment, $field = 'id' ) {
171 $comment = is_object( $comment ) ? $comment : get_comment( absint( $comment ) );
172
173 $req_name_email = get_option( 'require_name_email' );
174 $req_user_login = get_option( 'comment_registration' );
175
176 $user_id = 0;
177 $user_name = esc_html__( 'Guest', 'stream' );
178
179 $output = '';
180
181 if ( $req_name_email && isset( $comment->comment_author_email ) && isset( $comment->comment_author ) ) {
182 $user = get_user_by( 'email', $comment->comment_author_email );
183 $user_id = isset( $user->ID ) ? $user->ID : 0;
184 $user_name = isset( $user->display_name ) ? $user->display_name : $comment->comment_author;
185 }
186
187 if ( $req_user_login ) {
188 $user = wp_get_current_user();
189 $user_id = $user->ID;
190 $user_name = $user->display_name;
191 }
192
193 if ( 'id' === $field ) {
194 $output = $user_id;
195 } elseif ( 'name' === $field ) {
196 $output = $user_name;
197 }
198
199 return $output;
200 }
201
202 /**
203 * Tracks comment flood blocks
204 *
205 * @action comment_flood_trigger
206 *
207 * @param string $time_lastcomment
208 * @param string $time_newcomment
209 */
210 public function callback_comment_flood_trigger( $time_lastcomment, $time_newcomment ) {
211 $options = wp_stream_get_instance()->settings->options;
212 $flood_tracking = isset( $options['advanced_comment_flood_tracking'] ) ? $options['advanced_comment_flood_tracking'] : false;
213
214 if ( ! $flood_tracking ) {
215 return;
216 }
217
218 $req_user_login = get_option( 'comment_registration' );
219
220 if ( $req_user_login ) {
221 $user = wp_get_current_user();
222 $user_id = $user->ID;
223 $user_name = $user->display_name;
224 } else {
225 $user_name = esc_html__( 'a logged out user', 'stream' );
226 }
227
228 $this->log(
229 __( 'Comment flooding by %s detected and prevented', 'stream' ),
230 compact( 'user_name', 'user_id', 'time_lastcomment', 'time_newcomment' ),
231 null,
232 'comments',
233 'flood'
234 );
235 }
236
237 /**
238 * Tracks comment creation
239 *
240 * @action wp_insert_comment
241 *
242 * @param int $comment_id
243 * @param object $comment
244 */
245 public function callback_wp_insert_comment( $comment_id, $comment ) {
246 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
247 return;
248 }
249
250 $user_id = $this->get_comment_author( $comment, 'id' );
251 $user_name = $this->get_comment_author( $comment, 'name' );
252 $post_id = $comment->comment_post_ID;
253 $post_type = get_post_type( $post_id );
254 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
255 $comment_status = ( 1 === $comment->comment_approved ) ? esc_html__( 'approved automatically', 'stream' ) : esc_html__( 'pending approval', 'stream' );
256 $is_spam = false;
257
258 // Auto-marked spam comments
259 $options = wp_stream_get_instance()->settings->options;
260 $ak_tracking = isset( $options['advanced_akismet_tracking'] ) ? $options['advanced_akismet_tracking'] : false;
261
262 if ( class_exists( 'Akismet' ) && $ak_tracking && \Akismet::matches_last_comment( $comment ) ) {
263 $ak_last_comment = \Akismet::get_last_comment();
264 if ( 'true' === $ak_last_comment['akismet_result'] ) {
265 $is_spam = true;
266 $comment_status = esc_html__( 'automatically marked as spam by Akismet', 'stream' );
267 }
268 }
269
270 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
271
272 if ( $comment->comment_parent ) {
273 $parent_user_id = get_comment_author( $comment->comment_parent, 'id' );
274 $parent_user_name = get_comment_author( $comment->comment_parent, 'name' );
275
276 $this->log(
277 _x(
278 'Reply to %1$s\'s %5$s by %2$s on %3$s %4$s',
279 "1: Parent comment's author, 2: Comment author, 3: Post title, 4: Comment status, 5: Comment type",
280 'stream'
281 ),
282 compact( 'parent_user_name', 'user_name', 'post_title', 'comment_status', 'comment_type', 'post_id', 'parent_user_id' ),
283 $comment_id,
284 $post_type,
285 'replied',
286 $user_id
287 );
288 } else {
289 $this->log(
290 _x(
291 'New %4$s by %1$s on %2$s %3$s',
292 '1: Comment author, 2: Post title 3: Comment status, 4: Comment type',
293 'stream'
294 ),
295 compact( 'user_name', 'post_title', 'comment_status', 'comment_type', 'post_id', 'is_spam' ),
296 $comment_id,
297 $post_type,
298 $is_spam ? 'spammed' : 'created',
299 $user_id
300 );
301 }
302 }
303
304 /**
305 * Tracks comment updates
306 *
307 * @action edit_comment
308 *
309 * @param int $comment_id
310 */
311 public function callback_edit_comment( $comment_id ) {
312 $comment = get_comment( $comment_id );
313
314 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
315 return;
316 }
317
318 $user_id = $this->get_comment_author( $comment, 'id' );
319 $user_name = $this->get_comment_author( $comment, 'name' );
320 $post_id = $comment->comment_post_ID;
321 $post_type = get_post_type( $post_id );
322 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
323 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
324
325 $this->log(
326 _x(
327 '%1$s\'s %3$s on %2$s edited',
328 '1: Comment author, 2: Post title, 3: Comment type',
329 'stream'
330 ),
331 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
332 $comment_id,
333 $post_type,
334 'edited'
335 );
336 }
337
338 /**
339 * Catch the post ID during deletion
340 *
341 * @action before_delete_post
342 *
343 * @param int $post_id
344 */
345 public function callback_before_delete_post( $post_id ) {
346 if ( wp_is_post_revision( $post_id ) ) {
347 return;
348 }
349
350 $this->delete_post = $post_id;
351 }
352
353 /**
354 * Reset the post ID after deletion
355 *
356 * @action deleted_post
357 *
358 * @param int $post_id
359 */
360 public function callback_deleted_post( $post_id ) {
361 if ( wp_is_post_revision( $post_id ) ) {
362 return;
363 }
364
365 $this->delete_post = 0;
366 }
367
368 /**
369 * Tracks comment delete
370 *
371 * @action delete_comment
372 *
373 * @param int $comment_id
374 */
375 public function callback_delete_comment( $comment_id ) {
376 $comment = get_comment( $comment_id );
377
378 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
379 return;
380 }
381
382 $user_id = $this->get_comment_author( $comment, 'id' );
383 $user_name = $this->get_comment_author( $comment, 'name' );
384 $post_id = absint( $comment->comment_post_ID );
385 $post_type = get_post_type( $post_id );
386 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
387 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
388
389 if ( $this->delete_post === $post_id ) {
390 return;
391 }
392
393 $this->log(
394 _x(
395 '%1$s\'s %3$s on %2$s deleted permanently',
396 '1: Comment author, 2: Post title, 3: Comment type',
397 'stream'
398 ),
399 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
400 $comment_id,
401 $post_type,
402 'deleted'
403 );
404 }
405
406 /**
407 * Tracks comment trashing
408 *
409 * @action trash_comment
410 *
411 * @param int $comment_id
412 */
413 public function callback_trash_comment( $comment_id ) {
414 $comment = get_comment( $comment_id );
415
416 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
417 return;
418 }
419
420 $user_id = $this->get_comment_author( $comment, 'id' );
421 $user_name = $this->get_comment_author( $comment, 'name' );
422 $post_id = $comment->comment_post_ID;
423 $post_type = get_post_type( $post_id );
424 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
425 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
426
427 $this->log(
428 _x(
429 '%1$s\'s %3$s on %2$s trashed',
430 '1: Comment author, 2: Post title, 3: Comment type',
431 'stream'
432 ),
433 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
434 $comment_id,
435 $post_type,
436 'trashed'
437 );
438 }
439
440 /**
441 * Tracks comment trashing
442 *
443 * @action untrash_comment
444 *
445 * @param int $comment_id
446 */
447 public function callback_untrash_comment( $comment_id ) {
448 $comment = get_comment( $comment_id );
449
450 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
451 return;
452 }
453
454 $user_id = $this->get_comment_author( $comment, 'id' );
455 $user_name = $this->get_comment_author( $comment, 'name' );
456 $post_id = $comment->comment_post_ID;
457 $post_type = get_post_type( $post_id );
458 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
459 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
460
461 $this->log(
462 _x(
463 '%1$s\'s %3$s on %2$s restored',
464 '1: Comment author, 2: Post title, 3: Comment type',
465 'stream'
466 ),
467 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
468 $comment_id,
469 $post_type,
470 'untrashed'
471 );
472 }
473
474 /**
475 * Tracks comment marking as spam
476 *
477 * @action spam_comment
478 *
479 * @param int $comment_id
480 */
481 public function callback_spam_comment( $comment_id ) {
482 $comment = get_comment( $comment_id );
483
484 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
485 return;
486 }
487
488 $user_id = $this->get_comment_author( $comment, 'id' );
489 $user_name = $this->get_comment_author( $comment, 'name' );
490 $post_id = $comment->comment_post_ID;
491 $post_type = get_post_type( $post_id );
492 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
493 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
494
495 $this->log(
496 _x(
497 '%1$s\'s %3$s on %2$s marked as spam',
498 '1: Comment author, 2: Post title, 3: Comment type',
499 'stream'
500 ),
501 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
502 $comment_id,
503 $post_type,
504 'spammed'
505 );
506 }
507
508 /**
509 * Tracks comment unmarking as spam
510 *
511 * @action unspam_comment
512 *
513 * @param int $comment_id
514 */
515 public function callback_unspam_comment( $comment_id ) {
516 $comment = get_comment( $comment_id );
517
518 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
519 return;
520 }
521
522 $user_id = $this->get_comment_author( $comment, 'id' );
523 $user_name = $this->get_comment_author( $comment, 'name' );
524 $post_id = $comment->comment_post_ID;
525 $post_type = get_post_type( $post_id );
526 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
527 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
528
529 $this->log(
530 _x(
531 '%1$s\'s %3$s on %2$s unmarked as spam',
532 '1: Comment author, 2: Post title, 3: Comment type',
533 'stream'
534 ),
535 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
536 $comment_id,
537 $post_type,
538 'unspammed'
539 );
540 }
541
542 /**
543 * Track comment status transition
544 *
545 * @action transition_comment_status
546 *
547 * @param string $new_status
548 * @param string $old_status
549 * @param object $comment
550 */
551 public function callback_transition_comment_status( $new_status, $old_status, $comment ) {
552 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
553 return;
554 }
555
556 if ( 'approved' !== $new_status && 'unapproved' !== $new_status || 'trash' === $old_status || 'spam' === $old_status ) {
557 return;
558 }
559
560 $user_id = $this->get_comment_author( $comment, 'id' );
561 $user_name = $this->get_comment_author( $comment, 'name' );
562 $post_id = $comment->comment_post_ID;
563 $post_type = get_post_type( $post_id );
564 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
565 $comment_type = get_comment_type( $comment->comment_ID );
566
567 $this->log(
568 _x(
569 '%1$s\'s %3$s %2$s',
570 'Comment status transition. 1: Comment author, 2: Post title, 3: Comment type',
571 'stream'
572 ),
573 compact( 'user_name', 'new_status', 'comment_type', 'old_status', 'post_title', 'post_id', 'user_id' ),
574 $comment->comment_ID,
575 $post_type,
576 $new_status
577 );
578 }
579
580 /**
581 * Track attempts to add duplicate comments
582 *
583 * @action comment_duplicate_trigger
584 *
585 * @param array $comment_data
586 */
587 public function callback_comment_duplicate_trigger( $comment_data ) {
588 global $wpdb;
589 unset( $comment_data );
590
591 $comment_id = $wpdb->last_result[0]->comment_ID;
592 $comment = get_comment( $comment_id );
593
594 if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
595 return;
596 }
597
598 $user_id = $this->get_comment_author( $comment, 'id' );
599 $user_name = $this->get_comment_author( $comment, 'name' );
600 $post_id = $comment->comment_post_ID;
601 $post_type = get_post_type( $post_id );
602 $post_title = ( $post = get_post( $post_id ) ) ? "\"$post->post_title\"" : esc_html__( 'a post', 'stream' );
603 $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
604
605 $this->log(
606 _x(
607 'Duplicate %3$s by %1$s prevented on %2$s',
608 '1: Comment author, 2: Post title, 3: Comment type',
609 'stream'
610 ),
611 compact( 'user_name', 'post_title', 'comment_type', 'post_id', 'user_id' ),
612 $comment_id,
613 $post_type,
614 'duplicate'
615 );
616 }
617
618 /**
619 * Constructs list of ignored comment types for the comments connector
620 *
621 * @return array List of ignored comment types
622 */
623 public function get_ignored_comment_types() {
624 return apply_filters(
625 'wp_stream_comments_exclude_comment_types',
626 array()
627 );
628 }
629 }
630