Skip to:
Content

BuddyPress.org

Changeset 10516


Ignore:
Timestamp:
02/05/2016 03:54:56 AM (5 years ago)
Author:
boonebgorges
Message:

Move bp-activity classes to their own files.

See #6870.

Location:
trunk/src/bp-activity
Files:
5 edited
5 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-activity/bp-activity-admin.php

    r10487 r10516  
    1616// Include WP's list table class.
    1717if ( !class_exists( 'WP_List_Table' ) ) require( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
     18
     19require dirname( __FILE__ ) . '/classes/class-bp-activity-list-table.php';
    1820
    1921// Per_page screen option. Has to be hooked in extremely early.
     
    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 }
  • trunk/src/bp-activity/bp-activity-akismet.php

    r10455 r10516  
    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 {
    20 
    21     /**
    22      * The activity last marked as spam.
    23      *
    24      * @since 1.6.0
    25      * @var BP_Activity_Activity
    26      */
    27     protected $last_activity = null;
    28 
    29     /**
    30      * Constructor.
    31      *
    32      * @since 1.6.0
    33      */
    34     public function __construct() {
    35         $this->setup_actions();
    36     }
    37 
    38     /**
    39      * Hook Akismet into the activity stream.
    40      *
    41      * @since 1.6.0
    42      */
    43     protected function setup_actions() {
    44         // Add nonces to activity stream lists.
    45         add_action( 'bp_after_activity_post_form', array( $this, 'add_activity_stream_nonce' ) );
    46         add_action( 'bp_activity_entry_comments',  array( $this, 'add_activity_stream_nonce' ) );
    47 
    48         // Add a "mark as spam" button to individual activity items.
    49         add_action( 'bp_activity_entry_meta',      array( $this, 'add_activity_spam_button' ) );
    50         add_action( 'bp_activity_comment_options', array( $this, 'add_activity_comment_spam_button' ) );
    51 
    52         // Check activity for spam.
    53         add_action( 'bp_activity_before_save',     array( $this, 'check_activity' ), 4, 1 );
    54 
    55         // Tidy up member's latest (activity) update.
    56         add_action( 'bp_activity_posted_update',   array( $this, 'check_member_activity_update' ), 1, 3 );
    57 
    58         // Hooks to extend Activity core spam/ham functions for Akismet.
    59         add_action( 'bp_activity_mark_as_spam',    array( $this, 'mark_as_spam' ), 10, 2 );
    60         add_action( 'bp_activity_mark_as_ham',     array( $this, 'mark_as_ham' ),  10, 2 );
    61 
    62         // Hook into the Activity wp-admin screen.
    63         add_action( 'bp_activity_admin_comment_row_actions', array( $this, 'comment_row_action' ), 10, 2 );
    64         add_action( 'bp_activity_admin_load',                array( $this, 'add_history_metabox' ) );
    65     }
    66 
    67     /**
    68      * Add a history item to the hover links in an activity's row.
    69      *
    70      * This function lifted with love from the Akismet WordPress plugin's
    71      * akismet_comment_row_action() function. Thanks!
    72      *
    73      * @since 1.6.0
    74      *
    75      * @param array $actions  The hover links.
    76      * @param array $activity The activity for the current row being processed.
    77      * @return array The hover links.
    78      */
    79     function comment_row_action( $actions, $activity ) {
    80         $akismet_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_result' );
    81         $user_result    = bp_activity_get_meta( $activity['id'], '_bp_akismet_user_result' );
    82         $desc           = '';
    83 
    84         if ( !$user_result || $user_result == $akismet_result ) {
    85             // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same.
    86             if ( 'true' == $akismet_result && $activity['is_spam'] )
    87                 $desc = __( 'Flagged as spam by Akismet', 'buddypress' );
    88 
    89             elseif ( 'false' == $akismet_result && !$activity['is_spam'] )
    90                 $desc = __( 'Cleared by Akismet', 'buddypress' );
    91 
    92         } else {
    93             $who = bp_activity_get_meta( $activity['id'], '_bp_akismet_user' );
    94 
    95             if ( 'true' == $user_result )
    96                 $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 }
     13require dirname( __FILE__ ) . '/classes/class-bp-akismet.php';
    65214
    65315/**
  • trunk/src/bp-activity/bp-activity-loader.php

    r10455 r10516  
    1313defined( 'ABSPATH' ) || exit;
    1414
    15 /**
    16  * Main Activity Class.
    17  *
    18  * @since 1.5.0
    19  */
    20 class BP_Activity_Component extends BP_Component {
    21 
    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 }
     15require dirname( __FILE__ ) . '/classes/class-bp-activity-component.php';
    38916
    39017/**
  • trunk/src/bp-activity/bp-activity-screens.php

    r10417 r10516  
    1414// Exit if accessed directly.
    1515defined( 'ABSPATH' ) || exit;
     16
     17require dirname( __FILE__ ) . '/classes/class-bp-activity-theme-compat.php';
    1618
    1719/**
     
    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();
  • trunk/src/bp-activity/bp-activity-template.php

    r10487 r10516  
    1010// Exit if accessed directly.
    1111defined( 'ABSPATH' ) || exit;
     12
     13require dirname( __FILE__ ) . '/classes/class-bp-activity-template.php';
    1214
    1315/**
     
    106108        return apply_filters( 'bp_get_activity_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_activity_root_slug() ) );
    107109    }
    108 
    109 /**
    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 }
    506110
    507111/**
  • trunk/src/bp-activity/classes/class-bp-activity-component.php

    r10515 r10516  
    387387    }
    388388}
    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 );
  • trunk/src/bp-activity/classes/class-bp-activity-list-table.php

    r10515 r10516  
    11<?php
    22/**
    3  * BuddyPress Activity component admin screen.
     3 * BuddyPress Activity component admin list table.
    44 *
    55 * Props to WordPress core for the Comments admin screen, and its contextual
     
    1313// Exit if accessed directly.
    1414defined( '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 
    23 /**
    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 }
    104115
    104216/**
  • trunk/src/bp-activity/classes/class-bp-activity-template.php

    r10515 r10516  
    11<?php
    22/**
    3  * BuddyPress Activity Template Functions.
     3 * BuddyPress Activity Template.
    44 *
    55 * @package BuddyPress
     
    1010// Exit if accessed directly.
    1111defined( 'ABSPATH' ) || exit;
    12 
    13 /**
    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     }
    10812
    10913/**
     
    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      *
    2444      * @since 1.5.0
    2445      *
    2446      * @uses bp_core_get_user_domain()
    2447      * @uses bp_get_activity_comment_user_id()
    2448      * @uses apply_filters() To call the 'bp_activity_comment_user_link' hook.
    2449      *
    2450      * @return string $user_link The URL of the activity comment author's profile.
    2451      */
    2452     function bp_get_activity_comment_user_link() {
    2453         $user_link = bp_core_get_user_domain( bp_get_activity_comment_user_id() );
    2454 
    2455         /**
    2456          * Filters the author link for the activity comment currently being displayed.
    2457          *
    2458          * @since 1.5.0
    2459          *
    2460          * @param string $user_link Link for the author of the activity comment currently being displayed.
    2461          */
    2462         return apply_filters( 'bp_activity_comment_user_link', $user_link );
    2463     }
    2464 
    2465 /**
    2466  * Output the author name for the activity comment currently being displayed.
    2467  *
    2468  * @since 1.5.0
    2469  *
    2470  * @uses bp_get_activity_comment_name()
    2471  */
    2472 function bp_activity_comment_name() {
    2473     echo bp_get_activity_comment_name();
    2474 }
    2475 
    2476     /**
    2477      * Return the author name for the activity comment currently being displayed.
    2478      *
    2479      * The use of the 'bp_acomment_name' filter is deprecated. Please use
    2480      * 'bp_activity_comment_name'.
    2481      *
    2482      * @since 1.5.0
    2483      *
    2484      * @global object $activities_template {@link BP_Activity_Template}
    2485      * @uses apply_filters() To call the 'bp_acomment_name' hook.
    2486      * @uses apply_filters() To call the 'bp_activity_comment_name' hook.
    2487      *
    2488      * @return string $name The full name of the activity comment author.
    2489      */
    2490     function bp_get_activity_comment_name() {
    2491         global $activities_template;
    2492 
    2493         if ( isset( $activities_template->activity->current_comment->user_fullname ) ) {
    2494 
    2495             $name = apply_filters( 'bp_acomment_name', $activities_template->activity->current_comment->user_fullname, $activities_template->activity->current_comment );  // Backward compatibility.
    2496         } else {
    2497             $name = $activities_template->activity->current_comment->display_name;
    2498         }
    2499 
    2500         /**
    2501          * Filters the name of the author for the activity comment.
    2502          *
    2503          * @since 1.5.0
    2504          *
    2505          * @param string $name Name to be displayed with the activity comment.
    2506          */
    2507         return apply_filters( 'bp_activity_comment_name', $name );
    2508     }
    2509 
    2510 /**
    2511  * Output the formatted date_recorded of the activity comment currently being displayed.
    2512  *
    2513  * @since 1.5.0
    2514  *
    2515  * @uses bp_get_activity_comment_date_recorded()
    2516  */
    2517 function bp_activity_comment_date_recorded() {
    2518     echo bp_get_activity_comment_date_recorded();
    2519 }
    2520 
    2521     /**
    2522      * Return the formatted date_recorded for the activity comment currently being displayed.
    2523      *
    2524      * @since 1.5.0
    2525      *
    2526      * @uses bp_core_time_since()
    2527      * @uses apply_filters() To call the 'bp_activity_comment_date_recorded' hook.
    2528      *
    2529      * @return string|bool $date_recorded Time since the activity was recorded,
    2530      *                                    in the form "%s ago". False on failure.
    2531      */
    2532     function bp_get_activity_comment_date_recorded() {
    2533 
    2534         /**
    2535          * Filters the recorded date of the activity comment currently being displayed.
    2536          *
    2537          * @since 1.5.0
    2538          *
    2539          * @param string|bool Date for the activity comment currently being displayed.
    2540          */
    2541         return apply_filters( 'bp_activity_comment_date_recorded', bp_core_time_since( bp_get_activity_comment_date_recorded_raw() ) );
    2542     }
    2543 
    2544 /**
    2545  * Output the date_recorded of the activity comment currently being displayed.
    2546  *
    2547  * @since 2.3.0
    2548  *
    2549  * @uses bp_get_activity_comment_date_recorded()
    2550  */
    2551 function bp_activity_comment_date_recorded_raw() {
    2552     echo bp_get_activity_comment_date_recorded_raw();
    2553 }
    2554 
    2555     /**
    2556      * Return the date_recorded for the activity comment currently being displayed.
    2557      *
    2558      * @since 2.3.0
    2559      *
    2560      * @global object $activities_template {@link BP_Activity_Template}
    2561      * @uses bp_core_time_since()
    2562      * @uses apply_filters() To call the 'bp_activity_comment_date_recorded' hook.
    2563      *
    2564      * @return string|bool $date_recorded Time since the activity was recorded,
    2565      *                                    in the form "%s ago". False on failure.
    2566      */
    2567     function bp_get_activity_comment_date_recorded_raw() {
    2568         global $activities_template;
    2569 
    2570         /**
    2571          * Filters the raw recorded date of the activity comment currently being displayed.
    2572          *
    2573          * @since 2.3.0
    2574          *
    2575          * @param string|bool Raw date for the activity comment currently being displayed.
    2576          */
    2577         return apply_filters( 'bp_activity_comment_date_recorded', $activities_template->activity->current_comment->date_recorded );
    2578     }
    2579 
    2580 /**
    2581  * Output the 'delete' URL for the activity comment currently being displayed.
    2582  *
    2583  * @since 1.5.0
    2584  *
    2585  * @uses bp_get_activity_comment_delete_link()
    2586  */
    2587 function bp_activity_comment_delete_link() {
    2588     echo bp_get_activity_comment_delete_link();
    2589 }
    2590 
    2591     /**
    2592      * Gets the 'delete' URL for the activity comment currently being displayed.
    2593      *
    2594      * @since 1.5.0
    2595      *
    2596      * @uses wp_nonce_url()
    2597      * @uses bp_get_root_domain()
    2598      * @uses bp_get_activity_slug()
    2599      * @uses bp_get_activity_comment_id()
    2600      * @uses apply_filters() To call the 'bp_activity_comment_delete_link' hook.
    2601      *
    2602      * @return string $link The nonced URL for deleting the current
    2603      *                      activity comment.
    2604      */
    2605     function bp_get_activity_comment_delete_link() {
    2606         $link = wp_nonce_url( bp_get_root_domain() . '/' . bp_get_activity_slug() . '/delete/' . bp_get_activity_comment_id() . '?cid=' . bp_get_activity_comment_id(), 'bp_activity_delete_link' );
    2607 
    2608         /**
    2609          * Filters the link used for deleting the activity comment currently being displayed.
    2610          *
    2611          * @since 1.5.0
    2612          *
    2613          * @param string $link Link to use for deleting the currently displayed activity comment.
    2614          */
    2615         return apply_filters( 'bp_activity_comment_delete_link', $link );
    2616     }
    2617 
    2618 /**
    2619  * Output the content of the activity comment currently being displayed.
    2620  *
    2621  * @since 1.5.0
    2622  *
    2623  * @uses bp_get_activity_comment_content()
    2624  */
    2625 function bp_activity_comment_content() {
    2626     echo bp_get_activity_comment_content();
    2627 }
    2628 
    2629     /**
    2630      * Return the content of the activity comment currently being displayed.
    2631      *
    2632      * The content is run through two filters. 'bp_get_activity_content'
    2633      * will apply all filters applied to activity items in general. Use
    2634      * 'bp_activity_comment_content' to modify the content of activity
    2635      * comments only.
    2636      *
    2637      * @since 1.5.0
    2638      *
    2639      * @global object $activities_template {@link BP_Activity_Template}
    2640      * @uses apply_filters() To call the 'bp_get_activity_content' hook.
    2641      * @uses apply_filters() To call the 'bp_activity_comment_content' hook.
    2642      *
    2643      * @return string $content The content of the current activity comment.
    2644      */
    2645     function bp_get_activity_comment_content() {
    2646         global $activities_template;
    2647 
    2648         /** This filter is documented in bp-activity/bp-activity-template.php */
    2649         $content = apply_filters( 'bp_get_activity_content', $activities_template->activity->current_comment->content );
    2650 
    2651         /**
    2652          * Filters the content of the current activity comment.
    2653          *
    2654          * @since 1.2.0
    2655          *
    2656          * @param string $content The content of the current activity comment.
    2657          */
    2658         return apply_filters( 'bp_activity_comment_content', $content );
    2659     }
    2660 
    2661 /**
    2662  * Output the activity comment count.
    2663  *
    2664  * @since 1.2.0
    2665  *
    2666  * @uses bp_activity_get_comment_count()
    2667  */
    2668 function bp_activity_comment_count() {
    2669     echo bp_activity_get_comment_count();
    2670 }
    2671 
    2672     /**
    2673      * Return the comment count of an activity item.
    2674      *
    2675      * @since 1.2.0
    2676      *
    2677      * @global object $activities_template {@link BP_Activity_Template}
    2678      * @uses bp_activity_recurse_comment_count()
    2679      * @uses apply_filters() To call the 'bp_activity_get_comment_count' hook.
    2680      *
    2681      * @param array|null $deprecated Deprecated.
    2682      * @return int $count The activity comment count.
    2683      */
    2684     function bp_activity_get_comment_count( $deprecated = null ) {
    2685         global $activities_template;
    2686 
    2687         // Deprecated notice about $args.
    2688         if ( ! empty( $deprecated ) ) {
    2689             _deprecated_argument( __FUNCTION__, '1.2', sprintf( __( '%1$s no longer accepts arguments. See the inline documentation at %2$s for more details.', 'buddypress' ), __FUNCTION__, __FILE__ ) );
    2690         }
    2691 
    2692         // Get the count using the purpose-built recursive function.
    2693         $count = ! empty( $activities_template->activity->children )
    2694             ? bp_activity_recurse_comment_count( $activities_template->activity )
    2695             : 0;
    2696 
    2697         /**
    2698          * Filters the activity comment count.
    2699          *
    2700          * @since 1.2.0
    2701          *
    2702          * @param int $count The activity comment count.
    2703          */
    2704         return apply_filters( 'bp_activity_get_comment_count', (int) $count );
    2705     }
    2706 
    2707         /**
    2708          * Return the total number of comments to the current comment.
    2709          *
    2710          * This function recursively adds the total number of comments each
    2711          * activity child has, and returns them.
    2712          *
    2713          * @since 1.2.0
    2714          *
    2715          * @uses bp_activity_recurse_comment_count()
    2716          * @uses apply_filters() To call the 'bp_activity_recurse_comment_count' hook.
    2717          *
    2718          * @param object $comment Activity comment object.
    2719          * @param int    $count The current iteration count.
    2720          * @return int $count The activity comment count.
    2721          */
    2722         function bp_activity_recurse_comment_count( $comment, $count = 0 ) {
    2723 
    2724             // Copy the count.
    2725             $new_count = $count;
    2726 
    2727             // Loop through children and recursively count comments.
    2728             if ( ! empty( $comment->children ) ) {
    2729                 foreach ( (array) $comment->children as $comment ) {
    2730                     $new_count++;
    2731                     $new_count = bp_activity_recurse_comment_count( $comment, $new_count );
    2732                 }
    2733             }
    2734 
    2735             /**
    2736              * Filters the total number of comments for the current comment.
    2737              *
    2738              * @since 2.1.0
    2739              *
    2740              * @param int    $new_count New total count for the current comment.
    2741              * @param object $comment   Activity comment object.
    2742              * @param int    $count     Current iteration count for the current comment.
    2743              */
    2744             return apply_filters( 'bp_activity_recurse_comment_count', $new_count, $comment, $count );
    2745         }
    2746 
    2747 /**
    2748  * Output the depth of the current activity comment.
    2749  *
    2750  * @since 2.0.0
    2751  */
    2752 function bp_activity_comment_depth() {
    2753     echo bp_activity_get_comment_depth();
    2754 }
    2755     /**
    2756      * Return the current activity comment depth.
    2757      *
    2758      * @since 2.0.0
    2759      *
    2760      * @return int $depth Depth for the current activity comment.
    2761      */
    2762     function bp_activity_get_comment_depth() {
    2763         global $activities_template;
    2764 
    2765         /**
    2766          * Filters the comment depth of the current activity comment.
    2767          *
    2768          * @since 2.0.0
    2769          *
    2770          * @param int $depth Depth for the current activity comment.
    2771          */
    2772         return apply_filters( 'bp_activity_get_comment_depth', $activities_template->activity->current_comment->depth );
    2773     }
    2774 
    2775 /**
    2776  * Output the activity comment link.
    2777  *
    2778  * @since 1.2.0
    2779  *
    2780  * @uses bp_get_activity_comment_link()
    2781  */
    2782 function bp_activity_comment_link() {
    2783     echo bp_get_activity_comment_link();
    2784 }
    2785 
    2786     /**
    2787      * Return the activity comment link.
    2788      *
    2789      * @since 1.2.0
    2790      *
    2791      * @global object $activities_template {@link BP_Activity_Template}
    2792      * @uses apply_filters() To call the 'bp_get_activity_comment_link' hook.
    2793      *
    2794      * @return string The activity comment link.
    2795      */
    2796     function bp_get_activity_comment_link() {
    2797         global $activities_template;
    2798 
    2799         /**
    2800          * Filters the comment link for the current activity comment.
    2801          *
    2802          * @since 1.2.0
    2803          *
    2804          * @param string $value Constructed URL parameters with activity IDs.
    2805          */
    2806         return apply_filters( 'bp_get_activity_comment_link', '?ac=' . $activities_template->activity->id . '/#ac-form-' . $activities_template->activity->id );
    2807     }
    2808 
    2809 /**
    2810  * Output the activity comment form no JavaScript display CSS.
    2811  *
    2812  * @since 1.2.0
    2813  *
    2814  * @uses bp_get_activity_comment_form_nojs_display()
    2815  */
    2816 function bp_activity_comment_form_nojs_display() {
    2817     echo bp_get_activity_comment_form_nojs_display();
    2818 }
    2819 
    2820     /**
    2821      * Return the activity comment form no JavaScript display CSS.
    2822      *
    2823      * @since 1.2.0
    2824      *
    2825      * @global object $activities_template {@link BP_Activity_Template}
    2826      *
    2827      * @return string|bool The activity comment form no JavaScript
    2828      *                     display CSS. False on failure.
    2829      */
    2830     function bp_get_activity_comment_form_nojs_display() {
    2831         global $activities_template;
    2832 
    2833         if ( isset( $_GET['ac'] ) && ( $_GET['ac'] === ( $activities_template->activity->id . '/' ) ) ) {
    2834             return 'style="display: block"';
    2835         }
    2836 
    2837         return false;
    2838     }
    2839 
    2840 /**
    2841  * Output the activity comment form action.
    2842  *
    2843  * @since 1.2.0
    2844  *
    2845  * @uses bp_get_activity_comment_form_action()
    2846  */
    2847 function bp_activity_comment_form_action() {
    2848     echo bp_get_activity_comment_form_action();
    2849 }
    2850 
    2851     /**
    2852      * Return the activity comment form action.
    2853      *
    2854      * @since 1.2.0
    2855      *
    2856      * @uses home_url()
    2857      * @uses bp_get_activity_root_slug()
    2858      * @uses apply_filters() To call the 'bp_get_activity_comment_form_action' hook.
    2859      *
    2860      * @return string The activity comment form action.
    2861      */
    2862     function bp_get_activity_comment_form_action() {
    2863 
    2864         /**
    2865          * Filters the activity comment form action URL.
    2866          *
    2867          * @since 1.2.0
    2868          *
    2869          * @param string $value URL to use in the comment form's action attribute.
    2870          */
    2871         return apply_filters( 'bp_get_activity_comment_form_action', home_url( bp_get_activity_root_slug() . '/reply/' ) );
    2872     }
    2873 
    2874 /**
    2875  * Output the activity permalink ID.
    2876  *
    2877  * @since 1.2.0
    2878  *
    2879  * @uses bp_get_activity_permalink_id()
    2880  */
    2881 function bp_activity_permalink_id() {
    2882     echo bp_get_activity_permalink_id();
    2883 }
    2884 
    2885     /**
    2886      * Return the activity permalink ID.
    2887      *
    2888      * @since 1.2.0
    2889      *
    2890      * @uses apply_filters() To call the 'bp_get_activity_permalink_id' hook.
    2891      *
    2892      * @return string The activity permalink ID.
    2893      */
    2894     function bp_get_activity_permalink_id() {
    2895 
    2896         /**
    2897          * Filters the activity action permalink ID.
    2898          *
    2899          * @since 1.2.0
    2900          *
    2901          * @param string $value Current action for the activity item.
    2902          */
    2903         return apply_filters( 'bp_get_activity_permalink_id', bp_current_action() );
    2904     }
    2905 
    2906 /**
    2907  * Output the activity thread permalink.
    2908  *
    2909  * @since 1.2.0
    2910  *
    2911  * @uses bp_get_activity_permalink_id()
    2912  */
    2913 function bp_activity_thread_permalink() {
    2914     echo bp_get_activity_thread_permalink();
    2915 }
    2916 
    2917     /**
    2918      * Return the activity thread permalink.
    2919      *
    2920      * @since 1.2.0
    2921      *
    2922      * @uses bp_activity_get_permalink()
    2923      * @uses apply_filters() To call the 'bp_get_activity_thread_permalink' hook.
    2924      *
    2925      * @return string $link The activity thread permalink.
    2926      */
    2927     function bp_get_activity_thread_permalink() {
    2928         global $activities_template;
    2929 
    2930         $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
    2931 
    2932         /**
    2933          * Filters the activity thread permalink.
    2934          *
    2935          * @since 1.2.0
    2936          *
    2937          * @param string $link The activity thread permalink.
    2938          */
    2939         return apply_filters( 'bp_get_activity_thread_permalink', $link );
    2940     }
    2941 
    2942 /**
    2943  * Output the activity comment permalink.
    2944  *
    2945  * @since 1.8.0
    2946  *
    2947  * @uses bp_get_activity_permalink_id()
    2948  */
    2949 function bp_activity_comment_permalink() {
    2950     echo bp_get_activity_comment_permalink();
    2951 }
    2952     /**
    2953      * Return the activity comment permalink.
    2954      *
    2955      * @since 1.8.0
    2956      *
    2957      * @uses bp_activity_get_permalink()
    2958      * @uses apply_filters() To call the 'bp_get_activity_comment_permalink' hook.
    2959      *
    2960      * @return string $link The activity comment permalink.
    2961      */
    2962     function bp_get_activity_comment_permalink() {
    2963         global $activities_template;
    2964 
    2965         // Check that comment exists.
    2966         $comment_id = isset( $activities_template->activity->current_comment->id )
    2967             ? $activities_template->activity->current_comment->id
    2968             : 0;
    2969 
    2970         // Setup the comment link.
    2971         $comment_link = ! empty( $comment_id )
    2972             ? '#acomment-' .$comment_id
    2973             : false;
    2974 
    2975         // Append comment ID to end of activity permalink.
    2976         $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity ) . $comment_link;
    2977 
    2978         /**
    2979          * Filters the activity comment permalink.
    2980          *
    2981          * @since 1.8.0
    2982          *
    2983          * @param string $link       Activity comment permalink.
    2984          * @param int    $comment_id ID for the current activity comment.
    2985          */
    2986         return apply_filters( 'bp_get_activity_comment_permalink', $link, $comment_id );
    2987     }
    2988 
    2989 /**
    2990  * Output the activity favorite link.
    2991  *
    2992  * @since 1.2.0
    2993  *
    2994  * @uses bp_get_activity_favorite_link()
    2995  */
    2996 function bp_activity_favorite_link() {
    2997     echo bp_get_activity_favorite_link();
    2998 }
    2999 
    3000     /**
    3001      * Return the activity favorite link.
    3002      *
    3003      * @since 1.2.0
    3004      *
    3005      * @global object $activities_template {@link BP_Activity_Template}
    3006      * @uses wp_nonce_url()
    3007      * @uses home_url()
    3008      * @uses bp_get_activity_root_slug()
    3009      * @uses apply_filters() To call the 'bp_get_activity_favorite_link' hook.
    3010      *
    3011      * @return string The activity favorite link.
    3012      */
    3013     function bp_get_activity_favorite_link() {
    3014         global $activities_template;
    3015 
    3016         /**
    3017          * Filters the activity favorite link.
    3018          *
    3019          * @since 1.2.0
    3020          *
    3021          * @param string $value Constructed link for favoriting the activity comment.
    3022          */
    3023         return apply_filters( 'bp_get_activity_favorite_link', wp_nonce_url( home_url( bp_get_activity_root_slug() . '/favorite/' . $activities_template->activity->id . '/' ), 'mark_favorite' ) );
    3024     }
    3025 
    3026 /**
    3027  * Output the activity unfavorite link.
    3028  *
    3029  * @since 1.2.0
    3030  *
    3031  * @uses bp_get_activity_unfavorite_link()
    3032  */
    3033 function bp_activity_unfavorite_link() {
    3034     echo bp_get_activity_unfavorite_link();
    3035 }
    3036 
    3037     /**
    3038      * Return the activity unfavorite link.
    3039      *
    3040      * @since 1.2.0
    3041      *
    3042      * @global object $activities_template {@link BP_Activity_Template}
    3043      * @uses wp_nonce_url()
    3044      * @uses home_url()
    3045      * @uses bp_get_activity_root_slug()
    3046      * @uses apply_filters() To call the 'bp_get_activity_unfavorite_link' hook.
    3047      *
    3048      * @return string The activity unfavorite link.
    3049      */
    3050     function bp_get_activity_unfavorite_link() {
    3051         global $activities_template;
    3052 
    3053         /**
    3054          * Filters the activity unfavorite link.
    3055          *
    3056          * @since 1.2.0
    3057          *
    3058          * @param string $value Constructed link for unfavoriting the activity comment.
    3059          */
    3060         return apply_filters( 'bp_get_activity_unfavorite_link', wp_nonce_url( home_url( bp_get_activity_root_slug() . '/unfavorite/' . $activities_template->activity->id . '/' ), 'unmark_favorite' ) );
    3061     }
    3062 
    3063 /**
    3064  * Output the activity CSS class.
    3065  *
    3066  * @since 1.0.0
    3067  *
    3068  * @uses bp_get_activity_css_class()
    3069  */
    3070 function bp_activity_css_class() {
    3071     echo bp_get_activity_css_class();
    3072 }
    3073 
    3074     /**
    3075      * Return the current activity item's CSS class.
    3076      *
    3077      * @since 1.0.0
    3078      *
    3079      * @global object $activities_template {@link BP_Activity_Template}
    3080      * @uses apply_filters() To call the 'bp_activity_mini_activity_types' hook.
    3081      * @uses bp_activity_get_comment_count()
    3082      * @uses bp_activity_can_comment()
    3083      * @uses apply_filters() To call the 'bp_get_activity_css_class' hook.
    3084      *
    3085      * @return string The activity item's CSS class.
    3086      */
    3087     function bp_get_activity_css_class() {
    3088         global $activities_template;
    3089 
    3090         /**
    3091          * Filters the available mini activity actions available as CSS classes.
    3092          *
    3093          * @since 1.2.0
    3094          *
    3095          * @param array $value Array of classes used to determine classes applied to HTML element.
    3096          */
    3097         $mini_activity_actions = apply_filters( 'bp_activity_mini_activity_types', array(
    3098             'friendship_accepted',
    3099             'friendship_created',
    3100             'new_blog',
    3101             'joined_group',
    3102