[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Akismet support for BuddyPress' Activity Stream. 4 * 5 * @package BuddyPress 6 * @subpackage ActivityAkismet 7 * @since 1.6.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * Akismet support for the Activity component. 15 * 16 * @since 1.6.0 17 * @since 2.3.0 We only support Akismet 3+. 18 */ 19 class BP_Akismet { 20 21 /** 22 * The activity last marked as spam. 23 * 24 * @since 1.6.0 25 * @var BP_Activity_Activity 26 */ 27 protected $last_activity = null; 28 29 /** 30 * Constructor. 31 * 32 * @since 1.6.0 33 */ 34 public function __construct() { 35 $this->setup_actions(); 36 } 37 38 /** 39 * Hook Akismet into the activity stream. 40 * 41 * @since 1.6.0 42 */ 43 protected function setup_actions() { 44 // Add nonces to activity stream lists. 45 add_action( 'bp_after_activity_post_form', array( $this, 'add_activity_stream_nonce' ) ); 46 add_action( 'bp_activity_entry_comments', array( $this, 'add_activity_stream_nonce' ) ); 47 48 // Add a "mark as spam" button to individual activity items. 49 add_action( 'bp_activity_entry_meta', array( $this, 'add_activity_spam_button' ) ); 50 add_action( 'bp_activity_comment_options', array( $this, 'add_activity_comment_spam_button' ) ); 51 52 // Check activity for spam. 53 add_action( 'bp_activity_before_save', array( $this, 'check_activity' ), 4, 1 ); 54 55 // Tidy up member's latest (activity) update. 56 add_action( 'bp_activity_posted_update', array( $this, 'check_member_activity_update' ), 1, 3 ); 57 58 // Hooks to extend Activity core spam/ham functions for Akismet. 59 add_action( 'bp_activity_mark_as_spam', array( $this, 'mark_as_spam' ), 10, 2 ); 60 add_action( 'bp_activity_mark_as_ham', array( $this, 'mark_as_ham' ), 10, 2 ); 61 62 // Hook into the Activity wp-admin screen. 63 add_action( 'bp_activity_admin_comment_row_actions', array( $this, 'comment_row_action' ), 10, 2 ); 64 add_action( 'bp_activity_admin_load', array( $this, 'add_history_metabox' ) ); 65 } 66 67 /** 68 * Add a history item to the hover links in an activity's row. 69 * 70 * This function lifted with love from the Akismet WordPress plugin's 71 * akismet_comment_row_action() function. Thanks! 72 * 73 * @since 1.6.0 74 * 75 * @param array $actions The hover links. 76 * @param array $activity The activity for the current row being processed. 77 * @return array The hover links. 78 */ 79 function comment_row_action( $actions, $activity ) { 80 $akismet_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_result' ); 81 $user_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_user_result' ); 82 $desc = ''; 83 84 if ( !$user_result || $user_result == $akismet_result ) { 85 // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same. 86 if ( 'true' == $akismet_result && $activity['is_spam'] ) 87 $desc = __( 'Flagged as spam by Akismet', 'buddypress' ); 88 89 elseif ( 'false' == $akismet_result && !$activity['is_spam'] ) 90 $desc = __( 'Cleared by Akismet', 'buddypress' ); 91 92 } else { 93 $who = bp_activity_get_meta( $activity['id'], '_bp_akismet_user' ); 94 95 if ( 'true' == $user_result ) { 96 /* translators: %s: the name of the user */ 97 $desc = sprintf( __( 'Flagged as spam by %s', 'buddypress' ), $who ); 98 } else { 99 /* translators: %s: the name of the user */ 100 $desc = sprintf( __( 'Un-spammed by %s', 'buddypress' ), $who ); 101 } 102 } 103 104 // Add a History item to the hover links, just after Edit. 105 if ( $akismet_result ) { 106 $b = array(); 107 foreach ( $actions as $k => $item ) { 108 $b[ $k ] = $item; 109 if ( $k == 'edit' ) 110 $b['history'] = '<a href="' . esc_url( bp_get_admin_url( 'admin.php?page=bp-activity&action=edit&aid=' . $activity['id'] ) ) . '#bp_activity_history"> '. __( 'History', 'buddypress' ) . '</a>'; 111 } 112 113 $actions = $b; 114 } 115 116 if ( $desc ) 117 echo '<span class="akismet-status"><a href="' . esc_url( bp_get_admin_url( 'admin.php?page=bp-activity&action=edit&aid=' . $activity['id'] ) ) . '#bp_activity_history">' . htmlspecialchars( $desc ) . '</a></span>'; 118 119 /** 120 * Filters the list of actions for the current activity's row. 121 * 122 * @since 1.6.0 123 * 124 * @param array $actions Array of available actions for the current activity item's row. 125 */ 126 return apply_filters( 'bp_akismet_comment_row_action', $actions ); 127 } 128 129 /** 130 * Generate nonces for activity forms. 131 * 132 * These nonces appear in the member profile status form, as well as in 133 * the reply form of each activity item. The nonces are, in turn, used 134 * by Akismet to help detect spam activity. 135 * 136 * @since 1.6.0 137 * 138 * @see https://plugins.trac.wordpress.org/ticket/1232 139 */ 140 public function add_activity_stream_nonce() { 141 $form_id = '_bp_as_nonce'; 142 $value = '_bp_as_nonce_' . bp_loggedin_user_id(); 143 144 // If we're in the activity stream loop, we can use the current item's ID to make the nonce unique. 145 if ( 'bp_activity_entry_comments' == current_filter() ) { 146 $form_id .= '_' . bp_get_activity_id(); 147 $value .= '_' . bp_get_activity_id(); 148 } 149 150 wp_nonce_field( $value, $form_id, false ); 151 } 152 153 /** 154 * Clean up the bp_latest_update usermeta in case of spamming. 155 * 156 * Run just after an update is posted, this method check to see whether 157 * the newly created update has been marked as spam by Akismet. If so, 158 * the cached update is cleared from the user's 'bp_latest_update' 159 * usermeta, ensuring that it won't appear in the member header and 160 * elsewhere in the theme. 161 * 162 * This can't be done in BP_Akismet::check_activity() due to the 163 * default AJAX implementation; see bp_dtheme_post_update(). 164 * 165 * @since 1.6.0 166 * 167 * @see bp_dtheme_post_update() 168 * 169 * @param string $content Activity update text. 170 * @param int $user_id User ID. 171 * @param int $activity_id Activity ID. 172 */ 173 public function check_member_activity_update( $content, $user_id, $activity_id ) { 174 // By default, only handle activity updates and activity comments. 175 if ( empty( $this->last_activity ) || !in_array( $this->last_activity->type, BP_Akismet::get_activity_types() ) ) 176 return; 177 178 // Was this $activity_id just marked as spam? If not, bail out. 179 if ( !$this->last_activity->id || $activity_id != $this->last_activity->id || 'false' == $this->last_activity->akismet_submission['bp_as_result'] ) 180 return; 181 182 // It was, so delete the member's latest activity update. 183 bp_delete_user_meta( $user_id, 'bp_latest_update' ); 184 } 185 186 /** 187 * Adds a "mark as spam" button to each activity item for site admins. 188 * 189 * This function is intended to be used inside the activity stream loop. 190 * 191 * @since 1.6.0 192 */ 193 public function add_activity_spam_button() { 194 if ( !bp_activity_user_can_mark_spam() ) 195 return; 196 197 // By default, only handle activity updates and activity comments. 198 if ( !in_array( bp_get_activity_type(), BP_Akismet::get_activity_types() ) ) 199 return; 200 201 bp_button( 202 array( 203 'block_self' => false, 204 'component' => 'activity', 205 'id' => 'activity_make_spam_' . bp_get_activity_id(), 206 'link_class' => 'bp-secondary-action spam-activity confirm button item-button', 207 'link_href' => wp_nonce_url( bp_get_root_domain() . '/' . bp_get_activity_slug() . '/spam/' . bp_get_activity_id() . '/', 'bp_activity_akismet_spam_' . bp_get_activity_id() ), 208 'link_text' => __( 'Spam', 'buddypress' ), 209 'wrapper' => false, 210 ) 211 ); 212 } 213 214 /** 215 * Adds a "mark as spam" button to each activity COMMENT item for site admins. 216 * 217 * This function is intended to be used inside the activity stream loop. 218 * 219 * @since 1.6.0 220 */ 221 public function add_activity_comment_spam_button() { 222 if ( !bp_activity_user_can_mark_spam() ) 223 return; 224 225 // By default, only handle activity updates and activity comments. 226 $current_comment = bp_activity_current_comment(); 227 if ( empty( $current_comment ) || !in_array( $current_comment->type, BP_Akismet::get_activity_types() ) ) 228 return; 229 230 bp_button( 231 array( 232 'block_self' => false, 233 'component' => 'activity', 234 'id' => 'activity_make_spam_' . bp_get_activity_comment_id(), 235 'link_class' => 'bp-secondary-action spam-activity-comment confirm', 236 'link_href' => wp_nonce_url( bp_get_root_domain() . '/' . bp_get_activity_slug() . '/spam/' . bp_get_activity_comment_id() . '/?cid=' . bp_get_activity_comment_id(), 'bp_activity_akismet_spam_' . bp_get_activity_comment_id() ), 237 'link_text' => __( 'Spam', 'buddypress' ), 238 'wrapper' => false, 239 ) 240 ); 241 } 242 243 /** 244 * Get a filterable list of activity types that Akismet should automatically check for spam. 245 * 246 * @since 1.6.0 247 * 248 * @static 249 * 250 * @return array $value List of activity types. 251 */ 252 public static function get_activity_types() { 253 254 /** 255 * Filters the list of activity types that Akismet should automatically check for spam. 256 * 257 * @since 1.6.0 258 * 259 * @param array $value Array of default activity types for Akismet to check. 260 */ 261 return apply_filters( 'bp_akismet_get_activity_types', array( 'activity_comment', 'activity_update' ) ); 262 } 263 264 /** 265 * Mark activity item as spam. 266 * 267 * @since 1.6.0 268 * 269 * @param BP_Activity_Activity $activity Activity item being spammed. 270 * @param string $source Either "by_a_person" (e.g. a person has 271 * manually marked the activity as spam) or 272 * "by_akismet" (automatically spammed). 273 */ 274 public function mark_as_spam( $activity, $source ) { 275 // Record this item so we can do some tidyup in BP_Akismet::check_member_activity_update(). 276 $this->last_activity = $activity; 277 278 /** 279 * Fires after marking an activity item has been marked as spam. 280 * 281 * @since 1.6.0 282 * 283 * @param BP_Activity_Activity $activity Activity object being marked as spam. 284 * @param string $source Source of the whom marked as spam. 285 * Either "by_a_person" (e.g. a person has 286 * manually marked the activity as spam) 287 * or "by_akismet". 288 */ 289 do_action( 'bp_activity_akismet_mark_as_spam', $activity, $source ); 290 } 291 292 /** 293 * Mark activity item as ham. 294 * 295 * @since 1.6.0 296 * 297 * @param BP_Activity_Activity $activity Activity item being hammed. 298 * @param string $source Either "by_a_person" (e.g. a person has 299 * manually marked the activity as ham) or 300 * "by_akismet" (automatically hammed). 301 */ 302 public function mark_as_ham( $activity, $source ) { 303 // If the activity was, originally, automatically marked as spam by Akismet, run the @mentions filter as it would have been skipped. 304 if ( 'true' == bp_activity_get_meta( $activity->id, '_bp_akismet_result' ) && !bp_activity_get_meta( $activity->id, '_bp_akismet_user_result' ) ) 305 $activity->content = bp_activity_at_name_filter( $activity->content, $activity->id ); 306 307 /** 308 * Fires after marking an activity item has been marked as ham. 309 * 310 * @since 1.6.0 311 * 312 * @param BP_Activity_Activity $activity Activity object being marked as ham. 313 * @param string $source Source of the whom marked as ham. 314 * Either "by_a_person" (e.g. a person has 315 * manually marked the activity as ham) or 316 * "by_akismet" (automatically hammed). 317 */ 318 do_action( 'bp_activity_akismet_mark_as_ham', $activity, $source ); 319 } 320 321 /** 322 * Build a data package for the Akismet service to inspect. 323 * 324 * @since 1.6.0 325 * 326 * @see http://akismet.com/development/api/#comment-check 327 * @static 328 * 329 * @param BP_Activity_Activity $activity Activity item data. 330 * @return array $activity_data 331 */ 332 public static function build_akismet_data_package( $activity ) { 333 $userdata = get_userdata( $activity->user_id ); 334 335 $activity_data = array(); 336 $activity_data['akismet_comment_nonce'] = 'inactive'; 337 $activity_data['comment_author'] = $userdata->display_name; 338 $activity_data['comment_author_email'] = $userdata->user_email; 339 $activity_data['comment_author_url'] = bp_core_get_userlink( $userdata->ID, false, true); 340 $activity_data['comment_content'] = $activity->content; 341 $activity_data['comment_type'] = $activity->type; 342 $activity_data['permalink'] = bp_activity_get_permalink( $activity->id, $activity ); 343 $activity_data['user_ID'] = $userdata->ID; 344 $activity_data['user_role'] = Akismet::get_user_roles( $userdata->ID ); 345 346 /** 347 * Get the nonce if the new activity was submitted through the "what's up, Paul?" form. 348 * This helps Akismet ensure that the update was a valid form submission. 349 */ 350 if ( !empty( $_POST['_bp_as_nonce'] ) ) 351 $activity_data['akismet_comment_nonce'] = wp_verify_nonce( $_POST['_bp_as_nonce'], "_bp_as_nonce_{$userdata->ID}" ) ? 'passed' : 'failed'; 352 353 /** 354 * If the new activity was a reply to an existing item, check the nonce with the activity parent ID. 355 * This helps Akismet ensure that the update was a valid form submission. 356 */ 357 elseif ( !empty( $activity->secondary_item_id ) && !empty( $_POST['_bp_as_nonce_' . $activity->secondary_item_id] ) ) 358 $activity_data['akismet_comment_nonce'] = wp_verify_nonce( $_POST["_bp_as_nonce_{$activity->secondary_item_id}"], "_bp_as_nonce_{$userdata->ID}_{$activity->secondary_item_id}" ) ? 'passed' : 'failed'; 359 360 /** 361 * Filters activity data before being sent to Akismet to inspect. 362 * 363 * @since 1.6.0 364 * 365 * @param array $activity_data Array of activity data for Akismet to inspect. 366 * @param BP_Activity_Activity $activity Activity item data. 367 */ 368 return apply_filters( 'bp_akismet_build_akismet_data_package', $activity_data, $activity ); 369 } 370 371 /** 372 * Check if the activity item is spam or ham. 373 * 374 * @since 1.6.0 375 * 376 * @see http://akismet.com/development/api/ 377 * @todo Spam counter? 378 * @todo Auto-delete old spam? 379 * 380 * @param BP_Activity_Activity $activity The activity item to check. 381 */ 382 public function check_activity( $activity ) { 383 // By default, only handle activity updates and activity comments. 384 if ( !in_array( $activity->type, BP_Akismet::get_activity_types() ) ) 385 return; 386 387 // Make sure last_activity is clear to avoid any confusion. 388 $this->last_activity = null; 389 390 // Build data package for Akismet. 391 $activity_data = BP_Akismet::build_akismet_data_package( $activity ); 392 393 // Check with Akismet to see if this is spam. 394 $activity_data = $this->send_akismet_request( $activity_data, 'check', 'spam' ); 395 396 // Record this item. 397 $this->last_activity = $activity; 398 399 // Store a copy of the data that was submitted to Akismet. 400 $this->last_activity->akismet_submission = $activity_data; 401 402 // Spam. 403 if ( 'true' == $activity_data['bp_as_result'] ) { 404 /** 405 * Fires after an activity item has been proven to be spam, but before officially being marked as spam. 406 * 407 * @since 1.6.0 408 * 409 * @param BP_Activity_Activity $activity The activity item proven to be spam. 410 * @param array $activity_data Array of activity data for item including 411 * Akismet check results data. 412 */ 413 do_action_ref_array( 'bp_activity_akismet_spam_caught', array( &$activity, $activity_data ) ); 414 415 // Mark as spam. 416 bp_activity_mark_as_spam( $activity, 'by_akismet' ); 417 418 if ( 419 Akismet::allow_discard() && 420 ! empty( $activity_data['akismet_pro_tip'] ) && 421 'discard' === $activity_data['akismet_pro_tip'] 422 ) { 423 // If this is so spammy it's not worth your time, let's just delete it. 424 if ( $activity->type === 'activity_comment' ) { 425 bp_activity_delete_comment( $activity->item_id, $activity->id ); 426 } else { 427 bp_activity_delete( array( 'id' => $activity->id ) ); 428 } 429 } 430 } 431 432 // Update activity meta after a spam check. 433 add_action( 'bp_activity_after_save', array( $this, 'update_activity_akismet_meta' ), 1, 1 ); 434 } 435 436 /** 437 * Update activity meta after a manual spam change (user-initiated). 438 * 439 * @since 1.6.0 440 * 441 * @param BP_Activity_Activity $activity The activity to check. 442 */ 443 public function update_activity_spam_meta( $activity ) { 444 // By default, only handle activity updates and activity comments. 445 if ( !in_array( $activity->type, BP_Akismet::get_activity_types() ) ) 446 return; 447 448 $this->update_activity_history( 449 $activity->id, 450 sprintf( 451 /* translators: %s: the current user username */ 452 __( '%s reported this activity as spam', 'buddypress' ), 453 bp_get_loggedin_user_username() 454 ), 455 'report-spam' 456 ); 457 458 bp_activity_update_meta( $activity->id, '_bp_akismet_user_result', 'true' ); 459 bp_activity_update_meta( $activity->id, '_bp_akismet_user', bp_get_loggedin_user_username() ); 460 } 461 462 /** 463 * Update activity meta after a manual ham change (user-initiated). 464 * 465 * @since 1.6.0 466 * 467 * @param BP_Activity_Activity $activity The activity to check. 468 */ 469 public function update_activity_ham_meta( $activity ) { 470 // By default, only handle activity updates and activity comments. 471 if ( !in_array( $activity->type, BP_Akismet::get_activity_types() ) ) 472 return; 473 474 $this->update_activity_history( 475 $activity->id, 476 sprintf( 477 /* translators: %s: the current user username */ 478 __( '%s reported this activity as not spam', 'buddypress' ), 479 bp_get_loggedin_user_username() 480 ), 481 'report-ham' 482 ); 483 484 bp_activity_update_meta( $activity->id, '_bp_akismet_user_result', 'false' ); 485 bp_activity_update_meta( $activity->id, '_bp_akismet_user', bp_get_loggedin_user_username() ); 486 } 487 488 /** 489 * Update activity meta after an automatic spam check (not user-initiated). 490 * 491 * @since 1.6.0 492 * 493 * @param BP_Activity_Activity $activity The activity to check. 494 */ 495 public function update_activity_akismet_meta( $activity ) { 496 // Check we're dealing with what was last updated by Akismet. 497 if ( empty( $this->last_activity ) || !empty( $this->last_activity ) && $activity->id != $this->last_activity->id ) 498 return; 499 500 // By default, only handle activity updates and activity comments. 501 if ( !in_array( $this->last_activity->type, BP_Akismet::get_activity_types() ) ) 502 return; 503 504 // Spam. 505 if ( 'true' == $this->last_activity->akismet_submission['bp_as_result'] ) { 506 bp_activity_update_meta( $activity->id, '_bp_akismet_result', 'true' ); 507 $this->update_activity_history( $activity->id, __( 'Akismet caught this item as spam', 'buddypress' ), 'check-spam' ); 508 509 // Not spam. 510 } elseif ( 'false' == $this->last_activity->akismet_submission['bp_as_result'] ) { 511 bp_activity_update_meta( $activity->id, '_bp_akismet_result', 'false' ); 512 $this->update_activity_history( $activity->id, __( 'Akismet cleared this item', 'buddypress' ), 'check-ham' ); 513 514 // Uh oh, something's gone horribly wrong. Unexpected result. 515 } else { 516 bp_activity_update_meta( $activity->id, '_bp_akismet_error', bp_core_current_time() ); 517 $this->update_activity_history( 518 $activity->id, 519 sprintf( 520 /* translators: %s the akismet result */ 521 __( 'Akismet was unable to check this item (response: %s), will automatically retry again later.', 'buddypress' ), 522 $this->last_activity->akismet_submission['bp_as_result'] 523 ), 524 'check-error' 525 ); 526 } 527 528 // Record the original data which was submitted to Akismet for checking. 529 bp_activity_update_meta( $activity->id, '_bp_akismet_submission', $this->last_activity->akismet_submission ); 530 } 531 532 /** 533 * Contact Akismet to check if this is spam or ham. 534 * 535 * Props to WordPress core Akismet plugin for a lot of this. 536 * 537 * @since 1.6.0 538 * 539 * @param array $activity_data Packet of information to submit to Akismet. 540 * @param string $check "check" or "submit". 541 * @param string $spam "spam" or "ham". 542 * @return array $activity_data Activity data, with Akismet data added. 543 */ 544 public function send_akismet_request( $activity_data, $check = 'check', $spam = 'spam' ) { 545 $query_string = $path = ''; 546 547 $activity_data['blog'] = bp_get_option( 'home' ); 548 $activity_data['blog_charset'] = bp_get_option( 'blog_charset' ); 549 $activity_data['blog_lang'] = get_locale(); 550 $activity_data['referrer'] = $_SERVER['HTTP_REFERER']; 551 $activity_data['user_agent'] = bp_core_current_user_ua(); 552 $activity_data['user_ip'] = bp_core_current_user_ip(); 553 554 if ( Akismet::is_test_mode() ) 555 $activity_data['is_test'] = 'true'; 556 557 // Loop through _POST args and rekey strings. 558 foreach ( $_POST as $key => $value ) 559 if ( is_string( $value ) && 'cookie' != $key ) 560 $activity_data['POST_' . $key] = $value; 561 562 // Keys to ignore. 563 $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' ); 564 565 // Loop through _SERVER args and remove specified keys. 566 foreach ( $_SERVER as $key => $value ) { 567 568 // Key should not be ignored. 569 if ( !in_array( $key, $ignore ) && is_string( $value ) ) { 570 $activity_data[$key] = $value; 571 572 // Key should be ignored. 573 } else { 574 $activity_data[$key] = ''; 575 } 576 } 577 578 foreach ( $activity_data as $key => $data ) 579 $query_string .= $key . '=' . urlencode( stripslashes( $data ) ) . '&'; 580 581 if ( 'check' == $check ) 582 $path = 'comment-check'; 583 elseif ( 'submit' == $check ) 584 $path = 'submit-' . $spam; 585 586 // Send to Akismet. 587 add_filter( 'akismet_ua', array( $this, 'buddypress_ua' ) ); 588 $response = Akismet::http_post( $query_string, $path ); 589 remove_filter( 'akismet_ua', array( $this, 'buddypress_ua' ) ); 590 591 // Save response data. 592 $activity_data['bp_as_result'] = $response[1]; 593 if ( isset( $response[0]['x-akismet-pro-tip'] ) ) { 594 $activity_data['akismet_pro_tip'] = $response[0]['x-akismet-pro-tip']; 595 } 596 597 // Perform a daily tidy up. 598 if ( ! wp_next_scheduled( 'bp_activity_akismet_delete_old_metadata' ) ) 599 wp_schedule_event( time(), 'daily', 'bp_activity_akismet_delete_old_metadata' ); 600 601 return $activity_data; 602 } 603 604 /** 605 * Filters user agent when sending to Akismet to add BuddyPress info. 606 * 607 * @since 1.6.0 608 * 609 * @param string $user_agent User agent string, as generated by Akismet. 610 * @return string $user_agent Modified user agent string. 611 */ 612 public function buddypress_ua( $user_agent ) { 613 $user_agent = 'BuddyPress/' . bp_get_version() . ' | Akismet/'. constant( 'AKISMET_VERSION' ); 614 return $user_agent; 615 } 616 617 /** 618 * Adds a "History" meta box to the activity edit screen. 619 * 620 * @since 1.6.0 621 * 622 * @param string $screen_action The type of screen that has been requested. 623 */ 624 function add_history_metabox( $screen_action ) { 625 // Only proceed if we're on the edit screen. 626 if ( 'edit' != $screen_action ) 627 return; 628 629 // Display meta box with a low priority (low position on screen by default). 630 add_meta_box( 'bp_activity_history', __( 'Activity History', 'buddypress' ), array( $this, 'history_metabox' ), get_current_screen()->id, 'normal', 'low' ); 631 } 632 633 /** 634 * History meta box for the Activity admin edit screen. 635 * 636 * @since 1.6.0 637 * 638 * @see https://buddypress.trac.wordpress.org/ticket/3907 639 * @todo Update activity meta to allow >1 record with the same key (iterate through $history). 640 * 641 * @param object $item Activity item. 642 */ 643 function history_metabox( $item ) { 644 $history = BP_Akismet::get_activity_history( $item->id ); 645 646 if ( empty( $history ) ) 647 return; 648 649 echo '<div class="akismet-history"><div>'; 650 /* translators: 1: the human diff time. 2: the akismet history data. */ 651 printf( _x( '%1$s — %2$s', 'x hours ago - akismet cleared this item', 'buddypress' ), '<span>' . bp_core_time_since( $history[2] ) . '</span>', esc_html( $history[1] ) ); 652 echo '</div></div>'; 653 } 654 655 /** 656 * Update an activity item's Akismet history. 657 * 658 * @since 1.6.0 659 * 660 * @param int $activity_id Activity item ID. 661 * @param string $message Human-readable description of what's changed. 662 * @param string $event The type of check we were carrying out. 663 */ 664 public function update_activity_history( $activity_id = 0, $message = '', $event = '' ) { 665 $event = array( 666 'event' => $event, 667 'message' => $message, 668 'time' => Akismet::_get_microtime(), 669 'user' => bp_loggedin_user_id(), 670 ); 671 672 // Save the history data. 673 bp_activity_update_meta( $activity_id, '_bp_akismet_history', $event ); 674 } 675 676 /** 677 * Get an activity item's Akismet history. 678 * 679 * @since 1.6.0 680 * 681 * @param int $activity_id Activity item ID. 682 * @return array The activity item's Akismet history. 683 */ 684 public function get_activity_history( $activity_id = 0 ) { 685 $history = bp_activity_get_meta( $activity_id, '_bp_akismet_history' ); 686 if ( $history === false ) 687 $history = array(); 688 689 // Sort it by the time recorded. 690 usort( $history, 'akismet_cmp_time' ); 691 692 return $history; 693 } 694 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Dec 5 01:00:58 2024 | Cross-referenced by PHPXref 0.7.1 |