diff --git bp-activity/bp-activity-classes.php bp-activity/bp-activity-classes.php
index 5be5de3..f1e6054 100644
|
|
class BP_Activity_Activity { |
1189 | 1189 | * @since BuddyPress (1.5.0) |
1190 | 1190 | * |
1191 | 1191 | * @param array $filter_array { |
1192 | | * Fields and values to filter by. Each can be either a single |
1193 | | * string, a comma-separated list, or an array of values. |
| 1192 | * Fields and values to filter by. |
1194 | 1193 | * @type array|string|id $user_id User ID(s). |
1195 | 1194 | * @type array|string $object Corresponds to the 'component' |
1196 | 1195 | * column in the database. |
… |
… |
class BP_Activity_Activity { |
1200 | 1199 | * column in the database. |
1201 | 1200 | * @type array|string|int $secondary_id Corresponds to the |
1202 | 1201 | * 'secondary_item_id' column in the database. |
| 1202 | * @type int $offset Return only those items with an ID greater |
| 1203 | * than the offset value. |
| 1204 | * @type string $since Return only those items that have a |
| 1205 | * date_recorded value greater than a given MySQL-formatted |
| 1206 | * date. |
1203 | 1207 | * } |
1204 | 1208 | * @return string The filter clause, for use in a SQL query. |
1205 | 1209 | */ |
… |
… |
class BP_Activity_Activity { |
1242 | 1246 | $filter_sql[] = "a.id >= {$sid_sql}"; |
1243 | 1247 | } |
1244 | 1248 | |
| 1249 | if ( ! empty( $filter_array['since'] ) ) { |
| 1250 | // Validate that this is a proper Y-m-d H:i:s date |
| 1251 | // Trick: parse to UNIX date then translate back |
| 1252 | $translated_date = date( 'Y-m-d H:i:s', strtotime( $filter_array['since'] ) ); |
| 1253 | if ( $translated_date === $filter_array['since'] ) { |
| 1254 | $filter_sql[] = "a.date_recorded > '{$translated_date}'"; |
| 1255 | } |
| 1256 | } |
| 1257 | |
1245 | 1258 | if ( empty( $filter_sql ) ) |
1246 | 1259 | return false; |
1247 | 1260 | |
diff --git bp-activity/bp-activity-filters.php bp-activity/bp-activity-filters.php
index 8f9cbff..9c6e5d9 100644
|
|
add_filter( 'bp_core_get_js_dependencies', 'bp_activity_get_js_dependencies', 10 |
429 | 429 | function bp_activity_newest_class( $classes = '' ) { |
430 | 430 | $bp = buddypress(); |
431 | 431 | |
432 | | if ( ! empty( $bp->activity->new_update_id ) && $bp->activity->new_update_id == bp_get_activity_id() ) { |
| 432 | if ( ! empty( $bp->activity->last_recorded ) && $bp->activity->last_recorded == bp_get_activity_date_recorded() ) { |
433 | 433 | $classes .= ' new-update'; |
434 | 434 | } |
435 | 435 | |
… |
… |
function bp_activity_newest_class( $classes = '' ) { |
438 | 438 | } |
439 | 439 | |
440 | 440 | /** |
| 441 | * Check if Activity Heartbeat feature i on to add a timestamp class. |
| 442 | * |
| 443 | * @since BuddyPress (2.0.0) |
| 444 | * |
| 445 | * @param string $classes |
| 446 | * @return string $classes |
| 447 | */ |
| 448 | function bp_activity_timestamp_class( $classes = '' ) { |
| 449 | |
| 450 | if ( ! bp_activity_do_heartbeat() ) { |
| 451 | return $classes; |
| 452 | } |
| 453 | |
| 454 | $activity_date = bp_get_activity_date_recorded(); |
| 455 | |
| 456 | if ( empty( $activity_date ) ) { |
| 457 | return $classes; |
| 458 | } |
| 459 | |
| 460 | $classes .= ' date-recorded-' . strtotime( $activity_date ); |
| 461 | |
| 462 | return $classes; |
| 463 | } |
| 464 | add_filter( 'bp_get_activity_css_class', 'bp_activity_timestamp_class', 9, 1 ); |
| 465 | |
| 466 | /** |
441 | 467 | * Use WordPress Heartbeat API to check for latest activity update. |
442 | 468 | * |
443 | 469 | * @since BuddyPress (2.0.0) |
444 | 470 | * |
445 | 471 | * @uses bp_activity_get_last_updated() to get the recorded date of the last activity |
446 | | |
| 472 | * |
447 | 473 | * @param array $response |
448 | 474 | * @param array $data |
449 | 475 | * @return array $response |
… |
… |
function bp_activity_newest_class( $classes = '' ) { |
451 | 477 | function bp_activity_heartbeat_last_recorded( $response = array(), $data = array() ) { |
452 | 478 | $bp = buddypress(); |
453 | 479 | |
454 | | if ( empty( $data['bp_activity_last_id'] ) ) { |
| 480 | if ( empty( $data['bp_activity_last_recorded'] ) ) { |
455 | 481 | return $response; |
456 | 482 | } |
457 | 483 | |
… |
… |
function bp_activity_heartbeat_last_recorded( $response = array(), $data = array |
459 | 485 | // filters), but force the offset to get only new items |
460 | 486 | $activity_latest_args = bp_parse_args( |
461 | 487 | bp_ajax_querystring( 'activity' ), |
462 | | array( 'offset' => absint( $data['bp_activity_last_id'] ) + 1 ), |
| 488 | array( 'since' => date( 'Y-m-d H:i:s', $data['bp_activity_last_recorded'] ) ), |
463 | 489 | 'activity_latest_args' |
464 | 490 | ); |
465 | 491 | |
466 | 492 | $newest_activities = array(); |
467 | | $last_activity_id = 0; |
| 493 | $last_activity_recorded = 0; |
468 | 494 | |
469 | 495 | // Temporarly add a just-posted class for new activity items |
470 | 496 | add_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 ); |
… |
… |
function bp_activity_heartbeat_last_recorded( $response = array(), $data = array |
474 | 500 | while ( bp_activities() ) { |
475 | 501 | bp_the_activity(); |
476 | 502 | |
477 | | if ( $last_activity_id < bp_get_activity_id() ) { |
478 | | $last_activity_id = bp_get_activity_id(); |
| 503 | $atime = strtotime( bp_get_activity_date_recorded() ); |
| 504 | if ( $last_activity_recorded < $atime ) { |
| 505 | $last_activity_recorded = $atime; |
479 | 506 | } |
480 | 507 | |
481 | 508 | bp_get_template_part( 'activity/entry' ); |
482 | 509 | } |
483 | 510 | } |
484 | 511 | |
485 | | $newest_activities['activities'] = ob_get_contents(); |
486 | | $newest_activities['last_id'] = $last_activity_id; |
| 512 | $newest_activities['activities'] = ob_get_contents(); |
| 513 | $newest_activities['last_recorded'] = $last_activity_recorded; |
487 | 514 | ob_end_clean(); |
488 | 515 | |
489 | 516 | // Remove the temporary filter |
490 | 517 | remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 ); |
491 | 518 | |
492 | | if ( ! empty( $newest_activities['last_id'] ) ) { |
| 519 | if ( ! empty( $newest_activities['last_recorded'] ) ) { |
493 | 520 | $response['bp_activity_newest_activities'] = $newest_activities; |
494 | 521 | } |
495 | 522 | |
diff --git bp-activity/bp-activity-template.php bp-activity/bp-activity-template.php
index e6b57dd..8e28b6b 100644
|
|
function bp_has_activities( $args = '' ) { |
547 | 547 | 'primary_id' => $primary_id, // object ID to filter on e.g. a group_id or forum_id or blog_id etc. |
548 | 548 | 'secondary_id' => false, // secondary object ID to filter on e.g. a post_id |
549 | 549 | 'offset' => false, // return only items >= this ID |
| 550 | 'since' => false, // return only items recorded since this Y-m-d H:i:s date |
550 | 551 | |
551 | 552 | 'meta_query' => false, // filter on activity meta. See WP_Meta_Query for format |
552 | 553 | |
… |
… |
function bp_has_activities( $args = '' ) { |
641 | 642 | // into bp-custom.php or your theme's functions.php |
642 | 643 | if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) ) |
643 | 644 | $filter = array( 'object' => $_GET['afilter'] ); |
644 | | else if ( ! empty( $user_id ) || ! empty( $object ) || ! empty( $action ) || ! empty( $primary_id ) || ! empty( $secondary_id ) || ! empty( $offset ) ) |
645 | | $filter = array( 'user_id' => $user_id, 'object' => $object, 'action' => $action, 'primary_id' => $primary_id, 'secondary_id' => $secondary_id, 'offset' => $offset ); |
| 645 | else if ( ! empty( $user_id ) || ! empty( $object ) || ! empty( $action ) || ! empty( $primary_id ) || ! empty( $secondary_id ) || ! empty( $offset ) || ! empty( $since ) ) |
| 646 | $filter = array( 'user_id' => $user_id, 'object' => $object, 'action' => $action, 'primary_id' => $primary_id, 'secondary_id' => $secondary_id, 'offset' => $offset, 'since' => $since ); |
646 | 647 | else |
647 | 648 | $filter = false; |
648 | 649 | |
… |
… |
function bp_send_public_message_link() { |
2805 | 2806 | */ |
2806 | 2807 | function bp_activity_recurse_comments_activity_ids( $activity = array(), $activity_ids = array() ) { |
2807 | 2808 | if ( is_array( $activity ) && ! empty( $activity['activities'] ) ) { |
2808 | | $activity = $activity['activities'][0]; |
| 2809 | $activity = $activity['activities'][0]; |
2809 | 2810 | } |
2810 | 2811 | |
2811 | 2812 | if ( ! empty( $activity->children ) ) { |
diff --git bp-templates/bp-legacy/buddypress-functions.php bp-templates/bp-legacy/buddypress-functions.php
index e1b3431..bca42bb 100644
|
|
function bp_legacy_theme_post_update() { |
706 | 706 | if ( empty( $activity_id ) ) |
707 | 707 | exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem posting your update, please try again.', 'buddypress' ) . '</p></div>' ); |
708 | 708 | |
709 | | $last_id = isset( $_POST['offset'] ) ? absint( $_POST['offset'] ) + 1 : 0; |
710 | | if ( $last_id ) { |
711 | | $activity_args = array( 'offset' => $last_id ); |
712 | | $bp->activity->new_update_id = $activity_id; |
| 709 | $last_recorded = isset( $_POST['since'] ) ? date( 'Y-m-d H:i:s', intval( $_POST['since'] ) ) : 0; |
| 710 | if ( $last_recorded ) { |
| 711 | $activity_args = array( 'since' => $last_recorded ); |
| 712 | $bp->activity->last_recorded = $last_recorded; |
713 | 713 | add_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 ); |
714 | 714 | } else { |
715 | 715 | $activity_args = array( 'include' => $activity_id ); |
… |
… |
function bp_legacy_theme_post_update() { |
722 | 722 | } |
723 | 723 | } |
724 | 724 | |
725 | | if ( ! empty( $last_id ) ) { |
| 725 | if ( ! empty( $last_recorded ) ) { |
726 | 726 | remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 ); |
727 | 727 | } |
728 | 728 | |
diff --git bp-templates/bp-legacy/js/buddypress.js bp-templates/bp-legacy/js/buddypress.js
index 610f704..7b62056 100644
|
|
var bp_ajax_request = null; |
6 | 6 | |
7 | 7 | // Global variables to temporarly store newest activities |
8 | 8 | var newest_activities = ''; |
9 | | var activity_last_id = 0; |
| 9 | var activity_last_recorded = 0; |
10 | 10 | |
11 | 11 | jq(document).ready( function() { |
12 | 12 | /**** Page Load Actions *******************************************************/ |
… |
… |
jq(document).ready( function() { |
91 | 91 | |
92 | 92 | /* New posts */ |
93 | 93 | jq("#aw-whats-new-submit").on( 'click', function() { |
94 | | var last_displayed_id = 0; |
| 94 | var last_date_recorded = 0; |
95 | 95 | var button = jq(this); |
96 | 96 | var form = button.closest("form#whats-new-form"); |
97 | 97 | |
… |
… |
jq(document).ready( function() { |
111 | 111 | var item_id = jq("#whats-new-post-in").val(); |
112 | 112 | var content = jq("#whats-new").val(); |
113 | 113 | var firstrow = jq( '#buddypress ul.activity-list li' ).first(); |
| 114 | var activity_row = firstrow; |
114 | 115 | |
115 | | if ( firstrow.hasClass( 'load-newest' ) ) { |
116 | | last_displayed_id = firstrow.next().prop( 'id' ) ? firstrow.next().prop( 'id' ).replace( 'activity-','' ) : 0; |
117 | | } else { |
118 | | last_displayed_id = firstrow.prop( 'id' ) ? firstrow.prop( 'id' ).replace( 'activity-','' ) : 0; |
| 116 | if ( activity_row.hasClass( 'load-newest' ) ) { |
| 117 | activity_row = firstrow.next(); |
| 118 | } |
| 119 | |
| 120 | timestamp = activity_row.prop( 'class' ).match( /date-recorded-([0-9]+)/ ); |
| 121 | |
| 122 | if ( timestamp ) { |
| 123 | last_date_recorded = timestamp[1]; |
119 | 124 | } |
120 | 125 | |
121 | 126 | /* Set object for non-profile posts */ |
… |
… |
jq(document).ready( function() { |
130 | 135 | 'content': content, |
131 | 136 | 'object': object, |
132 | 137 | 'item_id': item_id, |
133 | | 'offset': last_displayed_id, |
| 138 | 'since': last_date_recorded, |
134 | 139 | '_bp_as_nonce': jq('#_bp_as_nonce').val() || '' |
135 | 140 | }, |
136 | 141 | function(response) { |
… |
… |
jq(document).ready( function() { |
157 | 162 | |
158 | 163 | jq("#activity-stream").prepend(response); |
159 | 164 | |
160 | | if ( ! last_displayed_id ) |
| 165 | if ( ! last_date_recorded ) |
161 | 166 | jq("#activity-stream li:first").addClass('new-update just-posted'); |
162 | 167 | |
163 | 168 | if ( 0 != jq("#latest-update").length ) { |
… |
… |
jq(document).ready( function() { |
184 | 189 | |
185 | 190 | // reset vars to get newest activities |
186 | 191 | newest_activities = ''; |
187 | | activity_last_id = 0; |
| 192 | activity_last_recorded = 0; |
188 | 193 | } |
189 | 194 | |
190 | 195 | jq("#whats-new-options").animate({ |
… |
… |
jq(document).ready( function() { |
305 | 310 | var id = li.attr('id').substr( 9, li.attr('id').length ); |
306 | 311 | var link_href = target.attr('href'); |
307 | 312 | var nonce = link_href.split('_wpnonce='); |
| 313 | var timestamp = li.prop( 'class' ).match( /date-recorded-([0-9]+)/ ); |
308 | 314 | |
309 | 315 | nonce = nonce[1]; |
310 | 316 | |
… |
… |
jq(document).ready( function() { |
325 | 331 | li.slideUp(300); |
326 | 332 | |
327 | 333 | // reset vars to get newest activities |
328 | | if ( activity_last_id == id ) { |
| 334 | if ( timestamp && activity_last_recorded == timestamp[1] ) { |
329 | 335 | newest_activities = ''; |
330 | | activity_last_id = 0; |
| 336 | activity_last_recorded = 0; |
331 | 337 | } |
332 | 338 | } |
333 | 339 | }); |
… |
… |
jq(document).ready( function() { |
337 | 343 | |
338 | 344 | // Spam activity stream items |
339 | 345 | if ( target.hasClass( 'spam-activity' ) ) { |
340 | | var li = target.parents( 'div.activity ul li' ); |
| 346 | var li = target.parents( 'div.activity ul li' ); |
| 347 | var timestamp = li.prop( 'class' ).match( /date-recorded-([0-9]+)/ ); |
341 | 348 | target.addClass( 'loading' ); |
342 | 349 | |
343 | 350 | jq.post( ajaxurl, { |
… |
… |
jq(document).ready( function() { |
354 | 361 | } else { |
355 | 362 | li.slideUp( 300 ); |
356 | 363 | // reset vars to get newest activities |
357 | | if ( activity_last_id == id ) { |
| 364 | if ( timestamp && activity_last_recorded == timestamp[1] ) { |
358 | 365 | newest_activities = ''; |
359 | | activity_last_id = 0; |
| 366 | activity_last_recorded = 0; |
360 | 367 | } |
361 | 368 | } |
362 | 369 | }); |
… |
… |
jq(document).ready( function() { |
407 | 414 | event.preventDefault(); |
408 | 415 | |
409 | 416 | target.parent().hide(); |
| 417 | |
| 418 | /** |
| 419 | * If a plugin is updating the recorded_date of an activity |
| 420 | * it will be loaded as a new one. We need to look in the |
| 421 | * stream and eventually remove similar ids to avoid "double". |
| 422 | */ |
| 423 | activity_html = jq.parseHTML( newest_activities ); |
| 424 | |
| 425 | jq.each( activity_html, function( i, el ){ |
| 426 | if( 'LI' == el.nodeName && jq(el).hasClass( 'just-posted' ) ) { |
| 427 | if( jq( '#' + jq(el).attr( 'id' ) ).length ) |
| 428 | jq( '#' + jq(el).attr( 'id' ) ).remove(); |
| 429 | } |
| 430 | } ); |
| 431 | |
| 432 | // Now the stream is cleaned, prepend newest |
410 | 433 | jq( '#buddypress ul.activity-list' ).prepend( newest_activities ); |
411 | 434 | |
412 | 435 | // reset the newest activities now they're displayed |
… |
… |
jq(document).ready( function() { |
1492 | 1515 | |
1493 | 1516 | // Set the last id to request after |
1494 | 1517 | jq( document ).on( 'heartbeat-send.buddypress', function( e, data ) { |
| 1518 | |
| 1519 | firstrow = 0; |
1495 | 1520 | |
1496 | 1521 | // First row is default latest activity id |
1497 | 1522 | if ( jq( '#buddypress ul.activity-list li' ).first().prop( 'id' ) ) { |
1498 | | firstrow = jq( '#buddypress ul.activity-list li' ).first().prop( 'id' ).replace( 'activity-','' ); |
1499 | | } else { |
1500 | | firstrow = 0; |
| 1523 | // getting the timestamp |
| 1524 | timestamp = jq( '#buddypress ul.activity-list li' ).first().prop( 'class' ).match( /date-recorded-([0-9]+)/ ); |
| 1525 | |
| 1526 | if ( timestamp ) { |
| 1527 | firstrow = timestamp[1]; |
| 1528 | } |
1501 | 1529 | } |
1502 | 1530 | |
1503 | | if ( 0 == activity_last_id || Number( firstrow ) > activity_last_id ) |
1504 | | activity_last_id = Number( firstrow ); |
| 1531 | if ( 0 == activity_last_recorded || Number( firstrow ) > activity_last_recorded ) |
| 1532 | activity_last_recorded = Number( firstrow ); |
1505 | 1533 | |
1506 | | data['bp_activity_last_id'] = activity_last_id; |
| 1534 | data['bp_activity_last_recorded'] = activity_last_recorded; |
1507 | 1535 | }); |
1508 | 1536 | |
1509 | | // Increment newest_activities and activity_last_id if data has been returned |
| 1537 | // Increment newest_activities and activity_last_recorded if data has been returned |
1510 | 1538 | jq( document ).on( 'heartbeat-tick', function( e, data ) { |
1511 | 1539 | |
1512 | 1540 | // Only proceed if we have newest activities |
… |
… |
jq(document).ready( function() { |
1515 | 1543 | } |
1516 | 1544 | |
1517 | 1545 | newest_activities = data['bp_activity_newest_activities']['activities'] + newest_activities; |
1518 | | activity_last_id = Number( data['bp_activity_newest_activities']['last_id'] ); |
| 1546 | activity_last_recorded = Number( data['bp_activity_newest_activities']['last_recorded'] ); |
1519 | 1547 | |
1520 | 1548 | if ( jq( '#buddypress ul.activity-list li' ).first().hasClass( 'load-newest' ) ) |
1521 | 1549 | return; |
diff --git tests/testcases/activity/class.BP_Activity_Activity.php tests/testcases/activity/class.BP_Activity_Activity.php
index b4f61bc..117771e 100644
|
|
class BP_Tests_Activity_Class extends BP_UnitTestCase { |
282 | 282 | $ids = wp_list_pluck( $activity['activities'], 'id' ); |
283 | 283 | $this->assertEquals( array( $a3, $a2 ), $ids ); |
284 | 284 | } |
| 285 | |
| 286 | /** |
| 287 | * @group get |
| 288 | */ |
| 289 | public function test_get_with_since() { |
| 290 | $now = time(); |
| 291 | $a1 = $this->factory->activity->create( array( |
| 292 | 'content' => 'Life Rules', |
| 293 | 'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ), |
| 294 | ) ); |
| 295 | $a2 = $this->factory->activity->create( array( |
| 296 | 'content' => 'Life Drools', |
| 297 | 'recorded_time' => date( 'Y-m-d H:i:s', $now - 50 ), |
| 298 | ) ); |
| 299 | $a3 = $this->factory->activity->create( array( |
| 300 | 'content' => 'Life Drools', |
| 301 | 'recorded_time' => date( 'Y-m-d H:i:s', $now - 10 ), |
| 302 | ) ); |
| 303 | |
| 304 | $activity = BP_Activity_Activity::get( array( |
| 305 | 'filter' => array( |
| 306 | 'since' => date( 'Y-m-d H:i:s', $now - 70 ), |
| 307 | ), |
| 308 | ) ); |
| 309 | $ids = wp_list_pluck( $activity['activities'], 'id' ); |
| 310 | $this->assertEquals( array( $a3, $a2 ), $ids ); |
| 311 | } |
| 312 | |
285 | 313 | /** |
286 | 314 | * @group get_id |
287 | 315 | */ |