Skip to:
Content

BuddyPress.org

Ticket #6870: 6870.diff

File 6870.diff, 261.0 KB (added by boonebgorges, 9 years ago)
  • src/bp-activity/bp-activity-admin.php

     
    1616// Include WP's list table class.
    1717if ( !class_exists( 'WP_List_Table' ) ) require( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
    1818
     19require dirname( __FILE__ ) . '/classes/class-bp-activity-list-table.php';
     20
    1921// Per_page screen option. Has to be hooked in extremely early.
    2022if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-activity' == $_REQUEST['page'] )
    2123        add_filter( 'set-screen-option', 'bp_activity_admin_screen_options', 10, 3 );
     
    10381040
    10391041<?php
    10401042}
    1041 
    1042 /**
    1043  * List table class for the Activity component admin page.
    1044  *
    1045  * @since 1.6.0
    1046  */
    1047 class BP_Activity_List_Table extends WP_List_Table {
    1048 
    1049         /**
    1050          * What type of view is being displayed?
    1051          *
    1052          * E.g. "all", "pending", "approved", "spam"...
    1053          *
    1054          * @since 1.6.0
    1055          * @var string $view
    1056          */
    1057         public $view = 'all';
    1058 
    1059         /**
    1060          * How many activity items have been marked as spam.
    1061          *
    1062          * @since 1.6.0
    1063          * @var int $spam_count
    1064          */
    1065         public $spam_count = 0;
    1066 
    1067         /**
    1068          * Store activity-to-user-ID mappings for use in the In Response To column.
    1069          *
    1070          * @since 1.6.0
    1071          * @var array $activity_user_id
    1072          */
    1073         protected $activity_user_id = array();
    1074 
    1075         /**
    1076          * If users can comment on blog & forum activity items.
    1077          *
    1078          * @link https://buddypress.trac.wordpress.org/ticket/6277
    1079          *
    1080          * @since 2.2.2
    1081          * @var bool $disable_blogforum_comments
    1082          */
    1083         public $disable_blogforum_comments = false;
    1084 
    1085         /**
    1086          * Constructor.
    1087          *
    1088          * @since 1.6.0
    1089          */
    1090         public function __construct() {
    1091 
    1092                 // See if activity commenting is enabled for blog / forum activity items.
    1093                 $this->disable_blogforum_comments = bp_disable_blogforum_comments();
    1094 
    1095                 // Define singular and plural labels, as well as whether we support AJAX.
    1096                 parent::__construct( array(
    1097                         'ajax'     => false,
    1098                         'plural'   => 'activities',
    1099                         'singular' => 'activity',
    1100                         'screen'   => get_current_screen(),
    1101                 ) );
    1102         }
    1103 
    1104         /**
    1105          * Handle filtering of data, sorting, pagination, and any other data manipulation prior to rendering.
    1106          *
    1107          * @since 1.6.0
    1108          */
    1109         function prepare_items() {
    1110 
    1111                 // Option defaults.
    1112                 $filter           = array();
    1113                 $include_id       = false;
    1114                 $search_terms     = false;
    1115                 $sort             = 'DESC';
    1116                 $spam             = 'ham_only';
    1117 
    1118                 // Set current page.
    1119                 $page = $this->get_pagenum();
    1120 
    1121                 // Set per page from the screen options.
    1122                 $per_page = $this->get_items_per_page( str_replace( '-', '_', "{$this->screen->id}_per_page" ) );
    1123 
    1124                 // Check if we're on the "Spam" view.
    1125                 if ( !empty( $_REQUEST['activity_status'] ) && 'spam' == $_REQUEST['activity_status'] ) {
    1126                         $spam       = 'spam_only';
    1127                         $this->view = 'spam';
    1128                 }
    1129 
    1130                 // Sort order.
    1131                 if ( !empty( $_REQUEST['order'] ) && 'desc' != $_REQUEST['order'] )
    1132                         $sort = 'ASC';
    1133 
    1134                 // Order by.
    1135                 /*if ( !empty( $_REQUEST['orderby'] ) ) {
    1136                 }*/
    1137 
    1138                 // Filter.
    1139                 if ( !empty( $_REQUEST['activity_type'] ) )
    1140                         $filter = array( 'action' => $_REQUEST['activity_type'] );
    1141 
    1142                 // Are we doing a search?
    1143                 if ( !empty( $_REQUEST['s'] ) )
    1144                         $search_terms = $_REQUEST['s'];
    1145 
    1146                 // Check if user has clicked on a specific activity (if so, fetch only that, and any related, activity).
    1147                 if ( !empty( $_REQUEST['aid'] ) )
    1148                         $include_id = (int) $_REQUEST['aid'];
    1149 
    1150                 // Get the spam total (ignoring any search query or filter).
    1151                 $spams = bp_activity_get( array(
    1152                         'display_comments' => 'stream',
    1153                         'show_hidden'      => true,
    1154                         'spam'             => 'spam_only',
    1155                         'count_total'      => 'count_query',
    1156                 ) );
    1157                 $this->spam_count = $spams['total'];
    1158                 unset( $spams );
    1159 
    1160                 // Get the activities from the database.
    1161                 $activities = bp_activity_get( array(
    1162                         'display_comments' => 'stream',
    1163                         'filter'           => $filter,
    1164                         'in'               => $include_id,
    1165                         'page'             => $page,
    1166                         'per_page'         => $per_page,
    1167                         'search_terms'     => $search_terms,
    1168                         'show_hidden'      => true,
    1169                         // 'sort'             => $sort,
    1170                         'spam'             => $spam,
    1171                         'count_total'      => 'count_query',
    1172                 ) );
    1173 
    1174                 // If we're viewing a specific activity, flatten all activities into a single array.
    1175                 if ( $include_id ) {
    1176                         $activities['activities'] = BP_Activity_List_Table::flatten_activity_array( $activities['activities'] );
    1177                         $activities['total']      = count( $activities['activities'] );
    1178 
    1179                         // Sort the array by the activity object's date_recorded value.
    1180                         usort( $activities['activities'], create_function( '$a, $b', 'return $a->date_recorded > $b->date_recorded;' ) );
    1181                 }
    1182 
    1183                 // The bp_activity_get function returns an array of objects; cast these to arrays for WP_List_Table.
    1184                 $new_activities = array();
    1185                 foreach ( $activities['activities'] as $activity_item ) {
    1186                         $new_activities[] = (array) $activity_item;
    1187 
    1188                         // Build an array of activity-to-user ID mappings for better efficiency in the In Response To column.
    1189                         $this->activity_user_id[$activity_item->id] = $activity_item->user_id;
    1190                 }
    1191 
    1192                 // Set raw data to display.
    1193                 $this->items       = $new_activities;
    1194 
    1195                 // Store information needed for handling table pagination.
    1196                 $this->set_pagination_args( array(
    1197                         'per_page'    => $per_page,
    1198                         'total_items' => $activities['total'],
    1199                         'total_pages' => ceil( $activities['total'] / $per_page )
    1200                 ) );
    1201 
    1202                 // Don't truncate activity items; bp_activity_truncate_entry() needs to be used inside a BP_Activity_Template loop.
    1203                 remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
    1204         }
    1205 
    1206         /**
    1207          * Get an array of all the columns on the page.
    1208          *
    1209          * @since 1.6.0
    1210          *
    1211          * @return array Column headers.
    1212          */
    1213         function get_column_info() {
    1214                 $this->_column_headers = array(
    1215                         $this->get_columns(),
    1216                         array(),
    1217                         $this->get_sortable_columns(),
    1218                         $this->get_default_primary_column_name(),
    1219                 );
    1220 
    1221                 return $this->_column_headers;
    1222         }
    1223 
    1224         /**
    1225          * Get name of default primary column
    1226          *
    1227          * @since 2.3.3
    1228          *
    1229          * @return string
    1230          */
    1231         protected function get_default_primary_column_name() {
    1232                 return 'author';
    1233         }
    1234 
    1235         /**
    1236          * Display a message on screen when no items are found (e.g. no search matches).
    1237          *
    1238          * @since 1.6.0
    1239          */
    1240         function no_items() {
    1241                 _e( 'No activities found.', 'buddypress' );
    1242         }
    1243 
    1244         /**
    1245          * Output the Activity data table.
    1246          *
    1247          * @since 1.6.0
    1248          */
    1249         function display() {
    1250                 $this->display_tablenav( 'top' ); ?>
    1251 
    1252                 <h2 class="screen-reader-text"><?php _e( 'Activities list', 'buddypress' ); ?></h2>
    1253 
    1254                 <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>" cellspacing="0">
    1255                         <thead>
    1256                                 <tr>
    1257                                         <?php $this->print_column_headers(); ?>
    1258                                 </tr>
    1259                         </thead>
    1260 
    1261                         <tfoot>
    1262                                 <tr>
    1263                                         <?php $this->print_column_headers( false ); ?>
    1264                                 </tr>
    1265                         </tfoot>
    1266 
    1267                         <tbody id="the-comment-list">
    1268                                 <?php $this->display_rows_or_placeholder(); ?>
    1269                         </tbody>
    1270                 </table>
    1271                 <?php
    1272 
    1273                 $this->display_tablenav( 'bottom' );
    1274         }
    1275 
    1276         /**
    1277          * Generate content for a single row of the table.
    1278          *
    1279          * @since 1.6.0
    1280          *
    1281          * @param object $item The current item.
    1282          */
    1283         function single_row( $item ) {
    1284                 static $even = false;
    1285 
    1286                 if ( $even ) {
    1287                         $row_class = ' class="even"';
    1288                 } else {
    1289                         $row_class = ' class="alternate odd"';
    1290                 }
    1291 
    1292                 if ( 'activity_comment' === $item['type'] ) {
    1293                         $root_id = $item['item_id'];
    1294                 } else {
    1295                         $root_id = $item['id'];
    1296                 }
    1297 
    1298                 echo '<tr' . $row_class . ' id="activity-' . esc_attr( $item['id'] ) . '" data-parent_id="' . esc_attr( $item['id'] ) . '" data-root_id="' . esc_attr( $root_id ) . '">';
    1299                 echo $this->single_row_columns( $item );
    1300                 echo '</tr>';
    1301 
    1302                 $even = ! $even;
    1303         }
    1304 
    1305         /**
    1306          * Get the list of views available on this table (e.g. "all", "spam").
    1307          *
    1308          * @since 1.6.0
    1309          */
    1310         function get_views() {
    1311                 $url_base = add_query_arg( array( 'page' => 'bp-activity' ), bp_get_admin_url( 'admin.php' ) ); ?>
    1312 
    1313                 <h2 class="screen-reader-text"><?php _e( 'Filter activities list', 'buddypress' ); ?></h2>
    1314 
    1315                 <ul class="subsubsub">
    1316                         <li class="all"><a href="<?php echo esc_url( $url_base ); ?>" class="<?php if ( 'spam' != $this->view ) echo 'current'; ?>"><?php _e( 'All', 'buddypress' ); ?></a> |</li>
    1317                         <li class="spam"><a href="<?php echo esc_url( add_query_arg( array( 'activity_status' => 'spam' ), $url_base ) ); ?>" class="<?php if ( 'spam' == $this->view ) echo 'current'; ?>"><?php printf( __( 'Spam <span class="count">(%s)</span>', 'buddypress' ), number_format_i18n( $this->spam_count ) ); ?></a></li>
    1318 
    1319                         <?php
    1320 
    1321                         /**
    1322                          * Fires inside listing of views so plugins can add their own.
    1323                          *
    1324                          * @since 1.6.0
    1325                          *
    1326                          * @param string $url_base Current URL base for view.
    1327                          * @param string $view     Current view being displayed.
    1328                          */
    1329                         do_action( 'bp_activity_list_table_get_views', $url_base, $this->view ); ?>
    1330                 </ul>
    1331         <?php
    1332         }
    1333 
    1334         /**
    1335          * Get bulk actions.
    1336          *
    1337          * @since 1.6.0
    1338          *
    1339          * @return array Key/value pairs for the bulk actions dropdown.
    1340          */
    1341         function get_bulk_actions() {
    1342                 $actions = array();
    1343                 $actions['bulk_spam']   = __( 'Mark as Spam', 'buddypress' );
    1344                 $actions['bulk_ham']    = __( 'Not Spam', 'buddypress' );
    1345                 $actions['bulk_delete'] = __( 'Delete Permanently', 'buddypress' );
    1346 
    1347                 /**
    1348                  * Filters the default bulk actions so plugins can add custom actions.
    1349                  *
    1350                  * @since 1.6.0
    1351                  *
    1352                  * @param array $actions Default available actions for bulk operations.
    1353                  */
    1354                 return apply_filters( 'bp_activity_list_table_get_bulk_actions', $actions );
    1355         }
    1356 
    1357         /**
    1358          * Get the table column titles.
    1359          *
    1360          * @since 1.6.0
    1361          *
    1362          * @see WP_List_Table::single_row_columns()
    1363          *
    1364          * @return array The columns to appear in the Activity list table.
    1365          */
    1366         function get_columns() {
    1367                 /**
    1368                  * Filters the titles for the columns for the activity list table.
    1369                  *
    1370                  * @since 2.4.0
    1371                  *
    1372                  * @param array $value Array of slugs and titles for the columns.
    1373                  */
    1374                 return apply_filters( 'bp_activity_list_table_get_columns', array(
    1375                         'cb'       => '<input name type="checkbox" />',
    1376                         'author'   => _x('Author', 'Admin SWA column header', 'buddypress' ),
    1377                         'comment'  => _x( 'Activity', 'Admin SWA column header', 'buddypress' ),
    1378                         'action'   => _x( 'Action', 'Admin SWA column header', 'buddypress' ),
    1379                         'response' => _x( 'In Response To', 'Admin SWA column header', 'buddypress' ),
    1380                 ) );
    1381         }
    1382 
    1383         /**
    1384          * Get the column names for sortable columns.
    1385          *
    1386          * Currently, returns an empty array (no columns are sortable).
    1387          *
    1388          * @since 1.6.0
    1389          * @todo For this to work, BP_Activity_Activity::get() needs updating
    1390          *       to support ordering by specific fields.
    1391          *
    1392          * @return array The columns that can be sorted on the Activity screen.
    1393          */
    1394         function get_sortable_columns() {
    1395                 return array();
    1396 
    1397                 /*return array(
    1398                         'author' => array( 'activity_author', false ),  // Intentionally not using "=>"
    1399                 );*/
    1400         }
    1401 
    1402         /**
    1403          * Markup for the "filter" part of the form (i.e. which activity type to display).
    1404          *
    1405          * @since 1.6.0
    1406          *
    1407          * @param string $which 'top' or 'bottom'.
    1408          */
    1409         function extra_tablenav( $which ) {
    1410 
    1411                 // Bail on bottom table nav.
    1412                 if ( 'bottom' === $which ) {
    1413                         return;
    1414                 }
    1415 
    1416                 // Is any filter currently selected?
    1417                 $selected = ( ! empty( $_REQUEST['activity_type'] ) ) ? $_REQUEST['activity_type'] : '';
    1418 
    1419                 // Get the actions.
    1420                 $activity_actions = bp_activity_get_actions(); ?>
    1421 
    1422                 <div class="alignleft actions">
    1423                         <label for="activity-type" class="screen-reader-text"><?php _e( 'Filter by activity type', 'buddypress' ); ?></label>
    1424                         <select name="activity_type" id="activity-type">
    1425                                 <option value="" <?php selected( ! $selected ); ?>><?php _e( 'View all actions', 'buddypress' ); ?></option>
    1426 
    1427                                 <?php foreach ( $activity_actions as $component => $actions ) : ?>
    1428 
    1429                                         <optgroup label="<?php echo ucfirst( $component ); ?>">
    1430 
    1431                                                 <?php foreach ( $actions as $action_key => $action_values ) : ?>
    1432 
    1433                                                         <?php
    1434 
    1435                                                         // Skip the incorrectly named pre-1.6 action.
    1436                                                         if ( 'friends_register_activity_action' !== $action_key ) : ?>
    1437 
    1438                                                                 <option value="<?php echo esc_attr( $action_key ); ?>" <?php selected( $action_key,  $selected ); ?>><?php echo esc_html( $action_values[ 'value' ] ); ?></option>
    1439 
    1440                                                         <?php endif; ?>
    1441 
    1442                                                 <?php endforeach; ?>
    1443 
    1444                                         </optgroup>
    1445 
    1446                                 <?php endforeach; ?>
    1447 
    1448                         </select>
    1449 
    1450                         <?php submit_button( __( 'Filter', 'buddypress' ), 'secondary', false, false, array( 'id' => 'post-query-submit' ) ); ?>
    1451                 </div>
    1452 
    1453         <?php
    1454         }
    1455 
    1456         /**
    1457          * Override WP_List_Table::row_actions().
    1458          *
    1459          * Basically a duplicate of the row_actions() method, but removes the
    1460          * unnecessary <button> addition.
    1461          *
    1462          * @since 2.3.3
    1463          * @since 2.3.4 Visibility set to public for compatibility with WP < 4.0.0.
    1464          *
    1465          * @param array $actions The list of actions.
    1466          * @param bool  $always_visible Whether the actions should be always visible.
    1467          * @return string
    1468          */
    1469         public function row_actions( $actions, $always_visible = false ) {
    1470                 $action_count = count( $actions );
    1471                 $i = 0;
    1472 
    1473                 if ( !$action_count )
    1474                         return '';
    1475 
    1476                 $out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
    1477                 foreach ( $actions as $action => $link ) {
    1478                         ++$i;
    1479                         ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
    1480                         $out .= "<span class='$action'>$link$sep</span>";
    1481                 }
    1482                 $out .= '</div>';
    1483 
    1484                 return $out;
    1485         }
    1486 
    1487         /**
    1488          * Checkbox column markup.
    1489          *
    1490          * @since 1.6.0
    1491          *
    1492          * @see WP_List_Table::single_row_columns()
    1493          *
    1494          * @param array $item A singular item (one full row).
    1495          */
    1496         function column_cb( $item ) {
    1497                 printf( '<label class="screen-reader-text" for="aid-%1$d">' . __( 'Select activity item %1$d', 'buddypress' ) . '</label><input type="checkbox" name="aid[]" value="%1$d" id="aid-%1$d" />', $item['id'] );
    1498         }
    1499 
    1500         /**
    1501          * Author column markup.
    1502          *
    1503          * @since 1.6.0
    1504          *
    1505          * @see WP_List_Table::single_row_columns()
    1506          *
    1507          * @param array $item A singular item (one full row).
    1508          */
    1509         function column_author( $item ) {
    1510                 echo '<strong>' . get_avatar( $item['user_id'], '32' ) . ' ' . bp_core_get_userlink( $item['user_id'] ) . '</strong>';
    1511         }
    1512 
    1513         /**
    1514          * Action column markup.
    1515          *
    1516          * @since 2.0.0
    1517          *
    1518          * @see WP_List_Table::single_row_columns()
    1519          *
    1520          * @param array $item A singular item (one full row).
    1521          */
    1522         function column_action( $item ) {
    1523                 $actions = bp_activity_admin_get_activity_actions();
    1524 
    1525                 if ( isset( $actions[ $item['type'] ] ) ) {
    1526                         echo $actions[ $item['type'] ];
    1527                 } else {
    1528                         printf( __( 'Unregistered action - %s', 'buddypress' ), $item['type'] );
    1529                 }
    1530         }
    1531 
    1532         /**
    1533          * Content column, and "quick admin" rollover actions.
    1534          *
    1535          * Called "comment" in the CSS so we can re-use some WP core CSS.
    1536          *
    1537          * @since 1.6.0
    1538          *
    1539          * @see WP_List_Table::single_row_columns()
    1540          *
    1541          * @param array $item A singular item (one full row).
    1542          */
    1543         function column_comment( $item ) {
    1544                 // Determine what type of item (row) we're dealing with.
    1545                 if ( $item['is_spam'] )
    1546                         $item_status = 'spam';
    1547                 else
    1548                         $item_status = 'all';
    1549 
    1550                 // Preorder items: Reply | Edit | Spam | Delete Permanently.
    1551                 $actions = array(
    1552                         'reply'  => '',
    1553                         'edit'   => '',
    1554                         'spam'   => '', 'unspam' => '',
    1555                         'delete' => '',
    1556                 );
    1557 
    1558                 // Build actions URLs.
    1559                 $base_url   = bp_get_admin_url( 'admin.php?page=bp-activity&amp;aid=' . $item['id'] );
    1560                 $spam_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'spam-activity_' . $item['id'] ) );
    1561 
    1562                 $delete_url = $base_url . "&amp;action=delete&amp;$spam_nonce";
    1563                 $edit_url   = $base_url . '&amp;action=edit';
    1564                 $ham_url    = $base_url . "&amp;action=ham&amp;$spam_nonce";
    1565                 $spam_url   = $base_url . "&amp;action=spam&amp;$spam_nonce";
    1566 
    1567                 // Rollover actions.
    1568                 // Reply - JavaScript only; implemented by AJAX.
    1569                 if ( 'spam' != $item_status ) {
    1570                         if ( $this->can_comment( $item ) ) {
    1571                                 $actions['reply'] = sprintf( '<a href="#" class="reply hide-if-no-js">%s</a>', __( 'Reply', 'buddypress' ) );
    1572                         } else {
    1573                                 $actions['reply'] = sprintf( '<span class="form-input-tip" title="%s">%s</span>', __( 'Replies are disabled for this activity item', 'buddypress' ), __( 'Replies disabled', 'buddypress' ) );
    1574                         }
    1575 
    1576                         // Edit.
    1577                         $actions['edit'] = sprintf( '<a href="%s">%s</a>', $edit_url, __( 'Edit', 'buddypress' ) );
    1578                 }
    1579 
    1580                 // Spam/unspam.
    1581                 if ( 'spam' == $item_status )
    1582                         $actions['unspam'] = sprintf( '<a href="%s">%s</a>', $ham_url, __( 'Not Spam', 'buddypress' ) );
    1583                 else
    1584                         $actions['spam'] = sprintf( '<a href="%s">%s</a>', $spam_url, __( 'Spam', 'buddypress' ) );
    1585 
    1586                 // Delete.
    1587                 $actions['delete'] = sprintf( '<a href="%s" onclick="%s">%s</a>', $delete_url, "javascript:return confirm('" . esc_js( __( 'Are you sure?', 'buddypress' ) ) . "'); ", __( 'Delete Permanently', 'buddypress' ) );
    1588 
    1589                 // Start timestamp.
    1590                 echo '<div class="submitted-on">';
    1591 
    1592                 /**
    1593                  * Filters available actions for plugins to alter.
    1594                  *
    1595                  * @since 1.6.0
    1596                  *
    1597                  * @param array $actions Array of available actions user could use.
    1598                  * @param array $item    Current item being added to page.
    1599                  */
    1600                 $actions = apply_filters( 'bp_activity_admin_comment_row_actions', array_filter( $actions ), $item );
    1601 
    1602                 /* translators: 2: activity admin ui date/time */
    1603                 printf(
    1604                         __( 'Submitted on <a href="%1$s">%2$s at %3$s</a>', 'buddypress' ),
    1605                         bp_activity_get_permalink( $item['id'] ),
    1606                         date_i18n( bp_get_option( 'date_format' ), strtotime( $item['date_recorded'] ) ),
    1607                         get_date_from_gmt( $item['date_recorded'], bp_get_option( 'time_format' ) )
    1608                 );
    1609 
    1610                 // End timestamp.
    1611                 echo '</div>';
    1612 
    1613                 // Get activity content - if not set, use the action.
    1614                 if ( ! empty( $item['content'] ) ) {
    1615 
    1616                         /**
    1617                          * Filters current activity item content.
    1618                          *
    1619                          * @since 1.2.0
    1620                          *
    1621                          * @param array $item Array index holding current activity item content.
    1622                          */
    1623                         $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $item['content'] ) );
    1624                 } else {
    1625                         /**
    1626                          * Filters current activity item action.
    1627                          *
    1628                          * @since 1.2.0
    1629                          *
    1630                          * @var array $item Array index holding current activity item action.
    1631                          */
    1632                         $content = apply_filters_ref_array( 'bp_get_activity_action', array( $item['action'] ) );
    1633                 }
    1634 
    1635                 /**
    1636                  * Filter here to add extra output to the activity content into the Administration.
    1637                  *
    1638                  * @since  2.4.0
    1639                  *
    1640                  * @param  string $content The activity content.
    1641                  * @param  array  $item    The activity object converted into an array.
    1642                  */
    1643                 echo apply_filters( 'bp_activity_admin_comment_content', $content, $item ) . ' ' . $this->row_actions( $actions );
    1644         }
    1645 
    1646         /**
    1647          * "In response to" column markup.
    1648          *
    1649          * @since 1.6.0
    1650          *
    1651          * @see WP_List_Table::single_row_columns()
    1652          *
    1653          * @param array $item A singular item (one full row).
    1654          */
    1655         function column_response( $item ) {
    1656 
    1657                 // Is $item is a root activity?
    1658                 ?>
    1659 
    1660                 <div class="response-links">
    1661 
    1662                 <?php
    1663                 // Activity permalink.
    1664                 $activity_permalink = '';
    1665                 if ( ! $item['is_spam'] ) {
    1666                         $activity_permalink = '<a href="' . bp_activity_get_permalink( $item['id'], (object) $item ) . '" class="comments-view-item-link">' . __( 'View Activity', 'buddypress' ) . '</a>';
    1667                 }
    1668 
    1669                 /**
    1670                  * Filters default list of default root activity types.
    1671                  *
    1672                  * @since 1.6.0
    1673                  *
    1674                  * @param array $value Array of default activity types.
    1675                  * @param array $item  Current item being displayed.
    1676                  */
    1677                 if ( empty( $item['item_id'] ) || ! in_array( $item['type'], apply_filters( 'bp_activity_admin_root_activity_types', array( 'activity_comment' ), $item ) ) ) {
    1678                         echo $activity_permalink;
    1679 
    1680                         $comment_count     = !empty( $item['children'] ) ? bp_activity_recurse_comment_count( (object) $item ) : 0;
    1681                         $root_activity_url = bp_get_admin_url( 'admin.php?page=bp-activity&amp;aid=' . $item['id'] );
    1682 
    1683                         // If the activity has comments, display a link to the activity's permalink, with its comment count in a speech bubble.
    1684                         if ( $comment_count ) {
    1685                                 $title_attr = sprintf( _n( '%s related activity', '%s related activities', $comment_count, 'buddypress' ), number_format_i18n( $comment_count ) );
    1686                                 printf( '<a href="%1$s" title="%2$s" class="post-com-count post-com-count-approved"><span class="comment-count comment-count-approved">%3$s</span></a>', esc_url( $root_activity_url ), esc_attr( $title_attr ), number_format_i18n( $comment_count ) );
    1687                         }
    1688 
    1689                 // For non-root activities, display a link to the replied-to activity's author's profile.
    1690                 } else {
    1691                         echo '<strong>' . get_avatar( $this->get_activity_user_id( $item['item_id'] ), '32' ) . ' ' . bp_core_get_userlink( $this->get_activity_user_id( $item['item_id'] ) ) . '</strong><br />';
    1692                         echo $activity_permalink;
    1693                 }
    1694                 ?>
    1695 
    1696                 </div>
    1697 
    1698                 <?php
    1699         }
    1700 
    1701         /**
    1702          * Allow plugins to add their custom column.
    1703          *
    1704          * @since 2.4.0
    1705          *
    1706          * @param array  $item        Information about the current row.
    1707          * @param string $column_name The column name.
    1708          * @return string
    1709          */
    1710         public function column_default( $item = array(), $column_name = '' ) {
    1711 
    1712                 /**
    1713                  * Filters a string to allow plugins to add custom column content.
    1714                  *
    1715                  * @since 2.4.0
    1716                  *
    1717                  * @param string $value       Empty string.
    1718                  * @param string $column_name Name of the column being rendered.
    1719                  * @param array  $item        The current activity item in the loop.
    1720                  */
    1721                 return apply_filters( 'bp_activity_admin_get_custom_column', '', $column_name, $item );
    1722         }
    1723 
    1724         /**
    1725          * Get the user id associated with a given activity item.
    1726          *
    1727          * Wraps bp_activity_get_specific(), with some additional logic for
    1728          * avoiding duplicate queries.
    1729          *
    1730          * @since 1.6.0
    1731          *
    1732          * @param int $activity_id Activity ID to retrieve User ID for.
    1733          * @return int User ID of the activity item in question.
    1734          */
    1735         protected function get_activity_user_id( $activity_id ) {
    1736                 // If there is an existing activity/user ID mapping, just return the user ID.
    1737                 if ( ! empty( $this->activity_user_id[$activity_id] ) ) {
    1738                         return $this->activity_user_id[$activity_id];
    1739 
    1740                 /*
    1741                  * We don't have a mapping. This means the $activity_id is not on the current
    1742                  * page of results, so fetch its details from the database.
    1743                  */
    1744                 } else {
    1745                         $activity = bp_activity_get_specific( array( 'activity_ids' => $activity_id, 'show_hidden' => true, 'spam' => 'all', ) );
    1746 
    1747                         /*
    1748                          * If, somehow, the referenced activity has been deleted, leaving its associated
    1749                          * activities as orphans, use the logged in user's ID to avoid errors.
    1750                          */
    1751                         if ( empty( $activity['activities'] ) )
    1752                                 return bp_loggedin_user_id();
    1753 
    1754                         // Store the new activity/user ID mapping for any later re-use.
    1755                         $this->activity_user_id[ $activity['activities'][0]->id ] = $activity['activities'][0]->user_id;
    1756 
    1757                         // Return the user ID.
    1758                         return $activity['activities'][0]->user_id;
    1759                 }
    1760         }
    1761 
    1762         /**
    1763          * Checks if an activity item can be replied to.
    1764          *
    1765          * This method merges functionality from {@link bp_activity_can_comment()} and
    1766          * {@link bp_blogs_disable_activity_commenting()}. This is done because the activity
    1767          * list table doesn't use a BuddyPress activity loop, which prevents those
    1768          * functions from working as intended.
    1769          *
    1770          * @since 2.0.0
    1771          *
    1772          * @param array $item An array version of the BP_Activity_Activity object.
    1773          * @return bool $can_comment
    1774          */
    1775         protected function can_comment( $item  ) {
    1776                 $can_comment = true;
    1777 
    1778                 if ( $this->disable_blogforum_comments ) {
    1779                         switch ( $item['type'] ) {
    1780                                 case 'new_blog_post' :
    1781                                 case 'new_blog_comment' :
    1782                                 case 'new_forum_topic' :
    1783                                 case 'new_forum_post' :
    1784                                         $can_comment = false;
    1785                                         break;
    1786                         }
    1787 
    1788                 // Activity comments supported.
    1789                 } else {
    1790                         // Activity comment.
    1791                         if ( 'activity_comment' == $item['type'] ) {
    1792                                 // Blogs.
    1793                                 if ( bp_is_active( 'blogs' ) ) {
    1794                                         // Grab the parent activity entry.
    1795                                         $parent_activity = new BP_Activity_Activity( $item['item_id'] );
    1796 
    1797                                         // Fetch blog post comment depth and if the blog post's comments are open.
    1798                                         bp_blogs_setup_activity_loop_globals( $parent_activity );
    1799 
    1800                                         // Check if the activity item can be replied to.
    1801                                         if ( false === bp_blogs_can_comment_reply( true, $item ) ) {
    1802                                                 $can_comment = false;
    1803                                         }
    1804                                 }
    1805 
    1806                         // Blog post.
    1807                         } elseif ( 'new_blog_post' == $item['type'] ) {
    1808                                 if ( bp_is_active( 'blogs' ) ) {
    1809                                         bp_blogs_setup_activity_loop_globals( (object) $item );
    1810 
    1811                                         if ( empty( buddypress()->blogs->allow_comments[$item['id']] ) ) {
    1812                                                 $can_comment = false;
    1813                                         }
    1814                                 }
    1815                         }
    1816                 }
    1817 
    1818                 /**
    1819                  * Filters if an activity item can be commented on or not.
    1820                  *
    1821                  * @since 2.0.0
    1822                  *
    1823                  * @param bool $can_comment Whether an activity item can be commented on or not.
    1824                  */
    1825                 return apply_filters( 'bp_activity_list_table_can_comment', $can_comment );
    1826         }
    1827 
    1828         /**
    1829          * Flatten the activity array.
    1830          *
    1831          * In some cases, BuddyPress gives us a structured tree of activity
    1832          * items plus their comments. This method converts it to a flat array.
    1833          *
    1834          * @since 1.6.0
    1835          *
    1836          * @param array $tree Source array.
    1837          * @return array Flattened array.
    1838          */
    1839         public static function flatten_activity_array( $tree ){
    1840                 foreach ( (array) $tree as $node ) {
    1841                         if ( isset( $node->children ) ) {
    1842 
    1843                                 foreach ( BP_Activity_List_Table::flatten_activity_array( $node->children ) as $child ) {
    1844                                         $tree[] = $child;
    1845                                 }
    1846 
    1847                                 unset( $node->children );
    1848                         }
    1849                 }
    1850 
    1851                 return $tree;
    1852         }
    1853 }
  • src/bp-activity/bp-activity-akismet.php

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

     
    1212// Exit if accessed directly.
    1313defined( 'ABSPATH' ) || exit;
    1414
    15 /**
    16  * Main Activity Class.
    17  *
    18  * @since 1.5.0
    19  */
    20 class BP_Activity_Component extends BP_Component {
     15require dirname( __FILE__ ) . '/classes/class-bp-activity-loader.php';
    2116
    22         /**
    23          * Start the activity component setup process.
    24          *
    25          * @since 1.5.0
    26          */
    27         public function __construct() {
    28                 parent::start(
    29                         'activity',
    30                         __( 'Activity Streams', 'buddypress' ),
    31                         buddypress()->plugin_dir,
    32                         array(
    33                                 'adminbar_myaccount_order' => 10,
    34                                 'search_query_arg' => 'activity_search',
    35                         )
    36                 );
    37         }
    38 
    39         /**
    40          * Include component files.
    41          *
    42          * @since 1.5.0
    43          *
    44          * @see BP_Component::includes() for a description of arguments.
    45          *
    46          * @param array $includes See BP_Component::includes() for a description.
    47          */
    48         public function includes( $includes = array() ) {
    49 
    50                 // Files to include.
    51                 $includes = array(
    52                         'cssjs',
    53                         'actions',
    54                         'screens',
    55                         'filters',
    56                         'classes',
    57                         'template',
    58                         'functions',
    59                         'notifications',
    60                         'cache'
    61                 );
    62 
    63                 // Load Akismet support if Akismet is configured.
    64                 $akismet_key = bp_get_option( 'wordpress_api_key' );
    65 
    66                 /** This filter is documented in bp-activity/bp-activity-actions.php */
    67                 if ( defined( 'AKISMET_VERSION' ) && class_exists( 'Akismet' ) && ( ! empty( $akismet_key ) || defined( 'WPCOM_API_KEY' ) ) && apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) ) {
    68                         $includes[] = 'akismet';
    69                 }
    70 
    71                 if ( is_admin() ) {
    72                         $includes[] = 'admin';
    73                 }
    74 
    75                 parent::includes( $includes );
    76         }
    77 
    78         /**
    79          * Set up component global variables.
    80          *
    81          * The BP_ACTIVITY_SLUG constant is deprecated, and only used here for
    82          * backwards compatibility.
    83          *
    84          * @since 1.5.0
    85          *
    86          * @see BP_Component::setup_globals() for a description of arguments.
    87          *
    88          * @param array $args See BP_Component::setup_globals() for a description.
    89          */
    90         public function setup_globals( $args = array() ) {
    91                 $bp = buddypress();
    92 
    93                 // Define a slug, if necessary.
    94                 if ( ! defined( 'BP_ACTIVITY_SLUG' ) ) {
    95                         define( 'BP_ACTIVITY_SLUG', $this->id );
    96                 }
    97 
    98                 // Global tables for activity component.
    99                 $global_tables = array(
    100                         'table_name'      => $bp->table_prefix . 'bp_activity',
    101                         'table_name_meta' => $bp->table_prefix . 'bp_activity_meta',
    102                 );
    103 
    104                 // Metadata tables for groups component.
    105                 $meta_tables = array(
    106                         'activity' => $bp->table_prefix . 'bp_activity_meta',
    107                 );
    108 
    109                 // All globals for activity component.
    110                 // Note that global_tables is included in this array.
    111                 $args = array(
    112                         'slug'                  => BP_ACTIVITY_SLUG,
    113                         'root_slug'             => isset( $bp->pages->activity->slug ) ? $bp->pages->activity->slug : BP_ACTIVITY_SLUG,
    114                         'has_directory'         => true,
    115                         'directory_title'       => _x( 'Site-Wide Activity', 'component directory title', 'buddypress' ),
    116                         'notification_callback' => 'bp_activity_format_notifications',
    117                         'search_string'         => __( 'Search Activity...', 'buddypress' ),
    118                         'global_tables'         => $global_tables,
    119                         'meta_tables'           => $meta_tables,
    120                 );
    121 
    122                 parent::setup_globals( $args );
    123         }
    124 
    125         /**
    126          * Set up component navigation.
    127          *
    128          * @since 1.5.0
    129          *
    130          * @see BP_Component::setup_nav() for a description of arguments.
    131          * @uses bp_is_active()
    132          * @uses is_user_logged_in()
    133          * @uses bp_get_friends_slug()
    134          * @uses bp_get_groups_slug()
    135          *
    136          * @param array $main_nav Optional. See BP_Component::setup_nav() for description.
    137          * @param array $sub_nav  Optional. See BP_Component::setup_nav() for description.
    138          */
    139         public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
    140 
    141                 // Stop if there is no user displayed or logged in.
    142                 if ( ! is_user_logged_in() && ! bp_displayed_user_id() ) {
    143                         return;
    144                 }
    145 
    146                 // Determine user to use.
    147                 if ( bp_displayed_user_domain() ) {
    148                         $user_domain = bp_displayed_user_domain();
    149                 } elseif ( bp_loggedin_user_domain() ) {
    150                         $user_domain = bp_loggedin_user_domain();
    151                 } else {
    152                         return;
    153                 }
    154 
    155                 $slug          = bp_get_activity_slug();
    156                 $activity_link = trailingslashit( $user_domain . $slug );
    157 
    158                 // Add 'Activity' to the main navigation.
    159                 $main_nav = array(
    160                         'name'                => _x( 'Activity', 'Profile activity screen nav', 'buddypress' ),
    161                         'slug'                => $slug,
    162                         'position'            => 10,
    163                         'screen_function'     => 'bp_activity_screen_my_activity',
    164                         'default_subnav_slug' => 'just-me',
    165                         'item_css_id'         => $this->id
    166                 );
    167 
    168                 // Add the subnav items to the activity nav item if we are using a theme that supports this.
    169                 $sub_nav[] = array(
    170                         'name'            => _x( 'Personal', 'Profile activity screen sub nav', 'buddypress' ),
    171                         'slug'            => 'just-me',
    172                         'parent_url'      => $activity_link,
    173                         'parent_slug'     => $slug,
    174                         'screen_function' => 'bp_activity_screen_my_activity',
    175                         'position'        => 10
    176                 );
    177 
    178                 // Check @mentions.
    179                 if ( bp_activity_do_mentions() ) {
    180                         $sub_nav[] = array(
    181                                 'name'            => _x( 'Mentions', 'Profile activity screen sub nav', 'buddypress' ),
    182                                 'slug'            => 'mentions',
    183                                 'parent_url'      => $activity_link,
    184                                 'parent_slug'     => $slug,
    185                                 'screen_function' => 'bp_activity_screen_mentions',
    186                                 'position'        => 20,
    187                                 'item_css_id'     => 'activity-mentions'
    188                         );
    189                 }
    190 
    191                 // Favorite activity items.
    192                 if ( bp_activity_can_favorite() ) {
    193                         $sub_nav[] = array(
    194                                 'name'            => _x( 'Favorites', 'Profile activity screen sub nav', 'buddypress' ),
    195                                 'slug'            => 'favorites',
    196                                 'parent_url'      => $activity_link,
    197                                 'parent_slug'     => $slug,
    198                                 'screen_function' => 'bp_activity_screen_favorites',
    199                                 'position'        => 30,
    200                                 'item_css_id'     => 'activity-favs'
    201                         );
    202                 }
    203 
    204                 // Additional menu if friends is active.
    205                 if ( bp_is_active( 'friends' ) ) {
    206                         $sub_nav[] = array(
    207                                 'name'            => _x( 'Friends', 'Profile activity screen sub nav', 'buddypress' ),
    208                                 'slug'            => bp_get_friends_slug(),
    209                                 'parent_url'      => $activity_link,
    210                                 'parent_slug'     => $slug,
    211                                 'screen_function' => 'bp_activity_screen_friends',
    212                                 'position'        => 40,
    213                                 'item_css_id'     => 'activity-friends'
    214                         ) ;
    215                 }
    216 
    217                 // Additional menu if groups is active.
    218                 if ( bp_is_active( 'groups' ) ) {
    219                         $sub_nav[] = array(
    220                                 'name'            => _x( 'Groups', 'Profile activity screen sub nav', 'buddypress' ),
    221                                 'slug'            => bp_get_groups_slug(),
    222                                 'parent_url'      => $activity_link,
    223                                 'parent_slug'     => $slug,
    224                                 'screen_function' => 'bp_activity_screen_groups',
    225                                 'position'        => 50,
    226                                 'item_css_id'     => 'activity-groups'
    227                         );
    228                 }
    229 
    230                 parent::setup_nav( $main_nav, $sub_nav );
    231         }
    232 
    233         /**
    234          * Set up the component entries in the WordPress Admin Bar.
    235          *
    236          * @since 1.5.0
    237          *
    238          * @see BP_Component::setup_nav() for a description of the $wp_admin_nav
    239          *      parameter array.
    240          * @uses is_user_logged_in()
    241          * @uses trailingslashit()
    242          * @uses bp_get_total_mention_count_for_user()
    243          * @uses bp_loggedin_user_id()
    244          * @uses bp_is_active()
    245          * @uses bp_get_friends_slug()
    246          * @uses bp_get_groups_slug()
    247          *
    248          * @param array $wp_admin_nav See BP_Component::setup_admin_bar() for a
    249          *                            description.
    250          */
    251         public function setup_admin_bar( $wp_admin_nav = array() ) {
    252 
    253                 // Menus for logged in user.
    254                 if ( is_user_logged_in() ) {
    255 
    256                         // Setup the logged in user variables.
    257                         $activity_link = trailingslashit( bp_loggedin_user_domain() . bp_get_activity_slug() );
    258 
    259                         // Unread message count.
    260                         if ( bp_activity_do_mentions() ) {
    261                                 $count = bp_get_total_mention_count_for_user( bp_loggedin_user_id() );
    262                                 if ( !empty( $count ) ) {
    263                                         $title = sprintf( _x( 'Mentions <span class="count">%s</span>', 'Toolbar Mention logged in user', 'buddypress' ), bp_core_number_format( $count ) );
    264                                 } else {
    265                                         $title = _x( 'Mentions', 'Toolbar Mention logged in user', 'buddypress' );
    266                                 }
    267                         }
    268 
    269                         // Add the "Activity" sub menu.
    270                         $wp_admin_nav[] = array(
    271                                 'parent' => buddypress()->my_account_menu_id,
    272                                 'id'     => 'my-account-' . $this->id,
    273                                 'title'  => _x( 'Activity', 'My Account Activity sub nav', 'buddypress' ),
    274                                 'href'   => $activity_link
    275                         );
    276 
    277                         // Personal.
    278                         $wp_admin_nav[] = array(
    279                                 'parent' => 'my-account-' . $this->id,
    280                                 'id'     => 'my-account-' . $this->id . '-personal',
    281                                 'title'  => _x( 'Personal', 'My Account Activity sub nav', 'buddypress' ),
    282                                 'href'   => $activity_link
    283                         );
    284 
    285                         // Mentions.
    286                         if ( bp_activity_do_mentions() ) {
    287                                 $wp_admin_nav[] = array(
    288                                         'parent' => 'my-account-' . $this->id,
    289                                         'id'     => 'my-account-' . $this->id . '-mentions',
    290                                         'title'  => $title,
    291                                         'href'   => trailingslashit( $activity_link . 'mentions' )
    292                                 );
    293                         }
    294 
    295                         // Favorite activity items.
    296                         if ( bp_activity_can_favorite() ) {
    297                                 $wp_admin_nav[] = array(
    298                                         'parent' => 'my-account-' . $this->id,
    299                                         'id'     => 'my-account-' . $this->id . '-favorites',
    300                                         'title'  => _x( 'Favorites', 'My Account Activity sub nav', 'buddypress' ),
    301                                         'href'   => trailingslashit( $activity_link . 'favorites' )
    302                                 );
    303                         }
    304 
    305                         // Friends?
    306                         if ( bp_is_active( 'friends' ) ) {
    307                                 $wp_admin_nav[] = array(
    308                                         'parent' => 'my-account-' . $this->id,
    309                                         'id'     => 'my-account-' . $this->id . '-friends',
    310                                         'title'  => _x( 'Friends', 'My Account Activity sub nav', 'buddypress' ),
    311                                         'href'   => trailingslashit( $activity_link . bp_get_friends_slug() )
    312                                 );
    313                         }
    314 
    315                         // Groups?
    316                         if ( bp_is_active( 'groups' ) ) {
    317                                 $wp_admin_nav[] = array(
    318                                         'parent' => 'my-account-' . $this->id,
    319                                         'id'     => 'my-account-' . $this->id . '-groups',
    320                                         'title'  => _x( 'Groups', 'My Account Activity sub nav', 'buddypress' ),
    321                                         'href'   => trailingslashit( $activity_link . bp_get_groups_slug() )
    322                                 );
    323                         }
    324                 }
    325 
    326                 parent::setup_admin_bar( $wp_admin_nav );
    327         }
    328 
    329         /**
    330          * Set up the title for pages and <title>.
    331          *
    332          * @since 1.5.0
    333          *
    334          * @uses bp_is_activity_component()
    335          * @uses bp_is_my_profile()
    336          * @uses bp_core_fetch_avatar()
    337          */
    338         public function setup_title() {
    339 
    340                 // Adjust title based on view.
    341                 if ( bp_is_activity_component() ) {
    342                         $bp = buddypress();
    343 
    344                         if ( bp_is_my_profile() ) {
    345                                 $bp->bp_options_title = _x( 'My Activity', 'Page and <title>', 'buddypress' );
    346                         } else {
    347                                 $bp->bp_options_avatar = bp_core_fetch_avatar( array(
    348                                         'item_id' => bp_displayed_user_id(),
    349                                         'type'    => 'thumb',
    350                                         'alt'     => sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_get_displayed_user_fullname() )
    351                                 ) );
    352                                 $bp->bp_options_title  = bp_get_displayed_user_fullname();
    353                         }
    354                 }
    355 
    356                 parent::setup_title();
    357         }
    358 
    359         /**
    360          * Set up actions necessary for the component.
    361          *
    362          * @since 1.6.0
    363          */
    364         public function setup_actions() {
    365 
    366                 // Spam prevention.
    367                 add_action( 'bp_include', 'bp_activity_setup_akismet' );
    368 
    369                 parent::setup_actions();
    370         }
    371 
    372         /**
    373          * Setup cache groups.
    374          *
    375          * @since 2.2.0
    376          */
    377         public function setup_cache_groups() {
    378 
    379                 // Global groups.
    380                 wp_cache_add_global_groups( array(
    381                         'bp_activity',
    382                         'bp_activity_comments',
    383                         'activity_meta'
    384                 ) );
    385 
    386                 parent::setup_cache_groups();
    387         }
    388 }
    389 
    39017/**
    39118 * Bootstrap the Activity component.
    39219 *
  • src/bp-activity/bp-activity-screens.php

     
    1414// Exit if accessed directly.
    1515defined( 'ABSPATH' ) || exit;
    1616
     17require dirname( __FILE__ ) . '/classes/class-bp-activity-theme-compat.php';
     18
    1719/**
    1820 * Load the Activity directory.
    1921 *
     
    416418
    417419/** Theme Compatibility *******************************************************/
    418420
    419 /**
    420  * The main theme compat class for BuddyPress Activity.
    421  *
    422  * This class sets up the necessary theme compatibility actions to safely output
    423  * activity template parts to the_title and the_content areas of a theme.
    424  *
    425  * @since 1.7.0
    426  */
    427 class BP_Activity_Theme_Compat {
    428 
    429         /**
    430          * Set up the activity component theme compatibility.
    431          *
    432          * @since 1.7.0
    433          */
    434         public function __construct() {
    435                 add_action( 'bp_setup_theme_compat', array( $this, 'is_activity' ) );
    436         }
    437 
    438         /**
    439          * Set up the theme compatibility hooks, if we're looking at an activity page.
    440          *
    441          * @since 1.7.0
    442          */
    443         public function is_activity() {
    444 
    445                 // Bail if not looking at a group.
    446                 if ( ! bp_is_activity_component() )
    447                         return;
    448 
    449                 // Activity Directory.
    450                 if ( ! bp_displayed_user_id() && ! bp_current_action() ) {
    451                         bp_update_is_directory( true, 'activity' );
    452 
    453                         /** This action is documented in bp-activity/bp-activity-screens.php */
    454                         do_action( 'bp_activity_screen_index' );
    455 
    456                         add_filter( 'bp_get_buddypress_template',                array( $this, 'directory_template_hierarchy' ) );
    457                         add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'directory_dummy_post' ) );
    458                         add_filter( 'bp_replace_the_content',                    array( $this, 'directory_content'    ) );
    459 
    460                 // Single activity.
    461                 } elseif ( bp_is_single_activity() ) {
    462                         add_filter( 'bp_get_buddypress_template',                array( $this, 'single_template_hierarchy' ) );
    463                         add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'single_dummy_post' ) );
    464                         add_filter( 'bp_replace_the_content',                    array( $this, 'single_dummy_content'    ) );
    465                 }
    466         }
    467 
    468         /** Directory *************************************************************/
    469 
    470         /**
    471          * Add template hierarchy to theme compat for the activity directory page.
    472          *
    473          * This is to mirror how WordPress has {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
    474          *
    475          * @since 1.8.0
    476          *
    477          * @param string $templates The templates from bp_get_theme_compat_templates().
    478          * @return array $templates Array of custom templates to look for.
    479          */
    480         public function directory_template_hierarchy( $templates ) {
    481 
    482                 /**
    483                  * Filters the template hierarchy for the activity directory page.
    484                  *
    485                  * @since 1.8.0
    486                  *
    487                  * @param array $index-directory Array holding template names to be merged into template list.
    488                  */
    489                 $new_templates = apply_filters( 'bp_template_hierarchy_activity_directory', array(
    490                         'activity/index-directory.php'
    491                 ) );
    492 
    493                 // Merge new templates with existing stack
    494                 // @see bp_get_theme_compat_templates().
    495                 $templates = array_merge( (array) $new_templates, $templates );
    496 
    497                 return $templates;
    498         }
    499 
    500         /**
    501          * Update the global $post with directory data.
    502          *
    503          * @since 1.7.0
    504          */
    505         public function directory_dummy_post() {
    506                 bp_theme_compat_reset_post( array(
    507                         'ID'             => 0,
    508                         'post_title'     => bp_get_directory_title( 'activity' ),
    509                         'post_author'    => 0,
    510                         'post_date'      => 0,
    511                         'post_content'   => '',
    512                         'post_type'      => 'page',
    513                         'post_status'    => 'publish',
    514                         'is_page'        => true,
    515                         'comment_status' => 'closed'
    516                 ) );
    517         }
    518 
    519         /**
    520          * Filter the_content with the groups index template part.
    521          *
    522          * @since 1.7.0
    523          */
    524         public function directory_content() {
    525                 return bp_buffer_template_part( 'activity/index', null, false );
    526         }
    527 
    528         /** Single ****************************************************************/
    529 
    530         /**
    531          * Add custom template hierarchy to theme compat for activity permalink pages.
    532          *
    533          * This is to mirror how WordPress has {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
    534          *
    535          * @since 1.8.0
    536          *
    537          * @param string $templates The templates from bp_get_theme_compat_templates().
    538          * @return array $templates Array of custom templates to look for.
    539          */
    540         public function single_template_hierarchy( $templates ) {
    541 
    542                 /**
    543                  * Filters the template hierarchy for the activity permalink pages.
    544                  *
    545                  * @since 1.8.0
    546                  *
    547                  * @param array $index Array holding template names to be merged into template list.
    548                  */
    549                 $new_templates = apply_filters( 'bp_template_hierarchy_activity_single_item', array(
    550                         'activity/single/index.php'
    551                 ) );
    552 
    553                 // Merge new templates with existing stack
    554                 // @see bp_get_theme_compat_templates().
    555                 $templates = array_merge( (array) $new_templates, $templates );
    556 
    557                 return $templates;
    558         }
    559 
    560         /**
    561          * Update the global $post with the displayed user's data.
    562          *
    563          * @since 1.7.0
    564          */
    565         public function single_dummy_post() {
    566                 bp_theme_compat_reset_post( array(
    567                         'ID'             => 0,
    568                         'post_title'     => __( 'Activity', 'buddypress' ),
    569                         'post_author'    => 0,
    570                         'post_date'      => 0,
    571                         'post_content'   => '',
    572                         'post_type'      => 'page',
    573                         'post_status'    => 'publish',
    574                         'is_page'        => true,
    575                         'comment_status' => 'closed'
    576                 ) );
    577         }
    578 
    579         /**
    580          * Filter the_content with the members' activity permalink template part.
    581          *
    582          * @since 1.7.0
    583          */
    584         public function single_dummy_content() {
    585                 return bp_buffer_template_part( 'activity/single/home', null, false );
    586         }
    587 }
    588421new BP_Activity_Theme_Compat();
  • src/bp-activity/bp-activity-template.php

     
    1010// Exit if accessed directly.
    1111defined( 'ABSPATH' ) || exit;
    1212
     13require dirname( __FILE__ ) . '/classes/class-bp-activity-template.php';
     14
    1315/**
    1416 * Output the activity component slug.
    1517 *
     
    107109        }
    108110
    109111/**
    110  * The main activity template loop class.
    111  *
    112  * This is responsible for loading a group of activity items and displaying them.
    113  *
    114  * @since 1.0.0
    115  */
    116 class BP_Activity_Template {
    117 
    118         /**
    119          * The loop iterator.
    120          *
    121          * @since 1.0.0
    122          * @var int
    123          */
    124         public $current_activity = -1;
    125 
    126         /**
    127          * The activity count.
    128          *
    129          * @since 1.0.0
    130          * @var int
    131          */
    132         public $activity_count;
    133 
    134         /**
    135          * The total activity count.
    136          *
    137          * @since 1.0.0
    138          * @var int
    139          */
    140         public $total_activity_count;
    141 
    142         /**
    143          * Array of activities located by the query.
    144          *
    145          * @since 1.0.0
    146          * @var array
    147          */
    148         public $activities;
    149 
    150         /**
    151          * The activity object currently being iterated on.
    152          *
    153          * @since 1.0.0
    154          * @var object
    155          */
    156         public $activity;
    157 
    158         /**
    159          * A flag for whether the loop is currently being iterated.
    160          *
    161          * @since 1.0.0
    162          * @var bool
    163          */
    164         public $in_the_loop;
    165 
    166         /**
    167          * URL parameter key for activity pagination. Default: 'acpage'.
    168          *
    169          * @since 2.1.0
    170          * @var string
    171          */
    172         public $pag_arg;
    173 
    174         /**
    175          * The page number being requested.
    176          *
    177          * @since 1.0.0
    178          * @var int
    179          */
    180         public $pag_page;
    181 
    182         /**
    183          * The number of items being requested per page.
    184          *
    185          * @since 1.0.0
    186          * @var int
    187          */
    188         public $pag_num;
    189 
    190         /**
    191          * An HTML string containing pagination links.
    192          *
    193          * @since 1.0.0
    194          * @var string
    195          */
    196         public $pag_links;
    197 
    198         /**
    199          * The displayed user's full name.
    200          *
    201          * @since 1.0.0
    202          * @var string
    203          */
    204         public $full_name;
    205 
    206         /**
    207          * Constructor method.
    208          *
    209          * The arguments passed to this class constructor are of the same
    210          * format as {@link BP_Activity_Activity::get()}.
    211          *
    212          * @since 1.5.0
    213          *
    214          * @see BP_Activity_Activity::get() for a description of the argument
    215          *      structure, as well as default values.
    216          *
    217          * @param array $args {
    218          *     Array of arguments. Supports all arguments from
    219          *     BP_Activity_Activity::get(), as well as 'page_arg' and
    220          *     'include'. Default values for 'per_page' and 'display_comments'
    221          *     differ from the originating function, and are described below.
    222          *     @type string      $page_arg         The string used as a query parameter in
    223          *                                         pagination links. Default: 'acpage'.
    224          *     @type array|bool  $include          Pass an array of activity IDs to
    225          *                                         retrieve only those items, or false to noop the 'include'
    226          *                                         parameter. 'include' differs from 'in' in that 'in' forms
    227          *                                         an IN clause that works in conjunction with other filters
    228          *                                         passed to the function, while 'include' is interpreted as
    229          *                                         an exact list of items to retrieve, which skips all other
    230          *                                         filter-related parameters. Default: false.
    231          *     @type int|bool    $per_page         Default: 20.
    232          *     @type string|bool $display_comments Default: 'threaded'.
    233          * }
    234          */
    235         public function __construct( $args ) {
    236                 $bp = buddypress();
    237 
    238                 // Backward compatibility with old method of passing arguments.
    239                 if ( !is_array( $args ) || func_num_args() > 1 ) {
    240                         _deprecated_argument( __METHOD__, '1.6', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
    241 
    242                         $old_args_keys = array(
    243                                 0 => 'page',
    244                                 1 => 'per_page',
    245                                 2 => 'max',
    246                                 3 => 'include',
    247                                 4 => 'sort',
    248                                 5 => 'filter',
    249                                 6 => 'search_terms',
    250                                 7 => 'display_comments',
    251                                 8 => 'show_hidden',
    252                                 9 => 'exclude',
    253                                 10 => 'in',
    254                                 11 => 'spam',
    255                                 12 => 'page_arg'
    256                         );
    257 
    258                         $func_args = func_get_args();
    259                         $args = bp_core_parse_args_array( $old_args_keys, $func_args );
    260                 }
    261 
    262                 $defaults = array(
    263                         'page'              => 1,
    264                         'per_page'          => 20,
    265                         'page_arg'          => 'acpage',
    266                         'max'               => false,
    267                         'fields'            => 'all',
    268                         'count_total'       => false,
    269                         'sort'              => false,
    270                         'include'           => false,
    271                         'exclude'           => false,
    272                         'in'                => false,
    273                         'filter'            => false,
    274                         'scope'             => false,
    275                         'search_terms'      => false,
    276                         'meta_query'        => false,
    277                         'date_query'        => false,
    278                         'filter_query'      => false,
    279                         'display_comments'  => 'threaded',
    280                         'show_hidden'       => false,
    281                         'spam'              => 'ham_only',
    282                         'update_meta_cache' => true,
    283                 );
    284                 $r = wp_parse_args( $args, $defaults );
    285                 extract( $r );
    286 
    287                 $this->pag_arg  = sanitize_key( $r['page_arg'] );
    288                 $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page']     );
    289                 $this->pag_num  = bp_sanitize_pagination_arg( 'num',          $r['per_page'] );
    290 
    291                 // Check if blog/forum replies are disabled.
    292                 $this->disable_blogforum_replies = (bool) bp_core_get_root_option( 'bp-disable-blogforum-comments' );
    293 
    294                 // Get an array of the logged in user's favorite activities.
    295                 $this->my_favs = maybe_unserialize( bp_get_user_meta( bp_loggedin_user_id(), 'bp_favorite_activities', true ) );
    296 
    297                 // Fetch specific activity items based on ID's.
    298                 if ( !empty( $include ) ) {
    299                         $this->activities = bp_activity_get_specific( array(
    300                                 'activity_ids'      => explode( ',', $include ),
    301                                 'max'               => $max,
    302                                 'count_total'       => $count_total,
    303                                 'page'              => $this->pag_page,
    304                                 'per_page'          => $this->pag_num,
    305                                 'sort'              => $sort,
    306                                 'display_comments'  => $display_comments,
    307                                 'show_hidden'       => $show_hidden,
    308                                 'spam'              => $spam,
    309                                 'update_meta_cache' => $update_meta_cache,
    310                         ) );
    311 
    312                 // Fetch all activity items.
    313                 } else {
    314                         $this->activities = bp_activity_get( array(
    315                                 'display_comments'  => $display_comments,
    316                                 'max'               => $max,
    317                                 'count_total'       => $count_total,
    318                                 'per_page'          => $this->pag_num,
    319                                 'page'              => $this->pag_page,
    320                                 'sort'              => $sort,
    321                                 'search_terms'      => $search_terms,
    322                                 'meta_query'        => $meta_query,
    323                                 'date_query'        => $date_query,
    324                                 'filter_query'      => $filter_query,
    325                                 'filter'            => $filter,
    326                                 'scope'             => $scope,
    327                                 'show_hidden'       => $show_hidden,
    328                                 'exclude'           => $exclude,
    329                                 'in'                => $in,
    330                                 'spam'              => $spam,
    331                                 'update_meta_cache' => $update_meta_cache,
    332                         ) );
    333                 }
    334 
    335                 // The total_activity_count property will be set only if a
    336                 // 'count_total' query has taken place.
    337                 if ( ! is_null( $this->activities['total'] ) ) {
    338                         if ( ! $max || $max >= (int) $this->activities['total'] ) {
    339                                 $this->total_activity_count = (int) $this->activities['total'];
    340                         } else {
    341                                 $this->total_activity_count = (int) $max;
    342                         }
    343                 }
    344 
    345                 $this->has_more_items = $this->activities['has_more_items'];
    346 
    347                 $this->activities = $this->activities['activities'];
    348 
    349                 if ( $max ) {
    350                         if ( $max >= count($this->activities) ) {
    351                                 $this->activity_count = count( $this->activities );
    352                         } else {
    353                                 $this->activity_count = (int) $max;
    354                         }
    355                 } else {
    356                         $this->activity_count = count( $this->activities );
    357                 }
    358 
    359                 $this->full_name = bp_get_displayed_user_fullname();
    360 
    361                 // Fetch parent content for activity comments so we do not have to query in the loop.
    362                 foreach ( (array) $this->activities as $activity ) {
    363                         if ( 'activity_comment' != $activity->type ) {
    364                                 continue;
    365                         }
    366 
    367                         $parent_ids[] = $activity->item_id;
    368                 }
    369 
    370                 if ( !empty( $parent_ids ) ) {
    371                         $activity_parents = bp_activity_get_specific( array( 'activity_ids' => $parent_ids ) );
    372                 }
    373 
    374                 if ( !empty( $activity_parents['activities'] ) ) {
    375                         foreach( $activity_parents['activities'] as $parent ) {
    376                                 $this->activity_parents[$parent->id] = $parent;
    377                         }
    378 
    379                         unset( $activity_parents );
    380                 }
    381 
    382                 if ( (int) $this->total_activity_count && (int) $this->pag_num ) {
    383                         $this->pag_links = paginate_links( array(
    384                                 'base'      => add_query_arg( $this->pag_arg, '%#%' ),
    385                                 'format'    => '',
    386                                 'total'     => ceil( (int) $this->total_activity_count / (int) $this->pag_num ),
    387                                 'current'   => (int) $this->pag_page,
    388                                 'prev_text' => _x( '&larr;', 'Activity pagination previous text', 'buddypress' ),
    389                                 'next_text' => _x( '&rarr;', 'Activity pagination next text', 'buddypress' ),
    390                                 'mid_size'  => 1,
    391                                 'add_args'  => array(),
    392                         ) );
    393                 }
    394         }
    395 
    396         /**
    397          * Whether there are activity items available in the loop.
    398          *
    399          * @since 1.0.0
    400          *
    401          * @see bp_has_activities()
    402          *
    403          * @return bool True if there are items in the loop, otherwise false.
    404          */
    405         function has_activities() {
    406                 if ( $this->activity_count ) {
    407                         return true;
    408                 }
    409 
    410                 return false;
    411         }
    412 
    413         /**
    414          * Set up the next activity item and iterate index.
    415          *
    416          * @since 1.0.0
    417          *
    418          * @return object The next activity item to iterate over.
    419          */
    420         public function next_activity() {
    421                 $this->current_activity++;
    422                 $this->activity = $this->activities[ $this->current_activity ];
    423 
    424                 return $this->activity;
    425         }
    426 
    427         /**
    428          * Rewind the posts and reset post index.
    429          *
    430          * @since 1.0.0
    431          */
    432         public function rewind_activities() {
    433                 $this->current_activity = -1;
    434                 if ( $this->activity_count > 0 ) {
    435                         $this->activity = $this->activities[0];
    436                 }
    437         }
    438 
    439         /**
    440          * Whether there are activity items left in the loop to iterate over.
    441          *
    442          * This method is used by {@link bp_activities()} as part of the while loop
    443          * that controls iteration inside the activities loop, eg:
    444          *     while ( bp_activities() ) { ...
    445          *
    446          * @since 1.0.0
    447          *
    448          * @see bp_activities()
    449          *
    450          * @return bool True if there are more activity items to show,
    451          *              otherwise false.
    452          */
    453         public function user_activities() {
    454                 if ( ( $this->current_activity + 1 ) < $this->activity_count ) {
    455                         return true;
    456                 } elseif ( ( $this->current_activity + 1 ) == $this->activity_count ) {
    457 
    458                         /**
    459                          * Fires right before the rewinding of activity posts.
    460                          *
    461                          * @since 1.1.0
    462                          */
    463                         do_action( 'activity_loop_end' );
    464 
    465                         // Do some cleaning up after the loop.
    466                         $this->rewind_activities();
    467                 }
    468 
    469                 $this->in_the_loop = false;
    470 
    471                 return false;
    472         }
    473 
    474         /**
    475          * Set up the current activity item inside the loop.
    476          *
    477          * Used by {@link bp_the_activity()} to set up the current activity item
    478          * data while looping, so that template tags used during that iteration
    479          * make reference to the current activity item.
    480          *
    481          * @since 1.0.0
    482          *
    483          * @see bp_the_activity()
    484          */
    485         public function the_activity() {
    486 
    487                 $this->in_the_loop = true;
    488                 $this->activity    = $this->next_activity();
    489 
    490                 if ( is_array( $this->activity ) ) {
    491                         $this->activity = (object) $this->activity;
    492                 }
    493 
    494                 // Loop has just started.
    495                 if ( $this->current_activity == 0 ) {
    496 
    497                         /**
    498                          * Fires if the current activity item is the first in the activity loop.
    499                          *
    500                          * @since 1.1.0
    501                          */
    502                         do_action('activity_loop_start');
    503                 }
    504         }
    505 }
    506 
    507 /**
    508112 * Initialize the activity loop.
    509113 *
    510114 * Based on the $args passed, bp_has_activities() populates the
  • src/bp-activity/classes/class-bp-activity-list-table.php

     
    11<?php
    2 /**
    3  * BuddyPress Activity component admin screen.
    4  *
    5  * Props to WordPress core for the Comments admin screen, and its contextual
    6  * help text, on which this implementation is heavily based.
    7  *
    8  * @package BuddyPress
    9  * @subpackage ActivityAdmin
    10  * @since 1.6.0
    11  */
    122
    13 // Exit if accessed directly.
    14 defined( 'ABSPATH' ) || exit;
    15 
    16 // Include WP's list table class.
    17 if ( !class_exists( 'WP_List_Table' ) ) require( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
    18 
    19 // Per_page screen option. Has to be hooked in extremely early.
    20 if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-activity' == $_REQUEST['page'] )
    21         add_filter( 'set-screen-option', 'bp_activity_admin_screen_options', 10, 3 );
    22 
    233/**
    24  * Register the Activity component admin screen.
    25  *
    26  * @since 1.6.0
    27  */
    28 function bp_activity_add_admin_menu() {
    29 
    30         // Add our screen.
    31         $hook = add_menu_page(
    32                 _x( 'Activity', 'Admin Dashbord SWA page title', 'buddypress' ),
    33                 _x( 'Activity', 'Admin Dashbord SWA menu', 'buddypress' ),
    34                 'bp_moderate',
    35                 'bp-activity',
    36                 'bp_activity_admin',
    37                 'div'
    38         );
    39 
    40         // Hook into early actions to load custom CSS and our init handler.
    41         add_action( "load-$hook", 'bp_activity_admin_load' );
    42 }
    43 add_action( bp_core_admin_hook(), 'bp_activity_add_admin_menu' );
    44 
    45 /**
    46  * Add activity component to custom menus array.
    47  *
    48  * Several BuddyPress components have top-level menu items in the Dashboard,
    49  * which all appear together in the middle of the Dashboard menu. This function
    50  * adds the Activity page to the array of these menu items.
    51  *
    52  * @since 1.7.0
    53  *
    54  * @param array $custom_menus The list of top-level BP menu items.
    55  * @return array $custom_menus List of top-level BP menu items, with Activity added.
    56  */
    57 function bp_activity_admin_menu_order( $custom_menus = array() ) {
    58         array_push( $custom_menus, 'bp-activity' );
    59         return $custom_menus;
    60 }
    61 add_filter( 'bp_admin_menu_order', 'bp_activity_admin_menu_order' );
    62 
    63 /**
    64  * AJAX receiver for Activity replies via the admin screen.
    65  *
    66  * Processes requests to add new activity comments, and echoes HTML for a new
    67  * table row.
    68  *
    69  * @since 1.6.0
    70  */
    71 function bp_activity_admin_reply() {
    72         // Check nonce.
    73         check_ajax_referer( 'bp-activity-admin-reply', '_ajax_nonce-bp-activity-admin-reply' );
    74 
    75         $parent_id = ! empty( $_REQUEST['parent_id'] ) ? (int) $_REQUEST['parent_id'] : 0;
    76         $root_id   = ! empty( $_REQUEST['root_id'] )   ? (int) $_REQUEST['root_id']   : 0;
    77 
    78         // $parent_id is required
    79         if ( empty( $parent_id ) )
    80                 die( '-1' );
    81 
    82         // If $root_id not set (e.g. for root items), use $parent_id.
    83         if ( empty( $root_id ) )
    84                 $root_id = $parent_id;
    85 
    86         // Check that a reply has been entered.
    87         if ( empty( $_REQUEST['content'] ) )
    88                 die( __( 'ERROR: Please type a reply.', 'buddypress' ) );
    89 
    90         // Check parent activity exists.
    91         $parent_activity = new BP_Activity_Activity( $parent_id );
    92         if ( empty( $parent_activity->component ) )
    93                 die( __( 'ERROR: The item you are trying to reply to cannot be found, or it has been deleted.', 'buddypress' ) );
    94 
    95         // @todo: Check if user is allowed to create new activity items
    96         // if ( ! current_user_can( 'bp_new_activity' ) )
    97         if ( ! current_user_can( 'bp_moderate' ) )
    98                 die( '-1' );
    99 
    100         // Add new activity comment.
    101         $new_activity_id = bp_activity_new_comment( array(
    102                 'activity_id' => $root_id,              // ID of the root activity item.
    103                 'content'     => $_REQUEST['content'],
    104                 'parent_id'   => $parent_id,            // ID of a parent comment.
    105         ) );
    106 
    107         // Fetch the new activity item, as we need it to create table markup to return.
    108         $new_activity = new BP_Activity_Activity( $new_activity_id );
    109 
    110         // This needs to be set for the BP_Activity_List_Table constructor to work.
    111         set_current_screen( 'toplevel_page_bp-activity' );
    112 
    113         // Set up an output buffer.
    114         ob_start();
    115         $list_table = new BP_Activity_List_Table();
    116         $list_table->single_row( (array) $new_activity );
    117 
    118         // Get table markup.
    119         $response =  array(
    120                 'data'     => ob_get_contents(),
    121                 'id'       => $new_activity_id,
    122                 'position' => -1,
    123                 'what'     => 'bp_activity',
    124         );
    125         ob_end_clean();
    126 
    127         // Send response.
    128         $r = new WP_Ajax_Response();
    129         $r->add( $response );
    130         $r->send();
    131 
    132         exit();
    133 }
    134 add_action( 'wp_ajax_bp-activity-admin-reply', 'bp_activity_admin_reply' );
    135 
    136 /**
    137  * Handle save/update of screen options for the Activity component admin screen.
    138  *
    139  * @since 1.6.0
    140  *
    141  * @param string $value     Will always be false unless another plugin filters it first.
    142  * @param string $option    Screen option name.
    143  * @param string $new_value Screen option form value.
    144  * @return string Option value. False to abandon update.
    145  */
    146 function bp_activity_admin_screen_options( $value, $option, $new_value ) {
    147         if ( 'toplevel_page_bp_activity_per_page' != $option && 'toplevel_page_bp_activity_network_per_page' != $option )
    148                 return $value;
    149 
    150         // Per page.
    151         $new_value = (int) $new_value;
    152         if ( $new_value < 1 || $new_value > 999 )
    153                 return $value;
    154 
    155         return $new_value;
    156 }
    157 
    158 /**
    159  * Hide the advanced edit meta boxes by default, so we don't clutter the screen.
    160  *
    161  * @since 1.6.0
    162  *
    163  * @param array     $hidden Array of items to hide.
    164  * @param WP_Screen $screen Screen identifier.
    165  * @return array Hidden Meta Boxes.
    166  */
    167 function bp_activity_admin_edit_hidden_metaboxes( $hidden, $screen ) {
    168         if ( empty( $screen->id ) || 'toplevel_page_bp-activity' != $screen->id && 'toplevel_page_bp-activity_network' != $screen->id )
    169                 return $hidden;
    170 
    171         // Hide the primary link meta box by default.
    172         $hidden  = array_merge( (array) $hidden, array( 'bp_activity_itemids', 'bp_activity_link', 'bp_activity_type', 'bp_activity_userid', ) );
    173 
    174         /**
    175          * Filters default hidden metaboxes so plugins can alter list.
    176          *
    177          * @since 1.6.0
    178          *
    179          * @param array     $hidden Default metaboxes to hide.
    180          * @param WP_Screen $screen Screen identifier.
    181          */
    182         return apply_filters( 'bp_hide_meta_boxes', array_unique( $hidden ), $screen );
    183 }
    184 add_filter( 'default_hidden_meta_boxes', 'bp_activity_admin_edit_hidden_metaboxes', 10, 2 );
    185 
    186 /**
    187  * Set up the Activity admin page.
    188  *
    189  * Does the following:
    190  *   - Register contextual help and screen options for this admin page.
    191  *   - Enqueues scripts and styles.
    192  *   - Catches POST and GET requests related to Activity.
    193  *
    194  * @since 1.6.0
    195  *
    196  * @global object                 $bp                     BuddyPress global settings.
    197  * @global BP_Activity_List_Table $bp_activity_list_table Activity screen list table.
    198  */
    199 function bp_activity_admin_load() {
    200         global $bp_activity_list_table;
    201 
    202         $bp = buddypress();
    203 
    204         // Decide whether to load the dev version of the CSS and JavaScript.
    205         $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : 'min.';
    206 
    207         $doaction = bp_admin_list_table_current_bulk_action();
    208 
    209         /**
    210          * Fires at top of Activity admin page.
    211          *
    212          * @since 1.6.0
    213          *
    214          * @param string $doaction Current $_GET action being performed in admin screen.
    215          */
    216         do_action( 'bp_activity_admin_load', $doaction );
    217 
    218         // Edit screen.
    219         if ( 'edit' == $doaction && ! empty( $_GET['aid'] ) ) {
    220                 // Columns screen option.
    221                 add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) );
    222 
    223                 get_current_screen()->add_help_tab( array(
    224                         'id'      => 'bp-activity-edit-overview',
    225                         'title'   => __( 'Overview', 'buddypress' ),
    226                         'content' =>
    227                                 '<p>' . __( 'You edit activities made on your site similar to the way you edit a comment. This is useful if you need to change which page the activity links to, or when you notice that the author has made a typographical error.', 'buddypress' ) . '</p>' .
    228                                 '<p>' . __( 'The two big editing areas for the activity title and content are fixed in place, but you can reposition all the other boxes using drag and drop, and can minimize or expand them by clicking the title bar of each box. Use the Screen Options tab to unhide more boxes (Primary Item/Secondary Item, Link, Type, Author ID) or to choose a 1- or 2-column layout for this screen.', 'buddypress' ) . '</p>' .
    229                                 '<p>' . __( 'You can also moderate the activity from this screen using the Status box, where you can also change the timestamp of the activity.', 'buddypress' ) . '</p>'
    230                 ) );
    231 
    232                 get_current_screen()->add_help_tab( array(
    233                         'id'      => 'bp-activity-edit-advanced',
    234                         'title'   => __( 'Item, Link, Type', 'buddypress' ),
    235                         'content' =>
    236                                 '<p>' . __( '<strong>Primary Item/Secondary Item</strong> - These identify the object that created the activity. For example, the fields could reference a comment left on a specific site. Some types of activity may only use one, or none, of these fields.', 'buddypress' ) . '</p>' .
    237                                 '<p>' . __( '<strong>Link</strong> - Used by some types of activity (e.g blog posts and comments, and forum topics and replies) to store a link back to the original content.', 'buddypress' ) . '</p>' .
    238                                 '<p>' . __( '<strong>Type</strong> - Each distinct kind of activity has its own type. For example, <code>created_group</code> is used when a group is created and <code>joined_group</code> is used when a user joins a group.', 'buddypress' ) . '</p>' .
    239                                 '<p>' . __( 'For information about when and how BuddyPress uses all of these settings, see the Managing Activity link in the panel to the side.', 'buddypress' ) . '</p>'
    240                 ) );
    241 
    242                 // Help panel - sidebar links.
    243                 get_current_screen()->set_help_sidebar(
    244                         '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
    245                         '<p>' . __( '<a href="https://codex.buddypress.org/administrator-guide/activity-stream-management-panels/">Managing Activity</a>', 'buddypress' ) . '</p>' .
    246                         '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
    247                 );
    248 
    249                 // Register metaboxes for the edit screen.
    250                 add_meta_box( 'submitdiv',           _x( 'Status', 'activity admin edit screen', 'buddypress' ), 'bp_activity_admin_edit_metabox_status', get_current_screen()->id, 'side', 'core' );
    251                 add_meta_box( 'bp_activity_itemids', _x( 'Primary Item/Secondary Item', 'activity admin edit screen', 'buddypress' ), 'bp_activity_admin_edit_metabox_itemids', get_current_screen()->id, 'normal', 'core' );
    252                 add_meta_box( 'bp_activity_link',    _x( 'Link', 'activity admin edit screen', 'buddypress' ), 'bp_activity_admin_edit_metabox_link', get_current_screen()->id, 'normal', 'core' );
    253                 add_meta_box( 'bp_activity_type',    _x( 'Type', 'activity admin edit screen', 'buddypress' ), 'bp_activity_admin_edit_metabox_type', get_current_screen()->id, 'normal', 'core' );
    254                 add_meta_box( 'bp_activity_userid',  _x( 'Author ID', 'activity admin edit screen', 'buddypress' ), 'bp_activity_admin_edit_metabox_userid', get_current_screen()->id, 'normal', 'core' );
    255 
    256                 /**
    257                  * Fires after the registration of all of the default activity meta boxes.
    258                  *
    259                  * @since 2.4.0
    260                  */
    261                 do_action( 'bp_activity_admin_meta_boxes' );
    262 
    263                 // Enqueue JavaScript files.
    264                 wp_enqueue_script( 'postbox' );
    265                 wp_enqueue_script( 'dashboard' );
    266                 wp_enqueue_script( 'comment' );
    267 
    268         // Index screen.
    269         } else {
    270                 // Create the Activity screen list table.
    271                 $bp_activity_list_table = new BP_Activity_List_Table();
    272 
    273                 // The per_page screen option.
    274                 add_screen_option( 'per_page', array( 'label' => _x( 'Activity', 'Activity items per page (screen options)', 'buddypress' )) );
    275 
    276                 // Help panel - overview text.
    277                 get_current_screen()->add_help_tab( array(
    278                         'id'      => 'bp-activity-overview',
    279                         'title'   => __( 'Overview', 'buddypress' ),
    280                         'content' =>
    281                                 '<p>' . __( 'You can manage activities made on your site similar to the way you manage comments and other content. This screen is customizable in the same ways as other management screens, and you can act on activities using the on-hover action links or the Bulk Actions.', 'buddypress' ) . '</p>' .
    282                                 '<p>' . __( 'There are many different types of activities. Some are generated automatically by BuddyPress and other plugins, and some are entered directly by a user in the form of status update. To help manage the different activity types, use the filter dropdown box to switch between them.', 'buddypress' ) . '</p>'
    283                 ) );
    284 
    285                 // Help panel - moderation text.
    286                 get_current_screen()->add_help_tab( array(
    287                         'id'            => 'bp-activity-moderating',
    288                         'title'         => __( 'Moderating Activity', 'buddypress' ),
    289                         'content'       =>
    290                                 '<p>' . __( 'In the <strong>Activity</strong> column, above each activity it says &#8220;Submitted on,&#8221; followed by the date and time the activity item was generated on your site. Clicking on the date/time link will take you to that activity on your live site. Hovering over any activity gives you options to reply, edit, spam mark, or delete that activity.', 'buddypress' ) . '</p>' .
    291                                 '<p>' . __( "In the <strong>In Response To</strong> column, if the activity was in reply to another activity, it shows that activity's author's picture and name, and a link to that activity on your live site. If there is a small bubble, the number in it shows how many other activities are related to this one; these are usually comments. Clicking the bubble will filter the activity screen to show only related activity items.", 'buddypress' ) . '</p>'
    292                 ) );
    293 
    294                 // Help panel - sidebar links.
    295                 get_current_screen()->set_help_sidebar(
    296                         '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
    297                         '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
    298                 );
    299 
    300                 // Add accessible hidden heading and text for Activity screen pagination.
    301                 if ( bp_get_major_wp_version() >= 4.4 ) {
    302                         get_current_screen()->set_screen_reader_content( array(
    303                                 'heading_pagination' => __( 'Activity list navigation', 'buddypress' ),
    304                         ) );
    305                 }
    306         }
    307 
    308         // Enqueue CSS and JavaScript.
    309         wp_enqueue_script( 'bp_activity_admin_js', $bp->plugin_url . "bp-activity/admin/js/admin.{$min}js",   array( 'jquery', 'wp-ajax-response' ), bp_get_version(), true );
    310         wp_localize_script( 'bp_activity_admin_js', 'bp_activity_admin_vars', array(
    311                 'page' => get_current_screen()->id
    312         ) );
    313         wp_enqueue_style( 'bp_activity_admin_css', $bp->plugin_url . "bp-activity/admin/css/admin.{$min}css", array(),                               bp_get_version()       );
    314 
    315         wp_style_add_data( 'bp_activity_admin_css', 'rtl', true );
    316         if ( $min ) {
    317                 wp_style_add_data( 'bp_activity_admin_css', 'suffix', $min );
    318         }
    319 
    320         /**
    321          * Fires after the activity js and style has been enqueued.
    322          *
    323          * @since 2.4.0
    324          */
    325         do_action( 'bp_activity_admin_enqueue_scripts' );
    326 
    327         // Handle spam/un-spam/delete of activities.
    328         if ( !empty( $doaction ) && ! in_array( $doaction, array( '-1', 'edit', 'save', ) ) ) {
    329 
    330                 // Build redirection URL.
    331                 $redirect_to = remove_query_arg( array( 'aid', 'deleted', 'error', 'spammed', 'unspammed', ), wp_get_referer() );
    332                 $redirect_to = add_query_arg( 'paged', $bp_activity_list_table->get_pagenum(), $redirect_to );
    333 
    334                 // Get activity IDs.
    335                 $activity_ids = array_map( 'absint', (array) $_REQUEST['aid'] );
    336 
    337                 /**
    338                  * Filters list of IDs being spammed/un-spammed/deleted.
    339                  *
    340                  * @since 1.6.0
    341                  *
    342                  * @param array $activity_ids Activity IDs to spam/un-spam/delete.
    343                  */
    344                 $activity_ids = apply_filters( 'bp_activity_admin_action_activity_ids', $activity_ids );
    345 
    346                 // Is this a bulk request?
    347                 if ( 'bulk_' == substr( $doaction, 0, 5 ) && ! empty( $_REQUEST['aid'] ) ) {
    348                         // Check this is a valid form submission.
    349                         check_admin_referer( 'bulk-activities' );
    350 
    351                         // Trim 'bulk_' off the action name to avoid duplicating a ton of code.
    352                         $doaction = substr( $doaction, 5 );
    353 
    354                 // This is a request to delete, spam, or un-spam, a single item.
    355                 } elseif ( !empty( $_REQUEST['aid'] ) ) {
    356 
    357                         // Check this is a valid form submission.
    358                         check_admin_referer( 'spam-activity_' . $activity_ids[0] );
    359                 }
    360 
    361                 // Initialise counters for how many of each type of item we perform an action on.
    362                 $deleted = $spammed = $unspammed = 0;
    363 
    364                 // Store any errors that occurs when updating the database items.
    365                 $errors = array();
    366 
    367                 // "We'd like to shoot the monster, could you move, please?"
    368                 foreach ( $activity_ids as $activity_id ) {
    369                         // @todo: Check the permissions on each
    370                         // if ( ! current_user_can( 'bp_edit_activity', $activity_id ) )
    371                         // continue;
    372                         // Get the activity from the database.
    373                         $activity = new BP_Activity_Activity( $activity_id );
    374                         if ( empty( $activity->component ) ) {
    375                                 $errors[] = $activity_id;
    376                                 continue;
    377                         }
    378 
    379                         switch ( $doaction ) {
    380                                 case 'delete' :
    381                                         if ( 'activity_comment' == $activity->type )
    382                                                 bp_activity_delete_comment( $activity->item_id, $activity->id );
    383                                         else
    384                                                 bp_activity_delete( array( 'id' => $activity->id ) );
    385 
    386                                         $deleted++;
    387                                         break;
    388 
    389                                 case 'ham' :
    390                                         /**
    391                                          * Remove moderation and blacklist checks in case we want to ham an activity
    392                                          * which contains one of these listed keys.
    393                                          */
    394                                         remove_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2, 1 );
    395                                         remove_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys',  2, 1 );
    396 
    397                                         bp_activity_mark_as_ham( $activity );
    398                                         $result = $activity->save();
    399 
    400                                         // Check for any error during activity save.
    401                                         if ( ! $result )
    402                                                 $errors[] = $activity->id;
    403                                         else
    404                                                 $unspammed++;
    405                                         break;
    406 
    407                                 case 'spam' :
    408                                         bp_activity_mark_as_spam( $activity );
    409                                         $result = $activity->save();
    410 
    411                                         // Check for any error during activity save.
    412                                         if ( ! $result )
    413                                                 $errors[] = $activity->id;
    414                                         else
    415                                                 $spammed++;
    416                                         break;
    417 
    418                                 default:
    419                                         break;
    420                         }
    421 
    422                         // Release memory.
    423                         unset( $activity );
    424                 }
    425 
    426                 /**
    427                  * Fires before redirect for plugins to do something with activity.
    428                  *
    429                  * Passes an activity array counts how many were spam, not spam, deleted, and IDs that were errors.
    430                  *
    431                  * @since 1.6.0
    432                  *
    433                  * @param array  $value        Array holding spam, not spam, deleted counts, error IDs.
    434                  * @param string $redirect_to  URL to redirect to.
    435                  * @param array  $activity_ids Original array of activity IDs.
    436                  */
    437                 do_action( 'bp_activity_admin_action_after', array( $spammed, $unspammed, $deleted, $errors ), $redirect_to, $activity_ids );
    438 
    439                 // Add arguments to the redirect URL so that on page reload, we can easily display what we've just done.
    440                 if ( $spammed )
    441                         $redirect_to = add_query_arg( 'spammed', $spammed, $redirect_to );
    442 
    443                 if ( $unspammed )
    444                         $redirect_to = add_query_arg( 'unspammed', $unspammed, $redirect_to );
    445 
    446                 if ( $deleted )
    447                         $redirect_to = add_query_arg( 'deleted', $deleted, $redirect_to );
    448 
    449                 // If an error occurred, pass back the activity ID that failed.
    450                 if ( ! empty( $errors ) )
    451                         $redirect_to = add_query_arg( 'error', implode ( ',', array_map( 'absint', $errors ) ), $redirect_to );
    452 
    453                 /**
    454                  * Filters redirect URL after activity spamming/un-spamming/deletion occurs.
    455                  *
    456                  * @since 1.6.0
    457                  *
    458                  * @param string $redirect_to URL to redirect to.
    459                  */
    460                 wp_redirect( apply_filters( 'bp_activity_admin_action_redirect', $redirect_to ) );
    461                 exit;
    462 
    463 
    464         // Save the edit.
    465         } elseif ( $doaction && 'save' == $doaction ) {
    466                 // Build redirection URL.
    467                 $redirect_to = remove_query_arg( array( 'action', 'aid', 'deleted', 'error', 'spammed', 'unspammed', ), $_SERVER['REQUEST_URI'] );
    468 
    469                 // Get activity ID.
    470                 $activity_id = (int) $_REQUEST['aid'];
    471 
    472                 // Check this is a valid form submission.
    473                 check_admin_referer( 'edit-activity_' . $activity_id );
    474 
    475                 // Get the activity from the database.
    476                 $activity = new BP_Activity_Activity( $activity_id );
    477 
    478                 // If the activity doesn't exist, just redirect back to the index.
    479                 if ( empty( $activity->component ) ) {
    480                         wp_redirect( $redirect_to );
    481                         exit;
    482                 }
    483 
    484                 // Check the form for the updated properties.
    485                 // Store any error that occurs when updating the database item.
    486                 $error = 0;
    487 
    488                 // Activity spam status.
    489                 $prev_spam_status = $new_spam_status = false;
    490                 if ( ! empty( $_POST['activity_status'] ) ) {
    491                         $prev_spam_status = $activity->is_spam;
    492                         $new_spam_status  = ( 'spam' == $_POST['activity_status'] ) ? true : false;
    493                 }
    494 
    495                 // Activity action.
    496                 if ( isset( $_POST['bp-activities-action'] ) )
    497                         $activity->action = $_POST['bp-activities-action'];
    498 
    499                 // Activity content.
    500                 if ( isset( $_POST['bp-activities-content'] ) )
    501                         $activity->content = $_POST['bp-activities-content'];
    502 
    503                 // Activity primary link.
    504                 if ( ! empty( $_POST['bp-activities-link'] ) )
    505                         $activity->primary_link = $_POST['bp-activities-link'];
    506 
    507                 // Activity user ID.
    508                 if ( ! empty( $_POST['bp-activities-userid'] ) )
    509                         $activity->user_id = (int) $_POST['bp-activities-userid'];
    510 
    511                 // Activity item primary ID.
    512                 if ( isset( $_POST['bp-activities-primaryid'] ) )
    513                         $activity->item_id = (int) $_POST['bp-activities-primaryid'];
    514 
    515                 // Activity item secondary ID.
    516                 if ( isset( $_POST['bp-activities-secondaryid'] ) )
    517                         $activity->secondary_item_id = (int) $_POST['bp-activities-secondaryid'];
    518 
    519                 // Activity type.
    520                 if ( ! empty( $_POST['bp-activities-type'] ) ) {
    521                         $actions = bp_activity_admin_get_activity_actions();
    522 
    523                         // Check that the new type is a registered activity type.
    524                         if ( in_array( $_POST['bp-activities-type'], $actions ) ) {
    525                                 $activity->type = $_POST['bp-activities-type'];
    526                         }
    527                 }
    528 
    529                 // Activity timestamp.
    530                 if ( ! empty( $_POST['aa'] ) && ! empty( $_POST['mm'] ) && ! empty( $_POST['jj'] ) && ! empty( $_POST['hh'] ) && ! empty( $_POST['mn'] ) && ! empty( $_POST['ss'] ) ) {
    531                         $aa = $_POST['aa'];
    532                         $mm = $_POST['mm'];
    533                         $jj = $_POST['jj'];
    534                         $hh = $_POST['hh'];
    535                         $mn = $_POST['mn'];
    536                         $ss = $_POST['ss'];
    537                         $aa = ( $aa <= 0 ) ? date( 'Y' ) : $aa;
    538                         $mm = ( $mm <= 0 ) ? date( 'n' ) : $mm;
    539                         $jj = ( $jj > 31 ) ? 31 : $jj;
    540                         $jj = ( $jj <= 0 ) ? date( 'j' ) : $jj;
    541                         $hh = ( $hh > 23 ) ? $hh -24 : $hh;
    542                         $mn = ( $mn > 59 ) ? $mn -60 : $mn;
    543                         $ss = ( $ss > 59 ) ? $ss -60 : $ss;
    544 
    545                         // Reconstruct the date into a timestamp.
    546                         $gmt_date = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
    547 
    548                         $activity->date_recorded = $gmt_date;
    549                 }
    550 
    551                 // Has the spam status has changed?
    552                 if ( $new_spam_status != $prev_spam_status ) {
    553                         if ( $new_spam_status )
    554                                 bp_activity_mark_as_spam( $activity );
    555                         else
    556                                 bp_activity_mark_as_ham( $activity );
    557                 }
    558 
    559                 // Save.
    560                 $result = $activity->save();
    561 
    562                 // Clear the activity stream first page cache, in case this activity's timestamp was changed.
    563                 wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
    564 
    565                 // Check for any error during activity save.
    566                 if ( false === $result )
    567                         $error = $activity->id;
    568 
    569                 /**
    570                  * Fires before redirect so plugins can do something first on save action.
    571                  *
    572                  * @since 1.6.0
    573                  *
    574                  * @param array $value Array holding activity object and ID that holds error.
    575                  */
    576                 do_action_ref_array( 'bp_activity_admin_edit_after', array( &$activity, $error ) );
    577 
    578                 // If an error occurred, pass back the activity ID that failed.
    579                 if ( $error )
    580                         $redirect_to = add_query_arg( 'error', (int) $error, $redirect_to );
    581                 else
    582                         $redirect_to = add_query_arg( 'updated', (int) $activity->id, $redirect_to );
    583 
    584                 /**
    585                  * Filters URL to redirect to after saving.
    586                  *
    587                  * @since 1.6.0
    588                  *
    589                  * @param string $redirect_to URL to redirect to.
    590                  */
    591                 wp_redirect( apply_filters( 'bp_activity_admin_edit_redirect', $redirect_to ) );
    592                 exit;
    593 
    594 
    595         // If a referrer and a nonce is supplied, but no action, redirect back.
    596         } elseif ( ! empty( $_GET['_wp_http_referer'] ) ) {
    597                 wp_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), stripslashes( $_SERVER['REQUEST_URI'] ) ) );
    598                 exit;
    599         }
    600 }
    601 
    602 /**
    603  * Output the Activity component admin screens.
    604  *
    605  * @since 1.6.0
    606  */
    607 function bp_activity_admin() {
    608         // Decide whether to load the index or edit screen.
    609         $doaction = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
    610 
    611         // Display the single activity edit screen.
    612         if ( 'edit' == $doaction && ! empty( $_GET['aid'] ) )
    613                 bp_activity_admin_edit();
    614 
    615         // Otherwise, display the Activity index screen.
    616         else
    617                 bp_activity_admin_index();
    618 }
    619 
    620 /**
    621  * Display the single activity edit screen.
    622  *
    623  * @since 1.6.0
    624  */
    625 function bp_activity_admin_edit() {
    626 
    627         // @todo: Check if user is allowed to edit activity items
    628         // if ( ! current_user_can( 'bp_edit_activity' ) )
    629         if ( ! is_super_admin() )
    630                 die( '-1' );
    631 
    632         // Get the activity from the database.
    633         $activity = bp_activity_get( array(
    634                 'in'               => ! empty( $_REQUEST['aid'] ) ? (int) $_REQUEST['aid'] : 0,
    635                 'max'              => 1,
    636                 'show_hidden'      => true,
    637                 'spam'             => 'all',
    638                 'display_comments' => 0
    639         ) );
    640 
    641         if ( ! empty( $activity['activities'][0] ) ) {
    642                 $activity = $activity['activities'][0];
    643 
    644                 // Workaround to use WP's touch_time() without duplicating that function.
    645                 $GLOBALS['comment'] = new stdClass;
    646                 $GLOBALS['comment']->comment_date = $activity->date_recorded;
    647         } else {
    648                 $activity = '';
    649         }
    650 
    651         // Construct URL for form.
    652         $form_url = remove_query_arg( array( 'action', 'deleted', 'error', 'spammed', 'unspammed', ), $_SERVER['REQUEST_URI'] );
    653         $form_url = add_query_arg( 'action', 'save', $form_url );
    654 
    655         /**
    656          * Fires before activity edit form is displays so plugins can modify the activity.
    657          *
    658          * @since 1.6.0
    659          *
    660          * @param array $value Array holding single activity object that was passed by reference.
    661          */
    662         do_action_ref_array( 'bp_activity_admin_edit', array( &$activity ) ); ?>
    663 
    664         <div class="wrap">
    665                 <h1><?php printf( __( 'Editing Activity (ID #%s)', 'buddypress' ), number_format_i18n( (int) $_REQUEST['aid'] ) ); ?></h1>
    666 
    667                 <?php if ( ! empty( $activity ) ) : ?>
    668 
    669                         <form action="<?php echo esc_url( $form_url ); ?>" id="bp-activities-edit-form" method="post">
    670                                 <div id="poststuff">
    671 
    672                                         <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
    673                                                 <div id="post-body-content">
    674                                                         <div id="postdiv">
    675                                                                 <div id="bp_activity_action" class="postbox">
    676                                                                         <h2><?php _e( 'Action', 'buddypress' ); ?></h2>
    677                                                                         <div class="inside">
    678                                                                                 <?php wp_editor( stripslashes( $activity->action ), 'bp-activities-action', array( 'media_buttons' => false, 'textarea_rows' => 7, 'teeny' => true, 'quicktags' => array( 'buttons' => 'strong,em,link,block,del,ins,img,code,spell,close' ) ) ); ?>
    679                                                                         </div>
    680                                                                 </div>
    681 
    682                                                                 <div id="bp_activity_content" class="postbox">
    683                                                                         <h2><?php _e( 'Content', 'buddypress' ); ?></h2>
    684                                                                         <div class="inside">
    685                                                                                 <?php wp_editor( stripslashes( $activity->content ), 'bp-activities-content', array( 'media_buttons' => false, 'teeny' => true, 'quicktags' => array( 'buttons' => 'strong,em,link,block,del,ins,img,code,spell,close' ) ) ); ?>
    686                                                                         </div>
    687                                                                 </div>
    688                                                         </div>
    689                                                 </div><!-- #post-body-content -->
    690 
    691                                                 <div id="postbox-container-1" class="postbox-container">
    692                                                         <?php do_meta_boxes( get_current_screen()->id, 'side', $activity ); ?>
    693                                                 </div>
    694 
    695                                                 <div id="postbox-container-2" class="postbox-container">
    696                                                         <?php do_meta_boxes( get_current_screen()->id, 'normal', $activity ); ?>
    697                                                         <?php do_meta_boxes( get_current_screen()->id, 'advanced', $activity ); ?>
    698                                                 </div>
    699                                         </div><!-- #post-body -->
    700 
    701                                 </div><!-- #poststuff -->
    702                                 <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
    703                                 <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
    704                                 <?php wp_nonce_field( 'edit-activity_' . $activity->id ); ?>
    705                         </form>
    706 
    707                 <?php else : ?>
    708                         <p>
    709                                 <?php _e( 'No activity found with this ID.', 'buddypress' ); ?>
    710                                 <a href="<?php echo esc_url( bp_get_admin_url( 'admin.php?page=bp-activity' ) ); ?>"><?php _e( 'Go back and try again.', 'buddypress' ); ?></a>
    711                         </p>
    712                 <?php endif; ?>
    713 
    714         </div><!-- .wrap -->
    715 
    716 <?php
    717 }
    718 
    719 /**
    720  * Status metabox for the Activity admin edit screen.
    721  *
    722  * @since 1.6.0
    723  *
    724  * @param object $item Activity item.
    725  */
    726 function bp_activity_admin_edit_metabox_status( $item ) {
    727 ?>
    728 
    729         <div class="submitbox" id="submitcomment">
    730 
    731                 <div id="minor-publishing">
    732                         <div id="minor-publishing-actions">
    733                                 <div id="preview-action">
    734                                         <a class="button preview" href="<?php echo esc_attr( bp_activity_get_permalink( $item->id, $item ) ); ?>" target="_blank"><?php _e( 'View Activity', 'buddypress' ); ?></a>
    735                                 </div>
    736 
    737                                 <div class="clear"></div>
    738                         </div><!-- #minor-publishing-actions -->
    739 
    740                         <div id="misc-publishing-actions">
    741                                 <div class="misc-pub-section" id="comment-status-radio">
    742                                         <label class="approved" for="activity-status-approved"><input type="radio" name="activity_status" id="activity-status-approved" value="ham" <?php checked( $item->is_spam, 0 ); ?>><?php _e( 'Approved', 'buddypress' ); ?></label><br />
    743                                         <label class="spam" for="activity-status-spam"><input type="radio" name="activity_status" id="activity-status-spam" value="spam" <?php checked( $item->is_spam, 1 ); ?>><?php _e( 'Spam', 'buddypress' ); ?></label>
    744                                 </div>
    745 
    746                                 <div class="misc-pub-section curtime misc-pub-section-last">
    747                                         <?php
    748                                         // Translators: Publish box date format, see http://php.net/date.
    749                                         $datef = __( 'M j, Y @ G:i', 'buddypress' );
    750                                         $date  = date_i18n( $datef, strtotime( $item->date_recorded ) );
    751                                         ?>
    752                                         <span id="timestamp"><?php printf( __( 'Submitted on: %s', 'buddypress' ), '<strong>' . $date . '</strong>' ); ?></span>&nbsp;<a href="#edit_timestamp" class="edit-timestamp hide-if-no-js" tabindex='4'><?php _e( 'Edit', 'buddypress' ); ?></a>
    753 
    754                                         <div id='timestampdiv' class='hide-if-js'>
    755                                                 <?php touch_time( 1, 0, 5 ); ?>
    756                                         </div><!-- #timestampdiv -->
    757                                 </div>
    758                         </div> <!-- #misc-publishing-actions -->
    759 
    760                         <div class="clear"></div>
    761                 </div><!-- #minor-publishing -->
    762 
    763                 <div id="major-publishing-actions">
    764                         <div id="publishing-action">
    765                                 <?php submit_button( __( 'Update', 'buddypress' ), 'primary', 'save', false ); ?>
    766                         </div>
    767                         <div class="clear"></div>
    768                 </div><!-- #major-publishing-actions -->
    769 
    770         </div><!-- #submitcomment -->
    771 
    772 <?php
    773 }
    774 
    775 /**
    776  * Primary link metabox for the Activity admin edit screen.
    777  *
    778  * @since 1.6.0
    779  *
    780  * @param object $item Activity item.
    781  */
    782 function bp_activity_admin_edit_metabox_link( $item ) {
    783 ?>
    784 
    785         <label class="screen-reader-text" for="bp-activities-link"><?php _e( 'Link', 'buddypress' ); ?></label>
    786         <input type="url" name="bp-activities-link" id="bp-activities-link" value="<?php echo esc_url( $item->primary_link ); ?>" aria-describedby="bp-activities-link-description" />
    787         <p id="bp-activities-link-description"><?php _e( 'Activity generated by posts and comments, forum topics and replies, and some plugins, uses the link field for a permalink back to the content item.', 'buddypress' ); ?></p>
    788 
    789 <?php
    790 }
    791 
    792 /**
    793  * User ID metabox for the Activity admin edit screen.
    794  *
    795  * @since 1.6.0
    796  *
    797  * @param object $item Activity item.
    798  */
    799 function bp_activity_admin_edit_metabox_userid( $item ) {
    800 ?>
    801 
    802         <label class="screen-reader-text" for="bp-activities-userid"><?php _e( 'Author ID', 'buddypress' ); ?></label>
    803         <input type="number" name="bp-activities-userid" id="bp-activities-userid" value="<?php echo esc_attr( $item->user_id ); ?>" min="1" />
    804 
    805 <?php
    806 }
    807 
    808 /**
    809  * Get flattened array of all registered activity actions.
    810  *
    811  * Format is [activity_type] => Pretty name for activity type.
    812  *
    813  * @since 2.0.0
    814  *
    815  * @return array $actions
    816  */
    817 function bp_activity_admin_get_activity_actions() {
    818         $actions  = array();
    819 
    820         // Walk through the registered actions, and build an array of actions/values.
    821         foreach ( bp_activity_get_actions() as $action ) {
    822                 $action = array_values( (array) $action );
    823 
    824                 for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ ) {
    825                         $actions[ $action[$i]['key'] ] = $action[$i]['value'];
    826                 }
    827         }
    828 
    829         // This was a mis-named activity type from before BP 1.6.
    830         unset( $actions['friends_register_activity_action'] );
    831 
    832         // Sort array by the human-readable value.
    833         natsort( $actions );
    834 
    835         return $actions;
    836 }
    837 
    838 /**
    839  * Activity type metabox for the Activity admin edit screen.
    840  *
    841  * @since 1.6.0
    842  *
    843  * @param object $item Activity item.
    844  */
    845 function bp_activity_admin_edit_metabox_type( $item ) {
    846         $bp = buddypress();
    847 
    848         $actions  = array();
    849         $selected = $item->type;
    850 
    851         // Walk through the registered actions, and build an array of actions/values.
    852         foreach ( bp_activity_get_actions() as $action ) {
    853                 $action = array_values( (array) $action );
    854 
    855                 for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ )
    856                         $actions[ $action[$i]['key'] ] = $action[$i]['value'];
    857         }
    858 
    859         // This was a mis-named activity type from before BP 1.6.
    860         unset( $actions['friends_register_activity_action'] );
    861 
    862         // Sort array by the human-readable value.
    863         natsort( $actions );
    864 
    865         /*
    866          * If the activity type is not registered properly (eg, a plugin has
    867          * not called bp_activity_set_action()), add the raw type to the end
    868          * of the list.
    869          */
    870         if ( ! isset( $actions[ $selected ] ) ) {
    871                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'This activity item has a type (%s) that is not registered using bp_activity_set_action(), so no label is available.', 'buddypress' ), $selected ), '2.0.0' );
    872                 $actions[ $selected ] = $selected;
    873         }
    874 
    875         ?>
    876 
    877         <label for="bp-activities-type" class="screen-reader-text"><?php esc_html_e( 'Select activity type', 'buddypress' ); ?></label>
    878         <select name="bp-activities-type" id="bp-activities-type">
    879                 <?php foreach ( $actions as $k => $v ) : ?>
    880                         <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $k,  $selected ); ?>><?php echo esc_html( $v ); ?></option>
    881                 <?php endforeach; ?>
    882         </select>
    883 
    884 <?php
    885 }
    886 
    887 /**
    888  * Primary item ID/Secondary item ID metabox for the Activity admin edit screen.
    889  *
    890  * @since 1.6.0
    891  *
    892  * @param object $item Activity item.
    893  */
    894 function bp_activity_admin_edit_metabox_itemids( $item ) {
    895 ?>
    896 
    897         <label for="bp-activities-primaryid"><?php _e( 'Primary Item ID', 'buddypress' ); ?></label>
    898         <input type="number" name="bp-activities-primaryid" id="bp-activities-primaryid" value="<?php echo esc_attr( $item->item_id ); ?>" min="0" />
    899         <br />
    900 
    901         <label for="bp-activities-secondaryid"><?php _e( 'Secondary Item ID', 'buddypress' ); ?></label>
    902         <input type="number" name="bp-activities-secondaryid" id="bp-activities-secondaryid" value="<?php echo esc_attr( $item->secondary_item_id ); ?>" min="0" />
    903 
    904         <p><?php _e( 'These identify the object that created this activity. For example, the fields could reference a pair of site and comment IDs.', 'buddypress' ); ?></p>
    905 
    906 <?php
    907 }
    908 
    909 /**
    910  * Display the Activity admin index screen, which contains a list of all the activities.
    911  *
    912  * @since 1.6.0
    913  *
    914  * @global BP_Activity_List_Table $bp_activity_list_table Activity screen list table.
    915  * @global string                 $plugin_page            The current plugin page.
    916  */
    917 function bp_activity_admin_index() {
    918         global $bp_activity_list_table, $plugin_page;
    919 
    920         $messages = array();
    921 
    922         // If the user has just made a change to an activity item, build status messages.
    923         if ( ! empty( $_REQUEST['deleted'] ) || ! empty( $_REQUEST['spammed'] ) || ! empty( $_REQUEST['unspammed'] ) || ! empty( $_REQUEST['error'] ) || ! empty( $_REQUEST['updated'] ) ) {
    924                 $deleted   = ! empty( $_REQUEST['deleted']   ) ? (int) $_REQUEST['deleted']   : 0;
    925                 $errors    = ! empty( $_REQUEST['error']     ) ? $_REQUEST['error']           : '';
    926                 $spammed   = ! empty( $_REQUEST['spammed']   ) ? (int) $_REQUEST['spammed']   : 0;
    927                 $unspammed = ! empty( $_REQUEST['unspammed'] ) ? (int) $_REQUEST['unspammed'] : 0;
    928                 $updated   = ! empty( $_REQUEST['updated']   ) ? (int) $_REQUEST['updated']   : 0;
    929 
    930                 $errors = array_map( 'absint', explode( ',', $errors ) );
    931 
    932                 // Make sure we don't get any empty values in $errors.
    933                 for ( $i = 0, $errors_count = count( $errors ); $i < $errors_count; $i++ ) {
    934                         if ( 0 === $errors[$i] ) {
    935                                 unset( $errors[$i] );
    936                         }
    937                 }
    938 
    939                 // Reindex array.
    940                 $errors = array_values( $errors );
    941 
    942                 if ( $deleted > 0 )
    943                         $messages[] = sprintf( _n( '%s activity item has been permanently deleted.', '%s activity items have been permanently deleted.', $deleted, 'buddypress' ), number_format_i18n( $deleted ) );
    944 
    945                 if ( ! empty( $errors ) ) {
    946                         if ( 1 == count( $errors ) ) {
    947                                 $messages[] = sprintf( __( 'An error occurred when trying to update activity ID #%s.', 'buddypress' ), number_format_i18n( $errors[0] ) );
    948 
    949                         } else {
    950                                 $error_msg  = __( 'Errors occurred when trying to update these activity items:', 'buddypress' );
    951                                 $error_msg .= '<ul class="activity-errors">';
    952 
    953                                 // Display each error as a list item.
    954                                 foreach ( $errors as $error ) {
    955                                         // Translators: This is a bulleted list of item IDs.
    956                                         $error_msg .= '<li>' . sprintf( __( '#%s', 'buddypress' ), number_format_i18n( $error ) ) . '</li>';
    957                                 }
    958 
    959                                 $error_msg  .= '</ul>';
    960                                 $messages[] = $error_msg;
    961                         }
    962                 }
    963 
    964                 if ( $spammed > 0 )
    965                         $messages[] = sprintf( _n( '%s activity item has been successfully spammed.', '%s activity items have been successfully spammed.', $spammed, 'buddypress' ), number_format_i18n( $spammed ) );
    966 
    967                 if ( $unspammed > 0 )
    968                         $messages[] = sprintf( _n( '%s activity item has been successfully unspammed.', '%s activity items have been successfully unspammed.', $unspammed, 'buddypress' ), number_format_i18n( $unspammed ) );
    969 
    970                 if ( $updated > 0 )
    971                         $messages[] = __( 'The activity item has been updated successfully.', 'buddypress' );
    972         }
    973 
    974         // Prepare the activity items for display.
    975         $bp_activity_list_table->prepare_items();
    976 
    977         /**
    978          * Fires before edit form is displayed so plugins can modify the activity messages.
    979          *
    980          * @since 1.6.0
    981          *
    982          * @param array $messages Array of messages to display at top of page.
    983          */
    984         do_action( 'bp_activity_admin_index', $messages ); ?>
    985 
    986         <div class="wrap">
    987                 <h1>
    988                         <?php if ( !empty( $_REQUEST['aid'] ) ) : ?>
    989                                 <?php printf( __( 'Activity related to ID #%s', 'buddypress' ), number_format_i18n( (int) $_REQUEST['aid'] ) ); ?>
    990                         <?php else : ?>
    991                                 <?php _ex( 'Activity', 'Admin SWA page', 'buddypress' ); ?>
    992                         <?php endif; ?>
    993 
    994                         <?php if ( !empty( $_REQUEST['s'] ) ) : ?>
    995                                 <span class="subtitle"><?php printf( __( 'Search results for &#8220;%s&#8221;', 'buddypress' ), wp_html_excerpt( esc_html( stripslashes( $_REQUEST['s'] ) ), 50 ) ); ?></span>
    996                         <?php endif; ?>
    997                 </h1>
    998 
    999                 <?php // If the user has just made a change to an activity item, display the status messages. ?>
    1000                 <?php if ( !empty( $messages ) ) : ?>
    1001                         <div id="moderated" class="<?php echo ( ! empty( $_REQUEST['error'] ) ) ? 'error' : 'updated'; ?>"><p><?php echo implode( "<br/>\n", $messages ); ?></p></div>
    1002                 <?php endif; ?>
    1003 
    1004                 <?php // Display each activity on its own row. ?>
    1005                 <?php $bp_activity_list_table->views(); ?>
    1006 
    1007                 <form id="bp-activities-form" action="" method="get">
    1008                         <?php $bp_activity_list_table->search_box( __( 'Search all Activity', 'buddypress' ), 'bp-activity' ); ?>
    1009                         <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" />
    1010                         <?php $bp_activity_list_table->display(); ?>
    1011                 </form>
    1012 
    1013                 <?php // This markup is used for the reply form. ?>
    1014                 <table style="display: none;">
    1015                         <tr id="bp-activities-container" style="display: none;">
    1016                                 <td colspan="4">
    1017                                         <form method="get" action="">
    1018 
    1019                                                 <h3 id="bp-replyhead"><?php _e( 'Reply to Activity', 'buddypress' ); ?></h3>
    1020                                                 <?php wp_editor( '', 'bp-activities', array( 'dfw' => false, 'media_buttons' => false, 'quicktags' => array( 'buttons' => 'strong,em,link,block,del,ins,img,code,spell,close' ), 'tinymce' => false, ) ); ?>
    1021 
    1022                                                 <p id="bp-replysubmit" class="submit">
    1023                                                         <a href="#" class="cancel button-secondary alignleft"><?php _e( 'Cancel', 'buddypress' ); ?></a>
    1024                                                         <a href="#" class="save button-primary alignright"><?php _e( 'Reply', 'buddypress' ); ?></a>
    1025 
    1026                                                         <img class="waiting" style="display:none;" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
    1027                                                         <span class="error" style="display:none;"></span>
    1028                                                         <br class="clear" />
    1029                                                 </p>
    1030 
    1031                                                 <?php wp_nonce_field( 'bp-activity-admin-reply', '_ajax_nonce-bp-activity-admin-reply', false ); ?>
    1032 
    1033                                         </form>
    1034                                 </td>
    1035                         </tr>
    1036                 </table>
    1037         </div>
    1038 
    1039 <?php
    1040 }
    1041 
    1042 /**
    10434 * List table class for the Activity component admin page.
    10445 *
    10456 * @since 1.6.0
  • src/bp-activity/classes/class-bp-activity-loader.php

     
    11<?php
    22/**
    3  * BuddyPress Activity Streams Loader.
     3 * Activity component class.
    44 *
    5  * An activity stream component, for users, groups, and site tracking.
    6  *
    75 * @package BuddyPress
    86 * @subpackage ActivityCore
    97 * @since 1.5.0
     
    386384                parent::setup_cache_groups();
    387385        }
    388386}
    389 
    390 /**
    391  * Bootstrap the Activity component.
    392  *
    393  * @since 1.6.0
    394  */
    395 function bp_setup_activity() {
    396         buddypress()->activity = new BP_Activity_Component();
    397 }
    398 add_action( 'bp_setup_components', 'bp_setup_activity', 6 );
  • src/bp-activity/classes/class-bp-activity-template.php

     
    1111defined( 'ABSPATH' ) || exit;
    1212
    1313/**
    14  * Output the activity component slug.
    15  *
    16  * @since 1.5.0
    17  *
    18  * @uses bp_get_activity_slug()
    19  */
    20 function bp_activity_slug() {
    21         echo bp_get_activity_slug();
    22 }
    23         /**
    24          * Return the activity component slug.
    25          *
    26          * @since 1.5.0
    27          *
    28          * @uses apply_filters() To call the 'bp_get_activity_slug' hook.
    29          *
    30          * @return string The activity component slug.
    31          */
    32         function bp_get_activity_slug() {
    33 
    34                 /**
    35                  * Filters the activity component slug.
    36                  *
    37                  * @since 1.5.0
    38                  *
    39                  * @param string $slug Activity component slug.
    40                  */
    41                 return apply_filters( 'bp_get_activity_slug', buddypress()->activity->slug );
    42         }
    43 
    44 /**
    45  * Output the activity component root slug.
    46  *
    47  * @since 1.5.0
    48  *
    49  * @uses bp_get_activity_root_slug()
    50  */
    51 function bp_activity_root_slug() {
    52         echo bp_get_activity_root_slug();
    53 }
    54         /**
    55          * Return the activity component root slug.
    56          *
    57          * @since 1.5.0
    58          *
    59          * @uses apply_filters() To call the 'bp_get_activity_root_slug' hook.
    60          *
    61          * @return string The activity component root slug.
    62          */
    63         function bp_get_activity_root_slug() {
    64 
    65                 /**
    66                  * Filters the activity component root slug.
    67                  *
    68                  * @since 1.5.0
    69                  *
    70                  * @param string $root_slug Activity component root slug.
    71                  */
    72                 return apply_filters( 'bp_get_activity_root_slug', buddypress()->activity->root_slug );
    73         }
    74 
    75 /**
    76  * Output activity directory permalink.
    77  *
    78  * @since 1.5.0
    79  *
    80  * @uses bp_get_activity_directory_permalink()
    81  */
    82 function bp_activity_directory_permalink() {
    83         echo esc_url( bp_get_activity_directory_permalink() );
    84 }
    85         /**
    86          * Return activity directory permalink.
    87          *
    88          * @since 1.5.0
    89          *
    90          * @uses trailingslashit()
    91          * @uses bp_get_root_domain()
    92          * @uses bp_get_activity_root_slug()
    93          * @uses apply_filters() To call the 'bp_get_activity_directory_permalink' hook.
    94          *
    95          * @return string Activity directory permalink.
    96          */
    97         function bp_get_activity_directory_permalink() {
    98 
    99                 /**
    100                  * Filters the activity directory permalink.
    101                  *
    102                  * @since 1.5.0
    103                  *
    104                  * @param string $url Permalink url for the activity directory.
    105                  */
    106                 return apply_filters( 'bp_get_activity_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_activity_root_slug() ) );
    107         }
    108 
    109 /**
    11014 * The main activity template loop class.
    11115 *
    11216 * This is responsible for loading a group of activity items and displaying them.
     
    503407                }
    504408        }
    505409}
    506 
    507 /**
    508  * Initialize the activity loop.
    509  *
    510  * Based on the $args passed, bp_has_activities() populates the
    511  * $activities_template global, enabling the use of BuddyPress templates and
    512  * template functions to display a list of activity items.
    513  *
    514  * @since 1.0.0
    515  * @since 2.4.0 Introduced the `$fields` parameter.
    516  *
    517  * @global object $activities_template {@link BP_Activity_Template}
    518  * @uses groups_is_user_member()
    519  * @uses bp_current_action()
    520  * @uses bp_is_current_action()
    521  * @uses bp_get_activity_slug()
    522  * @uses bp_action_variable()
    523  * @uses wp_parse_args()
    524  * @uses bp_is_active()
    525  * @uses friends_get_friend_user_ids()
    526  * @uses groups_get_user_groups()
    527  * @uses bp_activity_get_user_favorites()
    528  * @uses apply_filters() To call the 'bp_has_activities' hook.
    529  *
    530  * @param array|string $args {
    531  *     Arguments for limiting the contents of the activity loop. Most arguments
    532  *     are in the same format as {@link BP_Activity_Activity::get()}. However,
    533  *     because the format of the arguments accepted here differs in a number of
    534  *     ways, and because bp_has_activities() determines some default arguments in
    535  *     a dynamic fashion, we list all accepted arguments here as well.
    536  *
    537  *     Arguments can be passed as an associative array, or as a URL querystring
    538  *     (eg, 'user_id=4&display_comments=threaded').
    539  *
    540  *     @type int               $page             Which page of results to fetch. Using page=1 without per_page will result
    541  *                                               in no pagination. Default: 1.
    542  *     @type int|bool          $per_page         Number of results per page. Default: 20.
    543  *     @type string            $page_arg         String used as a query parameter in pagination links. Default: 'acpage'.
    544  *     @type int|bool          $max              Maximum number of results to return. Default: false (unlimited).
    545  *     @type string            $fields           Activity fields to retrieve. 'all' to fetch entire activity objects,
    546  *                                               'ids' to get only the activity IDs. Default 'all'.
    547  *     @type string|bool       $count_total      If true, an additional DB query is run to count the total activity items
    548  *                                               for the query. Default: false.
    549  *     @type string            $sort             'ASC' or 'DESC'. Default: 'DESC'.
    550  *     @type array|bool        $exclude          Array of activity IDs to exclude. Default: false.
    551  *     @type array|bool        $in               Array of IDs to limit query by (IN). 'in' is intended to be used in
    552  *                                               conjunction with other filter parameters. Default: false.
    553  *     @type array|bool        $include          Array of exact activity IDs to query. Providing an 'include' array will
    554  *                                               override all other filters passed in the argument array. When viewing the
    555  *                                               permalink page for a single activity item, this value defaults to the ID of
    556  *                                               that item. Otherwise the default is false.
    557  *     @type array             $meta_query       Limit by activitymeta by passing an array of meta_query conditions. See
    558  *                                               {@link WP_Meta_Query::queries} for a description of the syntax.
    559  *     @type array             $date_query       Limit by date by passing an array of date_query conditions. See first
    560  *                                               parameter of {@link WP_Date_Query::__construct()} for syntax.
    561  *     @type array             $filter_query     Advanced activity filtering.  See {@link BP_Activity_Query::__construct()}.
    562  *     @type string            $search_terms     Limit results by a search term. Default: false.
    563  *     @type string            $scope            Use a BuddyPress pre-built filter.
    564  *                                                 - 'just-me' retrieves items belonging only to a user; this is equivalent
    565  *                                                   to passing a 'user_id' argument.
    566  *                                                 - 'friends' retrieves items belonging to the friends of a user.
    567  *                                                 - 'groups' retrieves items belonging to groups to which a user belongs to.
    568  *                                                 - 'favorites' retrieves a user's favorited activity items.
    569  *                                                 - 'mentions' retrieves items where a user has received an @-mention.
    570  *                                               The default value of 'scope' is set to one of the above if that value
    571  *                                               appears in the appropriate place in the URL; eg, 'scope' will be 'groups'
    572  *                                               when visiting http://example.com/members/joe/activity/groups/. Otherwise
    573  *                                               defaults to false.
    574  *     @type int|array|bool    $user_id          The ID(s) of user(s) whose activity should be fetched. Pass a single ID or
    575  *                                               an array of IDs. When viewing a user profile page (but not that user's
    576  *                                               activity subpages, ie My Friends, My Groups, etc), 'user_id' defaults to
    577  *                                               the ID of the displayed user. Otherwise the default is false.
    578  *     @type string|array|bool $object           Filters by the `component` column in the database, which is generally the
    579  *                                               component ID in the case of BuddyPress components, or the plugin slug in
    580  *                                               the case of plugins. For example, 'groups' will limit results to those that
    581  *                                               are associated with the BP Groups component. Accepts a single component
    582  *                                               string, or an array of multiple components. Defaults to 'groups' when
    583  *                                               viewing the page of a single group, the My Groups activity filter, or the
    584  *                                               Activity > Groups filter of a user profile. Otherwise defaults to false.
    585  *     @type string|array|bool $action           Filters by the `type` column in the database, which is a string
    586  *                                               categorizing the activity item (eg, 'new_blog_post', 'created_group').
    587  *                                               Accepts a comma-delimited string or an array of types. Default: false.
    588  *     @type int|array|bool    $primary_id       Filters by the `item_id` column in the database. The meaning of
    589  *                                               'primary_id' differs between components/types; for example, in the case of
    590  *                                               'created_group', 'primary_id' is the ID of the group. Accepts a single ID,
    591  *                                               or an array of multiple IDs. When viewing a single group, defaults to the
    592  *                                               current group ID. When viewing a user's Groups stream page, defaults to the
    593  *                                               IDs of the user's groups. Otherwise defaults to false.
    594  *     @type int|array|bool    $secondary_id     Filters by the `secondary_item_id` column in the database. The meaning of
    595  *                                               'secondary_id' differs between components/types. Accepts a single ID, or an
    596  *                                               array of multiple IDs. Defaults to false.
    597  *     @type int               $offset           Return only activity items with an ID greater than or equal to this one.
    598  *                                               Note that providing an offset will disable pagination. Default: false.
    599  *     @type string|bool       $display_comments How to handle activity comments. Possible values:
    600  *                                                 - 'threaded' - comments appear in a threaded tree, under their parent
    601  *                                                   items.
    602  *                                                 - 'stream' - the activity stream is presented in a flat manner, with
    603  *                                                   comments sorted in chronological order alongside other activity items.
    604  *                                                 - false - don't fetch activity comments at all.
    605  *                                               Default: 'threaded'.
    606  *     @type bool              $show_hidden      Whether to show items marked hide_sitewide. Defaults to false, except in
    607  *                                               the following cases:
    608  *                                                 - User is viewing his own activity stream.
    609  *                                                 - User is viewing the activity stream of a non-public group of which he
    610  *                                                   is a member.
    611  *     @type string|bool       $spam             Spam status. 'ham_only', 'spam_only', or false to show all activity
    612  *                                               regardless of spam status. Default: 'ham_only'.
    613  *     @type bool              $populate_extras  Whether to pre-fetch the activity metadata for the queried items.
    614  *                                               Default: true.
    615  * }
    616  * @return bool Returns true when activities are found, otherwise false.
    617  */
    618 function bp_has_activities( $args = '' ) {
    619         global $activities_template;
    620 
    621         // Get BuddyPress.
    622         $bp = buddypress();
    623 
    624         /*
    625          * Smart Defaults.
    626          */
    627 
    628         // User filtering.
    629         $user_id = bp_displayed_user_id()
    630                 ? bp_displayed_user_id()
    631                 : false;
    632 
    633         // Group filtering.
    634         if ( bp_is_group() ) {
    635                 $object      = $bp->groups->id;
    636                 $primary_id  = bp_get_current_group_id();
    637                 $show_hidden = (bool) ( groups_is_user_member( bp_loggedin_user_id(), $primary_id ) || bp_current_user_can( 'bp_moderate' ) );
    638         } else {
    639                 $object      = false;
    640                 $primary_id  = false;
    641                 $show_hidden = false;
    642         }
    643 
    644         // The default scope should recognize custom slugs.
    645         $scope = array_key_exists( bp_current_action(), (array) $bp->loaded_components )
    646                 ? $bp->loaded_components[ bp_current_action() ]
    647                 : bp_current_action();
    648 
    649         // Support for permalinks on single item pages: /groups/my-group/activity/124/.
    650         $include = bp_is_current_action( bp_get_activity_slug() )
    651                 ? bp_action_variable( 0 )
    652                 : false;
    653 
    654         $search_terms_default = false;
    655         $search_query_arg = bp_core_get_component_search_query_arg( 'activity' );
    656         if ( ! empty( $_REQUEST[ $search_query_arg ] ) ) {
    657                 $search_terms_default = stripslashes( $_REQUEST[ $search_query_arg ] );
    658         }
    659 
    660         /*
    661          * Parse Args.
    662          */
    663 
    664         // Note: any params used for filtering can be a single value, or multiple
    665         // values comma separated.
    666         $r = bp_parse_args( $args, array(
    667                 'display_comments'  => 'threaded',   // False for none, stream/threaded - show comments in the stream or threaded under items.
    668                 'include'           => $include,     // Pass an activity_id or string of IDs comma-separated.
    669                 'exclude'           => false,        // Pass an activity_id or string of IDs comma-separated.
    670                 'in'                => false,        // Comma-separated list or array of activity IDs among which to search.
    671                 'sort'              => 'DESC',       // Sort DESC or ASC.
    672                 'page'              => 1,            // Which page to load.
    673                 'per_page'          => 20,           // Number of items per page.
    674                 'page_arg'          => 'acpage',     // See https://buddypress.trac.wordpress.org/ticket/3679.
    675                 'max'               => false,        // Max number to return.
    676                 'fields'            => 'all',
    677                 'count_total'       => false,
    678                 'show_hidden'       => $show_hidden, // Show activity items that are hidden site-wide?
    679                 'spam'              => 'ham_only',   // Hide spammed items.
    680 
    681                 // Scope - pre-built activity filters for a user (friends/groups/favorites/mentions).
    682                 'scope'             => $scope,
    683 
    684                 // Filtering
    685                 'user_id'           => $user_id,     // user_id to filter on.
    686                 'object'            => $object,      // Object to filter on e.g. groups, profile, status, friends.
    687                 'action'            => false,        // Action to filter on e.g. activity_update, new_forum_post, profile_updated.
    688                 'primary_id'        => $primary_id,  // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
    689                 'secondary_id'      => false,        // Secondary object ID to filter on e.g. a post_id.
    690                 'offset'            => false,        // Return only items >= this ID.
    691                 'since'             => false,        // Return only items recorded since this Y-m-d H:i:s date.
    692 
    693                 'meta_query'        => false,        // Filter on activity meta. See WP_Meta_Query for format.
    694                 'date_query'        => false,        // Filter by date. See first parameter of WP_Date_Query for format.
    695                 'filter_query'      => false,        // Advanced filtering.  See BP_Activity_Query for format.
    696 
    697                 // Searching.
    698                 'search_terms'      => $search_terms_default,
    699                 'update_meta_cache' => true,
    700         ), 'has_activities' );
    701 
    702         /*
    703          * Smart Overrides.
    704          */
    705 
    706         // Translate various values for 'display_comments'
    707         // This allows disabling comments via ?display_comments=0
    708         // or =none or =false. Final true is a strict type check. See #5029.
    709         if ( in_array( $r['display_comments'], array( 0, '0', 'none', 'false' ), true ) ) {
    710                 $r['display_comments'] = false;
    711         }
    712 
    713         // Ignore pagination if an offset is passed.
    714         if ( ! empty( $r['offset'] ) ) {
    715                 $r['page'] = 0;
    716         }
    717 
    718         // Search terms.
    719         if ( ! empty( $_REQUEST['s'] ) && empty( $r['search_terms'] ) ) {
    720                 $r['search_terms'] = $_REQUEST['s'];
    721         }
    722 
    723         // Do not exceed the maximum per page.
    724         if ( ! empty( $r['max'] ) && ( (int) $r['per_page'] > (int) $r['max'] ) ) {
    725                 $r['per_page'] = $r['max'];
    726         }
    727 
    728         /**
    729          * Filters whether BuddyPress should enable afilter support.
    730          *
    731          * Support for basic filters in earlier BP versions is disabled by default.
    732          * To enable, put add_filter( 'bp_activity_enable_afilter_support', '__return_true' );
    733          * into bp-custom.php or your theme's functions.php.
    734          *
    735          * @since 1.6.0
    736          *
    737          * @param bool $value True if BuddyPress should enable afilter support.
    738          */
    739         if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) ) {
    740                 $r['filter'] = array(
    741                         'object' => $_GET['afilter']
    742                 );
    743         } elseif ( ! empty( $r['user_id'] ) || ! empty( $r['object'] ) || ! empty( $r['action'] ) || ! empty( $r['primary_id'] ) || ! empty( $r['secondary_id'] ) || ! empty( $r['offset'] ) || ! empty( $r['since'] ) ) {
    744                 $r['filter'] = array(
    745                         'user_id'      => $r['user_id'],
    746                         'object'       => $r['object'],
    747                         'action'       => $r['action'],
    748                         'primary_id'   => $r['primary_id'],
    749                         'secondary_id' => $r['secondary_id'],
    750                         'offset'       => $r['offset'],
    751                         'since'        => $r['since']
    752                 );
    753         } else {
    754                 $r['filter'] = false;
    755         }
    756 
    757         // If specific activity items have been requested, override the $hide_spam
    758         // argument. This prevents backpat errors with AJAX.
    759         if ( ! empty( $r['include'] ) && ( 'ham_only' === $r['spam'] ) ) {
    760                 $r['spam'] = 'all';
    761         }
    762 
    763         /*
    764          * Query
    765          */
    766 
    767         $activities_template = new BP_Activity_Template( $r );
    768 
    769         /**
    770          * Filters whether or not there are activity items to display.
    771          *
    772          * @since 1.1.0
    773          *
    774          * @param bool   $value               Whether or not there are activity items to display.
    775          * @param string $activities_template Current activities template being used.
    776          * @param array  $r                   Array of arguments passed into the BP_Activity_Template class.
    777          */
    778         return apply_filters( 'bp_has_activities', $activities_template->has_activities(), $activities_template, $r );
    779 }
    780 
    781 /**
    782  * Determine if there are still activities left in the loop.
    783  *
    784  * @since 1.0.0
    785  *
    786  * @global object $activities_template {@link BP_Activity_Template}
    787  * @uses BP_Activity_Template::user_activities() {@link BP_Activity_Template::user_activities()}
    788  *
    789  * @return bool Returns true when activities are found.
    790  */
    791 function bp_activities() {
    792         global $activities_template;
    793         return $activities_template->user_activities();
    794 }
    795 
    796 /**
    797  * Get the current activity object in the loop.
    798  *
    799  * @since 1.0.0
    800  *
    801  * @global object $activities_template {@link BP_Activity_Template}
    802  * @uses BP_Activity_Template::the_activity() {@link BP_Activity_Template::the_activity()}
    803  *
    804  * @return object The current activity within the loop.
    805  */
    806 function bp_the_activity() {
    807         global $activities_template;
    808         return $activities_template->the_activity();
    809 }
    810 
    811 /**
    812  * Output the URL for the Load More link.
    813  *
    814  * @since 2.1.0
    815  */
    816 function bp_activity_load_more_link() {
    817         echo esc_url( bp_get_activity_load_more_link() );
    818 }
    819         /**
    820          * Get the URL for the Load More link.
    821          *
    822          * @since 2.1.0
    823          *
    824          * @return string $link
    825          */
    826         function bp_get_activity_load_more_link() {
    827                 global $activities_template;
    828 
    829                 $url  = bp_get_requested_url();
    830                 $link = add_query_arg( $activities_template->pag_arg, $activities_template->pag_page + 1, $url );
    831 
    832                 /**
    833                  * Filters the Load More link URL.
    834                  *
    835                  * @since 2.1.0
    836                  *
    837                  * @param string $link                The "Load More" link URL with appropriate query args.
    838                  * @param string $url                 The original URL.
    839                  * @param object $activities_template The activity template loop global.
    840                  */
    841                 return apply_filters( 'bp_get_activity_load_more_link', $link, $url, $activities_template );
    842         }
    843 
    844 /**
    845  * Output the activity pagination count.
    846  *
    847  * @since 1.0.0
    848  *
    849  * @global object $activities_template {@link BP_Activity_Template}
    850  * @uses BP_Activity_Template::the_activity() {@link BP_Activity_Template::the_activity()}
    851  */
    852 function bp_activity_pagination_count() {
    853         echo bp_get_activity_pagination_count();
    854 }
    855 
    856         /**
    857          * Return the activity pagination count.
    858          *
    859          * @since 1.2.0
    860          *
    861          * @global object $activities_template {@link BP_Activity_Template}
    862          * @uses bp_core_number_format()
    863          *
    864          * @return string The pagination text.
    865          */
    866         function bp_get_activity_pagination_count() {
    867                 global $activities_template;
    868 
    869                 $start_num = intval( ( $activities_template->pag_page - 1 ) * $activities_template->pag_num ) + 1;
    870                 $from_num  = bp_core_number_format( $start_num );
    871                 $to_num    = bp_core_number_format( ( $start_num + ( $activities_template->pag_num - 1 ) > $activities_template->total_activity_count ) ? $activities_template->total_activity_count : $start_num + ( $activities_template->pag_num - 1 ) );
    872                 $total     = bp_core_number_format( $activities_template->total_activity_count );
    873 
    874                 if ( 1 == $activities_template->total_activity_count ) {
    875                         $message = __( 'Viewing 1 item', 'buddypress' );
    876                 } else {
    877                         $message = sprintf( _n( 'Viewing %1$s - %2$s of %3$s item', 'Viewing %1$s - %2$s of %3$s items', $activities_template->total_activity_count, 'buddypress' ), $from_num, $to_num, $total );
    878                 }
    879 
    880                 return $message;
    881         }
    882 
    883 /**
    884  * Output the activity pagination links.
    885  *
    886  * @since 1.0.0
    887  *
    888  * @uses bp_get_activity_pagination_links()
    889  */
    890 function bp_activity_pagination_links() {
    891         echo bp_get_activity_pagination_links();
    892 }
    893 
    894         /**
    895          * Return the activity pagination links.
    896          *
    897          * @since 1.0.0
    898          *
    899          * @global object $activities_template {@link BP_Activity_Template}
    900          * @uses apply_filters() To call the 'bp_get_activity_pagination_links' hook.
    901          *
    902          * @return string The pagination links.
    903          */
    904         function bp_get_activity_pagination_links() {
    905                 global $activities_template;
    906 
    907                 /**
    908                  * Filters the activity pagination link output.
    909                  *
    910                  * @since 1.0.0
    911                  *
    912                  * @param string $pag_links Output for the activity pagination links.
    913                  */
    914                 return apply_filters( 'bp_get_activity_pagination_links', $activities_template->pag_links );
    915         }
    916 
    917 /**
    918  * Return true when there are more activity items to be shown than currently appear.
    919  *
    920  * @since 1.5.0
    921  *
    922  * @global object $activities_template {@link BP_Activity_Template}
    923  * @uses apply_filters() To call the 'bp_activity_has_more_items' hook.
    924  *
    925  * @return bool $has_more_items True if more items, false if not.
    926  */
    927 function bp_activity_has_more_items() {
    928         global $activities_template;
    929 
    930         if ( ! empty( $activities_template->has_more_items )  ) {
    931                 $has_more_items = true;
    932         } else {
    933                 $remaining_pages = 0;
    934 
    935                 if ( ! empty( $activities_template->pag_page ) ) {
    936                         $remaining_pages = floor( ( $activities_template->total_activity_count - 1 ) / ( $activities_template->pag_num * $activities_template->pag_page ) );
    937                 }
    938 
    939                 $has_more_items = (int) $remaining_pages > 0;
    940         }
    941 
    942         /**
    943          * Filters whether there are more activity items to display.
    944          *
    945          * @since 1.5.0
    946          *
    947          * @param bool $has_more_items Whether or not there are more activity items to display.
    948          */
    949         return apply_filters( 'bp_activity_has_more_items', $has_more_items );
    950 }
    951 
    952 /**
    953  * Output the activity count.
    954  *
    955  * @since 1.2.0
    956  *
    957  * @uses bp_get_activity_count()
    958  */
    959 function bp_activity_count() {
    960         echo bp_get_activity_count();
    961 }
    962 
    963         /**
    964          * Return the activity count.
    965          *
    966          * @since 1.2.0
    967          *
    968          * @global object $activities_template {@link BP_Activity_Template}
    969          * @uses apply_filters() To call the 'bp_get_activity_count' hook.
    970          *
    971          * @return int The activity count.
    972          */
    973         function bp_get_activity_count() {
    974                 global $activities_template;
    975 
    976                 /**
    977                  * Filters the activity count for the activity template.
    978                  *
    979                  * @since 1.2.0
    980                  *
    981                  * @param int $activity_count The count for total activity.
    982                  */
    983                 return apply_filters( 'bp_get_activity_count', (int) $activities_template->activity_count );
    984         }
    985 
    986 /**
    987  * Output the number of activities per page.
    988  *
    989  * @since 1.2.0
    990  *
    991  * @uses bp_get_activity_per_page()
    992  */
    993 function bp_activity_per_page() {
    994         echo bp_get_activity_per_page();
    995 }
    996 
    997         /**
    998          * Return the number of activities per page.
    999          *
    1000          * @since 1.2.0
    1001          *
    1002          * @global object $activities_template {@link BP_Activity_Template}
    1003          * @uses apply_filters() To call the 'bp_get_activity_per_page' hook.
    1004          *
    1005          * @return int The activities per page.
    1006          */
    1007         function bp_get_activity_per_page() {
    1008                 global $activities_template;
    1009 
    1010                 /**
    1011                  * Filters the activity posts per page value.
    1012                  *
    1013                  * @since 1.2.0
    1014                  *
    1015                  * @param int $pag_num How many post should be displayed for pagination.
    1016                  */
    1017                 return apply_filters( 'bp_get_activity_per_page', (int) $activities_template->pag_num );
    1018         }
    1019 
    1020 /**
    1021  * Output the activities title.
    1022  *
    1023  * @since 1.0.0
    1024  *
    1025  * @uses bp_get_activities_title()
    1026  * @todo Deprecate.
    1027  */
    1028 function bp_activities_title() {
    1029         echo bp_get_activities_title();
    1030 }
    1031 
    1032         /**
    1033          * Return the activities title.
    1034          *
    1035          * @since 1.0.0
    1036          *
    1037          * @global string $bp_activity_title
    1038          * @uses apply_filters() To call the 'bp_get_activities_title' hook.
    1039          * @todo Deprecate.
    1040          *
    1041          * @return string The activities title.
    1042          */
    1043         function bp_get_activities_title() {
    1044                 global $bp_activity_title;
    1045 
    1046                 /**
    1047                  * Filters the activities title for the activity template.
    1048                  *
    1049                  * @since 1.0.0
    1050                  *
    1051                  * @param string $bp_activity_title The title to be displayed.
    1052                  */
    1053                 return apply_filters( 'bp_get_activities_title', $bp_activity_title );
    1054         }
    1055 
    1056 /**
    1057  * {@internal Missing Description}
    1058  *
    1059  * @since 1.0.0
    1060  *
    1061  * @uses bp_get_activities_no_activity()
    1062  * @todo Deprecate.
    1063  */
    1064 function bp_activities_no_activity() {
    1065         echo bp_get_activities_no_activity();
    1066 }
    1067 
    1068         /**
    1069          * {@internal Missing Description}
    1070          *
    1071          * @since 1.0.0
    1072          *
    1073          * @global string $bp_activity_no_activity
    1074          * @uses apply_filters() To call the 'bp_get_activities_no_activity' hook.
    1075          * @todo Deprecate.
    1076          *
    1077          * @return string
    1078          */
    1079         function bp_get_activities_no_activity() {
    1080                 global $bp_activity_no_activity;
    1081 
    1082                 /**
    1083                  * Filters the text used when there is no activity to display.
    1084                  *
    1085                  * @since 1.0.0
    1086                  *
    1087                  * @param string $bp_activity_no_activity Text to display for no activity.
    1088                  */
    1089                 return apply_filters( 'bp_get_activities_no_activity', $bp_activity_no_activity );
    1090         }
    1091 
    1092 /**
    1093  * Output the activity ID.
    1094  *
    1095  * @since 1.2.0
    1096  *
    1097  * @uses bp_get_activity_id()
    1098  */
    1099 function bp_activity_id() {
    1100         echo bp_get_activity_id();
    1101 }
    1102 
    1103         /**
    1104          * Return the activity ID.
    1105          *
    1106          * @since 1.2.0
    1107          *
    1108          * @global object $activities_template {@link BP_Activity_Template}
    1109          * @uses apply_filters() To call the 'bp_get_activity_id' hook.
    1110          *
    1111          * @return int The activity ID.
    1112          */
    1113         function bp_get_activity_id() {
    1114                 global $activities_template;
    1115 
    1116                 /**
    1117                  * Filters the activity ID being displayed.
    1118                  *
    1119                  * @since 1.2.0
    1120                  *
    1121                  * @param int $id The activity ID.
    1122                  */
    1123                 return apply_filters( 'bp_get_activity_id', $activities_template->activity->id );
    1124         }
    1125 
    1126 /**
    1127  * Output the activity item ID.
    1128  *
    1129  * @since 1.2.0
    1130  *
    1131  * @uses bp_get_activity_item_id()
    1132  */
    1133 function bp_activity_item_id() {
    1134         echo bp_get_activity_item_id();
    1135 }
    1136 
    1137         /**
    1138          * Return the activity item ID.
    1139          *
    1140          * @since 1.2.0
    1141          *
    1142          * @global object $activities_template {@link BP_Activity_Template}
    1143          * @uses apply_filters() To call the 'bp_get_activity_item_id' hook.
    1144          *
    1145          * @return int The activity item ID.
    1146          */
    1147         function bp_get_activity_item_id() {
    1148                 global $activities_template;
    1149 
    1150                 /**
    1151                  * Filters the activity item ID being displayed.
    1152                  *
    1153                  * @since 1.2.0
    1154                  *
    1155                  * @param int $item_id The activity item ID.
    1156                  */
    1157                 return apply_filters( 'bp_get_activity_item_id', $activities_template->activity->item_id );
    1158         }
    1159 
    1160 /**
    1161  * Output the activity secondary item ID.
    1162  *
    1163  * @since 1.2.0
    1164  *
    1165  * @uses bp_get_activity_secondary_item_id()
    1166  */
    1167 function bp_activity_secondary_item_id() {
    1168         echo bp_get_activity_secondary_item_id();
    1169 }
    1170 
    1171         /**
    1172          * Return the activity secondary item ID.
    1173          *
    1174          * @since 1.2.0
    1175          *
    1176          * @global object $activities_template {@link BP_Activity_Template}
    1177          * @uses apply_filters() To call the 'bp_get_activity_secondary_item_id' hook.
    1178          *
    1179          * @return int The activity secondary item ID.
    1180          */
    1181         function bp_get_activity_secondary_item_id() {
    1182                 global $activities_template;
    1183 
    1184                 /**
    1185                  * Filters the activity secondary item ID being displayed.
    1186                  *
    1187                  * @since 1.2.0
    1188                  *
    1189                  * @param int $secondary_item_id The activity secondary item ID.
    1190                  */
    1191                 return apply_filters( 'bp_get_activity_secondary_item_id', $activities_template->activity->secondary_item_id );
    1192         }
    1193 
    1194 /**
    1195  * Output the date the activity was recorded.
    1196  *
    1197  * @since 1.2.0
    1198  *
    1199  * @uses bp_get_activity_date_recorded()
    1200  */
    1201 function bp_activity_date_recorded() {
    1202         echo bp_get_activity_date_recorded();
    1203 }
    1204 
    1205         /**
    1206          * Return the date the activity was recorded.
    1207          *
    1208          * @since 1.2.0
    1209          *
    1210          * @global object $activities_template {@link BP_Activity_Template}
    1211          * @uses apply_filters() To call the 'bp_get_activity_date_recorded' hook.
    1212          *
    1213          * @return string The date the activity was recorded.
    1214          */
    1215         function bp_get_activity_date_recorded() {
    1216                 global $activities_template;
    1217 
    1218                 /**
    1219                  * Filters the date the activity was recorded.
    1220                  *
    1221                  * @since 1.2.0
    1222                  *
    1223                  * @param int $date_recorded The activity's date.
    1224                  */
    1225                 return apply_filters( 'bp_get_activity_date_recorded', $activities_template->activity->date_recorded );
    1226         }
    1227 
    1228 /**
    1229  * Output the display name of the member who posted the activity.
    1230  *
    1231  * @since 2.1.0
    1232  *
    1233  * @uses bp_get_activity_member_display_name()
    1234  */
    1235 function bp_activity_member_display_name() {
    1236         echo bp_get_activity_member_display_name();
    1237 }
    1238 
    1239         /**
    1240          * Return the display name of the member who posted the activity.
    1241          *
    1242          * @since 2.1.0
    1243          *
    1244          * @global object $activities_template {@link BP_Activity_Template}
    1245          * @uses apply_filters() To call the 'bp_get_activity_member_display_name' hook.
    1246          *
    1247          * @return string The date the activity was recorded.
    1248          */
    1249         function bp_get_activity_member_display_name() {
    1250                 global $activities_template;
    1251 
    1252                 $retval = isset( $activities_template->activity->display_name )
    1253                         ? $activities_template->activity->display_name
    1254                         : '';
    1255 
    1256                 /**
    1257                  * Filters the display name of the member who posted the activity.
    1258                  *
    1259                  * @since 2.1.0
    1260                  *
    1261                  * @param int $retval Display name for the member who posted.
    1262                  */
    1263                 return apply_filters( 'bp_get_activity_member_display_name', $retval );
    1264         }
    1265 
    1266 /**
    1267  * Output the activity object name.
    1268  *
    1269  * @since 1.2.0
    1270  *
    1271  * @uses bp_get_activity_object_name()
    1272  */
    1273 function bp_activity_object_name() {
    1274         echo bp_get_activity_object_name();
    1275 }
    1276 
    1277         /**
    1278          * Return the activity object name.
    1279          *
    1280          * @since 1.2.0
    1281          *
    1282          * @global object $activities_template {@link BP_Activity_Template}
    1283          * @uses apply_filters() To call the 'bp_get_activity_object_name' hook.
    1284          *
    1285          * @return string The activity object name.
    1286          */
    1287         function bp_get_activity_object_name() {
    1288                 global $activities_template;
    1289 
    1290                 /**
    1291                  * Filters the activity object name.
    1292                  *
    1293                  * @since 1.2.0
    1294                  *
    1295                  * @param string $activity_component The activity object name.
    1296                  */
    1297                 return apply_filters( 'bp_get_activity_object_name', $activities_template->activity->component );
    1298         }
    1299 
    1300 /**
    1301  * Output the activity type.
    1302  *
    1303  * @since 1.2.0
    1304  *
    1305  * @uses bp_get_activity_type()
    1306  */
    1307 function bp_activity_type() {
    1308         echo bp_get_activity_type();
    1309 }
    1310 
    1311         /**
    1312          * Return the activity type.
    1313          *
    1314          * @since 1.2.0
    1315          *
    1316          * @global object $activities_template {@link BP_Activity_Template}
    1317          * @uses apply_filters() To call the 'bp_get_activity_type' hook.
    1318          *
    1319          * @return string The activity type.
    1320          */
    1321         function bp_get_activity_type() {
    1322                 global $activities_template;
    1323 
    1324                 /**
    1325                  * Filters the activity type.
    1326                  *
    1327                  * @since 1.2.0
    1328                  *
    1329                  * @param string $activity_type The activity type.
    1330                  */
    1331                 return apply_filters( 'bp_get_activity_type', $activities_template->activity->type );
    1332         }
    1333 
    1334         /**
    1335          * Output the activity action name.
    1336          *
    1337          * Just a wrapper for bp_activity_type().
    1338          *
    1339          * @since 1.2.0
    1340          * @deprecated 1.5.0
    1341          *
    1342          * @todo Properly deprecate in favor of bp_activity_type() and
    1343          *       remove redundant echo
    1344          *
    1345          * @uses bp_activity_type()
    1346          */
    1347         function bp_activity_action_name() { echo bp_activity_type(); }
    1348 
    1349         /**
    1350          * Return the activity type.
    1351          *
    1352          * Just a wrapper for bp_get_activity_type().
    1353          *
    1354          * @since 1.2.0
    1355          * @deprecated 1.5.0
    1356          *
    1357          * @todo Properly deprecate in favor of bp_get_activity_type().
    1358          *
    1359          * @uses bp_get_activity_type()
    1360          *
    1361          * @return string The activity type.
    1362          */
    1363         function bp_get_activity_action_name() { return bp_get_activity_type(); }
    1364 
    1365 /**
    1366  * Output the activity user ID.
    1367  *
    1368  * @since 1.1.0
    1369  *
    1370  * @uses bp_get_activity_user_id()
    1371  */
    1372 function bp_activity_user_id() {
    1373         echo bp_get_activity_user_id();
    1374 }
    1375 
    1376         /**
    1377          * Return the activity user ID.
    1378          *
    1379          * @since 1.1.0
    1380          *
    1381          * @global object $activities_template {@link BP_Activity_Template}
    1382          * @uses apply_filters() To call the 'bp_get_activity_user_id' hook.
    1383          *
    1384          * @return int The activity user ID.
    1385          */
    1386         function bp_get_activity_user_id() {
    1387                 global $activities_template;
    1388 
    1389                 /**
    1390                  * Filters the activity user ID.
    1391                  *
    1392                  * @since 1.1.0
    1393                  *
    1394                  * @param int $user_id The activity user ID.
    1395                  */
    1396                 return apply_filters( 'bp_get_activity_user_id', $activities_template->activity->user_id );
    1397         }
    1398 
    1399 /**
    1400  * Output the activity user link.
    1401  *
    1402  * @since 1.2.0
    1403  *
    1404  * @uses bp_get_activity_user_link()
    1405  */
    1406 function bp_activity_user_link() {
    1407         echo bp_get_activity_user_link();
    1408 }
    1409 
    1410         /**
    1411          * Return the activity user link.
    1412          *
    1413          * @since 1.2.0
    1414          *
    1415          * @global object $activities_template {@link BP_Activity_Template}
    1416          * @uses bp_core_get_user_domain()
    1417          * @uses apply_filters() To call the 'bp_get_activity_user_link' hook.
    1418          *
    1419          * @return string $link The activity user link.
    1420          */
    1421         function bp_get_activity_user_link() {
    1422                 global $activities_template;
    1423 
    1424                 if ( empty( $activities_template->activity->user_id ) || empty( $activities_template->activity->user_nicename ) || empty( $activities_template->activity->user_login ) ) {
    1425                         $link = $activities_template->activity->primary_link;
    1426                 } else {
    1427                         $link = bp_core_get_user_domain( $activities_template->activity->user_id, $activities_template->activity->user_nicename, $activities_template->activity->user_login );
    1428                 }
    1429 
    1430                 /**
    1431                  * Filters the activity user link.
    1432                  *
    1433                  * @since 1.2.0
    1434                  *
    1435                  * @param string $link The activity user link.
    1436                  */
    1437                 return apply_filters( 'bp_get_activity_user_link', $link );
    1438         }
    1439 
    1440 /**
    1441  * Output the avatar of the user that performed the action.
    1442  *
    1443  * @since 1.1.0
    1444  *
    1445  * @see bp_get_activity_avatar() for description of arguments.
    1446  * @uses bp_get_activity_avatar()
    1447  *
    1448  * @param array|string $args See {@link bp_get_activity_avatar()} for description.
    1449  */
    1450 function bp_activity_avatar( $args = '' ) {
    1451         echo bp_get_activity_avatar( $args );
    1452 }
    1453         /**
    1454          * Return the avatar of the user that performed the action.
    1455          *
    1456          * @since 1.1.0
    1457          *
    1458          * @see bp_core_fetch_avatar() For a description of the arguments.
    1459          * @global object $activities_template {@link BP_Activity_Template}
    1460          * @uses bp_is_single_activity()
    1461          * @uses wp_parse_args()
    1462          * @uses apply_filters() To call the 'bp_get_activity_avatar_object_' . $current_activity_item->component hook.
    1463          * @uses apply_filters() To call the 'bp_get_activity_avatar_item_id' hook.
    1464          * @uses bp_core_fetch_avatar()
    1465          * @uses apply_filters() To call the 'bp_get_activity_avatar' hook.
    1466          *
    1467          * @param array|string $args  {
    1468          *     Arguments are listed here with an explanation of their defaults.
    1469          *     For more information about the arguments, see
    1470          *     {@link bp_core_fetch_avatar()}.
    1471          *     @type string      $alt     Default: 'Profile picture of [user name]' if
    1472          *                                activity user name is available, otherwise 'Profile picture'.
    1473          *     @type string      $class   Default: 'avatar'.
    1474          *     @type string|bool $email   Default: Email of the activity's
    1475          *                                associated user, if available. Otherwise false.
    1476          *     @type string      $type    Default: 'full' when viewing a single activity
    1477          *                                permalink page, otherwise 'thumb'.
    1478          *     @type int|bool    $user_id Default: ID of the activity's user.
    1479          * }
    1480          * @return string User avatar string.
    1481          */
    1482         function bp_get_activity_avatar( $args = '' ) {
    1483                 global $activities_template;
    1484 
    1485                 $bp = buddypress();
    1486 
    1487                 // On activity permalink pages, default to the full-size avatar.
    1488                 $type_default = bp_is_single_activity() ? 'full' : 'thumb';
    1489 
    1490                 // Within the activity comment loop, the current activity should be set
    1491                 // to current_comment. Otherwise, just use activity.
    1492                 $current_activity_item = isset( $activities_template->activity->current_comment ) ? $activities_template->activity->current_comment : $activities_template->activity;
    1493 
    1494                 // Activity user display name.
    1495                 $dn_default  = isset( $current_activity_item->display_name ) ? $current_activity_item->display_name : '';
    1496 
    1497                 // Prepend some descriptive text to alt.
    1498                 $alt_default = !empty( $dn_default ) ? sprintf( __( 'Profile picture of %s', 'buddypress' ), $dn_default ) : __( 'Profile picture', 'buddypress' );
    1499 
    1500                 $defaults = array(
    1501                         'alt'     => $alt_default,
    1502                         'class'   => 'avatar',
    1503                         'email'   => false,
    1504                         'type'    => $type_default,
    1505                         'user_id' => false
    1506                 );
    1507 
    1508                 $r = wp_parse_args( $args, $defaults );
    1509                 extract( $r, EXTR_SKIP );
    1510 
    1511                 if ( !isset( $height ) && !isset( $width ) ) {
    1512 
    1513                         // Backpat.
    1514                         if ( isset( $bp->avatar->full->height ) || isset( $bp->avatar->thumb->height ) ) {
    1515                                 $height = ( 'full' == $type ) ? $bp->avatar->full->height : $bp->avatar->thumb->height;
    1516                         } else {
    1517                                 $height = 20;
    1518                         }
    1519 
    1520                         // Backpat.
    1521                         if ( isset( $bp->avatar->full->width ) || isset( $bp->avatar->thumb->width ) ) {
    1522                                 $width = ( 'full' == $type ) ? $bp->avatar->full->width : $bp->avatar->thumb->width;
    1523                         } else {
    1524                                 $width = 20;
    1525                         }
    1526                 }
    1527 
    1528                 /**
    1529                  * Filters the activity avatar object based on current activity item component.
    1530                  *
    1531                  * This is a variable filter dependent on the component used.
    1532                  * Possible hooks are bp_get_activity_avatar_object_blog,
    1533                  * bp_get_activity_avatar_object_group, and bp_get_activity_avatar_object_user.
    1534                  *
    1535                  * @since 1.1.0
    1536                  *
    1537                  * @param string $component Component being displayed.
    1538                  */
    1539                 $object  = apply_filters( 'bp_get_activity_avatar_object_' . $current_activity_item->component, 'user' );
    1540                 $item_id = !empty( $user_id ) ? $user_id : $current_activity_item->user_id;
    1541 
    1542                 /**
    1543                  * Filters the activity avatar item ID.
    1544                  *
    1545                  * @since 1.2.10
    1546                  *
    1547                  * @param int $item_id Item ID for the activity avatar.
    1548                  */
    1549                 $item_id = apply_filters( 'bp_get_activity_avatar_item_id', $item_id );
    1550 
    1551                 // If this is a user object pass the users' email address for Gravatar so we don't have to prefetch it.
    1552                 if ( 'user' == $object && empty( $user_id ) && empty( $email ) && isset( $current_activity_item->user_email ) ) {
    1553                         $email = $current_activity_item->user_email;
    1554                 }
    1555 
    1556                 /**
    1557                  * Filters the value returned by bp_core_fetch_avatar.
    1558                  *
    1559                  * @since 1.1.3
    1560                  *
    1561                  * @param array $value Array of arguments calculated for use with bp_core_fetch_avatar.
    1562                  */
    1563                 return apply_filters( 'bp_get_activity_avatar', bp_core_fetch_avatar( array(
    1564                         'item_id' => $item_id,
    1565                         'object'  => $object,
    1566                         'type'    => $type,
    1567                         'alt'     => $alt,
    1568                         'class'   => $class,
    1569                         'width'   => $width,
    1570                         'height'  => $height,
    1571                         'email'   => $email
    1572                 ) ) );
    1573         }
    1574 
    1575 /**
    1576  * Output the avatar of the object that action was performed on.
    1577  *
    1578  * @since 1.2.0
    1579  *
    1580  * @see bp_get_activity_secondary_avatar() for description of arguments.
    1581  * @uses bp_get_activity_secondary_avatar()
    1582  *
    1583  * @param array|string $args See {@link bp_get_activity_secondary_avatar} for description.
    1584  */
    1585 function bp_activity_secondary_avatar( $args = '' ) {
    1586         echo bp_get_activity_secondary_avatar( $args );
    1587 }
    1588 
    1589         /**
    1590          * Return the avatar of the object that action was performed on.
    1591          *
    1592          * @since 1.2.0
    1593          *
    1594          * @see bp_core_fetch_avatar() for description of arguments.
    1595          * @global object $activities_template {@link BP_Activity_Template}
    1596          * @uses wp_parse_args()
    1597          * @uses get_blog_option()
    1598          * @uses apply_filters() To call the 'bp_get_activity_secondary_avatar_object_' . $activities_template->activity->component hook.
    1599          * @uses apply_filters() To call the 'bp_get_activity_secondary_avatar_item_id' hook.
    1600          * @uses bp_core_fetch_avatar()
    1601          * @uses apply_filters() To call the 'bp_get_activity_secondary_avatar' hook.
    1602          *
    1603          * @param array|string $args  {
    1604          *     For a complete description of arguments, see {@link bp_core_fetch_avatar()}.
    1605          *     @type string      $alt     Default value varies based on current activity
    1606          *                                item component.
    1607          *     @type string      $type    Default: 'full' when viewing a single activity
    1608          *                                permalink page, otherwise 'thumb'.
    1609          *     @type string      $class   Default: 'avatar'.
    1610          *     @type string|bool $email   Default: email of the activity's user.
    1611          *     @type int|bool    $user_id Default: ID of the activity's user.
    1612          * }
    1613          * @return string The secondary avatar.
    1614          */
    1615         function bp_get_activity_secondary_avatar( $args = '' ) {
    1616                 global $activities_template;
    1617 
    1618                 $r = wp_parse_args( $args, array(
    1619                         'alt'        => '',
    1620                         'type'       => 'thumb',
    1621                         'width'      => 20,
    1622                         'height'     => 20,
    1623                         'class'      => 'avatar',
    1624                         'link_class' => '',
    1625                         'linked'     => true,
    1626                         'email'      => false
    1627                 ) );
    1628                 extract( $r, EXTR_SKIP );
    1629 
    1630                 // Set item_id and object (default to user).
    1631                 switch ( $activities_template->activity->component ) {
    1632                         case 'groups' :
    1633                                 if ( bp_disable_group_avatar_uploads() ) {
    1634                                         return false;
    1635                                 }
    1636 
    1637                                 $object  = 'group';
    1638                                 $item_id = $activities_template->activity->item_id;
    1639                                 $link    = '';
    1640                                 $name    = '';
    1641 
    1642                                 // Only if groups is active.
    1643                                 if ( bp_is_active( 'groups' ) ) {
    1644                                         $group = groups_get_group( array(
    1645                                                 'group_id'          => $item_id,
    1646                                                 'populate_extras'   => false,
    1647                                                 'update_meta_cache' => false,
    1648                                         ) );
    1649                                         $link  = bp_get_group_permalink( $group );
    1650                                         $name  = $group->name;
    1651                                 }
    1652 
    1653                                 if ( empty( $alt ) ) {
    1654                                         $alt = __( 'Group logo', 'buddypress' );
    1655 
    1656                                         if ( ! empty( $name ) ) {
    1657                                                 $alt = sprintf( __( 'Group logo of %s', 'buddypress' ), $name );
    1658                                         }
    1659                                 }
    1660 
    1661                                 break;
    1662                         case 'blogs' :
    1663                                 $object  = 'blog';
    1664                                 $item_id = $activities_template->activity->item_id;
    1665                                 $link    = home_url();
    1666 
    1667                                 if ( empty( $alt ) ) {
    1668                                         $alt = sprintf( __( 'Profile picture of the author of the site %s', 'buddypress' ), get_blog_option( $item_id, 'blogname' ) );
    1669                                 }
    1670 
    1671                                 break;
    1672                         case 'friends' :
    1673                                 $object  = 'user';
    1674                                 $item_id = $activities_template->activity->secondary_item_id;
    1675                                 $link    = bp_core_get_userlink( $item_id, false, true );
    1676 
    1677                                 if ( empty( $alt ) ) {
    1678                                         $alt = sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_core_get_user_displayname( $activities_template->activity->secondary_item_id ) );
    1679                                 }
    1680 
    1681                                 break;
    1682                         default :
    1683                                 $object  = 'user';
    1684                                 $item_id = $activities_template->activity->user_id;
    1685                                 $email   = $activities_template->activity->user_email;
    1686                                 $link    = bp_core_get_userlink( $item_id, false, true );
    1687 
    1688                                 if ( empty( $alt ) ) {
    1689                                         $alt = sprintf( __( 'Profile picture of %s', 'buddypress' ), $activities_template->activity->display_name );
    1690                                 }
    1691 
    1692                                 break;
    1693                 }
    1694 
    1695                 /**
    1696                  * Filters the activity secondary avatar object based on current activity item component.
    1697                  *
    1698                  * This is a variable filter dependent on the component used. Possible hooks are
    1699                  * bp_get_activity_secondary_avatar_object_blog, bp_get_activity_secondary_avatar_object_group,
    1700                  * and bp_get_activity_secondary_avatar_object_user.
    1701                  *
    1702                  * @since 1.2.10
    1703                  *
    1704                  * @param string $object Component being displayed.
    1705                  */
    1706                 $object  = apply_filters( 'bp_get_activity_secondary_avatar_object_' . $activities_template->activity->component, $object );
    1707 
    1708                 /**
    1709                  * Filters the activity secondary avatar item ID.
    1710                  *
    1711                  * @since 1.2.10
    1712                  *
    1713                  * @param int $item_id ID for the secondary avatar item.
    1714                  */
    1715                 $item_id = apply_filters( 'bp_get_activity_secondary_avatar_item_id', $item_id );
    1716 
    1717                 // If we have no item_id or object, there is no avatar to display.
    1718                 if ( empty( $item_id ) || empty( $object ) ) {
    1719                         return false;
    1720                 }
    1721 
    1722                 // Get the avatar.
    1723                 $avatar = bp_core_fetch_avatar( array(
    1724                         'item_id' => $item_id,
    1725                         'object'  => $object,
    1726                         'type'    => $type,
    1727                         'alt'     => $alt,
    1728                         'class'   => $class,
    1729                         'width'   => $width,
    1730                         'height'  => $height,
    1731                         'email'   => $email
    1732                 ) );
    1733 
    1734                 if ( !empty( $linked ) ) {
    1735 
    1736                         /**
    1737                          * Filters the secondary avatar link for current activity.
    1738                          *
    1739                          * @since 1.7.0
    1740                          *
    1741                          * @param string $link      Link to wrap the avatar image in.
    1742                          * @param string $component Activity component being acted on.
    1743                          */
    1744                         $link = apply_filters( 'bp_get_activity_secondary_avatar_link', $link, $activities_template->activity->component );
    1745 
    1746                         /**
    1747                          * Filters the determined avatar for the secondary activity item.
    1748                          *
    1749                          * @since 1.2.10
    1750                          *
    1751                          * @param string $avatar Formatted HTML <img> element, or raw avatar URL.
    1752                          */
    1753                         $avatar = apply_filters( 'bp_get_activity_secondary_avatar', $avatar );
    1754 
    1755                         return sprintf( '<a href="%s" class="%s">%s</a>',
    1756                                 $link,
    1757                                 $link_class,
    1758                                 $avatar
    1759                         );
    1760                 }
    1761 
    1762                 /** This filter is documented in bp-activity/bp-activity-template.php */
    1763                 return apply_filters( 'bp_get_activity_secondary_avatar', $avatar );
    1764         }
    1765 
    1766 /**
    1767  * Output the activity action.
    1768  *
    1769  * @since 1.2.0
    1770  *
    1771  * @param array $args See bp_get_activity_action().
    1772  * @uses bp_get_activity_action()
    1773  */
    1774 function bp_activity_action( $args = array() ) {
    1775         echo bp_get_activity_action( $args );
    1776 }
    1777 
    1778         /**
    1779          * Return the activity action.
    1780          *
    1781          * @since 1.2.0
    1782          *
    1783          * @global object $activities_template {@link BP_Activity_Template}
    1784          * @uses apply_filters_ref_array() To call the 'bp_get_activity_action_pre_meta' hook.
    1785          * @uses bp_insert_activity_meta()
    1786          * @uses apply_filters_ref_array() To call the 'bp_get_activity_action' hook.
    1787          *
    1788          * @param array $args {
    1789          *     @type bool $no_timestamp Whether to exclude the timestamp.
    1790          * }
    1791          *
    1792          * @return string The activity action.
    1793          */
    1794         function bp_get_activity_action( $args = array() ) {
    1795                 global $activities_template;
    1796 
    1797                 $r = wp_parse_args( $args, array(
    1798                         'no_timestamp' => false,
    1799                 ) );
    1800 
    1801                 /**
    1802                  * Filters the activity action before the action is inserted as meta.
    1803                  *
    1804                  * @since 1.2.10
    1805                  *
    1806                  * @param array $value Array containing the current action, the current activity, and the $args array passed into the function.
    1807                  */
    1808                 $action = apply_filters_ref_array( 'bp_get_activity_action_pre_meta', array(
    1809                         $activities_template->activity->action,
    1810                         &$activities_template->activity,
    1811                         $r
    1812                 ) );
    1813 
    1814                 // Prepend the activity action meta (link, time since, etc...).
    1815                 if ( ! empty( $action ) && empty( $r['no_timestamp'] ) ) {
    1816                         $action = bp_insert_activity_meta( $action );
    1817                 }
    1818 
    1819                 /**
    1820                  * Filters the activity action after the action has been inserted as meta.
    1821                  *
    1822                  * @since 1.2.0
    1823                  *
    1824                  * @param array $value Array containing the current action, the current activity, and the $args array passed into the function.
    1825                  */
    1826                 return apply_filters_ref_array( 'bp_get_activity_action', array(
    1827                         $action,
    1828                         &$activities_template->activity,
    1829                         $r
    1830                 ) );
    1831         }
    1832 
    1833 /**
    1834  * Output the activity content body.
    1835  *
    1836  * @since 1.2.0
    1837  *
    1838  * @uses bp_get_activity_content_body()
    1839  */
    1840 function bp_activity_content_body() {
    1841         echo bp_get_activity_content_body();
    1842 }
    1843 
    1844         /**
    1845          * Return the activity content body.
    1846          *
    1847          * @since 1.2.0
    1848          *
    1849          * @global object $activities_template {@link BP_Activity_Template}
    1850          * @uses bp_insert_activity_meta()
    1851          * @uses apply_filters_ref_array() To call the 'bp_get_activity_content_body' hook.
    1852          *
    1853          * @return string The activity content body.
    1854          */
    1855         function bp_get_activity_content_body() {
    1856                 global $activities_template;
    1857 
    1858                 // Backwards compatibility if action is not being used.
    1859                 if ( empty( $activities_template->activity->action ) && ! empty( $activities_template->activity->content ) ) {
    1860                         $activities_template->activity->content = bp_insert_activity_meta( $activities_template->activity->content );
    1861                 }
    1862 
    1863                 /**
    1864                  * Filters the activity content body.
    1865                  *
    1866                  * @since 1.2.0
    1867                  *
    1868                  * @param array $value Array containing the current activity content body and the current activity.
    1869                  */
    1870                 return apply_filters_ref_array( 'bp_get_activity_content_body', array( $activities_template->activity->content, &$activities_template->activity ) );
    1871         }
    1872 
    1873 /**
    1874  * Does the activity have content?
    1875  *
    1876  * @since 1.2.0
    1877  *
    1878  * @global object $activities_template {@link BP_Activity_Template}
    1879  *
    1880  * @return bool True if activity has content, false otherwise.
    1881  */
    1882 function bp_activity_has_content() {
    1883         global $activities_template;
    1884 
    1885         if ( ! empty( $activities_template->activity->content ) ) {
    1886                 return true;
    1887         }
    1888 
    1889         return false;
    1890 }
    1891 
    1892 /**
    1893  * Output the activity content.
    1894  *
    1895  * @since 1.0.0
    1896  * @deprecated 1.5.0
    1897  *
    1898  * @todo properly deprecate this function.
    1899  *
    1900  * @uses bp_get_activity_content()
    1901  */
    1902 function bp_activity_content() {
    1903         echo bp_get_activity_content();
    1904 }
    1905 
    1906         /**
    1907          * Return the activity content.
    1908          *
    1909          * @since 1.0.0
    1910          * @deprecated 1.5.0
    1911          *
    1912          * @todo properly deprecate this function.
    1913          *
    1914          * @uses bp_get_activity_action()
    1915          * @uses bp_get_activity_content_body()
    1916          * @uses apply_filters() To call the 'bp_get_activity_content' hook.
    1917          *
    1918          * @return string The activity content.
    1919          */
    1920         function bp_get_activity_content() {
    1921 
    1922                 /**
    1923                  * If you want to filter activity update content, please use
    1924                  * the filter 'bp_get_activity_content_body'.
    1925                  *
    1926                  * This function is mainly for backwards compatibility.
    1927                  */
    1928                 $content = bp_get_activity_action() . ' ' . bp_get_activity_content_body();
    1929                 return apply_filters( 'bp_get_activity_content', $content );
    1930         }
    1931 
    1932 /**
    1933  * Attach metadata about an activity item to the activity content.
    1934  *
    1935  * This metadata includes the time since the item was posted (which will appear
    1936  * as a link to the item's permalink).
    1937  *
    1938  * @since 1.2.0
    1939  *
    1940  * @global object $activities_template {@link BP_Activity_Template}
    1941  * @uses bp_core_time_since()
    1942  * @uses apply_filters_ref_array() To call the 'bp_activity_time_since' hook.
    1943  * @uses bp_is_single_activity()
    1944  * @uses bp_activity_get_permalink()
    1945  * @uses esc_attr__()
    1946  * @uses apply_filters_ref_array() To call the 'bp_activity_permalink' hook.
    1947  * @uses apply_filters() To call the 'bp_insert_activity_meta' hook.
    1948  *
    1949  * @param string $content The activity content.
    1950  * @return string The activity content with the metadata string attached.
    1951  */
    1952 function bp_insert_activity_meta( $content = '' ) {
    1953         global $activities_template;
    1954 
    1955         // Strip any legacy time since placeholders from BP 1.0-1.1.
    1956         $new_content = str_replace( '<span class="time-since">%s</span>', '', $content );
    1957 
    1958         // Get the time since this activity was recorded.
    1959         $date_recorded  = bp_core_time_since( $activities_template->activity->date_recorded );
    1960 
    1961         /**
    1962          * Filters the activity item time since markup.
    1963          *
    1964          * @since 1.2.0
    1965          *
    1966          * @param array $value Array containing the time since markup and the current activity component.
    1967          */
    1968         $time_since = apply_filters_ref_array( 'bp_activity_time_since', array(
    1969                 '<span class="time-since">' . $date_recorded . '</span>',
    1970                 &$activities_template->activity
    1971         ) );
    1972 
    1973         // Insert the permalink.
    1974         if ( ! bp_is_single_activity() ) {
    1975 
    1976                 // Setup variables for activity meta.
    1977                 $activity_permalink = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
    1978                 $activity_meta      = sprintf( '%1$s <a href="%2$s" class="view activity-time-since" title="%3$s">%4$s</a>',
    1979                         $new_content,
    1980                         $activity_permalink,
    1981                         esc_attr__( 'View Discussion', 'buddypress' ),
    1982                         $time_since
    1983                 );
    1984 
    1985                 /**
    1986                  * Filters the activity permalink to be added to the activity content.
    1987                  *
    1988                  * @since 1.2.0
    1989                  *
    1990                  * @param array $value Array containing the html markup for the activity permalink, after being parsed by
    1991                  *                     sprintf and current activity component.
    1992                  */
    1993                 $new_content = apply_filters_ref_array( 'bp_activity_permalink', array(
    1994                         $activity_meta,
    1995                         &$activities_template->activity
    1996                 ) );
    1997         } else {
    1998                 $new_content .= str_pad( $time_since, strlen( $time_since ) + 2, ' ', STR_PAD_BOTH );
    1999         }
    2000 
    2001         /**
    2002          * Filters the activity content after activity metadata has been attached.
    2003          *
    2004          * @since 1.2.0
    2005          *
    2006          * @param string $content Activity content with the activity metadata added.
    2007          */
    2008         return apply_filters( 'bp_insert_activity_meta', $new_content, $content );
    2009 }
    2010 
    2011 /**
    2012  * Determine if the current user can delete an activity item.
    2013  *
    2014  * @since 1.2.0
    2015  *
    2016  * @global object $activities_template {@link BP_Activity_Template}
    2017  * @uses apply_filters() To call the 'bp_activity_user_can_delete' hook.
    2018  *
    2019  * @param object|bool $activity Optional. Falls back on the current item in the loop.
    2020  * @return bool True if can delete, false otherwise.
    2021  */
    2022 function bp_activity_user_can_delete( $activity = false ) {
    2023         global $activities_template;
    2024 
    2025         // Try to use current activity if none was passed.
    2026         if ( empty( $activity ) && ! empty( $activities_template->activity ) ) {
    2027                 $activity = $activities_template->activity;
    2028         }
    2029 
    2030         // If current_comment is set, we'll use that in place of the main activity.
    2031         if ( isset( $activity->current_comment ) ) {
    2032                 $activity = $activity->current_comment;
    2033         }
    2034 
    2035         // Assume the user cannot delete the activity item.
    2036         $can_delete = false;
    2037 
    2038         // Only logged in users can delete activity.
    2039         if ( is_user_logged_in() ) {
    2040 
    2041                 // Community moderators can always delete activity (at least for now).
    2042                 if ( bp_current_user_can( 'bp_moderate' ) ) {
    2043                         $can_delete = true;
    2044                 }
    2045 
    2046                 // Users are allowed to delete their own activity. This is actually
    2047                 // quite powerful, because doing so also deletes all comments to that
    2048                 // activity item. We should revisit this eventually.
    2049                 if ( isset( $activity->user_id ) && ( (int) $activity->user_id === bp_loggedin_user_id() ) ) {
    2050                         $can_delete = true;
    2051                 }
    2052 
    2053                 // Viewing a single item, and this user is an admin of that item.
    2054                 if ( bp_is_single_item() && bp_is_item_admin() ) {
    2055                         $can_delete = true;
    2056                 }
    2057         }
    2058 
    2059         /**
    2060          * Filters whether the current user can delete an activity item.
    2061          *
    2062          * @since 1.5.0
    2063          *
    2064          * @param bool   $can_delete Whether the user can delete the item.
    2065          * @param object $activity   Current activity item object.
    2066          */
    2067         return (bool) apply_filters( 'bp_activity_user_can_delete', $can_delete, $activity );
    2068 }
    2069 
    2070 /**
    2071  * Output the activity parent content.
    2072  *
    2073  * @since 1.2.0
    2074  *
    2075  * @see bp_get_activity_parent_content() for a description of arguments.
    2076  * @uses bp_get_activity_parent_content()
    2077  *
    2078  * @param array|string $args See {@link bp_get_activity_parent_content} for description.
    2079  */
    2080 function bp_activity_parent_content( $args = '' ) {
    2081         echo bp_get_activity_parent_content($args);
    2082 }
    2083 
    2084         /**
    2085          * Return the activity content.
    2086          *
    2087          * @since 1.2.0
    2088          *
    2089          * @global object $activities_template {@link BP_Activity_Template}
    2090          * @uses apply_filters() To call the 'bp_get_activity_parent_content' hook.
    2091          *
    2092          * @param string $args Unused. Left over from an earlier implementation.
    2093          * @return mixed False on failure, otherwise the activity parent content.
    2094          */
    2095         function bp_get_activity_parent_content( $args = '' ) {
    2096                 global $activities_template;
    2097 
    2098                 // Bail if no activity on no item ID.
    2099                 if ( empty( $activities_template->activity ) || empty( $activities_template->activity->item_id ) ) {
    2100                         return false;
    2101                 }
    2102 
    2103                 // Get the ID of the parent activity content.
    2104                 $parent_id = (int) $activities_template->activity->item_id;
    2105 
    2106                 // Bail if no parent content.
    2107                 if ( empty( $activities_template->activity_parents[ $parent_id ] ) ) {
    2108                         return false;
    2109                 }
    2110 
    2111                 // Bail if no action.
    2112                 if ( empty( $activities_template->activity_parents[ $parent_id ]->action ) ) {
    2113                         return false;
    2114                 }
    2115 
    2116                 // Content always includes action.
    2117                 $content = $activities_template->activity_parents[ $parent_id ]->action;
    2118 
    2119                 // Maybe append activity content, if it exists.
    2120                 if ( ! empty( $activities_template->activity_parents[ $parent_id ]->content ) ) {
    2121                         $content .= ' ' . $activities_template->activity_parents[ $parent_id ]->content;
    2122                 }
    2123 
    2124                 // Remove the time since content for backwards compatibility.
    2125                 $content = str_replace( '<span class="time-since">%s</span>', '', $content );
    2126 
    2127                 // Remove images.
    2128                 $content = preg_replace( '/<img[^>]*>/Ui', '', $content );
    2129 
    2130                 /**
    2131                  * Filters the activity parent content.
    2132                  *
    2133                  * @since 1.2.0
    2134                  *
    2135                  * @param string $content Content set to be displayed as parent content.
    2136                  */
    2137                 return apply_filters( 'bp_get_activity_parent_content', $content );
    2138         }
    2139 
    2140 /**
    2141  * Output the parent activity's user ID.
    2142  *
    2143  * @since 1.7.0
    2144  */
    2145 function bp_activity_parent_user_id() {
    2146         echo bp_get_activity_parent_user_id();
    2147 }
    2148 
    2149         /**
    2150          * Return the parent activity's user ID.
    2151          *
    2152          * @since 1.7.0
    2153          *
    2154          * @global BP_Activity_Template $activities_template
    2155          *
    2156          * @return bool|int False if parent activity can't be found, otherwise
    2157          *                  the parent activity's user ID.
    2158          */
    2159         function bp_get_activity_parent_user_id() {
    2160                 global $activities_template;
    2161 
    2162                 // Bail if no activity on no item ID.
    2163                 if ( empty( $activities_template->activity ) || empty( $activities_template->activity->item_id ) ) {
    2164                         return false;
    2165                 }
    2166 
    2167                 // Get the ID of the parent activity content.
    2168                 $parent_id = (int) $activities_template->activity->item_id;
    2169 
    2170                 // Bail if no parent item.
    2171                 if ( empty( $activities_template->activity_parents[ $parent_id ] ) ) {
    2172                         return false;
    2173                 }
    2174 
    2175                 // Bail if no parent user ID.
    2176                 if ( empty( $activities_template->activity_parents[ $parent_id ]->user_id ) ) {
    2177                         return false;
    2178                 }
    2179 
    2180                 $retval = $activities_template->activity_parents[ $parent_id ]->user_id;
    2181 
    2182                 /**
    2183                  * Filters the activity parent item's user ID.
    2184                  *
    2185                  * @since 1.7.0
    2186                  *
    2187                  * @param int $retval ID for the activity parent's user.
    2188                  */
    2189                 return (int) apply_filters( 'bp_get_activity_parent_user_id', $retval );
    2190         }
    2191 
    2192 /**
    2193  * Output whether or not the current activity is in a current user's favorites.
    2194  *
    2195  * @since 1.2.0
    2196  *
    2197  * @uses bp_get_activity_is_favorite()
    2198  */
    2199 function bp_activity_is_favorite() {
    2200         echo bp_get_activity_is_favorite();
    2201 }
    2202 
    2203         /**
    2204          * Return whether the current activity is in a current user's favorites.
    2205          *
    2206          * @since 1.2.0
    2207          *
    2208          * @global object $activities_template {@link BP_Activity_Template}
    2209          * @uses apply_filters() To call the 'bp_get_activity_is_favorite' hook.
    2210          *
    2211          * @return bool True if user favorite, false otherwise.
    2212          */
    2213         function bp_get_activity_is_favorite() {
    2214                 global $activities_template;
    2215 
    2216                 /**
    2217                  * Filters whether the current activity item is in the current user's favorites.
    2218                  *
    2219                  * @since 1.2.0
    2220                  *
    2221                  * @param bool $value Whether or not the current activity item is in the current user's favorites.
    2222                  */
    2223                 return (bool) apply_filters( 'bp_get_activity_is_favorite', in_array( $activities_template->activity->id, (array) $activities_template->my_favs ) );
    2224         }
    2225 
    2226 /**
    2227  * Output the comment markup for an activity item.
    2228  *
    2229  * @since 1.2.0
    2230  *
    2231  * @todo deprecate $args param
    2232  *
    2233  * @param array|string $args See {@link bp_activity_get_comments} for description.
    2234  */
    2235 function bp_activity_comments( $args = '' ) {
    2236         echo bp_activity_get_comments( $args );
    2237 }
    2238 
    2239         /**
    2240          * Get the comment markup for an activity item.
    2241          *
    2242          * @since 1.2.0
    2243          *
    2244          * @todo deprecate $args param
    2245          * @todo Given that checks for children already happen in bp_activity_recurse_comments(),
    2246          *       this function can probably be streamlined or removed.
    2247          *
    2248          * @global object $activities_template {@link BP_Activity_Template}
    2249          * @uses bp_activity_recurse_comments()
    2250          *
    2251          * @param string $args Unused. Left over from an earlier implementation.
    2252          * @return bool
    2253          */
    2254         function bp_activity_get_comments( $args = '' ) {
    2255                 global $activities_template;
    2256 
    2257                 if ( empty( $activities_template->activity->children ) ) {
    2258                         return false;
    2259                 }
    2260 
    2261                 bp_activity_recurse_comments( $activities_template->activity );
    2262         }
    2263 
    2264                 /**
    2265                  * Loops through a level of activity comments and loads the template for each.
    2266                  *
    2267                  * Note: The recursion itself used to happen entirely in this function. Now it is
    2268                  * split between here and the comment.php template.
    2269                  *
    2270                  * @since 1.2.0
    2271                  *
    2272                  * @global object $activities_template {@link BP_Activity_Template}
    2273                  * @uses locate_template()
    2274                  *
    2275                  * @param object $comment The activity object currently being recursed.
    2276                  * @return bool|string
    2277                  */
    2278                 function bp_activity_recurse_comments( $comment ) {
    2279                         global $activities_template;
    2280 
    2281                         if ( empty( $comment ) ) {
    2282                                 return false;
    2283                         }
    2284 
    2285                         if ( empty( $comment->children ) ) {
    2286                                 return false;
    2287                         }
    2288 
    2289                         /**
    2290                          * Filters the opening tag for the template that lists activity comments.
    2291                          *
    2292                          * @since 1.6.0
    2293                          *
    2294                          * @param string $value Opening tag for the HTML markup to use.
    2295                          */
    2296                         echo apply_filters( 'bp_activity_recurse_comments_start_ul', '<ul>' );
    2297                         foreach ( (array) $comment->children as $comment_child ) {
    2298 
    2299                                 // Put the comment into the global so it's available to filters.
    2300                                 $activities_template->activity->current_comment = $comment_child;
    2301 
    2302                                 $template = bp_locate_template( 'activity/comment.php', false, false );
    2303 
    2304                                 // Backward compatibility. In older versions of BP, the markup was
    2305                                 // generated in the PHP instead of a template. This ensures that
    2306                                 // older themes (which are not children of bp-default and won't
    2307                                 // have the new template) will still work.
    2308                                 if ( !$template ) {
    2309                                         $template = buddypress()->plugin_dir . '/bp-themes/bp-default/activity/comment.php';
    2310                                 }
    2311 
    2312                                 load_template( $template, false );
    2313 
    2314                                 unset( $activities_template->activity->current_comment );
    2315                         }
    2316 
    2317                         /**
    2318                          * Filters the closing tag for the template that list activity comments.
    2319                          *
    2320                          * @since  1.6.0
    2321                          *
    2322                          * @param string $value Closing tag for the HTML markup to use.
    2323                          */
    2324                         echo apply_filters( 'bp_activity_recurse_comments_end_ul', '</ul>' );
    2325                 }
    2326 
    2327 /**
    2328  * Utility function that returns the comment currently being recursed.
    2329  *
    2330  * @since 1.5.0
    2331  *
    2332  * @global object $activities_template {@link BP_Activity_Template}
    2333  * @uses apply_filters() To call the 'bp_activity_current_comment' hook.
    2334  *
    2335  * @return object|bool $current_comment The activity comment currently being
    2336  *                                      displayed. False on failure.
    2337  */
    2338 function bp_activity_current_comment() {
    2339         global $activities_template;
    2340 
    2341         $current_comment = !empty( $activities_template->activity->current_comment )
    2342                 ? $activities_template->activity->current_comment
    2343                 : false;
    2344 
    2345         /**
    2346          * Filters the current comment being recursed.
    2347          *
    2348          * @since 1.5.0
    2349          *
    2350          * @param object|bool $current_comment The activity comment currently being displayed. False on failure.
    2351          */
    2352         return apply_filters( 'bp_activity_current_comment', $current_comment );
    2353 }
    2354 
    2355 
    2356 /**
    2357  * Output the ID of the activity comment currently being displayed.
    2358  *
    2359  * @since 1.5.0
    2360  *
    2361  * @uses bp_get_activity_comment_id()
    2362  */
    2363 function bp_activity_comment_id() {
    2364         echo bp_get_activity_comment_id();
    2365 }
    2366 
    2367         /**
    2368          * Return the ID of the activity comment currently being displayed.
    2369          *
    2370          * @since 1.5.0
    2371          *
    2372          * @global object $activities_template {@link BP_Activity_Template}
    2373          * @uses apply_filters() To call the 'bp_activity_comment_id' hook.
    2374          *
    2375          * @return int|bool $comment_id The ID of the activity comment currently
    2376          *                              being displayed, false if none is found.
    2377          */
    2378         function bp_get_activity_comment_id() {
    2379                 global $activities_template;
    2380 
    2381                 $comment_id = isset( $activities_template->activity->current_comment->id ) ? $activities_template->activity->current_comment->id : false;
    2382 
    2383                 /**
    2384                  * Filters the ID of the activity comment currently being displayed.
    2385                  *
    2386                  * @since 1.5.0
    2387                  *
    2388                  * @param int|bool $comment_id ID for the comment currently being displayed.
    2389                  */
    2390                 return apply_filters( 'bp_activity_comment_id', $comment_id );
    2391         }
    2392 
    2393 /**
    2394  * Output the ID of the author of the activity comment currently being displayed.
    2395  *
    2396  * @since 1.5.0
    2397  *
    2398  * @uses bp_get_activity_comment_user_id()
    2399  */
    2400 function bp_activity_comment_user_id() {
    2401         echo bp_get_activity_comment_user_id();
    2402 }
    2403 
    2404         /**
    2405          * Return the ID of the author of the activity comment currently being displayed.
    2406          *
    2407          * @since 1.5.0
    2408          *
    2409          * @global object $activities_template {@link BP_Activity_Template}
    2410          * @uses apply_filters() To call the 'bp_activity_comment_user_id' hook.
    2411          *
    2412          * @return int|bool $user_id The user_id of the author of the displayed
    2413          *                           activity comment. False on failure.
    2414          */
    2415         function bp_get_activity_comment_user_id() {
    2416                 global $activities_template;
    2417 
    2418                 $user_id = isset( $activities_template->activity->current_comment->user_id ) ? $activities_template->activity->current_comment->user_id : false;
    2419 
    2420                 /**
    2421                  * Filters the ID of the author of the activity comment currently being displayed.
    2422                  *
    2423                  * @since 1.5.0
    2424                  *
    2425                  * @param int|bool $user_id ID for the author of the comment currently being displayed.
    2426                  */
    2427                 return apply_filters( 'bp_activity_comment_user_id', $user_id );
    2428         }
    2429 
    2430 /**
    2431  * Output the author link for the activity comment currently being displayed.
    2432  *
    2433  * @since 1.5.0
    2434  *
    2435  * @uses bp_get_activity_comment_user_link()
    2436  */
    2437 function bp_activity_comment_user_link() {
    2438         echo bp_get_activity_comment_user_link();
    2439 }
    2440 
    2441         /**
    2442          * Return the author link for the activity comment currently being displayed.
    2443       &n