BuddyPress - Version 2.0.6

Version Description

See: http://codex.buddypress.org/releases/version-2-0-6/

Download this release

Release Info

Developer boonebgorges
Plugin Icon 128x128 BuddyPress
Version 2.0.6
Comparing to
See all releases

Code changes from version 2.8.1 to 2.0.6

Files changed (46) hide show
  1. .travis.yml +48 -0
  2. bp-activity/admin/css/admin-rtl.css +0 -87
  3. bp-activity/admin/css/admin-rtl.min.css +0 -1
  4. bp-activity/admin/css/admin.css +0 -7
  5. bp-activity/admin/css/admin.min.css +1 -1
  6. bp-activity/admin/js/admin.js +17 -20
  7. bp-activity/admin/js/admin.min.js +1 -1
  8. bp-activity/bp-activity-actions.php +197 -402
  9. bp-activity/bp-activity-admin.php +801 -289
  10. bp-activity/bp-activity-adminbar.php +0 -47
  11. bp-activity/bp-activity-akismet.php +588 -29
  12. bp-activity/bp-activity-cache.php +10 -35
  13. bp-activity/bp-activity-classes.php +1682 -0
  14. bp-activity/bp-activity-cssjs.php +0 -76
  15. bp-activity/bp-activity-embeds.php +0 -352
  16. bp-activity/bp-activity-filters.php +110 -369
  17. bp-activity/bp-activity-functions.php +723 -2618
  18. bp-activity/bp-activity-loader.php +352 -5
  19. bp-activity/bp-activity-notifications.php +302 -248
  20. bp-activity/bp-activity-screens.php +248 -170
  21. bp-activity/bp-activity-template.php +1322 -1839
  22. bp-activity/classes/class-bp-activity-activity.php +0 -1871
  23. bp-activity/classes/class-bp-activity-component.php +0 -384
  24. bp-activity/classes/class-bp-activity-feed.php +0 -468
  25. bp-activity/classes/class-bp-activity-list-table.php +0 -858
  26. bp-activity/classes/class-bp-activity-oembed-extension.php +0 -329
  27. bp-activity/classes/class-bp-activity-query.php +0 -247
  28. bp-activity/classes/class-bp-activity-template.php +0 -408
  29. bp-activity/classes/class-bp-activity-theme-compat.php +0 -180
  30. bp-activity/classes/class-bp-akismet.php +0 -651
  31. bp-activity/css/mentions-rtl.css +0 -92
  32. bp-activity/css/mentions-rtl.min.css +0 -1
  33. bp-activity/css/mentions.css +0 -93
  34. bp-activity/css/mentions.min.css +0 -1
  35. bp-activity/js/mentions.js +0 -255
  36. bp-activity/js/mentions.min.js +0 -1
  37. bp-blogs/bp-blogs-actions.php +7 -7
  38. bp-blogs/bp-blogs-activity.php +261 -788
  39. bp-blogs/bp-blogs-buddybar.php +78 -0
  40. bp-blogs/bp-blogs-cache.php +28 -20
  41. bp-blogs/{classes/class-bp-blogs-blog.php → bp-blogs-classes.php} +109 -247
  42. bp-blogs/bp-blogs-filters.php +6 -105
  43. bp-blogs/bp-blogs-functions.php +599 -748
  44. bp-blogs/bp-blogs-loader.php +237 -10
  45. bp-blogs/bp-blogs-screens.php +178 -20
  46. bp-blogs/bp-blogs-template.php +265 -61
.travis.yml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ php:
4
+ - 5.2
5
+ - 5.3
6
+ - 5.4
7
+ - 5.5
8
+
9
+ env:
10
+ - WP_VERSION=trunk WP_MULTISITE=0
11
+ - WP_VERSION=tags/3.8.1 WP_MULTISITE=0
12
+ - WP_VERSION=tags/3.7.1 WP_MULTISITE=0
13
+ - WP_VERSION=trunk WP_MULTISITE=1
14
+ - WP_VERSION=tags/3.8.1 WP_MULTISITE=1
15
+ - WP_VERSION=tags/3.7.1 WP_MULTISITE=1
16
+
17
+ before_script:
18
+ # set up WP install
19
+ - WP_CORE_DIR=/tmp/wordpress/
20
+ - mkdir -p $WP_CORE_DIR
21
+ - svn co --ignore-externals https://develop.svn.wordpress.org/$WP_VERSION $WP_CORE_DIR
22
+ - plugin_slug=$(basename $(pwd))
23
+ - plugin_dir=$WP_CORE_DIR/src/wp-content/plugins/$plugin_slug
24
+ - cd ..
25
+ - mv $plugin_slug $plugin_dir
26
+ # set up tests config
27
+ - cd $WP_CORE_DIR
28
+ - cp wp-tests-config-sample.php wp-tests-config.php
29
+ - sed -i "s/youremptytestdbnamehere/wordpress_test/" wp-tests-config.php
30
+ - sed -i "s/yourusernamehere/root/" wp-tests-config.php
31
+ - sed -i "s/yourpasswordhere//" wp-tests-config.php
32
+ # disable WP_DEBUG for PHP 5.5 due to ext/mysqli E_DEPRECATED errors
33
+ - if [[ "$TRAVIS_PHP_VERSION" == 5.5* ]] ; then sed -i "s:define( 'WP_DEBUG://define( 'WP_DEBUG:" wp-tests-config.php; fi;
34
+ # set up database
35
+ - mysql -e 'CREATE DATABASE wordpress_test;' -uroot
36
+ # prepare for running the tests
37
+ - cd $plugin_dir/tests
38
+
39
+ script: phpunit
40
+
41
+ notifications:
42
+ email: false
43
+
44
+ irc:
45
+ channels:
46
+ - "irc.freenode.net#buddypress-dev"
47
+ template:
48
+ - "Build %{build_number} (%{branch} - %{commit}): %{message} %{build_url}"
bp-activity/admin/css/admin-rtl.css DELETED
@@ -1,87 +0,0 @@
1
- .akismet-status {
2
- float: left;
3
- }
4
- .akismet-status a {
5
- color: #AAA;
6
- font-style: italic;
7
- }
8
- .akismet-history {
9
- margin: 13px;
10
- }
11
- .akismet-history div {
12
- margin-bottom: 13px;
13
- }
14
- .akismet-history span {
15
- color: #999;
16
- }
17
-
18
- #wp-bp-activities-wrap {
19
- padding: 5px 0;
20
- }
21
- #bp-activities {
22
- height: 120px;
23
- }
24
- #bp-replyhead {
25
- font-size: 1em;
26
- line-height: 1.4em;
27
- margin: 0;
28
- }
29
- #bp-replysubmit {
30
- margin: 0;
31
- padding: 0 0 3px;
32
- text-align: center;
33
- }
34
- #bp-replysubmit .error {
35
- color: red;
36
- line-height: 21px;
37
- text-align: center;
38
- vertical-align: center;
39
- }
40
- #bp-replysubmit img.waiting {
41
- float: left;
42
- padding: 4px 10px 0;
43
- vertical-align: top;
44
- }
45
- #bp-activities-form .column-response img {
46
- float: right;
47
- margin-bottom: 5px;
48
- margin-left: 10px;
49
- margin-top: 1px;
50
- }
51
- .activity-errors {
52
- list-style-type: disc;
53
- margin-right: 2em;
54
- }
55
-
56
- #bp_activity_action div.inside,
57
- #bp_activity_content div.inside {
58
- line-height: 0;
59
- }
60
- #bp_activity_action h3,
61
- #bp_activity_content h3 {
62
- cursor: auto;
63
- }
64
- #bp_activity_action td.mceIframeContainer,
65
- #bp_activity_content td.mceIframeContainer {
66
- background-color: white;
67
- }
68
- #post-body #bp-activities-action_resize,
69
- #post-body #bp-activities-content_resize {
70
- position: inherit;
71
- margin-top: -2px;
72
- }
73
- #bp_activity_link input {
74
- width: 99%;
75
- }
76
- #bp-activities-primaryid {
77
- margin-bottom: 1em;
78
- }
79
- .column-action {
80
- width: 12%;
81
- }
82
-
83
- @media screen and (max-width: 782px) {
84
- body.toplevel_page_bp-activity .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column) {
85
- display: table-cell;
86
- }
87
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/admin/css/admin-rtl.min.css DELETED
@@ -1 +0,0 @@
1
- .akismet-status{float:left}.akismet-status a{color:#AAA;font-style:italic}.akismet-history{margin:13px}.akismet-history div{margin-bottom:13px}.akismet-history span{color:#999}#wp-bp-activities-wrap{padding:5px 0}#bp-activities{height:120px}#bp-replyhead{font-size:1em;line-height:1.4em;margin:0}#bp-replysubmit{margin:0;padding:0 0 3px;text-align:center}#bp-replysubmit .error{color:red;line-height:21px;text-align:center;vertical-align:center}#bp-replysubmit img.waiting{float:left;padding:4px 10px 0;vertical-align:top}#bp-activities-form .column-response img{float:right;margin-bottom:5px;margin-left:10px;margin-top:1px}.activity-errors{list-style-type:disc;margin-right:2em}#bp_activity_action div.inside,#bp_activity_content div.inside{line-height:0}#bp_activity_action h3,#bp_activity_content h3{cursor:auto}#bp_activity_action td.mceIframeContainer,#bp_activity_content td.mceIframeContainer{background-color:#fff}#post-body #bp-activities-action_resize,#post-body #bp-activities-content_resize{position:inherit;margin-top:-2px}#bp_activity_link input{width:99%}#bp-activities-primaryid{margin-bottom:1em}.column-action{width:12%}@media screen and (max-width:782px){body.toplevel_page_bp-activity .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column){display:table-cell}}
 
bp-activity/admin/css/admin.css CHANGED
@@ -44,7 +44,6 @@
44
  }
45
  #bp-activities-form .column-response img {
46
  float: left;
47
- margin-bottom: 5px;
48
  margin-right: 10px;
49
  margin-top: 1px;
50
  }
@@ -78,10 +77,4 @@
78
  }
79
  .column-action {
80
  width: 12%;
81
- }
82
-
83
- @media screen and (max-width: 782px) {
84
- body.toplevel_page_bp-activity .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column) {
85
- display: table-cell;
86
- }
87
  }
44
  }
45
  #bp-activities-form .column-response img {
46
  float: left;
 
47
  margin-right: 10px;
48
  margin-top: 1px;
49
  }
77
  }
78
  .column-action {
79
  width: 12%;
 
 
 
 
 
 
80
  }
bp-activity/admin/css/admin.min.css CHANGED
@@ -1 +1 @@
1
- .akismet-status{float:right}.akismet-status a{color:#AAA;font-style:italic}.akismet-history{margin:13px}.akismet-history div{margin-bottom:13px}.akismet-history span{color:#999}#wp-bp-activities-wrap{padding:5px 0}#bp-activities{height:120px}#bp-replyhead{font-size:1em;line-height:1.4em;margin:0}#bp-replysubmit{margin:0;padding:0 0 3px;text-align:center}#bp-replysubmit .error{color:red;line-height:21px;text-align:center;vertical-align:center}#bp-replysubmit img.waiting{float:right;padding:4px 10px 0;vertical-align:top}#bp-activities-form .column-response img{float:left;margin-bottom:5px;margin-right:10px;margin-top:1px}.activity-errors{list-style-type:disc;margin-left:2em}#bp_activity_action div.inside,#bp_activity_content div.inside{line-height:0}#bp_activity_action h3,#bp_activity_content h3{cursor:auto}#bp_activity_action td.mceIframeContainer,#bp_activity_content td.mceIframeContainer{background-color:#fff}#post-body #bp-activities-action_resize,#post-body #bp-activities-content_resize{position:inherit;margin-top:-2px}#bp_activity_link input{width:99%}#bp-activities-primaryid{margin-bottom:1em}.column-action{width:12%}@media screen and (max-width:782px){body.toplevel_page_bp-activity .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column){display:table-cell}}
1
+ .akismet-status{float:right}.akismet-status a{color:#AAA;font-style:italic}.akismet-history{margin:13px}.akismet-history div{margin-bottom:13px}.akismet-history span{color:#999}#wp-bp-activities-wrap{padding:5px 0}#bp-activities{height:120px}#bp-replyhead{font-size:1em;line-height:1.4em;margin:0}#bp-replysubmit{margin:0;padding:0 0 3px;text-align:center}#bp-replysubmit .error{color:red;line-height:21px;text-align:center;vertical-align:center}#bp-replysubmit img.waiting{float:right;padding:4px 10px 0;vertical-align:top}#bp-activities-form .column-response img{float:left;margin-right:10px;margin-top:1px}.activity-errors{list-style-type:disc;margin-left:2em}#bp_activity_action div.inside,#bp_activity_content div.inside{line-height:0}#bp_activity_action h3,#bp_activity_content h3{cursor:auto}#bp_activity_action td.mceIframeContainer,#bp_activity_content td.mceIframeContainer{background-color:white}#post-body #bp-activities-action_resize,#post-body #bp-activities-content_resize{position:inherit;margin-top:-2px}#bp_activity_link input{width:99%}#bp-activities-primaryid{margin-bottom:1em}.column-action{width:12%}
bp-activity/admin/js/admin.js CHANGED
@@ -1,17 +1,16 @@
1
- /* global bp_activity_admin_vars, postboxes, wpAjax */
2
  (function( $ ) {
3
 
4
  /**
5
  * Activity reply object for the activity index screen
6
  *
7
- * @since 1.6.0
8
  */
9
  var activityReply = {
10
 
11
  /**
12
  * Attach event handler functions to the relevant elements.
13
  *
14
- * @since 1.6.0
15
  */
16
  init : function() {
17
  $(document).on( 'click', '.row-actions a.reply', activityReply.open );
@@ -20,7 +19,7 @@ var activityReply = {
20
 
21
  // Close textarea on escape
22
  $(document).on( 'keyup', '#bp-activities:visible', function( e ) {
23
- if ( 27 === e.which ) {
24
  activityReply.close();
25
  }
26
  });
@@ -29,9 +28,9 @@ var activityReply = {
29
  /**
30
  * Reveals the entire row when "reply" is pressed.
31
  *
32
- * @since 1.6.0
33
  */
34
- open : function() {
35
  // Hide the container row, and move it to the new location
36
  var box = $( '#bp-activities-container' ).hide();
37
  $( this ).parents( 'tr' ).after( box );
@@ -46,11 +45,11 @@ var activityReply = {
46
  /**
47
  * Hide and reset the entire row when "cancel", or escape, are pressed.
48
  *
49
- * @since 1.6.0
50
  */
51
- close : function() {
52
  // Hide the container row
53
- $('#bp-activities-container').fadeOut( '200', function () {
54
 
55
  // Empty and unfocus the text area
56
  $( '#bp-activities' ).val( '' ).blur();
@@ -66,9 +65,9 @@ var activityReply = {
66
  /**
67
  * Submits "form" via AJAX back to WordPress.
68
  *
69
- * @since 1.6.0
70
  */
71
- send : function() {
72
  // Hide any existing error message, and show the loading spinner
73
  $( '#bp-replysubmit .error' ).hide();
74
  $( '#bp-replysubmit .waiting' ).show();
@@ -100,7 +99,7 @@ var activityReply = {
100
  /**
101
  * send() error message handler
102
  *
103
- * @since 1.6.0
104
  */
105
  error : function( r ) {
106
  var er = r.statusText;
@@ -118,13 +117,13 @@ var activityReply = {
118
  /**
119
  * send() success handler
120
  *
121
- * @since 1.6.0
122
  */
123
  show : function ( xml ) {
124
  var bg, id, response;
125
 
126
  // Handle any errors in the response
127
- if ( typeof( xml ) === 'string' ) {
128
  activityReply.error( { 'responseText': xml } );
129
  return false;
130
  }
@@ -137,7 +136,7 @@ var activityReply = {
137
  response = response.responses[0];
138
 
139
  // Close and reset the reply row, and add the new Activity item into the list.
140
- $('#bp-activities-container').fadeOut( '200', function () {
141
 
142
  // Empty and unfocus the text area
143
  $( '#bp-activities' ).val( '' ).blur();
@@ -165,11 +164,9 @@ $(document).ready( function () {
165
  $( '#bp_activity_action h3, #bp_activity_content h3' ).unbind( 'click' );
166
 
167
  // redo the post box toggles to reset the one made by comment.js in favor
168
- // of activity administration page id so that metaboxes are still collapsible
169
  // in single Activity Administration screen.
170
- if ( typeof postboxes !== 'undefined' ) {
171
- postboxes.add_postbox_toggles( bp_activity_admin_vars.page );
172
- }
173
  });
174
 
175
- })(jQuery);
 
1
  (function( $ ) {
2
 
3
  /**
4
  * Activity reply object for the activity index screen
5
  *
6
+ * @since BuddyPress (1.6)
7
  */
8
  var activityReply = {
9
 
10
  /**
11
  * Attach event handler functions to the relevant elements.
12
  *
13
+ * @since BuddyPress (1.6)
14
  */
15
  init : function() {
16
  $(document).on( 'click', '.row-actions a.reply', activityReply.open );
19
 
20
  // Close textarea on escape
21
  $(document).on( 'keyup', '#bp-activities:visible', function( e ) {
22
+ if ( 27 == e.which ) {
23
  activityReply.close();
24
  }
25
  });
28
  /**
29
  * Reveals the entire row when "reply" is pressed.
30
  *
31
+ * @since BuddyPress (1.6)
32
  */
33
+ open : function( e ) {
34
  // Hide the container row, and move it to the new location
35
  var box = $( '#bp-activities-container' ).hide();
36
  $( this ).parents( 'tr' ).after( box );
45
  /**
46
  * Hide and reset the entire row when "cancel", or escape, are pressed.
47
  *
48
+ * @since BuddyPress (1.6)
49
  */
50
+ close : function( e ) {
51
  // Hide the container row
52
+ $('#bp-activities-container').fadeOut( '200', function () {
53
 
54
  // Empty and unfocus the text area
55
  $( '#bp-activities' ).val( '' ).blur();
65
  /**
66
  * Submits "form" via AJAX back to WordPress.
67
  *
68
+ * @since BuddyPress (1.6)
69
  */
70
+ send : function( e ) {
71
  // Hide any existing error message, and show the loading spinner
72
  $( '#bp-replysubmit .error' ).hide();
73
  $( '#bp-replysubmit .waiting' ).show();
99
  /**
100
  * send() error message handler
101
  *
102
+ * @since BuddyPress (1.6)
103
  */
104
  error : function( r ) {
105
  var er = r.statusText;
117
  /**
118
  * send() success handler
119
  *
120
+ * @since BuddyPress (1.6)
121
  */
122
  show : function ( xml ) {
123
  var bg, id, response;
124
 
125
  // Handle any errors in the response
126
+ if ( typeof( xml ) == 'string' ) {
127
  activityReply.error( { 'responseText': xml } );
128
  return false;
129
  }
136
  response = response.responses[0];
137
 
138
  // Close and reset the reply row, and add the new Activity item into the list.
139
+ $('#bp-activities-container').fadeOut( '200', function () {
140
 
141
  // Empty and unfocus the text area
142
  $( '#bp-activities' ).val( '' ).blur();
164
  $( '#bp_activity_action h3, #bp_activity_content h3' ).unbind( 'click' );
165
 
166
  // redo the post box toggles to reset the one made by comment.js in favor
167
+ // of activity administration page id so that metaboxes are still collapsible
168
  // in single Activity Administration screen.
169
+ postboxes.add_postbox_toggles( bp_activity_admin_vars.page );
 
 
170
  });
171
 
172
+ })(jQuery);
bp-activity/admin/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){var b={init:function(){a(document).on("click",".row-actions a.reply",b.open),a(document).on("click","#bp-activities-container a.cancel",b.close),a(document).on("click","#bp-activities-container a.save",b.send),a(document).on("keyup","#bp-activities:visible",function(a){27===a.which&&b.close()})},open:function(){var b=a("#bp-activities-container").hide();return a(this).parents("tr").after(b),b.fadeIn("300"),a("#bp-activities").focus(),!1},close:function(){return a("#bp-activities-container").fadeOut("200",function(){a("#bp-activities").val("").blur(),a("#bp-replysubmit .error").html("").hide(),a("#bp-replysubmit .waiting").hide()}),!1},send:function(){a("#bp-replysubmit .error").hide(),a("#bp-replysubmit .waiting").show();var c={};return c["_ajax_nonce-bp-activity-admin-reply"]=a('#bp-activities-container input[name="_ajax_nonce-bp-activity-admin-reply"]').val(),c.action="bp-activity-admin-reply",c.content=a("#bp-activities").val(),c.parent_id=a("#bp-activities-container").prev().data("parent_id"),c.root_id=a("#bp-activities-container").prev().data("root_id"),a.ajax({data:c,type:"POST",url:ajaxurl,error:function(a){b.error(a)},success:function(a){b.show(a)}}),!1},error:function(b){var c=b.statusText;a("#bp-replysubmit .waiting").hide(),b.responseText&&(c=b.responseText.replace(/<.[^<>]*?>/g,"")),c&&a("#bp-replysubmit .error").html(c).show()},show:function(c){var d,e,f;return"string"==typeof c?(b.error({responseText:c}),!1):(f=wpAjax.parseAjaxResponse(c),f.errors?(b.error({responseText:wpAjax.broken}),!1):(f=f.responses[0],void a("#bp-activities-container").fadeOut("200",function(){a("#bp-activities").val("").blur(),a("#bp-replysubmit .error").html("").hide(),a("#bp-replysubmit .waiting").hide(),a("#bp-activities-container").before(f.data),e=a("#activity-"+f.id),d=e.closest(".widefat").css("backgroundColor"),e.animate({backgroundColor:"#CEB"},300).animate({backgroundColor:d},300)})))}};a(document).ready(function(){b.init(),a("#bp_activity_action h3, #bp_activity_content h3").unbind("click"),"undefined"!=typeof postboxes&&postboxes.add_postbox_toggles(bp_activity_admin_vars.page)})}(jQuery);
1
+ (function(b){var a={init:function(){b(document).on("click",".row-actions a.reply",a.open);b(document).on("click","#bp-activities-container a.cancel",a.close);b(document).on("click","#bp-activities-container a.save",a.send);b(document).on("keyup","#bp-activities:visible",function(c){if(27==c.which){a.close()}})},open:function(d){var c=b("#bp-activities-container").hide();b(this).parents("tr").after(c);c.fadeIn("300");b("#bp-activities").focus();return false},close:function(c){b("#bp-activities-container").fadeOut("200",function(){b("#bp-activities").val("").blur();b("#bp-replysubmit .error").html("").hide();b("#bp-replysubmit .waiting").hide()});return false},send:function(d){b("#bp-replysubmit .error").hide();b("#bp-replysubmit .waiting").show();var c={};c["_ajax_nonce-bp-activity-admin-reply"]=b('#bp-activities-container input[name="_ajax_nonce-bp-activity-admin-reply"]').val();c.action="bp-activity-admin-reply";c.content=b("#bp-activities").val();c.parent_id=b("#bp-activities-container").prev().data("parent_id");c.root_id=b("#bp-activities-container").prev().data("root_id");b.ajax({data:c,type:"POST",url:ajaxurl,error:function(e){a.error(e)},success:function(e){a.show(e)}});return false},error:function(c){var d=c.statusText;b("#bp-replysubmit .waiting").hide();if(c.responseText){d=c.responseText.replace(/<.[^<>]*?>/g,"")}if(d){b("#bp-replysubmit .error").html(d).show()}},show:function(d){var e,f,c;if(typeof(d)=="string"){a.error({responseText:d});return false}c=wpAjax.parseAjaxResponse(d);if(c.errors){a.error({responseText:wpAjax.broken});return false}c=c.responses[0];b("#bp-activities-container").fadeOut("200",function(){b("#bp-activities").val("").blur();b("#bp-replysubmit .error").html("").hide();b("#bp-replysubmit .waiting").hide();b("#bp-activities-container").before(c.data);f=b("#activity-"+c.id);e=f.closest(".widefat").css("backgroundColor");f.animate({backgroundColor:"#CEB"},300).animate({backgroundColor:e},300)})}};b(document).ready(function(){a.init();b("#bp_activity_action h3, #bp_activity_content h3").unbind("click");postboxes.add_postbox_toggles(bp_activity_admin_vars.page)})})(jQuery);
bp-activity/bp-activity-actions.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * Action functions are exactly the same as screen functions, however they do
4
  * not have a template screen associated with them. Usually they will send the
@@ -6,25 +7,19 @@
6
  *
7
  * @package BuddyPress
8
  * @subpackage ActivityActions
9
- * @since 1.5.0
10
  */
11
 
12
- // Exit if accessed directly.
13
- defined( 'ABSPATH' ) || exit;
14
 
15
  /**
16
  * Allow core components and dependent plugins to register activity actions.
17
  *
18
- * @since 1.2.0
19
  *
 
20
  */
21
  function bp_register_activity_actions() {
22
-
23
- /**
24
- * Fires on bp_init to allow core components and dependent plugins to register activity actions.
25
- *
26
- * @since 1.2.0
27
- */
28
  do_action( 'bp_register_activity_actions' );
29
  }
30
  add_action( 'bp_init', 'bp_register_activity_actions', 8 );
@@ -32,21 +27,34 @@ add_action( 'bp_init', 'bp_register_activity_actions', 8 );
32
  /**
33
  * Catch and route requests for single activity item permalinks.
34
  *
35
- * @since 1.2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  *
37
  * @return bool False on failure.
38
  */
39
  function bp_activity_action_permalink_router() {
40
 
41
- // Not viewing activity.
42
  if ( ! bp_is_activity_component() || ! bp_is_current_action( 'p' ) )
43
  return false;
44
 
45
- // No activity to display.
46
  if ( ! bp_action_variable( 0 ) || ! is_numeric( bp_action_variable( 0 ) ) )
47
  return false;
48
 
49
- // Get the activity details.
50
  $activity = bp_activity_get_specific( array( 'activity_ids' => bp_action_variable( 0 ), 'show_hidden' => true ) );
51
 
52
  // 404 if activity does not exist
@@ -57,49 +65,43 @@ function bp_activity_action_permalink_router() {
57
  $activity = $activity['activities'][0];
58
  }
59
 
60
- // Do not redirect at default.
61
  $redirect = false;
62
 
63
- // Redirect based on the type of activity.
64
  if ( bp_is_active( 'groups' ) && $activity->component == buddypress()->groups->id ) {
65
 
66
- // Activity is a user update.
67
  if ( ! empty( $activity->user_id ) ) {
68
  $redirect = bp_core_get_user_domain( $activity->user_id, $activity->user_nicename, $activity->user_login ) . bp_get_activity_slug() . '/' . $activity->id . '/';
69
 
70
- // Activity is something else.
71
  } else {
72
 
73
- // Set redirect to group activity stream.
74
- if ( $group = groups_get_group( $activity->item_id ) ) {
75
  $redirect = bp_get_group_permalink( $group ) . bp_get_activity_slug() . '/' . $activity->id . '/';
76
  }
77
  }
78
 
79
- // Set redirect to users' activity stream.
80
- } elseif ( ! empty( $activity->user_id ) ) {
81
  $redirect = bp_core_get_user_domain( $activity->user_id, $activity->user_nicename, $activity->user_login ) . bp_get_activity_slug() . '/' . $activity->id . '/';
82
  }
83
 
84
- // If set, add the original query string back onto the redirect URL.
85
  if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
86
  $query_frags = array();
87
  wp_parse_str( $_SERVER['QUERY_STRING'], $query_frags );
88
  $redirect = add_query_arg( urlencode_deep( $query_frags ), $redirect );
89
  }
90
 
91
- /**
92
- * Filter the intended redirect url before the redirect occurs for the single activity item.
93
- *
94
- * @since 1.2.2
95
- *
96
- * @param array $value Array with url to redirect to and activity related to the redirect.
97
- */
98
  if ( ! $redirect = apply_filters_ref_array( 'bp_activity_permalink_redirect_url', array( $redirect, &$activity ) ) ) {
99
  bp_core_redirect( bp_get_root_domain() );
100
  }
101
 
102
- // Redirect to the actual activity permalink page.
103
  bp_core_redirect( $redirect );
104
  }
105
  add_action( 'bp_actions', 'bp_activity_action_permalink_router' );
@@ -107,62 +109,59 @@ add_action( 'bp_actions', 'bp_activity_action_permalink_router' );
107
  /**
108
  * Delete specific activity item and redirect to previous page.
109
  *
110
- * @since 1.1.0
111
  *
112
  * @param int $activity_id Activity id to be deleted. Defaults to 0.
 
 
 
 
 
 
 
 
 
 
 
 
113
  * @return bool False on failure.
114
  */
115
  function bp_activity_action_delete_activity( $activity_id = 0 ) {
116
 
117
- // Not viewing activity or action is not delete.
118
  if ( !bp_is_activity_component() || !bp_is_current_action( 'delete' ) )
119
  return false;
120
 
121
  if ( empty( $activity_id ) && bp_action_variable( 0 ) )
122
  $activity_id = (int) bp_action_variable( 0 );
123
 
124
- // Not viewing a specific activity item.
125
  if ( empty( $activity_id ) )
126
  return false;
127
 
128
- // Check the nonce.
129
  check_admin_referer( 'bp_activity_delete_link' );
130
 
131
- // Load up the activity item.
132
  $activity = new BP_Activity_Activity( $activity_id );
133
 
134
- // Check access.
135
  if ( ! bp_activity_user_can_delete( $activity ) )
136
  return false;
137
 
138
- /**
139
- * Fires before the deletion so plugins can still fetch information about it.
140
- *
141
- * @since 1.5.0
142
- *
143
- * @param int $activity_id The activity ID.
144
- * @param int $user_id The user associated with the activity.
145
- */
146
  do_action( 'bp_activity_before_action_delete_activity', $activity_id, $activity->user_id );
147
 
148
- // Delete the activity item and provide user feedback.
149
  if ( bp_activity_delete( array( 'id' => $activity_id, 'user_id' => $activity->user_id ) ) )
150
  bp_core_add_message( __( 'Activity deleted successfully', 'buddypress' ) );
151
  else
152
  bp_core_add_message( __( 'There was an error when deleting that activity', 'buddypress' ), 'error' );
153
 
154
- /**
155
- * Fires after the deletion so plugins can act afterwards based on the activity.
156
- *
157
- * @since 1.1.0
158
- *
159
- * @param int $activity_id The activity ID.
160
- * @param int $user_id The user associated with the activity.
161
- */
162
  do_action( 'bp_activity_action_delete_activity', $activity_id, $activity->user_id );
163
 
164
- // Check for the redirect query arg, otherwise let WP handle things.
165
- if ( !empty( $_GET['redirect_to'] ) )
166
  bp_core_redirect( esc_url( $_GET['redirect_to'] ) );
167
  else
168
  bp_core_redirect( wp_get_referer() );
@@ -172,22 +171,23 @@ add_action( 'bp_actions', 'bp_activity_action_delete_activity' );
172
  /**
173
  * Mark specific activity item as spam and redirect to previous page.
174
  *
175
- * @since 1.6.0
176
  *
 
177
  * @param int $activity_id Activity id to be deleted. Defaults to 0.
178
  * @return bool False on failure.
179
  */
180
  function bp_activity_action_spam_activity( $activity_id = 0 ) {
181
- $bp = buddypress();
182
 
183
- // Not viewing activity, or action is not spam, or Akismet isn't present.
184
  if ( !bp_is_activity_component() || !bp_is_current_action( 'spam' ) || empty( $bp->activity->akismet ) )
185
  return false;
186
 
187
  if ( empty( $activity_id ) && bp_action_variable( 0 ) )
188
  $activity_id = (int) bp_action_variable( 0 );
189
 
190
- // Not viewing a specific activity item.
191
  if ( empty( $activity_id ) )
192
  return false;
193
 
@@ -195,43 +195,28 @@ function bp_activity_action_spam_activity( $activity_id = 0 ) {
195
  if ( !bp_activity_user_can_mark_spam() )
196
  return false;
197
 
198
- // Load up the activity item.
199
  $activity = new BP_Activity_Activity( $activity_id );
200
  if ( empty( $activity->id ) )
201
  return false;
202
 
203
- // Check nonce.
204
  check_admin_referer( 'bp_activity_akismet_spam_' . $activity->id );
205
 
206
- /**
207
- * Fires before the marking activity as spam so plugins can modify things if they want to.
208
- *
209
- * @since 1.6.0
210
- *
211
- * @param int $activity_id Activity ID to be marked as spam.
212
- * @param object $activity Activity object for the ID to be marked as spam.
213
- */
214
  do_action( 'bp_activity_before_action_spam_activity', $activity->id, $activity );
215
 
216
- // Mark as spam.
217
  bp_activity_mark_as_spam( $activity );
218
  $activity->save();
219
 
220
- // Tell the user the spamming has been successful.
221
  bp_core_add_message( __( 'The activity item has been marked as spam and is no longer visible.', 'buddypress' ) );
222
 
223
- /**
224
- * Fires after the marking activity as spam so plugins can act afterwards based on the activity.
225
- *
226
- * @since 1.6.0
227
- *
228
- * @param int $activity_id Activity ID that was marked as spam.
229
- * @param int $user_id User ID associated with activity.
230
- */
231
  do_action( 'bp_activity_action_spam_activity', $activity_id, $activity->user_id );
232
 
233
- // Check for the redirect query arg, otherwise let WP handle things.
234
- if ( !empty( $_GET['redirect_to'] ) )
235
  bp_core_redirect( esc_url( $_GET['redirect_to'] ) );
236
  else
237
  bp_core_redirect( wp_get_referer() );
@@ -241,89 +226,72 @@ add_action( 'bp_actions', 'bp_activity_action_spam_activity' );
241
  /**
242
  * Post user/group activity update.
243
  *
244
- * @since 1.2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  *
246
  * @return bool False on failure.
247
  */
248
  function bp_activity_action_post_update() {
249
 
250
- // Do not proceed if user is not logged in, not viewing activity, or not posting.
251
  if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'post' ) )
252
  return false;
253
 
254
- // Check the nonce.
255
  check_admin_referer( 'post_update', '_wpnonce_post_update' );
256
 
257
- /**
258
- * Filters the content provided in the activity input field.
259
- *
260
- * @since 1.2.0
261
- *
262
- * @param string $value Activity message being posted.
263
- */
264
  $content = apply_filters( 'bp_activity_post_update_content', $_POST['whats-new'] );
265
 
266
  if ( ! empty( $_POST['whats-new-post-object'] ) ) {
267
-
268
- /**
269
- * Filters the item type that the activity update should be associated with.
270
- *
271
- * @since 1.2.0
272
- *
273
- * @param string $value Item type to associate with.
274
- */
275
  $object = apply_filters( 'bp_activity_post_update_object', $_POST['whats-new-post-object'] );
276
  }
277
 
278
  if ( ! empty( $_POST['whats-new-post-in'] ) ) {
279
-
280
- /**
281
- * Filters what component the activity is being to.
282
- *
283
- * @since 1.2.0
284
- *
285
- * @param string $value Chosen component to post activity to.
286
- */
287
  $item_id = apply_filters( 'bp_activity_post_update_item_id', $_POST['whats-new-post-in'] );
288
  }
289
 
290
- // No activity content so provide feedback and redirect.
291
  if ( empty( $content ) ) {
292
  bp_core_add_message( __( 'Please enter some content to post.', 'buddypress' ), 'error' );
293
  bp_core_redirect( wp_get_referer() );
294
  }
295
 
296
- // No existing item_id.
297
  if ( empty( $item_id ) ) {
298
  $activity_id = bp_activity_post_update( array( 'content' => $content ) );
299
 
300
- // Post to groups object.
301
- } elseif ( 'groups' == $object && bp_is_active( 'groups' ) ) {
302
  if ( (int) $item_id ) {
303
  $activity_id = groups_post_update( array( 'content' => $content, 'group_id' => $item_id ) );
304
  }
305
 
 
306
  } else {
307
-
308
- /**
309
- * Filters activity object for BuddyPress core and plugin authors before posting activity update.
310
- *
311
- * @since 1.2.0
312
- *
313
- * @param string $object Activity item being associated to.
314
- * @param string $item_id Component ID being posted to.
315
- * @param string $content Activity content being posted.
316
- */
317
  $activity_id = apply_filters( 'bp_activity_custom_update', $object, $item_id, $content );
318
  }
319
 
320
- // Provide user feedback.
321
  if ( !empty( $activity_id ) )
322
  bp_core_add_message( __( 'Update Posted!', 'buddypress' ) );
323
  else
324
- bp_core_add_message( __( 'There was an error when posting your update. Please try again.', 'buddypress' ), 'error' );
325
 
326
- // Redirect.
327
  bp_core_redirect( wp_get_referer() );
328
  }
329
  add_action( 'bp_actions', 'bp_activity_action_post_update' );
@@ -331,7 +299,18 @@ add_action( 'bp_actions', 'bp_activity_action_post_update' );
331
  /**
332
  * Post new activity comment.
333
  *
334
- * @since 1.2.0
 
 
 
 
 
 
 
 
 
 
 
335
  *
336
  * @return bool False on failure.
337
  */
@@ -340,25 +319,10 @@ function bp_activity_action_post_comment() {
340
  if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'reply' ) )
341
  return false;
342
 
343
- // Check the nonce.
344
  check_admin_referer( 'new_activity_comment', '_wpnonce_new_activity_comment' );
345
 
346
- /**
347
- * Filters the activity ID a comment will be in reply to.
348
- *
349
- * @since 1.2.0
350
- *
351
- * @param string $value ID of the activity being replied to.
352
- */
353
  $activity_id = apply_filters( 'bp_activity_post_comment_activity_id', $_POST['comment_form_id'] );
354
-
355
- /**
356
- * Filters the comment content for a comment reply.
357
- *
358
- * @since 1.2.0
359
- *
360
- * @param string $value Comment content being posted.
361
- */
362
  $content = apply_filters( 'bp_activity_post_comment_content', $_POST['ac_input_' . $activity_id] );
363
 
364
  if ( empty( $content ) ) {
@@ -375,7 +339,7 @@ function bp_activity_action_post_comment() {
375
  if ( !empty( $comment_id ) )
376
  bp_core_add_message( __( 'Reply Posted!', 'buddypress' ) );
377
  else
378
- bp_core_add_message( __( 'There was an error posting that reply. Please try again.', 'buddypress' ), 'error' );
379
 
380
  bp_core_redirect( wp_get_referer() . '#ac-form-' . $activity_id );
381
  }
@@ -384,7 +348,17 @@ add_action( 'bp_actions', 'bp_activity_action_post_comment' );
384
  /**
385
  * Mark activity as favorite.
386
  *
387
- * @since 1.2.0
 
 
 
 
 
 
 
 
 
 
388
  *
389
  * @return bool False on failure.
390
  */
@@ -393,13 +367,13 @@ function bp_activity_action_mark_favorite() {
393
  if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'favorite' ) )
394
  return false;
395
 
396
- // Check the nonce.
397
  check_admin_referer( 'mark_favorite' );
398
 
399
  if ( bp_activity_add_user_favorite( bp_action_variable( 0 ) ) )
400
  bp_core_add_message( __( 'Activity marked as favorite.', 'buddypress' ) );
401
  else
402
- bp_core_add_message( __( 'There was an error marking that activity as a favorite. Please try again.', 'buddypress' ), 'error' );
403
 
404
  bp_core_redirect( wp_get_referer() . '#activity-' . bp_action_variable( 0 ) );
405
  }
@@ -408,7 +382,17 @@ add_action( 'bp_actions', 'bp_activity_action_mark_favorite' );
408
  /**
409
  * Remove activity from favorites.
410
  *
411
- * @since 1.2.0
 
 
 
 
 
 
 
 
 
 
412
  *
413
  * @return bool False on failure.
414
  */
@@ -417,13 +401,13 @@ function bp_activity_action_remove_favorite() {
417
  if ( ! is_user_logged_in() || ! bp_is_activity_component() || ! bp_is_current_action( 'unfavorite' ) )
418
  return false;
419
 
420
- // Check the nonce.
421
  check_admin_referer( 'unmark_favorite' );
422
 
423
  if ( bp_activity_remove_user_favorite( bp_action_variable( 0 ) ) )
424
  bp_core_add_message( __( 'Activity removed as favorite.', 'buddypress' ) );
425
  else
426
- bp_core_add_message( __( 'There was an error removing that activity as a favorite. Please try again.', 'buddypress' ), 'error' );
427
 
428
  bp_core_redirect( wp_get_referer() . '#activity-' . bp_action_variable( 0 ) );
429
  }
@@ -432,22 +416,28 @@ add_action( 'bp_actions', 'bp_activity_action_remove_favorite' );
432
  /**
433
  * Load the sitewide activity feed.
434
  *
435
- * @since 1.0.0
 
 
 
 
 
 
436
  *
437
  * @return bool False on failure.
438
  */
439
  function bp_activity_action_sitewide_feed() {
440
- $bp = buddypress();
441
 
442
  if ( ! bp_is_activity_component() || ! bp_is_current_action( 'feed' ) || bp_is_user() || ! empty( $bp->groups->current_group ) )
443
  return false;
444
 
445
- // Setup the feed.
446
  buddypress()->activity->feed = new BP_Activity_Feed( array(
447
  'id' => 'sitewide',
448
 
449
  /* translators: Sitewide activity RSS title - "[Site Name] | Site Wide Activity" */
450
- 'title' => sprintf( __( '%s | Site-Wide Activity', 'buddypress' ), bp_get_site_name() ),
451
 
452
  'link' => bp_get_activity_directory_permalink(),
453
  'description' => __( 'Activity feed for the entire site.', 'buddypress' ),
@@ -459,7 +449,11 @@ add_action( 'bp_actions', 'bp_activity_action_sitewide_feed' );
459
  /**
460
  * Load a user's personal activity feed.
461
  *
462
- * @since 1.0.0
 
 
 
 
463
  *
464
  * @return bool False on failure.
465
  */
@@ -468,7 +462,7 @@ function bp_activity_action_personal_feed() {
468
  return false;
469
  }
470
 
471
- // Setup the feed.
472
  buddypress()->activity->feed = new BP_Activity_Feed( array(
473
  'id' => 'personal',
474
 
@@ -485,7 +479,14 @@ add_action( 'bp_actions', 'bp_activity_action_personal_feed' );
485
  /**
486
  * Load a user's friends' activity feed.
487
  *
488
- * @since 1.0.0
 
 
 
 
 
 
 
489
  *
490
  * @return bool False on failure.
491
  */
@@ -494,7 +495,7 @@ function bp_activity_action_friends_feed() {
494
  return false;
495
  }
496
 
497
- // Setup the feed.
498
  buddypress()->activity->feed = new BP_Activity_Feed( array(
499
  'id' => 'friends',
500
 
@@ -511,7 +512,14 @@ add_action( 'bp_actions', 'bp_activity_action_friends_feed' );
511
  /**
512
  * Load the activity feed for a user's groups.
513
  *
514
- * @since 1.2.0
 
 
 
 
 
 
 
515
  *
516
  * @return bool False on failure.
517
  */
@@ -520,11 +528,11 @@ function bp_activity_action_my_groups_feed() {
520
  return false;
521
  }
522
 
523
- // Get displayed user's group IDs.
524
  $groups = groups_get_user_groups();
525
  $group_ids = implode( ',', $groups['groups'] );
526
 
527
- // Setup the feed.
528
  buddypress()->activity->feed = new BP_Activity_Feed( array(
529
  'id' => 'mygroups',
530
 
@@ -532,7 +540,7 @@ function bp_activity_action_my_groups_feed() {
532
  'title' => sprintf( __( '%1$s | %2$s | Group Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
533
 
534
  'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_groups_slug() ),
535
- 'description' => sprintf( __( "Public group activity feed of which %s is a member.", 'buddypress' ), bp_get_displayed_user_fullname() ),
536
  'activity_args' => array(
537
  'object' => buddypress()->groups->id,
538
  'primary_id' => $group_ids,
@@ -545,7 +553,12 @@ add_action( 'bp_actions', 'bp_activity_action_my_groups_feed' );
545
  /**
546
  * Load a user's @mentions feed.
547
  *
548
- * @since 1.2.0
 
 
 
 
 
549
  *
550
  * @return bool False on failure.
551
  */
@@ -558,7 +571,7 @@ function bp_activity_action_mentions_feed() {
558
  return false;
559
  }
560
 
561
- // Setup the feed.
562
  buddypress()->activity->feed = new BP_Activity_Feed( array(
563
  'id' => 'mentions',
564
 
@@ -577,7 +590,12 @@ add_action( 'bp_actions', 'bp_activity_action_mentions_feed' );
577
  /**
578
  * Load a user's favorites feed.
579
  *
580
- * @since 1.2.0
 
 
 
 
 
581
  *
582
  * @return bool False on failure.
583
  */
@@ -586,11 +604,11 @@ function bp_activity_action_favorites_feed() {
586
  return false;
587
  }
588
 
589
- // Get displayed user's favorite activity IDs.
590
  $favs = bp_activity_get_user_favorites( bp_displayed_user_id() );
591
  $fav_ids = implode( ',', (array) $favs );
592
 
593
- // Setup the feed.
594
  buddypress()->activity->feed = new BP_Activity_Feed( array(
595
  'id' => 'favorites',
596
 
@@ -605,250 +623,27 @@ function bp_activity_action_favorites_feed() {
605
  add_action( 'bp_actions', 'bp_activity_action_favorites_feed' );
606
 
607
  /**
608
- * AJAX endpoint for Suggestions API lookups.
609
  *
610
- * @since 2.1.0
611
- */
612
- function bp_ajax_get_suggestions() {
613
- if ( ! bp_is_user_active() || empty( $_GET['term'] ) || empty( $_GET['type'] ) ) {
614
- wp_send_json_error( 'missing_parameter' );
615
- exit;
616
- }
617
-
618
- $args = array(
619
- 'term' => sanitize_text_field( $_GET['term'] ),
620
- 'type' => sanitize_text_field( $_GET['type'] ),
621
- );
622
-
623
- // Support per-Group suggestions.
624
- if ( ! empty( $_GET['group-id'] ) ) {
625
- $args['group_id'] = absint( $_GET['group-id'] );
626
- }
627
-
628
- $results = bp_core_get_suggestions( $args );
629
-
630
- if ( is_wp_error( $results ) ) {
631
- wp_send_json_error( $results->get_error_message() );
632
- exit;
633
- }
634
-
635
- wp_send_json_success( $results );
636
- }
637
- add_action( 'wp_ajax_bp_get_suggestions', 'bp_ajax_get_suggestions' );
638
-
639
- /**
640
- * Detect a change in post type status, and initiate an activity update if necessary.
641
- *
642
- * @since 2.2.0
643
- *
644
- * @todo Support untrashing better.
645
  *
646
- * @param string $new_status New status for the post.
647
- * @param string $old_status Old status for the post.
648
- * @param object $post Post data.
649
  */
650
- function bp_activity_catch_transition_post_type_status( $new_status, $old_status, $post ) {
651
- if ( ! post_type_supports( $post->post_type, 'buddypress-activity' ) ) {
652
- return;
653
- }
654
-
655
- // This is an edit.
656
- if ( $new_status === $old_status ) {
657
- // An edit of an existing post should update the existing activity item.
658
- if ( $new_status == 'publish' ) {
659
- $edit = bp_activity_post_type_update( $post );
660
-
661
- // Post was never recorded into activity stream, so record it now!
662
- if ( null === $edit ) {
663
- bp_activity_post_type_publish( $post->ID, $post );
664
- }
665
-
666
- // Allow plugins to eventually deal with other post statuses.
667
- } else {
668
- /**
669
- * Fires when editing the post and the new status is not 'publish'.
670
- *
671
- * This is a variable filter that is dependent on the post type
672
- * being untrashed.
673
- *
674
- * @since 2.5.0
675
- *
676
- * @param WP_Post $post Post data.
677
- * @param string $new_status New status for the post.
678
- * @param string $old_status Old status for the post.
679
- */
680
- do_action( 'bp_activity_post_type_edit_' . $post->post_type, $post, $new_status, $old_status );
681
- }
682
-
683
- return;
684
- }
685
-
686
- // Publishing a previously unpublished post.
687
- if ( 'publish' === $new_status ) {
688
- // Untrashing the post type - nothing here yet.
689
- if ( 'trash' == $old_status ) {
690
-
691
- /**
692
- * Fires if untrashing post in a post type.
693
- *
694
- * This is a variable filter that is dependent on the post type
695
- * being untrashed.
696
- *
697
- * @since 2.2.0
698
- *
699
- * @param WP_Post $post Post data.
700
- */
701
- do_action( 'bp_activity_post_type_untrash_' . $post->post_type, $post );
702
- } else {
703
- // Record the post.
704
- bp_activity_post_type_publish( $post->ID, $post );
705
- }
706
-
707
- // Unpublishing a previously published post.
708
- } elseif ( 'publish' === $old_status ) {
709
- // Some form of pending status - only remove the activity entry.
710
- bp_activity_post_type_unpublish( $post->ID, $post );
711
 
712
- // For any other cases, allow plugins to eventually deal with it.
713
- } else {
714
- /**
715
- * Fires when the old and the new post status are not 'publish'.
716
- *
717
- * This is a variable filter that is dependent on the post type
718
- * being untrashed.
719
- *
720
- * @since 2.5.0
721
- *
722
- * @param WP_Post $post Post data.
723
- * @param string $new_status New status for the post.
724
- * @param string $old_status Old status for the post.
725
- */
726
- do_action( 'bp_activity_post_type_transition_status_' . $post->post_type, $post, $new_status, $old_status );
727
- }
728
- }
729
- add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 );
730
-
731
- /**
732
- * When a post type comment status transition occurs, update the relevant activity's status.
733
- *
734
- * @since 2.5.0
735
- *
736
- * @param string $new_status New comment status.
737
- * @param string $old_status Previous comment status.
738
- * @param WP_Comment $comment Comment data.
739
- */
740
- function bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment ) {
741
- $post_type = get_post_type( $comment->comment_post_ID );
742
- if ( ! $post_type ) {
743
  return;
744
- }
745
-
746
- // Get the post type tracking args.
747
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
748
-
749
- // Bail if the activity type does not exist
750
- if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
751
- return false;
752
-
753
- // Set the $activity_comment_object
754
- } else {
755
- $activity_comment_object = $activity_post_object->comments_tracking;
756
- }
757
-
758
- // Init an empty activity ID
759
- $activity_id = 0;
760
-
761
- /**
762
- * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
763
- *
764
- * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
765
- * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
766
- * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
767
- * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
768
- * Otherwise, record the comment into the activity stream.
769
- */
770
-
771
- // This clause handles delete/hold.
772
- if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
773
- return bp_activity_post_type_remove_comment( $comment->comment_ID, $activity_post_object );
774
-
775
- // These clauses handle trash, spam, and un-spams.
776
- } elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
777
- $action = 'spam_activity';
778
- } elseif ( 'approved' == $new_status ) {
779
- $action = 'ham_activity';
780
- }
781
-
782
- // Get the activity
783
- if ( bp_disable_blogforum_comments() ) {
784
- $activity_id = bp_activity_get_activity_id( array(
785
- 'component' => $activity_comment_object->component_id,
786
- 'item_id' => get_current_blog_id(),
787
- 'secondary_item_id' => $comment->comment_ID,
788
- 'type' => $activity_comment_object->action_id,
789
- ) );
790
- } else {
791
- $activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
792
- }
793
-
794
- /**
795
- * Leave a chance to plugins to manage activity comments differently.
796
- *
797
- * @since 2.5.0
798
- *
799
- * @param bool $value True to override BuddyPress management.
800
- * @param string $post_type The post type name.
801
- * @param int $activity_id The post type activity (0 if not found).
802
- * @param string $new_status The new status of the post type comment.
803
- * @param string $old_status The old status of the post type comment.
804
- * @param WP_Comment $comment Comment data.
805
- */
806
- if ( true === apply_filters( 'bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment ) ) {
807
- return false;
808
- }
809
-
810
- // Check activity item exists
811
- if ( empty( $activity_id ) ) {
812
- // If no activity exists, but the comment has been approved, record it into the activity table.
813
- if ( 'approved' == $new_status ) {
814
- return bp_activity_post_type_comment( $comment->comment_ID, true, $activity_post_object );
815
- }
816
 
 
 
817
  return;
818
- }
819
 
820
- // Create an activity object
821
- $activity = new BP_Activity_Activity( $activity_id );
822
- if ( empty( $activity->component ) ) {
823
  return;
824
- }
825
-
826
- // Spam/ham the activity if it's not already in that state
827
- if ( 'spam_activity' === $action && ! $activity->is_spam ) {
828
- bp_activity_mark_as_spam( $activity );
829
- } elseif ( 'ham_activity' == $action) {
830
- bp_activity_mark_as_ham( $activity );
831
- }
832
-
833
- // Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
834
- $post_type_comment_action = $activity_comment_object->action_id;
835
- $comment_akismet_history = function ( $activity_types ) use ( $post_type_comment_action ) {
836
- $activity_types[] = $post_type_comment_action;
837
-
838
- return $activity_types;
839
- };
840
- add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
841
-
842
- // Make sure the activity change won't edit the comment if sync is on
843
- remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
844
-
845
- // Save the updated activity
846
- $activity->save();
847
-
848
- // Restore the action
849
- add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
850
 
851
- // Remove the "new_blog_comment" activity type whitelist so we don't break anything
852
- remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
853
  }
854
- add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
1
  <?php
2
+
3
  /**
4
  * Action functions are exactly the same as screen functions, however they do
5
  * not have a template screen associated with them. Usually they will send the
7
  *
8
  * @package BuddyPress
9
  * @subpackage ActivityActions
 
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( !defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
  * Allow core components and dependent plugins to register activity actions.
17
  *
18
+ * @since BuddyPress (1.2)
19
  *
20
+ * @uses do_action() To call 'bp_register_activity_actions' hook.
21
  */
22
  function bp_register_activity_actions() {
 
 
 
 
 
 
23
  do_action( 'bp_register_activity_actions' );
24
  }
25
  add_action( 'bp_init', 'bp_register_activity_actions', 8 );
27
  /**
28
  * Catch and route requests for single activity item permalinks.
29
  *
30
+ * @since BuddyPress (1.2)
31
+ *
32
+ * @global object $bp BuddyPress global settings
33
+ * @uses bp_is_activity_component()
34
+ * @uses bp_is_current_action()
35
+ * @uses bp_action_variable()
36
+ * @uses bp_activity_get_specific()
37
+ * @uses bp_is_active()
38
+ * @uses bp_core_get_user_domain()
39
+ * @uses groups_get_group()
40
+ * @uses bp_get_group_permalink()
41
+ * @uses apply_filters_ref_array() To call the 'bp_activity_permalink_redirect_url' hook.
42
+ * @uses bp_core_redirect()
43
+ * @uses bp_get_root_domain()
44
  *
45
  * @return bool False on failure.
46
  */
47
  function bp_activity_action_permalink_router() {
48
 
49
+ // Not viewing activity
50
  if ( ! bp_is_activity_component() || ! bp_is_current_action( 'p' ) )
51
  return false;
52
 
53
+ // No activity to display
54
  if ( ! bp_action_variable( 0 ) || ! is_numeric( bp_action_variable( 0 ) ) )
55
  return false;
56
 
57
+ // Get the activity details
58
  $activity = bp_activity_get_specific( array( 'activity_ids' => bp_action_variable( 0 ), 'show_hidden' => true ) );
59
 
60
  // 404 if activity does not exist
65
  $activity = $activity['activities'][0];
66
  }
67
 
68
+ // Do not redirect at default
69
  $redirect = false;
70
 
71
+ // Redirect based on the type of activity
72
  if ( bp_is_active( 'groups' ) && $activity->component == buddypress()->groups->id ) {
73
 
74
+ // Activity is a user update
75
  if ( ! empty( $activity->user_id ) ) {
76
  $redirect = bp_core_get_user_domain( $activity->user_id, $activity->user_nicename, $activity->user_login ) . bp_get_activity_slug() . '/' . $activity->id . '/';
77
 
78
+ // Activity is something else
79
  } else {
80
 
81
+ // Set redirect to group activity stream
82
+ if ( $group = groups_get_group( array( 'group_id' => $activity->item_id ) ) ) {
83
  $redirect = bp_get_group_permalink( $group ) . bp_get_activity_slug() . '/' . $activity->id . '/';
84
  }
85
  }
86
 
87
+ // Set redirect to users' activity stream
88
+ } else if ( ! empty( $activity->user_id ) ) {
89
  $redirect = bp_core_get_user_domain( $activity->user_id, $activity->user_nicename, $activity->user_login ) . bp_get_activity_slug() . '/' . $activity->id . '/';
90
  }
91
 
92
+ // If set, add the original query string back onto the redirect URL
93
  if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
94
  $query_frags = array();
95
  wp_parse_str( $_SERVER['QUERY_STRING'], $query_frags );
96
  $redirect = add_query_arg( urlencode_deep( $query_frags ), $redirect );
97
  }
98
 
99
+ // Allow redirect to be filtered
 
 
 
 
 
 
100
  if ( ! $redirect = apply_filters_ref_array( 'bp_activity_permalink_redirect_url', array( $redirect, &$activity ) ) ) {
101
  bp_core_redirect( bp_get_root_domain() );
102
  }
103
 
104
+ // Redirect to the actual activity permalink page
105
  bp_core_redirect( $redirect );
106
  }
107
  add_action( 'bp_actions', 'bp_activity_action_permalink_router' );
109
  /**
110
  * Delete specific activity item and redirect to previous page.
111
  *
112
+ * @since BuddyPress (1.1)
113
  *
114
  * @param int $activity_id Activity id to be deleted. Defaults to 0.
115
+ *
116
+ * @uses bp_is_activity_component()
117
+ * @uses bp_is_current_action()
118
+ * @uses bp_action_variable()
119
+ * @uses check_admin_referer()
120
+ * @uses bp_activity_user_can_delete()
121
+ * @uses do_action() Calls 'bp_activity_before_action_delete_activity' hook to allow actions to be taken before the activity is deleted.
122
+ * @uses bp_activity_delete()
123
+ * @uses bp_core_add_message()
124
+ * @uses do_action() Calls 'bp_activity_action_delete_activity' hook to allow actions to be taken after the activity is deleted.
125
+ * @uses bp_core_redirect()
126
+ *
127
  * @return bool False on failure.
128
  */
129
  function bp_activity_action_delete_activity( $activity_id = 0 ) {
130
 
131
+ // Not viewing activity or action is not delete
132
  if ( !bp_is_activity_component() || !bp_is_current_action( 'delete' ) )
133
  return false;
134
 
135
  if ( empty( $activity_id ) && bp_action_variable( 0 ) )
136
  $activity_id = (int) bp_action_variable( 0 );
137
 
138
+ // Not viewing a specific activity item
139
  if ( empty( $activity_id ) )
140
  return false;
141
 
142
+ // Check the nonce
143
  check_admin_referer( 'bp_activity_delete_link' );
144
 
145
+ // Load up the activity item
146
  $activity = new BP_Activity_Activity( $activity_id );
147
 
148
+ // Check access
149
  if ( ! bp_activity_user_can_delete( $activity ) )
150
  return false;
151
 
152
+ // Call the action before the delete so plugins can still fetch information about it
 
 
 
 
 
 
 
153
  do_action( 'bp_activity_before_action_delete_activity', $activity_id, $activity->user_id );
154
 
155
+ // Delete the activity item and provide user feedback
156
  if ( bp_activity_delete( array( 'id' => $activity_id, 'user_id' => $activity->user_id ) ) )
157
  bp_core_add_message( __( 'Activity deleted successfully', 'buddypress' ) );
158
  else
159
  bp_core_add_message( __( 'There was an error when deleting that activity', 'buddypress' ), 'error' );
160
 
 
 
 
 
 
 
 
 
161
  do_action( 'bp_activity_action_delete_activity', $activity_id, $activity->user_id );
162
 
163
+ // Check for the redirect query arg, otherwise let WP handle things
164
+ if ( !empty( $_GET['redirect_to'] ) )
165
  bp_core_redirect( esc_url( $_GET['redirect_to'] ) );
166
  else
167
  bp_core_redirect( wp_get_referer() );
171
  /**
172
  * Mark specific activity item as spam and redirect to previous page.
173
  *
174
+ * @since BuddyPress (1.6)
175
  *
176
+ * @global object $bp BuddyPress global settings
177
  * @param int $activity_id Activity id to be deleted. Defaults to 0.
178
  * @return bool False on failure.
179
  */
180
  function bp_activity_action_spam_activity( $activity_id = 0 ) {
181
+ global $bp;
182
 
183
+ // Not viewing activity, or action is not spam, or Akismet isn't present
184
  if ( !bp_is_activity_component() || !bp_is_current_action( 'spam' ) || empty( $bp->activity->akismet ) )
185
  return false;
186
 
187
  if ( empty( $activity_id ) && bp_action_variable( 0 ) )
188
  $activity_id = (int) bp_action_variable( 0 );
189
 
190
+ // Not viewing a specific activity item
191
  if ( empty( $activity_id ) )
192
  return false;
193
 
195
  if ( !bp_activity_user_can_mark_spam() )
196
  return false;
197
 
198
+ // Load up the activity item
199
  $activity = new BP_Activity_Activity( $activity_id );
200
  if ( empty( $activity->id ) )
201
  return false;
202
 
203
+ // Check nonce
204
  check_admin_referer( 'bp_activity_akismet_spam_' . $activity->id );
205
 
206
+ // Call an action before the spamming so plugins can modify things if they want to
 
 
 
 
 
 
 
207
  do_action( 'bp_activity_before_action_spam_activity', $activity->id, $activity );
208
 
209
+ // Mark as spam
210
  bp_activity_mark_as_spam( $activity );
211
  $activity->save();
212
 
213
+ // Tell the user the spamming has been succesful
214
  bp_core_add_message( __( 'The activity item has been marked as spam and is no longer visible.', 'buddypress' ) );
215
 
 
 
 
 
 
 
 
 
216
  do_action( 'bp_activity_action_spam_activity', $activity_id, $activity->user_id );
217
 
218
+ // Check for the redirect query arg, otherwise let WP handle things
219
+ if ( !empty( $_GET['redirect_to'] ) )
220
  bp_core_redirect( esc_url( $_GET['redirect_to'] ) );
221
  else
222
  bp_core_redirect( wp_get_referer() );
226
  /**
227
  * Post user/group activity update.
228
  *
229
+ * @since BuddyPress (1.2)
230
+ *
231
+ * @uses is_user_logged_in()
232
+ * @uses bp_is_activity_component()
233
+ * @uses bp_is_current_action()
234
+ * @uses check_admin_referer()
235
+ * @uses apply_filters() To call 'bp_activity_post_update_content' hook.
236
+ * @uses apply_filters() To call 'bp_activity_post_update_object' hook.
237
+ * @uses apply_filters() To call 'bp_activity_post_update_item_id' hook.
238
+ * @uses bp_core_add_message()
239
+ * @uses bp_core_redirect()
240
+ * @uses bp_activity_post_update()
241
+ * @uses groups_post_update()
242
+ * @uses bp_core_redirect()
243
+ * @uses apply_filters() To call 'bp_activity_custom_update' hook.
244
  *
245
  * @return bool False on failure.
246
  */
247
  function bp_activity_action_post_update() {
248
 
249
+ // Do not proceed if user is not logged in, not viewing activity, or not posting
250
  if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'post' ) )
251
  return false;
252
 
253
+ // Check the nonce
254
  check_admin_referer( 'post_update', '_wpnonce_post_update' );
255
 
256
+ // Get activity info
 
 
 
 
 
 
257
  $content = apply_filters( 'bp_activity_post_update_content', $_POST['whats-new'] );
258
 
259
  if ( ! empty( $_POST['whats-new-post-object'] ) ) {
 
 
 
 
 
 
 
 
260
  $object = apply_filters( 'bp_activity_post_update_object', $_POST['whats-new-post-object'] );
261
  }
262
 
263
  if ( ! empty( $_POST['whats-new-post-in'] ) ) {
 
 
 
 
 
 
 
 
264
  $item_id = apply_filters( 'bp_activity_post_update_item_id', $_POST['whats-new-post-in'] );
265
  }
266
 
267
+ // No activity content so provide feedback and redirect
268
  if ( empty( $content ) ) {
269
  bp_core_add_message( __( 'Please enter some content to post.', 'buddypress' ), 'error' );
270
  bp_core_redirect( wp_get_referer() );
271
  }
272
 
273
+ // No existing item_id
274
  if ( empty( $item_id ) ) {
275
  $activity_id = bp_activity_post_update( array( 'content' => $content ) );
276
 
277
+ // Post to groups object
278
+ } else if ( 'groups' == $object && bp_is_active( 'groups' ) ) {
279
  if ( (int) $item_id ) {
280
  $activity_id = groups_post_update( array( 'content' => $content, 'group_id' => $item_id ) );
281
  }
282
 
283
+ // Special circumstance so let filters handle it
284
  } else {
 
 
 
 
 
 
 
 
 
 
285
  $activity_id = apply_filters( 'bp_activity_custom_update', $object, $item_id, $content );
286
  }
287
 
288
+ // Provide user feedback
289
  if ( !empty( $activity_id ) )
290
  bp_core_add_message( __( 'Update Posted!', 'buddypress' ) );
291
  else
292
+ bp_core_add_message( __( 'There was an error when posting your update, please try again.', 'buddypress' ), 'error' );
293
 
294
+ // Redirect
295
  bp_core_redirect( wp_get_referer() );
296
  }
297
  add_action( 'bp_actions', 'bp_activity_action_post_update' );
299
  /**
300
  * Post new activity comment.
301
  *
302
+ * @since BuddyPress (1.2)
303
+ *
304
+ * @uses is_user_logged_in()
305
+ * @uses bp_is_activity_component()
306
+ * @uses bp_is_current_action()
307
+ * @uses check_admin_referer()
308
+ * @uses apply_filters() To call 'bp_activity_post_comment_activity_id' hook.
309
+ * @uses apply_filters() To call 'bp_activity_post_comment_content' hook.
310
+ * @uses bp_core_add_message()
311
+ * @uses bp_core_redirect()
312
+ * @uses bp_activity_new_comment()
313
+ * @uses wp_get_referer()
314
  *
315
  * @return bool False on failure.
316
  */
319
  if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'reply' ) )
320
  return false;
321
 
322
+ // Check the nonce
323
  check_admin_referer( 'new_activity_comment', '_wpnonce_new_activity_comment' );
324
 
 
 
 
 
 
 
 
325
  $activity_id = apply_filters( 'bp_activity_post_comment_activity_id', $_POST['comment_form_id'] );
 
 
 
 
 
 
 
 
326
  $content = apply_filters( 'bp_activity_post_comment_content', $_POST['ac_input_' . $activity_id] );
327
 
328
  if ( empty( $content ) ) {
339
  if ( !empty( $comment_id ) )
340
  bp_core_add_message( __( 'Reply Posted!', 'buddypress' ) );
341
  else
342
+ bp_core_add_message( __( 'There was an error posting that reply, please try again.', 'buddypress' ), 'error' );
343
 
344
  bp_core_redirect( wp_get_referer() . '#ac-form-' . $activity_id );
345
  }
348
  /**
349
  * Mark activity as favorite.
350
  *
351
+ * @since BuddyPress (1.2)
352
+ *
353
+ * @uses is_user_logged_in()
354
+ * @uses bp_is_activity_component()
355
+ * @uses bp_is_current_action()
356
+ * @uses check_admin_referer()
357
+ * @uses bp_activity_add_user_favorite()
358
+ * @uses bp_action_variable()
359
+ * @uses bp_core_add_message()
360
+ * @uses bp_core_redirect()
361
+ * @uses wp_get_referer()
362
  *
363
  * @return bool False on failure.
364
  */
367
  if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'favorite' ) )
368
  return false;
369
 
370
+ // Check the nonce
371
  check_admin_referer( 'mark_favorite' );
372
 
373
  if ( bp_activity_add_user_favorite( bp_action_variable( 0 ) ) )
374
  bp_core_add_message( __( 'Activity marked as favorite.', 'buddypress' ) );
375
  else
376
+ bp_core_add_message( __( 'There was an error marking that activity as a favorite, please try again.', 'buddypress' ), 'error' );
377
 
378
  bp_core_redirect( wp_get_referer() . '#activity-' . bp_action_variable( 0 ) );
379
  }
382
  /**
383
  * Remove activity from favorites.
384
  *
385
+ * @since BuddyPress (1.2)
386
+ *
387
+ * @uses is_user_logged_in()
388
+ * @uses bp_is_activity_component()
389
+ * @uses bp_is_current_action()
390
+ * @uses check_admin_referer()
391
+ * @uses bp_activity_remove_user_favorite()
392
+ * @uses bp_action_variable()
393
+ * @uses bp_core_add_message()
394
+ * @uses bp_core_redirect()
395
+ * @uses wp_get_referer()
396
  *
397
  * @return bool False on failure.
398
  */
401
  if ( ! is_user_logged_in() || ! bp_is_activity_component() || ! bp_is_current_action( 'unfavorite' ) )
402
  return false;
403
 
404
+ // Check the nonce
405
  check_admin_referer( 'unmark_favorite' );
406
 
407
  if ( bp_activity_remove_user_favorite( bp_action_variable( 0 ) ) )
408
  bp_core_add_message( __( 'Activity removed as favorite.', 'buddypress' ) );
409
  else
410
+ bp_core_add_message( __( 'There was an error removing that activity as a favorite, please try again.', 'buddypress' ), 'error' );
411
 
412
  bp_core_redirect( wp_get_referer() . '#activity-' . bp_action_variable( 0 ) );
413
  }
416
  /**
417
  * Load the sitewide activity feed.
418
  *
419
+ * @since BuddyPress (1.0)
420
+ *
421
+ * @global object $bp BuddyPress global settings
422
+ * @uses bp_is_activity_component()
423
+ * @uses bp_is_current_action()
424
+ * @uses bp_is_user()
425
+ * @uses status_header()
426
  *
427
  * @return bool False on failure.
428
  */
429
  function bp_activity_action_sitewide_feed() {
430
+ global $bp;
431
 
432
  if ( ! bp_is_activity_component() || ! bp_is_current_action( 'feed' ) || bp_is_user() || ! empty( $bp->groups->current_group ) )
433
  return false;
434
 
435
+ // setup the feed
436
  buddypress()->activity->feed = new BP_Activity_Feed( array(
437
  'id' => 'sitewide',
438
 
439
  /* translators: Sitewide activity RSS title - "[Site Name] | Site Wide Activity" */
440
+ 'title' => sprintf( __( '%s | Site Wide Activity', 'buddypress' ), bp_get_site_name() ),
441
 
442
  'link' => bp_get_activity_directory_permalink(),
443
  'description' => __( 'Activity feed for the entire site.', 'buddypress' ),
449
  /**
450
  * Load a user's personal activity feed.
451
  *
452
+ * @since BuddyPress (1.0)
453
+ *
454
+ * @uses bp_is_user_activity()
455
+ * @uses bp_is_current_action()
456
+ * @uses status_header()
457
  *
458
  * @return bool False on failure.
459
  */
462
  return false;
463
  }
464
 
465
+ // setup the feed
466
  buddypress()->activity->feed = new BP_Activity_Feed( array(
467
  'id' => 'personal',
468
 
479
  /**
480
  * Load a user's friends' activity feed.
481
  *
482
+ * @since BuddyPress (1.0)
483
+ *
484
+ * @uses bp_is_active()
485
+ * @uses bp_is_user_activity()
486
+ * @uses bp_is_current_action()
487
+ * @uses bp_get_friends_slug()
488
+ * @uses bp_is_action_variable()
489
+ * @uses status_header()
490
  *
491
  * @return bool False on failure.
492
  */
495
  return false;
496
  }
497
 
498
+ // setup the feed
499
  buddypress()->activity->feed = new BP_Activity_Feed( array(
500
  'id' => 'friends',
501
 
512
  /**
513
  * Load the activity feed for a user's groups.
514
  *
515
+ * @since BuddyPress (1.2)
516
+ *
517
+ * @uses bp_is_active()
518
+ * @uses bp_is_user_activity()
519
+ * @uses bp_is_current_action()
520
+ * @uses bp_get_groups_slug()
521
+ * @uses bp_is_action_variable()
522
+ * @uses status_header()
523
  *
524
  * @return bool False on failure.
525
  */
528
  return false;
529
  }
530
 
531
+ // get displayed user's group IDs
532
  $groups = groups_get_user_groups();
533
  $group_ids = implode( ',', $groups['groups'] );
534
 
535
+ // setup the feed
536
  buddypress()->activity->feed = new BP_Activity_Feed( array(
537
  'id' => 'mygroups',
538
 
540
  'title' => sprintf( __( '%1$s | %2$s | Group Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
541
 
542
  'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_groups_slug() ),
543
+ 'description' => sprintf( __( "Public group activity feed of which %s is a member of.", 'buddypress' ), bp_get_displayed_user_fullname() ),
544
  'activity_args' => array(
545
  'object' => buddypress()->groups->id,
546
  'primary_id' => $group_ids,
553
  /**
554
  * Load a user's @mentions feed.
555
  *
556
+ * @since BuddyPress (1.2)
557
+ *
558
+ * @uses bp_is_user_activity()
559
+ * @uses bp_is_current_action()
560
+ * @uses bp_is_action_variable()
561
+ * @uses status_header()
562
  *
563
  * @return bool False on failure.
564
  */
571
  return false;
572
  }
573
 
574
+ // setup the feed
575
  buddypress()->activity->feed = new BP_Activity_Feed( array(
576
  'id' => 'mentions',
577
 
590
  /**
591
  * Load a user's favorites feed.
592
  *
593
+ * @since BuddyPress (1.2)
594
+ *
595
+ * @uses bp_is_user_activity()
596
+ * @uses bp_is_current_action()
597
+ * @uses bp_is_action_variable()
598
+ * @uses status_header()
599
  *
600
  * @return bool False on failure.
601
  */
604
  return false;
605
  }
606
 
607
+ // get displayed user's favorite activity IDs
608
  $favs = bp_activity_get_user_favorites( bp_displayed_user_id() );
609
  $fav_ids = implode( ',', (array) $favs );
610
 
611
+ // setup the feed
612
  buddypress()->activity->feed = new BP_Activity_Feed( array(
613
  'id' => 'favorites',
614
 
623
  add_action( 'bp_actions', 'bp_activity_action_favorites_feed' );
624
 
625
  /**
626
+ * Loads Akismet filtering for activity.
627
  *
628
+ * @since BuddyPress (1.6)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
629
  *
630
+ * @global object $bp BuddyPress global settings
 
 
631
  */
632
+ function bp_activity_setup_akismet() {
633
+ global $bp;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
634
 
635
+ // Bail if Akismet is not active
636
+ if ( ! defined( 'AKISMET_VERSION' ) )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
 
639
+ // Bail if no Akismet key is set
640
+ if ( ! bp_get_option( 'wordpress_api_key' ) && ! defined( 'WPCOM_API_KEY' ) )
641
  return;
 
642
 
643
+ // Bail if BuddyPress Activity Akismet support has been disabled by another plugin
644
+ if ( ! apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) )
 
645
  return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
 
647
+ // Instantiate Akismet for BuddyPress
648
+ $bp->activity->akismet = new BP_Akismet();
649
  }
 
bp-activity/bp-activity-admin.php CHANGED
@@ -6,31 +6,31 @@
6
  * help text, on which this implementation is heavily based.
7
  *
8
  * @package BuddyPress
9
- * @subpackage ActivityAdmin
10
- * @since 1.6.0
11
  */
12
 
13
- // Exit if accessed directly.
14
- defined( 'ABSPATH' ) || exit;
15
 
16
- // Include WP's list table class.
17
  if ( !class_exists( 'WP_List_Table' ) ) require( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
18
 
19
- // Per_page screen option. Has to be hooked in extremely early.
20
  if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-activity' == $_REQUEST['page'] )
21
  add_filter( 'set-screen-option', 'bp_activity_admin_screen_options', 10, 3 );
22
 
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',
@@ -49,10 +49,10 @@ add_action( bp_core_admin_hook(), 'bp_activity_add_admin_menu' );
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' );
@@ -66,10 +66,10 @@ add_filter( 'bp_admin_menu_order', 'bp_activity_admin_menu_order' );
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;
@@ -79,15 +79,15 @@ function bp_activity_admin_reply() {
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' ) );
@@ -97,25 +97,25 @@ function bp_activity_admin_reply() {
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,
@@ -124,7 +124,7 @@ function bp_activity_admin_reply() {
124
  );
125
  ob_end_clean();
126
 
127
- // Send response.
128
  $r = new WP_Ajax_Response();
129
  $r->add( $response );
130
  $r->send();
@@ -136,10 +136,11 @@ add_action( 'wp_ajax_bp-activity-admin-reply', 'bp_activity_admin_reply' );
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
  */
@@ -147,7 +148,7 @@ 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;
@@ -158,28 +159,18 @@ function bp_activity_admin_screen_options( $value, $option, $new_value ) {
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
 
172
- // Hide the primary link meta box by default.
173
  $hidden = array_merge( (array) $hidden, array( 'bp_activity_itemids', 'bp_activity_link', 'bp_activity_type', 'bp_activity_userid', ) );
174
 
175
- /**
176
- * Filters default hidden metaboxes so plugins can alter list.
177
- *
178
- * @since 1.6.0
179
- *
180
- * @param array $hidden Default metaboxes to hide.
181
- * @param WP_Screen $screen Screen identifier.
182
- */
183
  return apply_filters( 'bp_hide_meta_boxes', array_unique( $hidden ), $screen );
184
  }
185
  add_filter( 'default_hidden_meta_boxes', 'bp_activity_admin_edit_hidden_metaboxes', 10, 2 );
@@ -189,33 +180,30 @@ add_filter( 'default_hidden_meta_boxes', 'bp_activity_admin_edit_hidden_metaboxe
189
  *
190
  * Does the following:
191
  * - Register contextual help and screen options for this admin page.
192
- * - Enqueues scripts and styles.
193
- * - Catches POST and GET requests related to Activity.
194
  *
195
- * @since 1.6.0
196
  *
197
- * @global object $bp BuddyPress global settings.
198
  * @global BP_Activity_List_Table $bp_activity_list_table Activity screen list table.
199
  */
200
  function bp_activity_admin_load() {
201
  global $bp_activity_list_table;
202
 
203
- $bp = buddypress();
 
 
 
 
204
  $doaction = bp_admin_list_table_current_bulk_action();
205
- $min = bp_core_get_minified_asset_suffix();
206
 
207
- /**
208
- * Fires at top of Activity admin page.
209
- *
210
- * @since 1.6.0
211
- *
212
- * @param string $doaction Current $_GET action being performed in admin screen.
213
- */
214
  do_action( 'bp_activity_admin_load', $doaction );
215
 
216
- // Edit screen.
217
  if ( 'edit' == $doaction && ! empty( $_GET['aid'] ) ) {
218
- // Columns screen option.
219
  add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) );
220
 
221
  get_current_screen()->add_help_tab( array(
@@ -232,16 +220,16 @@ function bp_activity_admin_load() {
232
  'title' => __( 'Item, Link, Type', 'buddypress' ),
233
  'content' =>
234
  '<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>' .
235
- '<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>' .
236
  '<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>' .
237
  '<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>'
238
  ) );
239
 
240
- // Help panel - sidebar links.
241
  get_current_screen()->set_help_sidebar(
242
  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
243
- '<p>' . __( '<a href="https://codex.buddypress.org/administrator-guide/activity-stream-management-panels/">Managing Activity</a>', 'buddypress' ) . '</p>' .
244
- '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
245
  );
246
 
247
  // Register metaboxes for the edit screen.
@@ -251,27 +239,20 @@ function bp_activity_admin_load() {
251
  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' );
252
  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' );
253
 
254
- /**
255
- * Fires after the registration of all of the default activity meta boxes.
256
- *
257
- * @since 2.4.0
258
- */
259
- do_action( 'bp_activity_admin_meta_boxes' );
260
-
261
- // Enqueue JavaScript files.
262
  wp_enqueue_script( 'postbox' );
263
  wp_enqueue_script( 'dashboard' );
264
  wp_enqueue_script( 'comment' );
265
 
266
- // Index screen.
267
  } else {
268
- // Create the Activity screen list table.
269
  $bp_activity_list_table = new BP_Activity_List_Table();
270
 
271
- // The per_page screen option.
272
  add_screen_option( 'per_page', array( 'label' => _x( 'Activity', 'Activity items per page (screen options)', 'buddypress' )) );
273
 
274
- // Help panel - overview text.
275
  get_current_screen()->add_help_tab( array(
276
  'id' => 'bp-activity-overview',
277
  'title' => __( 'Overview', 'buddypress' ),
@@ -280,7 +261,7 @@ function bp_activity_admin_load() {
280
  '<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>'
281
  ) );
282
 
283
- // Help panel - moderation text.
284
  get_current_screen()->add_help_tab( array(
285
  'id' => 'bp-activity-moderating',
286
  'title' => __( 'Moderating Activity', 'buddypress' ),
@@ -289,86 +270,61 @@ function bp_activity_admin_load() {
289
  '<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>'
290
  ) );
291
 
292
- // Help panel - sidebar links.
293
  get_current_screen()->set_help_sidebar(
294
  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
295
- '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
296
  );
297
-
298
- // Add accessible hidden heading and text for Activity screen pagination.
299
- if ( bp_get_major_wp_version() >= 4.4 ) {
300
- get_current_screen()->set_screen_reader_content( array(
301
- /* translators: accessibility text */
302
- 'heading_pagination' => __( 'Activity list navigation', 'buddypress' ),
303
- ) );
304
- }
305
  }
306
 
307
- // Enqueue CSS and JavaScript.
308
- 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 );
309
  wp_localize_script( 'bp_activity_admin_js', 'bp_activity_admin_vars', array(
310
- 'page' => get_current_screen()->id
311
- ) );
312
- wp_enqueue_style( 'bp_activity_admin_css', $bp->plugin_url . "bp-activity/admin/css/admin{$min}.css", array(), bp_get_version() );
313
 
314
- wp_style_add_data( 'bp_activity_admin_css', 'rtl', true );
315
- if ( $min ) {
316
- wp_style_add_data( 'bp_activity_admin_css', 'suffix', $min );
317
- }
318
-
319
- /**
320
- * Fires after the activity js and style has been enqueued.
321
- *
322
- * @since 2.4.0
323
- */
324
- do_action( 'bp_activity_admin_enqueue_scripts' );
325
-
326
- // Handle spam/un-spam/delete of activities.
327
  if ( !empty( $doaction ) && ! in_array( $doaction, array( '-1', 'edit', 'save', ) ) ) {
328
 
329
- // Build redirection URL.
330
  $redirect_to = remove_query_arg( array( 'aid', 'deleted', 'error', 'spammed', 'unspammed', ), wp_get_referer() );
331
  $redirect_to = add_query_arg( 'paged', $bp_activity_list_table->get_pagenum(), $redirect_to );
332
 
333
- // Get activity IDs.
334
  $activity_ids = array_map( 'absint', (array) $_REQUEST['aid'] );
335
 
336
- /**
337
- * Filters list of IDs being spammed/un-spammed/deleted.
338
- *
339
- * @since 1.6.0
340
- *
341
- * @param array $activity_ids Activity IDs to spam/un-spam/delete.
342
- */
343
  $activity_ids = apply_filters( 'bp_activity_admin_action_activity_ids', $activity_ids );
344
 
345
  // Is this a bulk request?
346
  if ( 'bulk_' == substr( $doaction, 0, 5 ) && ! empty( $_REQUEST['aid'] ) ) {
347
- // Check this is a valid form submission.
348
  check_admin_referer( 'bulk-activities' );
349
 
350
- // Trim 'bulk_' off the action name to avoid duplicating a ton of code.
351
  $doaction = substr( $doaction, 5 );
352
 
353
  // This is a request to delete, spam, or un-spam, a single item.
354
  } elseif ( !empty( $_REQUEST['aid'] ) ) {
355
 
356
- // Check this is a valid form submission.
357
  check_admin_referer( 'spam-activity_' . $activity_ids[0] );
358
  }
359
 
360
- // Initialise counters for how many of each type of item we perform an action on.
361
  $deleted = $spammed = $unspammed = 0;
362
 
363
- // Store any errors that occurs when updating the database items.
364
  $errors = array();
365
 
366
  // "We'd like to shoot the monster, could you move, please?"
367
  foreach ( $activity_ids as $activity_id ) {
368
  // @todo: Check the permissions on each
369
- // if ( ! current_user_can( 'bp_edit_activity', $activity_id ) )
370
- // continue;
371
- // Get the activity from the database.
 
372
  $activity = new BP_Activity_Activity( $activity_id );
373
  if ( empty( $activity->component ) ) {
374
  $errors[] = $activity_id;
@@ -390,13 +346,13 @@ function bp_activity_admin_load() {
390
  * Remove moderation and blacklist checks in case we want to ham an activity
391
  * which contains one of these listed keys.
392
  */
393
- remove_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2 );
394
- remove_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2 );
395
 
396
  bp_activity_mark_as_ham( $activity );
397
  $result = $activity->save();
398
 
399
- // Check for any error during activity save.
400
  if ( ! $result )
401
  $errors[] = $activity->id;
402
  else
@@ -407,7 +363,7 @@ function bp_activity_admin_load() {
407
  bp_activity_mark_as_spam( $activity );
408
  $result = $activity->save();
409
 
410
- // Check for any error during activity save.
411
  if ( ! $result )
412
  $errors[] = $activity->id;
413
  else
@@ -418,21 +374,11 @@ function bp_activity_admin_load() {
418
  break;
419
  }
420
 
421
- // Release memory.
422
  unset( $activity );
423
  }
424
 
425
- /**
426
- * Fires before redirect for plugins to do something with activity.
427
- *
428
- * Passes an activity array counts how many were spam, not spam, deleted, and IDs that were errors.
429
- *
430
- * @since 1.6.0
431
- *
432
- * @param array $value Array holding spam, not spam, deleted counts, error IDs.
433
- * @param string $redirect_to URL to redirect to.
434
- * @param array $activity_ids Original array of activity IDs.
435
- */
436
  do_action( 'bp_activity_admin_action_after', array( $spammed, $unspammed, $deleted, $errors ), $redirect_to, $activity_ids );
437
 
438
  // Add arguments to the redirect URL so that on page reload, we can easily display what we've just done.
@@ -445,87 +391,82 @@ function bp_activity_admin_load() {
445
  if ( $deleted )
446
  $redirect_to = add_query_arg( 'deleted', $deleted, $redirect_to );
447
 
448
- // If an error occurred, pass back the activity ID that failed.
449
  if ( ! empty( $errors ) )
450
  $redirect_to = add_query_arg( 'error', implode ( ',', array_map( 'absint', $errors ) ), $redirect_to );
451
 
452
- /**
453
- * Filters redirect URL after activity spamming/un-spamming/deletion occurs.
454
- *
455
- * @since 1.6.0
456
- *
457
- * @param string $redirect_to URL to redirect to.
458
- */
459
  wp_redirect( apply_filters( 'bp_activity_admin_action_redirect', $redirect_to ) );
460
  exit;
461
 
462
 
463
- // Save the edit.
464
  } elseif ( $doaction && 'save' == $doaction ) {
465
- // Build redirection URL.
466
  $redirect_to = remove_query_arg( array( 'action', 'aid', 'deleted', 'error', 'spammed', 'unspammed', ), $_SERVER['REQUEST_URI'] );
467
 
468
- // Get activity ID.
469
  $activity_id = (int) $_REQUEST['aid'];
470
 
471
- // Check this is a valid form submission.
472
  check_admin_referer( 'edit-activity_' . $activity_id );
473
 
474
- // Get the activity from the database.
475
  $activity = new BP_Activity_Activity( $activity_id );
476
 
477
- // If the activity doesn't exist, just redirect back to the index.
478
  if ( empty( $activity->component ) ) {
479
  wp_redirect( $redirect_to );
480
  exit;
481
  }
482
 
483
- // Check the form for the updated properties.
484
- // Store any error that occurs when updating the database item.
 
485
  $error = 0;
486
 
487
- // Activity spam status.
488
  $prev_spam_status = $new_spam_status = false;
489
  if ( ! empty( $_POST['activity_status'] ) ) {
490
  $prev_spam_status = $activity->is_spam;
491
  $new_spam_status = ( 'spam' == $_POST['activity_status'] ) ? true : false;
492
  }
493
 
494
- // Activity action.
495
  if ( isset( $_POST['bp-activities-action'] ) )
496
  $activity->action = $_POST['bp-activities-action'];
497
 
498
- // Activity content.
499
  if ( isset( $_POST['bp-activities-content'] ) )
500
  $activity->content = $_POST['bp-activities-content'];
501
 
502
- // Activity primary link.
503
  if ( ! empty( $_POST['bp-activities-link'] ) )
504
  $activity->primary_link = $_POST['bp-activities-link'];
505
 
506
- // Activity user ID.
507
  if ( ! empty( $_POST['bp-activities-userid'] ) )
508
  $activity->user_id = (int) $_POST['bp-activities-userid'];
509
 
510
- // Activity item primary ID.
511
  if ( isset( $_POST['bp-activities-primaryid'] ) )
512
  $activity->item_id = (int) $_POST['bp-activities-primaryid'];
513
 
514
- // Activity item secondary ID.
515
  if ( isset( $_POST['bp-activities-secondaryid'] ) )
516
  $activity->secondary_item_id = (int) $_POST['bp-activities-secondaryid'];
517
 
518
- // Activity type.
519
  if ( ! empty( $_POST['bp-activities-type'] ) ) {
520
  $actions = bp_activity_admin_get_activity_actions();
521
 
522
- // Check that the new type is a registered activity type.
523
  if ( in_array( $_POST['bp-activities-type'], $actions ) ) {
524
  $activity->type = $_POST['bp-activities-type'];
525
  }
526
  }
527
 
528
- // Activity timestamp.
529
  if ( ! empty( $_POST['aa'] ) && ! empty( $_POST['mm'] ) && ! empty( $_POST['jj'] ) && ! empty( $_POST['hh'] ) && ! empty( $_POST['mn'] ) && ! empty( $_POST['ss'] ) ) {
530
  $aa = $_POST['aa'];
531
  $mm = $_POST['mm'];
@@ -541,7 +482,7 @@ function bp_activity_admin_load() {
541
  $mn = ( $mn > 59 ) ? $mn -60 : $mn;
542
  $ss = ( $ss > 59 ) ? $ss -60 : $ss;
543
 
544
- // Reconstruct the date into a timestamp.
545
  $gmt_date = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
546
 
547
  $activity->date_recorded = $gmt_date;
@@ -555,38 +496,26 @@ function bp_activity_admin_load() {
555
  bp_activity_mark_as_ham( $activity );
556
  }
557
 
558
- // Save.
559
  $result = $activity->save();
560
 
561
- // Clear the activity stream first page cache, in case this activity's timestamp was changed.
562
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
563
 
564
- // Check for any error during activity save.
565
  if ( false === $result )
566
  $error = $activity->id;
567
 
568
- /**
569
- * Fires before redirect so plugins can do something first on save action.
570
- *
571
- * @since 1.6.0
572
- *
573
- * @param array $value Array holding activity object and ID that holds error.
574
- */
575
  do_action_ref_array( 'bp_activity_admin_edit_after', array( &$activity, $error ) );
576
 
577
- // If an error occurred, pass back the activity ID that failed.
578
  if ( $error )
579
- $redirect_to = add_query_arg( 'error', $error, $redirect_to );
580
  else
581
- $redirect_to = add_query_arg( 'updated', $activity->id, $redirect_to );
582
 
583
- /**
584
- * Filters URL to redirect to after saving.
585
- *
586
- * @since 1.6.0
587
- *
588
- * @param string $redirect_to URL to redirect to.
589
- */
590
  wp_redirect( apply_filters( 'bp_activity_admin_edit_redirect', $redirect_to ) );
591
  exit;
592
 
@@ -601,17 +530,17 @@ function bp_activity_admin_load() {
601
  /**
602
  * Output the Activity component admin screens.
603
  *
604
- * @since 1.6.0
605
  */
606
  function bp_activity_admin() {
607
- // Decide whether to load the index or edit screen.
608
  $doaction = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
609
 
610
- // Display the single activity edit screen.
611
  if ( 'edit' == $doaction && ! empty( $_GET['aid'] ) )
612
  bp_activity_admin_edit();
613
 
614
- // Otherwise, display the Activity index screen.
615
  else
616
  bp_activity_admin_index();
617
  }
@@ -619,7 +548,7 @@ function bp_activity_admin() {
619
  /**
620
  * Display the single activity edit screen.
621
  *
622
- * @since 1.6.0
623
  */
624
  function bp_activity_admin_edit() {
625
 
@@ -628,7 +557,7 @@ function bp_activity_admin_edit() {
628
  if ( ! is_super_admin() )
629
  die( '-1' );
630
 
631
- // Get the activity from the database.
632
  $activity = bp_activity_get( array(
633
  'in' => ! empty( $_REQUEST['aid'] ) ? (int) $_REQUEST['aid'] : 0,
634
  'max' => 1,
@@ -640,55 +569,42 @@ function bp_activity_admin_edit() {
640
  if ( ! empty( $activity['activities'][0] ) ) {
641
  $activity = $activity['activities'][0];
642
 
643
- // Workaround to use WP's touch_time() without duplicating that function.
644
  $GLOBALS['comment'] = new stdClass;
645
  $GLOBALS['comment']->comment_date = $activity->date_recorded;
646
  } else {
647
  $activity = '';
648
  }
649
 
650
- // Construct URL for form.
651
  $form_url = remove_query_arg( array( 'action', 'deleted', 'error', 'spammed', 'unspammed', ), $_SERVER['REQUEST_URI'] );
652
  $form_url = add_query_arg( 'action', 'save', $form_url );
653
 
654
- /**
655
- * Fires before activity edit form is displays so plugins can modify the activity.
656
- *
657
- * @since 1.6.0
658
- *
659
- * @param array $value Array holding single activity object that was passed by reference.
660
- */
661
  do_action_ref_array( 'bp_activity_admin_edit', array( &$activity ) ); ?>
662
 
663
  <div class="wrap">
664
- <h1><?php printf( __( 'Editing Activity (ID #%s)', 'buddypress' ), number_format_i18n( (int) $_REQUEST['aid'] ) ); ?></h1>
 
665
 
666
  <?php if ( ! empty( $activity ) ) : ?>
667
 
668
- <form action="<?php echo esc_url( $form_url ); ?>" id="bp-activities-edit-form" method="post">
669
  <div id="poststuff">
670
 
671
  <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
672
  <div id="post-body-content">
673
  <div id="postdiv">
674
  <div id="bp_activity_action" class="postbox">
675
- <h2><?php _e( 'Action', 'buddypress' ); ?></h2>
676
  <div class="inside">
677
- <label for="bp-activities-action" class="screen-reader-text"><?php
678
- /* translators: accessibility text */
679
- _e( 'Edit activity action', 'buddypress' );
680
- ?></label>
681
  <?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' ) ) ); ?>
682
  </div>
683
  </div>
684
 
685
  <div id="bp_activity_content" class="postbox">
686
- <h2><?php _e( 'Content', 'buddypress' ); ?></h2>
687
  <div class="inside">
688
- <label for="bp-activities-content" class="screen-reader-text"><?php
689
- /* translators: accessibility text */
690
- _e( 'Edit activity content', 'buddypress' );
691
- ?></label>
692
  <?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' ) ) ); ?>
693
  </div>
694
  </div>
@@ -712,16 +628,7 @@ function bp_activity_admin_edit() {
712
  </form>
713
 
714
  <?php else : ?>
715
-
716
- <p><?php
717
- printf(
718
- '%1$s <a href="%2$s">%3$s</a>',
719
- __( 'No activity found with this ID.', 'buddypress' ),
720
- esc_url( bp_get_admin_url( 'admin.php?page=bp-activity' ) ),
721
- __( 'Go back and try again.', 'buddypress' )
722
- );
723
- ?></p>
724
-
725
  <?php endif; ?>
726
 
727
  </div><!-- .wrap -->
@@ -732,7 +639,7 @@ function bp_activity_admin_edit() {
732
  /**
733
  * Status metabox for the Activity admin edit screen.
734
  *
735
- * @since 1.6.0
736
  *
737
  * @param object $item Activity item.
738
  */
@@ -752,17 +659,17 @@ function bp_activity_admin_edit_metabox_status( $item ) {
752
 
753
  <div id="misc-publishing-actions">
754
  <div class="misc-pub-section" id="comment-status-radio">
755
- <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 />
756
- <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>
757
  </div>
758
 
759
  <div class="misc-pub-section curtime misc-pub-section-last">
760
  <?php
761
- // Translators: Publish box date format, see http://php.net/date.
762
  $datef = __( 'M j, Y @ G:i', 'buddypress' );
763
  $date = date_i18n( $datef, strtotime( $item->date_recorded ) );
764
  ?>
765
- <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>
766
 
767
  <div id='timestampdiv' class='hide-if-js'>
768
  <?php touch_time( 1, 0, 5 ); ?>
@@ -775,7 +682,7 @@ function bp_activity_admin_edit_metabox_status( $item ) {
775
 
776
  <div id="major-publishing-actions">
777
  <div id="publishing-action">
778
- <?php submit_button( __( 'Update', 'buddypress' ), 'primary', 'save', false ); ?>
779
  </div>
780
  <div class="clear"></div>
781
  </div><!-- #major-publishing-actions -->
@@ -788,19 +695,16 @@ function bp_activity_admin_edit_metabox_status( $item ) {
788
  /**
789
  * Primary link metabox for the Activity admin edit screen.
790
  *
791
- * @since 1.6.0
792
  *
793
  * @param object $item Activity item.
794
  */
795
  function bp_activity_admin_edit_metabox_link( $item ) {
796
  ?>
797
 
798
- <label class="screen-reader-text" for="bp-activities-link"><?php
799
- /* translators: accessibility text */
800
- _e( 'Link', 'buddypress' );
801
- ?></label>
802
- <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" />
803
- <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>
804
 
805
  <?php
806
  }
@@ -808,18 +712,15 @@ function bp_activity_admin_edit_metabox_link( $item ) {
808
  /**
809
  * User ID metabox for the Activity admin edit screen.
810
  *
811
- * @since 1.6.0
812
  *
813
  * @param object $item Activity item.
814
  */
815
  function bp_activity_admin_edit_metabox_userid( $item ) {
816
  ?>
817
 
818
- <label class="screen-reader-text" for="bp-activities-userid"><?php
819
- /* translators: accessibility text */
820
- _e( 'Author ID', 'buddypress' );
821
- ?></label>
822
- <input type="number" name="bp-activities-userid" id="bp-activities-userid" value="<?php echo esc_attr( $item->user_id ); ?>" min="1" />
823
 
824
  <?php
825
  }
@@ -829,15 +730,15 @@ function bp_activity_admin_edit_metabox_userid( $item ) {
829
  *
830
  * Format is [activity_type] => Pretty name for activity type.
831
  *
832
- * @since 2.0.0
833
  *
834
- * @return array $actions
835
  */
836
  function bp_activity_admin_get_activity_actions() {
837
  $actions = array();
838
 
839
  // Walk through the registered actions, and build an array of actions/values.
840
- foreach ( bp_activity_get_actions() as $action ) {
841
  $action = array_values( (array) $action );
842
 
843
  for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ ) {
@@ -845,47 +746,47 @@ function bp_activity_admin_get_activity_actions() {
845
  }
846
  }
847
 
848
- // This was a mis-named activity type from before BP 1.6.
849
  unset( $actions['friends_register_activity_action'] );
850
 
851
- // Sort array by the human-readable value.
852
  natsort( $actions );
853
 
854
  return $actions;
855
  }
856
 
857
  /**
858
- * Activity type metabox for the Activity admin edit screen.
 
 
859
  *
860
- * @since 1.6.0
861
  *
862
  * @param object $item Activity item.
863
  */
864
  function bp_activity_admin_edit_metabox_type( $item ) {
865
- $bp = buddypress();
866
 
867
  $actions = array();
868
  $selected = $item->type;
869
 
870
  // Walk through the registered actions, and build an array of actions/values.
871
- foreach ( bp_activity_get_actions() as $action ) {
872
  $action = array_values( (array) $action );
873
 
874
  for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ )
875
  $actions[ $action[$i]['key'] ] = $action[$i]['value'];
876
  }
877
 
878
- // This was a mis-named activity type from before BP 1.6.
879
  unset( $actions['friends_register_activity_action'] );
880
 
881
- // Sort array by the human-readable value.
882
  natsort( $actions );
883
 
884
- /*
885
- * If the activity type is not registered properly (eg, a plugin has
886
- * not called bp_activity_set_action()), add the raw type to the end
887
- * of the list.
888
- */
889
  if ( ! isset( $actions[ $selected ] ) ) {
890
  _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' );
891
  $actions[ $selected ] = $selected;
@@ -893,11 +794,7 @@ function bp_activity_admin_edit_metabox_type( $item ) {
893
 
894
  ?>
895
 
896
- <label for="bp-activities-type" class="screen-reader-text"><?php
897
- /* translators: accessibility text */
898
- esc_html_e( 'Select activity type', 'buddypress' );
899
- ?></label>
900
- <select name="bp-activities-type" id="bp-activities-type">
901
  <?php foreach ( $actions as $k => $v ) : ?>
902
  <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $k, $selected ); ?>><?php echo esc_html( $v ); ?></option>
903
  <?php endforeach; ?>
@@ -909,7 +806,7 @@ function bp_activity_admin_edit_metabox_type( $item ) {
909
  /**
910
  * Primary item ID/Secondary item ID metabox for the Activity admin edit screen.
911
  *
912
- * @since 1.6.0
913
  *
914
  * @param object $item Activity item.
915
  */
@@ -931,17 +828,18 @@ function bp_activity_admin_edit_metabox_itemids( $item ) {
931
  /**
932
  * Display the Activity admin index screen, which contains a list of all the activities.
933
  *
934
- * @since 1.6.0
935
  *
936
- * @global BP_Activity_List_Table $bp_activity_list_table Activity screen list table.
937
- * @global string $plugin_page The current plugin page.
 
938
  */
939
  function bp_activity_admin_index() {
940
  global $bp_activity_list_table, $plugin_page;
941
 
942
  $messages = array();
943
 
944
- // If the user has just made a change to an activity item, build status messages.
945
  if ( ! empty( $_REQUEST['deleted'] ) || ! empty( $_REQUEST['spammed'] ) || ! empty( $_REQUEST['unspammed'] ) || ! empty( $_REQUEST['error'] ) || ! empty( $_REQUEST['updated'] ) ) {
946
  $deleted = ! empty( $_REQUEST['deleted'] ) ? (int) $_REQUEST['deleted'] : 0;
947
  $errors = ! empty( $_REQUEST['error'] ) ? $_REQUEST['error'] : '';
@@ -951,14 +849,14 @@ function bp_activity_admin_index() {
951
 
952
  $errors = array_map( 'absint', explode( ',', $errors ) );
953
 
954
- // Make sure we don't get any empty values in $errors.
955
  for ( $i = 0, $errors_count = count( $errors ); $i < $errors_count; $i++ ) {
956
  if ( 0 === $errors[$i] ) {
957
  unset( $errors[$i] );
958
  }
959
  }
960
 
961
- // Reindex array.
962
  $errors = array_values( $errors );
963
 
964
  if ( $deleted > 0 )
@@ -972,9 +870,9 @@ function bp_activity_admin_index() {
972
  $error_msg = __( 'Errors occurred when trying to update these activity items:', 'buddypress' );
973
  $error_msg .= '<ul class="activity-errors">';
974
 
975
- // Display each error as a list item.
976
  foreach ( $errors as $error ) {
977
- // Translators: This is a bulleted list of item IDs.
978
  $error_msg .= '<li>' . sprintf( __( '#%s', 'buddypress' ), number_format_i18n( $error ) ) . '</li>';
979
  }
980
 
@@ -990,40 +888,35 @@ function bp_activity_admin_index() {
990
  $messages[] = sprintf( _n( '%s activity item has been successfully unspammed.', '%s activity items have been successfully unspammed.', $unspammed, 'buddypress' ), number_format_i18n( $unspammed ) );
991
 
992
  if ( $updated > 0 )
993
- $messages[] = __( 'The activity item has been updated successfully.', 'buddypress' );
994
  }
995
 
996
- // Prepare the activity items for display.
997
  $bp_activity_list_table->prepare_items();
998
 
999
- /**
1000
- * Fires before edit form is displayed so plugins can modify the activity messages.
1001
- *
1002
- * @since 1.6.0
1003
- *
1004
- * @param array $messages Array of messages to display at top of page.
1005
- */
1006
  do_action( 'bp_activity_admin_index', $messages ); ?>
1007
 
1008
  <div class="wrap">
1009
- <h1>
 
1010
  <?php if ( !empty( $_REQUEST['aid'] ) ) : ?>
1011
  <?php printf( __( 'Activity related to ID #%s', 'buddypress' ), number_format_i18n( (int) $_REQUEST['aid'] ) ); ?>
1012
  <?php else : ?>
1013
- <?php _ex( 'Activity', 'Admin SWA page', 'buddypress' ); ?>
1014
  <?php endif; ?>
1015
 
1016
  <?php if ( !empty( $_REQUEST['s'] ) ) : ?>
1017
  <span class="subtitle"><?php printf( __( 'Search results for &#8220;%s&#8221;', 'buddypress' ), wp_html_excerpt( esc_html( stripslashes( $_REQUEST['s'] ) ), 50 ) ); ?></span>
1018
  <?php endif; ?>
1019
- </h1>
1020
 
1021
- <?php // If the user has just made a change to an activity item, display the status messages. ?>
1022
  <?php if ( !empty( $messages ) ) : ?>
1023
  <div id="moderated" class="<?php echo ( ! empty( $_REQUEST['error'] ) ) ? 'error' : 'updated'; ?>"><p><?php echo implode( "<br/>\n", $messages ); ?></p></div>
1024
  <?php endif; ?>
1025
 
1026
- <?php // Display each activity on its own row. ?>
1027
  <?php $bp_activity_list_table->views(); ?>
1028
 
1029
  <form id="bp-activities-form" action="" method="get">
@@ -1032,24 +925,20 @@ function bp_activity_admin_index() {
1032
  <?php $bp_activity_list_table->display(); ?>
1033
  </form>
1034
 
1035
- <?php // This markup is used for the reply form. ?>
1036
  <table style="display: none;">
1037
  <tr id="bp-activities-container" style="display: none;">
1038
  <td colspan="4">
1039
  <form method="get" action="">
1040
 
1041
- <h3 id="bp-replyhead"><?php _e( 'Reply to Activity', 'buddypress' ); ?></h3>
1042
- <label for="bp-activities" class="screen-reader-text"><?php
1043
- /* translators: accessibility text */
1044
- _e( 'Reply', 'buddypress' );
1045
- ?></label>
1046
  <?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, ) ); ?>
1047
 
1048
  <p id="bp-replysubmit" class="submit">
1049
  <a href="#" class="cancel button-secondary alignleft"><?php _e( 'Cancel', 'buddypress' ); ?></a>
1050
  <a href="#" class="save button-primary alignright"><?php _e( 'Reply', 'buddypress' ); ?></a>
1051
 
1052
- <img class="waiting" style="display:none;" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
1053
  <span class="error" style="display:none;"></span>
1054
  <br class="clear" />
1055
  </p>
@@ -1064,3 +953,626 @@ function bp_activity_admin_index() {
1064
 
1065
  <?php
1066
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  * help text, on which this implementation is heavily based.
7
  *
8
  * @package BuddyPress
9
+ * @since BuddyPress (1.6.0)
10
+ * @subpackage Activity
11
  */
12
 
13
+ // Exit if accessed directly
14
+ if ( !defined( 'ABSPATH' ) ) exit;
15
 
16
+ // Include WP's list table class
17
  if ( !class_exists( 'WP_List_Table' ) ) require( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
18
 
19
+ // per_page screen option. Has to be hooked in extremely early.
20
  if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-activity' == $_REQUEST['page'] )
21
  add_filter( 'set-screen-option', 'bp_activity_admin_screen_options', 10, 3 );
22
 
23
  /**
24
  * Register the Activity component admin screen.
25
  *
26
+ * @since BuddyPress (1.6)
27
  */
28
  function bp_activity_add_admin_menu() {
29
 
30
+ // Add our screen
31
  $hook = add_menu_page(
32
+ __( 'Activity', 'buddypress' ),
33
+ __( 'Activity', 'buddypress' ),
34
  'bp_moderate',
35
  'bp-activity',
36
  'bp_activity_admin',
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 BuddyPress (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' );
66
  * Processes requests to add new activity comments, and echoes HTML for a new
67
  * table row.
68
  *
69
+ * @since BuddyPress (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;
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' ) );
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,
124
  );
125
  ob_end_clean();
126
 
127
+ // Send response
128
  $r = new WP_Ajax_Response();
129
  $r->add( $response );
130
  $r->send();
136
  /**
137
  * Handle save/update of screen options for the Activity component admin screen.
138
  *
139
+ * @since BuddyPress (1.6.0)
140
  *
141
+ * @param string $value Will always be false unless another plugin filters it
142
+ * first.
143
+ * @param string $option Screen option name.
144
  * @param string $new_value Screen option form value.
145
  * @return string Option value. False to abandon update.
146
  */
148
  if ( 'toplevel_page_bp_activity_per_page' != $option && 'toplevel_page_bp_activity_network_per_page' != $option )
149
  return $value;
150
 
151
+ // Per page
152
  $new_value = (int) $new_value;
153
  if ( $new_value < 1 || $new_value > 999 )
154
  return $value;
159
  /**
160
  * Hide the advanced edit meta boxes by default, so we don't clutter the screen.
161
  *
162
+ * @since BuddyPress (1.6.0)
163
  *
 
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
  return apply_filters( 'bp_hide_meta_boxes', array_unique( $hidden ), $screen );
175
  }
176
  add_filter( 'default_hidden_meta_boxes', 'bp_activity_admin_edit_hidden_metaboxes', 10, 2 );
180
  *
181
  * Does the following:
182
  * - Register contextual help and screen options for this admin page.
183
+ * - Enqueues scripts and styles
184
+ * - Catches POST and GET requests related to Activity
185
  *
186
+ * @since BuddyPress (1.6.0)
187
  *
188
+ * @global object $bp BuddyPress global settings.
189
  * @global BP_Activity_List_Table $bp_activity_list_table Activity screen list table.
190
  */
191
  function bp_activity_admin_load() {
192
  global $bp_activity_list_table;
193
 
194
+ $bp = buddypress();
195
+
196
+ // Decide whether to load the dev version of the CSS and JavaScript
197
+ $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : 'min.';
198
+
199
  $doaction = bp_admin_list_table_current_bulk_action();
 
200
 
201
+ // Call an action for plugins to hook in early
 
 
 
 
 
 
202
  do_action( 'bp_activity_admin_load', $doaction );
203
 
204
+ // Edit screen
205
  if ( 'edit' == $doaction && ! empty( $_GET['aid'] ) ) {
206
+ // columns screen option
207
  add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) );
208
 
209
  get_current_screen()->add_help_tab( array(
220
  'title' => __( 'Item, Link, Type', 'buddypress' ),
221
  'content' =>
222
  '<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>' .
223
+ '<p>' . __( '<strong>Link</strong> - 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. Some types of activity may not use this field, even if it has been set.', 'buddypress' ) . '</p>' .
224
  '<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>' .
225
  '<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>'
226
  ) );
227
 
228
+ // Help panel - sidebar links
229
  get_current_screen()->set_help_sidebar(
230
  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
231
+ '<p>' . __( '<a href="http://codex.buddypress.org/buddypress-site-administration/managing-activity/">Managing Activity</a>', 'buddypress' ) . '</p>' .
232
+ '<p>' . __( '<a href="http://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
233
  );
234
 
235
  // Register metaboxes for the edit screen.
239
  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' );
240
  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' );
241
 
242
+ // Enqueue javascripts
 
 
 
 
 
 
 
243
  wp_enqueue_script( 'postbox' );
244
  wp_enqueue_script( 'dashboard' );
245
  wp_enqueue_script( 'comment' );
246
 
247
+ // Index screen
248
  } else {
249
+ // Create the Activity screen list table
250
  $bp_activity_list_table = new BP_Activity_List_Table();
251
 
252
+ // per_page screen option
253
  add_screen_option( 'per_page', array( 'label' => _x( 'Activity', 'Activity items per page (screen options)', 'buddypress' )) );
254
 
255
+ // Help panel - overview text
256
  get_current_screen()->add_help_tab( array(
257
  'id' => 'bp-activity-overview',
258
  'title' => __( 'Overview', 'buddypress' ),
261
  '<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>'
262
  ) );
263
 
264
+ // Help panel - moderation text
265
  get_current_screen()->add_help_tab( array(
266
  'id' => 'bp-activity-moderating',
267
  'title' => __( 'Moderating Activity', 'buddypress' ),
270
  '<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>'
271
  ) );
272
 
273
+ // Help panel - sidebar links
274
  get_current_screen()->set_help_sidebar(
275
  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
276
+ '<p>' . __( '<a href="http://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
277
  );
 
 
 
 
 
 
 
 
278
  }
279
 
280
+ // Enqueue CSS and JavaScript
281
+ 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 );
282
  wp_localize_script( 'bp_activity_admin_js', 'bp_activity_admin_vars', array(
283
+ 'page' => get_current_screen()->id
284
+ ) );
285
+ wp_enqueue_style( 'bp_activity_admin_css', $bp->plugin_url . "bp-activity/admin/css/admin.{$min}css", array(), bp_get_version() );
286
 
287
+ // Handle spam/un-spam/delete of activities
 
 
 
 
 
 
 
 
 
 
 
 
288
  if ( !empty( $doaction ) && ! in_array( $doaction, array( '-1', 'edit', 'save', ) ) ) {
289
 
290
+ // Build redirection URL
291
  $redirect_to = remove_query_arg( array( 'aid', 'deleted', 'error', 'spammed', 'unspammed', ), wp_get_referer() );
292
  $redirect_to = add_query_arg( 'paged', $bp_activity_list_table->get_pagenum(), $redirect_to );
293
 
294
+ // Get activity IDs
295
  $activity_ids = array_map( 'absint', (array) $_REQUEST['aid'] );
296
 
297
+ // Call a filter for plugins to modify the requested activities to load
 
 
 
 
 
 
298
  $activity_ids = apply_filters( 'bp_activity_admin_action_activity_ids', $activity_ids );
299
 
300
  // Is this a bulk request?
301
  if ( 'bulk_' == substr( $doaction, 0, 5 ) && ! empty( $_REQUEST['aid'] ) ) {
302
+ // Check this is a valid form submission
303
  check_admin_referer( 'bulk-activities' );
304
 
305
+ // Trim 'bulk_' off the action name to avoid duplicating a ton of code
306
  $doaction = substr( $doaction, 5 );
307
 
308
  // This is a request to delete, spam, or un-spam, a single item.
309
  } elseif ( !empty( $_REQUEST['aid'] ) ) {
310
 
311
+ // Check this is a valid form submission
312
  check_admin_referer( 'spam-activity_' . $activity_ids[0] );
313
  }
314
 
315
+ // Initialise counters for how many of each type of item we perform an action on
316
  $deleted = $spammed = $unspammed = 0;
317
 
318
+ // Store any errors that occurs when updating the database items
319
  $errors = array();
320
 
321
  // "We'd like to shoot the monster, could you move, please?"
322
  foreach ( $activity_ids as $activity_id ) {
323
  // @todo: Check the permissions on each
324
+ //if ( ! current_user_can( 'bp_edit_activity', $activity_id ) )
325
+ // continue;
326
+
327
+ // Get the activity from the database
328
  $activity = new BP_Activity_Activity( $activity_id );
329
  if ( empty( $activity->component ) ) {
330
  $errors[] = $activity_id;
346
  * Remove moderation and blacklist checks in case we want to ham an activity
347
  * which contains one of these listed keys.
348
  */
349
+ remove_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2, 1 );
350
+ remove_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2, 1 );
351
 
352
  bp_activity_mark_as_ham( $activity );
353
  $result = $activity->save();
354
 
355
+ // Check for any error during activity save
356
  if ( ! $result )
357
  $errors[] = $activity->id;
358
  else
363
  bp_activity_mark_as_spam( $activity );
364
  $result = $activity->save();
365
 
366
+ // Check for any error during activity save
367
  if ( ! $result )
368
  $errors[] = $activity->id;
369
  else
374
  break;
375
  }
376
 
377
+ // Release memory
378
  unset( $activity );
379
  }
380
 
381
+ // Call actions for plugins to do something before we redirect
 
 
 
 
 
 
 
 
 
 
382
  do_action( 'bp_activity_admin_action_after', array( $spammed, $unspammed, $deleted, $errors ), $redirect_to, $activity_ids );
383
 
384
  // Add arguments to the redirect URL so that on page reload, we can easily display what we've just done.
391
  if ( $deleted )
392
  $redirect_to = add_query_arg( 'deleted', $deleted, $redirect_to );
393
 
394
+ // If an error occurred, pass back the activity ID that failed
395
  if ( ! empty( $errors ) )
396
  $redirect_to = add_query_arg( 'error', implode ( ',', array_map( 'absint', $errors ) ), $redirect_to );
397
 
398
+ // Redirect
 
 
 
 
 
 
399
  wp_redirect( apply_filters( 'bp_activity_admin_action_redirect', $redirect_to ) );
400
  exit;
401
 
402
 
403
+ // Save the edit
404
  } elseif ( $doaction && 'save' == $doaction ) {
405
+ // Build redirection URL
406
  $redirect_to = remove_query_arg( array( 'action', 'aid', 'deleted', 'error', 'spammed', 'unspammed', ), $_SERVER['REQUEST_URI'] );
407
 
408
+ // Get activity ID
409
  $activity_id = (int) $_REQUEST['aid'];
410
 
411
+ // Check this is a valid form submission
412
  check_admin_referer( 'edit-activity_' . $activity_id );
413
 
414
+ // Get the activity from the database
415
  $activity = new BP_Activity_Activity( $activity_id );
416
 
417
+ // If the activity doesn't exist, just redirect back to the index
418
  if ( empty( $activity->component ) ) {
419
  wp_redirect( $redirect_to );
420
  exit;
421
  }
422
 
423
+ // Check the form for the updated properties
424
+
425
+ // Store any error that occurs when updating the database item
426
  $error = 0;
427
 
428
+ // Activity spam status
429
  $prev_spam_status = $new_spam_status = false;
430
  if ( ! empty( $_POST['activity_status'] ) ) {
431
  $prev_spam_status = $activity->is_spam;
432
  $new_spam_status = ( 'spam' == $_POST['activity_status'] ) ? true : false;
433
  }
434
 
435
+ // Activity action
436
  if ( isset( $_POST['bp-activities-action'] ) )
437
  $activity->action = $_POST['bp-activities-action'];
438
 
439
+ // Activity content
440
  if ( isset( $_POST['bp-activities-content'] ) )
441
  $activity->content = $_POST['bp-activities-content'];
442
 
443
+ // Activity primary link
444
  if ( ! empty( $_POST['bp-activities-link'] ) )
445
  $activity->primary_link = $_POST['bp-activities-link'];
446
 
447
+ // Activity user ID
448
  if ( ! empty( $_POST['bp-activities-userid'] ) )
449
  $activity->user_id = (int) $_POST['bp-activities-userid'];
450
 
451
+ // Activity item primary ID
452
  if ( isset( $_POST['bp-activities-primaryid'] ) )
453
  $activity->item_id = (int) $_POST['bp-activities-primaryid'];
454
 
455
+ // Activity item secondary ID
456
  if ( isset( $_POST['bp-activities-secondaryid'] ) )
457
  $activity->secondary_item_id = (int) $_POST['bp-activities-secondaryid'];
458
 
459
+ // Activity type
460
  if ( ! empty( $_POST['bp-activities-type'] ) ) {
461
  $actions = bp_activity_admin_get_activity_actions();
462
 
463
+ // Check that the new type is a registered activity type
464
  if ( in_array( $_POST['bp-activities-type'], $actions ) ) {
465
  $activity->type = $_POST['bp-activities-type'];
466
  }
467
  }
468
 
469
+ // Activity timestamp
470
  if ( ! empty( $_POST['aa'] ) && ! empty( $_POST['mm'] ) && ! empty( $_POST['jj'] ) && ! empty( $_POST['hh'] ) && ! empty( $_POST['mn'] ) && ! empty( $_POST['ss'] ) ) {
471
  $aa = $_POST['aa'];
472
  $mm = $_POST['mm'];
482
  $mn = ( $mn > 59 ) ? $mn -60 : $mn;
483
  $ss = ( $ss > 59 ) ? $ss -60 : $ss;
484
 
485
+ // Reconstruct the date into a timestamp
486
  $gmt_date = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
487
 
488
  $activity->date_recorded = $gmt_date;
496
  bp_activity_mark_as_ham( $activity );
497
  }
498
 
499
+ // Save
500
  $result = $activity->save();
501
 
502
+ // Clear the activity stream first page cache, in case this activity's timestamp was changed
503
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
504
 
505
+ // Check for any error during activity save
506
  if ( false === $result )
507
  $error = $activity->id;
508
 
509
+ // Call actions for plugins to do something before we redirect
 
 
 
 
 
 
510
  do_action_ref_array( 'bp_activity_admin_edit_after', array( &$activity, $error ) );
511
 
512
+ // If an error occurred, pass back the activity ID that failed
513
  if ( $error )
514
+ $redirect_to = add_query_arg( 'error', (int) $error, $redirect_to );
515
  else
516
+ $redirect_to = add_query_arg( 'updated', (int) $activity->id, $redirect_to );
517
 
518
+ // Redirect
 
 
 
 
 
 
519
  wp_redirect( apply_filters( 'bp_activity_admin_edit_redirect', $redirect_to ) );
520
  exit;
521
 
530
  /**
531
  * Output the Activity component admin screens.
532
  *
533
+ * @since BuddyPress (1.6.0)
534
  */
535
  function bp_activity_admin() {
536
+ // Decide whether to load the index or edit screen
537
  $doaction = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
538
 
539
+ // Display the single activity edit screen
540
  if ( 'edit' == $doaction && ! empty( $_GET['aid'] ) )
541
  bp_activity_admin_edit();
542
 
543
+ // Otherwise, display the Activity index screen
544
  else
545
  bp_activity_admin_index();
546
  }
548
  /**
549
  * Display the single activity edit screen.
550
  *
551
+ * @since BuddyPress (1.6.0)
552
  */
553
  function bp_activity_admin_edit() {
554
 
557
  if ( ! is_super_admin() )
558
  die( '-1' );
559
 
560
+ // Get the activity from the database
561
  $activity = bp_activity_get( array(
562
  'in' => ! empty( $_REQUEST['aid'] ) ? (int) $_REQUEST['aid'] : 0,
563
  'max' => 1,
569
  if ( ! empty( $activity['activities'][0] ) ) {
570
  $activity = $activity['activities'][0];
571
 
572
+ // Workaround to use WP's touch_time() without duplicating that function
573
  $GLOBALS['comment'] = new stdClass;
574
  $GLOBALS['comment']->comment_date = $activity->date_recorded;
575
  } else {
576
  $activity = '';
577
  }
578
 
579
+ // Construct URL for form
580
  $form_url = remove_query_arg( array( 'action', 'deleted', 'error', 'spammed', 'unspammed', ), $_SERVER['REQUEST_URI'] );
581
  $form_url = add_query_arg( 'action', 'save', $form_url );
582
 
583
+ // Call an action for plugins to modify the activity before we display the edit form
 
 
 
 
 
 
584
  do_action_ref_array( 'bp_activity_admin_edit', array( &$activity ) ); ?>
585
 
586
  <div class="wrap">
587
+ <?php screen_icon( 'buddypress-activity' ); ?>
588
+ <h2><?php printf( __( 'Editing Activity (ID #%s)', 'buddypress' ), number_format_i18n( (int) $_REQUEST['aid'] ) ); ?></h2>
589
 
590
  <?php if ( ! empty( $activity ) ) : ?>
591
 
592
+ <form action="<?php echo esc_attr( $form_url ); ?>" id="bp-activities-edit-form" method="post">
593
  <div id="poststuff">
594
 
595
  <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
596
  <div id="post-body-content">
597
  <div id="postdiv">
598
  <div id="bp_activity_action" class="postbox">
599
+ <h3><?php _e( 'Action', 'buddypress' ); ?></h3>
600
  <div class="inside">
 
 
 
 
601
  <?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' ) ) ); ?>
602
  </div>
603
  </div>
604
 
605
  <div id="bp_activity_content" class="postbox">
606
+ <h3><?php _e( 'Content', 'buddypress' ); ?></h3>
607
  <div class="inside">
 
 
 
 
608
  <?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' ) ) ); ?>
609
  </div>
610
  </div>
628
  </form>
629
 
630
  <?php else : ?>
631
+ <p><?php printf( __( 'No activity found with this ID. <a href="%s">Go back and try again</a>.', 'buddypress' ), esc_url( bp_get_admin_url( 'admin.php?page=bp-activity' ) ) ); ?></p>
 
 
 
 
 
 
 
 
 
632
  <?php endif; ?>
633
 
634
  </div><!-- .wrap -->
639
  /**
640
  * Status metabox for the Activity admin edit screen.
641
  *
642
+ * @since BuddyPress (1.6.0)
643
  *
644
  * @param object $item Activity item.
645
  */
659
 
660
  <div id="misc-publishing-actions">
661
  <div class="misc-pub-section" id="comment-status-radio">
662
+ <label class="approved"><input type="radio" name="activity_status" value="ham" <?php checked( $item->is_spam, 0 ); ?>><?php _e( 'Approved', 'buddypress' ); ?></label><br />
663
+ <label class="spam"><input type="radio" name="activity_status" value="spam" <?php checked( $item->is_spam, 1 ); ?>><?php _e( 'Spam', 'buddypress' ); ?></label>
664
  </div>
665
 
666
  <div class="misc-pub-section curtime misc-pub-section-last">
667
  <?php
668
+ // translators: Publish box date format, see http://php.net/date
669
  $datef = __( 'M j, Y @ G:i', 'buddypress' );
670
  $date = date_i18n( $datef, strtotime( $item->date_recorded ) );
671
  ?>
672
+ <span id="timestamp"><?php printf( __( 'Submitted on: <strong>%1$s</strong>', 'buddypress' ), $date ); ?></span>&nbsp;<a href="#edit_timestamp" class="edit-timestamp hide-if-no-js" tabindex='4'><?php _e( 'Edit', 'buddypress' ); ?></a>
673
 
674
  <div id='timestampdiv' class='hide-if-js'>
675
  <?php touch_time( 1, 0, 5 ); ?>
682
 
683
  <div id="major-publishing-actions">
684
  <div id="publishing-action">
685
+ <?php submit_button( __( 'Update', 'buddypress' ), 'primary', 'save', false, array( 'tabindex' => '4' ) ); ?>
686
  </div>
687
  <div class="clear"></div>
688
  </div><!-- #major-publishing-actions -->
695
  /**
696
  * Primary link metabox for the Activity admin edit screen.
697
  *
698
+ * @since BuddyPress (1.6.0)
699
  *
700
  * @param object $item Activity item.
701
  */
702
  function bp_activity_admin_edit_metabox_link( $item ) {
703
  ?>
704
 
705
+ <label class="screen-reader-text" for="bp-activities-link"><?php _e( 'Link', 'buddypress' ); ?></label>
706
+ <input type="url" name="bp-activities-link" value="<?php echo esc_url( $item->primary_link ); ?>" />
707
+ <p><?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>
 
 
 
708
 
709
  <?php
710
  }
712
  /**
713
  * User ID metabox for the Activity admin edit screen.
714
  *
715
+ * @since BuddyPress (1.6.0)
716
  *
717
  * @param object $item Activity item.
718
  */
719
  function bp_activity_admin_edit_metabox_userid( $item ) {
720
  ?>
721
 
722
+ <label class="screen-reader-text" for="bp-activities-userid"><?php _e( 'Author ID', 'buddypress' ); ?></label>
723
+ <input type="number" name="bp-activities-userid" value="<?php echo esc_attr( $item->user_id ); ?>" min="1" />
 
 
 
724
 
725
  <?php
726
  }
730
  *
731
  * Format is [activity_type] => Pretty name for activity type.
732
  *
733
+ * @since BuddyPress (2.0.0)
734
  *
735
+ * @return array
736
  */
737
  function bp_activity_admin_get_activity_actions() {
738
  $actions = array();
739
 
740
  // Walk through the registered actions, and build an array of actions/values.
741
+ foreach ( buddypress()->activity->actions as $action ) {
742
  $action = array_values( (array) $action );
743
 
744
  for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ ) {
746
  }
747
  }
748
 
749
+ // This was a mis-named activity type from before BP 1.6
750
  unset( $actions['friends_register_activity_action'] );
751
 
752
+ // Sort array by the human-readable value
753
  natsort( $actions );
754
 
755
  return $actions;
756
  }
757
 
758
  /**
759
+ * Activity type metabox for the Activity admin edit screen
760
+ *
761
+ * @since BuddyPress (1.6.0)
762
  *
763
+ * @global object $bp BuddyPress global settings.
764
  *
765
  * @param object $item Activity item.
766
  */
767
  function bp_activity_admin_edit_metabox_type( $item ) {
768
+ global $bp;
769
 
770
  $actions = array();
771
  $selected = $item->type;
772
 
773
  // Walk through the registered actions, and build an array of actions/values.
774
+ foreach ( $bp->activity->actions as $action ) {
775
  $action = array_values( (array) $action );
776
 
777
  for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ )
778
  $actions[ $action[$i]['key'] ] = $action[$i]['value'];
779
  }
780
 
781
+ // This was a mis-named activity type from before BP 1.6
782
  unset( $actions['friends_register_activity_action'] );
783
 
784
+ // Sort array by the human-readable value
785
  natsort( $actions );
786
 
787
+ // If the activity type is not registered properly (eg, a plugin has
788
+ // not called bp_activity_set_action()), add the raw type to the end
789
+ // of the list
 
 
790
  if ( ! isset( $actions[ $selected ] ) ) {
791
  _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' );
792
  $actions[ $selected ] = $selected;
794
 
795
  ?>
796
 
797
+ <select name="bp-activities-type">
 
 
 
 
798
  <?php foreach ( $actions as $k => $v ) : ?>
799
  <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $k, $selected ); ?>><?php echo esc_html( $v ); ?></option>
800
  <?php endforeach; ?>
806
  /**
807
  * Primary item ID/Secondary item ID metabox for the Activity admin edit screen.
808
  *
809
+ * @since BuddyPress (1.6.0)
810
  *
811
  * @param object $item Activity item.
812
  */
828
  /**
829
  * Display the Activity admin index screen, which contains a list of all the activities.
830
  *
831
+ * @since BuddyPress (1.6.0)
832
  *
833
+ * @global BP_Activity_List_Table $bp_activity_list_table Activity screen list
834
+ * table.
835
+ * @global string $plugin_page The current plugin page.
836
  */
837
  function bp_activity_admin_index() {
838
  global $bp_activity_list_table, $plugin_page;
839
 
840
  $messages = array();
841
 
842
+ // If the user has just made a change to an activity item, build status messages
843
  if ( ! empty( $_REQUEST['deleted'] ) || ! empty( $_REQUEST['spammed'] ) || ! empty( $_REQUEST['unspammed'] ) || ! empty( $_REQUEST['error'] ) || ! empty( $_REQUEST['updated'] ) ) {
844
  $deleted = ! empty( $_REQUEST['deleted'] ) ? (int) $_REQUEST['deleted'] : 0;
845
  $errors = ! empty( $_REQUEST['error'] ) ? $_REQUEST['error'] : '';
849
 
850
  $errors = array_map( 'absint', explode( ',', $errors ) );
851
 
852
+ // Make sure we don't get any empty values in $errors
853
  for ( $i = 0, $errors_count = count( $errors ); $i < $errors_count; $i++ ) {
854
  if ( 0 === $errors[$i] ) {
855
  unset( $errors[$i] );
856
  }
857
  }
858
 
859
+ // Reindex array
860
  $errors = array_values( $errors );
861
 
862
  if ( $deleted > 0 )
870
  $error_msg = __( 'Errors occurred when trying to update these activity items:', 'buddypress' );
871
  $error_msg .= '<ul class="activity-errors">';
872
 
873
+ // Display each error as a list item
874
  foreach ( $errors as $error ) {
875
+ // Translators: This is a bulleted list of item IDs
876
  $error_msg .= '<li>' . sprintf( __( '#%s', 'buddypress' ), number_format_i18n( $error ) ) . '</li>';
877
  }
878
 
888
  $messages[] = sprintf( _n( '%s activity item has been successfully unspammed.', '%s activity items have been successfully unspammed.', $unspammed, 'buddypress' ), number_format_i18n( $unspammed ) );
889
 
890
  if ( $updated > 0 )
891
+ $messages[] = __( 'The activity item has been updated succesfully.', 'buddypress' );
892
  }
893
 
894
+ // Prepare the activity items for display
895
  $bp_activity_list_table->prepare_items();
896
 
897
+ // Call an action for plugins to modify the activity before we display the edit form
 
 
 
 
 
 
898
  do_action( 'bp_activity_admin_index', $messages ); ?>
899
 
900
  <div class="wrap">
901
+ <?php screen_icon( 'buddypress-activity' ); ?>
902
+ <h2>
903
  <?php if ( !empty( $_REQUEST['aid'] ) ) : ?>
904
  <?php printf( __( 'Activity related to ID #%s', 'buddypress' ), number_format_i18n( (int) $_REQUEST['aid'] ) ); ?>
905
  <?php else : ?>
906
+ <?php _e( 'Activity', 'buddypress' ); ?>
907
  <?php endif; ?>
908
 
909
  <?php if ( !empty( $_REQUEST['s'] ) ) : ?>
910
  <span class="subtitle"><?php printf( __( 'Search results for &#8220;%s&#8221;', 'buddypress' ), wp_html_excerpt( esc_html( stripslashes( $_REQUEST['s'] ) ), 50 ) ); ?></span>
911
  <?php endif; ?>
912
+ </h2>
913
 
914
+ <?php // If the user has just made a change to an activity item, display the status messages ?>
915
  <?php if ( !empty( $messages ) ) : ?>
916
  <div id="moderated" class="<?php echo ( ! empty( $_REQUEST['error'] ) ) ? 'error' : 'updated'; ?>"><p><?php echo implode( "<br/>\n", $messages ); ?></p></div>
917
  <?php endif; ?>
918
 
919
+ <?php // Display each activity on its own row ?>
920
  <?php $bp_activity_list_table->views(); ?>
921
 
922
  <form id="bp-activities-form" action="" method="get">
925
  <?php $bp_activity_list_table->display(); ?>
926
  </form>
927
 
928
+ <?php // This markup is used for the reply form ?>
929
  <table style="display: none;">
930
  <tr id="bp-activities-container" style="display: none;">
931
  <td colspan="4">
932
  <form method="get" action="">
933
 
934
+ <h5 id="bp-replyhead"><?php _e( 'Reply to Activity', 'buddypress' ); ?></h5>
 
 
 
 
935
  <?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, ) ); ?>
936
 
937
  <p id="bp-replysubmit" class="submit">
938
  <a href="#" class="cancel button-secondary alignleft"><?php _e( 'Cancel', 'buddypress' ); ?></a>
939
  <a href="#" class="save button-primary alignright"><?php _e( 'Reply', 'buddypress' ); ?></a>
940
 
941
+ <img class="waiting" style="display:none;" src="<?php echo esc_url( bp_get_admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
942
  <span class="error" style="display:none;"></span>
943
  <br class="clear" />
944
  </p>
953
 
954
  <?php
955
  }
956
+
957
+ /**
958
+ * List table class for the Activity component admin page.
959
+ *
960
+ * @since BuddyPress (1.6)
961
+ */
962
+ class BP_Activity_List_Table extends WP_List_Table {
963
+
964
+ /**
965
+ * What type of view is being displayed?
966
+ *
967
+ * e.g. "all", "pending", "approved", "spam"...
968
+ *
969
+ * @since BuddyPress (1.6.0)
970
+ * @var string
971
+ */
972
+ public $view = 'all';
973
+
974
+ /**
975
+ * How many activity items have been marked as spam.
976
+ *
977
+ * @since BuddyPress (1.6.0)
978
+ * @var int
979
+ */
980
+ public $spam_count = 0;
981
+
982
+ /**
983
+ * Store activity-to-user-ID mappings for use in the In Response To column.
984
+ *
985
+ * @since BuddyPress (1.6.0)
986
+ * @var array
987
+ */
988
+ protected $activity_user_id = array();
989
+
990
+ /**
991
+ * Constructor.
992
+ *
993
+ * @since BuddyPress (1.6.0)
994
+ */
995
+ public function __construct() {
996
+
997
+ // See if activity commenting is enabled for blog / forum activity items
998
+ $this->disable_blogforum_comments = bp_disable_blogforum_comments();
999
+
1000
+ // Define singular and plural labels, as well as whether we support AJAX.
1001
+ parent::__construct( array(
1002
+ 'ajax' => false,
1003
+ 'plural' => 'activities',
1004
+ 'singular' => 'activity',
1005
+ 'screen' => get_current_screen(),
1006
+ ) );
1007
+ }
1008
+
1009
+ /**
1010
+ * Handle filtering of data, sorting, pagination, and any other data manipulation prior to rendering.
1011
+ *
1012
+ * @since BuddyPress (1.6.0)
1013
+ */
1014
+ function prepare_items() {
1015
+
1016
+ // Option defaults
1017
+ $filter = array();
1018
+ $include_id = false;
1019
+ $search_terms = false;
1020
+ $sort = 'DESC';
1021
+ $spam = 'ham_only';
1022
+
1023
+ // Set current page
1024
+ $page = $this->get_pagenum();
1025
+
1026
+ // Set per page from the screen options
1027
+ $per_page = $this->get_items_per_page( str_replace( '-', '_', "{$this->screen->id}_per_page" ) );
1028
+
1029
+ // Check if we're on the "Spam" view
1030
+ if ( !empty( $_REQUEST['activity_status'] ) && 'spam' == $_REQUEST['activity_status'] ) {
1031
+ $spam = 'spam_only';
1032
+ $this->view = 'spam';
1033
+ }
1034
+
1035
+ // Sort order
1036
+ if ( !empty( $_REQUEST['order'] ) && 'desc' != $_REQUEST['order'] )
1037
+ $sort = 'ASC';
1038
+
1039
+ // Order by
1040
+ /*if ( !empty( $_REQUEST['orderby'] ) ) {
1041
+ }*/
1042
+
1043
+ // Filter
1044
+ if ( !empty( $_REQUEST['activity_type'] ) )
1045
+ $filter = array( 'action' => $_REQUEST['activity_type'] );
1046
+
1047
+ // Are we doing a search?
1048
+ if ( !empty( $_REQUEST['s'] ) )
1049
+ $search_terms = $_REQUEST['s'];
1050
+
1051
+ // Check if user has clicked on a specific activity (if so, fetch only that, and any related, activity).
1052
+ if ( !empty( $_REQUEST['aid'] ) )
1053
+ $include_id = (int) $_REQUEST['aid'];
1054
+
1055
+ // Get the spam total (ignoring any search query or filter)
1056
+ $spams = bp_activity_get( array(
1057
+ 'display_comments' => 'stream',
1058
+ 'show_hidden' => true,
1059
+ 'spam' => 'spam_only',
1060
+ ) );
1061
+ $this->spam_count = $spams['total'];
1062
+ unset( $spams );
1063
+
1064
+ // Get the activities from the database
1065
+ $activities = bp_activity_get( array(
1066
+ 'display_comments' => 'stream',
1067
+ 'filter' => $filter,
1068
+ 'in' => $include_id,
1069
+ 'page' => $page,
1070
+ 'per_page' => $per_page,
1071
+ 'search_terms' => $search_terms,
1072
+ 'show_hidden' => true,
1073
+ //'sort' => $sort,
1074
+ 'spam' => $spam,
1075
+ ) );
1076
+
1077
+ // If we're viewing a specific activity, flatten all activites into a single array.
1078
+ if ( $include_id ) {
1079
+ $activities['activities'] = BP_Activity_List_Table::flatten_activity_array( $activities['activities'] );
1080
+ $activities['total'] = count( $activities['activities'] );
1081
+
1082
+ // Sort the array by the activity object's date_recorded value
1083
+ usort( $activities['activities'], create_function( '$a, $b', 'return $a->date_recorded > $b->date_recorded;' ) );
1084
+ }
1085
+
1086
+ // bp_activity_get returns an array of objects; cast these to arrays for WP_List_Table.
1087
+ $new_activities = array();
1088
+ foreach ( $activities['activities'] as $activity_item ) {
1089
+ $new_activities[] = (array) $activity_item;
1090
+
1091
+ // Build an array of activity-to-user ID mappings for better efficency in the In Response To column
1092
+ $this->activity_user_id[$activity_item->id] = $activity_item->user_id;
1093
+ }
1094
+
1095
+ // Set raw data to display
1096
+ $this->items = $new_activities;
1097
+
1098
+ // Store information needed for handling table pagination
1099
+ $this->set_pagination_args( array(
1100
+ 'per_page' => $per_page,
1101
+ 'total_items' => $activities['total'],
1102
+ 'total_pages' => ceil( $activities['total'] / $per_page )
1103
+ ) );
1104
+
1105
+ // Don't truncate activity items; bp_activity_truncate_entry() needs to be used inside a BP_Activity_Template loop.
1106
+ remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
1107
+ }
1108
+
1109
+ /**
1110
+ * Get an array of all the columns on the page.
1111
+ *
1112
+ * @since BuddyPress (1.6.0)
1113
+ *
1114
+ * @return array Column headers.
1115
+ */
1116
+ function get_column_info() {
1117
+ $this->_column_headers = array(
1118
+ $this->get_columns(),
1119
+ array(),
1120
+ $this->get_sortable_columns(),
1121
+ );
1122
+
1123
+ return $this->_column_headers;
1124
+ }
1125
+
1126
+ /**
1127
+ * Display a message on screen when no items are found (e.g. no search matches).
1128
+ *
1129
+ * @since BuddyPress (1.6.0)
1130
+ */
1131
+ function no_items() {
1132
+ _e( 'No activities found.', 'buddypress' );
1133
+ }
1134
+
1135
+ /**
1136
+ * Output the Activity data table.
1137
+ *
1138
+ * @since BuddyPress (1.6.0)
1139
+ */
1140
+ function display() {
1141
+ extract( $this->_args );
1142
+
1143
+ $this->display_tablenav( 'top' ); ?>
1144
+
1145
+ <table class="<?php echo implode( ' ', $this->get_table_classes() ); ?>" cellspacing="0">
1146
+ <thead>
1147
+ <tr>
1148
+ <?php $this->print_column_headers(); ?>
1149
+ </tr>
1150
+ </thead>
1151
+
1152
+ <tfoot>
1153
+ <tr>
1154
+ <?php $this->print_column_headers( false ); ?>
1155
+ </tr>
1156
+ </tfoot>
1157
+
1158
+ <tbody id="the-comment-list">
1159
+ <?php $this->display_rows_or_placeholder(); ?>
1160
+ </tbody>
1161
+ </table>
1162
+ <?php
1163
+
1164
+ $this->display_tablenav( 'bottom' );
1165
+ }
1166
+
1167
+ /**
1168
+ * Generate content for a single row of the table.
1169
+ *
1170
+ * @since BuddyPress (1.6.0)
1171
+ *
1172
+ * @param object $item The current item.
1173
+ */
1174
+ function single_row( $item ) {
1175
+ static $even = false;
1176
+
1177
+ if ( $even ) {
1178
+ $row_class = ' class="even"';
1179
+ } else {
1180
+ $row_class = ' class="alternate odd"';
1181
+ }
1182
+
1183
+ if ( 'activity_comment' === $item['type'] ) {
1184
+ $root_id = $item['item_id'];
1185
+ } else {
1186
+ $root_id = $item['id'];
1187
+ }
1188
+
1189
+ echo '<tr' . $row_class . ' id="activity-' . esc_attr( $item['id'] ) . '" data-parent_id="' . esc_attr( $item['id'] ) . '" data-root_id="' . esc_attr( $root_id ) . '">';
1190
+ echo $this->single_row_columns( $item );
1191
+ echo '</tr>';
1192
+
1193
+ $even = ! $even;
1194
+ }
1195
+
1196
+ /**
1197
+ * Get the list of views available on this table (e.g. "all", "spam").
1198
+ *
1199
+ * @since BuddyPress (1.6.0)
1200
+ */
1201
+ function get_views() {
1202
+ $url_base = bp_get_admin_url( 'admin.php?page=bp-activity' ); ?>
1203
+
1204
+ <ul class="subsubsub">
1205
+ <li class="all"><a href="<?php echo esc_attr( esc_url( $url_base ) ); ?>" class="<?php if ( 'spam' != $this->view ) echo 'current'; ?>"><?php _e( 'All', 'buddypress' ); ?></a> |</li>
1206
+ <li class="spam"><a href="<?php echo esc_attr( esc_url( add_query_arg( '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>
1207
+
1208
+ <?php do_action( 'bp_activity_list_table_get_views', $url_base, $this->view ); ?>
1209
+ </ul>
1210
+ <?php
1211
+ }
1212
+
1213
+ /**
1214
+ * Get bulk actions.
1215
+ *
1216
+ * @since BuddyPress (1.6.0)
1217
+ *
1218
+ * @return array Key/value pairs for the bulk actions dropdown.
1219
+ */
1220
+ function get_bulk_actions() {
1221
+ $actions = array();
1222
+ $actions['bulk_spam'] = __( 'Mark as Spam', 'buddypress' );
1223
+ $actions['bulk_ham'] = __( 'Not Spam', 'buddypress' );
1224
+ $actions['bulk_delete'] = __( 'Delete Permanently', 'buddypress' );
1225
+
1226
+ return apply_filters( 'bp_activity_list_table_get_bulk_actions', $actions );
1227
+ }
1228
+
1229
+ /**
1230
+ * Get the table column titles.
1231
+ *
1232
+ * @since BuddyPress (1.6.0)
1233
+ *
1234
+ * @see WP_List_Table::single_row_columns()
1235
+ *
1236
+ * @return array The columns to appear in the Activity list table.
1237
+ */
1238
+ function get_columns() {
1239
+ return array(
1240
+ 'cb' => '<input name type="checkbox" />',
1241
+ 'author' => __( 'Author', 'buddypress' ),
1242
+ 'comment' => __( 'Activity', 'buddypress' ),
1243
+ 'action' => __( 'Action', 'buddypress' ),
1244
+ 'response' => __( 'In Response To', 'buddypress' ),
1245
+ );
1246
+ }
1247
+
1248
+ /**
1249
+ * Get the column names for sortable columns.
1250
+ *
1251
+ * Currently, returns an empty array (no columns are sortable).
1252
+ *
1253
+ * @since BuddyPress (1.6.0)
1254
+ * @todo For this to work, BP_Activity_Activity::get() needs updating
1255
+ * to support ordering by specific fields.
1256
+ *
1257
+ * @return array The columns that can be sorted on the Activity screen.
1258
+ */
1259
+ function get_sortable_columns() {
1260
+ return array();
1261
+
1262
+ /*return array(
1263
+ 'author' => array( 'activity_author', false ), // Intentionally not using "=>"
1264
+ );*/
1265
+ }
1266
+
1267
+ /**
1268
+ * Markup for the "filter" part of the form (i.e. which activity type to display).
1269
+ *
1270
+ * @since BuddyPress (1.6.0)
1271
+ *
1272
+ * @param string $which 'top' or 'bottom'.
1273
+ */
1274
+ function extra_tablenav( $which ) {
1275
+ if ( 'bottom' == $which )
1276
+ return;
1277
+
1278
+ $selected = !empty( $_REQUEST['activity_type'] ) ? $_REQUEST['activity_type'] : '';
1279
+
1280
+ // Get all types of activities, and sort alphabetically.
1281
+ $actions = bp_activity_get_types();
1282
+ natsort( $actions );
1283
+ ?>
1284
+
1285
+ <div class="alignleft actions">
1286
+ <select name="activity_type">
1287
+ <option value="" <?php selected( !$selected ); ?>><?php _e( 'Show all activity types', 'buddypress' ); ?></option>
1288
+
1289
+ <?php foreach ( $actions as $k => $v ) : ?>
1290
+ <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $k, $selected ); ?>><?php echo esc_html( $v ); ?></option>
1291
+ <?php endforeach; ?>
1292
+ </select>
1293
+
1294
+ <?php submit_button( __( 'Filter', 'buddypress' ), 'secondary', false, false, array( 'id' => 'post-query-submit' ) ); ?>
1295
+ </div>
1296
+
1297
+ <?php
1298
+ }
1299
+
1300
+ /**
1301
+ * Checkbox column markup.
1302
+ *
1303
+ * @since BuddyPress (1.6.0)
1304
+ *
1305
+ * @see WP_List_Table::single_row_columns()
1306
+ *
1307
+ * @param array $item A singular item (one full row).
1308
+ */
1309
+ function column_cb( $item ) {
1310
+ 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'] );
1311
+ }
1312
+
1313
+ /**
1314
+ * Author column markup.
1315
+ *
1316
+ * @since BuddyPress (1.6.0)
1317
+ *
1318
+ * @see WP_List_Table::single_row_columns()
1319
+ *
1320
+ * @param array $item A singular item (one full row).
1321
+ */
1322
+ function column_author( $item ) {
1323
+ echo '<strong>' . get_avatar( $item['user_id'], '32' ) . ' ' . bp_core_get_userlink( $item['user_id'] ) . '</strong>';
1324
+ }
1325
+
1326
+ /**
1327
+ * Action column markup.
1328
+ *
1329
+ * @since BuddyPress (2.0.0)
1330
+ *
1331
+ * @see WP_List_Table::single_row_columns()
1332
+ *
1333
+ * @param array $item A singular item (one full row).
1334
+ */
1335
+ function column_action( $item ) {
1336
+ $actions = bp_activity_admin_get_activity_actions();
1337
+
1338
+ if ( isset( $actions[ $item['type'] ] ) ) {
1339
+ echo $actions[ $item['type'] ];
1340
+ } else {
1341
+ printf( __( 'Unregistered action - %s', 'buddypress' ), $item['type'] );
1342
+ }
1343
+ }
1344
+
1345
+ /**
1346
+ * Content column, and "quick admin" rollover actions.
1347
+ *
1348
+ * Called "comment" in the CSS so we can re-use some WP core CSS.
1349
+ *
1350
+ * @since BuddyPress (1.6.0)
1351
+ *
1352
+ * @see WP_List_Table::single_row_columns()
1353
+ *
1354
+ * @param array $item A singular item (one full row).
1355
+ */
1356
+ function column_comment( $item ) {
1357
+ // Determine what type of item (row) we're dealing with
1358
+ if ( $item['is_spam'] )
1359
+ $item_status = 'spam';
1360
+ else
1361
+ $item_status = 'all';
1362
+
1363
+ // Preorder items: Reply | Edit | Spam | Delete Permanently
1364
+ $actions = array(
1365
+ 'reply' => '',
1366
+ 'edit' => '',
1367
+ 'spam' => '', 'unspam' => '',
1368
+ 'delete' => '',
1369
+ );
1370
+
1371
+ // Build actions URLs
1372
+ $base_url = bp_get_admin_url( 'admin.php?page=bp-activity&amp;aid=' . $item['id'] );
1373
+ $spam_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'spam-activity_' . $item['id'] ) );
1374
+
1375
+ $delete_url = $base_url . "&amp;action=delete&amp;$spam_nonce";
1376
+ $edit_url = $base_url . '&amp;action=edit';
1377
+ $ham_url = $base_url . "&amp;action=ham&amp;$spam_nonce";
1378
+ $spam_url = $base_url . "&amp;action=spam&amp;$spam_nonce";
1379
+
1380
+ // Rollover actions
1381
+
1382
+ // Reply - javascript only; implemented by AJAX.
1383
+ if ( 'spam' != $item_status ) {
1384
+ if ( $this->can_comment( $item ) ) {
1385
+ $actions['reply'] = sprintf( '<a href="#" class="reply hide-if-no-js">%s</a>', __( 'Reply', 'buddypress' ) );
1386
+ } else {
1387
+ $actions['reply'] = sprintf( '<span class="form-input-tip" title="%s">%s</span>', __( 'Replies are disabled for this activity item', 'buddypress' ), __( 'Replies disabled', 'buddypress' ) );
1388
+ }
1389
+
1390
+ // Edit
1391
+ $actions['edit'] = sprintf( '<a href="%s">%s</a>', $edit_url, __( 'Edit', 'buddypress' ) );
1392
+ }
1393
+
1394
+ // Spam/unspam
1395
+ if ( 'spam' == $item_status )
1396
+ $actions['unspam'] = sprintf( '<a href="%s">%s</a>', $ham_url, __( 'Not Spam', 'buddypress' ) );
1397
+ else
1398
+ $actions['spam'] = sprintf( '<a href="%s">%s</a>', $spam_url, __( 'Spam', 'buddypress' ) );
1399
+
1400
+ // Delete
1401
+ $actions['delete'] = sprintf( '<a href="%s" onclick="%s">%s</a>', $delete_url, "javascript:return confirm('" . esc_js( __( 'Are you sure?', 'buddypress' ) ) . "'); ", __( 'Delete Permanently', 'buddypress' ) );
1402
+
1403
+ // Start timestamp
1404
+ echo '<div class="submitted-on">';
1405
+
1406
+ // Other plugins can filter which actions are shown
1407
+ $actions = apply_filters( 'bp_activity_admin_comment_row_actions', array_filter( $actions ), $item );
1408
+
1409
+ /* translators: 2: activity admin ui date/time */
1410
+ printf( __( 'Submitted on <a href="%1$s">%2$s at %3$s</a>', 'buddypress' ), bp_activity_get_permalink( $item['id'] ), get_date_from_gmt( $item['date_recorded'], get_option( 'date_format' ) ), get_date_from_gmt( $item['date_recorded'], get_option( 'time_format' ) ) );
1411
+
1412
+ // End timestamp
1413
+ echo '</div>';
1414
+
1415
+ // Get activity content - if not set, use the action
1416
+ if ( ! empty( $item['content'] ) ) {
1417
+ $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $item['content'] ) );
1418
+ } else {
1419
+ $content = apply_filters_ref_array( 'bp_get_activity_action', array( $item['action'] ) );
1420
+ }
1421
+
1422
+ echo $content . ' ' . $this->row_actions( $actions );
1423
+ }
1424
+
1425
+ /**
1426
+ * "In response to" column markup.
1427
+ *
1428
+ * @since BuddyPress (1.6.0)
1429
+ *
1430
+ * @see WP_List_Table::single_row_columns()
1431
+ *
1432
+ * @param array $item A singular item (one full row).
1433
+ */
1434
+ function column_response( $item ) {
1435
+ // Is $item is a root activity?
1436
+ if ( empty( $item['item_id'] ) || ! in_array( $item['type'], apply_filters( 'bp_activity_admin_root_activity_types', array( 'activity_comment' ), $item ) ) ) {
1437
+ $comment_count = !empty( $item['children'] ) ? bp_activity_recurse_comment_count( (object) $item ) : 0;
1438
+ $root_activity_url = bp_get_admin_url( 'admin.php?page=bp-activity&amp;aid=' . $item['id'] );
1439
+
1440
+ // If the activity has comments, display a link to the activity's permalink, with its comment count in a speech bubble
1441
+ if ( $comment_count ) {
1442
+ $title_attr = sprintf( _n( '%s related activity', '%s related activities', $comment_count, 'buddypress' ), number_format_i18n( $comment_count ) );
1443
+ printf( '<a href="%1$s" title="%2$s" class="post-com-count"><span class="comment-count">%3$s</span></a>', esc_url( $root_activity_url ), esc_attr( $title_attr ), number_format_i18n( $comment_count ) );
1444
+ }
1445
+
1446
+ // For non-root activities, display a link to the replied-to activity's author's profile
1447
+ } else {
1448
+ 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 />';
1449
+ }
1450
+
1451
+ // Activity permalink
1452
+ if ( ! $item['is_spam'] )
1453
+ printf( __( '<a href="%1$s">View Activity</a>', 'buddypress' ), bp_activity_get_permalink( $item['id'], (object) $item ) );
1454
+ }
1455
+
1456
+ /**
1457
+ * Get the user id associated with a given activity item.
1458
+ *
1459
+ * Wraps bp_activity_get_specific(), with some additional logic for
1460
+ * avoiding duplicate queries.
1461
+ *
1462
+ * @since BuddyPress (1.6.0)
1463
+ *
1464
+ * @param int $activity_id Activity ID to retrieve User ID for.
1465
+ * @return int User ID of the activity item in question.
1466
+ */
1467
+ protected function get_activity_user_id( $activity_id ) {
1468
+ // If there is an existing activity/user ID mapping, just return the user ID.
1469
+ if ( ! empty( $this->activity_user_id[$activity_id] ) ) {
1470
+ return $this->activity_user_id[$activity_id];
1471
+
1472
+ /**
1473
+ * We don't have a mapping. This means the $activity_id is not on the current
1474
+ * page of results, so fetch its details from the database.
1475
+ */
1476
+ } else {
1477
+ $activity = bp_activity_get_specific( array( 'activity_ids' => $activity_id, 'show_hidden' => true, 'spam' => 'all', ) );
1478
+
1479
+ /**
1480
+ * If, somehow, the referenced activity has been deleted, leaving its associated
1481
+ * activites as orphans, use the logged in user's ID to avoid errors.
1482
+ */
1483
+ if ( empty( $activity['activities'] ) )
1484
+ return bp_loggedin_user_id();
1485
+
1486
+ // Store the new activity/user ID mapping for any later re-use
1487
+ $this->activity_user_id[ $activity['activities'][0]->id ] = $activity['activities'][0]->user_id;
1488
+
1489
+ // Return the user ID
1490
+ return $activity['activities'][0]->user_id;
1491
+ }
1492
+ }
1493
+
1494
+ /**
1495
+ * Checks if an activity item can be replied to.
1496
+ *
1497
+ * This method merges functionality from {@link bp_activity_can_comment()} and
1498
+ * {@link bp_blogs_disable_activity_commenting()}. This is done because the activity
1499
+ * list table doesn't use a BuddyPress activity loop, which prevents those
1500
+ * functions from working as intended.
1501
+ *
1502
+ * @since BuddyPress (2.0.0)
1503
+ *
1504
+ * @param array $item An array version of the BP_Activity_Activity object.
1505
+ * @return bool
1506
+ */
1507
+ protected function can_comment( $item ) {
1508
+ $can_comment = true;
1509
+
1510
+ if ( $this->disable_blogforum_comments ) {
1511
+ switch ( $item['type'] ) {
1512
+ case 'new_blog_post' :
1513
+ case 'new_blog_comment' :
1514
+ case 'new_forum_topic' :
1515
+ case 'new_forum_post' :
1516
+ $can_comment = false;
1517
+ break;
1518
+ }
1519
+
1520
+ // activity comments supported
1521
+ } else {
1522
+ // activity comment
1523
+ if ( 'activity_comment' == $item['type'] ) {
1524
+ // blogs
1525
+ if ( bp_is_active( 'blogs' ) ) {
1526
+ // grab the parent activity entry
1527
+ $parent_activity = new BP_Activity_Activity( $item['item_id'] );
1528
+
1529
+ // fetch blog post comment depth and if the blog post's comments are open
1530
+ bp_blogs_setup_activity_loop_globals( $parent_activity );
1531
+
1532
+ // check if the activity item can be replied to
1533
+ if ( false === bp_blogs_can_comment_reply( true, $item ) ) {
1534
+ $can_comment = false;
1535
+ }
1536
+ }
1537
+
1538
+ // blog post
1539
+ } elseif ( 'new_blog_post' == $item['type'] ) {
1540
+ if ( bp_is_active( 'blogs' ) ) {
1541
+ bp_blogs_setup_activity_loop_globals( (object) $item );
1542
+
1543
+ if ( empty( buddypress()->blogs->allow_comments[$item['id']] ) ) {
1544
+ $can_comment = false;
1545
+ }
1546
+ }
1547
+ }
1548
+ }
1549
+
1550
+ return apply_filters( 'bp_activity_list_table_can_comment', $can_comment );
1551
+ }
1552
+
1553
+ /**
1554
+ * Flatten the activity array.
1555
+ *
1556
+ * In some cases, BuddyPress gives us a structured tree of activity
1557
+ * items plus their comments. This method converts it to a flat array.
1558
+ *
1559
+ * @since BuddyPress (1.6.0)
1560
+ *
1561
+ * @param array $tree Source array.
1562
+ * @return array Flattened array.
1563
+ */
1564
+ public static function flatten_activity_array( $tree ){
1565
+ foreach ( (array) $tree as $node ) {
1566
+ if ( isset( $node->children ) ) {
1567
+
1568
+ foreach ( BP_Activity_List_Table::flatten_activity_array( $node->children ) as $child ) {
1569
+ $tree[] = $child;
1570
+ }
1571
+
1572
+ unset( $node->children );
1573
+ }
1574
+ }
1575
+
1576
+ return $tree;
1577
+ }
1578
+ }
bp-activity/bp-activity-adminbar.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Toolbar.
4
- *
5
- * Handles the activity functions related to the WordPress Toolbar.
6
- *
7
- * @package BuddyPress
8
- * @subpackage Activity
9
- */
10
-
11
- // Exit if accessed directly.
12
- defined( 'ABSPATH' ) || exit;
13
-
14
- /**
15
- * Add the Activity top-level menu link when viewing single activity item.
16
- *
17
- * @since 2.6.0
18
- *
19
- * @return null Null if user does not have access to editing functionality.
20
- */
21
- function bp_activity_admin_menu() {
22
- global $wp_admin_bar;
23
-
24
- // Only show if viewing a single activity item.
25
- if ( ! bp_is_single_activity() ) {
26
- return;
27
- }
28
-
29
- // Only show this menu to super admins
30
- if ( ! bp_current_user_can( 'bp_moderate' ) ) {
31
- return;
32
- }
33
-
34
- $activity_edit_link = add_query_arg( array(
35
- 'page' => 'bp-activity',
36
- 'aid' => bp_current_action(),
37
- 'action' => 'edit'
38
- ), bp_get_admin_url( 'admin.php' ) );
39
-
40
- // Add the top-level Edit Activity button.
41
- $wp_admin_bar->add_menu( array(
42
- 'id' => 'activity-admin',
43
- 'title' => __( 'Edit Activity', 'buddypress' ),
44
- 'href' => esc_url( $activity_edit_link ),
45
- ) );
46
- }
47
- add_action( 'admin_bar_menu', 'bp_activity_admin_menu', 99 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-akismet.php CHANGED
@@ -3,61 +3,620 @@
3
  * Akismet support for BuddyPress' Activity Stream.
4
  *
5
  * @package BuddyPress
6
- * @subpackage ActivityAkismet
7
- * @since 1.6.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
- * Loads Akismet filtering for activity.
15
  *
16
- * @since 1.6.0
17
- * @since 2.3.0 We only support Akismet 3+.
18
  */
19
- function bp_activity_setup_akismet() {
20
  /**
21
- * Filters if BuddyPress Activity Akismet support has been disabled by another plugin.
22
  *
23
- * @since 1.6.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  *
25
- * @param bool $value Return value of bp_is_akismet_active boolean function.
26
  */
27
- if ( ! apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) ) {
28
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
 
31
- // Instantiate Akismet for BuddyPress.
32
- buddypress()->activity->akismet = new BP_Akismet();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
- add_action( 'bp_activity_setup_globals', 'bp_activity_setup_akismet' );
35
 
36
  /**
37
- * Delete old spam activity meta data.
38
  *
39
  * This is done as a clean-up mechanism, as _bp_akismet_submission meta can
40
  * grow to be quite large.
41
  *
42
- * @since 1.6.0
43
  *
 
44
  * @global wpdb $wpdb WordPress database object.
45
  */
46
  function bp_activity_akismet_delete_old_metadata() {
47
- global $wpdb;
48
-
49
- $bp = buddypress();
50
 
51
- /**
52
- * Filters the threshold for how many days old Akismet metadata needs to be before being automatically deleted.
53
- *
54
- * @since 1.6.0
55
- *
56
- * @param integer 15 How many days old metadata needs to be.
57
- */
58
  $interval = apply_filters( 'bp_activity_akismet_delete_meta_interval', 15 );
59
 
60
- // Enforce a minimum of 1 day.
61
  $interval = max( 1, absint( $interval ) );
62
 
63
  // _bp_akismet_submission meta values are large, so expire them after $interval days regardless of the activity status
3
  * Akismet support for BuddyPress' Activity Stream.
4
  *
5
  * @package BuddyPress
6
+ * @since BuddyPress (1.6)
7
+ * @subpackage Activity
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
+ * Akismet support for the Activity component.
15
  *
16
+ * @since BuddyPress (1.6)
 
17
  */
18
+ class BP_Akismet {
19
  /**
20
+ * The activity last marked as spam.
21
  *
22
+ * @access protected
23
+ * @var BP_Activity_Activity
24
+ * @since BuddyPress (1.6)
25
+ */
26
+ protected $last_activity = null;
27
+
28
+ /**
29
+ * Constructor.
30
+ *
31
+ * @since BuddyPress (1.6)
32
+ */
33
+ public function __construct() {
34
+ $this->setup_actions();
35
+ }
36
+
37
+ /**
38
+ * Hook Akismet into the activity stream.
39
+ *
40
+ * @since BuddyPress (1.6)
41
+ */
42
+ protected function setup_actions() {
43
+ // Add nonces to activity stream lists
44
+ add_action( 'bp_after_activity_post_form', array( $this, 'add_activity_stream_nonce' ) );
45
+ add_action( 'bp_activity_entry_comments', array( $this, 'add_activity_stream_nonce' ) );
46
+
47
+ // Add a "mark as spam" button to individual activity items
48
+ add_action( 'bp_activity_entry_meta', array( $this, 'add_activity_spam_button' ) );
49
+ add_action( 'bp_activity_comment_options', array( $this, 'add_activity_comment_spam_button' ) );
50
+
51
+ // Check activity for spam
52
+ add_action( 'bp_activity_before_save', array( $this, 'check_activity' ), 4, 1 );
53
+
54
+ // Tidy up member's latest (activity) update
55
+ add_action( 'bp_activity_posted_update', array( $this, 'check_member_activity_update' ), 1, 3 );
56
+
57
+ // Hooks to extend Activity core spam/ham functions for Akismet
58
+ add_action( 'bp_activity_mark_as_spam', array( $this, 'mark_as_spam' ), 10, 2 );
59
+ add_action( 'bp_activity_mark_as_ham', array( $this, 'mark_as_ham' ), 10, 2 );
60
+
61
+ // Hook into the Activity wp-admin screen
62
+ add_action( 'bp_activity_admin_comment_row_actions', array( $this, 'comment_row_action' ), 10, 2 );
63
+ add_action( 'bp_activity_admin_load', array( $this, 'add_history_metabox' ) );
64
+ }
65
+
66
+ /**
67
+ * Add a history item to the hover links in an activity's row.
68
+ *
69
+ * This function lifted with love from the Akismet WordPress plugin's
70
+ * akismet_comment_row_action() function. Thanks!
71
+ *
72
+ * @since BuddyPress (1.6)
73
+ *
74
+ * @param array $actions The hover links.
75
+ * @param array $activity The activity for the current row being processed.
76
+ * @return array The hover links.
77
+ */
78
+ function comment_row_action( $actions, $activity ) {
79
+ $akismet_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_result' );
80
+ $user_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_user_result' );
81
+ $desc = '';
82
+
83
+ if ( !$user_result || $user_result == $akismet_result ) {
84
+ // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same
85
+ if ( 'true' == $akismet_result && $activity['is_spam'] )
86
+ $desc = __( 'Flagged as spam by Akismet', 'buddypress' );
87
+
88
+ elseif ( 'false' == $akismet_result && !$activity['is_spam'] )
89
+ $desc = __( 'Cleared by Akismet', 'buddypress' );
90
+
91
+ } else {
92
+ $who = bp_activity_get_meta( $activity['id'], '_bp_akismet_user' );
93
+
94
+ if ( 'true' == $user_result )
95
+ $desc = sprintf( __( 'Flagged as spam by %s', 'buddypress' ), $who );
96
+ else
97
+ $desc = sprintf( __( 'Un-spammed by %s', 'buddypress' ), $who );
98
+ }
99
+
100
+ // add a History item to the hover links, just after Edit
101
+ if ( $akismet_result ) {
102
+ $b = array();
103
+ foreach ( $actions as $k => $item ) {
104
+ $b[ $k ] = $item;
105
+ if ( $k == 'edit' )
106
+ $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>';
107
+ }
108
+
109
+ $actions = $b;
110
+ }
111
+
112
+ if ( $desc )
113
+ 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>';
114
+
115
+ return apply_filters( 'bp_akismet_comment_row_action', $actions );
116
+ }
117
+
118
+ /**
119
+ * Generate nonces for activity forms.
120
+ *
121
+ * These nonces appear in the member profile status form, as well as in
122
+ * the reply form of each activity item. The nonces are, in turn, used
123
+ * by Akismet to help detect spam activity.
124
+ *
125
+ * @since BuddyPress (1.6)
126
+ *
127
+ * @see http://plugins.trac.wordpress.org/ticket/1232
128
+ */
129
+ public function add_activity_stream_nonce() {
130
+ $form_id = '_bp_as_nonce';
131
+ $value = '_bp_as_nonce_' . bp_loggedin_user_id();
132
+
133
+ // If we're in the activity stream loop, we can use the current item's ID to make the nonce unique
134
+ if ( 'bp_activity_entry_comments' == current_filter() ) {
135
+ $form_id .= '_' . bp_get_activity_id();
136
+ $value .= '_' . bp_get_activity_id();
137
+ }
138
+
139
+ wp_nonce_field( $value, $form_id, false );
140
+ }
141
+
142
+ /**
143
+ * Clean up the bp_latest_update usermeta in case of spamming.
144
+ *
145
+ * Run just after an update is posted, this method check to see whether
146
+ * the newly created update has been marked as spam by Akismet. If so,
147
+ * the cached update is cleared from the user's 'bp_latest_update'
148
+ * usermeta, ensuring that it won't appear in the member header and
149
+ * elsewhere in the theme.
150
+ *
151
+ * This can't be done in BP_Akismet::check_activity() due to the
152
+ * default AJAX implementation; see bp_dtheme_post_update().
153
+ *
154
+ * @since BuddyPress (1.6)
155
+ *
156
+ * @see bp_dtheme_post_update()
157
+ *
158
+ * @param string $content Activity update text.
159
+ * @param int $user_id User ID.
160
+ * @param int $activity_id Activity ID.
161
+ */
162
+ public function check_member_activity_update( $content, $user_id, $activity_id ) {
163
+ // By default, only handle activity updates and activity comments.
164
+ if ( empty( $this->last_activity ) || !in_array( $this->last_activity->type, BP_Akismet::get_activity_types() ) )
165
+ return;
166
+
167
+ // Was this $activity_id just marked as spam? If not, bail out.
168
+ if ( !$this->last_activity->id || $activity_id != $this->last_activity->id || 'false' == $this->last_activity->akismet_submission['bp_as_result'] )
169
+ return;
170
+
171
+ // It was, so delete the member's latest activity update.
172
+ bp_delete_user_meta( $user_id, 'bp_latest_update' );
173
+ }
174
+
175
+ /**
176
+ * Adds a "mark as spam" button to each activity item for site admins.
177
+ *
178
+ * This function is intended to be used inside the activity stream loop.
179
+ *
180
+ * @since BuddyPress (1.6)
181
+ */
182
+ public function add_activity_spam_button() {
183
+ if ( !bp_activity_user_can_mark_spam() )
184
+ return;
185
+
186
+ // By default, only handle activity updates and activity comments.
187
+ if ( !in_array( bp_get_activity_type(), BP_Akismet::get_activity_types() ) )
188
+ return;
189
+
190
+ bp_button(
191
+ array(
192
+ 'block_self' => false,
193
+ 'component' => 'activity',
194
+ 'id' => 'activity_make_spam_' . bp_get_activity_id(),
195
+ 'link_class' => 'bp-secondary-action spam-activity confirm button item-button',
196
+ '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() ),
197
+ 'link_text' => __( 'Spam', 'buddypress' ),
198
+ 'wrapper' => false,
199
+ )
200
+ );
201
+ }
202
+
203
+ /**
204
+ * Adds a "mark as spam" button to each activity COMMENT item for site admins.
205
+ *
206
+ * This function is intended to be used inside the activity stream loop.
207
+ *
208
+ * @since BuddyPress (1.6)
209
+ */
210
+ public function add_activity_comment_spam_button() {
211
+ if ( !bp_activity_user_can_mark_spam() )
212
+ return;
213
+
214
+ // By default, only handle activity updates and activity comments.
215
+ $current_comment = bp_activity_current_comment();
216
+ if ( empty( $current_comment ) || !in_array( $current_comment->type, BP_Akismet::get_activity_types() ) )
217
+ return;
218
+
219
+ bp_button(
220
+ array(
221
+ 'block_self' => false,
222
+ 'component' => 'activity',
223
+ 'id' => 'activity_make_spam_' . bp_get_activity_comment_id(),
224
+ 'link_class' => 'bp-secondary-action spam-activity-comment confirm',
225
+ '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() ),
226
+ 'link_text' => __( 'Spam', 'buddypress' ),
227
+ 'wrapper' => false,
228
+ )
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Get a filterable list of activity types that Akismet should automatically check for spam.
234
+ *
235
+ * @since BuddyPress (1.6)
236
+ *
237
+ * @static
238
+ *
239
+ * @return array List of activity types.
240
+ */
241
+ public static function get_activity_types() {
242
+ return apply_filters( 'bp_akismet_get_activity_types', array( 'activity_comment', 'activity_update' ) );
243
+ }
244
+
245
+ /**
246
+ * Mark activity item as spam.
247
+ *
248
+ * @since BuddyPress (1.6)
249
+ *
250
+ * @param BP_Activity_Activity $activity
251
+ * @param string $source Either "by_a_person" (e.g. a person has manually marked the activity as spam) or "by_akismet" (automatically spammed).
252
+ */
253
+ public function mark_as_spam( $activity, $source ) {
254
+ // Record this item so we can do some tidyup in BP_Akismet::check_member_activity_update()
255
+ $this->last_activity = $activity;
256
+
257
+ do_action( 'bp_activity_akismet_mark_as_spam', $activity, $source );
258
+ }
259
+
260
+ /**
261
+ * Mark activity item as ham.
262
+ *
263
+ * @since BuddyPress (1.6)
264
+ *
265
+ * @param BP_Activity_Activity $activity
266
+ * @param string $source Either "by_a_person" (e.g. a person has manually marked the activity as ham) or "by_akismet" (automatically hammed).
267
+ */
268
+ public function mark_as_ham( $activity, $source ) {
269
+ // If the activity was, originally, automatically marked as spam by Akismet, run the @mentions filter as it would have been skipped.
270
+ if ( 'true' == bp_activity_get_meta( $activity->id, '_bp_akismet_result' ) && !bp_activity_get_meta( $activity->id, '_bp_akismet_user_result' ) )
271
+ $activity->content = bp_activity_at_name_filter( $activity->content, $activity->id );
272
+
273
+ do_action( 'bp_activity_akismet_mark_as_ham', $activity, $source );
274
+ }
275
+
276
+ /**
277
+ * Build a data package for the Akismet service to inspect.
278
+ *
279
+ * @since BuddyPress (1.6)
280
+ *
281
+ * @see http://akismet.com/development/api/#comment-check
282
+ * @static
283
+ *
284
+ * @param BP_Activity_Activity $activity Activity item data.
285
+ */
286
+ public static function build_akismet_data_package( $activity ) {
287
+ $userdata = get_userdata( $activity->user_id );
288
+
289
+ $activity_data = array();
290
+ $activity_data['akismet_comment_nonce'] = 'inactive';
291
+ $activity_data['comment_author'] = $userdata->display_name;
292
+ $activity_data['comment_author_email'] = $userdata->user_email;
293
+ $activity_data['comment_author_url'] = bp_core_get_userlink( $userdata->ID, false, true);
294
+ $activity_data['comment_content'] = $activity->content;
295
+ $activity_data['comment_type'] = $activity->type;
296
+ $activity_data['permalink'] = bp_activity_get_permalink( $activity->id, $activity );
297
+ $activity_data['user_ID'] = $userdata->ID;
298
+ $activity_data['user_role'] = akismet_get_user_roles( $userdata->ID );
299
+
300
+ /**
301
+ * Get the nonce if the new activity was submitted through the "what's up, Paul?" form.
302
+ * This helps Akismet ensure that the update was a valid form submission.
303
+ */
304
+ if ( !empty( $_POST['_bp_as_nonce'] ) )
305
+ $activity_data['akismet_comment_nonce'] = wp_verify_nonce( $_POST['_bp_as_nonce'], "_bp_as_nonce_{$userdata->ID}" ) ? 'passed' : 'failed';
306
+
307
+ /**
308
+ * If the new activity was a reply to an existing item, check the nonce with the activity parent ID.
309
+ * This helps Akismet ensure that the update was a valid form submission.
310
+ */
311
+ elseif ( !empty( $activity->secondary_item_id ) && !empty( $_POST['_bp_as_nonce_' . $activity->secondary_item_id] ) )
312
+ $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';
313
+
314
+ return apply_filters( 'bp_akismet_build_akismet_data_package', $activity_data, $activity );
315
+ }
316
+
317
+ /**
318
+ * Check if the activity item is spam or ham.
319
+ *
320
+ * @since BuddyPress (1.6)
321
+ *
322
+ * @see http://akismet.com/development/api/
323
+ * @todo Spam counter?
324
+ * @todo Auto-delete old spam?
325
+ *
326
+ * @param BP_Activity_Activity $activity The activity item to check.
327
+ */
328
+ public function check_activity( $activity ) {
329
+ // By default, only handle activity updates and activity comments.
330
+ if ( !in_array( $activity->type, BP_Akismet::get_activity_types() ) )
331
+ return;
332
+
333
+ // Make sure last_activity is clear to avoid any confusion
334
+ $this->last_activity = null;
335
+
336
+ // Build data package for Akismet
337
+ $activity_data = BP_Akismet::build_akismet_data_package( $activity );
338
+
339
+ // Check with Akismet to see if this is spam
340
+ $activity_data = $this->send_akismet_request( $activity_data, 'check', 'spam' );
341
+
342
+ // Record this item
343
+ $this->last_activity = $activity;
344
+
345
+ // Store a copy of the data that was submitted to Akismet
346
+ $this->last_activity->akismet_submission = $activity_data;
347
+
348
+ // Spam
349
+ if ( 'true' == $activity_data['bp_as_result'] ) {
350
+ // Action for plugin authors
351
+ do_action_ref_array( 'bp_activity_akismet_spam_caught', array( &$activity, $activity_data ) );
352
+
353
+ // Mark as spam
354
+ bp_activity_mark_as_spam( $activity, 'by_akismet' );
355
+ }
356
+
357
+ // Update activity meta after a spam check
358
+ add_action( 'bp_activity_after_save', array( $this, 'update_activity_akismet_meta' ), 1, 1 );
359
+ }
360
+
361
+ /**
362
+ * Update activity meta after a manual spam change (user-initiated).
363
+ *
364
+ * @since BuddyPress (1.6)
365
+ *
366
+ * @param BP_Activity_Activity $activity The activity to check.
367
+ */
368
+ public function update_activity_spam_meta( $activity ) {
369
+ // By default, only handle activity updates and activity comments.
370
+ if ( !in_array( $activity->type, BP_Akismet::get_activity_types() ) )
371
+ return;
372
+
373
+ $this->update_activity_history( $activity->id, sprintf( __( '%s reported this activity as spam', 'buddypress' ), bp_get_loggedin_user_username() ), 'report-spam' );
374
+ bp_activity_update_meta( $activity->id, '_bp_akismet_user_result', 'true' );
375
+ bp_activity_update_meta( $activity->id, '_bp_akismet_user', bp_get_loggedin_user_username() );
376
+ }
377
+
378
+ /**
379
+ * Update activity meta after a manual ham change (user-initiated).
380
+ *
381
+ * @since BuddyPress (1.6)
382
+ *
383
+ * @param BP_Activity_Activity $activity The activity to check.
384
+ */
385
+ public function update_activity_ham_meta( $activity ) {
386
+ // By default, only handle activity updates and activity comments.
387
+ if ( !in_array( $activity->type, BP_Akismet::get_activity_types() ) )
388
+ return;
389
+
390
+ $this->update_activity_history( $activity->id, sprintf( __( '%s reported this activity as not spam', 'buddypress' ), bp_get_loggedin_user_username() ), 'report-ham' );
391
+ bp_activity_update_meta( $activity->id, '_bp_akismet_user_result', 'false' );
392
+ bp_activity_update_meta( $activity->id, '_bp_akismet_user', bp_get_loggedin_user_username() );
393
+ }
394
+
395
+ /**
396
+ * Update activity meta after an automatic spam check (not user-initiated).
397
+ *
398
+ * @since BuddyPress (1.6)
399
+ *
400
+ * @param BP_Activity_Activity $activity The activity to check.
401
+ */
402
+ public function update_activity_akismet_meta( $activity ) {
403
+ // Check we're dealing with what was last updated by Akismet
404
+ if ( empty( $this->last_activity ) || !empty( $this->last_activity ) && $activity->id != $this->last_activity->id )
405
+ return;
406
+
407
+ // By default, only handle activity updates and activity comments.
408
+ if ( !in_array( $this->last_activity->type, BP_Akismet::get_activity_types() ) )
409
+ return;
410
+
411
+ // Spam
412
+ if ( 'true' == $this->last_activity->akismet_submission['bp_as_result'] ) {
413
+ bp_activity_update_meta( $activity->id, '_bp_akismet_result', 'true' );
414
+ $this->update_activity_history( $activity->id, __( 'Akismet caught this item as spam', 'buddypress' ), 'check-spam' );
415
+
416
+ // Not spam
417
+ } elseif ( 'false' == $this->last_activity->akismet_submission['bp_as_result'] ) {
418
+ bp_activity_update_meta( $activity->id, '_bp_akismet_result', 'false' );
419
+ $this->update_activity_history( $activity->id, __( 'Akismet cleared this item', 'buddypress' ), 'check-ham' );
420
+
421
+ // Uh oh, something's gone horribly wrong. Unexpected result.
422
+ } else {
423
+ bp_activity_update_meta( $activity->id, '_bp_akismet_error', bp_core_current_time() );
424
+ $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' );
425
+ }
426
+
427
+ // Record the original data which was submitted to Akismet for checking
428
+ bp_activity_update_meta( $activity->id, '_bp_akismet_submission', $this->last_activity->akismet_submission );
429
+ }
430
+
431
+ /**
432
+ * Contact Akismet to check if this is spam or ham.
433
+ *
434
+ * Props to WordPress core Akismet plugin for alot of this.
435
+ *
436
+ * @since BuddyPress (1.6)
437
+ *
438
+ * @global string $akismet_api_host
439
+ * @global string $akismet_api_port
440
+ *
441
+ * @param array $activity_data Packet of information to submit to Akismet.
442
+ * @param string $check "check" or "submit".
443
+ * @param string $spam "spam" or "ham".
444
+ * @return array $activity_data Activity data, with Akismet data added.
445
+ */
446
+ public function send_akismet_request( $activity_data, $check = 'check', $spam = 'spam' ) {
447
+ global $akismet_api_host, $akismet_api_port;
448
+
449
+ // Check that host and port are set, if not, set them
450
+ if ( function_exists( 'akismet_init' ) && ( empty( $akismet_api_host ) || empty( $akismet_api_port ) ) )
451
+ akismet_init();
452
+
453
+ $query_string = $path = $response = '';
454
+
455
+ $activity_data['blog'] = bp_get_option( 'home' );
456
+ $activity_data['blog_charset'] = bp_get_option( 'blog_charset' );
457
+ $activity_data['blog_lang'] = get_locale();
458
+ $activity_data['referrer'] = $_SERVER['HTTP_REFERER'];
459
+ $activity_data['user_agent'] = bp_core_current_user_ua();
460
+ $activity_data['user_ip'] = bp_core_current_user_ip();
461
+
462
+ if ( akismet_test_mode() )
463
+ $activity_data['is_test'] = 'true';
464
+
465
+ // Loop through _POST args and rekey strings
466
+ foreach ( $_POST as $key => $value )
467
+ if ( is_string( $value ) && 'cookie' != $key )
468
+ $activity_data['POST_' . $key] = $value;
469
+
470
+ // Keys to ignore
471
+ $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' );
472
+
473
+ // Loop through _SERVER args and remove whitelisted keys
474
+ foreach ( $_SERVER as $key => $value ) {
475
+
476
+ // Key should not be ignored
477
+ if ( !in_array( $key, $ignore ) && is_string( $value ) ) {
478
+ $activity_data[$key] = $value;
479
+
480
+ // Key should be ignored
481
+ } else {
482
+ $activity_data[$key] = '';
483
+ }
484
+ }
485
+
486
+ foreach ( $activity_data as $key => $data )
487
+ $query_string .= $key . '=' . urlencode( stripslashes( $data ) ) . '&';
488
+
489
+ if ( 'check' == $check )
490
+ $path = '/1.1/comment-check';
491
+ elseif ( 'submit' == $check )
492
+ $path = '/1.1/submit-' . $spam;
493
+
494
+ // Send to Akismet
495
+ add_filter( 'akismet_ua', array( $this, 'buddypress_ua' ) );
496
+ $response = akismet_http_post( $query_string, $akismet_api_host, $path, $akismet_api_port );
497
+ remove_filter( 'akismet_ua', array( $this, 'buddypress_ua' ) );
498
+
499
+ // Get the response
500
+ if ( ! empty( $response[1] ) && ! is_wp_error( $response[1] ) )
501
+ $activity_data['bp_as_result'] = $response[1];
502
+ else
503
+ $activity_data['bp_as_result'] = false;
504
+
505
+ // Perform a daily tidy up
506
+ if ( ! wp_next_scheduled( 'bp_activity_akismet_delete_old_metadata' ) )
507
+ wp_schedule_event( time(), 'daily', 'bp_activity_akismet_delete_old_metadata' );
508
+
509
+ return $activity_data;
510
+ }
511
+
512
+ /**
513
+ * Filters user agent when sending to Akismet to add BuddyPress info.
514
+ *
515
+ * @since BuddyPress (1.6)
516
+ *
517
+ * @param string $user_agent User agent string, as generated by Akismet.
518
+ * @return string $user_agent Modified user agent string.
519
+ */
520
+ public function buddypress_ua( $user_agent ) {
521
+ $user_agent = 'BuddyPress/' . bp_get_version() . ' | Akismet/'. constant( 'AKISMET_VERSION' );
522
+ return $user_agent;
523
+ }
524
+
525
+ /**
526
+ * Adds a "History" meta box to the activity edit screen.
527
+ *
528
+ * @since BuddyPress (1.6)
529
+ *
530
+ * @param string $screen_action The type of screen that has been requested.
531
+ */
532
+ function add_history_metabox( $screen_action ) {
533
+ // Only proceed if we're on the edit screen
534
+ if ( 'edit' != $screen_action )
535
+ return;
536
+
537
+ // Display meta box with a low priority (low position on screen by default)
538
+ add_meta_box( 'bp_activity_history', __( 'Activity History', 'buddypress' ), array( $this, 'history_metabox' ), get_current_screen()->id, 'normal', 'low' );
539
+ }
540
+
541
+ /**
542
+ * History meta box for the Activity admin edit screen.
543
+ *
544
+ * @since BuddyPress (1.6)
545
+ *
546
+ * @see http://buddypress.trac.wordpress.org/ticket/3907
547
+ * @todo Update activity meta to allow >1 record with the same key (iterate through $history).
548
  *
549
+ * @param object $item Activity item.
550
  */
551
+ function history_metabox( $item ) {
552
+ $history = BP_Akismet::get_activity_history( $item->id );
553
+
554
+ if ( empty( $history ) )
555
+ return;
556
+
557
+ echo '<div class="akismet-history"><div>';
558
+ printf( _x( '<span>%1$s</span> &mdash; %2$s', 'x hours ago - akismet cleared this item', 'buddypress' ), bp_core_time_since( $history[2] ), esc_html( $history[1] ) );
559
+ echo '</div></div>';
560
+ }
561
+
562
+ /**
563
+ * Update an activity item's Akismet history.
564
+ *
565
+ * @since BuddyPress (1.6)
566
+ *
567
+ * @param int $activity_id Activity item ID.
568
+ * @param string $message Human-readable description of what's changed.
569
+ * @param string $event The type of check we were carrying out.
570
+ */
571
+ public function update_activity_history( $activity_id = 0, $message = '', $event = '' ) {
572
+ $event = array(
573
+ 'event' => $event,
574
+ 'message' => $message,
575
+ 'time' => akismet_microtime(),
576
+ 'user' => bp_loggedin_user_id(),
577
+ );
578
+
579
+ // Save the history data
580
+ bp_activity_update_meta( $activity_id, '_bp_akismet_history', $event );
581
  }
582
 
583
+ /**
584
+ * Get an activity item's Akismet history.
585
+ *
586
+ * @since BuddyPress (1.6)
587
+ *
588
+ * @param int $activity_id Activity item ID.
589
+ * @return array The activity item's Akismet history.
590
+ */
591
+ public function get_activity_history( $activity_id = 0 ) {
592
+ $history = bp_activity_get_meta( $activity_id, '_bp_akismet_history' );
593
+ if ( $history === false )
594
+ $history = array();
595
+
596
+ // Sort it by the time recorded
597
+ usort( $history, 'akismet_cmp_time' );
598
+
599
+ return $history;
600
+ }
601
  }
 
602
 
603
  /**
604
+ * Delete old spam activity meta data
605
  *
606
  * This is done as a clean-up mechanism, as _bp_akismet_submission meta can
607
  * grow to be quite large.
608
  *
609
+ * @since BuddyPress (1.6)
610
  *
611
+ * @global object $bp BuddyPress global settings.
612
  * @global wpdb $wpdb WordPress database object.
613
  */
614
  function bp_activity_akismet_delete_old_metadata() {
615
+ global $bp, $wpdb;
 
 
616
 
 
 
 
 
 
 
 
617
  $interval = apply_filters( 'bp_activity_akismet_delete_meta_interval', 15 );
618
 
619
+ // Enforce a minimum of 1 day
620
  $interval = max( 1, absint( $interval ) );
621
 
622
  // _bp_akismet_submission meta values are large, so expire them after $interval days regardless of the activity status
bp-activity/bp-activity-cache.php CHANGED
@@ -1,14 +1,13 @@
1
  <?php
 
2
  /**
3
  * Functions related to the BuddyPress Activity component and the WP Cache.
4
  *
5
- * @package BuddyPress
6
- * @subpackage ActivityCache
7
- * @since 1.6.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Slurp up activitymeta for a specified set of activity items.
@@ -17,13 +16,11 @@ defined( 'ABSPATH' ) || exit;
17
  * in $activity_ids and adds it to the WP cache. This improves efficiency when
18
  * using querying activitymeta inline.
19
  *
20
- * @since 1.6.0
21
- *
22
- * @param int|string|array|bool $activity_ids Accepts a single activity ID, or a comma-
23
- * separated list or array of activity ids.
24
  */
25
  function bp_activity_update_meta_cache( $activity_ids = false ) {
26
- $bp = buddypress();
27
 
28
  $cache_args = array(
29
  'object_ids' => $activity_ids,
@@ -40,20 +37,19 @@ function bp_activity_update_meta_cache( $activity_ids = false ) {
40
  /**
41
  * Clear a cached activity item when that item is updated.
42
  *
43
- * @since 2.0.0
44
  *
45
- * @param BP_Activity_Activity $activity Activity object.
46
  */
47
  function bp_activity_clear_cache_for_activity( $activity ) {
48
  wp_cache_delete( $activity->id, 'bp_activity' );
49
- wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
50
  }
51
  add_action( 'bp_activity_after_save', 'bp_activity_clear_cache_for_activity' );
52
 
53
  /**
54
  * Clear cached data for deleted activity items.
55
  *
56
- * @since 2.0.0
57
  *
58
  * @param array $deleted_ids IDs of deleted activity items.
59
  */
@@ -63,24 +59,3 @@ function bp_activity_clear_cache_for_deleted_activity( $deleted_ids ) {
63
  }
64
  }
65
  add_action( 'bp_activity_deleted_activities', 'bp_activity_clear_cache_for_deleted_activity' );
66
-
67
- /**
68
- * Reset cache incrementor for the Activity component.
69
- *
70
- * Called whenever an activity item is created, updated, or deleted, this
71
- * function effectively invalidates all cached results of activity queries.
72
- *
73
- * @since 2.7.0
74
- *
75
- * @return bool True on success, false on failure.
76
- */
77
- function bp_activity_reset_cache_incrementor() {
78
- $without_last_activity = bp_core_reset_incrementor( 'bp_activity' );
79
- $with_last_activity = bp_core_reset_incrementor( 'bp_activity_with_last_activity' );
80
- return $without_last_activity && $with_last_activity;
81
- }
82
- add_action( 'bp_activity_delete', 'bp_activity_reset_cache_incrementor' );
83
- add_action( 'bp_activity_add', 'bp_activity_reset_cache_incrementor' );
84
- add_action( 'added_activity_meta', 'bp_activity_reset_cache_incrementor' );
85
- add_action( 'updated_activity_meta', 'bp_activity_reset_cache_incrementor' );
86
- add_action( 'deleted_activity_meta', 'bp_activity_reset_cache_incrementor' );
1
  <?php
2
+
3
  /**
4
  * Functions related to the BuddyPress Activity component and the WP Cache.
5
  *
6
+ * @since BuddyPress (1.6)
 
 
7
  */
8
 
9
+ // Exit if accessed directly
10
+ if ( !defined( 'ABSPATH' ) ) exit;
11
 
12
  /**
13
  * Slurp up activitymeta for a specified set of activity items.
16
  * in $activity_ids and adds it to the WP cache. This improves efficiency when
17
  * using querying activitymeta inline.
18
  *
19
+ * @param int|str|array $activity_ids Accepts a single activity ID, or a comma-
20
+ * separated list or array of activity ids
 
 
21
  */
22
  function bp_activity_update_meta_cache( $activity_ids = false ) {
23
+ global $bp;
24
 
25
  $cache_args = array(
26
  'object_ids' => $activity_ids,
37
  /**
38
  * Clear a cached activity item when that item is updated.
39
  *
40
+ * @since 2.0
41
  *
42
+ * @param BP_Activity_Activity $activity
43
  */
44
  function bp_activity_clear_cache_for_activity( $activity ) {
45
  wp_cache_delete( $activity->id, 'bp_activity' );
 
46
  }
47
  add_action( 'bp_activity_after_save', 'bp_activity_clear_cache_for_activity' );
48
 
49
  /**
50
  * Clear cached data for deleted activity items.
51
  *
52
+ * @since 2.0
53
  *
54
  * @param array $deleted_ids IDs of deleted activity items.
55
  */
59
  }
60
  }
61
  add_action( 'bp_activity_deleted_activities', 'bp_activity_clear_cache_for_deleted_activity' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-classes.php ADDED
@@ -0,0 +1,1682 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * BuddyPress Activity Classes
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage Activity
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if ( !defined( 'ABSPATH' ) ) exit;
11
+
12
+ /**
13
+ * Database interaction class for the BuddyPress activity component.
14
+ *
15
+ * Instance methods are available for creating/editing an activity,
16
+ * static methods for querying activities.
17
+ *
18
+ * @since BuddyPress (1.0)
19
+ */
20
+ class BP_Activity_Activity {
21
+
22
+ /** Properties ************************************************************/
23
+
24
+ /**
25
+ * ID of the activity item.
26
+ *
27
+ * @var int
28
+ */
29
+ var $id;
30
+
31
+ /**
32
+ * ID of the associated item.
33
+ *
34
+ * @var int
35
+ */
36
+ var $item_id;
37
+
38
+ /**
39
+ * ID of the associated secondary item.
40
+ *
41
+ * @var int
42
+ */
43
+ var $secondary_item_id;
44
+
45
+ /**
46
+ * ID of user associated with the activity item.
47
+ *
48
+ * @var int
49
+ */
50
+ var $user_id;
51
+
52
+ /**
53
+ * The primary URL for the activity in RSS feeds.
54
+ *
55
+ * @var string
56
+ */
57
+ var $primary_link;
58
+
59
+ /**
60
+ * BuddyPress component the activity item relates to.
61
+ *
62
+ * @var string
63
+ */
64
+ var $component;
65
+
66
+ /**
67
+ * Activity type, eg 'new_blog_post'.
68
+ *
69
+ * @var string
70
+ */
71
+ var $type;
72
+
73
+ /**
74
+ * Description of the activity, eg 'Alex updated his profile.'
75
+ *
76
+ * @var string
77
+ */
78
+ var $action;
79
+
80
+ /**
81
+ * The content of the activity item.
82
+ *
83
+ * @var string
84
+ */
85
+ var $content;
86
+
87
+ /**
88
+ * The date the activity item was recorded, in 'Y-m-d h:i:s' format.
89
+ *
90
+ * @var string
91
+ */
92
+ var $date_recorded;
93
+
94
+ /**
95
+ * Whether the item should be hidden in sitewide streams.
96
+ *
97
+ * @var int
98
+ */
99
+ var $hide_sitewide = false;
100
+
101
+ /**
102
+ * Node boundary start for activity or activity comment.
103
+ *
104
+ * @var int
105
+ */
106
+ var $mptt_left;
107
+
108
+ /**
109
+ * Node boundary end for activity or activity comment.
110
+ *
111
+ * @var int
112
+ */
113
+ var $mptt_right;
114
+
115
+ /**
116
+ * Whether this item is marked as spam.
117
+ *
118
+ * @var int
119
+ */
120
+ var $is_spam;
121
+
122
+ /**
123
+ * Constructor method.
124
+ *
125
+ * @param int $id Optional. The ID of a specific activity item.
126
+ */
127
+ public function __construct( $id = false ) {
128
+ if ( !empty( $id ) ) {
129
+ $this->id = $id;
130
+ $this->populate();
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Populate the object with data about the specific activity item.
136
+ */
137
+ public function populate() {
138
+ global $wpdb, $bp;
139
+
140
+ $row = wp_cache_get( $this->id, 'bp_activity' );
141
+
142
+ if ( false === $row ) {
143
+ $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE id = %d", $this->id ) );
144
+
145
+ wp_cache_set( $this->id, $row, 'bp_activity' );
146
+ }
147
+
148
+ if ( ! empty( $row ) ) {
149
+ $this->id = $row->id;
150
+ $this->item_id = $row->item_id;
151
+ $this->secondary_item_id = $row->secondary_item_id;
152
+ $this->user_id = $row->user_id;
153
+ $this->primary_link = $row->primary_link;
154
+ $this->component = $row->component;
155
+ $this->type = $row->type;
156
+ $this->action = $row->action;
157
+ $this->content = $row->content;
158
+ $this->date_recorded = $row->date_recorded;
159
+ $this->hide_sitewide = $row->hide_sitewide;
160
+ $this->mptt_left = $row->mptt_left;
161
+ $this->mptt_right = $row->mptt_right;
162
+ $this->is_spam = $row->is_spam;
163
+ }
164
+
165
+ // Generate dynamic 'action' when possible
166
+ $action = bp_activity_generate_action_string( $this );
167
+ if ( false !== $action ) {
168
+ $this->action = $action;
169
+
170
+ // If no callback is available, use the literal string from
171
+ // the database row
172
+ } else if ( ! empty( $row->action ) ) {
173
+ $this->action = $row->action;
174
+
175
+ // Provide a fallback to avoid PHP notices
176
+ } else {
177
+ $this->action = '';
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Save the activity item to the database.
183
+ *
184
+ * @return bool True on success.
185
+ */
186
+ public function save() {
187
+ global $wpdb, $bp;
188
+
189
+ $this->id = apply_filters_ref_array( 'bp_activity_id_before_save', array( $this->id, &$this ) );
190
+ $this->item_id = apply_filters_ref_array( 'bp_activity_item_id_before_save', array( $this->item_id, &$this ) );
191
+ $this->secondary_item_id = apply_filters_ref_array( 'bp_activity_secondary_item_id_before_save', array( $this->secondary_item_id, &$this ) );
192
+ $this->user_id = apply_filters_ref_array( 'bp_activity_user_id_before_save', array( $this->user_id, &$this ) );
193
+ $this->primary_link = apply_filters_ref_array( 'bp_activity_primary_link_before_save', array( $this->primary_link, &$this ) );
194
+ $this->component = apply_filters_ref_array( 'bp_activity_component_before_save', array( $this->component, &$this ) );
195
+ $this->type = apply_filters_ref_array( 'bp_activity_type_before_save', array( $this->type, &$this ) );
196
+ $this->action = apply_filters_ref_array( 'bp_activity_action_before_save', array( $this->action, &$this ) );
197
+ $this->content = apply_filters_ref_array( 'bp_activity_content_before_save', array( $this->content, &$this ) );
198
+ $this->date_recorded = apply_filters_ref_array( 'bp_activity_date_recorded_before_save', array( $this->date_recorded, &$this ) );
199
+ $this->hide_sitewide = apply_filters_ref_array( 'bp_activity_hide_sitewide_before_save', array( $this->hide_sitewide, &$this ) );
200
+ $this->mptt_left = apply_filters_ref_array( 'bp_activity_mptt_left_before_save', array( $this->mptt_left, &$this ) );
201
+ $this->mptt_right = apply_filters_ref_array( 'bp_activity_mptt_right_before_save', array( $this->mptt_right, &$this ) );
202
+ $this->is_spam = apply_filters_ref_array( 'bp_activity_is_spam_before_save', array( $this->is_spam, &$this ) );
203
+
204
+ // Use this, not the filters above
205
+ do_action_ref_array( 'bp_activity_before_save', array( &$this ) );
206
+
207
+ if ( !$this->component || !$this->type )
208
+ return false;
209
+
210
+ if ( !$this->primary_link )
211
+ $this->primary_link = bp_loggedin_user_domain();
212
+
213
+ // If we have an existing ID, update the activity item, otherwise insert it.
214
+ if ( $this->id )
215
+ $q = $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET user_id = %d, component = %s, type = %s, action = %s, content = %s, primary_link = %s, date_recorded = %s, item_id = %d, secondary_item_id = %d, hide_sitewide = %d, is_spam = %d WHERE id = %d", $this->user_id, $this->component, $this->type, $this->action, $this->content, $this->primary_link, $this->date_recorded, $this->item_id, $this->secondary_item_id, $this->hide_sitewide, $this->is_spam, $this->id );
216
+ else
217
+ $q = $wpdb->prepare( "INSERT INTO {$bp->activity->table_name} ( user_id, component, type, action, content, primary_link, date_recorded, item_id, secondary_item_id, hide_sitewide, is_spam ) VALUES ( %d, %s, %s, %s, %s, %s, %s, %d, %d, %d, %d )", $this->user_id, $this->component, $this->type, $this->action, $this->content, $this->primary_link, $this->date_recorded, $this->item_id, $this->secondary_item_id, $this->hide_sitewide, $this->is_spam );
218
+
219
+ if ( false === $wpdb->query( $q ) )
220
+ return false;
221
+
222
+ // If this is a new activity item, set the $id property
223
+ if ( empty( $this->id ) )
224
+ $this->id = $wpdb->insert_id;
225
+
226
+ // If an existing activity item, prevent any changes to the content generating new @mention notifications.
227
+ else
228
+ add_filter( 'bp_activity_at_name_do_notifications', '__return_false' );
229
+
230
+ do_action_ref_array( 'bp_activity_after_save', array( &$this ) );
231
+
232
+ return true;
233
+ }
234
+
235
+ /** Static Methods ***************************************************/
236
+
237
+ /**
238
+ * Get activity items, as specified by parameters
239
+ *
240
+ * @see BP_Activity_Activity::get_filter_sql() for a description of the
241
+ * 'filter' parameter.
242
+ * @see WP_Meta_Query::queries for a description of the 'meta_query'
243
+ * parameter format.
244
+ *
245
+ * @param array $args {
246
+ * An array of arguments. All items are optional.
247
+ * @type int $page Which page of results to fetch. Using page=1
248
+ * without per_page will result in no pagination.
249
+ * Default: 1.
250
+ * @type int|bool $per_page Number of results per page. Default: 25.
251
+ * @type int|bool $max Maximum number of results to return.
252
+ * Default: false (unlimited).
253
+ * @type string $sort ASC or DESC. Default: 'DESC'.
254
+ * @type array $exclude Array of activity IDs to exclude.
255
+ * Default: false.
256
+ * @type array $in Array of ids to limit query by (IN).
257
+ * Default: false.
258
+ * @type array $meta_query An array of meta_query conditions.
259
+ * See WP_Meta_Query::queries for description.
260
+ * @type array $filter See BP_Activity_Activity::get_filter_sql().
261
+ * @type string $search_terms Limit results by a search term.
262
+ * Default: false.
263
+ * @type bool $display_comments Whether to include activity comments.
264
+ * Default: false.
265
+ * @type bool $show_hidden Whether to show items marked hide_sitewide.
266
+ * Default: false.
267
+ * @type string $spam Spam status. Default: 'ham_only'.
268
+ * @type bool $update_meta_cache Whether to pre-fetch metadata for
269
+ * queried activity items. Default: true.
270
+ * }
271
+ * @return array The array returned has two keys:
272
+ * - 'total' is the count of located activities
273
+ * - 'activities' is an array of the located activities
274
+ */
275
+ public static function get( $args = array() ) {
276
+ global $wpdb, $bp;
277
+
278
+ // Backward compatibility with old method of passing arguments
279
+ if ( !is_array( $args ) || func_num_args() > 1 ) {
280
+ _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__ ) );
281
+
282
+ $old_args_keys = array(
283
+ 0 => 'max',
284
+ 1 => 'page',
285
+ 2 => 'per_page',
286
+ 3 => 'sort',
287
+ 4 => 'search_terms',
288
+ 5 => 'filter',
289
+ 6 => 'display_comments',
290
+ 7 => 'show_hidden',
291
+ 8 => 'exclude',
292
+ 9 => 'in',
293
+ 10 => 'spam'
294
+ );
295
+
296
+ $func_args = func_get_args();
297
+ $args = bp_core_parse_args_array( $old_args_keys, $func_args );
298
+ }
299
+
300
+ $defaults = array(
301
+ 'page' => 1, // The current page
302
+ 'per_page' => 25, // Activity items per page
303
+ 'max' => false, // Max number of items to return
304
+ 'sort' => 'DESC', // ASC or DESC
305
+ 'exclude' => false, // Array of ids to exclude
306
+ 'in' => false, // Array of ids to limit query by (IN)
307
+ 'meta_query' => false, // Filter by activitymeta
308
+ 'filter' => false, // See self::get_filter_sql()
309
+ 'search_terms' => false, // Terms to search by
310
+ 'display_comments' => false, // Whether to include activity comments
311
+ 'show_hidden' => false, // Show items marked hide_sitewide
312
+ 'spam' => 'ham_only', // Spam status
313
+ 'update_meta_cache' => true,
314
+ );
315
+ $r = wp_parse_args( $args, $defaults );
316
+ extract( $r );
317
+
318
+ // Select conditions
319
+ $select_sql = "SELECT DISTINCT a.id";
320
+
321
+ $from_sql = " FROM {$bp->activity->table_name} a";
322
+
323
+ $join_sql = '';
324
+
325
+ // Where conditions
326
+ $where_conditions = array();
327
+
328
+ // Spam
329
+ if ( 'ham_only' == $spam )
330
+ $where_conditions['spam_sql'] = 'a.is_spam = 0';
331
+ elseif ( 'spam_only' == $spam )
332
+ $where_conditions['spam_sql'] = 'a.is_spam = 1';
333
+
334
+ // Searching
335
+ if ( $search_terms ) {
336
+ $search_terms = esc_sql( $search_terms );
337
+ $where_conditions['search_sql'] = "a.content LIKE '%%" . esc_sql( like_escape( $search_terms ) ) . "%%'";
338
+ }
339
+
340
+ // Filtering
341
+ if ( $filter && $filter_sql = BP_Activity_Activity::get_filter_sql( $filter ) )
342
+ $where_conditions['filter_sql'] = $filter_sql;
343
+
344
+ // Sorting
345
+ if ( $sort != 'ASC' && $sort != 'DESC' )
346
+ $sort = 'DESC';
347
+
348
+ // Hide Hidden Items?
349
+ if ( !$show_hidden )
350
+ $where_conditions['hidden_sql'] = "a.hide_sitewide = 0";
351
+
352
+ // Exclude specified items
353
+ if ( !empty( $exclude ) ) {
354
+ $exclude = implode( ',', wp_parse_id_list( $exclude ) );
355
+ $where_conditions['exclude'] = "a.id NOT IN ({$exclude})";
356
+ }
357
+
358
+ // The specific ids to which you want to limit the query
359
+ if ( !empty( $in ) ) {
360
+ $in = implode( ',', wp_parse_id_list( $in ) );
361
+ $where_conditions['in'] = "a.id IN ({$in})";
362
+ }
363
+
364
+ // Process meta_query into SQL
365
+ $meta_query_sql = self::get_meta_query_sql( $meta_query );
366
+
367
+ if ( ! empty( $meta_query_sql['join'] ) ) {
368
+ $join_sql .= $meta_query_sql['join'];
369
+ }
370
+
371
+ if ( ! empty( $meta_query_sql['where'] ) ) {
372
+ $where_conditions[] = $meta_query_sql['where'];
373
+ }
374
+
375
+ // Alter the query based on whether we want to show activity item
376
+ // comments in the stream like normal comments or threaded below
377
+ // the activity.
378
+ if ( false === $display_comments || 'threaded' === $display_comments ) {
379
+ $where_conditions[] = "a.type != 'activity_comment'";
380
+ }
381
+
382
+ // Exclude 'last_activity' items unless the 'action' filter has
383
+ // been explicitly set
384
+ if ( empty( $filter['object'] ) ) {
385
+ $where_conditions[] = "a.type != 'last_activity'";
386
+ }
387
+
388
+ // Filter the where conditions
389
+ $where_conditions = apply_filters( 'bp_activity_get_where_conditions', $where_conditions, $r, $select_sql, $from_sql, $join_sql );
390
+
391
+ // Join the where conditions together
392
+ $where_sql = 'WHERE ' . join( ' AND ', $where_conditions );
393
+
394
+ // Define the preferred order for indexes
395
+ $indexes = apply_filters( 'bp_activity_preferred_index_order', array( 'user_id', 'item_id', 'secondary_item_id', 'date_recorded', 'component', 'type', 'hide_sitewide', 'is_spam' ) );
396
+
397
+ foreach( $indexes as $key => $index ) {
398
+ if ( false !== strpos( $where_sql, $index ) ) {
399
+ $the_index = $index;
400
+ break; // Take the first one we find
401
+ }
402
+ }
403
+
404
+ if ( !empty( $the_index ) ) {
405
+ $index_hint_sql = "USE INDEX ({$the_index})";
406
+ } else {
407
+ $index_hint_sql = '';
408
+ }
409
+
410
+ // Sanitize page and per_page parameters
411
+ $page = absint( $page );
412
+ $per_page = absint( $per_page );
413
+
414
+ // Filter and return true to use the legacy query structure (not recommended)
415
+ if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, $r ) ) {
416
+
417
+ // Legacy queries joined against the user table
418
+ $select_sql = "SELECT DISTINCT a.*, u.user_email, u.user_nicename, u.user_login, u.display_name";
419
+ $from_sql = " FROM {$bp->activity->table_name} a LEFT JOIN {$wpdb->users} u ON a.user_id = u.ID";
420
+
421
+ if ( ! empty( $page ) && ! empty( $per_page ) ) {
422
+ $pag_sql = $wpdb->prepare( "LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page );
423
+ $activities = $wpdb->get_results( apply_filters( 'bp_activity_get_user_join_filter', "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort} {$pag_sql}", $select_sql, $from_sql, $where_sql, $sort, $pag_sql ) );
424
+ } else {
425
+ $activities = $wpdb->get_results( apply_filters( 'bp_activity_get_user_join_filter', "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}", $select_sql, $from_sql, $where_sql, $sort ) );
426
+ }
427
+
428
+ } else {
429
+
430
+ // Query first for activity IDs
431
+ $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}";
432
+
433
+ if ( ! empty( $per_page ) && ! empty( $page ) ) {
434
+ $activity_ids_sql .= $wpdb->prepare( " LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page );
435
+ }
436
+
437
+ $activity_ids_sql = apply_filters( 'bp_activity_paged_activities_sql', $activity_ids_sql, $r );
438
+
439
+ $activity_ids = $wpdb->get_col( $activity_ids_sql );
440
+ $activities = self::get_activity_data( $activity_ids );
441
+ }
442
+
443
+ $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
444
+ $total_activities = $wpdb->get_var( $total_activities_sql );
445
+
446
+ // Get the fullnames of users so we don't have to query in the loop
447
+ $activities = self::append_user_fullnames( $activities );
448
+
449
+ // Get activity meta
450
+ $activity_ids = array();
451
+ foreach ( (array) $activities as $activity ) {
452
+ $activity_ids[] = $activity->id;
453
+ }
454
+
455
+ if ( ! empty( $activity_ids ) && $update_meta_cache ) {
456
+ bp_activity_update_meta_cache( $activity_ids );
457
+ }
458
+
459
+ if ( $activities && $display_comments )
460
+ $activities = BP_Activity_Activity::append_comments( $activities, $spam );
461
+
462
+ // Pre-fetch data associated with activity users and other objects
463
+ BP_Activity_Activity::prefetch_object_data( $activities );
464
+
465
+ // Generate action strings
466
+ $activities = BP_Activity_Activity::generate_action_strings( $activities );
467
+
468
+ // If $max is set, only return up to the max results
469
+ if ( !empty( $max ) ) {
470
+ if ( (int) $total_activities > (int) $max )
471
+ $total_activities = $max;
472
+ }
473
+
474
+ return array( 'activities' => $activities, 'total' => (int) $total_activities );
475
+ }
476
+
477
+ /**
478
+ * Convert activity IDs to activity objects, as expected in template loop.
479
+ *
480
+ * @since 2.0
481
+ *
482
+ * @param array $activity_ids Array of activity IDs.
483
+ * @return array
484
+ */
485
+ protected static function get_activity_data( $activity_ids = array() ) {
486
+ global $wpdb;
487
+
488
+ // Bail if no activity ID's passed
489
+ if ( empty( $activity_ids ) ) {
490
+ return array();
491
+ }
492
+
493
+ // Get BuddyPress
494
+ $bp = buddypress();
495
+
496
+ $activities = array();
497
+ $uncached_ids = bp_get_non_cached_ids( $activity_ids, 'bp_activity' );
498
+
499
+ // Prime caches as necessary
500
+ if ( ! empty( $uncached_ids ) ) {
501
+ // Format the activity ID's for use in the query below
502
+ $uncached_ids_sql = implode( ',', wp_parse_id_list( $uncached_ids ) );
503
+
504
+ // Fetch data from activity table, preserving order
505
+ $queried_adata = $wpdb->get_results( "SELECT * FROM {$bp->activity->table_name} WHERE id IN ({$uncached_ids_sql})");
506
+
507
+ // Put that data into the placeholders created earlier,
508
+ // and add it to the cache
509
+ foreach ( (array) $queried_adata as $adata ) {
510
+ wp_cache_set( $adata->id, $adata, 'bp_activity' );
511
+ }
512
+ }
513
+
514
+ // Now fetch data from the cache
515
+ foreach ( $activity_ids as $activity_id ) {
516
+ $activities[] = wp_cache_get( $activity_id, 'bp_activity' );
517
+ }
518
+
519
+ // Then fetch user data
520
+ $user_query = new BP_User_Query( array(
521
+ 'user_ids' => wp_list_pluck( $activities, 'user_id' ),
522
+ 'populate_extras' => false,
523
+ ) );
524
+
525
+ // Associated located user data with activity items
526
+ foreach ( $activities as $a_index => $a_item ) {
527
+ $a_user_id = intval( $a_item->user_id );
528
+ $a_user = isset( $user_query->results[ $a_user_id ] ) ? $user_query->results[ $a_user_id ] : '';
529
+
530
+ if ( !empty( $a_user ) ) {
531
+ $activities[ $a_index ]->user_email = $a_user->user_email;
532
+ $activities[ $a_index ]->user_nicename = $a_user->user_nicename;
533
+ $activities[ $a_index ]->user_login = $a_user->user_login;
534
+ $activities[ $a_index ]->display_name = $a_user->display_name;
535
+ }
536
+ }
537
+
538
+ return $activities;
539
+ }
540
+
541
+ /**
542
+ * Append xProfile fullnames to an activity array.
543
+ *
544
+ * @since BuddyPress (2.0.0)
545
+ *
546
+ * @param array $activities Activities array.
547
+ * @return array
548
+ */
549
+ protected static function append_user_fullnames( $activities ) {
550
+ global $wpdb;
551
+
552
+ if ( bp_is_active( 'xprofile' ) && ! empty( $activities ) ) {
553
+ $activity_user_ids = wp_list_pluck( $activities, 'user_id' );
554
+
555
+ if ( ! empty( $activity_user_ids ) ) {
556
+ $fullnames = bp_core_get_user_displaynames( $activity_user_ids );
557
+ if ( ! empty( $fullnames ) ) {
558
+ foreach ( (array) $activities as $i => $activity ) {
559
+ if ( ! empty( $fullnames[ $activity->user_id ] ) ) {
560
+ $activities[ $i ]->user_fullname = $fullnames[ $activity->user_id ];
561
+ }
562
+ }
563
+ }
564
+ }
565
+ }
566
+
567
+ return $activities;
568
+ }
569
+
570
+ /**
571
+ * Pre-fetch data for objects associated with activity items.
572
+ *
573
+ * Activity items are associated with users, and often with other
574
+ * BuddyPress data objects. Here, we pre-fetch data about these
575
+ * associated objects, so that inline lookups - done primarily when
576
+ * building action strings - do not result in excess database queries.
577
+ *
578
+ * The only object data required for activity component activity types
579
+ * (activity_update and activity_comment) is related to users, and that
580
+ * info is fetched separately in BP_Activity_Activity::get_activity_data().
581
+ * So this method contains nothing but a filter that allows other
582
+ * components, such as bp-friends and bp-groups, to hook in and prime
583
+ * their own caches at the beginning of an activity loop.
584
+ *
585
+ * @since BuddyPress (2.0.0)
586
+ *
587
+ * @param array $activities Array of activities.
588
+ */
589
+ protected static function prefetch_object_data( $activities ) {
590
+ return apply_filters( 'bp_activity_prefetch_object_data', $activities );
591
+ }
592
+
593
+ /**
594
+ * Generate action strings for the activities located in BP_Activity_Activity::get().
595
+ *
596
+ * If no string can be dynamically generated for a given item
597
+ * (typically because the activity type has not been properly
598
+ * registered), the static 'action' value pulled from the database will
599
+ * be left in place.
600
+ *
601
+ * @since BuddyPress (2.0.0)
602
+ *
603
+ * @param array $activities Array of activities.
604
+ * @return array
605
+ */
606
+ protected static function generate_action_strings( $activities ) {
607
+ foreach ( $activities as $key => $activity ) {
608
+ $generated_action = bp_activity_generate_action_string( $activity );
609
+ if ( false !== $generated_action ) {
610
+ $activity->action = $generated_action;
611
+ }
612
+
613
+ $activities[ $key ] = $activity;
614
+ }
615
+
616
+ return $activities;
617
+ }
618
+
619
+ /**
620
+ * Get the SQL for the 'meta_query' param in BP_Activity_Activity::get().
621
+ *
622
+ * We use WP_Meta_Query to do the heavy lifting of parsing the
623
+ * meta_query array and creating the necessary SQL clauses. However,
624
+ * since BP_Activity_Activity::get() builds its SQL differently than
625
+ * WP_Query, we have to alter the return value (stripping the leading
626
+ * AND keyword from the 'where' clause).
627
+ *
628
+ * @since BuddyPress (1.8)
629
+ *
630
+ * @param array $meta_query An array of meta_query filters. See the
631
+ * documentation for WP_Meta_Query for details.
632
+ * @return array $sql_array 'join' and 'where' clauses.
633
+ */
634
+ public static function get_meta_query_sql( $meta_query = array() ) {
635
+ global $wpdb;
636
+
637
+ $sql_array = array(
638
+ 'join' => '',
639
+ 'where' => '',
640
+ );
641
+
642
+ if ( ! empty( $meta_query ) ) {
643
+ $activity_meta_query = new WP_Meta_Query( $meta_query );
644
+
645
+ // WP_Meta_Query expects the table name at
646
+ // $wpdb->activitymeta
647
+ $wpdb->activitymeta = buddypress()->activity->table_name_meta;
648
+
649
+ $meta_sql = $activity_meta_query->get_sql( 'activity', 'a', 'id' );
650
+
651
+ // Strip the leading AND - BP handles it in get()
652
+ $sql_array['where'] = preg_replace( '/^\sAND/', '', $meta_sql['where'] );
653
+ $sql_array['join'] = $meta_sql['join'];
654
+ }
655
+
656
+ return $sql_array;
657
+ }
658
+
659
+ /**
660
+ * In BuddyPress 1.2.x, this was used to retrieve specific activity stream items (for example, on an activity's permalink page).
661
+ *
662
+ * As of 1.5.x, use BP_Activity_Activity::get() with an 'in' parameter instead.
663
+ *
664
+ * @since BuddyPress (1.2)
665
+ *
666
+ * @deprecated 1.5
667
+ * @deprecated Use BP_Activity_Activity::get() with an 'in' parameter instead.
668
+ *
669
+ * @param mixed $activity_ids Array or comma-separated string of activity IDs to retrieve
670
+ * @param int $max Maximum number of results to return. (Optional; default is no maximum)
671
+ * @param int $page The set of results that the user is viewing. Used in pagination. (Optional; default is 1)
672
+ * @param int $per_page Specifies how many results per page. Used in pagination. (Optional; default is 25)
673
+ * @param string MySQL column sort; ASC or DESC. (Optional; default is DESC)
674
+ * @param bool $display_comments Retrieve an activity item's associated comments or not. (Optional; default is false)
675
+ * @return array
676
+ */
677
+ public static function get_specific( $activity_ids, $max = false, $page = 1, $per_page = 25, $sort = 'DESC', $display_comments = false ) {
678
+ _deprecated_function( __FUNCTION__, '1.5', 'Use BP_Activity_Activity::get() with the "in" parameter instead.' );
679
+ return BP_Activity_Activity::get( $max, $page, $per_page, $sort, false, false, $display_comments, false, false, $activity_ids );
680
+ }
681
+
682
+ /**
683
+ * Get the first activity ID that matches a set of criteria.
684
+ *
685
+ * @param int $user_id The user ID to filter by.
686
+ * @param string $component The component to filter by.
687
+ * @param string $type The activity type to filter by.
688
+ * @param int $item_id The associated item to filter by.
689
+ * @param int $secondary_item_id The secondary associated item to filter by.
690
+ * @param string $action The action to filter by.
691
+ * @param string $content The content to filter by.
692
+ * @param string $date_recorded The date to filter by.
693
+ * @return int|bool Activity ID on success, false if none is found.
694
+ */
695
+ public static function get_id( $user_id, $component, $type, $item_id, $secondary_item_id, $action, $content, $date_recorded ) {
696
+ global $bp, $wpdb;
697
+
698
+ $where_args = false;
699
+
700
+ if ( !empty( $user_id ) )
701
+ $where_args[] = $wpdb->prepare( "user_id = %d", $user_id );
702
+
703
+ if ( !empty( $component ) )
704
+ $where_args[] = $wpdb->prepare( "component = %s", $component );
705
+
706
+ if ( !empty( $type ) )
707
+ $where_args[] = $wpdb->prepare( "type = %s", $type );
708
+
709
+ if ( !empty( $item_id ) )
710
+ $where_args[] = $wpdb->prepare( "item_id = %d", $item_id );
711
+
712
+ if ( !empty( $secondary_item_id ) )
713
+ $where_args[] = $wpdb->prepare( "secondary_item_id = %d", $secondary_item_id );
714
+
715
+ if ( !empty( $action ) )
716
+ $where_args[] = $wpdb->prepare( "action = %s", $action );
717
+
718
+ if ( !empty( $content ) )
719
+ $where_args[] = $wpdb->prepare( "content = %s", $content );
720
+
721
+ if ( !empty( $date_recorded ) )
722
+ $where_args[] = $wpdb->prepare( "date_recorded = %s", $date_recorded );
723
+
724
+ if ( !empty( $where_args ) )
725
+ $where_sql = 'WHERE ' . join( ' AND ', $where_args );
726
+ else
727
+ return false;
728
+
729
+ return $wpdb->get_var( "SELECT id FROM {$bp->activity->table_name} {$where_sql}" );
730
+ }
731
+
732
+ /**
733
+ * Delete activity items from the database.
734
+ *
735
+ * To delete a specific activity item, pass an 'id' parameter.
736
+ * Otherwise use the filters.
737
+ *
738
+ * @since BuddyPress (1.2)
739
+ *
740
+ * @param array $args {
741
+ * @int $id Optional. The ID of a specific item to delete.
742
+ * @string $action Optional. The action to filter by.
743
+ * @string $content Optional. The content to filter by.
744
+ * @string $component Optional. The component name to filter by.
745
+ * @string $type Optional. The activity type to filter by.
746
+ * @string $primary_link Optional. The primary URL to filter by.
747
+ * @int $user_id Optional. The user ID to filter by.
748
+ * @int $item_id Optional. The associated item ID to filter by.
749
+ * @int $secondary_item_id Optional. The secondary associated item ID to filter by.
750
+ * @string $date_recorded Optional. The date to filter by.
751
+ * @int $hide_sitewide Optional. Default: false.
752
+ * }
753
+ * @return array|bool An array of deleted activity IDs on success, false on failure.
754
+ */
755
+ public static function delete( $args = array() ) {
756
+ global $wpdb, $bp;
757
+
758
+ $defaults = array(
759
+ 'id' => false,
760
+ 'action' => false,
761
+ 'content' => false,
762
+ 'component' => false,
763
+ 'type' => false,
764
+ 'primary_link' => false,
765
+ 'user_id' => false,
766
+ 'item_id' => false,
767
+ 'secondary_item_id' => false,
768
+ 'date_recorded' => false,
769
+ 'hide_sitewide' => false
770
+ );
771
+ $params = wp_parse_args( $args, $defaults );
772
+ extract( $params );
773
+
774
+ $where_args = false;
775
+
776
+ if ( !empty( $id ) )
777
+ $where_args[] = $wpdb->prepare( "id = %d", $id );
778
+
779
+ if ( !empty( $user_id ) )
780
+ $where_args[] = $wpdb->prepare( "user_id = %d", $user_id );
781
+
782
+ if ( !empty( $action ) )
783
+ $where_args[] = $wpdb->prepare( "action = %s", $action );
784
+
785
+ if ( !empty( $content ) )
786
+ $where_args[] = $wpdb->prepare( "content = %s", $content );
787
+
788
+ if ( !empty( $component ) )
789
+ $where_args[] = $wpdb->prepare( "component = %s", $component );
790
+
791
+ if ( !empty( $type ) )
792
+ $where_args[] = $wpdb->prepare( "type = %s", $type );
793
+
794
+ if ( !empty( $primary_link ) )
795
+ $where_args[] = $wpdb->prepare( "primary_link = %s", $primary_link );
796
+
797
+ if ( !empty( $item_id ) )
798
+ $where_args[] = $wpdb->prepare( "item_id = %d", $item_id );
799
+
800
+ if ( !empty( $secondary_item_id ) )
801
+ $where_args[] = $wpdb->prepare( "secondary_item_id = %d", $secondary_item_id );
802
+
803
+ if ( !empty( $date_recorded ) )
804
+ $where_args[] = $wpdb->prepare( "date_recorded = %s", $date_recorded );
805
+
806
+ if ( !empty( $hide_sitewide ) )
807
+ $where_args[] = $wpdb->prepare( "hide_sitewide = %d", $hide_sitewide );
808
+
809
+ if ( !empty( $where_args ) )
810
+ $where_sql = 'WHERE ' . join( ' AND ', $where_args );
811
+ else
812
+ return false;
813
+
814
+ // Fetch the activity IDs so we can delete any comments for this activity item
815
+ $activity_ids = $wpdb->get_col( "SELECT id FROM {$bp->activity->table_name} {$where_sql}" );
816
+
817
+ if ( ! $wpdb->query( "DELETE FROM {$bp->activity->table_name} {$where_sql}" ) ) {
818
+ return false;
819
+ }
820
+
821
+ // Handle accompanying activity comments and meta deletion
822
+ if ( $activity_ids ) {
823
+ $activity_ids_comma = implode( ',', wp_parse_id_list( $activity_ids ) );
824
+ $activity_comments_where_sql = "WHERE type = 'activity_comment' AND item_id IN ({$activity_ids_comma})";
825
+
826
+ // Fetch the activity comment IDs for our deleted activity items
827
+ $activity_comment_ids = $wpdb->get_col( "SELECT id FROM {$bp->activity->table_name} {$activity_comments_where_sql}" );
828
+
829
+ // We have activity comments!
830
+ if ( ! empty( $activity_comment_ids ) ) {
831
+ // Delete activity comments
832
+ $wpdb->query( "DELETE FROM {$bp->activity->table_name} {$activity_comments_where_sql}" );
833
+
834
+ // Merge activity IDs with activity comment IDs
835
+ $activity_ids = array_merge( $activity_ids, $activity_comment_ids );
836
+ }
837
+
838
+ // Delete all activity meta entries for activity items and activity comments
839
+ BP_Activity_Activity::delete_activity_meta_entries( $activity_ids );
840
+ }
841
+
842
+ return $activity_ids;
843
+ }
844
+
845
+ /**
846
+ * Delete the comments associated with a set of activity items.
847
+ *
848
+ * @since BuddyPress (1.2)
849
+ *
850
+ * @todo Mark as deprecated? Method is no longer used internally.
851
+ *
852
+ * @param array $activity_ids Activity IDs whose comments should be deleted.
853
+ * @param bool $delete_meta Should we delete the activity meta items for these comments?
854
+ * @return bool True on success.
855
+ */
856
+ public static function delete_activity_item_comments( $activity_ids = array(), $delete_meta = true ) {
857
+ global $bp, $wpdb;
858
+
859
+ $delete_meta = (bool) $delete_meta;
860
+
861
+ $activity_ids = implode( ',', wp_parse_id_list( $activity_ids ) );
862
+
863
+ if ( $delete_meta ) {
864
+ // Fetch the activity comment IDs for our deleted activity items
865
+ $activity_comment_ids = $wpdb->get_col( "SELECT id FROM {$bp->activity->table_name} WHERE type = 'activity_comment' AND item_id IN ({$activity_ids})" );
866
+
867
+ if ( ! empty( $activity_comment_ids ) ) {
868
+ self::delete_activity_meta_entries( $activity_comment_ids );
869
+ }
870
+ }
871
+
872
+ return $wpdb->query( "DELETE FROM {$bp->activity->table_name} WHERE type = 'activity_comment' AND item_id IN ({$activity_ids})" );
873
+ }
874
+
875
+ /**
876
+ * Delete the meta entries associated with a set of activity items.
877
+ *
878
+ * @since BuddyPress (1.2)
879
+ *
880
+ * @param array $activity_ids Activity IDs whose meta should be deleted.
881
+ * @return bool True on success.
882
+ */
883
+ public static function delete_activity_meta_entries( $activity_ids = array() ) {
884
+ $activity_ids = wp_parse_id_list( $activity_ids );
885
+
886
+ foreach ( $activity_ids as $activity_id ) {
887
+ bp_activity_delete_meta( $activity_id );
888
+ }
889
+
890
+ return true;
891
+ }
892
+
893
+ /**
894
+ * Append activity comments to their associated activity items.
895
+ *
896
+ * @since BuddyPress (1.2)
897
+ *
898
+ * @global wpdb $wpdb WordPress database object
899
+ *
900
+ * @param array $activities Activities to fetch comments for.
901
+ * @param bool $spam Optional. 'ham_only' (default), 'spam_only' or 'all'.
902
+ * @return array The updated activities with nested comments.
903
+ */
904
+ public static function append_comments( $activities, $spam = 'ham_only' ) {
905
+ $activity_comments = array();
906
+
907
+ // Now fetch the activity comments and parse them into the correct position in the activities array.
908
+ foreach ( (array) $activities as $activity ) {
909
+ $top_level_parent_id = 'activity_comment' == $activity->type ? $activity->item_id : 0;
910
+ $activity_comments[$activity->id] = BP_Activity_Activity::get_activity_comments( $activity->id, $activity->mptt_left, $activity->mptt_right, $spam, $top_level_parent_id );
911
+ }
912
+
913
+ // Merge the comments with the activity items
914
+ foreach ( (array) $activities as $key => $activity ) {
915
+ if ( isset( $activity_comments[$activity->id] ) ) {
916
+ $activities[$key]->children = $activity_comments[$activity->id];
917
+ }
918
+ }
919
+
920
+ return $activities;
921
+ }
922
+
923
+ /**
924
+ * Get activity comments that are associated with a specific activity ID.
925
+ *
926
+ * @since BuddyPress (1.2)
927
+ *
928
+ * @global BuddyPress $bp The one true BuddyPress instance.
929
+ * @global wpdb $wpdb WordPress database object.
930
+ *
931
+ * @param int $activity_id Activity ID to fetch comments for.
932
+ * @param int $left Left-most node boundary.
933
+ * @param into $right Right-most node boundary.
934
+ * @param bool $spam Optional. 'ham_only' (default), 'spam_only' or 'all'.
935
+ * @param int $top_level_parent_id Optional. The id of the root-level parent activity item.
936
+ * @return array The updated activities with nested comments.
937
+ */
938
+ public static function get_activity_comments( $activity_id, $left, $right, $spam = 'ham_only', $top_level_parent_id = 0 ) {
939
+ global $wpdb, $bp;
940
+
941
+ if ( empty( $top_level_parent_id ) ) {
942
+ $top_level_parent_id = $activity_id;
943
+ }
944
+
945
+ $comments = wp_cache_get( $activity_id, 'bp_activity_comments' );
946
+
947
+ // We store the string 'none' to cache the fact that the
948
+ // activity item has no comments
949
+ if ( 'none' === $comments ) {
950
+ $comments = false;
951
+
952
+ // A true cache miss
953
+ } else if ( empty( $comments ) ) {
954
+
955
+ // Select the user's fullname with the query
956
+ if ( bp_is_active( 'xprofile' ) ) {
957
+ $fullname_select = ", pd.value as user_fullname";
958
+ $fullname_from = ", {$bp->profile->table_name_data} pd ";
959
+ $fullname_where = "AND pd.user_id = a.user_id AND pd.field_id = 1";
960
+
961
+ // Prevent debug errors
962
+ } else {
963
+ $fullname_select = $fullname_from = $fullname_where = '';
964
+ }
965
+
966
+ // Don't retrieve activity comments marked as spam
967
+ if ( 'ham_only' == $spam ) {
968
+ $spam_sql = 'AND a.is_spam = 0';
969
+ } elseif ( 'spam_only' == $spam ) {
970
+ $spam_sql = 'AND a.is_spam = 1';
971
+ } else {
972
+ $spam_sql = '';
973
+ }
974
+
975
+ // Legacy query - not recommended
976
+ $func_args = func_get_args();
977
+ if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, $func_args ) ) {
978
+ $sql = apply_filters( 'bp_activity_comments_user_join_filter', $wpdb->prepare( "SELECT a.*, u.user_email, u.user_nicename, u.user_login, u.display_name{$fullname_select} FROM {$bp->activity->table_name} a, {$wpdb->users} u{$fullname_from} WHERE u.ID = a.user_id {$fullname_where} AND a.type = 'activity_comment' {$spam_sql} AND a.item_id = %d AND a.mptt_left > %d AND a.mptt_left < %d ORDER BY a.date_recorded ASC", $top_level_parent_id, $left, $right ), $activity_id, $left, $right, $spam_sql );
979
+
980
+ $descendants = $wpdb->get_results( $sql );
981
+
982
+ // We use the mptt BETWEEN clause to limit returned
983
+ // descendants to the correct part of the tree.
984
+ } else {
985
+ $sql = $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} a WHERE a.type = 'activity_comment' {$spam_sql} AND a.item_id = %d and a.mptt_left > %d AND a.mptt_left < %d ORDER BY a.date_recorded ASC", $top_level_parent_id, $left, $right );
986
+
987
+ $descendant_ids = $wpdb->get_col( $sql );
988
+ $descendants = self::get_activity_data( $descendant_ids );
989
+ $descendants = self::append_user_fullnames( $descendants );
990
+ }
991
+
992
+ $ref = array();
993
+
994
+ // Loop descendants and build an assoc array
995
+ foreach ( (array) $descendants as $d ) {
996
+ $d->children = array();
997
+
998
+ // If we have a reference on the parent
999
+ if ( isset( $ref[ $d->secondary_item_id ] ) ) {
1000
+ $ref[ $d->secondary_item_id ]->children[ $d->id ] = $d;
1001
+ $ref[ $d->id ] =& $ref[ $d->secondary_item_id ]->children[ $d->id ];
1002
+
1003
+ // If we don't have a reference on the parent, put in the root level
1004
+ } else {
1005
+ $comments[ $d->id ] = $d;
1006
+ $ref[ $d->id ] =& $comments[ $d->id ];
1007
+ }
1008
+ }
1009
+
1010
+ // Calculate depth for each item
1011
+ foreach ( $ref as &$r ) {
1012
+ $depth = 1;
1013
+ $parent_id = $r->secondary_item_id;
1014
+ while ( $parent_id !== $r->item_id ) {
1015
+ $depth++;
1016
+
1017
+ // When display_comments=stream, the
1018
+ // parent comment may not be part of
1019
+ // the returned results, so we manually
1020
+ // fetch it
1021
+ if ( empty( $ref[ $parent_id ] ) ) {
1022
+ $direct_parent = new BP_Activity_Activity( $parent_id );
1023
+ if ( isset( $direct_parent->secondary_item_id ) ) {
1024
+ $parent_id = $direct_parent->secondary_item_id;
1025
+ } else {
1026
+ // Something went wrong
1027
+ // Short-circuit the
1028
+ // depth calculation
1029
+ $parent_id = $r->item_id;
1030
+ }
1031
+ } else {
1032
+ $parent_id = $ref[ $parent_id ]->secondary_item_id;
1033
+ }
1034
+ }
1035
+ $r->depth = $depth;
1036
+ }
1037
+
1038
+ // If we cache a value of false, it'll count as a cache
1039
+ // miss the next time the activity comments are fetched.
1040
+ // Storing the string 'none' is a hack workaround to
1041
+ // avoid unnecessary queries.
1042
+ if ( false === $comments ) {
1043
+ $cache_value = 'none';
1044
+ } else {
1045
+ $cache_value = $comments;
1046
+ }
1047
+
1048
+ wp_cache_set( $activity_id, $cache_value, 'bp_activity_comments' );
1049
+ }
1050
+
1051
+ return $comments;
1052
+ }
1053
+
1054
+ /**
1055
+ * Rebuild nested comment tree under an activity or activity comment.
1056
+ *
1057
+ * @since BuddyPress (1.2)
1058
+ *
1059
+ * @global BuddyPress $bp The one true BuddyPress instance.
1060
+ * @global wpdb $wpdb WordPress database object.
1061
+ *
1062
+ * @param int $parent_id ID of an activty or activity comment.
1063
+ * @param int $left Node boundary start for activity or activity comment.
1064
+ * @return int Right node boundary of activity or activity comment.
1065
+ */
1066
+ public static function rebuild_activity_comment_tree( $parent_id, $left = 1 ) {
1067
+ global $wpdb, $bp;
1068
+
1069
+ // The right value of this node is the left value + 1
1070
+ $right = $left + 1;
1071
+
1072
+ // Get all descendants of this node
1073
+ $descendants = BP_Activity_Activity::get_child_comments( $parent_id );
1074
+
1075
+ // Loop the descendants and recalculate the left and right values
1076
+ foreach ( (array) $descendants as $descendant )
1077
+ $right = BP_Activity_Activity::rebuild_activity_comment_tree( $descendant->id, $right );
1078
+
1079
+ // We've got the left value, and now that we've processed the children
1080
+ // of this node we also know the right value
1081
+ if ( 1 == $left )
1082
+ $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET mptt_left = %d, mptt_right = %d WHERE id = %d", $left, $right, $parent_id ) );
1083
+ else
1084
+ $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET mptt_left = %d, mptt_right = %d WHERE type = 'activity_comment' AND id = %d", $left, $right, $parent_id ) );
1085
+
1086
+ // Return the right value of this node + 1
1087
+ return $right + 1;
1088
+ }
1089
+
1090
+ /**
1091
+ * Get child comments of an activity or activity comment.
1092
+ *
1093
+ * @since BuddyPress (1.2)
1094
+ *
1095
+ * @global BuddyPress $bp The one true BuddyPress instance.
1096
+ * @global wpdb $wpdb WordPress database object.
1097
+ *
1098
+ * @param int $parent_id ID of an activty or activity comment.
1099
+ * @return object Numerically indexed array of child comments.
1100
+ */
1101
+ public static function get_child_comments( $parent_id ) {
1102
+ global $bp, $wpdb;
1103
+
1104
+ return $wpdb->get_results( $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} WHERE type = 'activity_comment' AND secondary_item_id = %d", $parent_id ) );
1105
+ }
1106
+
1107
+ /**
1108
+ * Get a list of components that have recorded activity associated with them.
1109
+ *
1110
+ * @param bool $skip_last_activity If true, components will not be
1111
+ * included if the only activity type associated with them is
1112
+ * 'last_activity'. (Since 2.0.0, 'last_activity' is stored in
1113
+ * the activity table, but these items are not full-fledged
1114
+ * activity items.) Default: true.
1115
+ * @return array List of component names.
1116
+ */
1117
+ public static function get_recorded_components( $skip_last_activity = true ) {
1118
+ global $wpdb, $bp;
1119
+
1120
+ if ( $skip_last_activity ) {
1121
+ $components = $wpdb->get_col( "SELECT DISTINCT component FROM {$bp->activity->table_name} WHERE action != '' AND action != 'last_activity' ORDER BY component ASC" );
1122
+ } else {
1123
+ $components = $wpdb->get_col( "SELECT DISTINCT component FROM {$bp->activity->table_name} ORDER BY component ASC" );
1124
+ }
1125
+
1126
+ return $components;
1127
+ }
1128
+
1129
+ /**
1130
+ * Get sitewide activity items for use in an RSS feed.
1131
+ *
1132
+ * @param int $limit Optional. Number of items to fetch. Default: 35.
1133
+ * @return array $activity_feed List of activity items, with RSS data added.
1134
+ */
1135
+ public static function get_sitewide_items_for_feed( $limit = 35 ) {
1136
+ $activities = bp_activity_get_sitewide( array( 'max' => $limit ) );
1137
+ $activity_feed = array();
1138
+
1139
+ for ( $i = 0, $count = count( $activities ); $i < $count; ++$i ) {
1140
+ $title = explode( '<span', $activities[$i]['content'] );
1141
+ $activity_feed[$i]['title'] = trim( strip_tags( $title[0] ) );
1142
+ $activity_feed[$i]['link'] = $activities[$i]['primary_link'];
1143
+ $activity_feed[$i]['description'] = @sprintf( $activities[$i]['content'], '' );
1144
+ $activity_feed[$i]['pubdate'] = $activities[$i]['date_recorded'];
1145
+ }
1146
+
1147
+ return $activity_feed;
1148
+ }
1149
+
1150
+ /**
1151
+ * Create SQL IN clause for filter queries.
1152
+ *
1153
+ * @since BuddyPress (1.5)
1154
+ *
1155
+ * @see BP_Activity_Activity::get_filter_sql()
1156
+ *
1157
+ * @param string $field The database field.
1158
+ * @param array|bool $items The values for the IN clause, or false when none are found.
1159
+ */
1160
+ public static function get_in_operator_sql( $field, $items ) {
1161
+ global $wpdb;
1162
+
1163
+ // split items at the comma
1164
+ if ( ! is_array( $items ) ) {
1165
+ $items = explode( ',', $items );
1166
+ }
1167
+
1168
+ // array of prepared integers or quoted strings
1169
+ $items_prepared = array();
1170
+
1171
+ // clean up and format each item
1172
+ foreach ( $items as $item ) {
1173
+ // clean up the string
1174
+ $item = trim( $item );
1175
+ // pass everything through prepare for security and to safely quote strings
1176
+ $items_prepared[] = ( is_numeric( $item ) ) ? $wpdb->prepare( '%d', $item ) : $wpdb->prepare( '%s', $item );
1177
+ }
1178
+
1179
+ // build IN operator sql syntax
1180
+ if ( count( $items_prepared ) )
1181
+ return sprintf( '%s IN ( %s )', trim( $field ), implode( ',', $items_prepared ) );
1182
+ else
1183
+ return false;
1184
+ }
1185
+
1186
+ /**
1187
+ * Create filter SQL clauses.
1188
+ *
1189
+ * @since BuddyPress (1.5.0)
1190
+ *
1191
+ * @param array $filter_array {
1192
+ * Fields and values to filter by.
1193
+ * @type array|string|id $user_id User ID(s).
1194
+ * @type array|string $object Corresponds to the 'component'
1195
+ * column in the database.
1196
+ * @type array|string $action Corresponds to the 'type' column
1197
+ * in the database.
1198
+ * @type array|string|int $primary_id Corresponds to the 'item_id'
1199
+ * column in the database.
1200
+ * @type array|string|int $secondary_id Corresponds to the
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.
1207
+ * }
1208
+ * @return string The filter clause, for use in a SQL query.
1209
+ */
1210
+ public static function get_filter_sql( $filter_array ) {
1211
+
1212
+ $filter_sql = array();
1213
+
1214
+ if ( !empty( $filter_array['user_id'] ) ) {
1215
+ $user_sql = BP_Activity_Activity::get_in_operator_sql( 'a.user_id', $filter_array['user_id'] );
1216
+ if ( !empty( $user_sql ) )
1217
+ $filter_sql[] = $user_sql;
1218
+ }
1219
+
1220
+ if ( !empty( $filter_array['object'] ) ) {
1221
+ $object_sql = BP_Activity_Activity::get_in_operator_sql( 'a.component', $filter_array['object'] );
1222
+ if ( !empty( $object_sql ) )
1223
+ $filter_sql[] = $object_sql;
1224
+ }
1225
+
1226
+ if ( !empty( $filter_array['action'] ) ) {
1227
+ $action_sql = BP_Activity_Activity::get_in_operator_sql( 'a.type', $filter_array['action'] );
1228
+ if ( ! empty( $action_sql ) )
1229
+ $filter_sql[] = $action_sql;
1230
+ }
1231
+
1232
+ if ( !empty( $filter_array['primary_id'] ) ) {
1233
+ $pid_sql = BP_Activity_Activity::get_in_operator_sql( 'a.item_id', $filter_array['primary_id'] );
1234
+ if ( !empty( $pid_sql ) )
1235
+ $filter_sql[] = $pid_sql;
1236
+ }
1237
+
1238
+ if ( !empty( $filter_array['secondary_id'] ) ) {
1239
+ $sid_sql = BP_Activity_Activity::get_in_operator_sql( 'a.secondary_item_id', $filter_array['secondary_id'] );
1240
+ if ( !empty( $sid_sql ) )
1241
+ $filter_sql[] = $sid_sql;
1242
+ }
1243
+
1244
+ if ( ! empty( $filter_array['offset'] ) ) {
1245
+ $sid_sql = absint( $filter_array['offset'] );
1246
+ $filter_sql[] = "a.id >= {$sid_sql}";
1247
+ }
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
+
1258
+ if ( empty( $filter_sql ) )
1259
+ return false;
1260
+
1261
+ return join( ' AND ', $filter_sql );
1262
+ }
1263
+
1264
+ /**
1265
+ * Get the date/time of last recorded activity.
1266
+ *
1267
+ * @since BuddyPress (1.2)
1268
+ *
1269
+ * @return string ISO timestamp.
1270
+ */
1271
+ public static function get_last_updated() {
1272
+ global $bp, $wpdb;
1273
+
1274
+ return $wpdb->get_var( "SELECT date_recorded FROM {$bp->activity->table_name} ORDER BY date_recorded DESC LIMIT 1" );
1275
+ }
1276
+
1277
+ /**
1278
+ * Get favorite count for a given user.
1279
+ *
1280
+ * @since BuddyPress (1.2)
1281
+ *
1282
+ * @param int The ID of the user whose favorites you're counting.
1283
+ * @return int A count of the user's favorites.
1284
+ */
1285
+ public static function total_favorite_count( $user_id ) {
1286
+ if ( !$favorite_activity_entries = bp_get_user_meta( $user_id, 'bp_favorite_activities', true ) )
1287
+ return 0;
1288
+
1289
+ return count( maybe_unserialize( $favorite_activity_entries ) );
1290
+ }
1291
+
1292
+ /**
1293
+ * Check whether an activity item exists with a given string content.
1294
+ *
1295
+ * @param string $content The content to filter by.
1296
+ * @return int|bool The ID of the first matching item if found, otherwise false.
1297
+ */
1298
+ public static function check_exists_by_content( $content ) {
1299
+ global $wpdb, $bp;
1300
+
1301
+ return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} WHERE content = %s", $content ) );
1302
+ }
1303
+
1304
+ /**
1305
+ * Hide all activity for a given user.
1306
+ *
1307
+ * @param int $user_id The ID of the user whose activity you want to mark hidden.
1308
+ * @param int
1309
+ */
1310
+ public static function hide_all_for_user( $user_id ) {
1311
+ global $wpdb, $bp;
1312
+
1313
+ return $wpdb->get_var( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET hide_sitewide = 1 WHERE user_id = %d", $user_id ) );
1314
+ }
1315
+ }
1316
+
1317
+ /**
1318
+ * Create a RSS feed using the activity component.
1319
+ *
1320
+ * You should only construct a new feed when you've validated that you're on
1321
+ * the appropriate screen.
1322
+ *
1323
+ * See {@link bp_activity_action_sitewide_feed()} as an example.
1324
+ *
1325
+ * Accepted parameters:
1326
+ * id - internal id for the feed; should be alphanumeric only
1327
+ * (required)
1328
+ * title - RSS feed title
1329
+ * link - Relevant link for the RSS feed
1330
+ * description - RSS feed description
1331
+ * ttl - Time-to-live (see inline doc in constructor)
1332
+ * update_period - Part of the syndication module (see inline doc in
1333
+ * constructor for more info)
1334
+ * update_frequency - Part of the syndication module (see inline doc in
1335
+ * constructor for more info)
1336
+ * max - Number of feed items to display
1337
+ * activity_args - Arguments passed to {@link bp_has_activities()}
1338
+ *
1339
+ * @since BuddyPress (1.8)
1340
+ */
1341
+ class BP_Activity_Feed {
1342
+ /**
1343
+ * Holds our custom class properties.
1344
+ *
1345
+ * These variables are stored in a protected array that is magically
1346
+ * updated using PHP 5.2+ methods.
1347
+ *
1348
+ * @see BP_Feed::__construct() This is where $data is added
1349
+ * @var array
1350
+ */
1351
+ protected $data;
1352
+
1353
+ /**
1354
+ * Magic method for checking the existence of a certain data variable.
1355
+ *
1356
+ * @param string $key
1357
+ */
1358
+ public function __isset( $key ) { return isset( $this->data[$key] ); }
1359
+
1360
+ /**
1361
+ * Magic method for getting a certain data variable.
1362
+ *
1363
+ * @param string $key
1364
+ */
1365
+ public function __get( $key ) { return isset( $this->data[$key] ) ? $this->data[$key] : null; }
1366
+
1367
+ /**
1368
+ * Constructor.
1369
+ *
1370
+ * @param array $args Optional
1371
+ */
1372
+ public function __construct( $args = array() ) {
1373
+ // If feeds are disabled, stop now!
1374
+ if ( false === (bool) apply_filters( 'bp_activity_enable_feeds', true ) ) {
1375
+ global $wp_query;
1376
+
1377
+ // set feed flag to false
1378
+ $wp_query->is_feed = false;
1379
+
1380
+ return false;
1381
+ }
1382
+
1383
+ // Setup data
1384
+ $this->data = wp_parse_args( $args, array(
1385
+ // Internal identifier for the RSS feed - should be alphanumeric only
1386
+ 'id' => '',
1387
+
1388
+ // RSS title - should be plain-text
1389
+ 'title' => '',
1390
+
1391
+ // relevant link for the RSS feed
1392
+ 'link' => '',
1393
+
1394
+ // RSS description - should be plain-text
1395
+ 'description' => '',
1396
+
1397
+ // Time-to-live - number of minutes to cache the data before an aggregator
1398
+ // requests it again. This is only acknowledged if the RSS client supports it
1399
+ //
1400
+ // See: http://www.rssboard.org/rss-profile#element-channel-ttl
1401
+ // http://www.kbcafe.com/rss/rssfeedstate.html#ttl
1402
+ 'ttl' => '30',
1403
+
1404
+ // Syndication module - similar to ttl, but not really supported by RSS
1405
+ // clients
1406
+ //
1407
+ // See: http://web.resource.org/rss/1.0/modules/syndication/#description
1408
+ // http://www.kbcafe.com/rss/rssfeedstate.html#syndicationmodule
1409
+ 'update_period' => 'hourly',
1410
+ 'update_frequency' => 2,
1411
+
1412
+ // Number of items to display
1413
+ 'max' => 50,
1414
+
1415
+ // Activity arguments passed to bp_has_activities()
1416
+ 'activity_args' => array()
1417
+ ) );
1418
+
1419
+ // Plugins can use this filter to modify the feed before it is setup
1420
+ do_action_ref_array( 'bp_activity_feed_prefetch', array( &$this ) );
1421
+
1422
+ // Setup class properties
1423
+ $this->setup_properties();
1424
+
1425
+ // Check if id is valid
1426
+ if ( empty( $this->id ) ) {
1427
+ _doing_it_wrong( 'BP_Activity_Feed', __( "RSS feed 'id' must be defined", 'buddypress' ), 'BP 1.8' );
1428
+ return false;
1429
+ }
1430
+
1431
+ // Plugins can use this filter to modify the feed after it's setup
1432
+ do_action_ref_array( 'bp_activity_feed_postfetch', array( &$this ) );
1433
+
1434
+ // Setup feed hooks
1435
+ $this->setup_hooks();
1436
+
1437
+ // Output the feed
1438
+ $this->output();
1439
+
1440
+ // Kill the rest of the output
1441
+ die();
1442
+ }
1443
+
1444
+ /** SETUP ****************************************************************/
1445
+
1446
+ /**
1447
+ * Setup and validate the class properties.
1448
+ *
1449
+ * @access protected
1450
+ */
1451
+ protected function setup_properties() {
1452
+ $this->id = sanitize_title( $this->id );
1453
+ $this->title = strip_tags( $this->title );
1454
+ $this->link = esc_url_raw( $this->link );
1455
+ $this->description = strip_tags( $this->description );
1456
+ $this->ttl = (int) $this->ttl;
1457
+ $this->update_period = strip_tags( $this->update_period );
1458
+ $this->update_frequency = (int) $this->update_frequency;
1459
+
1460
+ $this->activity_args = wp_parse_args( $this->activity_args, array(
1461
+ 'max' => $this->max,
1462
+ 'per_page' => $this->max,
1463
+ 'display_comments' => 'stream'
1464
+ ) );
1465
+
1466
+ }
1467
+
1468
+ /**
1469
+ * Setup some hooks that are used in the feed.
1470
+ *
1471
+ * Currently, these hooks are used to maintain backwards compatibility with
1472
+ * the RSS feeds previous to BP 1.8.
1473
+ *
1474
+ * @access protected
1475
+ */
1476
+ protected function setup_hooks() {
1477
+ add_action( 'bp_activity_feed_rss_attributes', array( $this, 'backpat_rss_attributes' ) );
1478
+ add_action( 'bp_activity_feed_channel_elements', array( $this, 'backpat_channel_elements' ) );
1479
+ add_action( 'bp_activity_feed_item_elements', array( $this, 'backpat_item_elements' ) );
1480
+ }
1481
+
1482
+ /** BACKPAT HOOKS ********************************************************/
1483
+
1484
+ /**
1485
+ * Fire a hook to ensure backward compatibility for RSS attributes.
1486
+ */
1487
+ public function backpat_rss_attributes() {
1488
+ do_action( 'bp_activity_' . $this->id . '_feed' );
1489
+ }
1490
+
1491
+ /**
1492
+ * Fire a hook to ensure backward compatibility for channel elements.
1493
+ */
1494
+ public function backpat_channel_elements() {
1495
+ do_action( 'bp_activity_' . $this->id . '_feed_head' );
1496
+ }
1497
+
1498
+ /**
1499
+ * Fire a hook to ensure backward compatibility for item elements.
1500
+ */
1501
+ public function backpat_item_elements() {
1502
+ switch ( $this->id ) {
1503
+
1504
+ // sitewide and friends feeds use the 'personal' hook
1505
+ case 'sitewide' :
1506
+ case 'friends' :
1507
+ $id = 'personal';
1508
+
1509
+ break;
1510
+
1511
+ default :
1512
+ $id = $this->id;
1513
+
1514
+ break;
1515
+ }
1516
+
1517
+ do_action( 'bp_activity_' . $id . '_feed_item' );
1518
+ }
1519
+
1520
+ /** HELPERS **************************************************************/
1521
+
1522
+ /**
1523
+ * Output the feed's item content.
1524
+ *
1525
+ * @access protected
1526
+ */
1527
+ protected function feed_content() {
1528
+ bp_activity_content_body();
1529
+
1530
+ switch ( $this->id ) {
1531
+
1532
+ // also output parent activity item if we're on a specific feed
1533
+ case 'favorites' :
1534
+ case 'friends' :
1535
+ case 'mentions' :
1536
+ case 'personal' :
1537
+
1538
+ if ( 'activity_comment' == bp_get_activity_action_name() ) :
1539
+ ?>
1540
+ <strong><?php _e( 'In reply to', 'buddypress' ) ?></strong> -
1541
+ <?php bp_activity_parent_content() ?>
1542
+ <?php
1543
+ endif;
1544
+
1545
+ break;
1546
+ }
1547
+ }
1548
+
1549
+ /**
1550
+ * Sets various HTTP headers related to Content-Type and browser caching.
1551
+ *
1552
+ * Most of this class method is derived from {@link WP::send_headers()}.
1553
+ *
1554
+ * @since BuddyPress (1.9.0)
1555
+ *
1556
+ * @access protected
1557
+ */
1558
+ protected function http_headers() {
1559
+ // set up some additional headers if not on a directory page
1560
+ // this is done b/c BP uses pseudo-pages
1561
+ if ( ! bp_is_directory() ) {
1562
+ global $wp_query;
1563
+
1564
+ $wp_query->is_404 = false;
1565
+ status_header( 200 );
1566
+ }
1567
+
1568
+ // Set content-type
1569
+ @header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
1570
+
1571
+ // Cache-related variables
1572
+ $last_modified = mysql2date( 'D, d M Y H:i:s O', bp_activity_get_last_updated(), false );
1573
+ $modified_timestamp = strtotime( $last_modified );
1574
+ $etag = md5( $last_modified );
1575
+
1576
+ // Set cache-related headers
1577
+ @header( 'Last-Modified: ' . $last_modified );
1578
+ @header( 'Pragma: no-cache' );
1579
+ @header( 'ETag: ' . '"' . $etag . '"' );
1580
+
1581
+ // First commit of BuddyPress! (Easter egg)
1582
+ @header( 'Expires: Tue, 25 Mar 2008 17:13:55 GMT');
1583
+
1584
+ // Get ETag from supported user agents
1585
+ if ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ) {
1586
+ $client_etag = wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] );
1587
+
1588
+ // Remove quotes from ETag
1589
+ $client_etag = trim( $client_etag, '"' );
1590
+
1591
+ // Strip suffixes from ETag if they exist (eg. "-gzip")
1592
+ if ( $etag_suffix_pos = strpos( $client_etag, '-' ) ) {
1593
+ $client_etag = substr( $client_etag, 0, $etag_suffix_pos );
1594
+ }
1595
+
1596
+ // No ETag found
1597
+ } else {
1598
+ $client_etag = false;
1599
+ }
1600
+
1601
+ // Get client last modified timestamp from supported user agents
1602
+ $client_last_modified = empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ? '' : trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
1603
+ $client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;
1604
+
1605
+ // Set 304 status if feed hasn't been updated since last fetch
1606
+ if ( ( $client_last_modified && $client_etag ) ?
1607
+ ( ( $client_modified_timestamp >= $modified_timestamp ) && ( $client_etag == $etag ) ) :
1608
+ ( ( $client_modified_timestamp >= $modified_timestamp ) || ( $client_etag == $etag ) ) ) {
1609
+ $status = 304;
1610
+ } else {
1611
+ $status = false;
1612
+ }
1613
+
1614
+ // If feed hasn't changed as reported by the user agent, set 304 status header
1615
+ if ( ! empty( $status ) ) {
1616
+ status_header( $status );
1617
+
1618
+ // cached response, so stop now!
1619
+ if ( $status == 304 ) {
1620
+ exit();
1621
+ }
1622
+ }
1623
+ }
1624
+
1625
+ /** OUTPUT ***************************************************************/
1626
+
1627
+ /**
1628
+ * Output the RSS feed.
1629
+ *
1630
+ * @access protected
1631
+ */
1632
+ protected function output() {
1633
+ $this->http_headers();
1634
+ echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?'.'>';
1635
+ ?>
1636
+
1637
+ <rss version="2.0"
1638
+ xmlns:content="http://purl.org/rss/1.0/modules/content/"
1639
+ xmlns:atom="http://www.w3.org/2005/Atom"
1640
+ xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
1641
+ xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
1642
+ <?php do_action( 'bp_activity_feed_rss_attributes' ); ?>
1643
+ >
1644
+
1645
+ <channel>
1646
+ <title><?php echo $this->title; ?></title>
1647
+ <link><?php echo $this->link; ?></link>
1648
+ <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
1649
+ <description><?php echo $this->description ?></description>
1650
+ <lastBuildDate><?php echo mysql2date( 'D, d M Y H:i:s O', bp_activity_get_last_updated(), false ); ?></lastBuildDate>
1651
+ <generator>http://buddypress.org/?v=<?php bp_version(); ?></generator>
1652
+ <language><?php bloginfo_rss( 'language' ); ?></language>
1653
+ <ttl><?php echo $this->ttl; ?></ttl>
1654
+ <sy:updatePeriod><?php echo $this->update_period; ?></sy:updatePeriod>
1655
+ <sy:updateFrequency><?php echo $this->update_frequency; ?></sy:updateFrequency>
1656
+ <?php do_action( 'bp_activity_feed_channel_elements' ); ?>
1657
+
1658
+ <?php if ( bp_has_activities( $this->activity_args ) ) : ?>
1659
+ <?php while ( bp_activities() ) : bp_the_activity(); ?>
1660
+ <item>
1661
+ <guid isPermaLink="false"><?php bp_activity_feed_item_guid(); ?></guid>
1662
+ <title><?php echo stripslashes( bp_get_activity_feed_item_title() ); ?></title>
1663
+ <link><?php bp_activity_thread_permalink() ?></link>
1664
+ <pubDate><?php echo mysql2date( 'D, d M Y H:i:s O', bp_get_activity_feed_item_date(), false ); ?></pubDate>
1665
+
1666
+ <?php if ( bp_get_activity_feed_item_description() ) : ?>
1667
+ <content:encoded><![CDATA[<?php $this->feed_content(); ?>]]></content:encoded>
1668
+ <?php endif; ?>
1669
+
1670
+ <?php if ( bp_activity_can_comment() ) : ?>
1671
+ <slash:comments><?php bp_activity_comment_count(); ?></slash:comments>
1672
+ <?php endif; ?>
1673
+
1674
+ <?php do_action( 'bp_activity_feed_item_elements' ); ?>
1675
+ </item>
1676
+ <?php endwhile; ?>
1677
+
1678
+ <?php endif; ?>
1679
+ </channel>
1680
+ </rss><?php
1681
+ }
1682
+ }
bp-activity/bp-activity-cssjs.php DELETED
@@ -1,76 +0,0 @@
1
- <?php
2
- /**
3
- * Activity component CSS/JS
4
- *
5
- * @package BuddyPress
6
- * @subpackage ActivityScripts
7
- * @since 1.0.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- /**
14
- * Enqueue @mentions JS.
15
- *
16
- * @since 2.1.0
17
- */
18
- function bp_activity_mentions_script() {
19
- if ( ! bp_activity_maybe_load_mentions_scripts() ) {
20
- return;
21
- }
22
-
23
- // Special handling for New/Edit screens in wp-admin.
24
- if ( is_admin() ) {
25
- if (
26
- ! get_current_screen() ||
27
- ! in_array( get_current_screen()->base, array( 'page', 'post' ) ) ||
28
- ! post_type_supports( get_current_screen()->post_type, 'editor' ) ) {
29
- return;
30
- }
31
- }
32
-
33
-
34
- $min = bp_core_get_minified_asset_suffix();
35
-
36
- wp_enqueue_script( 'bp-mentions', buddypress()->plugin_url . "bp-activity/js/mentions{$min}.js", array( 'jquery', 'jquery-atwho' ), bp_get_version(), true );
37
- wp_enqueue_style( 'bp-mentions-css', buddypress()->plugin_url . "bp-activity/css/mentions{$min}.css", array(), bp_get_version() );
38
-
39
- wp_style_add_data( 'bp-mentions-css', 'rtl', true );
40
- if ( $min ) {
41
- wp_style_add_data( 'bp-mentions-css', 'suffix', $min );
42
- }
43
-
44
- // If the script has been enqueued, let's attach our mentions TinyMCE init callback.
45
- add_filter( 'tiny_mce_before_init', 'bp_add_mentions_on_tinymce_init', 10, 2 );
46
-
47
- /**
48
- * Fires at the end of the Activity Mentions script.
49
- *
50
- * This is the hook where BP components can add their own prefetched results
51
- * friends to the page for quicker @mentions lookups.
52
- *
53
- * @since 2.1.0
54
- */
55
- do_action( 'bp_activity_mentions_prime_results' );
56
- }
57
- add_action( 'bp_enqueue_scripts', 'bp_activity_mentions_script' );
58
- add_action( 'bp_admin_enqueue_scripts', 'bp_activity_mentions_script' );
59
-
60
- /**
61
- * Bind the mentions listener to a wp_editor instance when TinyMCE initializes.
62
- *
63
- * @since 2.3.3
64
- *
65
- * @param array $settings An array with TinyMCE config.
66
- * @param string $editor_id Unique editor identifier, e.g. 'content'.
67
- * @return array $mceInit An array with TinyMCE config.
68
- */
69
- function bp_add_mentions_on_tinymce_init( $settings, $editor_id ) {
70
- // We only apply the mentions init to the visual post editor in the WP dashboard.
71
- if ( 'content' === $editor_id ) {
72
- $settings['init_instance_callback'] = 'window.bp.mentions.tinyMCEinit';
73
- }
74
-
75
- return $settings;
76
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-embeds.php DELETED
@@ -1,352 +0,0 @@
1
- <?php
2
- /**
3
- * Functions related to embedding single activity items externally.
4
- *
5
- * Relies on WordPress 4.5.
6
- *
7
- * @since 2.6.0
8
- *
9
- * @package BuddyPress
10
- * @subpackage ActivityEmbeds
11
- */
12
-
13
- // Exit if accessed directly.
14
- defined( 'ABSPATH' ) || exit;
15
-
16
- /**
17
- * Loads our activity oEmbed component.
18
- *
19
- * @since 2.6.0
20
- */
21
- function bp_activity_setup_oembed() {
22
- if ( version_compare( $GLOBALS['wp_version'], '4.5', '>=' ) && bp_is_active( 'activity', 'embeds' ) ) {
23
- buddypress()->activity->oembed = new BP_Activity_oEmbed_Extension;
24
- }
25
- }
26
- add_action( 'bp_loaded', 'bp_activity_setup_oembed' );
27
-
28
- /**
29
- * Catch links in embed excerpt so top.location.href can be added.
30
- *
31
- * Due to <iframe sandbox="allow-top-navigation">, links in embeds can only be
32
- * clicked if invoked with top.location.href via JS.
33
- *
34
- * @since 2.6.0
35
- *
36
- * @param string $text Embed excerpt
37
- * @return string
38
- */
39
- function bp_activity_embed_excerpt_onclick_location_filter( $text ) {
40
- return preg_replace_callback( '/<a\s+[^>]*href=\"([^\"]*)\"/iU', 'bp_activity_embed_excerpt_onclick_location_filter_callback', $text );
41
- }
42
- /**
43
- * Add onclick="top.location.href" to a link.
44
- *
45
- * @since 2.6.0
46
- *
47
- * @param array $matches Items matched by bp_activity_embed_excerpt_onclick_location_filter().
48
- * @return string
49
- */
50
- function bp_activity_embed_excerpt_onclick_location_filter_callback( $matches ) {
51
- return sprintf( '<a href="%1$s" onclick="top.location.href=\'%1$s\'"', $matches[1] );
52
- }
53
-
54
- /**
55
- * Add inline styles for BP activity embeds.
56
- *
57
- * @since 2.6.0
58
- */
59
- function bp_activity_embed_add_inline_styles() {
60
- if ( false === bp_is_single_activity() ) {
61
- return;
62
- }
63
-
64
- $min = bp_core_get_minified_asset_suffix();
65
-
66
- if ( is_rtl() ) {
67
- $css = bp_locate_template_asset( "css/embeds-activity-rtl{$min}.css" );
68
- } else {
69
- $css = bp_locate_template_asset( "css/embeds-activity{$min}.css" );
70
- }
71
-
72
- // Bail if file wasn't found.
73
- if ( false === $css ) {
74
- return;
75
- }
76
-
77
- // Grab contents of CSS file and do some rudimentary CSS protection.
78
- $css = file_get_contents( $css['file'] );
79
- $css = wp_kses( $css, array( "\'", '\"' ) );
80
-
81
- printf( '<style type="text/css">%s</style>', $css );
82
- }
83
- add_action( 'embed_head', 'bp_activity_embed_add_inline_styles', 20 );
84
-
85
- /**
86
- * Query for the activity item on the activity embed template.
87
- *
88
- * Basically a wrapper for {@link bp_has_activities()}, but allows us to
89
- * use the activity loop without requerying for it again.
90
- *
91
- * @since 2.6.0
92
- *
93
- * @param int $activity_id The activity ID.
94
- * @return bool
95
- */
96
- function bp_activity_embed_has_activity( $activity_id = 0 ) {
97
- global $activities_template;
98
-
99
- if ( empty( $activity_id ) ) {
100
- return false;
101
- }
102
-
103
- if ( ! empty( $activities_template->activities ) ) {
104
- $activity = (array) $activities_template->activities;
105
- $activity = reset( $activity );
106
-
107
- // No need to requery if we already got the embed activity
108
- if ( (int) $activity_id === $activity->id ) {
109
- return $activities_template->has_activities();
110
- }
111
- }
112
-
113
- return bp_has_activities( array(
114
- 'display_comments' => 'threaded',
115
- 'show_hidden' => true,
116
- 'include' => (int) $activity_id,
117
- ) );
118
- }
119
-
120
- /**
121
- * Outputs excerpt for an activity embed item.
122
- *
123
- * @since 2.6.0
124
- */
125
- function bp_activity_embed_excerpt( $content = '' ) {
126
- echo bp_activity_get_embed_excerpt( $content = '' );
127
- }
128
-
129
- /**
130
- * Generates excerpt for an activity embed item.
131
- *
132
- * @since 2.6.0
133
- *
134
- * @param string $content The content to generate an excerpt for.
135
- * @return string
136
- */
137
- function bp_activity_get_embed_excerpt( $content = '' ) {
138
- if ( empty( $content ) && ! empty( $GLOBALS['activities_template']->in_the_loop ) ) {
139
- $content = $GLOBALS['activities_template']->activity->content;
140
- }
141
-
142
- /*
143
- * bp_activity_truncate_entry() includes the 'Read More' link, which is why
144
- * we're using this instead of bp_create_excerpt().
145
- */
146
- $content = html_entity_decode( $content );
147
- $content = bp_activity_truncate_entry( $content, array(
148
- 'html' => false,
149
- 'filter_shortcodes' => true,
150
- 'strip_tags' => true,
151
- 'force_truncate' => true
152
- ) );
153
-
154
- /**
155
- * Filter the activity embed excerpt.
156
- *
157
- * @since 2.6.0
158
- *
159
- * @var string $content Embed Excerpt.
160
- * @var string $unmodified_content Unmodified activity content.
161
- */
162
- return apply_filters( 'bp_activity_get_embed_excerpt', $content, $GLOBALS['activities_template']->activity->content );
163
- }
164
-
165
- /**
166
- * Outputs the first embedded item in the activity oEmbed template.
167
- *
168
- * @since 2.6.0
169
- */
170
- function bp_activity_embed_media() {
171
- // Bail if oEmbed request explicitly hides media.
172
- if ( isset( $_GET['hide_media'] ) && true == wp_validate_boolean( $_GET['hide_media'] ) ) {
173
- /**
174
- * Do something after media is rendered for an activity oEmbed item.
175
- *
176
- * @since 2.6.0
177
- */
178
- do_action( 'bp_activity_embed_after_media' );
179
-
180
- return;
181
- }
182
-
183
- /**
184
- * Should we display media in the oEmbed template?
185
- *
186
- * @since 2.6.0
187
- *
188
- * @param bool $retval Defaults to true.
189
- */
190
- $allow_media = apply_filters( 'bp_activity_embed_display_media', true );
191
-
192
- // Find oEmbeds from only WP registered providers.
193
- bp_remove_all_filters( 'oembed_providers' );
194
- $media = bp_core_extract_media_from_content( $GLOBALS['activities_template']->activity->content, 'embeds' );
195
- bp_restore_all_filters( 'oembed_providers' );
196
-
197
- // oEmbeds have precedence over inline video / audio.
198
- if ( isset( $media['embeds'] ) && true === $allow_media ) {
199
- // Autoembed first URL.
200
- $oembed_defaults = wp_embed_defaults();
201
- $oembed_args = array(
202
- 'width' => $oembed_defaults['width'],
203
- 'height' => $oembed_defaults['height'],
204
- 'discover' => true
205
- );
206
- $url = $media['embeds'][0]['url'];
207
- $cachekey = '_oembed_response_' . md5( $url . serialize( $oembed_args ) );
208
-
209
- // Try to fetch oEmbed response from meta.
210
- $oembed = bp_activity_get_meta( bp_get_activity_id(), $cachekey );
211
-
212
- // No cache, so fetch full oEmbed response now!
213
- if ( '' === $oembed ) {
214
- $o = _wp_oembed_get_object();
215
- $oembed = $o->fetch( $o->get_provider( $url, $oembed_args ), $url, $oembed_args );
216
-
217
- // Cache oEmbed response.
218
- bp_activity_update_meta( bp_get_activity_id(), $cachekey, $oembed );
219
- }
220
-
221
- $content = '';
222
-
223
- /**
224
- * Filters the default embed display max width.
225
- *
226
- * This is used if the oEmbed response does not return a thumbnail width.
227
- *
228
- * @since 2.6.0
229
- *
230
- * @param int $width.
231
- */
232
- $width = (int) apply_filters( 'bp_activity_embed_display_media_width', 550 );
233
-
234
- // Set thumbnail.
235
- if ( 'photo' === $oembed->type ) {
236
- $thumbnail = $oembed->url;
237
- } elseif ( isset( $oembed->thumbnail_url ) ) {
238
- $thumbnail = $oembed->thumbnail_url;
239
-
240
- /* Non-oEmbed standard attributes */
241
- // Mixcloud
242
- } elseif ( isset( $oembed->image ) ) {
243
- $thumbnail = $oembed->image;
244
- // ReverbNation
245
- } elseif ( isset( $oembed->{'thumbnail-url'} ) ) {
246
- $thumbnail = $oembed->{'thumbnail-url'};
247
- }
248
-
249
- // Display thumb and related oEmbed meta.
250
- if ( true === isset ( $thumbnail ) ) {
251
- $play_icon = $caption = '';
252
-
253
- // Add play icon for non-photos.
254
- if ( 'photo' !== $oembed->type ) {
255
- /**
256
- * ion-play icon from Ionicons.
257
- *
258
- * @link http://ionicons.com/
259
- * @license MIT
260
- */
261
- $play_icon = <<<EOD
262
- <svg id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M405.2,232.9L126.8,67.2c-3.4-2-6.9-3.2-10.9-3.2c-10.9,0-19.8,9-19.8,20H96v344h0.1c0,11,8.9,20,19.8,20 c4.1,0,7.5-1.4,11.2-3.4l278.1-165.5c6.6-5.5,10.8-13.8,10.8-23.1C416,246.7,411.8,238.5,405.2,232.9z"/></svg>
263
- EOD;
264
-
265
- $play_icon = sprintf( '<a rel="nofollow" class="play-btn" href="%1$s" onclick="top.location.href=\'%1$s\'">%2$s</a>', esc_url( $url ), $play_icon );
266
- }
267
-
268
- // Thumb width
269
- $thumb_width = isset( $oembed->thumbnail_width ) && 'photo' !== $oembed->type && (int) $oembed->thumbnail_width < 550 ? (int) $oembed->thumbnail_width : $width;
270
-
271
- $float_width = 350;
272
-
273
- // Set up thumb.
274
- $content = sprintf( '<div class="thumb" style="max-width:%1$spx">%2$s<a href="%3$s" rel="nofollow" onclick="top.location.href=\'%3$s\'"><img src="%4$s" /></a></div>', $thumb_width, $play_icon, esc_url( $url ), esc_url( $thumbnail ) );
275
-
276
- // Show title.
277
- if ( isset( $oembed->title ) ) {
278
- $caption .= sprintf( '<p class="caption-title"><strong>%s</strong></p>', apply_filters( 'single_post_title', $oembed->title ) );
279
- }
280
-
281
- // Show description (non-oEmbed standard)
282
- if ( isset( $oembed->description ) ) {
283
- $caption .= sprintf( '<div class="caption-description">%s</div>', apply_filters( 'bp_activity_get_embed_excerpt', $oembed->description ) );
284
- }
285
-
286
- // Show author info.
287
- if ( isset( $oembed->provider_name ) && isset( $oembed->author_name ) ) {
288
- /* translators: By [oEmbed author] on [oEmbed provider]. eg. By BuddyPress on YouTube. */
289
- $anchor_text = sprintf( __( 'By %1$s on %2$s', 'buddypress' ), $oembed->author_name, $oembed->provider_name );
290
-
291
- } elseif ( isset( $oembed->provider_name ) ) {
292
- $anchor_text = sprintf( __( 'View on %s', 'buddypress' ), $oembed->provider_name );
293
- }
294
-
295
- if ( true === isset( $anchor_text ) ) {
296
- $caption .= sprintf( '<a rel="nofollow" href="%1$s" onclick="top.location.href=\'%1$s\'">%2$s</a>', esc_url( $url ), apply_filters( 'the_title', $anchor_text ) );
297
- }
298
-
299
- // Set up caption.
300
- if ( '' !== $caption ) {
301
- $css_class = isset( $oembed->provider_name ) ? sprintf( ' provider-%s', sanitize_html_class( strtolower( $oembed->provider_name ) ) ) : '';
302
- $caption = sprintf( '<div class="caption%1$s" style="width:%2$s">%3$s</div>',
303
- $css_class,
304
- $thumb_width > $float_width ? 100 . '%' : round( ( $width - (int) $thumb_width ) / $width * 100 ) . '%',
305
- $caption
306
- );
307
-
308
- $content .= $caption;
309
- }
310
- }
311
-
312
- // Print rich content.
313
- if ( '' !== $content ) {
314
- printf( '<div class="bp-activity-embed-display-media %s" style="max-width:%spx">%s</div>',
315
- $thumb_width < $float_width ? 'two-col' : 'one-col',
316
- $thumb_width < $float_width ? $width : $thumb_width,
317
- $content
318
- );
319
- }
320
-
321
- // Video / audio.
322
- } elseif ( true === $allow_media ) {
323
- // Call BP_Embed if it hasn't already loaded.
324
- bp_embed_init();
325
-
326
- // Run shortcode and embed routine.
327
- $content = buddypress()->embed->run_shortcode( $GLOBALS['activities_template']->activity->content );
328
- $content = buddypress()->embed->autoembed( $content );
329
-
330
- // Try to find inline video / audio.
331
- $media = bp_core_extract_media_from_content( $content, 96 );
332
-
333
- // Video takes precedence. HTML5-only.
334
- if ( isset( $media['videos'] ) && 'shortcodes' === $media['videos'][0]['source'] ) {
335
- printf( '<video controls preload="metadata"><source src="%1$s"><p>%2$s</p></video>',
336
- esc_url( $media['videos'][0]['url'] ),
337
- esc_html__( 'Your browser does not support HTML5 video', 'buddypress' )
338
- );
339
-
340
- // No video? Try audio. HTML5-only.
341
- } elseif ( isset( $media['audio'] ) && 'shortcodes' === $media['audio'][0]['source'] ) {
342
- printf( '<audio controls preload="metadata"><source src="%1$s"><p>%2$s</p></audio>',
343
- esc_url( $media['audio'][0]['url'] ),
344
- esc_html__( 'Your browser does not support HTML5 audio', 'buddypress' )
345
- );
346
- }
347
-
348
- }
349
-
350
- /** This hook is documented in /bp-activity/bp-activity-embeds.php */
351
- do_action( 'bp_activity_embed_after_media' );
352
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-filters.php CHANGED
@@ -1,18 +1,18 @@
1
  <?php
 
2
  /**
3
  * Filters related to the Activity component.
4
  *
5
  * @package BuddyPress
6
  * @subpackage ActivityFilters
7
- * @since 1.0.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
- /* Filters *******************************************************************/
14
 
15
- // Apply WordPress defined filters.
16
  add_filter( 'bp_get_activity_action', 'bp_activity_filter_kses', 1 );
17
  add_filter( 'bp_get_activity_content_body', 'bp_activity_filter_kses', 1 );
18
  add_filter( 'bp_get_activity_content', 'bp_activity_filter_kses', 1 );
@@ -22,7 +22,7 @@ add_filter( 'bp_get_activity_latest_update_excerpt', 'bp_activity_filter_kses',
22
  add_filter( 'bp_get_activity_feed_item_description', 'bp_activity_filter_kses', 1 );
23
  add_filter( 'bp_activity_content_before_save', 'bp_activity_filter_kses', 1 );
24
  add_filter( 'bp_activity_action_before_save', 'bp_activity_filter_kses', 1 );
25
- add_filter( 'bp_activity_latest_update_content', 'bp_activity_filter_kses', 1 );
26
 
27
  add_filter( 'bp_get_activity_action', 'force_balance_tags' );
28
  add_filter( 'bp_get_activity_content_body', 'force_balance_tags' );
@@ -33,17 +33,12 @@ add_filter( 'bp_get_activity_feed_item_description', 'force_balance_tags' );
33
  add_filter( 'bp_activity_content_before_save', 'force_balance_tags' );
34
  add_filter( 'bp_activity_action_before_save', 'force_balance_tags' );
35
 
36
- if ( function_exists( 'wp_encode_emoji' ) ) {
37
- add_filter( 'bp_activity_content_before_save', 'wp_encode_emoji' );
38
- }
39
-
40
  add_filter( 'bp_get_activity_action', 'wptexturize' );
41
  add_filter( 'bp_get_activity_content_body', 'wptexturize' );
42
  add_filter( 'bp_get_activity_content', 'wptexturize' );
43
  add_filter( 'bp_get_activity_parent_content', 'wptexturize' );
44
  add_filter( 'bp_get_activity_latest_update', 'wptexturize' );
45
  add_filter( 'bp_get_activity_latest_update_excerpt', 'wptexturize' );
46
- add_filter( 'bp_activity_get_embed_excerpt', 'wptexturize' );
47
 
48
  add_filter( 'bp_get_activity_action', 'convert_smilies' );
49
  add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
@@ -51,7 +46,6 @@ add_filter( 'bp_get_activity_content', 'convert_smilies' );
51
  add_filter( 'bp_get_activity_parent_content', 'convert_smilies' );
52
  add_filter( 'bp_get_activity_latest_update', 'convert_smilies' );
53
  add_filter( 'bp_get_activity_latest_update_excerpt', 'convert_smilies' );
54
- add_filter( 'bp_activity_get_embed_excerpt', 'convert_smilies' );
55
 
56
  add_filter( 'bp_get_activity_action', 'convert_chars' );
57
  add_filter( 'bp_get_activity_content_body', 'convert_chars' );
@@ -59,13 +53,11 @@ add_filter( 'bp_get_activity_content', 'convert_chars' );
59
  add_filter( 'bp_get_activity_parent_content', 'convert_chars' );
60
  add_filter( 'bp_get_activity_latest_update', 'convert_chars' );
61
  add_filter( 'bp_get_activity_latest_update_excerpt', 'convert_chars' );
62
- add_filter( 'bp_activity_get_embed_excerpt', 'convert_chars' );
63
 
64
  add_filter( 'bp_get_activity_action', 'wpautop' );
65
  add_filter( 'bp_get_activity_content_body', 'wpautop' );
66
  add_filter( 'bp_get_activity_content', 'wpautop' );
67
  add_filter( 'bp_get_activity_feed_item_description', 'wpautop' );
68
- add_filter( 'bp_activity_get_embed_excerpt', 'wpautop' );
69
 
70
  add_filter( 'bp_get_activity_action', 'make_clickable', 9 );
71
  add_filter( 'bp_get_activity_content_body', 'make_clickable', 9 );
@@ -74,7 +66,6 @@ add_filter( 'bp_get_activity_parent_content', 'make_clickable', 9 );
74
  add_filter( 'bp_get_activity_latest_update', 'make_clickable', 9 );
75
  add_filter( 'bp_get_activity_latest_update_excerpt', 'make_clickable', 9 );
76
  add_filter( 'bp_get_activity_feed_item_description', 'make_clickable', 9 );
77
- add_filter( 'bp_activity_get_embed_excerpt', 'make_clickable', 9 );
78
 
79
  add_filter( 'bp_acomment_name', 'stripslashes_deep', 5 );
80
  add_filter( 'bp_get_activity_action', 'stripslashes_deep', 5 );
@@ -87,7 +78,7 @@ add_filter( 'bp_get_activity_feed_item_description', 'stripslashes_deep', 5 );
87
 
88
  add_filter( 'bp_activity_primary_link_before_save', 'esc_url_raw' );
89
 
90
- // Apply BuddyPress-defined filters.
91
  add_filter( 'bp_get_activity_content', 'bp_activity_make_nofollow_filter' );
92
  add_filter( 'bp_get_activity_content_body', 'bp_activity_make_nofollow_filter' );
93
  add_filter( 'bp_get_activity_parent_content', 'bp_activity_make_nofollow_filter' );
@@ -99,24 +90,18 @@ add_filter( 'pre_comment_content', 'bp_activity_at_name_filter
99
  add_filter( 'group_forum_topic_text_before_save', 'bp_activity_at_name_filter' );
100
  add_filter( 'group_forum_post_text_before_save', 'bp_activity_at_name_filter' );
101
  add_filter( 'the_content', 'bp_activity_at_name_filter' );
102
- add_filter( 'bp_activity_get_embed_excerpt', 'bp_activity_at_name_filter' );
103
 
104
  add_filter( 'bp_get_activity_parent_content', 'bp_create_excerpt' );
105
 
106
  add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
107
  add_filter( 'bp_get_activity_content', 'bp_activity_truncate_entry', 5 );
108
 
109
- add_filter( 'bp_get_total_favorite_count_for_user', 'bp_core_number_format' );
110
- add_filter( 'bp_get_total_mention_count_for_user', 'bp_core_number_format' );
111
-
112
- add_filter( 'bp_activity_get_embed_excerpt', 'bp_activity_embed_excerpt_onclick_location_filter', 9 );
113
 
114
- /* Actions *******************************************************************/
115
-
116
- // At-name filter.
117
  add_action( 'bp_activity_before_save', 'bp_activity_at_name_filter_updates' );
118
 
119
- // Activity stream moderation.
120
  add_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2, 1 );
121
  add_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2, 1 );
122
 
@@ -125,7 +110,7 @@ add_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2, 1
125
  /**
126
  * Types of activity stream items to moderate.
127
  *
128
- * @since 1.6.0
129
  *
130
  * @return array $types List of the activity types to moderate.
131
  */
@@ -134,71 +119,53 @@ function bp_activity_get_moderated_activity_types() {
134
  'activity_comment',
135
  'activity_update'
136
  );
137
-
138
- /**
139
- * Filters the default activity types that BuddyPress should moderate.
140
- *
141
- * @since 1.6.0
142
- *
143
- * @param array $types Default activity types to moderate.
144
- */
145
  return apply_filters( 'bp_activity_check_activity_types', $types );
146
  }
147
 
148
  /**
149
  * Moderate the posted activity item, if it contains moderate keywords.
150
  *
151
- * @since 1.6.0
152
  *
153
  * @param BP_Activity_Activity $activity The activity object to check.
154
  */
155
  function bp_activity_check_moderation_keys( $activity ) {
156
 
157
- // Only check specific types of activity updates.
158
- if ( ! in_array( $activity->type, bp_activity_get_moderated_activity_types() ) ) {
159
  return;
160
- }
161
-
162
- // Send back the error so activity update fails.
163
- // @todo This is temporary until some kind of moderation is built.
164
- $moderate = bp_core_check_for_moderation( $activity->user_id, '', $activity->content, 'wp_error' );
165
- if ( is_wp_error( $moderate ) ) {
166
- $activity->errors = $moderate;
167
 
168
- // Backpat.
 
 
169
  $activity->component = false;
170
- }
171
  }
172
 
173
  /**
174
  * Mark the posted activity as spam, if it contains blacklist keywords.
175
  *
176
- * @since 1.6.0
177
  *
178
  * @param BP_Activity_Activity $activity The activity object to check.
179
  */
180
  function bp_activity_check_blacklist_keys( $activity ) {
181
 
182
- // Only check specific types of activity updates.
183
- if ( ! in_array( $activity->type, bp_activity_get_moderated_activity_types() ) ) {
184
  return;
185
- }
186
-
187
- // Send back the error so activity update fails.
188
- // @todo This is temporary until some kind of trash status is built.
189
- $blacklist = bp_core_check_for_blacklist( $activity->user_id, '', $activity->content, 'wp_error' );
190
- if ( is_wp_error( $blacklist ) ) {
191
- $activity->errors = $blacklist;
192
 
193
- // Backpat.
194
- $activity->component = false;
195
- }
196
  }
197
 
198
  /**
199
  * Custom kses filtering for activity content.
200
  *
201
- * @since 1.1.0
 
 
 
202
  *
203
  * @param string $content The activity content.
204
  * @return string $content Filtered activity content.
@@ -207,15 +174,11 @@ function bp_activity_filter_kses( $content ) {
207
  global $allowedtags;
208
 
209
  $activity_allowedtags = $allowedtags;
210
- $activity_allowedtags['a']['class'] = array();
211
- $activity_allowedtags['a']['id'] = array();
212
- $activity_allowedtags['a']['rel'] = array();
213
- $activity_allowedtags['a']['title'] = array();
214
-
215
- $activity_allowedtags['b'] = array();
216
- $activity_allowedtags['code'] = array();
217
- $activity_allowedtags['i'] = array();
218
-
219
  $activity_allowedtags['img'] = array();
220
  $activity_allowedtags['img']['src'] = array();
221
  $activity_allowedtags['img']['alt'] = array();
@@ -224,19 +187,8 @@ function bp_activity_filter_kses( $content ) {
224
  $activity_allowedtags['img']['class'] = array();
225
  $activity_allowedtags['img']['id'] = array();
226
  $activity_allowedtags['img']['title'] = array();
 
227
 
228
- $activity_allowedtags['span'] = array();
229
- $activity_allowedtags['span']['class'] = array();
230
- $activity_allowedtags['span']['data-livestamp'] = array();
231
-
232
-
233
- /**
234
- * Filters the allowed HTML tags for BuddyPress Activity content.
235
- *
236
- * @since 1.2.0
237
- *
238
- * @param array $value Array of allowed HTML tags and attributes.
239
- */
240
  $activity_allowedtags = apply_filters( 'bp_activity_allowed_tags', $activity_allowedtags );
241
  return wp_kses( $content, $activity_allowedtags );
242
  }
@@ -244,10 +196,10 @@ function bp_activity_filter_kses( $content ) {
244
  /**
245
  * Find and link @-mentioned users in the contents of a given item.
246
  *
247
- * @since 1.2.0
248
  *
249
- * @param string $content The contents of a given item.
250
- * @param int $activity_id The activity id. Deprecated.
251
  * @return string $content Content filtered for mentions.
252
  */
253
  function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
@@ -257,7 +209,7 @@ function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
257
  return $content;
258
  }
259
 
260
- // Try to find mentions.
261
  $usernames = bp_activity_find_mentions( $content );
262
 
263
  // No mentions? Stop now!
@@ -265,11 +217,11 @@ function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
265
  return $content;
266
 
267
  // We don't want to link @mentions that are inside of links, so we
268
- // temporarily remove them.
269
  $replace_count = 0;
270
  $replacements = array();
271
  foreach ( $usernames as $username ) {
272
- // Prevent @ name linking inside <a> tags.
273
  preg_match_all( '/(<a.*?(?!<\/a>)@' . $username . '.*?<\/a>)/', $content, $content_matches );
274
  if ( ! empty( $content_matches[1] ) ) {
275
  foreach ( $content_matches[1] as $replacement ) {
@@ -280,19 +232,19 @@ function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
280
  }
281
  }
282
 
283
- // Linkify the mentions with the username.
284
  foreach ( (array) $usernames as $user_id => $username ) {
285
- $content = preg_replace( '/(@' . $username . '\b)/', "<a class='bp-suggestions-mention' href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $content );
286
  }
287
 
288
- // Put everything back.
289
  if ( ! empty( $replacements ) ) {
290
  foreach ( $replacements as $placeholder => $original ) {
291
  $content = str_replace( $placeholder, $original, $content );
292
  }
293
  }
294
 
295
- // Return the content.
296
  return $content;
297
  }
298
 
@@ -302,9 +254,11 @@ function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
302
  * If mentions are found, replace @mention text with user links and add our
303
  * hook to send mention notifications after the activity item is saved.
304
  *
305
- * @since 1.5.0
306
  *
307
- * @param BP_Activity_Activity $activity Activity Object.
 
 
308
  */
309
  function bp_activity_at_name_filter_updates( $activity ) {
310
  // Are mentions disabled?
@@ -316,20 +270,20 @@ function bp_activity_at_name_filter_updates( $activity ) {
316
  if ( ! empty( $activity->is_spam ) )
317
  return;
318
 
319
- // Try to find mentions.
320
  $usernames = bp_activity_find_mentions( $activity->content );
321
 
322
  // We have mentions!
323
  if ( ! empty( $usernames ) ) {
324
- // Replace @mention text with userlinks.
325
  foreach( (array) $usernames as $user_id => $username ) {
326
- $activity->content = preg_replace( '/(@' . $username . '\b)/', "<a class='bp-suggestions-mention' href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $activity->content );
327
  }
328
 
329
- // Add our hook to send @mention emails after the activity item is saved.
330
  add_action( 'bp_activity_after_save', 'bp_activity_at_name_send_emails' );
331
 
332
- // Temporary variable to avoid having to run bp_activity_find_mentions() again.
333
  buddypress()->activity->mentioned_users = $usernames;
334
  }
335
  }
@@ -337,9 +291,12 @@ function bp_activity_at_name_filter_updates( $activity ) {
337
  /**
338
  * Sends emails and BP notifications for users @-mentioned in an activity item.
339
  *
340
- * @since 1.7.0
 
 
 
341
  *
342
- * @param BP_Activity_Activity $activity The BP_Activity_Activity object.
343
  */
344
  function bp_activity_at_name_send_emails( $activity ) {
345
  // Are mentions disabled?
@@ -351,31 +308,20 @@ function bp_activity_at_name_send_emails( $activity ) {
351
  if ( empty( buddypress()->activity->mentioned_users ) )
352
  return;
353
 
354
- // Grab our temporary variable from bp_activity_at_name_filter_updates().
355
  $usernames = buddypress()->activity->mentioned_users;
356
 
357
- // Get rid of temporary variable.
358
  unset( buddypress()->activity->mentioned_users );
359
 
360
- // Send @mentions and setup BP notifications.
361
  foreach( (array) $usernames as $user_id => $username ) {
362
-
363
- /**
364
- * Filters BuddyPress' ability to send email notifications for @mentions.
365
- *
366
- * @since 1.6.0
367
- * @since 2.5.0 Introduced `$user_id` and `$activity` parameters.
368
- *
369
- * @param bool $value Whether or not BuddyPress should send a notification to the mentioned users.
370
- * @param array $usernames Array of users potentially notified.
371
- * @param int $user_id ID of the current user being notified.
372
- * @param BP_Activity_Activity $activity Activity object.
373
- */
374
- if ( apply_filters( 'bp_activity_at_name_do_notifications', true, $usernames, $user_id, $activity ) ) {
375
  bp_activity_at_message_notification( $activity->id, $user_id );
376
  }
377
 
378
- // Updates mention count for the user.
379
  bp_activity_update_mention_count_for_user( $user_id, $activity->id );
380
  }
381
  }
@@ -383,7 +329,7 @@ function bp_activity_at_name_send_emails( $activity ) {
383
  /**
384
  * Catch links in activity text so rel=nofollow can be added.
385
  *
386
- * @since 1.2.0
387
  *
388
  * @param string $text Activity text.
389
  * @return string $text Text with rel=nofollow added to any links.
@@ -395,10 +341,12 @@ function bp_activity_make_nofollow_filter( $text ) {
395
  /**
396
  * Add rel=nofollow to a link.
397
  *
398
- * @since 1.2.0
 
 
399
  *
400
  * @param array $matches Items matched by preg_replace_callback() in bp_activity_make_nofollow_filter().
401
- * @return string $text Link with rel=nofollow added.
402
  */
403
  function bp_activity_make_nofollow_filter_callback( $matches ) {
404
  $text = $matches[1];
@@ -409,81 +357,51 @@ function bp_activity_make_nofollow_filter( $text ) {
409
  /**
410
  * Truncate long activity entries when viewed in activity streams.
411
  *
412
- * This method can only be used inside the Activity loop.
413
  *
414
- * @since 1.5.0
415
- * @since 2.6.0 Added $args parameter.
 
 
 
 
 
416
  *
417
  * @param string $text The original activity entry text.
418
- * @param array $args {
419
- * Optional parameters. See $options argument of {@link bp_create_excerpt()}
420
- * for all available parameters.
421
- * }
422
  * @return string $excerpt The truncated text.
423
  */
424
- function bp_activity_truncate_entry( $text, $args = array() ) {
425
  global $activities_template;
426
 
427
- /**
428
- * Provides a filter that lets you choose whether to skip this filter on a per-activity basis.
429
- *
430
- * @since 2.3.0
431
- *
432
- * @param bool $value If true, text should be checked to see if it needs truncating.
433
- */
434
- $maybe_truncate_text = apply_filters(
435
- 'bp_activity_maybe_truncate_entry',
436
- isset( $activities_template->activity->type ) && ! in_array( $activities_template->activity->type, array( 'new_blog_post', ), true )
437
- );
438
-
439
- // The full text of the activity update should always show on the single activity screen.
440
- if ( empty( $args['force_truncate'] ) && ( ! $maybe_truncate_text || bp_is_single_activity() ) ) {
441
  return $text;
442
- }
443
 
444
- /**
445
- * Filters the appended text for the activity excerpt.
446
- *
447
- * @since 1.5.0
448
- *
449
- * @param string $value Internationalized "Read more" text.
450
- */
451
  $append_text = apply_filters( 'bp_activity_excerpt_append_text', __( '[Read more]', 'buddypress' ) );
 
452
 
453
- $excerpt_length = bp_activity_get_excerpt_length();
454
-
455
- $args = wp_parse_args( $args, array( 'ending' => __( '&hellip;', 'buddypress' ) ) );
456
-
457
- // Run the text through the excerpt function. If it's too short, the original text will be returned.
458
- $excerpt = bp_create_excerpt( $text, $excerpt_length, $args );
459
 
460
- /*
461
- * If the text returned by bp_create_excerpt() is different from the original text (ie it's
462
- * been truncated), add the "Read More" link. Note that bp_create_excerpt() is stripping
463
- * shortcodes, so we have strip them from the $text before the comparison.
464
- */
465
- if ( strlen( $excerpt ) < strlen( strip_shortcodes( $text ) ) ) {
466
  $id = !empty( $activities_template->activity->current_comment->id ) ? 'acomment-read-more-' . $activities_template->activity->current_comment->id : 'activity-read-more-' . bp_get_activity_id();
467
 
468
  $excerpt = sprintf( '%1$s<span class="activity-read-more" id="%2$s"><a href="%3$s" rel="nofollow">%4$s</a></span>', $excerpt, $id, bp_get_activity_thread_permalink(), $append_text );
469
  }
470
 
471
- /**
472
- * Filters the composite activity excerpt entry.
473
- *
474
- * @since 1.5.0
475
- *
476
- * @param string $excerpt Excerpt text and markup to be displayed.
477
- * @param string $text The original activity entry text.
478
- * @param string $append_text The final append text applied.
479
- */
480
  return apply_filters( 'bp_activity_truncate_entry', $excerpt, $text, $append_text );
481
  }
482
 
483
  /**
484
- * Include extra JavaScript dependencies for activity component.
 
 
485
  *
486
- * @since 2.0.0
487
  *
488
  * @param array $js_handles The original dependencies.
489
  * @return array $js_handles The new dependencies.
@@ -503,9 +421,9 @@ add_filter( 'bp_core_get_js_dependencies', 'bp_activity_get_js_dependencies', 10
503
  * We use these classes to avoid pagination issues when items are loaded
504
  * dynamically into the activity stream.
505
  *
506
- * @since 2.0.0
507
  *
508
- * @param string $classes Array of classes for most recent activity item.
509
  * @return string $classes
510
  */
511
  function bp_activity_newest_class( $classes = '' ) {
@@ -522,9 +440,9 @@ function bp_activity_newest_class( $classes = '' ) {
522
  /**
523
  * Check if Activity Heartbeat feature i on to add a timestamp class.
524
  *
525
- * @since 2.0.0
526
  *
527
- * @param string $classes Array of classes for timestamp.
528
  * @return string $classes
529
  */
530
  function bp_activity_timestamp_class( $classes = '' ) {
@@ -538,7 +456,7 @@ function bp_activity_timestamp_class( $classes = '' ) {
538
  if ( empty( $activity_date ) ) {
539
  return $classes;
540
  }
541
-
542
  $classes .= ' date-recorded-' . strtotime( $activity_date );
543
 
544
  return $classes;
@@ -548,33 +466,33 @@ add_filter( 'bp_get_activity_css_class', 'bp_activity_timestamp_class', 9, 1 );
548
  /**
549
  * Use WordPress Heartbeat API to check for latest activity update.
550
  *
551
- * @since 2.0.0
552
  *
553
- * @param array $response Array containing Heartbeat API response.
554
- * @param array $data Array containing data for Heartbeat API response.
 
 
555
  * @return array $response
556
  */
557
  function bp_activity_heartbeat_last_recorded( $response = array(), $data = array() ) {
 
 
558
  if ( empty( $data['bp_activity_last_recorded'] ) ) {
559
  return $response;
560
  }
561
 
562
  // Use the querystring argument stored in the cookie (to preserve
563
- // filters), but force the offset to get only new items.
564
  $activity_latest_args = bp_parse_args(
565
  bp_ajax_querystring( 'activity' ),
566
  array( 'since' => date( 'Y-m-d H:i:s', $data['bp_activity_last_recorded'] ) ),
567
  'activity_latest_args'
568
  );
569
 
570
- if ( ! empty( $data['bp_activity_last_recorded_search_terms'] ) && empty( $activity_latest_args['search_terms'] ) ) {
571
- $activity_latest_args['search_terms'] = addslashes( $data['bp_activity_last_recorded_search_terms'] );
572
- }
573
-
574
  $newest_activities = array();
575
  $last_activity_recorded = 0;
576
 
577
- // Temporarily add a just-posted class for new activity items.
578
  add_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 );
579
 
580
  ob_start();
@@ -595,8 +513,8 @@ function bp_activity_heartbeat_last_recorded( $response = array(), $data = array
595
  $newest_activities['last_recorded'] = $last_activity_recorded;
596
  ob_end_clean();
597
 
598
- // Remove the temporary filter.
599
- remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10 );
600
 
601
  if ( ! empty( $newest_activities['last_recorded'] ) ) {
602
  $response['bp_activity_newest_activities'] = $newest_activities;
@@ -610,7 +528,7 @@ add_filter( 'heartbeat_nopriv_received', 'bp_activity_heartbeat_last_recorded',
610
  /**
611
  * Set the strings for WP HeartBeat API where needed.
612
  *
613
- * @since 2.0.0
614
  *
615
  * @param array $strings Localized strings.
616
  * @return array $strings
@@ -623,26 +541,14 @@ function bp_activity_heartbeat_strings( $strings = array() ) {
623
 
624
  $global_pulse = 0;
625
 
626
- /**
627
- * Filter that checks whether the global heartbeat settings already exist.
628
- *
629
- * @since 2.0.0
630
- *
631
- * @param array $value Heartbeat settings array.
632
- */
633
  $heartbeat_settings = apply_filters( 'heartbeat_settings', array() );
634
  if ( ! empty( $heartbeat_settings['interval'] ) ) {
635
  // 'Fast' is 5
636
  $global_pulse = is_numeric( $heartbeat_settings['interval'] ) ? absint( $heartbeat_settings['interval'] ) : 5;
637
  }
638
 
639
- /**
640
- * Filters the pulse frequency to be used for the BuddyPress Activity heartbeat.
641
- *
642
- * @since 2.0.0
643
- *
644
- * @param int $value The frequency in seconds between pulses.
645
- */
646
  $bp_activity_pulse = apply_filters( 'bp_activity_heartbeat_pulse', 15 );
647
 
648
  /**
@@ -665,168 +571,3 @@ function bp_activity_heartbeat_strings( $strings = array() ) {
665
  return $strings;
666
  }
667
  add_filter( 'bp_core_get_js_strings', 'bp_activity_heartbeat_strings', 10, 1 );
668
-
669
- /** Scopes ********************************************************************/
670
-
671
- /**
672
- * Set up activity arguments for use with the 'just-me' scope.
673
- *
674
- * @since 2.2.0
675
- *
676
- * @param array $retval Empty array by default.
677
- * @param array $filter Current activity arguments.
678
- * @return array $retval
679
- */
680
- function bp_activity_filter_just_me_scope( $retval = array(), $filter = array() ) {
681
-
682
- // Determine the user_id.
683
- if ( ! empty( $filter['user_id'] ) ) {
684
- $user_id = $filter['user_id'];
685
- } else {
686
- $user_id = bp_displayed_user_id()
687
- ? bp_displayed_user_id()
688
- : bp_loggedin_user_id();
689
- }
690
-
691
- // Should we show all items regardless of sitewide visibility?
692
- $show_hidden = array();
693
- if ( ! empty( $user_id ) && $user_id !== bp_loggedin_user_id() ) {
694
- $show_hidden = array(
695
- 'column' => 'hide_sitewide',
696
- 'value' => 0
697
- );
698
- }
699
-
700
- $retval = array(
701
- 'relation' => 'AND',
702
- array(
703
- 'column' => 'user_id',
704
- 'value' => $user_id
705
- ),
706
- $show_hidden,
707
-
708
- // Overrides.
709
- 'override' => array(
710
- 'display_comments' => 'stream',
711
- 'filter' => array( 'user_id' => 0 ),
712
- 'show_hidden' => true
713
- ),
714
- );
715
-
716
- return $retval;
717
- }
718
- add_filter( 'bp_activity_set_just-me_scope_args', 'bp_activity_filter_just_me_scope', 10, 2 );
719
-
720
- /**
721
- * Set up activity arguments for use with the 'favorites' scope.
722
- *
723
- * @since 2.2.0
724
- *
725
- * @param array $retval Empty array by default.
726
- * @param array $filter Current activity arguments.
727
- * @return array $retval
728
- */
729
- function bp_activity_filter_favorites_scope( $retval = array(), $filter = array() ) {
730
-
731
- // Determine the user_id.
732
- if ( ! empty( $filter['user_id'] ) ) {
733
- $user_id = $filter['user_id'];
734
- } else {
735
- $user_id = bp_displayed_user_id()
736
- ? bp_displayed_user_id()
737
- : bp_loggedin_user_id();
738
- }
739
-
740
- // Determine the favorites.
741
- $favs = bp_activity_get_user_favorites( $user_id );
742
- if ( empty( $favs ) ) {
743
- $favs = array( 0 );
744
- }
745
-
746
- // Should we show all items regardless of sitewide visibility?
747
- $show_hidden = array();
748
- if ( ! empty( $user_id ) && ( $user_id !== bp_loggedin_user_id() ) ) {
749
- $show_hidden = array(
750
- 'column' => 'hide_sitewide',
751
- 'value' => 0
752
- );
753
- }
754
-
755
- $retval = array(
756
- 'relation' => 'AND',
757
- array(
758
- 'column' => 'id',
759
- 'compare' => 'IN',
760
- 'value' => (array) $favs
761
- ),
762
- $show_hidden,
763
-
764
- // Overrides.
765
- 'override' => array(
766
- 'display_comments' => true,
767
- 'filter' => array( 'user_id' => 0 ),
768
- 'show_hidden' => true
769
- ),
770
- );
771
-
772
- return $retval;
773
- }
774
- add_filter( 'bp_activity_set_favorites_scope_args', 'bp_activity_filter_favorites_scope', 10, 2 );
775
-
776
-
777
- /**
778
- * Set up activity arguments for use with the 'favorites' scope.
779
- *
780
- * @since 2.2.0
781
- *
782
- * @param array $retval Empty array by default.
783
- * @param array $filter Current activity arguments.
784
- * @return array $retval
785
- */
786
- function bp_activity_filter_mentions_scope( $retval = array(), $filter = array() ) {
787
-
788
- // Are mentions disabled?
789
- if ( ! bp_activity_do_mentions() ) {
790
- return $retval;
791
- }
792
-
793
- // Determine the user_id.
794
- if ( ! empty( $filter['user_id'] ) ) {
795
- $user_id = $filter['user_id'];
796
- } else {
797
- $user_id = bp_displayed_user_id()
798
- ? bp_displayed_user_id()
799
- : bp_loggedin_user_id();
800
- }
801
-
802
- // Should we show all items regardless of sitewide visibility?
803
- $show_hidden = array();
804
- if ( ! empty( $user_id ) && $user_id !== bp_loggedin_user_id() ) {
805
- $show_hidden = array(
806
- 'column' => 'hide_sitewide',
807
- 'value' => 0
808
- );
809
- }
810
-
811
- $retval = array(
812
- 'relation' => 'AND',
813
- array(
814
- 'column' => 'content',
815
- 'compare' => 'LIKE',
816
-
817
- // Start search at @ symbol and stop search at closing tag delimiter.
818
- 'value' => '@' . bp_activity_get_user_mentionname( $user_id ) . '<'
819
- ),
820
- $show_hidden,
821
-
822
- // Overrides.
823
- 'override' => array(
824
- 'display_comments' => 'stream',
825
- 'filter' => array( 'user_id' => 0 ),
826
- 'show_hidden' => true
827
- ),
828
- );
829
-
830
- return $retval;
831
- }
832
- add_filter( 'bp_activity_set_mentions_scope_args', 'bp_activity_filter_mentions_scope', 10, 2 );
1
  <?php
2
+
3
  /**
4
  * Filters related to the Activity component.
5
  *
6
  * @package BuddyPress
7
  * @subpackage ActivityFilters
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
+ /** Filters *******************************************************************/
14
 
15
+ // Apply WordPress defined filters
16
  add_filter( 'bp_get_activity_action', 'bp_activity_filter_kses', 1 );
17
  add_filter( 'bp_get_activity_content_body', 'bp_activity_filter_kses', 1 );
18
  add_filter( 'bp_get_activity_content', 'bp_activity_filter_kses', 1 );
22
  add_filter( 'bp_get_activity_feed_item_description', 'bp_activity_filter_kses', 1 );
23
  add_filter( 'bp_activity_content_before_save', 'bp_activity_filter_kses', 1 );
24
  add_filter( 'bp_activity_action_before_save', 'bp_activity_filter_kses', 1 );
25
+ add_filter( 'bp_activity_latest_update_content', 'wp_filter_kses', 1 );
26
 
27
  add_filter( 'bp_get_activity_action', 'force_balance_tags' );
28
  add_filter( 'bp_get_activity_content_body', 'force_balance_tags' );
33
  add_filter( 'bp_activity_content_before_save', 'force_balance_tags' );
34
  add_filter( 'bp_activity_action_before_save', 'force_balance_tags' );
35
 
 
 
 
 
36
  add_filter( 'bp_get_activity_action', 'wptexturize' );
37
  add_filter( 'bp_get_activity_content_body', 'wptexturize' );
38
  add_filter( 'bp_get_activity_content', 'wptexturize' );
39
  add_filter( 'bp_get_activity_parent_content', 'wptexturize' );
40
  add_filter( 'bp_get_activity_latest_update', 'wptexturize' );
41
  add_filter( 'bp_get_activity_latest_update_excerpt', 'wptexturize' );
 
42
 
43
  add_filter( 'bp_get_activity_action', 'convert_smilies' );
44
  add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
46
  add_filter( 'bp_get_activity_parent_content', 'convert_smilies' );
47
  add_filter( 'bp_get_activity_latest_update', 'convert_smilies' );
48
  add_filter( 'bp_get_activity_latest_update_excerpt', 'convert_smilies' );
 
49
 
50
  add_filter( 'bp_get_activity_action', 'convert_chars' );
51
  add_filter( 'bp_get_activity_content_body', 'convert_chars' );
53
  add_filter( 'bp_get_activity_parent_content', 'convert_chars' );
54
  add_filter( 'bp_get_activity_latest_update', 'convert_chars' );
55
  add_filter( 'bp_get_activity_latest_update_excerpt', 'convert_chars' );
 
56
 
57
  add_filter( 'bp_get_activity_action', 'wpautop' );
58
  add_filter( 'bp_get_activity_content_body', 'wpautop' );
59
  add_filter( 'bp_get_activity_content', 'wpautop' );
60
  add_filter( 'bp_get_activity_feed_item_description', 'wpautop' );
 
61
 
62
  add_filter( 'bp_get_activity_action', 'make_clickable', 9 );
63
  add_filter( 'bp_get_activity_content_body', 'make_clickable', 9 );
66
  add_filter( 'bp_get_activity_latest_update', 'make_clickable', 9 );
67
  add_filter( 'bp_get_activity_latest_update_excerpt', 'make_clickable', 9 );
68
  add_filter( 'bp_get_activity_feed_item_description', 'make_clickable', 9 );
 
69
 
70
  add_filter( 'bp_acomment_name', 'stripslashes_deep', 5 );
71
  add_filter( 'bp_get_activity_action', 'stripslashes_deep', 5 );
78
 
79
  add_filter( 'bp_activity_primary_link_before_save', 'esc_url_raw' );
80
 
81
+ // Apply BuddyPress-defined filters
82
  add_filter( 'bp_get_activity_content', 'bp_activity_make_nofollow_filter' );
83
  add_filter( 'bp_get_activity_content_body', 'bp_activity_make_nofollow_filter' );
84
  add_filter( 'bp_get_activity_parent_content', 'bp_activity_make_nofollow_filter' );
90
  add_filter( 'group_forum_topic_text_before_save', 'bp_activity_at_name_filter' );
91
  add_filter( 'group_forum_post_text_before_save', 'bp_activity_at_name_filter' );
92
  add_filter( 'the_content', 'bp_activity_at_name_filter' );
 
93
 
94
  add_filter( 'bp_get_activity_parent_content', 'bp_create_excerpt' );
95
 
96
  add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
97
  add_filter( 'bp_get_activity_content', 'bp_activity_truncate_entry', 5 );
98
 
99
+ /** Actions *******************************************************************/
 
 
 
100
 
101
+ // At-name filter
 
 
102
  add_action( 'bp_activity_before_save', 'bp_activity_at_name_filter_updates' );
103
 
104
+ // Activity stream moderation
105
  add_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2, 1 );
106
  add_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2, 1 );
107
 
110
  /**
111
  * Types of activity stream items to moderate.
112
  *
113
+ * @since BuddyPress (1.6)
114
  *
115
  * @return array $types List of the activity types to moderate.
116
  */
119
  'activity_comment',
120
  'activity_update'
121
  );
 
 
 
 
 
 
 
 
122
  return apply_filters( 'bp_activity_check_activity_types', $types );
123
  }
124
 
125
  /**
126
  * Moderate the posted activity item, if it contains moderate keywords.
127
  *
128
+ * @since BuddyPress (1.6)
129
  *
130
  * @param BP_Activity_Activity $activity The activity object to check.
131
  */
132
  function bp_activity_check_moderation_keys( $activity ) {
133
 
134
+ // Only check specific types of activity updates
135
+ if ( !in_array( $activity->type, bp_activity_get_moderated_activity_types() ) )
136
  return;
 
 
 
 
 
 
 
137
 
138
+ // Unset the activity component so activity stream update fails
139
+ // @todo This is temporary until some kind of moderation is built
140
+ if ( !bp_core_check_for_moderation( $activity->user_id, '', $activity->content ) )
141
  $activity->component = false;
 
142
  }
143
 
144
  /**
145
  * Mark the posted activity as spam, if it contains blacklist keywords.
146
  *
147
+ * @since BuddyPress (1.6)
148
  *
149
  * @param BP_Activity_Activity $activity The activity object to check.
150
  */
151
  function bp_activity_check_blacklist_keys( $activity ) {
152
 
153
+ // Only check specific types of activity updates
154
+ if ( ! in_array( $activity->type, bp_activity_get_moderated_activity_types() ) )
155
  return;
 
 
 
 
 
 
 
156
 
157
+ // Mark as spam
158
+ if ( ! bp_core_check_for_blacklist( $activity->user_id, '', $activity->content ) )
159
+ bp_activity_mark_as_spam( $activity, 'by_blacklist' );
160
  }
161
 
162
  /**
163
  * Custom kses filtering for activity content.
164
  *
165
+ * @since BuddyPress (1.1)
166
+ *
167
+ * @uses apply_filters() To call the 'bp_activity_allowed_tags' hook.
168
+ * @uses wp_kses()
169
  *
170
  * @param string $content The activity content.
171
  * @return string $content Filtered activity content.
174
  global $allowedtags;
175
 
176
  $activity_allowedtags = $allowedtags;
177
+ $activity_allowedtags['span'] = array();
178
+ $activity_allowedtags['span']['class'] = array();
179
+ $activity_allowedtags['a']['class'] = array();
180
+ $activity_allowedtags['a']['id'] = array();
181
+ $activity_allowedtags['a']['rel'] = array();
 
 
 
 
182
  $activity_allowedtags['img'] = array();
183
  $activity_allowedtags['img']['src'] = array();
184
  $activity_allowedtags['img']['alt'] = array();
187
  $activity_allowedtags['img']['class'] = array();
188
  $activity_allowedtags['img']['id'] = array();
189
  $activity_allowedtags['img']['title'] = array();
190
+ $activity_allowedtags['code'] = array();
191
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  $activity_allowedtags = apply_filters( 'bp_activity_allowed_tags', $activity_allowedtags );
193
  return wp_kses( $content, $activity_allowedtags );
194
  }
196
  /**
197
  * Find and link @-mentioned users in the contents of a given item.
198
  *
199
+ * @since BuddyPress (1.2.0)
200
  *
201
+ * @param string $content The contents of a given item.
202
+ * @param int $activity_id The activity id. Deprecated.
203
  * @return string $content Content filtered for mentions.
204
  */
205
  function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
209
  return $content;
210
  }
211
 
212
+ // Try to find mentions
213
  $usernames = bp_activity_find_mentions( $content );
214
 
215
  // No mentions? Stop now!
217
  return $content;
218
 
219
  // We don't want to link @mentions that are inside of links, so we
220
+ // temporarily remove them
221
  $replace_count = 0;
222
  $replacements = array();
223
  foreach ( $usernames as $username ) {
224
+ // prevent @ name linking inside <a> tags
225
  preg_match_all( '/(<a.*?(?!<\/a>)@' . $username . '.*?<\/a>)/', $content, $content_matches );
226
  if ( ! empty( $content_matches[1] ) ) {
227
  foreach ( $content_matches[1] as $replacement ) {
232
  }
233
  }
234
 
235
+ // Linkify the mentions with the username
236
  foreach ( (array) $usernames as $user_id => $username ) {
237
+ $content = preg_replace( '/(@' . $username . '\b)/', "<a href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $content );
238
  }
239
 
240
+ // put everything back
241
  if ( ! empty( $replacements ) ) {
242
  foreach ( $replacements as $placeholder => $original ) {
243
  $content = str_replace( $placeholder, $original, $content );
244
  }
245
  }
246
 
247
+ // Return the content
248
  return $content;
249
  }
250
 
254
  * If mentions are found, replace @mention text with user links and add our
255
  * hook to send mention notifications after the activity item is saved.
256
  *
257
+ * @since BuddyPress (1.5)
258
  *
259
+ * @uses bp_activity_find_mentions()
260
+ *
261
+ * @param BP_Activity_Activity $activity
262
  */
263
  function bp_activity_at_name_filter_updates( $activity ) {
264
  // Are mentions disabled?
270
  if ( ! empty( $activity->is_spam ) )
271
  return;
272
 
273
+ // Try to find mentions
274
  $usernames = bp_activity_find_mentions( $activity->content );
275
 
276
  // We have mentions!
277
  if ( ! empty( $usernames ) ) {
278
+ // Replace @mention text with userlinks
279
  foreach( (array) $usernames as $user_id => $username ) {
280
+ $activity->content = preg_replace( '/(@' . $username . '\b)/', "<a href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $activity->content );
281
  }
282
 
283
+ // Add our hook to send @mention emails after the activity item is saved
284
  add_action( 'bp_activity_after_save', 'bp_activity_at_name_send_emails' );
285
 
286
+ // temporary variable to avoid having to run bp_activity_find_mentions() again
287
  buddypress()->activity->mentioned_users = $usernames;
288
  }
289
  }
291
  /**
292
  * Sends emails and BP notifications for users @-mentioned in an activity item.
293
  *
294
+ * @since BuddyPress (1.7)
295
+ *
296
+ * @uses bp_activity_at_message_notification()
297
+ * @uses bp_activity_update_mention_count_for_user()
298
  *
299
+ * @param BP_Activity_Activity $activity The BP_Activity_Activity object
300
  */
301
  function bp_activity_at_name_send_emails( $activity ) {
302
  // Are mentions disabled?
308
  if ( empty( buddypress()->activity->mentioned_users ) )
309
  return;
310
 
311
+ // Grab our temporary variable from bp_activity_at_name_filter_updates()
312
  $usernames = buddypress()->activity->mentioned_users;
313
 
314
+ // Get rid of temporary variable
315
  unset( buddypress()->activity->mentioned_users );
316
 
317
+ // Send @mentions and setup BP notifications
318
  foreach( (array) $usernames as $user_id => $username ) {
319
+ // If you want to disable notifications, you can use this filter to stop email sending
320
+ if ( apply_filters( 'bp_activity_at_name_do_notifications', true, $usernames ) ) {
 
 
 
 
 
 
 
 
 
 
 
321
  bp_activity_at_message_notification( $activity->id, $user_id );
322
  }
323
 
324
+ // Updates mention count for the user
325
  bp_activity_update_mention_count_for_user( $user_id, $activity->id );
326
  }
327
  }
329
  /**
330
  * Catch links in activity text so rel=nofollow can be added.
331
  *
332
+ * @since BuddyPress (1.2)
333
  *
334
  * @param string $text Activity text.
335
  * @return string $text Text with rel=nofollow added to any links.
341
  /**
342
  * Add rel=nofollow to a link.
343
  *
344
+ * @since BuddyPress (1.2)
345
+ *
346
+ * @param array $matches
347
  *
348
  * @param array $matches Items matched by preg_replace_callback() in bp_activity_make_nofollow_filter().
349
+ * @return string $text Link with rel=nofollow added
350
  */
351
  function bp_activity_make_nofollow_filter_callback( $matches ) {
352
  $text = $matches[1];
357
  /**
358
  * Truncate long activity entries when viewed in activity streams.
359
  *
360
+ * @since BuddyPress (1.5)
361
  *
362
+ * @uses bp_is_single_activity()
363
+ * @uses apply_filters() To call the 'bp_activity_excerpt_append_text' hook.
364
+ * @uses apply_filters() To call the 'bp_activity_excerpt_length' hook.
365
+ * @uses bp_create_excerpt()
366
+ * @uses bp_get_activity_id()
367
+ * @uses bp_get_activity_thread_permalink()
368
+ * @uses apply_filters() To call the 'bp_activity_truncate_entry' hook.
369
  *
370
  * @param string $text The original activity entry text.
 
 
 
 
371
  * @return string $excerpt The truncated text.
372
  */
373
+ function bp_activity_truncate_entry( $text ) {
374
  global $activities_template;
375
 
376
+ // The full text of the activity update should always show on the single activity screen
377
+ if ( bp_is_single_activity() )
 
 
 
 
 
 
 
 
 
 
 
 
378
  return $text;
 
379
 
 
 
 
 
 
 
 
380
  $append_text = apply_filters( 'bp_activity_excerpt_append_text', __( '[Read more]', 'buddypress' ) );
381
+ $excerpt_length = apply_filters( 'bp_activity_excerpt_length', 358 );
382
 
383
+ // Run the text through the excerpt function. If it's too short, the original text will be
384
+ // returned.
385
+ $excerpt = bp_create_excerpt( $text, $excerpt_length, array( 'ending' => __( '&hellip;', 'buddypress' ) ) );
 
 
 
386
 
387
+ // If the text returned by bp_create_excerpt() is different from the original text (ie it's
388
+ // been truncated), add the "Read More" link. Note that bp_create_excerpt() is stripping
389
+ // shortcodes, so we have strip them from the $text before the comparison
390
+ if ( $excerpt != strip_shortcodes( $text ) ) {
 
 
391
  $id = !empty( $activities_template->activity->current_comment->id ) ? 'acomment-read-more-' . $activities_template->activity->current_comment->id : 'activity-read-more-' . bp_get_activity_id();
392
 
393
  $excerpt = sprintf( '%1$s<span class="activity-read-more" id="%2$s"><a href="%3$s" rel="nofollow">%4$s</a></span>', $excerpt, $id, bp_get_activity_thread_permalink(), $append_text );
394
  }
395
 
 
 
 
 
 
 
 
 
 
396
  return apply_filters( 'bp_activity_truncate_entry', $excerpt, $text, $append_text );
397
  }
398
 
399
  /**
400
+ * Include extra javascript dependencies for activity component.
401
+ *
402
+ * @since BuddyPress (2.0.0)
403
  *
404
+ * @uses bp_activity_do_heartbeat() to check if heartbeat is required.
405
  *
406
  * @param array $js_handles The original dependencies.
407
  * @return array $js_handles The new dependencies.
421
  * We use these classes to avoid pagination issues when items are loaded
422
  * dynamically into the activity stream.
423
  *
424
+ * @since BuddyPress (2.0.0)
425
  *
426
+ * @param string $classes
427
  * @return string $classes
428
  */
429
  function bp_activity_newest_class( $classes = '' ) {
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 = '' ) {
456
  if ( empty( $activity_date ) ) {
457
  return $classes;
458
  }
459
+
460
  $classes .= ' date-recorded-' . strtotime( $activity_date );
461
 
462
  return $classes;
466
  /**
467
  * Use WordPress Heartbeat API to check for latest activity update.
468
  *
469
+ * @since BuddyPress (2.0.0)
470
  *
471
+ * @uses bp_activity_get_last_updated() to get the recorded date of the last activity
472
+ *
473
+ * @param array $response
474
+ * @param array $data
475
  * @return array $response
476
  */
477
  function bp_activity_heartbeat_last_recorded( $response = array(), $data = array() ) {
478
+ $bp = buddypress();
479
+
480
  if ( empty( $data['bp_activity_last_recorded'] ) ) {
481
  return $response;
482
  }
483
 
484
  // Use the querystring argument stored in the cookie (to preserve
485
+ // filters), but force the offset to get only new items
486
  $activity_latest_args = bp_parse_args(
487
  bp_ajax_querystring( 'activity' ),
488
  array( 'since' => date( 'Y-m-d H:i:s', $data['bp_activity_last_recorded'] ) ),
489
  'activity_latest_args'
490
  );
491
 
 
 
 
 
492
  $newest_activities = array();
493
  $last_activity_recorded = 0;
494
 
495
+ // Temporarly add a just-posted class for new activity items
496
  add_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 );
497
 
498
  ob_start();
513
  $newest_activities['last_recorded'] = $last_activity_recorded;
514
  ob_end_clean();
515
 
516
+ // Remove the temporary filter
517
+ remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 );
518
 
519
  if ( ! empty( $newest_activities['last_recorded'] ) ) {
520
  $response['bp_activity_newest_activities'] = $newest_activities;
528
  /**
529
  * Set the strings for WP HeartBeat API where needed.
530
  *
531
+ * @since BuddyPress (2.0.0)
532
  *
533
  * @param array $strings Localized strings.
534
  * @return array $strings
541
 
542
  $global_pulse = 0;
543
 
544
+ // Check whether the global heartbeat settings already exist.
 
 
 
 
 
 
545
  $heartbeat_settings = apply_filters( 'heartbeat_settings', array() );
546
  if ( ! empty( $heartbeat_settings['interval'] ) ) {
547
  // 'Fast' is 5
548
  $global_pulse = is_numeric( $heartbeat_settings['interval'] ) ? absint( $heartbeat_settings['interval'] ) : 5;
549
  }
550
 
551
+ // Filter here to specify a BP-specific pulse frequency
 
 
 
 
 
 
552
  $bp_activity_pulse = apply_filters( 'bp_activity_heartbeat_pulse', 15 );
553
 
554
  /**
571
  return $strings;
572
  }
573
  add_filter( 'bp_core_get_js_strings', 'bp_activity_heartbeat_strings', 10, 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-functions.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Activity Functions.
4
  *
@@ -6,21 +7,24 @@
6
  *
7
  * @package BuddyPress
8
  * @subpackage ActivityFunctions
9
- * @since 1.5.0
10
  */
11
 
12
- // Exit if accessed directly.
13
- defined( 'ABSPATH' ) || exit;
14
 
15
  /**
16
  * Check whether the $bp global lists an activity directory page.
17
  *
18
- * @since 1.5.0
 
 
19
  *
20
  * @return bool True if activity directory page is found, otherwise false.
21
  */
22
  function bp_activity_has_directory() {
23
- return (bool) !empty( buddypress()->pages->activity->id );
 
 
24
  }
25
 
26
  /**
@@ -28,123 +32,72 @@ function bp_activity_has_directory() {
28
  *
29
  * The Mentions feature does a number of things, all of which will be turned
30
  * off if you disable mentions:
31
- * - Detecting and auto-linking @username in all BP/WP content.
32
  * - Sending BP notifications and emails to users when they are mentioned
33
- * using the @username syntax.
34
- * - The Public Message button on user profiles.
35
  *
36
  * Mentions are enabled by default. To disable, put the following line in
37
  * bp-custom.php or your theme's functions.php file:
38
  *
39
  * add_filter( 'bp_activity_do_mentions', '__return_false' );
40
  *
41
- * @since 1.8.0
 
 
42
  *
43
  * @return bool $retval True to enable mentions, false to disable.
44
  */
45
  function bp_activity_do_mentions() {
46
-
47
- /**
48
- * Filters whether or not mentions are enabled.
49
- *
50
- * @since 1.8.0
51
- *
52
- * @param bool $enabled True to enable mentions, false to disable.
53
- */
54
  return (bool) apply_filters( 'bp_activity_do_mentions', true );
55
  }
56
 
57
- /**
58
- * Should BuddyPress load the mentions scripts and related assets, including results to prime the
59
- * mentions suggestions?
60
- *
61
- * @since 2.1.0
62
- *
63
- * @return bool True if mentions scripts should be loaded.
64
- */
65
- function bp_activity_maybe_load_mentions_scripts() {
66
- $mentions_enabled = bp_activity_do_mentions() && bp_is_user_active();
67
- $load_mentions = $mentions_enabled && ( bp_is_activity_component() || is_admin() );
68
-
69
- /**
70
- * Filters whether or not BuddyPress should load mentions scripts and assets.
71
- *
72
- * @since 2.1.0
73
- *
74
- * @param bool $load_mentions True to load mentions assets, false otherwise.
75
- * @param bool $mentions_enabled True if mentions are enabled.
76
- */
77
- return (bool) apply_filters( 'bp_activity_maybe_load_mentions_scripts', $load_mentions, $mentions_enabled );
78
- }
79
-
80
  /**
81
  * Locate usernames in an activity content string, as designated by an @ sign.
82
  *
83
- * @since 1.5.0
84
  *
85
- * @param string $content The content of the activity, usually found in
86
- * $activity->content.
87
- * @return array|bool Associative array with user ID as key and username as
88
- * value. Boolean false if no mentions found.
89
  */
90
  function bp_activity_find_mentions( $content ) {
91
-
92
  $pattern = '/[@]+([A-Za-z0-9-_\.@]+)\b/';
93
  preg_match_all( $pattern, $content, $usernames );
94
 
95
- // Make sure there's only one instance of each username.
96
- $usernames = array_unique( $usernames[1] );
97
-
98
- // Bail if no usernames.
99
- if ( empty( $usernames ) ) {
100
  return false;
101
- }
102
 
103
  $mentioned_users = array();
104
 
105
- // We've found some mentions! Check to see if users exist.
106
- foreach( (array) array_values( $usernames ) as $username ) {
107
  $user_id = bp_activity_get_userid_from_mentionname( $username );
108
 
109
- // The user ID exists, so let's add it to our array.
110
  if ( ! empty( $user_id ) ) {
111
- $mentioned_users[ $user_id ] = $username;
112
  }
113
  }
114
 
115
- if ( empty( $mentioned_users ) ) {
116
  return false;
117
- }
118
 
119
- /**
120
- * Filters the mentioned users.
121
- *
122
- * @since 2.5.0
123
- *
124
- * @param array $mentioned_users Associative array with user IDs as keys and usernames as values.
125
- */
126
- return apply_filters( 'bp_activity_mentioned_users', $mentioned_users );
127
  }
128
 
129
  /**
130
  * Reset a user's unread mentions list and count.
131
  *
132
- * @since 1.5.0
 
 
133
  *
134
  * @param int $user_id The id of the user whose unread mentions are being reset.
135
  */
136
  function bp_activity_clear_new_mentions( $user_id ) {
137
  bp_delete_user_meta( $user_id, 'bp_new_mention_count' );
138
- bp_delete_user_meta( $user_id, 'bp_new_mentions' );
139
-
140
- /**
141
- * Fires once mentions has been reset for a given user.
142
- *
143
- * @since 2.5.0
144
- *
145
- * @param int $user_id The id of the user whose unread mentions are being reset.
146
- */
147
- do_action( 'bp_activity_clear_new_mentions', $user_id );
148
  }
149
 
150
  /**
@@ -155,32 +108,30 @@ function bp_activity_clear_new_mentions( $user_id ) {
155
  *
156
  * Currently, only used in {@link bp_activity_delete()}.
157
  *
158
- * @since 1.5.0
159
  *
160
- * @param int $activity_id The unique id for the activity item.
161
- * @param string $action Can be 'delete' or 'add'. Defaults to 'add'.
162
- * @return bool
 
 
163
  */
164
  function bp_activity_adjust_mention_count( $activity_id = 0, $action = 'add' ) {
165
-
166
- // Bail if no activity ID passed.
167
- if ( empty( $activity_id ) ) {
168
  return false;
169
- }
170
 
171
- // Get activity object.
172
- $activity = new BP_Activity_Activity( $activity_id );
173
 
174
- // Try to find mentions.
175
  $usernames = bp_activity_find_mentions( strip_tags( $activity->content ) );
176
 
177
- // Still empty? Stop now.
178
- if ( empty( $usernames ) ) {
179
  return false;
180
- }
181
 
182
- // Increment mention count foreach mentioned user.
183
- foreach( (array) array_keys( $usernames ) as $user_id ) {
184
  bp_activity_update_mention_count_for_user( $user_id, $activity_id, $action );
185
  }
186
  }
@@ -191,27 +142,24 @@ function bp_activity_adjust_mention_count( $activity_id = 0, $action = 'add' ) {
191
  * This function should be used when you've already parsed your activity item
192
  * for @mentions.
193
  *
194
- * @since 1.7.0
195
  *
196
- * @param int $user_id The user ID.
197
- * @param int $activity_id The unique ID for the activity item.
198
- * @param string $action 'delete' or 'add'. Default: 'add'.
 
 
 
199
  * @return bool
200
  */
201
  function bp_activity_update_mention_count_for_user( $user_id, $activity_id, $action = 'add' ) {
202
-
203
- if ( empty( $user_id ) || empty( $activity_id ) ) {
204
  return false;
205
- }
206
 
207
- // Adjust the mention list and count for the member.
208
  $new_mention_count = (int) bp_get_user_meta( $user_id, 'bp_new_mention_count', true );
209
- $new_mentions = bp_get_user_meta( $user_id, 'bp_new_mentions', true );
210
-
211
- // Make sure new mentions is an array.
212
- if ( empty( $new_mentions ) ) {
213
  $new_mentions = array();
214
- }
215
 
216
  switch ( $action ) {
217
  case 'delete' :
@@ -232,10 +180,10 @@ function bp_activity_update_mention_count_for_user( $user_id, $activity_id, $act
232
  break;
233
  }
234
 
235
- // Get an updated mention count.
236
  $new_mention_count = count( $new_mentions );
237
 
238
- // Resave the user_meta.
239
  bp_update_user_meta( $user_id, 'bp_new_mention_count', $new_mention_count );
240
  bp_update_user_meta( $user_id, 'bp_new_mentions', $new_mentions );
241
 
@@ -245,10 +193,9 @@ function bp_activity_update_mention_count_for_user( $user_id, $activity_id, $act
245
  /**
246
  * Determine a user's "mentionname", the name used for that user in @-mentions.
247
  *
248
- * @since 1.9.0
249
  *
250
- * @param int|string $user_id ID of the user to get @-mention name for.
251
- * @return string $mentionname User name appropriate for @-mentions.
252
  */
253
  function bp_activity_get_user_mentionname( $user_id ) {
254
  $mentionname = '';
@@ -269,24 +216,21 @@ function bp_activity_get_user_mentionname( $user_id ) {
269
  /**
270
  * Get a user ID from a "mentionname", the name used for a user in @-mentions.
271
  *
272
- * @since 1.9.0
273
  *
274
- * @param string $mentionname Username of user in @-mentions.
275
  * @return int|bool ID of the user, if one is found. Otherwise false.
276
  */
277
  function bp_activity_get_userid_from_mentionname( $mentionname ) {
278
  $user_id = false;
279
 
280
- /*
281
- * In username compatibility mode, hyphens are ambiguous between
282
- * actual hyphens and converted spaces.
283
- *
284
- * @todo There is the potential for username clashes between 'foo bar'
285
- * and 'foo-bar' in compatibility mode. Come up with a system for
286
- * unique mentionnames.
287
- */
288
  if ( bp_is_username_compatibility_mode() ) {
289
- // First, try the raw username.
290
  $userdata = get_user_by( 'login', $mentionname );
291
 
292
  // Doing a direct query to use proper regex. Necessary to
@@ -300,7 +244,7 @@ function bp_activity_get_userid_from_mentionname( $mentionname ) {
300
  }
301
 
302
  // When username compatibility mode is disabled, the mentionname is
303
- // the same as the nicename.
304
  } else {
305
  $user_id = bp_core_get_userid_from_nicename( $mentionname );
306
  }
@@ -325,32 +269,28 @@ function bp_activity_get_userid_from_mentionname( $mentionname ) {
325
  * panel, and dynamic action generation (which is essential for multilingual
326
  * sites, etc) will not work.
327
  *
328
- * @since 1.1.0
329
  *
330
- * @param string $component_id The unique string ID of the component.
331
- * @param string $type The action type.
332
- * @param string $description The action description.
333
- * @param callable|bool $format_callback Callback for formatting the action string.
334
- * @param string|bool $label String to describe this action in the activity stream filter dropdown.
335
- * @param array $context Optional. Activity stream contexts where the filter should appear.
336
- * Values: 'activity', 'member', 'member_groups', 'group'.
337
- * @param int $position Optional. The position of the action when listed in dropdowns.
338
  * @return bool False if any param is empty, otherwise true.
339
  */
340
- function bp_activity_set_action( $component_id, $type, $description, $format_callback = false, $label = false, $context = array(), $position = 0 ) {
341
  $bp = buddypress();
342
 
343
- // Return false if any of the above values are not set.
344
  if ( empty( $component_id ) || empty( $type ) || empty( $description ) ) {
345
  return false;
346
  }
347
 
348
- // Set activity action.
349
  if ( ! isset( $bp->activity->actions ) || ! is_object( $bp->activity->actions ) ) {
350
  $bp->activity->actions = new stdClass;
351
  }
352
 
353
- // Verify callback.
354
  if ( ! is_callable( $format_callback ) ) {
355
  $format_callback = '';
356
  }
@@ -359,458 +299,41 @@ function bp_activity_set_action( $component_id, $type, $description, $format_cal
359
  $bp->activity->actions->{$component_id} = new stdClass;
360
  }
361
 
362
- /**
363
- * Filters the action type being set for the current activity item.
364
- *
365
- * @since 1.1.0
366
- *
367
- * @param array $array Array of arguments for action type being set.
368
- * @param string $component_id ID of the current component being set.
369
- * @param string $type Action type being set.
370
- * @param string $description Action description for action being set.
371
- * @param callable $format_callback Callback for formatting the action string.
372
- * @param string $label String to describe this action in the activity stream filter dropdown.
373
- * @param array $context Activity stream contexts where the filter should appear. 'activity', 'member',
374
- * 'member_groups', 'group'.
375
- */
376
  $bp->activity->actions->{$component_id}->{$type} = apply_filters( 'bp_activity_set_action', array(
377
  'key' => $type,
378
  'value' => $description,
379
  'format_callback' => $format_callback,
380
- 'label' => $label,
381
- 'context' => $context,
382
- 'position' => $position,
383
- ), $component_id, $type, $description, $format_callback, $label, $context );
384
-
385
- // Sort the actions of the affected component.
386
- $action_array = (array) $bp->activity->actions->{$component_id};
387
- $action_array = bp_sort_by_key( $action_array, 'position', 'num' );
388
-
389
- // Restore keys.
390
- $bp->activity->actions->{$component_id} = new stdClass;
391
- foreach ( $action_array as $key_ordered ) {
392
- $bp->activity->actions->{$component_id}->{$key_ordered['key']} = $key_ordered;
393
- }
394
 
395
  return true;
396
  }
397
 
398
  /**
399
- * Set tracking arguments for a given post type.
400
- *
401
- * @since 2.2.0
402
- *
403
- * @global $wp_post_types
404
- *
405
- * @param string $post_type The name of the post type, as registered with WordPress. Eg 'post' or 'page'.
406
- * @param array $args {
407
- * An associative array of tracking parameters. All items are optional.
408
- * @type string $bp_activity_admin_filter String to use in the Dashboard > Activity dropdown.
409
- * @type string $bp_activity_front_filter String to use in the front-end dropdown.
410
- * @type string $bp_activity_new_post String format to use for generating the activity action. Should be a
411
- * translatable string where %1$s is replaced by a user link and %2$s is
412
- * the URL of the newly created post.
413
- * @type string $bp_activity_new_post_ms String format to use for generating the activity action on Multisite.
414
- * Should be a translatable string where %1$s is replaced by a user link,
415
- * %2$s is the URL of the newly created post, and %3$s is a link to
416
- * the site.
417
- * @type string $component_id ID of the BuddyPress component to associate the activity item.
418
- * @type string $action_id Value for the 'type' param of the new activity item.
419
- * @type callable $format_callback Callback for formatting the activity action string.
420
- * Default: 'bp_activity_format_activity_action_custom_post_type_post'.
421
- * @type array $contexts The directory contexts in which the filter will show.
422
- * Default: array( 'activity' ).
423
- * @type array $position Position of the item in filter dropdowns.
424
- * @type string $singular Singular, translatable name of the post type item. If no value is
425
- * provided, it's pulled from the 'singular_name' of the post type.
426
- * @type bool $activity_comment Whether to allow comments on the activity items. Defaults to true if
427
- * the post type does not natively support comments, otherwise false.
428
- * }
429
- * @return bool
430
- */
431
- function bp_activity_set_post_type_tracking_args( $post_type = '', $args = array() ) {
432
- global $wp_post_types;
433
-
434
- if ( empty( $wp_post_types[ $post_type ] ) || ! post_type_supports( $post_type, 'buddypress-activity' ) || ! is_array( $args ) ) {
435
- return false;
436
- }
437
-
438
- $activity_labels = array(
439
- /* Post labels */
440
- 'bp_activity_admin_filter',
441
- 'bp_activity_front_filter',
442
- 'bp_activity_new_post',
443
- 'bp_activity_new_post_ms',
444
- /* Comment labels */
445
- 'bp_activity_comments_admin_filter',
446
- 'bp_activity_comments_front_filter',
447
- 'bp_activity_new_comment',
448
- 'bp_activity_new_comment_ms'
449
- );
450
-
451
- // Labels are loaded into the post type object.
452
- foreach ( $activity_labels as $label_type ) {
453
- if ( ! empty( $args[ $label_type ] ) ) {
454
- $wp_post_types[ $post_type ]->labels->{$label_type} = $args[ $label_type ];
455
- unset( $args[ $label_type ] );
456
- }
457
- }
458
-
459
- // If there are any additional args, put them in the bp_activity attribute of the post type.
460
- if ( ! empty( $args ) ) {
461
- $wp_post_types[ $post_type ]->bp_activity = $args;
462
- }
463
- }
464
-
465
- /**
466
- * Get tracking arguments for a specific post type.
467
- *
468
- * @since 2.2.0
469
- * @since 2.5.0 Add post type comments tracking args
470
- *
471
- * @param string $post_type Name of the post type.
472
- * @return object The tracking arguments of the post type.
473
- */
474
- function bp_activity_get_post_type_tracking_args( $post_type ) {
475
- if ( ! post_type_supports( $post_type, 'buddypress-activity' ) ) {
476
- return false;
477
- }
478
-
479
- $post_type_object = get_post_type_object( $post_type );
480
- $post_type_support_comments = post_type_supports( $post_type, 'comments' );
481
-
482
- $post_type_activity = array(
483
- 'component_id' => buddypress()->activity->id,
484
- 'action_id' => 'new_' . $post_type,
485
- 'format_callback' => 'bp_activity_format_activity_action_custom_post_type_post',
486
- 'front_filter' => $post_type_object->labels->name,
487
- 'contexts' => array( 'activity' ),
488
- 'position' => 0,
489
- 'singular' => strtolower( $post_type_object->labels->singular_name ),
490
- 'activity_comment' => ! $post_type_support_comments,
491
- 'comment_action_id' => false,
492
- 'comment_format_callback' => 'bp_activity_format_activity_action_custom_post_type_comment',
493
- );
494
-
495
- if ( ! empty( $post_type_object->bp_activity ) ) {
496
- $post_type_activity = bp_parse_args( (array) $post_type_object->bp_activity, $post_type_activity, $post_type . '_tracking_args' );
497
- }
498
-
499
- $post_type_activity = (object) $post_type_activity;
500
-
501
- // Try to get the admin filter from the post type labels.
502
- if ( ! empty( $post_type_object->labels->bp_activity_admin_filter ) ) {
503
- $post_type_activity->admin_filter = $post_type_object->labels->bp_activity_admin_filter;
504
-
505
- // Fall back to a generic name.
506
- } else {
507
- $post_type_activity->admin_filter = _x( 'New item published', 'Post Type generic activity post admin filter', 'buddypress' );
508
- }
509
-
510
- // Check for the front filter in the post type labels.
511
- if ( ! empty( $post_type_object->labels->bp_activity_front_filter ) ) {
512
- $post_type_activity->front_filter = $post_type_object->labels->bp_activity_front_filter;
513
- }
514
-
515
- // Try to get the action for new post type action on non-multisite installations.
516
- if ( ! empty( $post_type_object->labels->bp_activity_new_post ) ) {
517
- $post_type_activity->new_post_type_action = $post_type_object->labels->bp_activity_new_post;
518
- }
519
-
520
- // Try to get the action for new post type action on multisite installations.
521
- if ( ! empty( $post_type_object->labels->bp_activity_new_post_ms ) ) {
522
- $post_type_activity->new_post_type_action_ms = $post_type_object->labels->bp_activity_new_post_ms;
523
- }
524
-
525
- // If the post type supports comments and has a comment action id, build the comments tracking args
526
- if ( $post_type_support_comments && ! empty( $post_type_activity->comment_action_id ) ) {
527
- // Init a new container for the activity type for comments
528
- $post_type_activity->comments_tracking = new stdClass();
529
-
530
- // Build the activity type for comments
531
- $post_type_activity->comments_tracking->component_id = $post_type_activity->component_id;
532
- $post_type_activity->comments_tracking->action_id = $post_type_activity->comment_action_id;
533
-
534
- // Try to get the comments admin filter from the post type labels.
535
- if ( ! empty( $post_type_object->labels->bp_activity_comments_admin_filter ) ) {
536
- $post_type_activity->comments_tracking->admin_filter = $post_type_object->labels->bp_activity_comments_admin_filter;
537
-
538
- // Fall back to a generic name.
539
- } else {
540
- $post_type_activity->comments_tracking->admin_filter = _x( 'New item comment posted', 'Post Type generic comments activity admin filter', 'buddypress' );
541
- }
542
-
543
- $post_type_activity->comments_tracking->format_callback = $post_type_activity->comment_format_callback;
544
-
545
- // Check for the comments front filter in the post type labels.
546
- if ( ! empty( $post_type_object->labels->bp_activity_comments_front_filter ) ) {
547
- $post_type_activity->comments_tracking->front_filter = $post_type_object->labels->bp_activity_comments_front_filter;
548
-
549
- // Fall back to a generic name.
550
- } else {
551
- $post_type_activity->comments_tracking->front_filter = _x( 'Item comments', 'Post Type generic comments activity front filter', 'buddypress' );
552
- }
553
-
554
- $post_type_activity->comments_tracking->contexts = $post_type_activity->contexts;
555
- $post_type_activity->comments_tracking->position = (int) $post_type_activity->position + 1;
556
-
557
- // Try to get the action for new post type comment action on non-multisite installations.
558
- if ( ! empty( $post_type_object->labels->bp_activity_new_comment ) ) {
559
- $post_type_activity->comments_tracking->new_post_type_comment_action = $post_type_object->labels->bp_activity_new_comment;
560
- }
561
-
562
- // Try to get the action for new post type comment action on multisite installations.
563
- if ( ! empty( $post_type_object->labels->bp_activity_new_comment_ms ) ) {
564
- $post_type_activity->comments_tracking->new_post_type_comment_action_ms = $post_type_object->labels->bp_activity_new_comment_ms;
565
- }
566
- }
567
-
568
- // Finally make sure we'll be able to find the post type this activity type is associated to.
569
- $post_type_activity->post_type = $post_type;
570
-
571
- /**
572
- * Filters tracking arguments for a specific post type.
573
- *
574
- * @since 2.2.0
575
- *
576
- * @param object $post_type_activity The tracking arguments of the post type.
577
- * @param string $post_type Name of the post type.
578
- */
579
- return apply_filters( 'bp_activity_get_post_type_tracking_args', $post_type_activity, $post_type );
580
- }
581
-
582
- /**
583
- * Get tracking arguments for all post types.
584
- *
585
- * @since 2.2.0
586
- * @since 2.5.0 Include post type comments tracking args if needed
587
- *
588
- * @return array List of post types with their tracking arguments.
589
- */
590
- function bp_activity_get_post_types_tracking_args() {
591
- // Fetch all public post types.
592
- $post_types = get_post_types( array( 'public' => true ), 'names' );
593
-
594
- $post_types_tracking_args = array();
595
-
596
- foreach ( $post_types as $post_type ) {
597
- $track_post_type = bp_activity_get_post_type_tracking_args( $post_type );
598
-
599
- if ( ! empty( $track_post_type ) ) {
600
- // Set the post type comments tracking args
601
- if ( ! empty( $track_post_type->comments_tracking->action_id ) ) {
602
- // Used to check support for comment tracking by activity type (new_post_type_comment)
603
- $track_post_type->comments_tracking->comments_tracking = true;
604
-
605
- // Used to be able to find the post type this activity type is associated to.
606
- $track_post_type->comments_tracking->post_type = $post_type;
607
-
608
- $post_types_tracking_args[ $track_post_type->comments_tracking->action_id ] = $track_post_type->comments_tracking;
609
-
610
- // Used to check support for comment tracking by activity type (new_post_type)
611
- $track_post_type->comments_tracking = true;
612
- }
613
-
614
- $post_types_tracking_args[ $track_post_type->action_id ] = $track_post_type;
615
- }
616
-
617
- }
618
-
619
- /**
620
- * Filters tracking arguments for all post types.
621
- *
622
- * @since 2.2.0
623
- *
624
- * @param array $post_types_tracking_args Array of post types with
625
- * their tracking arguments.
626
- */
627
- return apply_filters( 'bp_activity_get_post_types_tracking_args', $post_types_tracking_args );
628
- }
629
-
630
- /**
631
- * Check if the *Post Type* activity supports a specific feature.
632
- *
633
- * @since 2.5.0
634
- *
635
- * @param string $activity_type The activity type to check.
636
- * @param string $feature The feature to check. Currently supports:
637
- * 'post-type-comment-tracking', 'post-type-comment-reply' & 'comment-reply'.
638
- * See inline doc for more info.
639
- * @return bool
640
- */
641
- function bp_activity_type_supports( $activity_type = '', $feature = '' ) {
642
- $retval = false;
643
-
644
- $bp = buddypress();
645
-
646
- switch ( $feature ) {
647
- /**
648
- * Does this activity type support comment tracking?
649
- *
650
- * eg. 'new_blog_post' and 'new_blog_comment' will both return true.
651
- */
652
- case 'post-type-comment-tracking' :
653
- // Set the activity track global if not set yet
654
- if ( empty( $bp->activity->track ) ) {
655
- $bp->activity->track = bp_activity_get_post_types_tracking_args();
656
- }
657
-
658
- if ( ! empty( $bp->activity->track[ $activity_type ]->comments_tracking ) ) {
659
- $retval = true;
660
- }
661
- break;
662
-
663
- /**
664
- * Is this a parent activity type that support post comments?
665
- *
666
- * eg. 'new_blog_post' will return true; 'new_blog_comment' will return false.
667
- */
668
- case 'post-type-comment-reply' :
669
- // Set the activity track global if not set yet.
670
- if ( empty( $bp->activity->track ) ) {
671
- $bp->activity->track = bp_activity_get_post_types_tracking_args();
672
- }
673
-
674
- if ( ! empty( $bp->activity->track[ $activity_type ]->comments_tracking ) && ! empty( $bp->activity->track[ $activity_type ]->comment_action_id ) ) {
675
- $retval = true;
676
- }
677
- break;
678
-
679
- /**
680
- * Does this activity type support comment & reply?
681
- */
682
- case 'comment-reply' :
683
- // Set the activity track global if not set yet.
684
- if ( empty( $bp->activity->track ) ) {
685
- $bp->activity->track = bp_activity_get_post_types_tracking_args();
686
- }
687
-
688
- // Post Type activities
689
- if ( ! empty( $bp->activity->track[ $activity_type ] ) ) {
690
- if ( isset( $bp->activity->track[ $activity_type ]->activity_comment ) ) {
691
- $retval = $bp->activity->track[ $activity_type ]->activity_comment;
692
- }
693
-
694
- // Eventually override with comment synchronization feature.
695
- if ( isset( $bp->activity->track[ $activity_type ]->comments_tracking ) ) {
696
- $retval = $bp->activity->track[ $activity_type ]->comments_tracking && ! bp_disable_blogforum_comments();
697
- }
698
-
699
- // Retired Forums component
700
- } elseif ( 'new_forum_topic' === $activity_type || 'new_forum_post' === $activity_type ) {
701
- $retval = ! bp_disable_blogforum_comments();
702
-
703
- // By Default, all other activity types are supporting comments.
704
- } else {
705
- $retval = true;
706
- }
707
- break;
708
- }
709
-
710
- return $retval;
711
- }
712
-
713
- /**
714
- * Get a specific tracking argument for a given activity type
715
- *
716
- * @since 2.5.0
717
- *
718
- * @param string $activity_type the activity type.
719
- * @param string $arg the key of the tracking argument.
720
- * @return mixed the value of the tracking arg, false if not found.
721
- */
722
- function bp_activity_post_type_get_tracking_arg( $activity_type, $arg = '' ) {
723
- if ( empty( $activity_type ) || empty( $arg ) ) {
724
- return false;
725
- }
726
-
727
- $bp = buddypress();
728
-
729
- // Set the activity track global if not set yet
730
- if ( empty( $bp->activity->track ) ) {
731
- $bp->activity->track = bp_activity_get_post_types_tracking_args();
732
- }
733
-
734
- if ( isset( $bp->activity->track[ $activity_type ]->{$arg} ) ) {
735
- return $bp->activity->track[ $activity_type ]->{$arg};
736
- } else {
737
- return false;
738
- }
739
- }
740
-
741
- /**
742
- * Get all components' activity actions, sorted by their position attribute.
743
- *
744
- * @since 2.2.0
745
  *
746
- * @return object Actions ordered by their position.
747
- */
748
- function bp_activity_get_actions() {
749
- $bp = buddypress();
750
-
751
- $post_types = bp_activity_get_post_types_tracking_args();
752
-
753
- // Create the actions for the post types, if they haven't already been created.
754
- if ( ! empty( $post_types ) ) {
755
- foreach ( $post_types as $post_type ) {
756
- if ( isset( $bp->activity->actions->{$post_type->component_id}->{$post_type->action_id} ) ) {
757
- continue;
758
- }
759
-
760
- bp_activity_set_action(
761
- $post_type->component_id,
762
- $post_type->action_id,
763
- $post_type->admin_filter,
764
- $post_type->format_callback,
765
- $post_type->front_filter,
766
- $post_type->contexts,
767
- $post_type->position
768
- );
769
- }
770
- }
771
-
772
- return $bp->activity->actions;
773
- }
774
-
775
- /**
776
- * Retrieve the current action from a component and key.
777
  *
778
- * @since 1.1.0
 
779
  *
780
  * @param string $component_id The unique string ID of the component.
781
- * @param string $key The action key.
782
  * @return string|bool Action value if found, otherwise false.
783
  */
784
  function bp_activity_get_action( $component_id, $key ) {
 
785
 
786
- // Return false if any of the above values are not set.
787
- if ( empty( $component_id ) || empty( $key ) ) {
788
  return false;
789
- }
790
 
791
- $actions = bp_activity_get_actions();
792
- $retval = false;
793
-
794
- if ( isset( $actions->{$component_id}->{$key} ) ) {
795
- $retval = $actions->{$component_id}->{$key};
796
- }
797
-
798
- /**
799
- * Filters the current action by component and key.
800
- *
801
- * @since 1.1.0
802
- *
803
- * @param string|bool $retval The action key.
804
- * @param string $component_id The unique string ID of the component.
805
- * @param string $key The action key.
806
- */
807
- return apply_filters( 'bp_activity_get_action', $retval, $component_id, $key );
808
  }
809
 
810
  /**
811
  * Fetch details of all registered activity types.
812
  *
813
- * @since 1.7.0
814
  *
815
  * @return array array( type => description ), ...
816
  */
@@ -818,182 +341,103 @@ function bp_activity_get_types() {
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
- /**
833
- * Filters the available activity types.
834
- *
835
- * @since 1.7.0
836
- *
837
- * @param array $actions Array of registered activity types.
838
- */
839
  return apply_filters( 'bp_activity_get_types', $actions );
840
  }
841
 
842
- /**
843
- * Gets the current activity context.
844
- *
845
- * The "context" is the current view type, corresponding roughly to the
846
- * current component. Use this context to determine which activity actions
847
- * should be whitelisted for the filter dropdown.
848
- *
849
- * @since 2.8.0
850
- *
851
- * @return string Activity context. 'member', 'member_groups', 'group', 'activity'.
852
- */
853
- function bp_activity_get_current_context() {
854
- // On member pages, default to 'member', unless this is a user's Groups activity.
855
- if ( bp_is_user() ) {
856
- if ( bp_is_active( 'groups' ) && bp_is_current_action( bp_get_groups_slug() ) ) {
857
- $context = 'member_groups';
858
- } else {
859
- $context = 'member';
860
- }
861
-
862
- // On individual group pages, default to 'group'.
863
- } elseif ( bp_is_active( 'groups' ) && bp_is_group() ) {
864
- $context = 'group';
865
-
866
- // 'activity' everywhere else.
867
- } else {
868
- $context = 'activity';
869
- }
870
-
871
- return $context;
872
- }
873
-
874
- /**
875
- * Gets a flat list of activity actions compatible with a given context.
876
- *
877
- * @since 2.8.0
878
- *
879
- * @param string $context Optional. Name of the context. Defaults to the current context.
880
- * @return array
881
- */
882
- function bp_activity_get_actions_for_context( $context = '' ) {
883
- if ( ! $context ) {
884
- $context = bp_activity_get_current_context();
885
- }
886
-
887
- $actions = array();
888
- foreach ( bp_activity_get_actions() as $component_actions ) {
889
- foreach ( $component_actions as $component_action ) {
890
- if ( in_array( $context, (array) $component_action['context'], true ) ) {
891
- $actions[] = $component_action;
892
- }
893
- }
894
- }
895
-
896
- return $actions;
897
- }
898
-
899
  /** Favorites ****************************************************************/
900
 
901
  /**
902
  * Get a users favorite activity stream items.
903
  *
904
- * @since 1.2.0
 
 
 
905
  *
906
  * @param int $user_id ID of the user whose favorites are being queried.
907
  * @return array IDs of the user's favorite activity items.
908
  */
909
  function bp_activity_get_user_favorites( $user_id = 0 ) {
910
 
911
- // Fallback to logged in user if no user_id is passed.
912
- if ( empty( $user_id ) ) {
913
  $user_id = bp_displayed_user_id();
914
- }
915
 
916
- // Get favorites for user.
917
  $favs = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
918
 
919
- /**
920
- * Filters the favorited activity items for a specified user.
921
- *
922
- * @since 1.2.0
923
- *
924
- * @param array $favs Array of user's favorited activity items.
925
- */
926
  return apply_filters( 'bp_activity_get_user_favorites', $favs );
927
  }
928
 
929
  /**
930
  * Add an activity stream item as a favorite for a user.
931
  *
932
- * @since 1.2.0
 
 
 
 
 
 
 
 
933
  *
934
  * @param int $activity_id ID of the activity item being favorited.
935
- * @param int $user_id ID of the user favoriting the activity item.
936
  * @return bool True on success, false on failure.
937
  */
938
  function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
939
 
940
- // Favorite activity stream items are for logged in users only.
941
- if ( ! is_user_logged_in() ) {
942
  return false;
943
- }
944
 
945
- // Fallback to logged in user if no user_id is passed.
946
- if ( empty( $user_id ) ) {
947
  $user_id = bp_loggedin_user_id();
948
- }
949
 
950
  $my_favs = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
951
  if ( empty( $my_favs ) || ! is_array( $my_favs ) ) {
952
  $my_favs = array();
953
  }
954
 
955
- // Bail if the user has already favorited this activity item.
956
  if ( in_array( $activity_id, $my_favs ) ) {
957
  return false;
958
  }
959
 
960
- // Add to user's favorites.
961
  $my_favs[] = $activity_id;
962
 
963
- // Update the total number of users who have favorited this activity.
964
  $fav_count = bp_activity_get_meta( $activity_id, 'favorite_count' );
965
  $fav_count = !empty( $fav_count ) ? (int) $fav_count + 1 : 1;
966
 
967
- // Update user meta.
968
  bp_update_user_meta( $user_id, 'bp_favorite_activities', $my_favs );
969
 
970
- // Update activity meta counts.
971
  if ( bp_activity_update_meta( $activity_id, 'favorite_count', $fav_count ) ) {
972
 
973
- /**
974
- * Fires if bp_activity_update_meta() for favorite_count is successful and before returning a true value for success.
975
- *
976
- * @since 1.2.1
977
- *
978
- * @param int $activity_id ID of the activity item being favorited.
979
- * @param int $user_id ID of the user doing the favoriting.
980
- */
981
  do_action( 'bp_activity_add_user_favorite', $activity_id, $user_id );
982
 
983
- // Success.
984
  return true;
985
 
986
- // Saving meta was unsuccessful for an unknown reason.
987
  } else {
988
-
989
- /**
990
- * Fires if bp_activity_update_meta() for favorite_count is unsuccessful and before returning a false value for failure.
991
- *
992
- * @since 1.5.0
993
- *
994
- * @param int $activity_id ID of the activity item being favorited.
995
- * @param int $user_id ID of the user doing the favoriting.
996
- */
997
  do_action( 'bp_activity_add_user_favorite_fail', $activity_id, $user_id );
998
 
999
  return false;
@@ -1003,70 +447,67 @@ function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
1003
  /**
1004
  * Remove an activity stream item as a favorite for a user.
1005
  *
1006
- * @since 1.2.0
 
 
 
 
 
 
 
1007
  *
1008
  * @param int $activity_id ID of the activity item being unfavorited.
1009
- * @param int $user_id ID of the user unfavoriting the activity item.
1010
  * @return bool True on success, false on failure.
1011
  */
1012
  function bp_activity_remove_user_favorite( $activity_id, $user_id = 0 ) {
1013
 
1014
- // Favorite activity stream items are for logged in users only.
1015
- if ( ! is_user_logged_in() ) {
1016
  return false;
1017
- }
1018
 
1019
- // Fallback to logged in user if no user_id is passed.
1020
- if ( empty( $user_id ) ) {
1021
  $user_id = bp_loggedin_user_id();
1022
- }
1023
 
1024
  $my_favs = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
1025
  $my_favs = array_flip( (array) $my_favs );
1026
 
1027
- // Bail if the user has not previously favorited the item.
1028
  if ( ! isset( $my_favs[ $activity_id ] ) ) {
1029
  return false;
1030
  }
1031
 
1032
- // Remove the fav from the user's favs.
1033
  unset( $my_favs[$activity_id] );
1034
  $my_favs = array_unique( array_flip( $my_favs ) );
1035
 
1036
- // Update the total number of users who have favorited this activity.
1037
- $fav_count = bp_activity_get_meta( $activity_id, 'favorite_count' );
1038
- if ( ! empty( $fav_count ) ) {
1039
 
1040
- // Deduct from total favorites.
1041
  if ( bp_activity_update_meta( $activity_id, 'favorite_count', (int) $fav_count - 1 ) ) {
1042
 
1043
- // Update users favorites.
1044
  if ( bp_update_user_meta( $user_id, 'bp_favorite_activities', $my_favs ) ) {
1045
 
1046
- /**
1047
- * Fires if bp_update_user_meta() is successful and before returning a true value for success.
1048
- *
1049
- * @since 1.2.1
1050
- *
1051
- * @param int $activity_id ID of the activity item being unfavorited.
1052
- * @param int $user_id ID of the user doing the unfavoriting.
1053
- */
1054
  do_action( 'bp_activity_remove_user_favorite', $activity_id, $user_id );
1055
 
1056
- // Success.
1057
  return true;
1058
 
1059
- // Error updating.
1060
  } else {
1061
  return false;
1062
  }
1063
 
1064
- // Error updating favorite count.
1065
  } else {
1066
  return false;
1067
  }
1068
 
1069
- // Error getting favorite count.
1070
  } else {
1071
  return false;
1072
  }
@@ -1075,56 +516,47 @@ function bp_activity_remove_user_favorite( $activity_id, $user_id = 0 ) {
1075
  /**
1076
  * Check whether an activity item exists with a given content string.
1077
  *
1078
- * @since 1.1.0
 
 
 
1079
  *
1080
  * @param string $content The content to filter by.
1081
  * @return int|null The ID of the located activity item. Null if none is found.
1082
  */
1083
  function bp_activity_check_exists_by_content( $content ) {
1084
-
1085
- /**
1086
- * Filters the results of the check for whether an activity item exists by specified content.
1087
- *
1088
- * @since 1.1.0
1089
- *
1090
- * @param BP_Activity_Activity $value ID of the activity if found, else null.
1091
- */
1092
  return apply_filters( 'bp_activity_check_exists_by_content', BP_Activity_Activity::check_exists_by_content( $content ) );
1093
  }
1094
 
1095
  /**
1096
  * Retrieve the last time activity was updated.
1097
  *
1098
- * @since 1.0.0
 
 
 
1099
  *
1100
  * @return string Date last updated.
1101
  */
1102
  function bp_activity_get_last_updated() {
1103
-
1104
- /**
1105
- * Filters the value for the last updated time for an activity item.
1106
- *
1107
- * @since 1.1.0
1108
- *
1109
- * @param BP_Activity_Activity $last_updated Date last updated.
1110
- */
1111
  return apply_filters( 'bp_activity_get_last_updated', BP_Activity_Activity::get_last_updated() );
1112
  }
1113
 
1114
  /**
1115
  * Retrieve the number of favorite activity stream items a user has.
1116
  *
1117
- * @since 1.2.0
 
 
1118
  *
1119
  * @param int $user_id ID of the user whose favorite count is being requested.
1120
  * @return int Total favorite count for the user.
1121
  */
1122
  function bp_activity_total_favorites_for_user( $user_id = 0 ) {
1123
 
1124
- // Fallback on displayed user, and then logged in user.
1125
- if ( empty( $user_id ) ) {
1126
  $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
1127
- }
1128
 
1129
  return BP_Activity_Activity::total_favorite_count( $user_id );
1130
  }
@@ -1134,30 +566,32 @@ function bp_activity_total_favorites_for_user( $user_id = 0 ) {
1134
  /**
1135
  * Delete a meta entry from the DB for an activity stream item.
1136
  *
1137
- * @since 1.2.0
1138
  *
1139
  * @global object $wpdb WordPress database access object.
1140
- *
1141
- * @param int $activity_id ID of the activity item whose metadata is being deleted.
1142
- * @param string $meta_key Optional. The key of the metadata being deleted. If
1143
- * omitted, all metadata associated with the activity
1144
- * item will be deleted.
1145
- * @param string $meta_value Optional. If present, the metadata will only be
1146
- * deleted if the meta_value matches this parameter.
1147
- * @param bool $delete_all Optional. If true, delete matching metadata entries
1148
- * for all objects, ignoring the specified object_id. Otherwise,
1149
- * only delete matching metadata entries for the specified
1150
- * activity item. Default: false.
 
1151
  * @return bool True on success, false on failure.
1152
  */
1153
  function bp_activity_delete_meta( $activity_id, $meta_key = '', $meta_value = '', $delete_all = false ) {
 
1154
 
1155
- // Legacy - if no meta_key is passed, delete all for the item.
1156
  if ( empty( $meta_key ) ) {
1157
  $all_meta = bp_activity_get_meta( $activity_id );
1158
  $keys = ! empty( $all_meta ) ? array_keys( $all_meta ) : array();
1159
 
1160
- // With no meta_key, ignore $delete_all.
1161
  $delete_all = false;
1162
  } else {
1163
  $keys = array( $meta_key );
@@ -1177,15 +611,17 @@ function bp_activity_delete_meta( $activity_id, $meta_key = '', $meta_value = ''
1177
  /**
1178
  * Get metadata for a given activity item.
1179
  *
1180
- * @since 1.2.0
1181
  *
1182
- * @param int $activity_id ID of the activity item whose metadata is being requested.
1183
- * @param string $meta_key Optional. If present, only the metadata matching
1184
- * that meta key will be returned. Otherwise, all metadata for the
1185
- * activity item will be fetched.
1186
- * @param bool $single Optional. If true, return only the first value of the
1187
- * specified meta_key. This parameter has no effect if meta_key is not
1188
- * specified. Default: true.
 
 
1189
  * @return mixed The meta value(s) being requested.
1190
  */
1191
  function bp_activity_get_meta( $activity_id = 0, $meta_key = '', $single = true ) {
@@ -1193,32 +629,25 @@ function bp_activity_get_meta( $activity_id = 0, $meta_key = '', $single = true
1193
  $retval = get_metadata( 'activity', $activity_id, $meta_key, $single );
1194
  remove_filter( 'query', 'bp_filter_metaid_column_name' );
1195
 
1196
- /**
1197
- * Filters the metadata for a specified activity item.
1198
- *
1199
- * @since 1.5.0
1200
- *
1201
- * @param mixed $retval The meta values for the activity item.
1202
- * @param int $activity_id ID of the activity item.
1203
- * @param string $meta_key Meta key for the value being requested.
1204
- * @param bool $single Whether to return one matched meta key row or all.
1205
- */
1206
  return apply_filters( 'bp_activity_get_meta', $retval, $activity_id, $meta_key, $single );
1207
  }
1208
 
1209
  /**
1210
  * Update a piece of activity meta.
1211
  *
1212
- * @since 1.2.0
1213
  *
1214
- * @param int $activity_id ID of the activity item whose metadata is being updated.
1215
- * @param string $meta_key Key of the metadata being updated.
1216
- * @param mixed $meta_value Value to be set.
1217
- * @param mixed $prev_value Optional. If specified, only update existing metadata entries
1218
- * with the specified value. Otherwise, update all entries.
 
 
1219
  * @return bool|int Returns false on failure. On successful update of existing
1220
- * metadata, returns true. On successful creation of new metadata,
1221
- * returns the integer ID of the new metadata row.
1222
  */
1223
  function bp_activity_update_meta( $activity_id, $meta_key, $meta_value, $prev_value = '' ) {
1224
  add_filter( 'query', 'bp_filter_metaid_column_name' );
@@ -1231,14 +660,14 @@ function bp_activity_update_meta( $activity_id, $meta_key, $meta_value, $prev_va
1231
  /**
1232
  * Add a piece of activity metadata.
1233
  *
1234
- * @since 2.0.0
1235
  *
1236
- * @param int $activity_id ID of the activity item.
1237
- * @param string $meta_key Metadata key.
1238
- * @param mixed $meta_value Metadata value.
1239
- * @param bool $unique Optional. Whether to enforce a single metadata value for the
1240
- * given key. If true, and the object already has a value for
1241
- * the key, no change will be made. Default: false.
1242
  * @return int|bool The meta ID on successful update, false on failure.
1243
  */
1244
  function bp_activity_add_meta( $activity_id, $meta_key, $meta_value, $unique = false ) {
@@ -1254,35 +683,33 @@ function bp_activity_add_meta( $activity_id, $meta_key, $meta_value, $unique = f
1254
  /**
1255
  * Completely remove a user's activity data.
1256
  *
1257
- * @since 1.5.0
 
 
 
 
 
 
1258
  *
1259
  * @param int $user_id ID of the user whose activity is being deleted.
1260
- * @return bool
1261
  */
1262
  function bp_activity_remove_all_user_data( $user_id = 0 ) {
1263
 
1264
- // Do not delete user data unless a logged in user says so.
1265
- if ( empty( $user_id ) || ! is_user_logged_in() ) {
1266
  return false;
1267
- }
1268
 
1269
- // Clear the user's activity from the sitewide stream and clear their activity tables.
1270
  bp_activity_delete( array( 'user_id' => $user_id ) );
1271
 
1272
- // Remove any usermeta.
1273
- bp_delete_user_meta( $user_id, 'bp_latest_update' );
1274
  bp_delete_user_meta( $user_id, 'bp_favorite_activities' );
1275
 
1276
  // Execute additional code
1277
  do_action( 'bp_activity_remove_data', $user_id ); // Deprecated! Do not use!
1278
 
1279
- /**
1280
- * Fires after the removal of all of a user's activity data.
1281
- *
1282
- * @since 1.5.0
1283
- *
1284
- * @param int $user_id ID of the user being deleted.
1285
- */
1286
  do_action( 'bp_activity_remove_all_user_data', $user_id );
1287
  }
1288
  add_action( 'wpmu_delete_user', 'bp_activity_remove_all_user_data' );
@@ -1291,68 +718,52 @@ add_action( 'delete_user', 'bp_activity_remove_all_user_data' );
1291
  /**
1292
  * Mark all of the user's activity as spam.
1293
  *
1294
- * @since 1.6.0
1295
  *
1296
  * @global object $wpdb WordPress database access object.
 
1297
  *
1298
  * @param int $user_id ID of the user whose activity is being spammed.
1299
- * @return bool
1300
  */
1301
  function bp_activity_spam_all_user_data( $user_id = 0 ) {
1302
- global $wpdb;
1303
 
1304
- // Do not delete user data unless a logged in user says so.
1305
- if ( empty( $user_id ) || ! is_user_logged_in() ) {
1306
  return false;
1307
- }
1308
 
1309
  // Get all the user's activities.
1310
- $activities = bp_activity_get( array(
1311
- 'display_comments' => 'stream',
1312
- 'filter' => array( 'user_id' => $user_id ),
1313
- 'show_hidden' => true
1314
- ) );
1315
 
1316
- $bp = buddypress();
1317
-
1318
- // Mark each as spam.
1319
  foreach ( (array) $activities['activities'] as $activity ) {
1320
 
1321
- // Create an activity object.
1322
  $activity_obj = new BP_Activity_Activity;
1323
- foreach ( $activity as $k => $v ) {
1324
  $activity_obj->$k = $v;
1325
- }
1326
 
1327
- // Mark as spam.
1328
  bp_activity_mark_as_spam( $activity_obj );
1329
 
1330
  /*
1331
  * If Akismet is present, update the activity history meta.
1332
  *
1333
  * This is usually taken care of when BP_Activity_Activity::save() happens, but
1334
- * as we're going to be updating all the activity statuses directly, for efficiency,
1335
  * we need to update manually.
1336
  */
1337
- if ( ! empty( $bp->activity->akismet ) ) {
1338
  $bp->activity->akismet->update_activity_spam_meta( $activity_obj );
1339
- }
1340
 
1341
- // Tidy up.
1342
  unset( $activity_obj );
1343
  }
1344
 
1345
- // Mark all of this user's activities as spam.
1346
  $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET is_spam = 1 WHERE user_id = %d", $user_id ) );
1347
 
1348
- /**
1349
- * Fires after all activity data from a user has been marked as spam.
1350
- *
1351
- * @since 1.6.0
1352
- *
1353
- * @param int $user_id ID of the user whose activity is being marked as spam.
1354
- * @param array $activities Array of activity items being marked as spam.
1355
- */
1356
  do_action( 'bp_activity_spam_all_user_data', $user_id, $activities['activities'] );
1357
  }
1358
  add_action( 'bp_make_spam_user', 'bp_activity_spam_all_user_data' );
@@ -1360,105 +771,80 @@ add_action( 'bp_make_spam_user', 'bp_activity_spam_all_user_data' );
1360
  /**
1361
  * Mark all of the user's activity as ham (not spam).
1362
  *
1363
- * @since 1.6.0
1364
  *
1365
  * @global object $wpdb WordPress database access object.
 
1366
  *
1367
  * @param int $user_id ID of the user whose activity is being hammed.
1368
- * @return bool
1369
  */
1370
  function bp_activity_ham_all_user_data( $user_id = 0 ) {
1371
- global $wpdb;
1372
 
1373
- // Do not delete user data unless a logged in user says so.
1374
- if ( empty( $user_id ) || ! is_user_logged_in() ) {
1375
  return false;
1376
- }
1377
 
1378
  // Get all the user's activities.
1379
- $activities = bp_activity_get( array(
1380
- 'display_comments' => 'stream',
1381
- 'filter' => array( 'user_id' => $user_id ),
1382
- 'show_hidden' => true,
1383
- 'spam' => 'all'
1384
- ) );
1385
 
1386
- $bp = buddypress();
1387
-
1388
- // Mark each as not spam.
1389
  foreach ( (array) $activities['activities'] as $activity ) {
1390
 
1391
- // Create an activity object.
1392
  $activity_obj = new BP_Activity_Activity;
1393
- foreach ( $activity as $k => $v ) {
1394
  $activity_obj->$k = $v;
1395
- }
1396
 
1397
- // Mark as not spam.
1398
  bp_activity_mark_as_ham( $activity_obj );
1399
 
1400
  /*
1401
  * If Akismet is present, update the activity history meta.
1402
  *
1403
  * This is usually taken care of when BP_Activity_Activity::save() happens, but
1404
- * as we're going to be updating all the activity statuses directly, for efficiency,
1405
  * we need to update manually.
1406
  */
1407
- if ( ! empty( $bp->activity->akismet ) ) {
1408
  $bp->activity->akismet->update_activity_ham_meta( $activity_obj );
1409
- }
1410
 
1411
- // Tidy up.
1412
  unset( $activity_obj );
1413
  }
1414
 
1415
- // Mark all of this user's activities as not spam.
1416
  $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET is_spam = 0 WHERE user_id = %d", $user_id ) );
1417
 
1418
- /**
1419
- * Fires after all activity data from a user has been marked as ham.
1420
- *
1421
- * @since 1.6.0
1422
- *
1423
- * @param int $user_id ID of the user whose activity is being marked as ham.
1424
- * @param array $activities Array of activity items being marked as ham.
1425
- */
1426
  do_action( 'bp_activity_ham_all_user_data', $user_id, $activities['activities'] );
1427
  }
1428
  add_action( 'bp_make_ham_user', 'bp_activity_ham_all_user_data' );
1429
 
1430
  /**
1431
- * Register the activity stream actions for updates.
 
 
1432
  *
1433
- * @since 1.6.0
1434
  */
1435
  function bp_activity_register_activity_actions() {
1436
- $bp = buddypress();
1437
 
1438
  bp_activity_set_action(
1439
  $bp->activity->id,
1440
  'activity_update',
1441
  __( 'Posted a status update', 'buddypress' ),
1442
- 'bp_activity_format_activity_action_activity_update',
1443
- __( 'Updates', 'buddypress' ),
1444
- array( 'activity', 'group', 'member', 'member_groups' )
1445
  );
1446
 
1447
  bp_activity_set_action(
1448
  $bp->activity->id,
1449
  'activity_comment',
1450
  __( 'Replied to a status update', 'buddypress' ),
1451
- 'bp_activity_format_activity_action_activity_comment',
1452
- __( 'Activity Comments', 'buddypress' )
1453
  );
1454
 
1455
- /**
1456
- * Fires at the end of the activity actions registration.
1457
- *
1458
- * Allows plugin authors to add their own activity actions alongside the core actions.
1459
- *
1460
- * @since 1.6.0
1461
- */
1462
  do_action( 'bp_activity_register_activity_actions' );
1463
 
1464
  // Backpat. Don't use this.
@@ -1469,40 +855,29 @@ add_action( 'bp_register_activity_actions', 'bp_activity_register_activity_actio
1469
  /**
1470
  * Generate an activity action string for an activity item.
1471
  *
1472
- * @since 2.0.0
1473
- *
1474
  * @param object $activity Activity data object.
1475
  * @return string|bool Returns false if no callback is found, otherwise returns
1476
- * the formatted action string.
1477
  */
1478
  function bp_activity_generate_action_string( $activity ) {
1479
-
1480
- // Check for valid input.
1481
  if ( empty( $activity->component ) || empty( $activity->type ) ) {
1482
  return false;
1483
  }
1484
 
1485
- // Check for registered format callback.
1486
- $actions = bp_activity_get_actions();
1487
- if ( empty( $actions->{$activity->component}->{$activity->type}['format_callback'] ) ) {
1488
  return false;
1489
  }
1490
 
1491
- // We apply the format_callback as a filter.
1492
- add_filter( 'bp_activity_generate_action_string', $actions->{$activity->component}->{$activity->type}['format_callback'], 10, 2 );
1493
 
1494
- /**
1495
- * Filters the string for the activity action being returned.
1496
- *
1497
- * @since 2.0.0
1498
- *
1499
- * @param BP_Activity_Activity $action Action string being requested.
1500
- * @param BP_Activity_Activity $activity Activity item object.
1501
- */
1502
  $action = apply_filters( 'bp_activity_generate_action_string', $activity->action, $activity );
1503
 
1504
- // Remove the filter for future activity items.
1505
- remove_filter( 'bp_activity_generate_action_string', $actions->{$activity->component}->{$activity->type}['format_callback'], 10 );
1506
 
1507
  return $action;
1508
  }
@@ -1510,158 +885,32 @@ function bp_activity_generate_action_string( $activity ) {
1510
  /**
1511
  * Format 'activity_update' activity actions.
1512
  *
1513
- * @since 2.0.0
1514
  *
1515
- * @param string $action Static activity action.
1516
  * @param object $activity Activity data object.
1517
- * @return string $action
1518
  */
1519
  function bp_activity_format_activity_action_activity_update( $action, $activity ) {
1520
  $action = sprintf( __( '%s posted an update', 'buddypress' ), bp_core_get_userlink( $activity->user_id ) );
1521
-
1522
- /**
1523
- * Filters the formatted activity action update string.
1524
- *
1525
- * @since 1.2.0
1526
- *
1527
- * @param string $action Activity action string value.
1528
- * @param BP_Activity_Activity $activity Activity item object.
1529
- */
1530
  return apply_filters( 'bp_activity_new_update_action', $action, $activity );
1531
  }
1532
 
1533
  /**
1534
  * Format 'activity_comment' activity actions.
1535
  *
1536
- * @since 2.0.0
1537
  *
1538
- * @param string $action Static activity action.
1539
  * @param object $activity Activity data object.
1540
- * @return string $action
1541
  */
1542
  function bp_activity_format_activity_action_activity_comment( $action, $activity ) {
1543
  $action = sprintf( __( '%s posted a new activity comment', 'buddypress' ), bp_core_get_userlink( $activity->user_id ) );
1544
-
1545
- /**
1546
- * Filters the formatted activity action comment string.
1547
- *
1548
- * @since 1.2.0
1549
- *
1550
- * @param string $action Activity action string value.
1551
- * @param BP_Activity_Activity $activity Activity item object.
1552
- */
1553
  return apply_filters( 'bp_activity_comment_action', $action, $activity );
1554
  }
1555
 
1556
- /**
1557
- * Format activity action strings for custom post types.
1558
- *
1559
- * @since 2.2.0
1560
- *
1561
- * @param string $action Static activity action.
1562
- * @param object $activity Activity data object.
1563
- * @return string $action
1564
- */
1565
- function bp_activity_format_activity_action_custom_post_type_post( $action, $activity ) {
1566
- $bp = buddypress();
1567
-
1568
- // Fetch all the tracked post types once.
1569
- if ( empty( $bp->activity->track ) ) {
1570
- $bp->activity->track = bp_activity_get_post_types_tracking_args();
1571
- }
1572
-
1573
- if ( empty( $activity->type ) || empty( $bp->activity->track[ $activity->type ] ) ) {
1574
- return $action;
1575
- }
1576
-
1577
- $user_link = bp_core_get_userlink( $activity->user_id );
1578
- $blog_url = get_home_url( $activity->item_id );
1579
-
1580
- if ( empty( $activity->post_url ) ) {
1581
- $post_url = add_query_arg( 'p', $activity->secondary_item_id, trailingslashit( $blog_url ) );
1582
- } else {
1583
- $post_url = $activity->post_url;
1584
- }
1585
-
1586
- if ( is_multisite() ) {
1587
- $blog_link = '<a href="' . esc_url( $blog_url ) . '">' . get_blog_option( $activity->item_id, 'blogname' ) . '</a>';
1588
-
1589
- if ( ! empty( $bp->activity->track[ $activity->type ]->new_post_type_action_ms ) ) {
1590
- $action = sprintf( $bp->activity->track[ $activity->type ]->new_post_type_action_ms, $user_link, $post_url, $blog_link );
1591
- } else {
1592
- $action = sprintf( _x( '%1$s wrote a new <a href="%2$s">item</a>, on the site %3$s', 'Activity Custom Post Type post action', 'buddypress' ), $user_link, esc_url( $post_url ), $blog_link );
1593
- }
1594
- } else {
1595
- if ( ! empty( $bp->activity->track[ $activity->type ]->new_post_type_action ) ) {
1596
- $action = sprintf( $bp->activity->track[ $activity->type ]->new_post_type_action, $user_link, $post_url );
1597
- } else {
1598
- $action = sprintf( _x( '%1$s wrote a new <a href="%2$s">item</a>', 'Activity Custom Post Type post action', 'buddypress' ), $user_link, esc_url( $post_url ) );
1599
- }
1600
- }
1601
-
1602
- /**
1603
- * Filters the formatted custom post type activity post action string.
1604
- *
1605
- * @since 2.2.0
1606
- *
1607
- * @param string $action Activity action string value.
1608
- * @param BP_Activity_Activity $activity Activity item object.
1609
- */
1610
- return apply_filters( 'bp_activity_custom_post_type_post_action', $action, $activity );
1611
- }
1612
-
1613
- /**
1614
- * Format activity action strings for custom post types comments.
1615
- *
1616
- * @since 2.5.0
1617
- *
1618
- * @param string $action Static activity action.
1619
- * @param object $activity Activity data object.
1620
- *
1621
- * @return string
1622
- */
1623
- function bp_activity_format_activity_action_custom_post_type_comment( $action, $activity ) {
1624
- $bp = buddypress();
1625
-
1626
- // Fetch all the tracked post types once.
1627
- if ( empty( $bp->activity->track ) ) {
1628
- $bp->activity->track = bp_activity_get_post_types_tracking_args();
1629
- }
1630
-
1631
- if ( empty( $activity->type ) || empty( $bp->activity->track[ $activity->type ] ) ) {
1632
- return $action;
1633
- }
1634
-
1635
- $user_link = bp_core_get_userlink( $activity->user_id );
1636
-
1637
- if ( is_multisite() ) {
1638
- $blog_link = '<a href="' . esc_url( get_home_url( $activity->item_id ) ) . '">' . get_blog_option( $activity->item_id, 'blogname' ) . '</a>';
1639
-
1640
- if ( ! empty( $bp->activity->track[ $activity->type ]->new_post_type_comment_action_ms ) ) {
1641
- $action = sprintf( $bp->activity->track[ $activity->type ]->new_post_type_comment_action_ms, $user_link, $activity->primary_link, $blog_link );
1642
- } else {
1643
- $action = sprintf( _x( '%1$s commented on the <a href="%2$s">item</a>, on the site %3$s', 'Activity Custom Post Type comment action', 'buddypress' ), $user_link, $activity->primary_link, $blog_link );
1644
- }
1645
- } else {
1646
- if ( ! empty( $bp->activity->track[ $activity->type ]->new_post_type_comment_action ) ) {
1647
- $action = sprintf( $bp->activity->track[ $activity->type ]->new_post_type_comment_action, $user_link, $activity->primary_link );
1648
- } else {
1649
- $action = sprintf( _x( '%1$s commented on the <a href="%2$s">item</a>', 'Activity Custom Post Type post comment action', 'buddypress' ), $user_link, $activity->primary_link );
1650
- }
1651
- }
1652
-
1653
- /**
1654
- * Filters the formatted custom post type activity comment action string.
1655
- *
1656
- * @since 2.5.0
1657
- *
1658
- * @param string $action Activity action string value.
1659
- * @param BP_Activity_Activity $activity Activity item object.
1660
- */
1661
- return apply_filters( 'bp_activity_custom_post_type_comment_action', $action, $activity );
1662
- }
1663
-
1664
- /*
1665
  * Business functions are where all the magic happens in BuddyPress. They will
1666
  * handle the actual saving or manipulation of information. Usually they will
1667
  * hand off to a database class for data access, then return
@@ -1671,252 +920,240 @@ function bp_activity_format_activity_action_custom_post_type_comment( $action, $
1671
  /**
1672
  * Retrieve an activity or activities.
1673
  *
1674
- * The bp_activity_get() function shares all arguments with BP_Activity_Activity::get().
1675
- * The following is a list of bp_activity_get() parameters that have different
1676
  * default values from BP_Activity_Activity::get() (value in parentheses is
1677
  * the default for the bp_activity_get()).
1678
  * - 'per_page' (false)
1679
  *
1680
- * @since 1.2.0
1681
- * @since 2.4.0 Introduced the `$fields` parameter.
1682
  *
1683
  * @see BP_Activity_Activity::get() For more information on accepted arguments
1684
  * and the format of the returned value.
 
 
 
 
 
1685
  *
1686
- * @param array|string $args See BP_Activity_Activity::get() for description.
1687
  * @return array $activity See BP_Activity_Activity::get() for description.
1688
  */
1689
  function bp_activity_get( $args = '' ) {
1690
-
1691
- $r = bp_parse_args( $args, array(
1692
- 'max' => false, // Maximum number of results to return.
1693
- 'fields' => 'all',
1694
- 'page' => 1, // Page 1 without a per_page will result in no pagination.
1695
  'per_page' => false, // results per page
1696
  'sort' => 'DESC', // sort ASC or DESC
1697
- 'display_comments' => false, // False for no comments. 'stream' for within stream display, 'threaded' for below each activity item.
1698
 
1699
  'search_terms' => false, // Pass search terms as a string
1700
  'meta_query' => false, // Filter by activity meta. See WP_Meta_Query for format
1701
- 'date_query' => false, // Filter by date. See first parameter of WP_Date_Query for format.
1702
- 'filter_query' => false,
1703
  'show_hidden' => false, // Show activity items that are hidden site-wide?
1704
- 'exclude' => false, // Comma-separated list of activity IDs to exclude.
1705
- 'in' => false, // Comma-separated list or array of activity IDs to which you
1706
- // want to limit the query.
1707
  'spam' => 'ham_only', // 'ham_only' (default), 'spam_only' or 'all'.
1708
  'update_meta_cache' => true,
1709
- 'count_total' => false,
1710
- 'scope' => false,
1711
 
1712
  /**
1713
  * Pass filters as an array -- all filter items can be multiple values comma separated:
1714
  * array(
1715
- * 'user_id' => false, // User ID to filter on.
1716
- * 'object' => false, // Object to filter on e.g. groups, profile, status, friends.
1717
- * 'action' => false, // Action to filter on e.g. activity_update, profile_updated.
1718
- * 'primary_id' => false, // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
1719
- * 'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
1720
  * );
1721
  */
1722
  'filter' => array()
1723
- ), 'activity_get' );
1724
-
1725
- $activity = BP_Activity_Activity::get( array(
1726
- 'page' => $r['page'],
1727
- 'per_page' => $r['per_page'],
1728
- 'max' => $r['max'],
1729
- 'sort' => $r['sort'],
1730
- 'search_terms' => $r['search_terms'],
1731
- 'meta_query' => $r['meta_query'],
1732
- 'date_query' => $r['date_query'],
1733
- 'filter_query' => $r['filter_query'],
1734
- 'filter' => $r['filter'],
1735
- 'scope' => $r['scope'],
1736
- 'display_comments' => $r['display_comments'],
1737
- 'show_hidden' => $r['show_hidden'],
1738
- 'exclude' => $r['exclude'],
1739
- 'in' => $r['in'],
1740
- 'spam' => $r['spam'],
1741
- 'update_meta_cache' => $r['update_meta_cache'],
1742
- 'count_total' => $r['count_total'],
1743
- 'fields' => $r['fields'],
1744
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1745
 
1746
- /**
1747
- * Filters the requested activity item(s).
1748
- *
1749
- * @since 1.2.0
1750
- *
1751
- * @param BP_Activity_Activity $activity Requested activity object.
1752
- * @param array $r Arguments used for the activity query.
1753
- */
1754
  return apply_filters_ref_array( 'bp_activity_get', array( &$activity, &$r ) );
1755
  }
1756
 
1757
  /**
1758
  * Fetch specific activity items.
1759
  *
1760
- * @since 1.2.0
1761
  *
1762
- * @see BP_Activity_Activity::get() For more information on accepted arguments.
 
 
 
1763
  *
1764
- * @param array|string $args {
1765
  * All arguments and defaults are shared with BP_Activity_Activity::get(),
1766
  * except for the following:
1767
  * @type string|int|array Single activity ID, comma-separated list of IDs,
1768
- * or array of IDs.
1769
  * }
1770
  * @return array $activity See BP_Activity_Activity::get() for description.
1771
  */
1772
  function bp_activity_get_specific( $args = '' ) {
1773
-
1774
- $r = bp_parse_args( $args, array(
1775
- 'activity_ids' => false, // A single activity_id or array of IDs.
1776
- 'display_comments' => false, // True or false to display threaded comments for these specific activity items.
1777
- 'max' => false, // Maximum number of results to return.
1778
- 'page' => 1, // Page 1 without a per_page will result in no pagination.
1779
- 'per_page' => false, // Results per page.
1780
- 'show_hidden' => true, // When fetching specific items, show all.
1781
- 'sort' => 'DESC', // Sort ASC or DESC
1782
- 'spam' => 'ham_only', // Retrieve items marked as spam.
1783
  'update_meta_cache' => true,
1784
- ), 'activity_get_specific' );
 
 
1785
 
1786
  $get_args = array(
1787
- 'display_comments' => $r['display_comments'],
1788
- 'in' => $r['activity_ids'],
1789
- 'max' => $r['max'],
1790
- 'page' => $r['page'],
1791
- 'per_page' => $r['per_page'],
1792
- 'show_hidden' => $r['show_hidden'],
1793
- 'sort' => $r['sort'],
1794
- 'spam' => $r['spam'],
1795
- 'update_meta_cache' => $r['update_meta_cache'],
1796
  );
1797
-
1798
- /**
1799
- * Filters the requested specific activity item.
1800
- *
1801
- * @since 1.2.0
1802
- *
1803
- * @param BP_Activity_Activity $activity Requested activity object.
1804
- * @param array $args Original passed in arguments.
1805
- * @param array $get_args Constructed arguments used with request.
1806
- */
1807
  return apply_filters( 'bp_activity_get_specific', BP_Activity_Activity::get( $get_args ), $args, $get_args );
1808
  }
1809
 
1810
  /**
1811
  * Add an activity item.
1812
  *
1813
- * @since 1.1.0
1814
- * @since 2.6.0 Added 'error_type' parameter to $args.
 
 
 
 
 
1815
  *
1816
- * @param array|string $args {
1817
  * An array of arguments.
1818
- * @type int|bool $id Pass an activity ID to update an existing item, or
1819
- * false to create a new item. Default: false.
1820
- * @type string $action Optional. The activity action/description, typically
1821
- * something like "Joe posted an update". Values passed to this param
1822
- * will be stored in the database and used as a fallback for when the
1823
- * activity item's format_callback cannot be found (eg, when the
1824
- * component is disabled). As long as you have registered a
1825
- * format_callback for your $type, it is unnecessary to include this
1826
- * argument - BP will generate it automatically.
1827
- * See {@link bp_activity_set_action()}.
1828
- * @type string $content Optional. The content of the activity item.
1829
- * @type string $component The unique name of the component associated with
1830
- * the activity item - 'groups', 'profile', etc.
1831
- * @type string $type The specific activity type, used for directory
1832
- * filtering. 'new_blog_post', 'activity_update', etc.
1833
- * @type string $primary_link Optional. The URL for this item, as used in
1834
- * RSS feeds. Defaults to the URL for this activity
1835
- * item's permalink page.
1836
- * @type int|bool $user_id Optional. The ID of the user associated with the activity
1837
- * item. May be set to false or 0 if the item is not related
1838
- * to any user. Default: the ID of the currently logged-in user.
1839
- * @type int $item_id Optional. The ID of the associated item.
1840
- * @type int $secondary_item_id Optional. The ID of a secondary associated item.
1841
- * @type string $date_recorded Optional. The GMT time, in Y-m-d h:i:s format, when
1842
- * the item was recorded. Defaults to the current time.
1843
- * @type bool $hide_sitewide Should the item be hidden on sitewide streams?
1844
- * Default: false.
1845
- * @type bool $is_spam Should the item be marked as spam? Default: false.
1846
- * @type string $error_type Optional. Error type. Either 'bool' or 'wp_error'. Default: 'bool'.
1847
  * }
1848
  * @return int|bool The ID of the activity on success. False on error.
1849
  */
1850
  function bp_activity_add( $args = '' ) {
1851
 
1852
- $r = bp_parse_args( $args, array(
1853
- 'id' => false, // Pass an existing activity ID to update an existing entry.
1854
- 'action' => '', // The activity action - e.g. "Jon Doe posted an update"
1855
- 'content' => '', // Optional: The content of the activity item e.g. "BuddyPress is awesome guys!"
1856
- 'component' => false, // The name/ID of the component e.g. groups, profile, mycomponent.
1857
- 'type' => false, // The activity type e.g. activity_update, profile_updated.
1858
- 'primary_link' => '', // Optional: The primary URL for this item in RSS feeds (defaults to activity permalink).
1859
- 'user_id' => bp_loggedin_user_id(), // Optional: The user to record the activity for, can be false if this activity is not for a user.
1860
- 'item_id' => false, // Optional: The ID of the specific item being recorded, e.g. a blog_id.
1861
- 'secondary_item_id' => false, // Optional: A second ID used to further filter e.g. a comment_id.
1862
- 'recorded_time' => bp_core_current_time(), // The GMT time that this activity was recorded.
1863
- 'hide_sitewide' => false, // Should this be hidden on the sitewide activity stream?
1864
- 'is_spam' => false, // Is this activity item to be marked as spam?
1865
- 'error_type' => 'bool'
1866
- ), 'activity_add' );
1867
-
1868
- // Make sure we are backwards compatible.
1869
- if ( empty( $r['component'] ) && !empty( $r['component_name'] ) ) {
1870
- $r['component'] = $r['component_name'];
1871
- }
1872
 
1873
- if ( empty( $r['type'] ) && !empty( $r['component_action'] ) ) {
1874
- $r['type'] = $r['component_action'];
1875
- }
1876
 
1877
- // Setup activity to be added.
1878
- $activity = new BP_Activity_Activity( $r['id'] );
1879
- $activity->user_id = $r['user_id'];
1880
- $activity->component = $r['component'];
1881
- $activity->type = $r['type'];
1882
- $activity->content = $r['content'];
1883
- $activity->primary_link = $r['primary_link'];
1884
- $activity->item_id = $r['item_id'];
1885
- $activity->secondary_item_id = $r['secondary_item_id'];
1886
- $activity->date_recorded = $r['recorded_time'];
1887
- $activity->hide_sitewide = $r['hide_sitewide'];
1888
- $activity->is_spam = $r['is_spam'];
1889
- $activity->error_type = $r['error_type'];
1890
- $activity->action = ! empty( $r['action'] )
1891
- ? $r['action']
1892
- : bp_activity_generate_action_string( $activity );
1893
-
1894
- $save = $activity->save();
1895
-
1896
- if ( 'wp_error' === $r['error_type'] && is_wp_error( $save ) ) {
1897
- return $save;
1898
- } elseif ('bool' === $r['error_type'] && false === $save ) {
1899
- return false;
1900
- }
1901
 
1902
- // If this is an activity comment, rebuild the tree.
1903
- if ( 'activity_comment' === $activity->type ) {
1904
- // Also clear the comment cache for the parent activity ID.
1905
- wp_cache_delete( $activity->item_id, 'bp_activity_comments' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1906
 
 
 
1907
  BP_Activity_Activity::rebuild_activity_comment_tree( $activity->item_id );
1908
- }
1909
 
1910
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
1911
-
1912
- /**
1913
- * Fires at the end of the execution of adding a new activity item, before returning the new activity item ID.
1914
- *
1915
- * @since 1.1.0
1916
- *
1917
- * @param array $r Array of parsed arguments for the activity item being added.
1918
- */
1919
- do_action( 'bp_activity_add', $r );
1920
 
1921
  return $activity->id;
1922
  }
@@ -1924,740 +1161,136 @@ function bp_activity_add( $args = '' ) {
1924
  /**
1925
  * Post an activity update.
1926
  *
1927
- * @since 1.2.0
1928
- *
1929
- * @param array|string $args {
1930
- * @type string $content The content of the activity update.
1931
- * @type int $user_id Optional. Defaults to the logged-in user.
1932
- * @type string $error_type Optional. Error type to return. Either 'bool' or 'wp_error'. Defaults to
1933
- * 'bool' for boolean. 'wp_error' will return a WP_Error object.
 
 
 
 
 
 
 
 
 
 
1934
  * }
1935
- * @return int|bool|WP_Error $activity_id The activity id on success. On failure, either boolean false or WP_Error
1936
- * object depending on the 'error_type' $args parameter.
1937
  */
1938
  function bp_activity_post_update( $args = '' ) {
 
1939
 
1940
- $r = wp_parse_args( $args, array(
1941
- 'content' => false,
1942
- 'user_id' => bp_loggedin_user_id(),
1943
- 'error_type' => 'bool',
1944
- ) );
 
1945
 
1946
- if ( empty( $r['content'] ) || !strlen( trim( $r['content'] ) ) ) {
1947
  return false;
1948
- }
1949
 
1950
- if ( bp_is_user_inactive( $r['user_id'] ) ) {
1951
  return false;
1952
- }
1953
-
1954
- // Record this on the user's profile.
1955
- $activity_content = $r['content'];
1956
- $primary_link = bp_core_get_userlink( $r['user_id'], false, true );
1957
 
1958
- /**
1959
- * Filters the new activity content for current activity item.
1960
- *
1961
- * @since 1.2.0
1962
- *
1963
- * @param string $activity_content Activity content posted by user.
1964
- */
1965
- $add_content = apply_filters( 'bp_activity_new_update_content', $activity_content );
1966
-
1967
- /**
1968
- * Filters the activity primary link for current activity item.
1969
- *
1970
- * @since 1.2.0
1971
- *
1972
- * @param string $primary_link Link to the profile for the user who posted the activity.
1973
- */
1974
- $add_primary_link = apply_filters( 'bp_activity_new_update_primary_link', $primary_link );
1975
 
1976
- // Now write the values.
1977
  $activity_id = bp_activity_add( array(
1978
- 'user_id' => $r['user_id'],
1979
- 'content' => $add_content,
1980
- 'primary_link' => $add_primary_link,
1981
- 'component' => buddypress()->activity->id,
1982
  'type' => 'activity_update',
1983
- 'error_type' => $r['error_type']
1984
  ) );
1985
 
1986
- // Bail on failure.
1987
- if ( false === $activity_id || is_wp_error( $activity_id ) ) {
1988
- return $activity_id;
1989
- }
1990
-
1991
- /**
1992
- * Filters the latest update content for the activity item.
1993
- *
1994
- * @since 1.6.0
1995
- *
1996
- * @param string $r Content of the activity update.
1997
- * @param string $activity_content Content of the activity update.
1998
- */
1999
- $activity_content = apply_filters( 'bp_activity_latest_update_content', $r['content'], $activity_content );
2000
 
2001
  // Add this update to the "latest update" usermeta so it can be fetched anywhere.
2002
- bp_update_user_meta( bp_loggedin_user_id(), 'bp_latest_update', array(
2003
- 'id' => $activity_id,
2004
- 'content' => $activity_content
2005
- ) );
2006
-
2007
- /**
2008
- * Fires at the end of an activity post update, before returning the updated activity item ID.
2009
- *
2010
- * @since 1.2.0
2011
- *
2012
- * @param string $content Content of the activity post update.
2013
- * @param int $user_id ID of the user posting the activity update.
2014
- * @param int $activity_id ID of the activity item being updated.
2015
- */
2016
- do_action( 'bp_activity_posted_update', $r['content'], $r['user_id'], $activity_id );
2017
-
2018
- return $activity_id;
2019
- }
2020
-
2021
- /**
2022
- * Create an activity item for a newly published post type post.
2023
- *
2024
- * @since 2.2.0
2025
- *
2026
- * @param int $post_id ID of the new post.
2027
- * @param WP_Post|null $post Post object.
2028
- * @param int $user_id ID of the post author.
2029
- * @return int|bool The ID of the activity on success. False on error.
2030
- */
2031
- function bp_activity_post_type_publish( $post_id = 0, $post = null, $user_id = 0 ) {
2032
-
2033
- if ( ! is_a( $post, 'WP_Post' ) ) {
2034
- return;
2035
- }
2036
-
2037
- // Get the post type tracking args.
2038
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post->post_type );
2039
-
2040
- if ( 'publish' != $post->post_status || ! empty( $post->post_password ) || empty( $activity_post_object->action_id ) ) {
2041
- return;
2042
- }
2043
-
2044
- if ( empty( $post_id ) ) {
2045
- $post_id = $post->ID;
2046
- }
2047
-
2048
- $blog_id = get_current_blog_id();
2049
-
2050
- if ( empty( $user_id ) ) {
2051
- $user_id = (int) $post->post_author;
2052
- }
2053
-
2054
- // Bail if an activity item already exists for this post.
2055
- $existing = bp_activity_get( array(
2056
- 'filter' => array(
2057
- 'action' => $activity_post_object->action_id,
2058
- 'primary_id' => $blog_id,
2059
- 'secondary_id' => $post_id,
2060
- )
2061
- ) );
2062
-
2063
- if ( ! empty( $existing['activities'] ) ) {
2064
- return;
2065
- }
2066
-
2067
- /**
2068
- * Filters whether or not to post the activity.
2069
- *
2070
- * This is a variable filter, dependent on the post type,
2071
- * that lets components or plugins bail early if needed.
2072
- *
2073
- * @since 2.2.0
2074
- *
2075
- * @param bool $value Whether or not to continue.
2076
- * @param int $blog_id ID of the current site.
2077
- * @param int $post_id ID of the current post being published.
2078
- * @param int $user_id ID of the current user or post author.
2079
- */
2080
- if ( false === apply_filters( "bp_activity_{$post->post_type}_pre_publish", true, $blog_id, $post_id, $user_id ) ) {
2081
- return;
2082
- }
2083
 
2084
- // Record this in activity streams.
2085
- $blog_url = get_home_url( $blog_id );
2086
- $post_url = add_query_arg(
2087
- 'p',
2088
- $post_id,
2089
- trailingslashit( $blog_url )
2090
- );
2091
-
2092
- // Backward compatibility filters for the 'blogs' component.
2093
- if ( 'blogs' == $activity_post_object->component_id ) {
2094
- $activity_content = apply_filters( 'bp_blogs_activity_new_post_content', $post->post_content, $post, $post_url, $post->post_type );
2095
- $activity_primary_link = apply_filters( 'bp_blogs_activity_new_post_primary_link', $post_url, $post_id, $post->post_type );
2096
- } else {
2097
- $activity_content = $post->post_content;
2098
- $activity_primary_link = $post_url;
2099
- }
2100
-
2101
- $activity_args = array(
2102
- 'user_id' => $user_id,
2103
- 'content' => $activity_content,
2104
- 'primary_link' => $activity_primary_link,
2105
- 'component' => $activity_post_object->component_id,
2106
- 'type' => $activity_post_object->action_id,
2107
- 'item_id' => $blog_id,
2108
- 'secondary_item_id' => $post_id,
2109
- 'recorded_time' => $post->post_date_gmt,
2110
- );
2111
-
2112
- if ( ! empty( $activity_args['content'] ) ) {
2113
- // Create the excerpt.
2114
- $activity_summary = bp_activity_create_summary( $activity_args['content'], $activity_args );
2115
-
2116
- // Backward compatibility filter for blog posts.
2117
- if ( 'blogs' == $activity_post_object->component_id ) {
2118
- $activity_args['content'] = apply_filters( 'bp_blogs_record_activity_content', $activity_summary, $activity_args['content'], $activity_args, $post->post_type );
2119
- } else {
2120
- $activity_args['content'] = $activity_summary;
2121
- }
2122
- }
2123
-
2124
- // Set up the action by using the format functions.
2125
- $action_args = array_merge( $activity_args, array(
2126
- 'post_title' => $post->post_title,
2127
- 'post_url' => $post_url,
2128
- ) );
2129
-
2130
- $activity_args['action'] = call_user_func_array( $activity_post_object->format_callback, array( '', (object) $action_args ) );
2131
-
2132
- // Make sure the action is set.
2133
- if ( empty( $activity_args['action'] ) ) {
2134
- return;
2135
- } else {
2136
- // Backward compatibility filter for the blogs component.
2137
- if ( 'blogs' == $activity_post_object->component_id ) {
2138
- $activity_args['action'] = apply_filters( 'bp_blogs_record_activity_action', $activity_args['action'] );
2139
- }
2140
- }
2141
-
2142
- $activity_id = bp_activity_add( $activity_args );
2143
-
2144
- /**
2145
- * Fires after the publishing of an activity item for a newly published post type post.
2146
- *
2147
- * @since 2.2.0
2148
- *
2149
- * @param int $activity_id ID of the newly published activity item.
2150
- * @param WP_Post $post Post object.
2151
- * @param array $activity_args Array of activity arguments.
2152
- */
2153
- do_action( 'bp_activity_post_type_published', $activity_id, $post, $activity_args );
2154
 
2155
  return $activity_id;
2156
  }
2157
 
2158
- /**
2159
- * Update the activity item for a custom post type entry.
2160
- *
2161
- * @since 2.2.0
2162
- *
2163
- * @param WP_Post|null $post Post item.
2164
- * @return bool True on success, false on failure.
2165
- */
2166
- function bp_activity_post_type_update( $post = null ) {
2167
-
2168
- if ( ! is_a( $post, 'WP_Post' ) ) {
2169
- return;
2170
- }
2171
-
2172
- // Get the post type tracking args.
2173
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post->post_type );
2174
-
2175
- if ( empty( $activity_post_object->action_id ) ) {
2176
- return;
2177
- }
2178
-
2179
- $activity_id = bp_activity_get_activity_id( array(
2180
- 'component' => $activity_post_object->component_id,
2181
- 'item_id' => get_current_blog_id(),
2182
- 'secondary_item_id' => $post->ID,
2183
- 'type' => $activity_post_object->action_id,
2184
- ) );
2185
-
2186
- // Activity ID doesn't exist, so stop!
2187
- if ( empty( $activity_id ) ) {
2188
- return;
2189
- }
2190
-
2191
- // Delete the activity if the post was updated with a password.
2192
- if ( ! empty( $post->post_password ) ) {
2193
- bp_activity_delete( array( 'id' => $activity_id ) );
2194
- }
2195
-
2196
- // Update the activity entry.
2197
- $activity = new BP_Activity_Activity( $activity_id );
2198
-
2199
- if ( ! empty( $post->post_content ) ) {
2200
- $activity_summary = bp_activity_create_summary( $post->post_content, (array) $activity );
2201
-
2202
- // Backward compatibility filter for the blogs component.
2203
- if ( 'blogs' == $activity_post_object->component_id ) {
2204
- $activity->content = apply_filters( 'bp_blogs_record_activity_content', $activity_summary, $post->post_content, (array) $activity, $post->post_type );
2205
- } else {
2206
- $activity->content = $activity_summary;
2207
- }
2208
- }
2209
-
2210
- // Save the updated activity.
2211
- $updated = $activity->save();
2212
-
2213
- /**
2214
- * Fires after the updating of an activity item for a custom post type entry.
2215
- *
2216
- * @since 2.2.0
2217
- * @since 2.5.0 Add the post type tracking args parameter
2218
- *
2219
- * @param WP_Post $post Post object.
2220
- * @param BP_Activity_Activity $activity Activity object.
2221
- * @param object $activity_post_object The post type tracking args object.
2222
- */
2223
- do_action( 'bp_activity_post_type_updated', $post, $activity, $activity_post_object );
2224
-
2225
- return $updated;
2226
- }
2227
-
2228
- /**
2229
- * Unpublish an activity for the custom post type.
2230
- *
2231
- * @since 2.2.0
2232
- *
2233
- * @param int $post_id ID of the post being unpublished.
2234
- * @param WP_Post|null $post Post object.
2235
- * @return bool True on success, false on failure.
2236
- */
2237
- function bp_activity_post_type_unpublish( $post_id = 0, $post = null ) {
2238
-
2239
- if ( ! is_a( $post, 'WP_Post' ) ) {
2240
- return;
2241
- }
2242
-
2243
- // Get the post type tracking args.
2244
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post->post_type );
2245
-
2246
- if ( empty( $activity_post_object->action_id ) ) {
2247
- return;
2248
- }
2249
-
2250
- if ( empty( $post_id ) ) {
2251
- $post_id = $post->ID;
2252
- }
2253
-
2254
- $delete_activity_args = array(
2255
- 'item_id' => get_current_blog_id(),
2256
- 'secondary_item_id' => $post_id,
2257
- 'component' => $activity_post_object->component_id,
2258
- 'type' => $activity_post_object->action_id,
2259
- 'user_id' => false,
2260
- );
2261
-
2262
- $deleted = bp_activity_delete_by_item_id( $delete_activity_args );
2263
-
2264
- /**
2265
- * Fires after the unpublishing for the custom post type.
2266
- *
2267
- * @since 2.2.0
2268
- *
2269
- * @param array $delete_activity_args Array of arguments for activity deletion.
2270
- * @param WP_Post $post Post object.
2271
- * @param bool $activity Whether or not the activity was successfully deleted.
2272
- */
2273
- do_action( 'bp_activity_post_type_unpublished', $delete_activity_args, $post, $deleted );
2274
-
2275
- return $deleted;
2276
- }
2277
-
2278
- /**
2279
- * Create an activity item for a newly posted post type comment.
2280
- *
2281
- * @since 2.5.0
2282
- *
2283
- * @param int $comment_id ID of the comment.
2284
- * @param bool $is_approved Whether the comment is approved or not.
2285
- * @param object|null $activity_post_object The post type tracking args object.
2286
- * @return int|bool The ID of the activity on success. False on error.
2287
- */
2288
- function bp_activity_post_type_comment( $comment_id = 0, $is_approved = true, $activity_post_object = null ) {
2289
- // Get the users comment
2290
- $post_type_comment = get_comment( $comment_id );
2291
-
2292
- // Don't record activity if the comment hasn't been approved
2293
- if ( empty( $is_approved ) ) {
2294
- return false;
2295
- }
2296
-
2297
- // Don't record activity if no email address has been included
2298
- if ( empty( $post_type_comment->comment_author_email ) ) {
2299
- return false;
2300
- }
2301
-
2302
- // Don't record activity if the comment has already been marked as spam
2303
- if ( 'spam' === $is_approved ) {
2304
- return false;
2305
- }
2306
-
2307
- // Get the user by the comment author email.
2308
- $user = get_user_by( 'email', $post_type_comment->comment_author_email );
2309
-
2310
- // If user isn't registered, don't record activity
2311
- if ( empty( $user ) ) {
2312
- return false;
2313
- }
2314
-
2315
- // Get the user_id
2316
- $user_id = (int) $user->ID;
2317
-
2318
- // Get blog and post data
2319
- $blog_id = get_current_blog_id();
2320
-
2321
- // Get the post
2322
- $post_type_comment->post = get_post( $post_type_comment->comment_post_ID );
2323
-
2324
- if ( ! is_a( $post_type_comment->post, 'WP_Post' ) ) {
2325
- return false;
2326
- }
2327
-
2328
- /**
2329
- * Filters whether to publish activities about the comment regarding the post status
2330
- *
2331
- * @since 2.5.0
2332
- *
2333
- * @param bool true to bail, false otherwise.
2334
- */
2335
- $is_post_status_not_allowed = (bool) apply_filters( 'bp_activity_post_type_is_post_status_allowed', 'publish' !== $post_type_comment->post->post_status || ! empty( $post_type_comment->post->post_password ) );
2336
-
2337
- // If this is a password protected post, or not a public post don't record the comment
2338
- if ( $is_post_status_not_allowed ) {
2339
- return false;
2340
- }
2341
-
2342
- // Set post type
2343
- $post_type = $post_type_comment->post->post_type;
2344
-
2345
- if ( empty( $activity_post_object ) ) {
2346
- // Get the post type tracking args.
2347
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
2348
-
2349
- // Bail if the activity type does not exist
2350
- if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
2351
- return false;
2352
- }
2353
- }
2354
-
2355
- // Set the $activity_comment_object
2356
- $activity_comment_object = $activity_post_object->comments_tracking;
2357
-
2358
- /**
2359
- * Filters whether or not to post the activity about the comment.
2360
- *
2361
- * This is a variable filter, dependent on the post type,
2362
- * that lets components or plugins bail early if needed.
2363
- *
2364
- * @since 2.5.0
2365
- *
2366
- * @param bool $value Whether or not to continue.
2367
- * @param int $blog_id ID of the current site.
2368
- * @param int $post_id ID of the current post being commented.
2369
- * @param int $user_id ID of the current user.
2370
- * @param int $comment_id ID of the current comment being posted.
2371
- */
2372
- if ( false === apply_filters( "bp_activity_{$post_type}_pre_comment", true, $blog_id, $post_type_comment->post->ID, $user_id, $comment_id ) ) {
2373
- return false;
2374
- }
2375
-
2376
- // Is this an update ?
2377
- $activity_id = bp_activity_get_activity_id( array(
2378
- 'user_id' => $user_id,
2379
- 'component' => $activity_comment_object->component_id,
2380
- 'type' => $activity_comment_object->action_id,
2381
- 'item_id' => $blog_id,
2382
- 'secondary_item_id' => $comment_id,
2383
- ) );
2384
-
2385
- // Record this in activity streams.
2386
- $comment_link = get_comment_link( $post_type_comment->comment_ID );
2387
-
2388
- // Backward compatibility filters for the 'blogs' component.
2389
- if ( 'blogs' == $activity_comment_object->component_id ) {
2390
- $activity_content = apply_filters_ref_array( 'bp_blogs_activity_new_comment_content', array( $post_type_comment->comment_content, &$post_type_comment, $comment_link ) );
2391
- $activity_primary_link = apply_filters_ref_array( 'bp_blogs_activity_new_comment_primary_link', array( $comment_link, &$post_type_comment ) );
2392
- } else {
2393
- $activity_content = $post_type_comment->comment_content;
2394
- $activity_primary_link = $comment_link;
2395
- }
2396
-
2397
- $activity_args = array(
2398
- 'id' => $activity_id,
2399
- 'user_id' => $user_id,
2400
- 'content' => $activity_content,
2401
- 'primary_link' => $activity_primary_link,
2402
- 'component' => $activity_comment_object->component_id,
2403
- 'recorded_time' => $post_type_comment->comment_date_gmt,
2404
- );
2405
-
2406
- if ( bp_disable_blogforum_comments() ) {
2407
- $blog_url = get_home_url( $blog_id );
2408
- $post_url = add_query_arg(
2409
- 'p',
2410
- $post_type_comment->post->ID,
2411
- trailingslashit( $blog_url )
2412
- );
2413
-
2414
- $activity_args['type'] = $activity_comment_object->action_id;
2415
- $activity_args['item_id'] = $blog_id;
2416
- $activity_args['secondary_item_id'] = $post_type_comment->comment_ID;
2417
-
2418
- if ( ! empty( $activity_args['content'] ) ) {
2419
- // Create the excerpt.
2420
- $activity_summary = bp_activity_create_summary( $activity_args['content'], $activity_args );
2421
-
2422
- // Backward compatibility filter for blog comments.
2423
- if ( 'blogs' == $activity_post_object->component_id ) {
2424
- $activity_args['content'] = apply_filters( 'bp_blogs_record_activity_content', $activity_summary, $activity_args['content'], $activity_args, $post_type );
2425
- } else {
2426
- $activity_args['content'] = $activity_summary;
2427
- }
2428
- }
2429
-
2430
- // Set up the action by using the format functions.
2431
- $action_args = array_merge( $activity_args, array(
2432
- 'post_title' => $post_type_comment->post->post_title,
2433
- 'post_url' => $post_url,
2434
- 'blog_url' => $blog_url,
2435
- 'blog_name' => get_blog_option( $blog_id, 'blogname' ),
2436
- ) );
2437
-
2438
- $activity_args['action'] = call_user_func_array( $activity_comment_object->format_callback, array( '', (object) $action_args ) );
2439
-
2440
- // Make sure the action is set.
2441
- if ( empty( $activity_args['action'] ) ) {
2442
- return;
2443
- } else {
2444
- // Backward compatibility filter for the blogs component.
2445
- if ( 'blogs' === $activity_post_object->component_id ) {
2446
- $activity_args['action'] = apply_filters( 'bp_blogs_record_activity_action', $activity_args['action'] );
2447
- }
2448
- }
2449
-
2450
- $activity_id = bp_activity_add( $activity_args );
2451
- }
2452
-
2453
- /**
2454
- * Fires after the publishing of an activity item for a newly published post type post.
2455
- *
2456
- * @since 2.5.0
2457
- *
2458
- * @param int $activity_id ID of the newly published activity item.
2459
- * @param WP_Comment $post_type_comment Comment object.
2460
- * @param array $activity_args Array of activity arguments.
2461
- * @param object $activity_post_object the post type tracking args object.
2462
- */
2463
- do_action_ref_array( 'bp_activity_post_type_comment', array( &$activity_id, $post_type_comment, $activity_args, $activity_post_object ) );
2464
-
2465
- return $activity_id;
2466
- }
2467
- add_action( 'comment_post', 'bp_activity_post_type_comment', 10, 2 );
2468
- add_action( 'edit_comment', 'bp_activity_post_type_comment', 10 );
2469
-
2470
- /**
2471
- * Remove an activity item when a comment about a post type is deleted.
2472
- *
2473
- * @since 2.5.0
2474
- *
2475
- * @param int $comment_id ID of the comment.
2476
- * @param object|null $activity_post_object The post type tracking args object.
2477
- * @return bool True on success. False on error.
2478
- */
2479
- function bp_activity_post_type_remove_comment( $comment_id = 0, $activity_post_object = null ) {
2480
- if ( empty( $activity_post_object ) ) {
2481
- $comment = get_comment( $comment_id );
2482
- if ( ! $comment ) {
2483
- return;
2484
- }
2485
-
2486
- $post_type = get_post_type( $comment->comment_post_ID );
2487
- if ( ! $post_type ) {
2488
- return;
2489
- }
2490
-
2491
- // Get the post type tracking args.
2492
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
2493
-
2494
- // Bail if the activity type does not exist
2495
- if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
2496
- return false;
2497
- }
2498
- }
2499
-
2500
- // Set the $activity_comment_object
2501
- $activity_comment_object = $activity_post_object->comments_tracking;
2502
-
2503
- if ( empty( $activity_comment_object->action_id ) ) {
2504
- return false;
2505
- }
2506
-
2507
- $deleted = false;
2508
-
2509
- if ( bp_disable_blogforum_comments() ) {
2510
- $deleted = bp_activity_delete_by_item_id( array(
2511
- 'item_id' => get_current_blog_id(),
2512
- 'secondary_item_id' => $comment_id,
2513
- 'component' => $activity_comment_object->component_id,
2514
- 'type' => $activity_comment_object->action_id,
2515
- 'user_id' => false,
2516
- ) );
2517
- }
2518
-
2519
- /**
2520
- * Fires after the custom post type comment activity was removed.
2521
- *
2522
- * @since 2.5.0
2523
- *
2524
- * @param bool $deleted True if the activity was deleted false otherwise
2525
- * @param WP_Comment $comment Comment object.
2526
- * @param object $activity_post_object The post type tracking args object.
2527
- * @param string $value The post type comment activity type.
2528
- */
2529
- do_action( 'bp_activity_post_type_remove_comment', $deleted, $comment_id, $activity_post_object, $activity_comment_object->action_id );
2530
-
2531
- return $deleted;
2532
- }
2533
- add_action( 'delete_comment', 'bp_activity_post_type_remove_comment', 10, 1 );
2534
-
2535
  /**
2536
  * Add an activity comment.
2537
  *
2538
- * @since 1.2.0
2539
- * @since 2.5.0 Add a new possible parameter $skip_notification for the array of arguments.
2540
- * Add the $primary_link parameter for the array of arguments.
2541
- * @since 2.6.0 Added 'error_type' parameter to $args.
2542
- *
2543
- * @param array|string $args {
2544
- * An array of arguments.
2545
- * @type int $id Optional. Pass an ID to update an existing comment.
2546
- * @type string $content The content of the comment.
2547
- * @type int $user_id Optional. The ID of the user making the comment.
2548
- * Defaults to the ID of the logged-in user.
2549
- * @type int $activity_id The ID of the "root" activity item, ie the oldest
2550
- * ancestor of the comment.
2551
- * @type int $parent_id Optional. The ID of the parent activity item, ie the item to
2552
- * which the comment is an immediate reply. If not provided,
2553
- * this value defaults to the $activity_id.
2554
- * @type string $primary_link Optional. the primary link for the comment.
2555
- * Defaults to an empty string.
2556
- * @type bool $skip_notification Optional. false to send a comment notification, false otherwise.
2557
- * Defaults to false.
2558
- * @type string $error_type Optional. Error type. Either 'bool' or 'wp_error'. Default: 'bool'.
2559
  * }
2560
  * @return int|bool The ID of the comment on success, otherwise false.
2561
  */
2562
  function bp_activity_new_comment( $args = '' ) {
2563
- $bp = buddypress();
2564
 
2565
- $r = wp_parse_args( $args, array(
2566
- 'id' => false,
2567
- 'content' => false,
2568
- 'user_id' => bp_loggedin_user_id(),
2569
- 'activity_id' => false, // ID of the root activity item.
2570
- 'parent_id' => false, // ID of a parent comment (optional).
2571
- 'primary_link' => '',
2572
- 'skip_notification' => false,
2573
- 'error_type' => 'bool'
2574
  ) );
2575
 
2576
- // Error type is boolean; need to initialize some variables for backpat.
2577
- if ( 'bool' === $r['error_type'] ) {
2578
- if ( empty( $bp->activity->errors ) ) {
2579
- $bp->activity->errors = array();
2580
- }
2581
- }
2582
-
2583
- // Default error message.
2584
- $feedback = __( 'There was an error posting your reply. Please try again.', 'buddypress' );
2585
 
2586
- // Bail if missing necessary data.
2587
- if ( empty( $r['content'] ) || empty( $r['user_id'] ) || empty( $r['activity_id'] ) ) {
2588
- $error = new WP_Error( 'missing_data', $feedback );
2589
-
2590
- if ( 'wp_error' === $r['error_type'] ) {
2591
- return $error;
2592
-
2593
- // Backpat.
2594
- } else {
2595
- $bp->activity->errors['new_comment'] = $error;
2596
- return false;
2597
- }
2598
  }
2599
 
2600
- // Maybe set current activity ID as the parent.
2601
- if ( empty( $r['parent_id'] ) ) {
2602
- $r['parent_id'] = $r['activity_id'];
2603
  }
2604
 
2605
- $activity_id = $r['activity_id'];
2606
-
2607
- // Get the parent activity.
2608
  $activity = new BP_Activity_Activity( $activity_id );
 
2609
 
2610
- // Bail if the parent activity does not exist.
2611
- if ( empty( $activity->date_recorded ) ) {
2612
- $error = new WP_Error( 'missing_activity', __( 'The item you were replying to no longer exists.', 'buddypress' ) );
2613
-
2614
- if ( 'wp_error' === $r['error_type'] ) {
2615
- return $error;
2616
-
2617
- // Backpat.
2618
- } else {
2619
- $bp->activity->errors['new_comment'] = $error;
2620
- return false;
2621
- }
2622
-
2623
- }
2624
-
2625
- // Check to see if the parent activity is hidden, and if so, hide this comment publicly.
2626
- $is_hidden = $activity->hide_sitewide ? 1 : 0;
2627
-
2628
- /**
2629
- * Filters the content of a new comment.
2630
- *
2631
- * @since 1.2.0
2632
- *
2633
- * @param string $r Content for the newly posted comment.
2634
- */
2635
- $comment_content = apply_filters( 'bp_activity_comment_content', $r['content'] );
2636
-
2637
- // Insert the activity comment.
2638
  $comment_id = bp_activity_add( array(
2639
- 'id' => $r['id'],
2640
- 'content' => $comment_content,
2641
  'component' => buddypress()->activity->id,
2642
  'type' => 'activity_comment',
2643
- 'primary_link' => $r['primary_link'],
2644
- 'user_id' => $r['user_id'],
2645
  'item_id' => $activity_id,
2646
- 'secondary_item_id' => $r['parent_id'],
2647
- 'hide_sitewide' => $is_hidden,
2648
- 'error_type' => $r['error_type']
2649
  ) );
2650
 
2651
- // Bail on failure.
2652
- if ( false === $comment_id || is_wp_error( $comment_id ) ) {
2653
- return $comment_id;
2654
- }
2655
-
2656
- // Comment caches are stored only with the top-level item.
2657
  wp_cache_delete( $activity_id, 'bp_activity_comments' );
2658
 
2659
- // Walk the tree to clear caches for all parent items.
2660
- $clear_id = $r['parent_id'];
2661
  while ( $clear_id != $activity_id ) {
2662
  $clear_object = new BP_Activity_Activity( $clear_id );
2663
  wp_cache_delete( $clear_id, 'bp_activity' );
@@ -2665,43 +1298,7 @@ function bp_activity_new_comment( $args = '' ) {
2665
  }
2666
  wp_cache_delete( $activity_id, 'bp_activity' );
2667
 
2668
- if ( empty( $r[ 'skip_notification' ] ) ) {
2669
- /**
2670
- * Fires near the end of an activity comment posting, before the returning of the comment ID.
2671
- * Sends a notification to the user @see bp_activity_new_comment_notification_helper().
2672
- *
2673
- * @since 1.2.0
2674
- *
2675
- * @param int $comment_id ID of the newly posted activity comment.
2676
- * @param array $r Array of parsed comment arguments.
2677
- * @param BP_Activity_Activity $activity Activity item being commented on.
2678
- */
2679
- do_action( 'bp_activity_comment_posted', $comment_id, $r, $activity );
2680
- } else {
2681
- /**
2682
- * Fires near the end of an activity comment posting, before the returning of the comment ID.
2683
- * without sending a notification to the user
2684
- *
2685
- * @since 2.5.0
2686
- *
2687
- * @param int $comment_id ID of the newly posted activity comment.
2688
- * @param array $r Array of parsed comment arguments.
2689
- * @param BP_Activity_Activity $activity Activity item being commented on.
2690
- */
2691
- do_action( 'bp_activity_comment_posted_notification_skipped', $comment_id, $r, $activity );
2692
- }
2693
-
2694
- if ( empty( $comment_id ) ) {
2695
- $error = new WP_Error( 'comment_failed', $feedback );
2696
-
2697
- if ( 'wp_error' === $r['error_type'] ) {
2698
- return $error;
2699
-
2700
- // Backpat.
2701
- } else {
2702
- $bp->activity->errors['new_comment'] = $error;
2703
- }
2704
- }
2705
 
2706
  return $comment_id;
2707
  }
@@ -2709,16 +1306,18 @@ function bp_activity_new_comment( $args = '' ) {
2709
  /**
2710
  * Fetch the activity_id for an existing activity entry in the DB.
2711
  *
2712
- * @since 1.2.0
2713
  *
2714
  * @see BP_Activity_Activity::get() For more information on accepted arguments.
 
 
 
2715
  *
2716
- * @param array|string $args See BP_Activity_Activity::get() for description.
2717
  * @return int $activity_id The ID of the activity item found.
2718
  */
2719
  function bp_activity_get_activity_id( $args = '' ) {
2720
-
2721
- $r = bp_parse_args( $args, array(
2722
  'user_id' => false,
2723
  'component' => false,
2724
  'type' => false,
@@ -2727,28 +1326,12 @@ function bp_activity_get_activity_id( $args = '' ) {
2727
  'action' => false,
2728
  'content' => false,
2729
  'date_recorded' => false,
2730
- ) );
2731
 
2732
- /**
2733
- * Filters the activity ID being requested.
2734
- *
2735
- * @since 1.2.0
2736
- * @since 2.5.0 Added the `$r` and `$args` parameters.
2737
- *
2738
- * @param BP_Activity_Activity $value ID returned by BP_Activity_Activity get_id() method with provided arguments.
2739
- * @param array $r Parsed function arguments.
2740
- * @param array $args Arguments passed to the function.
2741
- */
2742
- return apply_filters( 'bp_activity_get_activity_id', BP_Activity_Activity::get_id(
2743
- $r['user_id'],
2744
- $r['component'],
2745
- $r['type'],
2746
- $r['item_id'],
2747
- $r['secondary_item_id'],
2748
- $r['action'],
2749
- $r['content'],
2750
- $r['date_recorded']
2751
- ), $r, $args );
2752
  }
2753
 
2754
  /**
@@ -2764,21 +1347,29 @@ function bp_activity_get_activity_id( $args = '' ) {
2764
  *
2765
  * If you are deleting an activity comment please use bp_activity_delete_comment();
2766
  *
2767
- * @since 1.0.0
2768
  *
2769
  * @see BP_Activity_Activity::get() For more information on accepted arguments.
2770
- *
2771
- * @param array|string $args To delete specific activity items, use
2772
- * $args = array( 'id' => $ids ); Otherwise, to use
2773
- * filters for item deletion, the argument format is
2774
- * the same as BP_Activity_Activity::get().
2775
- * See that method for a description.
 
 
 
 
 
 
 
 
2776
  * @return bool True on success, false on failure.
2777
  */
2778
  function bp_activity_delete( $args = '' ) {
2779
 
2780
- // Pass one or more the of following variables to delete by those variables.
2781
- $args = bp_parse_args( $args, array(
2782
  'id' => false,
2783
  'action' => false,
2784
  'content' => false,
@@ -2790,29 +1381,23 @@ function bp_activity_delete( $args = '' ) {
2790
  'secondary_item_id' => false,
2791
  'date_recorded' => false,
2792
  'hide_sitewide' => false
2793
- ) );
 
 
2794
 
2795
- /**
2796
- * Fires before an activity item proceeds to be deleted.
2797
- *
2798
- * @since 1.5.0
2799
- *
2800
- * @param array $args Array of arguments to be used with the activity deletion.
2801
- */
2802
  do_action( 'bp_before_activity_delete', $args );
2803
 
2804
- // Adjust the new mention count of any mentioned member.
2805
  bp_activity_adjust_mention_count( $args['id'], 'delete' );
2806
 
2807
- $activity_ids_deleted = BP_Activity_Activity::delete( $args );
2808
- if ( empty( $activity_ids_deleted ) ) {
2809
  return false;
2810
- }
2811
 
2812
- // Check if the user's latest update has been deleted.
2813
- $user_id = empty( $args['user_id'] )
2814
- ? bp_loggedin_user_id()
2815
- : $args['user_id'];
 
2816
 
2817
  $latest_update = bp_get_user_meta( $user_id, 'bp_latest_update', true );
2818
  if ( !empty( $latest_update ) ) {
@@ -2821,22 +1406,7 @@ function bp_activity_delete( $args = '' ) {
2821
  }
2822
  }
2823
 
2824
- /**
2825
- * Fires after the activity item has been deleted.
2826
- *
2827
- * @since 1.0.0
2828
- *
2829
- * @param array $args Array of arguments used with the activity deletion.
2830
- */
2831
  do_action( 'bp_activity_delete', $args );
2832
-
2833
- /**
2834
- * Fires after the activity item has been deleted.
2835
- *
2836
- * @since 1.2.0
2837
- *
2838
- * @param array $activity_ids_deleted Array of affected activity item IDs.
2839
- */
2840
  do_action( 'bp_activity_deleted_activities', $activity_ids_deleted );
2841
 
2842
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
@@ -2849,34 +1419,40 @@ function bp_activity_delete( $args = '' ) {
2849
  *
2850
  * You should use bp_activity_delete() instead.
2851
  *
2852
- * @since 1.1.0
2853
- * @deprecated 1.2.0
 
 
 
2854
  *
 
 
2855
  *
2856
- * @param array|string $args See BP_Activity_Activity::get for a
2857
- * description of accepted arguments.
2858
  * @return bool True on success, false on failure.
2859
  */
2860
  function bp_activity_delete_by_item_id( $args = '' ) {
2861
 
2862
- $r = bp_parse_args( $args, array(
2863
  'item_id' => false,
2864
  'component' => false,
2865
  'type' => false,
2866
  'user_id' => false,
2867
  'secondary_item_id' => false
2868
- ) );
 
 
2869
 
2870
- return bp_activity_delete( $r );
2871
  }
2872
 
2873
  /**
2874
  * Delete an activity item by activity id.
2875
  *
2876
- * @since 1.1.0
2877
  *
 
2878
  *
2879
- * @param int $activity_id ID of the activity item to be deleted.
2880
  * @return bool True on success, false on failure.
2881
  */
2882
  function bp_activity_delete_by_activity_id( $activity_id ) {
@@ -2888,23 +1464,19 @@ function bp_activity_delete( $args = '' ) {
2888
  *
2889
  * You should use bp_activity_delete() instead.
2890
  *
2891
- * @since 1.1.0
2892
- * @deprecated 1.2.0
2893
  *
 
2894
  *
2895
- * @param int $user_id The user id.
2896
- * @param string $content The activity id.
2897
  * @param string $component The activity component.
2898
- * @param string $type The activity type.
2899
  * @return bool True on success, false on failure.
2900
  */
2901
  function bp_activity_delete_by_content( $user_id, $content, $component, $type ) {
2902
- return bp_activity_delete( array(
2903
- 'user_id' => $user_id,
2904
- 'content' => $content,
2905
- 'component' => $component,
2906
- 'type' => $type
2907
- ) );
2908
  }
2909
 
2910
  /**
@@ -2912,26 +1484,29 @@ function bp_activity_delete( $args = '' ) {
2912
  *
2913
  * You should use bp_activity_delete() instead.
2914
  *
2915
- * @since 1.1.0
2916
- * @deprecated 1.2.0
2917
  *
 
2918
  *
2919
- * @param int $user_id The user id.
2920
  * @param string $component The activity component.
2921
  * @return bool True on success, false on failure.
2922
  */
2923
  function bp_activity_delete_for_user_by_component( $user_id, $component ) {
2924
- return bp_activity_delete( array(
2925
- 'user_id' => $user_id,
2926
- 'component' => $component
2927
- ) );
2928
  }
2929
 
2930
  /**
2931
  * Delete an activity comment.
2932
  *
2933
- * @since 1.2.0
2934
  *
 
 
 
 
 
2935
  * @todo Why is an activity id required? We could look this up.
2936
  * @todo Why do we encourage users to call this function directly? We could just
2937
  * as easily examine the activity type in bp_activity_delete() and then
@@ -2939,87 +1514,53 @@ function bp_activity_delete( $args = '' ) {
2939
  *
2940
  * @param int $activity_id The ID of the "root" activity, ie the comment's
2941
  * oldest ancestor.
2942
- * @param int $comment_id The ID of the comment to be deleted.
2943
- * @return bool True on success, false on failure.
2944
  */
2945
  function bp_activity_delete_comment( $activity_id, $comment_id ) {
2946
- $deleted = false;
2947
-
2948
- /**
2949
- * Filters whether BuddyPress should delete an activity comment or not.
2950
- *
2951
  * You may want to hook into this filter if you want to override this function and
2952
  * handle the deletion of child comments differently. Make sure you return false.
2953
- *
2954
- * @since 1.2.0
2955
- * @since 2.5.0 Add the deleted parameter (passed by reference)
2956
- *
2957
- * @param bool $value Whether BuddyPress should continue or not.
2958
- * @param int $activity_id ID of the root activity item being deleted.
2959
- * @param int $comment_id ID of the comment being deleted.
2960
- * @param bool $deleted Whether the activity comment has been deleted or not.
2961
  */
2962
- if ( ! apply_filters_ref_array( 'bp_activity_delete_comment_pre', array( true, $activity_id, $comment_id, &$deleted ) ) ) {
2963
- return $deleted;
2964
- }
2965
 
2966
  // Delete any children of this comment.
2967
  bp_activity_delete_children( $activity_id, $comment_id );
2968
 
2969
- // Delete the actual comment.
2970
- if ( ! bp_activity_delete( array( 'id' => $comment_id, 'type' => 'activity_comment' ) ) ) {
2971
  return false;
2972
- } else {
2973
- $deleted = true;
2974
- }
2975
-
2976
- // Purge comment cache for the root activity update.
2977
- wp_cache_delete( $activity_id, 'bp_activity_comments' );
2978
 
2979
- // Recalculate the comment tree.
2980
  BP_Activity_Activity::rebuild_activity_comment_tree( $activity_id );
2981
 
2982
- /**
2983
- * Fires at the end of the deletion of an activity comment, before returning success.
2984
- *
2985
- * @since 1.2.0
2986
- *
2987
- * @param int $activity_id ID of the activity that has had a comment deleted from.
2988
- * @param int $comment_id ID of the comment that was deleted.
2989
- */
2990
  do_action( 'bp_activity_delete_comment', $activity_id, $comment_id );
2991
 
2992
- return $deleted;
2993
  }
2994
 
2995
  /**
2996
  * Delete an activity comment's children.
2997
  *
2998
- * @since 1.2.0
2999
  *
 
 
 
3000
  *
3001
  * @param int $activity_id The ID of the "root" activity, ie the
3002
  * comment's oldest ancestor.
3003
- * @param int $comment_id The ID of the comment to be deleted.
3004
  */
3005
- function bp_activity_delete_children( $activity_id, $comment_id ) {
3006
-
3007
- // Get activity children to delete.
3008
- $children = BP_Activity_Activity::get_child_comments( $comment_id );
3009
-
3010
  // Recursively delete all children of this comment.
3011
- if ( ! empty( $children ) ) {
3012
  foreach( (array) $children as $child ) {
3013
  bp_activity_delete_children( $activity_id, $child->id );
3014
  }
3015
  }
3016
-
3017
- // Delete the comment itself.
3018
- bp_activity_delete( array(
3019
- 'secondary_item_id' => $comment_id,
3020
- 'type' => 'activity_comment',
3021
- 'item_id' => $activity_id
3022
- ) );
3023
  }
3024
 
3025
  /**
@@ -3030,58 +1571,44 @@ function bp_activity_delete_comment( $activity_id, $comment_id ) {
3030
  * be sure to pass the full $activity_obj parameter as well, if you already
3031
  * have it available.
3032
  *
3033
- * @since 1.2.0
 
 
 
 
3034
  *
3035
- * @param int $activity_id The unique id of the activity object.
3036
- * @param object|bool $activity_obj Optional. The activity object.
3037
  * @return string $link Permalink for the activity item.
3038
  */
3039
  function bp_activity_get_permalink( $activity_id, $activity_obj = false ) {
3040
- $bp = buddypress();
3041
 
3042
- if ( empty( $activity_obj ) ) {
3043
  $activity_obj = new BP_Activity_Activity( $activity_id );
3044
- }
3045
 
3046
  if ( isset( $activity_obj->current_comment ) ) {
3047
  $activity_obj = $activity_obj->current_comment;
3048
  }
3049
 
3050
- $use_primary_links = array(
3051
- 'new_blog_post',
3052
- 'new_blog_comment',
3053
- 'new_forum_topic',
3054
- 'new_forum_post',
3055
- );
3056
-
3057
- if ( ! empty( $bp->activity->track ) ) {
3058
- $use_primary_links = array_merge( $use_primary_links, array_keys( $bp->activity->track ) );
3059
- }
3060
-
3061
- if ( false !== array_search( $activity_obj->type, $use_primary_links ) ) {
3062
  $link = $activity_obj->primary_link;
3063
  } else {
3064
  if ( 'activity_comment' == $activity_obj->type ) {
3065
- $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->item_id . '/#acomment-' . $activity_obj->id;
3066
  } else {
3067
  $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->id . '/';
3068
  }
3069
  }
3070
 
3071
- /**
3072
- * Filters the activity permalink for the specified activity item.
3073
- *
3074
- * @since 1.2.0
3075
- *
3076
- * @param array $array Array holding activity permalink and activity item object.
3077
- */
3078
  return apply_filters_ref_array( 'bp_activity_get_permalink', array( $link, &$activity_obj ) );
3079
  }
3080
 
3081
  /**
3082
  * Hide a user's activity.
3083
  *
3084
- * @since 1.2.0
 
 
3085
  *
3086
  * @param int $user_id The ID of the user whose activity is being hidden.
3087
  * @return bool True on success, false on failure.
@@ -3100,14 +1627,15 @@ function bp_activity_hide_user_activity( $user_id ) {
3100
  * through the content, grabs the first image and converts it to a thumbnail,
3101
  * and removes the rest of the images from the string.
3102
  *
3103
- * As of BuddyPress 2.3, this function is no longer in use.
3104
  *
3105
- * @since 1.2.0
 
3106
  *
3107
- * @param string $content The content of the activity item.
3108
- * @param string|bool $link Optional. The unescaped URL that the image should link
3109
- * to. If absent, the image will not be a link.
3110
- * @param array|bool $args Optional. The args passed to the activity
3111
  * creation function (eg bp_blogs_record_activity()).
3112
  * @return string $content The content with images stripped and replaced with a
3113
  * single thumb.
@@ -3116,28 +1644,21 @@ function bp_activity_thumbnail_content_images( $content, $link = false, $args =
3116
 
3117
  preg_match_all( '/<img[^>]*>/Ui', $content, $matches );
3118
 
3119
- // Remove <img> tags. Also remove caption shortcodes and caption text if present.
3120
  $content = preg_replace('|(\[caption(.*?)\])?<img[^>]*>([^\[\[]*\[\/caption\])?|', '', $content );
3121
 
3122
  if ( !empty( $matches ) && !empty( $matches[0] ) ) {
 
 
3123
 
3124
- // Get the SRC value.
3125
- preg_match( '/<img.*?(src\=[\'|"]{0,1}.*?[\'|"]{0,1})[\s|>]{1}/i', $matches[0][0], $src );
3126
-
3127
- // Get the width and height.
3128
  preg_match( '/<img.*?(height\=[\'|"]{0,1}.*?[\'|"]{0,1})[\s|>]{1}/i', $matches[0][0], $height );
3129
  preg_match( '/<img.*?(width\=[\'|"]{0,1}.*?[\'|"]{0,1})[\s|>]{1}/i', $matches[0][0], $width );
3130
 
3131
- if ( ! empty( $src ) ) {
3132
- $src = substr( substr( str_replace( 'src=', '', $src[1] ), 0, -1 ), 1 );
3133
-
3134
- if ( isset( $width[1] ) ) {
3135
- $width = substr( substr( str_replace( 'width=', '', $width[1] ), 0, -1 ), 1 );
3136
- }
3137
-
3138
- if ( isset( $height[1] ) ) {
3139
- $height = substr( substr( str_replace( 'height=', '', $height[1] ), 0, -1 ), 1 );
3140
- }
3141
 
3142
  if ( empty( $width ) || empty( $height ) ) {
3143
  $width = 100;
@@ -3157,521 +1678,100 @@ function bp_activity_thumbnail_content_images( $content, $link = false, $args =
3157
  }
3158
  }
3159
 
3160
- /**
3161
- * Filters the activity content that had a thumbnail replace images.
3162
- *
3163
- * @since 1.2.0
3164
- *
3165
- * @param string $content Activity content that had images replaced in.
3166
- * @param array $matches Array of all image tags found in the posted content.
3167
- * @param array $args Arguments passed into function creating the activity update.
3168
- */
3169
  return apply_filters( 'bp_activity_thumbnail_content_images', $content, $matches, $args );
3170
  }
3171
 
3172
- /**
3173
- * Gets the excerpt length for activity items.
3174
- *
3175
- * @since 2.8.0
3176
- *
3177
- * @return int Character length for activity excerpts.
3178
- */
3179
- function bp_activity_get_excerpt_length() {
3180
- /**
3181
- * Filters the excerpt length for the activity excerpt.
3182
- *
3183
- * @since 1.5.0
3184
- *
3185
- * @param int Character length for activity excerpts.
3186
- */
3187
- return (int) apply_filters( 'bp_activity_excerpt_length', 358 );
3188
- }
3189
-
3190
- /**
3191
- * Create a rich summary of an activity item for the activity stream.
3192
- *
3193
- * More than just a simple excerpt, the summary could contain oEmbeds and other types of media.
3194
- * Currently, it's only used for blog post items, but it will probably be used for all types of
3195
- * activity in the future.
3196
- *
3197
- * @since 2.3.0
3198
- *
3199
- * @param string $content The content of the activity item.
3200
- * @param array $activity The data passed to bp_activity_add() or the values
3201
- * from an Activity obj.
3202
- * @return string $summary
3203
- */
3204
- function bp_activity_create_summary( $content, $activity ) {
3205
- $args = array(
3206
- 'width' => isset( $GLOBALS['content_width'] ) ? (int) $GLOBALS['content_width'] : 'medium',
3207
- );
3208
-
3209
- // Get the WP_Post object if this activity type is a blog post.
3210
- if ( $activity['type'] === 'new_blog_post' ) {
3211
- $content = get_post( $activity['secondary_item_id'] );
3212
- }
3213
-
3214
- /**
3215
- * Filter the class name of the media extractor when creating an Activity summary.
3216
- *
3217
- * Use this filter to change the media extractor used to extract media info for the activity item.
3218
- *
3219
- * @since 2.3.0
3220
- *
3221
- * @param string $extractor Class name.
3222
- * @param string $content The content of the activity item.
3223
- * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj.
3224
- */
3225
- $extractor = apply_filters( 'bp_activity_create_summary_extractor_class', 'BP_Media_Extractor', $content, $activity );
3226
- $extractor = new $extractor;
3227
-
3228
- /**
3229
- * Filter the arguments passed to the media extractor when creating an Activity summary.
3230
- *
3231
- * @since 2.3.0
3232
- *
3233
- * @param array $args Array of bespoke data for the media extractor.
3234
- * @param string $content The content of the activity item.
3235
- * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj.
3236
- * @param BP_Media_Extractor $extractor The media extractor object.
3237
- */
3238
- $args = apply_filters( 'bp_activity_create_summary_extractor_args', $args, $content, $activity, $extractor );
3239
-
3240
-
3241
- // Extract media information from the $content.
3242
- $media = $extractor->extract( $content, BP_Media_Extractor::ALL, $args );
3243
-
3244
- // If we converted $content to an object earlier, flip it back to a string.
3245
- if ( is_a( $content, 'WP_Post' ) ) {
3246
- $content = $content->post_content;
3247
- }
3248
-
3249
- $para_count = substr_count( strtolower( wpautop( $content ) ), '<p>' );
3250
- $has_audio = ! empty( $media['has']['audio'] ) && $media['has']['audio'];
3251
- $has_videos = ! empty( $media['has']['videos'] ) && $media['has']['videos'];
3252
- $has_feat_image = ! empty( $media['has']['featured_images'] ) && $media['has']['featured_images'];
3253
- $has_galleries = ! empty( $media['has']['galleries'] ) && $media['has']['galleries'];
3254
- $has_images = ! empty( $media['has']['images'] ) && $media['has']['images'];
3255
- $has_embeds = false;
3256
-
3257
- // Embeds must be subtracted from the paragraph count.
3258
- if ( ! empty( $media['has']['embeds'] ) ) {
3259
- $has_embeds = $media['has']['embeds'] > 0;
3260
- $para_count -= count( $media['has']['embeds'] );
3261
- }
3262
-
3263
- $extracted_media = array();
3264
- $use_media_type = '';
3265
- $image_source = '';
3266
-
3267
- // If it's a short article and there's an embed/audio/video, use it.
3268
- if ( $para_count <= 3 ) {
3269
- if ( $has_embeds ) {
3270
- $use_media_type = 'embeds';
3271
- } elseif ( $has_audio ) {
3272
- $use_media_type = 'audio';
3273
- } elseif ( $has_videos ) {
3274
- $use_media_type = 'videos';
3275
- }
3276
- }
3277
-
3278
- // If not, or in any other situation, try to use an image.
3279
- if ( ! $use_media_type && $has_images ) {
3280
- $use_media_type = 'images';
3281
- $image_source = 'html';
3282
-
3283
- // Featured Image > Galleries > inline <img>.
3284
- if ( $has_feat_image ) {
3285
- $image_source = 'featured_images';
3286
-
3287
- } elseif ( $has_galleries ) {
3288
- $image_source = 'galleries';
3289
- }
3290
- }
3291
-
3292
- // Extract an item from the $media results.
3293
- if ( $use_media_type ) {
3294
- if ( $use_media_type === 'images' ) {
3295
- $extracted_media = wp_list_filter( $media[ $use_media_type ], array( 'source' => $image_source ) );
3296
- $extracted_media = array_shift( $extracted_media );
3297
- } else {
3298
- $extracted_media = array_shift( $media[ $use_media_type ] );
3299
- }
3300
-
3301
- /**
3302
- * Filter the results of the media extractor when creating an Activity summary.
3303
- *
3304
- * @since 2.3.0
3305
- *
3306
- * @param array $extracted_media Extracted media item. See {@link BP_Media_Extractor::extract()} for format.
3307
- * @param string $content Content of the activity item.
3308
- * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj.
3309
- * @param array $media All results from the media extraction.
3310
- * See {@link BP_Media_Extractor::extract()} for format.
3311
- * @param string $use_media_type The kind of media item that was preferentially extracted.
3312
- * @param string $image_source If $use_media_type was "images", the preferential source of the image.
3313
- * Otherwise empty.
3314
- */
3315
- $extracted_media = apply_filters(
3316
- 'bp_activity_create_summary_extractor_result',
3317
- $extracted_media,
3318
- $content,
3319
- $activity,
3320
- $media,
3321
- $use_media_type,
3322
- $image_source
3323
- );
3324
- }
3325
-
3326
- // Generate a text excerpt for this activity item (and remove any oEmbeds URLs).
3327
- $summary = bp_create_excerpt( html_entity_decode( $content ), 225, array(
3328
- 'html' => false,
3329
- 'filter_shortcodes' => true,
3330
- 'strip_tags' => true,
3331
- 'remove_links' => true
3332
- ) );
3333
-
3334
- if ( $use_media_type === 'embeds' ) {
3335
- $summary .= PHP_EOL . PHP_EOL . $extracted_media['url'];
3336
- } elseif ( $use_media_type === 'images' ) {
3337
- $summary .= sprintf( ' <img src="%s">', esc_url( $extracted_media['url'] ) );
3338
- } elseif ( in_array( $use_media_type, array( 'audio', 'videos' ), true ) ) {
3339
- $summary .= PHP_EOL . PHP_EOL . $extracted_media['original']; // Full shortcode.
3340
- }
3341
-
3342
- /**
3343
- * Filters the newly-generated summary for the activity item.
3344
- *
3345
- * @since 2.3.0
3346
- *
3347
- * @param string $summary Activity summary HTML.
3348
- * @param string $content Content of the activity item.
3349
- * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj.
3350
- * @param array $extracted_media Media item extracted. See {@link BP_Media_Extractor::extract()} for format.
3351
- */
3352
- return apply_filters( 'bp_activity_create_summary', $summary, $content, $activity, $extracted_media );
3353
- }
3354
-
3355
  /**
3356
  * Fetch whether the current user is allowed to mark items as spam.
3357
  *
3358
- * @since 1.6.0
3359
  *
3360
  * @return bool True if user is allowed to mark activity items as spam.
3361
  */
3362
  function bp_activity_user_can_mark_spam() {
3363
-
3364
- /**
3365
- * Filters whether the current user should be able to mark items as spam.
3366
- *
3367
- * @since 1.6.0
3368
- *
3369
- * @param bool $moderate Whether or not the current user has bp_moderate capability.
3370
- */
3371
  return apply_filters( 'bp_activity_user_can_mark_spam', bp_current_user_can( 'bp_moderate' ) );
3372
  }
3373
 
3374
  /**
3375
  * Mark an activity item as spam.
3376
  *
3377
- * @since 1.6.0
3378
  *
3379
- * @todo We should probably save $source to activity meta.
3380
  *
3381
  * @param BP_Activity_Activity $activity The activity item to be spammed.
3382
- * @param string $source Optional. Default is "by_a_person" (ie, a person has
3383
- * manually marked the activity as spam). BP core also
3384
- * accepts 'by_akismet'.
3385
  */
3386
  function bp_activity_mark_as_spam( &$activity, $source = 'by_a_person' ) {
3387
- $bp = buddypress();
3388
 
3389
  $activity->is_spam = 1;
3390
 
3391
- // Clear the activity stream first page cache.
3392
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
3393
 
3394
- // Clear the activity comment cache for this activity item.
3395
  wp_cache_delete( $activity->id, 'bp_activity_comments' );
3396
 
3397
- // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity.
3398
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
3399
- remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4 );
3400
 
3401
- // Build data package for Akismet.
3402
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
3403
 
3404
- // Tell Akismet this is spam.
3405
  $activity_data = $bp->activity->akismet->send_akismet_request( $activity_data, 'submit', 'spam' );
3406
 
3407
- // Update meta.
3408
  add_action( 'bp_activity_after_save', array( $bp->activity->akismet, 'update_activity_spam_meta' ), 1, 1 );
3409
  }
3410
 
3411
- /**
3412
- * Fires at the end of the process to mark an activity item as spam.
3413
- *
3414
- * @since 1.6.0
3415
- *
3416
- * @param BP_Activity_Activity $activity Activity item being marked as spam.
3417
- * @param string $source Source of determination of spam status. For example
3418
- * "by_a_person" or "by_akismet".
3419
- */
3420
  do_action( 'bp_activity_mark_as_spam', $activity, $source );
3421
  }
3422
 
3423
  /**
3424
  * Mark an activity item as ham.
3425
  *
3426
- * @since 1.6.0
3427
  *
3428
- * @param BP_Activity_Activity $activity The activity item to be hammed. Passed by reference.
3429
- * @param string $source Optional. Default is "by_a_person" (ie, a person has
3430
- * manually marked the activity as spam). BP core also accepts
3431
- * 'by_akismet'.
 
 
3432
  */
3433
  function bp_activity_mark_as_ham( &$activity, $source = 'by_a_person' ) {
3434
- $bp = buddypress();
3435
 
3436
  $activity->is_spam = 0;
3437
 
3438
- // Clear the activity stream first page cache.
3439
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
3440
 
3441
- // Clear the activity comment cache for this activity item.
3442
  wp_cache_delete( $activity->id, 'bp_activity_comments' );
3443
 
3444
- // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity.
3445
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
3446
- remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4 );
3447
 
3448
- // Build data package for Akismet.
3449
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
3450
 
3451
- // Tell Akismet this is spam.
3452
  $activity_data = $bp->activity->akismet->send_akismet_request( $activity_data, 'submit', 'ham' );
3453
 
3454
- // Update meta.
3455
  add_action( 'bp_activity_after_save', array( $bp->activity->akismet, 'update_activity_ham_meta' ), 1, 1 );
3456
  }
3457
 
3458
- /**
3459
- * Fires at the end of the process to mark an activity item as ham.
3460
- *
3461
- * @since 1.6.0
3462
- *
3463
- * @param BP_Activity_Activity $activity Activity item being marked as ham.
3464
- * @param string $source Source of determination of ham status. For example
3465
- * "by_a_person" or "by_akismet".
3466
- */
3467
  do_action( 'bp_activity_mark_as_ham', $activity, $source );
3468
  }
3469
 
3470
- /* Emails *********************************************************************/
3471
-
3472
- /**
3473
- * Send email and BP notifications when a user is mentioned in an update.
3474
- *
3475
- * @since 1.2.0
3476
- *
3477
- * @param int $activity_id The ID of the activity update.
3478
- * @param int $receiver_user_id The ID of the user who is receiving the update.
3479
- */
3480
- function bp_activity_at_message_notification( $activity_id, $receiver_user_id ) {
3481
- $notifications = BP_Core_Notification::get_all_for_user( $receiver_user_id, 'all' );
3482
-
3483
- // Don't leave multiple notifications for the same activity item.
3484
- foreach( $notifications as $notification ) {
3485
- if ( $activity_id == $notification->item_id ) {
3486
- return;
3487
- }
3488
- }
3489
-
3490
- $activity = new BP_Activity_Activity( $activity_id );
3491
- $email_type = 'activity-at-message';
3492
- $group_name = '';
3493
- $message_link = bp_activity_get_permalink( $activity_id );
3494
- $poster_name = bp_core_get_user_displayname( $activity->user_id );
3495
-
3496
- remove_filter( 'bp_get_activity_content_body', 'convert_smilies' );
3497
- remove_filter( 'bp_get_activity_content_body', 'wpautop' );
3498
- remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
3499
-
3500
- /** This filter is documented in bp-activity/bp-activity-template.php */
3501
- $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $activity->content, &$activity ) );
3502
-
3503
- add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
3504
- add_filter( 'bp_get_activity_content_body', 'wpautop' );
3505
- add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
3506
-
3507
- // Now email the user with the contents of the message (if they have enabled email notifications).
3508
- if ( 'no' != bp_get_user_meta( $receiver_user_id, 'notification_activity_new_mention', true ) ) {
3509
- if ( bp_is_active( 'groups' ) && bp_is_group() ) {
3510
- $email_type = 'groups-at-message';
3511
- $group_name = bp_get_current_group_name();
3512
- }
3513
-
3514
- $unsubscribe_args = array(
3515
- 'user_id' => $receiver_user_id,
3516
- 'notification_type' => $email_type,
3517
- );
3518
-
3519
- $args = array(
3520
- 'tokens' => array(
3521
- 'activity' => $activity,
3522
- 'usermessage' => wp_strip_all_tags( $content ),
3523
- 'group.name' => $group_name,
3524
- 'mentioned.url' => $message_link,
3525
- 'poster.name' => $poster_name,
3526
- 'receiver-user.id' => $receiver_user_id,
3527
- 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
3528
- ),
3529
- );
3530
-
3531
- bp_send_email( $email_type, $receiver_user_id, $args );
3532
- }
3533
-
3534
- /**
3535
- * Fires after the sending of an @mention email notification.
3536
- *
3537
- * @since 1.5.0
3538
- * @since 2.5.0 $subject, $message, $content arguments unset and deprecated.
3539
- *
3540
- * @param BP_Activity_Activity $activity Activity Item object.
3541
- * @param string $deprecated Removed in 2.5; now an empty string.
3542
- * @param string $deprecated Removed in 2.5; now an empty string.
3543
- * @param string $deprecated Removed in 2.5; now an empty string.
3544
- * @param int $receiver_user_id The ID of the user who is receiving the update.
3545
- */
3546
- do_action( 'bp_activity_sent_mention_email', $activity, '', '', '', $receiver_user_id );
3547
- }
3548
-
3549
- /**
3550
- * Send email and BP notifications when an activity item receives a comment.
3551
- *
3552
- * @since 1.2.0
3553
- * @since 2.5.0 Updated to use new email APIs.
3554
- *
3555
- * @param int $comment_id The comment id.
3556
- * @param int $commenter_id The ID of the user who posted the comment.
3557
- * @param array $params {@link bp_activity_new_comment()}.
3558
- */
3559
- function bp_activity_new_comment_notification( $comment_id = 0, $commenter_id = 0, $params = array() ) {
3560
- $original_activity = new BP_Activity_Activity( $params['activity_id'] );
3561
- $poster_name = bp_core_get_user_displayname( $commenter_id );
3562
- $thread_link = bp_activity_get_permalink( $params['activity_id'] );
3563
-
3564
- remove_filter( 'bp_get_activity_content_body', 'convert_smilies' );
3565
- remove_filter( 'bp_get_activity_content_body', 'wpautop' );
3566
- remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
3567
-
3568
- /** This filter is documented in bp-activity/bp-activity-template.php */
3569
- $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $params['content'], &$original_activity ) );
3570
-
3571
- add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
3572
- add_filter( 'bp_get_activity_content_body', 'wpautop' );
3573
- add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
3574
-
3575
- if ( $original_activity->user_id != $commenter_id ) {
3576
-
3577
- // Send an email if the user hasn't opted-out.
3578
- if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
3579
-
3580
- $unsubscribe_args = array(
3581
- 'user_id' => $original_activity->user_id,
3582
- 'notification_type' => 'activity-comment',
3583
- );
3584
-
3585
- $args = array(
3586
- 'tokens' => array(
3587
- 'comment.id' => $comment_id,
3588
- 'commenter.id' => $commenter_id,
3589
- 'usermessage' => wp_strip_all_tags( $content ),
3590
- 'original_activity.user_id' => $original_activity->user_id,
3591
- 'poster.name' => $poster_name,
3592
- 'thread.url' => esc_url( $thread_link ),
3593
- 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
3594
- ),
3595
- );
3596
-
3597
- bp_send_email( 'activity-comment', $original_activity->user_id, $args );
3598
- }
3599
-
3600
- /**
3601
- * Fires at the point that notifications should be sent for activity comments.
3602
- *
3603
- * @since 2.6.0
3604
- *
3605
- * @param BP_Activity_Activity $original_activity The original activity.
3606
- * @param int $comment_id ID for the newly received comment.
3607
- * @param int $commenter_id ID of the user who made the comment.
3608
- * @param array $params Arguments used with the original activity comment.
3609
- */
3610
- do_action( 'bp_activity_sent_reply_to_update_notification', $original_activity, $comment_id, $commenter_id, $params );
3611
- }
3612
-
3613
-
3614
- /*
3615
- * If this is a reply to another comment, send an email notification to the
3616
- * author of the immediate parent comment.
3617
- */
3618
- if ( empty( $params['parent_id'] ) || ( $params['activity_id'] == $params['parent_id'] ) ) {
3619
- return;
3620
- }
3621
-
3622
- $parent_comment = new BP_Activity_Activity( $params['parent_id'] );
3623
-
3624
- if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id ) {
3625
-
3626
- // Send an email if the user hasn't opted-out.
3627
- if ( 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
3628
-
3629
- $unsubscribe_args = array(
3630
- 'user_id' => $parent_comment->user_id,
3631
- 'notification_type' => 'activity-comment-author',
3632
- );
3633
-
3634
- $args = array(
3635
- 'tokens' => array(
3636
- 'comment.id' => $comment_id,
3637
- 'commenter.id' => $commenter_id,
3638
- 'usermessage' => wp_strip_all_tags( $content ),
3639
- 'parent-comment-user.id' => $parent_comment->user_id,
3640
- 'poster.name' => $poster_name,
3641
- 'thread.url' => esc_url( $thread_link ),
3642
- 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
3643
- ),
3644
- );
3645
-
3646
- bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
3647
- }
3648
-
3649
- /**
3650
- * Fires at the point that notifications should be sent for comments on activity replies.
3651
- *
3652
- * @since 2.6.0
3653
- *
3654
- * @param BP_Activity_Activity $parent_comment The parent activity.
3655
- * @param int $comment_id ID for the newly received comment.
3656
- * @param int $commenter_id ID of the user who made the comment.
3657
- * @param array $params Arguments used with the original activity comment.
3658
- */
3659
- do_action( 'bp_activity_sent_reply_to_reply_notification', $parent_comment, $comment_id, $commenter_id, $params );
3660
- }
3661
- }
3662
-
3663
- /**
3664
- * Helper method to map action arguments to function parameters.
3665
- *
3666
- * @since 1.9.0
3667
- *
3668
- * @param int $comment_id ID of the comment being notified about.
3669
- * @param array $params Parameters to use with notification.
3670
- */
3671
- function bp_activity_new_comment_notification_helper( $comment_id, $params ) {
3672
- bp_activity_new_comment_notification( $comment_id, $params['user_id'], $params );
3673
- }
3674
- add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_helper', 10, 2 );
3675
 
3676
  /** Embeds *******************************************************************/
3677
 
@@ -3685,37 +1785,22 @@ add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_
3685
  * This does not cover recursive activity comments, as they do not use a real loop.
3686
  * For that, see {@link bp_activity_comment_embed()}.
3687
  *
3688
- * @since 1.5.0
3689
  *
3690
  * @see BP_Embed
3691
  * @see bp_embed_activity_cache()
3692
  * @see bp_embed_activity_save_cache()
3693
- *
 
 
3694
  */
3695
  function bp_activity_embed() {
3696
  add_filter( 'embed_post_id', 'bp_get_activity_id' );
3697
- add_filter( 'oembed_dataparse', 'bp_activity_oembed_dataparse', 10, 2 );
3698
  add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 );
3699
  add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
3700
  }
3701
  add_action( 'activity_loop_start', 'bp_activity_embed' );
3702
 
3703
- /**
3704
- * Cache full oEmbed response from oEmbed.
3705
- *
3706
- * @since 2.6.0
3707
- *
3708
- * @param string $retval Current oEmbed result.
3709
- * @param object $data Full oEmbed response.
3710
- * @param string $url URL used for the oEmbed request.
3711
- * @return string
3712
- */
3713
- function bp_activity_oembed_dataparse( $retval, $data ) {
3714
- buddypress()->activity->oembed_response = $data;
3715
-
3716
- return $retval;
3717
- }
3718
-
3719
  /**
3720
  * Set up activity oEmbed cache while recursing through activity comments.
3721
  *
@@ -3724,12 +1809,14 @@ function bp_activity_oembed_dataparse( $retval, $data ) {
3724
  * necessary to grab each comment's embeds from the cache, or put them in
3725
  * the cache if they are not there yet.
3726
  *
3727
- * @since 1.5.0
3728
  *
3729
  * @see BP_Embed
3730
  * @see bp_embed_activity_cache()
3731
  * @see bp_embed_activity_save_cache()
3732
- *
 
 
3733
  */
3734
  function bp_activity_comment_embed() {
3735
  add_filter( 'embed_post_id', 'bp_get_activity_comment_id' );
@@ -3741,21 +1828,26 @@ add_action( 'bp_before_activity_comment', 'bp_activity_comment_embed' );
3741
  /**
3742
  * When a user clicks on a "Read More" item, make sure embeds are correctly parsed and shown for the expanded content.
3743
  *
3744
- * @since 1.5.0
3745
  *
3746
  * @see BP_Embed
 
 
 
 
3747
  *
3748
  * @param object $activity The activity that is being expanded.
3749
  */
3750
  function bp_dtheme_embed_read_more( $activity ) {
3751
- buddypress()->activity->read_more_id = $activity->id;
3752
 
3753
- add_filter( 'embed_post_id', function() { return buddypress()->activity->read_more_id; } );
3754
- add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 );
3755
- add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
 
 
3756
  }
3757
- add_action( 'bp_dtheme_get_single_activity_content', 'bp_dtheme_embed_read_more' );
3758
- add_action( 'bp_legacy_theme_get_single_activity_content', 'bp_dtheme_embed_read_more' );
3759
 
3760
  /**
3761
  * Clean up 'embed_post_id' filter after comment recursion.
@@ -3763,9 +1855,10 @@ add_action( 'bp_legacy_theme_get_single_activity_content', 'bp_dtheme_embed_read
3763
  * This filter must be removed so that the non-comment filters take over again
3764
  * once the comments are done being processed.
3765
  *
3766
- * @since 1.5.0
3767
  *
3768
  * @see bp_activity_comment_embed()
 
3769
  */
3770
  function bp_activity_comment_embed_after_recurse() {
3771
  remove_filter( 'embed_post_id', 'bp_get_activity_comment_id' );
@@ -3777,13 +1870,14 @@ add_action( 'bp_after_activity_comment', 'bp_activity_comment_embed_after_recurs
3777
  *
3778
  * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}.
3779
  *
3780
- * @since 1.5.0
3781
  *
3782
  * @see BP_Embed::parse_oembed()
 
3783
  *
3784
- * @param string $cache An empty string passed by BP_Embed::parse_oembed() for
3785
- * functions like this one to filter.
3786
- * @param int $id The ID of the activity item.
3787
  * @param string $cachekey The cache key generated in BP_Embed::parse_oembed().
3788
  * @return mixed The cached embeds for this activity item.
3789
  */
@@ -3796,45 +1890,56 @@ function bp_embed_activity_cache( $cache, $id, $cachekey ) {
3796
  *
3797
  * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}.
3798
  *
3799
- * @since 1.5.0
3800
  *
3801
  * @see BP_Embed::parse_oembed()
 
3802
  *
3803
- * @param string $cache An empty string passed by BP_Embed::parse_oembed() for
3804
- * functions like this one to filter.
 
3805
  * @param string $cachekey The cache key generated in BP_Embed::parse_oembed().
3806
- * @param int $id The ID of the activity item.
3807
  */
3808
  function bp_embed_activity_save_cache( $cache, $cachekey, $id ) {
3809
  bp_activity_update_meta( $id, $cachekey, $cache );
3810
-
3811
- // Cache full oEmbed response.
3812
- if ( true === isset( buddypress()->activity->oembed_response ) ) {
3813
- $cachekey = str_replace( '_oembed', '_oembed_response', $cachekey );
3814
- bp_activity_update_meta( $id, $cachekey, buddypress()->activity->oembed_response );
3815
- }
3816
  }
3817
 
3818
  /**
3819
  * Should we use Heartbeat to refresh activities?
3820
  *
3821
- * @since 2.0.0
 
 
 
 
 
 
 
 
 
3822
  *
3823
  * @return bool True if activity heartbeat is enabled, otherwise false.
3824
  */
3825
  function bp_activity_do_heartbeat() {
3826
  $retval = false;
3827
 
3828
- if ( bp_is_activity_heartbeat_active() && ( bp_is_activity_directory() || bp_is_group_activity() ) ) {
 
 
 
 
3829
  $retval = true;
3830
  }
3831
 
3832
- /**
3833
- * Filters whether the heartbeat feature in the activity stream should be active.
3834
- *
3835
- * @since 2.8.0
3836
- *
3837
- * @param bool $retval Whether or not activity heartbeat is active.
3838
- */
3839
- return (bool) apply_filters( 'bp_activity_do_heartbeat', $retval );
 
 
3840
  }
1
  <?php
2
+
3
  /**
4
  * BuddyPress Activity Functions.
5
  *
7
  *
8
  * @package BuddyPress
9
  * @subpackage ActivityFunctions
 
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( !defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
  * Check whether the $bp global lists an activity directory page.
17
  *
18
+ * @since BuddyPress (1.5)
19
+ *
20
+ * @global object $bp BuddyPress global settings
21
  *
22
  * @return bool True if activity directory page is found, otherwise false.
23
  */
24
  function bp_activity_has_directory() {
25
+ global $bp;
26
+
27
+ return (bool) !empty( $bp->pages->activity->id );
28
  }
29
 
30
  /**
32
  *
33
  * The Mentions feature does a number of things, all of which will be turned
34
  * off if you disable mentions:
35
+ * - Detecting and auto-linking @username in all BP/WP content
36
  * - Sending BP notifications and emails to users when they are mentioned
37
+ * using the @username syntax
38
+ * - The Public Message button on user profiles
39
  *
40
  * Mentions are enabled by default. To disable, put the following line in
41
  * bp-custom.php or your theme's functions.php file:
42
  *
43
  * add_filter( 'bp_activity_do_mentions', '__return_false' );
44
  *
45
+ * @since BuddyPress (1.8)
46
+ *
47
+ * @uses apply_filters() To call 'bp_activity_do_mentions' hook.
48
  *
49
  * @return bool $retval True to enable mentions, false to disable.
50
  */
51
  function bp_activity_do_mentions() {
 
 
 
 
 
 
 
 
52
  return (bool) apply_filters( 'bp_activity_do_mentions', true );
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  /**
56
  * Locate usernames in an activity content string, as designated by an @ sign.
57
  *
58
+ * @since BuddyPress (1.5)
59
  *
60
+ * @param string $content The content of the activity, usually found in $activity->content.
61
+ * @return array|bool Associative array with user ID as key and username as value. Boolean false if no mentions found.
 
 
62
  */
63
  function bp_activity_find_mentions( $content ) {
 
64
  $pattern = '/[@]+([A-Za-z0-9-_\.@]+)\b/';
65
  preg_match_all( $pattern, $content, $usernames );
66
 
67
+ // Make sure there's only one instance of each username
68
+ if ( !$usernames = array_unique( $usernames[1] ) )
 
 
 
69
  return false;
 
70
 
71
  $mentioned_users = array();
72
 
73
+ // We've found some mentions! Check to see if users exist
74
+ foreach( (array) $usernames as $key => $username ) {
75
  $user_id = bp_activity_get_userid_from_mentionname( $username );
76
 
77
+ // user ID exists, so let's add it to our array
78
  if ( ! empty( $user_id ) ) {
79
+ $mentioned_users[$user_id] = $username;
80
  }
81
  }
82
 
83
+ if ( empty( $mentioned_users ) )
84
  return false;
 
85
 
86
+ return $mentioned_users;
 
 
 
 
 
 
 
87
  }
88
 
89
  /**
90
  * Reset a user's unread mentions list and count.
91
  *
92
+ * @since BuddyPress (1.5)
93
+ *
94
+ * @uses bp_delete_user_meta()
95
  *
96
  * @param int $user_id The id of the user whose unread mentions are being reset.
97
  */
98
  function bp_activity_clear_new_mentions( $user_id ) {
99
  bp_delete_user_meta( $user_id, 'bp_new_mention_count' );
100
+ bp_delete_user_meta( $user_id, 'bp_new_mentions' );
 
 
 
 
 
 
 
 
 
101
  }
102
 
103
  /**
108
  *
109
  * Currently, only used in {@link bp_activity_delete()}.
110
  *
111
+ * @since BuddyPress (1.5)
112
  *
113
+ * @uses bp_activity_find_mentions()
114
+ * @uses bp_activity_update_mention_count_for_user()
115
+ *
116
+ * @param int $activity_id The unique id for the activity item.
117
+ * @param string $action Can be 'delete' or 'add'. Defaults to 'add'.
118
  */
119
  function bp_activity_adjust_mention_count( $activity_id = 0, $action = 'add' ) {
120
+ if ( empty( $activity_id ) )
 
 
121
  return false;
 
122
 
123
+ // Get activity object
124
+ $activity = new BP_Activity_Activity( (int) $activity_id );
125
 
126
+ // Try to find mentions
127
  $usernames = bp_activity_find_mentions( strip_tags( $activity->content ) );
128
 
129
+ // Still empty? Stop now
130
+ if ( empty( $usernames ) )
131
  return false;
 
132
 
133
+ // Increment mention count foreach mentioned user
134
+ foreach( (array) $usernames as $user_id => $username ) {
135
  bp_activity_update_mention_count_for_user( $user_id, $activity_id, $action );
136
  }
137
  }
142
  * This function should be used when you've already parsed your activity item
143
  * for @mentions.
144
  *
145
+ * @since BuddyPress (1.7)
146
  *
147
+ * @uses bp_get_user_meta()
148
+ * @uses bp_update_user_meta()
149
+ *
150
+ * @param int $user_id The user ID.
151
+ * @param int $activity_id The unique ID for the activity item.
152
+ * @param string $action 'delete' or 'add'. Default: 'add'.
153
  * @return bool
154
  */
155
  function bp_activity_update_mention_count_for_user( $user_id, $activity_id, $action = 'add' ) {
156
+ if ( empty( $user_id ) || empty( $activity_id ) )
 
157
  return false;
 
158
 
159
+ // Adjust the mention list and count for the member
160
  $new_mention_count = (int) bp_get_user_meta( $user_id, 'bp_new_mention_count', true );
161
+ if ( !$new_mentions = bp_get_user_meta( $user_id, 'bp_new_mentions', true ) )
 
 
 
162
  $new_mentions = array();
 
163
 
164
  switch ( $action ) {
165
  case 'delete' :
180
  break;
181
  }
182
 
183
+ // Get an updated mention count
184
  $new_mention_count = count( $new_mentions );
185
 
186
+ // Resave the user_meta
187
  bp_update_user_meta( $user_id, 'bp_new_mention_count', $new_mention_count );
188
  bp_update_user_meta( $user_id, 'bp_new_mentions', $new_mentions );
189
 
193
  /**
194
  * Determine a user's "mentionname", the name used for that user in @-mentions.
195
  *
196
+ * @since BuddyPress (1.9.0)
197
  *
198
+ * @return string User name appropriate for @-mentions.
 
199
  */
200
  function bp_activity_get_user_mentionname( $user_id ) {
201
  $mentionname = '';
216
  /**
217
  * Get a user ID from a "mentionname", the name used for a user in @-mentions.
218
  *
219
+ * @since BuddyPress (1.9.0)
220
  *
 
221
  * @return int|bool ID of the user, if one is found. Otherwise false.
222
  */
223
  function bp_activity_get_userid_from_mentionname( $mentionname ) {
224
  $user_id = false;
225
 
226
+ // In username compatibility mode, hyphens are ambiguous between
227
+ // actual hyphens and converted spaces.
228
+ //
229
+ // @todo There is the potential for username clashes between 'foo bar'
230
+ // and 'foo-bar' in compatibility mode. Come up with a system for
231
+ // unique mentionnames.
 
 
232
  if ( bp_is_username_compatibility_mode() ) {
233
+ // First, try the raw username
234
  $userdata = get_user_by( 'login', $mentionname );
235
 
236
  // Doing a direct query to use proper regex. Necessary to
244
  }
245
 
246
  // When username compatibility mode is disabled, the mentionname is
247
+ // the same as the nicename
248
  } else {
249
  $user_id = bp_core_get_userid_from_nicename( $mentionname );
250
  }
269
  * panel, and dynamic action generation (which is essential for multilingual
270
  * sites, etc) will not work.
271
  *
272
+ * @since BuddyPress (1.1.0)
273
  *
274
+ * @param string $component_id The unique string ID of the component.
275
+ * @param string $type The action type.
276
+ * @param string $description The action description.
277
+ * @param callable $format_callback Callback for formatting the action string.
 
 
 
 
278
  * @return bool False if any param is empty, otherwise true.
279
  */
280
+ function bp_activity_set_action( $component_id, $type, $description, $format_callback = false ) {
281
  $bp = buddypress();
282
 
283
+ // Return false if any of the above values are not set
284
  if ( empty( $component_id ) || empty( $type ) || empty( $description ) ) {
285
  return false;
286
  }
287
 
288
+ // Set activity action
289
  if ( ! isset( $bp->activity->actions ) || ! is_object( $bp->activity->actions ) ) {
290
  $bp->activity->actions = new stdClass;
291
  }
292
 
293
+ // Verify callback
294
  if ( ! is_callable( $format_callback ) ) {
295
  $format_callback = '';
296
  }
299
  $bp->activity->actions->{$component_id} = new stdClass;
300
  }
301
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  $bp->activity->actions->{$component_id}->{$type} = apply_filters( 'bp_activity_set_action', array(
303
  'key' => $type,
304
  'value' => $description,
305
  'format_callback' => $format_callback,
306
+ ), $component_id, $type, $description, $format_callback );
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
  return true;
309
  }
310
 
311
  /**
312
+ * Retreive the current action from a component and key.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  *
314
+ * @since BuddyPress (1.1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  *
316
+ * @global object $bp BuddyPress global settings.
317
+ * @uses apply_filters() To call the 'bp_activity_get_action' hook.
318
  *
319
  * @param string $component_id The unique string ID of the component.
320
+ * @param string $key The action key.
321
  * @return string|bool Action value if found, otherwise false.
322
  */
323
  function bp_activity_get_action( $component_id, $key ) {
324
+ global $bp;
325
 
326
+ // Return false if any of the above values are not set
327
+ if ( empty( $component_id ) || empty( $key ) )
328
  return false;
 
329
 
330
+ return apply_filters( 'bp_activity_get_action', $bp->activity->actions->{$component_id}->{$key}, $component_id, $key );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  }
332
 
333
  /**
334
  * Fetch details of all registered activity types.
335
  *
336
+ * @since BuddyPress (1.7)
337
  *
338
  * @return array array( type => description ), ...
339
  */
341
  $actions = array();
342
 
343
  // Walk through the registered actions, and build an array of actions/values.
344
+ foreach ( buddypress()->activity->actions as $action ) {
345
  $action = array_values( (array) $action );
346
 
347
+ for ( $i = 0, $i_count = count( $action ); $i < $i_count; $i++ )
348
  $actions[ $action[$i]['key'] ] = $action[$i]['value'];
 
349
  }
350
 
351
+ // This was a mis-named activity type from before BP 1.6
352
  unset( $actions['friends_register_activity_action'] );
353
 
 
 
 
 
 
 
 
354
  return apply_filters( 'bp_activity_get_types', $actions );
355
  }
356
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  /** Favorites ****************************************************************/
358
 
359
  /**
360
  * Get a users favorite activity stream items.
361
  *
362
+ * @since BuddyPress (1.2)
363
+ *
364
+ * @uses bp_get_user_meta()
365
+ * @uses apply_filters() To call the 'bp_activity_get_user_favorites' hook.
366
  *
367
  * @param int $user_id ID of the user whose favorites are being queried.
368
  * @return array IDs of the user's favorite activity items.
369
  */
370
  function bp_activity_get_user_favorites( $user_id = 0 ) {
371
 
372
+ // Fallback to logged in user if no user_id is passed
373
+ if ( empty( $user_id ) )
374
  $user_id = bp_displayed_user_id();
 
375
 
376
+ // Get favorites for user
377
  $favs = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
378
 
 
 
 
 
 
 
 
379
  return apply_filters( 'bp_activity_get_user_favorites', $favs );
380
  }
381
 
382
  /**
383
  * Add an activity stream item as a favorite for a user.
384
  *
385
+ * @since BuddyPress (1.2)
386
+ *
387
+ * @uses is_user_logged_in()
388
+ * @uses bp_get_user_meta()
389
+ * @uses bp_activity_get_meta()
390
+ * @uses bp_update_user_meta()
391
+ * @uses bp_activity_update_meta()
392
+ * @uses do_action() To call the 'bp_activity_add_user_favorite' hook.
393
+ * @uses do_action() To call the 'bp_activity_add_user_favorite_fail' hook.
394
  *
395
  * @param int $activity_id ID of the activity item being favorited.
396
+ * @param int $user_id ID of the user favoriting the activity item.
397
  * @return bool True on success, false on failure.
398
  */
399
  function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
400
 
401
+ // Favorite activity stream items are for logged in users only
402
+ if ( !is_user_logged_in() )
403
  return false;
 
404
 
405
+ // Fallback to logged in user if no user_id is passed
406
+ if ( empty( $user_id ) )
407
  $user_id = bp_loggedin_user_id();
 
408
 
409
  $my_favs = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
410
  if ( empty( $my_favs ) || ! is_array( $my_favs ) ) {
411
  $my_favs = array();
412
  }
413
 
414
+ // Bail if the user has already favorited this activity item
415
  if ( in_array( $activity_id, $my_favs ) ) {
416
  return false;
417
  }
418
 
419
+ // Add to user's favorites
420
  $my_favs[] = $activity_id;
421
 
422
+ // Update the total number of users who have favorited this activity
423
  $fav_count = bp_activity_get_meta( $activity_id, 'favorite_count' );
424
  $fav_count = !empty( $fav_count ) ? (int) $fav_count + 1 : 1;
425
 
426
+ // Update user meta
427
  bp_update_user_meta( $user_id, 'bp_favorite_activities', $my_favs );
428
 
429
+ // Update activity meta counts
430
  if ( bp_activity_update_meta( $activity_id, 'favorite_count', $fav_count ) ) {
431
 
432
+ // Execute additional code
 
 
 
 
 
 
 
433
  do_action( 'bp_activity_add_user_favorite', $activity_id, $user_id );
434
 
435
+ // Success
436
  return true;
437
 
438
+ // Saving meta was unsuccessful for an unknown reason
439
  } else {
440
+ // Execute additional code
 
 
 
 
 
 
 
 
441
  do_action( 'bp_activity_add_user_favorite_fail', $activity_id, $user_id );
442
 
443
  return false;
447
  /**
448
  * Remove an activity stream item as a favorite for a user.
449
  *
450
+ * @since BuddyPress (1.2)
451
+ *
452
+ * @uses is_user_logged_in()
453
+ * @uses bp_get_user_meta()
454
+ * @uses bp_activity_get_meta()
455
+ * @uses bp_activity_update_meta()
456
+ * @uses bp_update_user_meta()
457
+ * @uses do_action() To call the 'bp_activity_remove_user_favorite' hook.
458
  *
459
  * @param int $activity_id ID of the activity item being unfavorited.
460
+ * @param int $user_id ID of the user unfavoriting the activity item.
461
  * @return bool True on success, false on failure.
462
  */
463
  function bp_activity_remove_user_favorite( $activity_id, $user_id = 0 ) {
464
 
465
+ // Favorite activity stream items are for logged in users only
466
+ if ( !is_user_logged_in() )
467
  return false;
 
468
 
469
+ // Fallback to logged in user if no user_id is passed
470
+ if ( empty( $user_id ) )
471
  $user_id = bp_loggedin_user_id();
 
472
 
473
  $my_favs = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
474
  $my_favs = array_flip( (array) $my_favs );
475
 
476
+ // Bail if the user has not previously favorited the item
477
  if ( ! isset( $my_favs[ $activity_id ] ) ) {
478
  return false;
479
  }
480
 
481
+ // Remove the fav from the user's favs
482
  unset( $my_favs[$activity_id] );
483
  $my_favs = array_unique( array_flip( $my_favs ) );
484
 
485
+ // Update the total number of users who have favorited this activity
486
+ if ( $fav_count = bp_activity_get_meta( $activity_id, 'favorite_count' ) ) {
 
487
 
488
+ // Deduct from total favorites
489
  if ( bp_activity_update_meta( $activity_id, 'favorite_count', (int) $fav_count - 1 ) ) {
490
 
491
+ // Update users favorites
492
  if ( bp_update_user_meta( $user_id, 'bp_favorite_activities', $my_favs ) ) {
493
 
494
+ // Execute additional code
 
 
 
 
 
 
 
495
  do_action( 'bp_activity_remove_user_favorite', $activity_id, $user_id );
496
 
497
+ // Success
498
  return true;
499
 
500
+ // Error updating
501
  } else {
502
  return false;
503
  }
504
 
505
+ // Error updating favorite count
506
  } else {
507
  return false;
508
  }
509
 
510
+ // Error getting favorite count
511
  } else {
512
  return false;
513
  }
516
  /**
517
  * Check whether an activity item exists with a given content string.
518
  *
519
+ * @since BuddyPress (1.1)
520
+ *
521
+ * @uses BP_Activity_Activity::check_exists_by_content() {@link BP_Activity_Activity}
522
+ * @uses apply_filters() To call the 'bp_activity_check_exists_by_content' hook.
523
  *
524
  * @param string $content The content to filter by.
525
  * @return int|null The ID of the located activity item. Null if none is found.
526
  */
527
  function bp_activity_check_exists_by_content( $content ) {
 
 
 
 
 
 
 
 
528
  return apply_filters( 'bp_activity_check_exists_by_content', BP_Activity_Activity::check_exists_by_content( $content ) );
529
  }
530
 
531
  /**
532
  * Retrieve the last time activity was updated.
533
  *
534
+ * @since BuddyPress (1.0)
535
+ *
536
+ * @uses BP_Activity_Activity::get_last_updated() {@link BP_Activity_Activity}
537
+ * @uses apply_filters() To call the 'bp_activity_get_last_updated' hook.
538
  *
539
  * @return string Date last updated.
540
  */
541
  function bp_activity_get_last_updated() {
 
 
 
 
 
 
 
 
542
  return apply_filters( 'bp_activity_get_last_updated', BP_Activity_Activity::get_last_updated() );
543
  }
544
 
545
  /**
546
  * Retrieve the number of favorite activity stream items a user has.
547
  *
548
+ * @since BuddyPress (1.2)
549
+ *
550
+ * @uses BP_Activity_Activity::total_favorite_count() {@link BP_Activity_Activity}
551
  *
552
  * @param int $user_id ID of the user whose favorite count is being requested.
553
  * @return int Total favorite count for the user.
554
  */
555
  function bp_activity_total_favorites_for_user( $user_id = 0 ) {
556
 
557
+ // Fallback on displayed user, and then logged in user
558
+ if ( empty( $user_id ) )
559
  $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
 
560
 
561
  return BP_Activity_Activity::total_favorite_count( $user_id );
562
  }
566
  /**
567
  * Delete a meta entry from the DB for an activity stream item.
568
  *
569
+ * @since BuddyPress (1.2.0)
570
  *
571
  * @global object $wpdb WordPress database access object.
572
+ * @global object $bp BuddyPress global settings.
573
+ *
574
+ * @param int $activity_id ID of the activity item whose metadata is being deleted.
575
+ * @param string $meta_key Optional. The key of the metadata being deleted. If
576
+ * omitted, all metadata associated with the activity
577
+ * item will be deleted.
578
+ * @param string $meta_value Optional. If present, the metadata will only be
579
+ * deleted if the meta_value matches this parameter.
580
+ * @param bool $delete_all Optional. If true, delete matching metadata entries
581
+ * for all objects, ignoring the specified object_id. Otherwise,
582
+ * only delete matching metadata entries for the specified
583
+ * activity item. Default: false.
584
  * @return bool True on success, false on failure.
585
  */
586
  function bp_activity_delete_meta( $activity_id, $meta_key = '', $meta_value = '', $delete_all = false ) {
587
+ global $wpdb, $bp;
588
 
589
+ // Legacy - if no meta_key is passed, delete all for the item
590
  if ( empty( $meta_key ) ) {
591
  $all_meta = bp_activity_get_meta( $activity_id );
592
  $keys = ! empty( $all_meta ) ? array_keys( $all_meta ) : array();
593
 
594
+ // With no meta_key, ignore $delete_all
595
  $delete_all = false;
596
  } else {
597
  $keys = array( $meta_key );
611
  /**
612
  * Get metadata for a given activity item.
613
  *
614
+ * @since BuddyPress (1.2)
615
  *
616
+ * @uses apply_filters() To call the 'bp_activity_get_meta' hook.
617
+ *
618
+ * @param int $activity_id ID of the activity item whose metadata is being requested.
619
+ * @param string $meta_key Optional. If present, only the metadata matching
620
+ * that meta key will be returned. Otherwise, all metadata for the
621
+ * activity item will be fetched.
622
+ * @param bool $single Optional. If true, return only the first value of the
623
+ * specified meta_key. This parameter has no effect if meta_key is not
624
+ * specified. Default: true.
625
  * @return mixed The meta value(s) being requested.
626
  */
627
  function bp_activity_get_meta( $activity_id = 0, $meta_key = '', $single = true ) {
629
  $retval = get_metadata( 'activity', $activity_id, $meta_key, $single );
630
  remove_filter( 'query', 'bp_filter_metaid_column_name' );
631
 
632
+ // Filter result before returning
 
 
 
 
 
 
 
 
 
633
  return apply_filters( 'bp_activity_get_meta', $retval, $activity_id, $meta_key, $single );
634
  }
635
 
636
  /**
637
  * Update a piece of activity meta.
638
  *
639
+ * @since BuddyPress (1.2)
640
  *
641
+ * @param int $activity_id ID of the activity item whose metadata is being
642
+ * updated.
643
+ * @param string $meta_key Key of the metadata being updated.
644
+ * @param mixed $meta_value Value to be set.
645
+ * @param mixed $prev_value Optional. If specified, only update existing
646
+ * metadata entries with the specified value. Otherwise, update all
647
+ * entries.
648
  * @return bool|int Returns false on failure. On successful update of existing
649
+ * metadata, returns true. On successful creation of new metadata,
650
+ * returns the integer ID of the new metadata row.
651
  */
652
  function bp_activity_update_meta( $activity_id, $meta_key, $meta_value, $prev_value = '' ) {
653
  add_filter( 'query', 'bp_filter_metaid_column_name' );
660
  /**
661
  * Add a piece of activity metadata.
662
  *
663
+ * @since BuddyPress (2.0.0)
664
  *
665
+ * @param int $activity_id ID of the activity item.
666
+ * @param string $meta_key Metadata key.
667
+ * @param mixed $meta_value Metadata value.
668
+ * @param bool $unique. Optional. Whether to enforce a single metadata value
669
+ * for the given key. If true, and the object already has a value for
670
+ * the key, no change will be made. Default: false.
671
  * @return int|bool The meta ID on successful update, false on failure.
672
  */
673
  function bp_activity_add_meta( $activity_id, $meta_key, $meta_value, $unique = false ) {
683
  /**
684
  * Completely remove a user's activity data.
685
  *
686
+ * @since BuddyPress (1.5)
687
+ *
688
+ * @uses is_user_logged_in()
689
+ * @uses bp_activity_delete()
690
+ * @uses bp_delete_user_meta()
691
+ * @uses do_action() To call the 'bp_activity_remove_data' hook.
692
+ * @uses do_action() To call the 'bp_activity_remove_all_user_data' hook.
693
  *
694
  * @param int $user_id ID of the user whose activity is being deleted.
 
695
  */
696
  function bp_activity_remove_all_user_data( $user_id = 0 ) {
697
 
698
+ // Do not delete user data unless a logged in user says so
699
+ if ( empty( $user_id ) || !is_user_logged_in() )
700
  return false;
 
701
 
702
+ // Clear the user's activity from the sitewide stream and clear their activity tables
703
  bp_activity_delete( array( 'user_id' => $user_id ) );
704
 
705
+ // Remove any usermeta
706
+ bp_delete_user_meta( $user_id, 'bp_latest_update' );
707
  bp_delete_user_meta( $user_id, 'bp_favorite_activities' );
708
 
709
  // Execute additional code
710
  do_action( 'bp_activity_remove_data', $user_id ); // Deprecated! Do not use!
711
 
712
+ // Use this going forward
 
 
 
 
 
 
713
  do_action( 'bp_activity_remove_all_user_data', $user_id );
714
  }
715
  add_action( 'wpmu_delete_user', 'bp_activity_remove_all_user_data' );
718
  /**
719
  * Mark all of the user's activity as spam.
720
  *
721
+ * @since BuddyPress (1.6)
722
  *
723
  * @global object $wpdb WordPress database access object.
724
+ * @global object $bp BuddyPress global settings.
725
  *
726
  * @param int $user_id ID of the user whose activity is being spammed.
 
727
  */
728
  function bp_activity_spam_all_user_data( $user_id = 0 ) {
729
+ global $bp, $wpdb;
730
 
731
+ // Do not delete user data unless a logged in user says so
732
+ if ( empty( $user_id ) || ! is_user_logged_in() )
733
  return false;
 
734
 
735
  // Get all the user's activities.
736
+ $activities = bp_activity_get( array( 'display_comments' => 'stream', 'filter' => array( 'user_id' => $user_id ), 'show_hidden' => true, ) );
 
 
 
 
737
 
738
+ // Mark each as spam
 
 
739
  foreach ( (array) $activities['activities'] as $activity ) {
740
 
741
+ // Create an activity object
742
  $activity_obj = new BP_Activity_Activity;
743
+ foreach ( $activity as $k => $v )
744
  $activity_obj->$k = $v;
 
745
 
746
+ // Mark as spam
747
  bp_activity_mark_as_spam( $activity_obj );
748
 
749
  /*
750
  * If Akismet is present, update the activity history meta.
751
  *
752
  * This is usually taken care of when BP_Activity_Activity::save() happens, but
753
+ * as we're going to be updating all the activity statuses directly, for efficency,
754
  * we need to update manually.
755
  */
756
+ if ( ! empty( $bp->activity->akismet ) )
757
  $bp->activity->akismet->update_activity_spam_meta( $activity_obj );
 
758
 
759
+ // Tidy up
760
  unset( $activity_obj );
761
  }
762
 
763
+ // Mark all of this user's activities as spam
764
  $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET is_spam = 1 WHERE user_id = %d", $user_id ) );
765
 
766
+ // Call an action for plugins to use
 
 
 
 
 
 
 
767
  do_action( 'bp_activity_spam_all_user_data', $user_id, $activities['activities'] );
768
  }
769
  add_action( 'bp_make_spam_user', 'bp_activity_spam_all_user_data' );
771
  /**
772
  * Mark all of the user's activity as ham (not spam).
773
  *
774
+ * @since BuddyPress (1.6)
775
  *
776
  * @global object $wpdb WordPress database access object.
777
+ * @global object $bp BuddyPress global settings.
778
  *
779
  * @param int $user_id ID of the user whose activity is being hammed.
 
780
  */
781
  function bp_activity_ham_all_user_data( $user_id = 0 ) {
782
+ global $bp, $wpdb;
783
 
784
+ // Do not delete user data unless a logged in user says so
785
+ if ( empty( $user_id ) || ! is_user_logged_in() )
786
  return false;
 
787
 
788
  // Get all the user's activities.
789
+ $activities = bp_activity_get( array( 'display_comments' => 'stream', 'filter' => array( 'user_id' => $user_id ), 'show_hidden' => true, 'spam' => 'all', ) );
 
 
 
 
 
790
 
791
+ // Mark each as not spam
 
 
792
  foreach ( (array) $activities['activities'] as $activity ) {
793
 
794
+ // Create an activity object
795
  $activity_obj = new BP_Activity_Activity;
796
+ foreach ( $activity as $k => $v )
797
  $activity_obj->$k = $v;
 
798
 
799
+ // Mark as not spam
800
  bp_activity_mark_as_ham( $activity_obj );
801
 
802
  /*
803
  * If Akismet is present, update the activity history meta.
804
  *
805
  * This is usually taken care of when BP_Activity_Activity::save() happens, but
806
+ * as we're going to be updating all the activity statuses directly, for efficency,
807
  * we need to update manually.
808
  */
809
+ if ( ! empty( $bp->activity->akismet ) )
810
  $bp->activity->akismet->update_activity_ham_meta( $activity_obj );
 
811
 
812
+ // Tidy up
813
  unset( $activity_obj );
814
  }
815
 
816
+ // Mark all of this user's activities as spam
817
  $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET is_spam = 0 WHERE user_id = %d", $user_id ) );
818
 
819
+ // Call an action for plugins to use
 
 
 
 
 
 
 
820
  do_action( 'bp_activity_ham_all_user_data', $user_id, $activities['activities'] );
821
  }
822
  add_action( 'bp_make_ham_user', 'bp_activity_ham_all_user_data' );
823
 
824
  /**
825
+ * Register the activity stream actions for updates
826
+ *
827
+ * @since BuddyPress (1.6)
828
  *
829
+ * @global object $bp BuddyPress global settings.
830
  */
831
  function bp_activity_register_activity_actions() {
832
+ global $bp;
833
 
834
  bp_activity_set_action(
835
  $bp->activity->id,
836
  'activity_update',
837
  __( 'Posted a status update', 'buddypress' ),
838
+ 'bp_activity_format_activity_action_activity_update'
 
 
839
  );
840
 
841
  bp_activity_set_action(
842
  $bp->activity->id,
843
  'activity_comment',
844
  __( 'Replied to a status update', 'buddypress' ),
845
+ 'bp_activity_format_activity_action_activity_comment'
 
846
  );
847
 
 
 
 
 
 
 
 
848
  do_action( 'bp_activity_register_activity_actions' );
849
 
850
  // Backpat. Don't use this.
855
  /**
856
  * Generate an activity action string for an activity item.
857
  *
 
 
858
  * @param object $activity Activity data object.
859
  * @return string|bool Returns false if no callback is found, otherwise returns
860
+ * the formatted action string.
861
  */
862
  function bp_activity_generate_action_string( $activity ) {
863
+ // Check for valid input
 
864
  if ( empty( $activity->component ) || empty( $activity->type ) ) {
865
  return false;
866
  }
867
 
868
+ // Check for registered format callback
869
+ if ( empty( buddypress()->activity->actions->{$activity->component}->{$activity->type}['format_callback'] ) ) {
 
870
  return false;
871
  }
872
 
873
+ // We apply the format_callback as a filter
874
+ add_filter( 'bp_activity_generate_action_string', buddypress()->activity->actions->{$activity->component}->{$activity->type}['format_callback'], 10, 2 );
875
 
876
+ // Generate the action string (run through the filter defined above)
 
 
 
 
 
 
 
877
  $action = apply_filters( 'bp_activity_generate_action_string', $activity->action, $activity );
878
 
879
+ // Remove the filter for future activity items
880
+ remove_filter( 'bp_activity_generate_action_string', buddypress()->activity->actions->{$activity->component}->{$activity->type}['format_callback'], 10, 2 );
881
 
882
  return $action;
883
  }
885
  /**
886
  * Format 'activity_update' activity actions.
887
  *
888
+ * @since BuddyPress (2.0.0)
889
  *
890
+ * @param string $action Static activity action.
891
  * @param object $activity Activity data object.
892
+ * @return string
893
  */
894
  function bp_activity_format_activity_action_activity_update( $action, $activity ) {
895
  $action = sprintf( __( '%s posted an update', 'buddypress' ), bp_core_get_userlink( $activity->user_id ) );
 
 
 
 
 
 
 
 
 
896
  return apply_filters( 'bp_activity_new_update_action', $action, $activity );
897
  }
898
 
899
  /**
900
  * Format 'activity_comment' activity actions.
901
  *
902
+ * @since BuddyPress (2.0.0)
903
  *
904
+ * @param string $action Static activity action.
905
  * @param object $activity Activity data object.
906
+ * @return string
907
  */
908
  function bp_activity_format_activity_action_activity_comment( $action, $activity ) {
909
  $action = sprintf( __( '%s posted a new activity comment', 'buddypress' ), bp_core_get_userlink( $activity->user_id ) );
 
 
 
 
 
 
 
 
 
910
  return apply_filters( 'bp_activity_comment_action', $action, $activity );
911
  }
912
 
913
+ /******************************************************************************
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
  * Business functions are where all the magic happens in BuddyPress. They will
915
  * handle the actual saving or manipulation of information. Usually they will
916
  * hand off to a database class for data access, then return
920
  /**
921
  * Retrieve an activity or activities.
922
  *
923
+ * bp_activity_get() shares all arguments with BP_Activity_Activity::get(). The
924
+ * following is a list of bp_activity_get() parameters that have different
925
  * default values from BP_Activity_Activity::get() (value in parentheses is
926
  * the default for the bp_activity_get()).
927
  * - 'per_page' (false)
928
  *
929
+ * @since BuddyPress (1.2)
 
930
  *
931
  * @see BP_Activity_Activity::get() For more information on accepted arguments
932
  * and the format of the returned value.
933
+ * @uses wp_parse_args()
934
+ * @uses wp_cache_get()
935
+ * @uses wp_cache_set()
936
+ * @uses BP_Activity_Activity::get() {@link BP_Activity_Activity}
937
+ * @uses apply_filters_ref_array() To call the 'bp_activity_get' hook.
938
  *
939
+ * @param array $args See BP_Activity_Activity::get() for description.
940
  * @return array $activity See BP_Activity_Activity::get() for description.
941
  */
942
  function bp_activity_get( $args = '' ) {
943
+ $defaults = array(
944
+ 'max' => false, // Maximum number of results to return
945
+ 'page' => 1, // page 1 without a per_page will result in no pagination.
 
 
946
  'per_page' => false, // results per page
947
  'sort' => 'DESC', // sort ASC or DESC
948
+ 'display_comments' => false, // false for no comments. 'stream' for within stream display, 'threaded' for below each activity item
949
 
950
  'search_terms' => false, // Pass search terms as a string
951
  'meta_query' => false, // Filter by activity meta. See WP_Meta_Query for format
 
 
952
  'show_hidden' => false, // Show activity items that are hidden site-wide?
953
+ 'exclude' => false, // Comma-separated list of activity IDs to exclude
954
+ 'in' => false, // Comma-separated list or array of activity IDs to which you want to limit the query
 
955
  'spam' => 'ham_only', // 'ham_only' (default), 'spam_only' or 'all'.
956
  'update_meta_cache' => true,
 
 
957
 
958
  /**
959
  * Pass filters as an array -- all filter items can be multiple values comma separated:
960
  * array(
961
+ * 'user_id' => false, // user_id to filter on
962
+ * 'object' => false, // object to filter on e.g. groups, profile, status, friends
963
+ * 'action' => false, // action to filter on e.g. activity_update, profile_updated
964
+ * 'primary_id' => false, // object ID to filter on e.g. a group_id or forum_id or blog_id etc.
965
+ * 'secondary_id' => false, // secondary object ID to filter on e.g. a post_id
966
  * );
967
  */
968
  'filter' => array()
969
+ );
970
+ $r = wp_parse_args( $args, $defaults );
971
+ extract( $r, EXTR_SKIP );
972
+
973
+ // Attempt to return a cached copy of the first page of sitewide activity.
974
+ if ( 1 == (int) $page && empty( $max ) && empty( $search_terms ) && empty( $meta_query ) && empty( $filter ) && empty( $exclude ) && empty( $in ) && 'DESC' == $sort && empty( $exclude ) && 'ham_only' == $spam ) {
975
+ if ( !$activity = wp_cache_get( 'bp_activity_sitewide_front', 'bp' ) ) {
976
+ $args = array(
977
+ 'page' => $page,
978
+ 'per_page' => $per_page,
979
+ 'max' => $max,
980
+ 'sort' => $sort,
981
+ 'search_terms' => $search_terms,
982
+ 'meta_query' => $meta_query,
983
+ 'filter' => $filter,
984
+ 'display_comments' => $display_comments,
985
+ 'show_hidden' => $show_hidden,
986
+ 'spam' => $spam,
987
+ 'update_meta_cache' => $update_meta_cache,
988
+ );
989
+ $activity = BP_Activity_Activity::get( $args );
990
+ wp_cache_set( 'bp_activity_sitewide_front', $activity, 'bp' );
991
+ }
992
+
993
+ } else {
994
+ $args = array(
995
+ 'page' => $page,
996
+ 'per_page' => $per_page,
997
+ 'max' => $max,
998
+ 'sort' => $sort,
999
+ 'search_terms' => $search_terms,
1000
+ 'meta_query' => $meta_query,
1001
+ 'filter' => $filter,
1002
+ 'display_comments' => $display_comments,
1003
+ 'show_hidden' => $show_hidden,
1004
+ 'exclude' => $exclude,
1005
+ 'in' => $in,
1006
+ 'spam' => $spam
1007
+ );
1008
+ $activity = BP_Activity_Activity::get( $args );
1009
+ }
1010
 
 
 
 
 
 
 
 
 
1011
  return apply_filters_ref_array( 'bp_activity_get', array( &$activity, &$r ) );
1012
  }
1013
 
1014
  /**
1015
  * Fetch specific activity items.
1016
  *
1017
+ * @since BuddyPress (1.2)
1018
  *
1019
+ * @see BP_Activity_Activity::get() For more information on accepted arguments
1020
+ * @uses wp_parse_args()
1021
+ * @uses apply_filters() To call the 'bp_activity_get_specific' hook
1022
+ * @uses BP_Activity_Activity::get() {@link BP_Activity_Activity}
1023
  *
1024
+ * @param array $args {
1025
  * All arguments and defaults are shared with BP_Activity_Activity::get(),
1026
  * except for the following:
1027
  * @type string|int|array Single activity ID, comma-separated list of IDs,
1028
+ * or array of IDs.
1029
  * }
1030
  * @return array $activity See BP_Activity_Activity::get() for description.
1031
  */
1032
  function bp_activity_get_specific( $args = '' ) {
1033
+ $defaults = array(
1034
+ 'activity_ids' => false, // A single activity_id or array of IDs.
1035
+ 'display_comments' => false, // true or false to display threaded comments for these specific activity items
1036
+ 'max' => false, // Maximum number of results to return
1037
+ 'page' => 1, // page 1 without a per_page will result in no pagination.
1038
+ 'per_page' => false, // results per page
1039
+ 'show_hidden' => true, // When fetching specific items, show all
1040
+ 'sort' => 'DESC', // sort ASC or DESC
1041
+ 'spam' => 'ham_only', // Retrieve items marked as spam
 
1042
  'update_meta_cache' => true,
1043
+ );
1044
+ $r = wp_parse_args( $args, $defaults );
1045
+ extract( $r, EXTR_SKIP );
1046
 
1047
  $get_args = array(
1048
+ 'page' => $page,
1049
+ 'per_page' => $per_page,
1050
+ 'max' => $max,
1051
+ 'sort' => $sort,
1052
+ 'display_comments' => $display_comments,
1053
+ 'show_hidden' => $show_hidden,
1054
+ 'in' => $activity_ids,
1055
+ 'spam' => $spam,
1056
+ 'update_meta_cache' => $update_meta_cache,
1057
  );
 
 
 
 
 
 
 
 
 
 
1058
  return apply_filters( 'bp_activity_get_specific', BP_Activity_Activity::get( $get_args ), $args, $get_args );
1059
  }
1060
 
1061
  /**
1062
  * Add an activity item.
1063
  *
1064
+ * @since BuddyPress (1.1)
1065
+ *
1066
+ * @uses wp_parse_args()
1067
+ * @uses BP_Activity_Activity::save() {@link BP_Activity_Activity}
1068
+ * @uses BP_Activity_Activity::rebuild_activity_comment_tree() {@link BP_Activity_Activity}
1069
+ * @uses wp_cache_delete()
1070
+ * @uses do_action() To call the 'bp_activity_add' hook
1071
  *
1072
+ * @param array $args {
1073
  * An array of arguments.
1074
+ * @type int|bool $id Pass an activity ID to update an existing item, or
1075
+ * false to create a new item. Default: false.
1076
+ * @type string $action Optional. The activity action/description, typically
1077
+ * something like "Joe posted an update". Values passed to this param
1078
+ * will be stored in the database and used as a fallback for when the
1079
+ * activity item's format_callback cannot be found (eg, when the
1080
+ * component is disabled). As long as you have registered a
1081
+ * format_callback for your $type, it is unnecessary to include this
1082
+ * argument - BP will generate it automatically.
1083
+ * See {@link bp_activity_set_action()}.
1084
+ * @type string $content Optional. The content of the activity item.
1085
+ * @type string $component The unique name of the component associated with
1086
+ * the activity item - 'groups', 'profile', etc.
1087
+ * @type string $type The specific activity type, used for directory
1088
+ * filtering. 'new_blog_post', 'activity_update', etc.
1089
+ * @type string $primary_link Optional. The URL for this item, as used in
1090
+ * RSS feeds. Defaults to the URL for this activity item's permalink page.
1091
+ * @type int|bool $user_id Optional. The ID of the user associated with the
1092
+ * activity item. May be set to false or 0 if the item is not related
1093
+ * to any user. Default: the ID of the currently logged-in user.
1094
+ * @type int $item_id Optional. The ID of the associated item.
1095
+ * @type int $secondary_item_id Optional. The ID of a secondary associated
1096
+ * item.
1097
+ * @type string $date_recorded Optional. The GMT time, in Y-m-d h:i:s format,
1098
+ * when the item was recorded. Defaults to the current time.
1099
+ * @type bool $hide_sitewide Should the item be hidden on sitewide streams?
1100
+ * Default: false.
1101
+ * @type bool $is_spam Should the item be marked as spam? Default: false.
 
1102
  * }
1103
  * @return int|bool The ID of the activity on success. False on error.
1104
  */
1105
  function bp_activity_add( $args = '' ) {
1106
 
1107
+ $defaults = array(
1108
+ 'id' => false, // Pass an existing activity ID to update an existing entry.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1109
 
1110
+ 'action' => '', // The activity action - e.g. "Jon Doe posted an update"
1111
+ 'content' => '', // Optional: The content of the activity item e.g. "BuddyPress is awesome guys!"
 
1112
 
1113
+ 'component' => false, // The name/ID of the component e.g. groups, profile, mycomponent
1114
+ 'type' => false, // The activity type e.g. activity_update, profile_updated
1115
+ 'primary_link' => '', // Optional: The primary URL for this item in RSS feeds (defaults to activity permalink)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1116
 
1117
+ 'user_id' => bp_loggedin_user_id(), // Optional: The user to record the activity for, can be false if this activity is not for a user.
1118
+ 'item_id' => false, // Optional: The ID of the specific item being recorded, e.g. a blog_id
1119
+ 'secondary_item_id' => false, // Optional: A second ID used to further filter e.g. a comment_id
1120
+ 'recorded_time' => bp_core_current_time(), // The GMT time that this activity was recorded
1121
+ 'hide_sitewide' => false, // Should this be hidden on the sitewide activity stream?
1122
+ 'is_spam' => false, // Is this activity item to be marked as spam?
1123
+ );
1124
+ $params = wp_parse_args( $args, $defaults );
1125
+ extract( $params, EXTR_SKIP );
1126
+
1127
+ // Make sure we are backwards compatible
1128
+ if ( empty( $component ) && !empty( $component_name ) )
1129
+ $component = $component_name;
1130
+
1131
+ if ( empty( $type ) && !empty( $component_action ) )
1132
+ $type = $component_action;
1133
+
1134
+ // Setup activity to be added
1135
+ $activity = new BP_Activity_Activity( $id );
1136
+ $activity->user_id = $user_id;
1137
+ $activity->component = $component;
1138
+ $activity->type = $type;
1139
+ $activity->content = $content;
1140
+ $activity->primary_link = $primary_link;
1141
+ $activity->item_id = $item_id;
1142
+ $activity->secondary_item_id = $secondary_item_id;
1143
+ $activity->date_recorded = $recorded_time;
1144
+ $activity->hide_sitewide = $hide_sitewide;
1145
+ $activity->is_spam = $is_spam;
1146
+ $activity->action = ! empty( $action ) ? $action : bp_activity_generate_action_string( $activity );
1147
+
1148
+ if ( !$activity->save() )
1149
+ return false;
1150
 
1151
+ // If this is an activity comment, rebuild the tree
1152
+ if ( 'activity_comment' == $activity->type )
1153
  BP_Activity_Activity::rebuild_activity_comment_tree( $activity->item_id );
 
1154
 
1155
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
1156
+ do_action( 'bp_activity_add', $params );
 
 
 
 
 
 
 
 
1157
 
1158
  return $activity->id;
1159
  }
1161
  /**
1162
  * Post an activity update.
1163
  *
1164
+ * @since BuddyPress (1.2)
1165
+ *
1166
+ * @global object $bp BuddyPress global settings.
1167
+ * @uses wp_parse_args()
1168
+ * @uses bp_is_user_inactive()
1169
+ * @uses bp_core_get_userlink()
1170
+ * @uses bp_activity_add()
1171
+ * @uses apply_filters() To call the 'bp_activity_new_update_action' hook.
1172
+ * @uses apply_filters() To call the 'bp_activity_new_update_content' hook.
1173
+ * @uses apply_filters() To call the 'bp_activity_new_update_primary_link' hook.
1174
+ * @uses bp_update_user_meta()
1175
+ * @uses wp_filter_kses()
1176
+ * @uses do_action() To call the 'bp_activity_posted_update' hook.
1177
+ *
1178
+ * @param array $args {
1179
+ * @type string $content The content of the activity update.
1180
+ * @type int $user_id Optional. Defaults to the logged-in user.
1181
  * }
1182
+ * @return int $activity_id The activity id
 
1183
  */
1184
  function bp_activity_post_update( $args = '' ) {
1185
+ global $bp;
1186
 
1187
+ $defaults = array(
1188
+ 'content' => false,
1189
+ 'user_id' => bp_loggedin_user_id()
1190
+ );
1191
+ $r = wp_parse_args( $args, $defaults );
1192
+ extract( $r, EXTR_SKIP );
1193
 
1194
+ if ( empty( $content ) || !strlen( trim( $content ) ) )
1195
  return false;
 
1196
 
1197
+ if ( bp_is_user_inactive( $user_id ) )
1198
  return false;
 
 
 
 
 
1199
 
1200
+ // Record this on the user's profile
1201
+ $from_user_link = bp_core_get_userlink( $user_id );
1202
+ $activity_content = $content;
1203
+ $primary_link = bp_core_get_userlink( $user_id, false, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
1204
 
1205
+ // Now write the values
1206
  $activity_id = bp_activity_add( array(
1207
+ 'user_id' => $user_id,
1208
+ 'content' => apply_filters( 'bp_activity_new_update_content', $activity_content ),
1209
+ 'primary_link' => apply_filters( 'bp_activity_new_update_primary_link', $primary_link ),
1210
+ 'component' => $bp->activity->id,
1211
  'type' => 'activity_update',
 
1212
  ) );
1213
 
1214
+ $activity_content = apply_filters( 'bp_activity_latest_update_content', $content, $activity_content );
 
 
 
 
 
 
 
 
 
 
 
 
 
1215
 
1216
  // Add this update to the "latest update" usermeta so it can be fetched anywhere.
1217
+ bp_update_user_meta( bp_loggedin_user_id(), 'bp_latest_update', array( 'id' => $activity_id, 'content' => $activity_content ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1218
 
1219
+ do_action( 'bp_activity_posted_update', $content, $user_id, $activity_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1220
 
1221
  return $activity_id;
1222
  }
1223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1224
  /**
1225
  * Add an activity comment.
1226
  *
1227
+ * @since BuddyPress (1.2)
1228
+ *
1229
+ * @global object $bp BuddyPress global settings.
1230
+ * @uses wp_parse_args()
1231
+ * @uses bp_activity_add()
1232
+ * @uses apply_filters() To call the 'bp_activity_comment_action' hook.
1233
+ * @uses apply_filters() To call the 'bp_activity_comment_content' hook.
1234
+ * @uses bp_activity_new_comment_notification()
1235
+ * @uses wp_cache_delete()
1236
+ * @uses do_action() To call the 'bp_activity_comment_posted' hook.
1237
+ *
1238
+ * @param array $args {
1239
+ * @type int $id Optional. Pass an ID to update an existing comment.
1240
+ * @type string $content The content of the comment.
1241
+ * @type int $user_id Optional. The ID of the user making the comment.
1242
+ * Defaults to the ID of the logged-in user.
1243
+ * @type int $activity_id The ID of the "root" activity item, ie the oldest
1244
+ * ancestor of the comment.
1245
+ * @type int $parent_id Optional. The ID of the parent activity item, ie the
1246
+ * item to which the comment is an immediate reply. If
1247
+ * not provided, this value defaults to the $activity_id.
1248
  * }
1249
  * @return int|bool The ID of the comment on success, otherwise false.
1250
  */
1251
  function bp_activity_new_comment( $args = '' ) {
 
1252
 
1253
+ $params = wp_parse_args( $args, array(
1254
+ 'id' => false,
1255
+ 'content' => false,
1256
+ 'user_id' => bp_loggedin_user_id(),
1257
+ 'activity_id' => false, // ID of the root activity item
1258
+ 'parent_id' => false // ID of a parent comment (optional)
 
 
 
1259
  ) );
1260
 
1261
+ extract( $params, EXTR_SKIP );
 
 
 
 
 
 
 
 
1262
 
1263
+ // Bail if missing necessary data
1264
+ if ( empty( $content ) || empty( $user_id ) || empty( $activity_id ) ) {
1265
+ return false;
 
 
 
 
 
 
 
 
 
1266
  }
1267
 
1268
+ // Maybe set current activity ID as the parent
1269
+ if ( empty( $parent_id ) ) {
1270
+ $parent_id = $activity_id;
1271
  }
1272
 
1273
+ // Check to see if the parent activity is hidden, and if so, hide this comment publically.
 
 
1274
  $activity = new BP_Activity_Activity( $activity_id );
1275
+ $is_hidden = ( (int) $activity->hide_sitewide ) ? 1 : 0;
1276
 
1277
+ // Insert the activity comment
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1278
  $comment_id = bp_activity_add( array(
1279
+ 'id' => $id,
1280
+ 'content' => apply_filters( 'bp_activity_comment_content', $content ),
1281
  'component' => buddypress()->activity->id,
1282
  'type' => 'activity_comment',
1283
+ 'user_id' => $user_id,
 
1284
  'item_id' => $activity_id,
1285
+ 'secondary_item_id' => $parent_id,
1286
+ 'hide_sitewide' => $is_hidden
 
1287
  ) );
1288
 
1289
+ // Comment caches are stored only with the top-level item
 
 
 
 
 
1290
  wp_cache_delete( $activity_id, 'bp_activity_comments' );
1291
 
1292
+ // Walk the tree to clear caches for all parent items
1293
+ $clear_id = $parent_id;
1294
  while ( $clear_id != $activity_id ) {
1295
  $clear_object = new BP_Activity_Activity( $clear_id );
1296
  wp_cache_delete( $clear_id, 'bp_activity' );
1298
  }
1299
  wp_cache_delete( $activity_id, 'bp_activity' );
1300
 
1301
+ do_action( 'bp_activity_comment_posted', $comment_id, $params, $activity );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1302
 
1303
  return $comment_id;
1304
  }
1306
  /**
1307
  * Fetch the activity_id for an existing activity entry in the DB.
1308
  *
1309
+ * @since BuddyPress (1.2)
1310
  *
1311
  * @see BP_Activity_Activity::get() For more information on accepted arguments.
1312
+ * @uses wp_parse_args()
1313
+ * @uses apply_filters() To call the 'bp_activity_get_activity_id' hook.
1314
+ * @uses BP_Activity_Activity::save() {@link BP_Activity_Activity}
1315
  *
1316
+ * @param array $args See BP_Activity_Activity::get() for description.
1317
  * @return int $activity_id The ID of the activity item found.
1318
  */
1319
  function bp_activity_get_activity_id( $args = '' ) {
1320
+ $defaults = array(
 
1321
  'user_id' => false,
1322
  'component' => false,
1323
  'type' => false,
1326
  'action' => false,
1327
  'content' => false,
1328
  'date_recorded' => false,
1329
+ );
1330
 
1331
+ $r = wp_parse_args( $args, $defaults );
1332
+ extract( $r, EXTR_SKIP );
1333
+
1334
+ return apply_filters( 'bp_activity_get_activity_id', BP_Activity_Activity::get_id( $user_id, $component, $type, $item_id, $secondary_item_id, $action, $content, $date_recorded ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1335
  }
1336
 
1337
  /**
1347
  *
1348
  * If you are deleting an activity comment please use bp_activity_delete_comment();
1349
  *
1350
+ * @since BuddyPress (1.0)
1351
  *
1352
  * @see BP_Activity_Activity::get() For more information on accepted arguments.
1353
+ * @uses wp_parse_args()
1354
+ * @uses bp_activity_adjust_mention_count()
1355
+ * @uses BP_Activity_Activity::delete() {@link BP_Activity_Activity}
1356
+ * @uses do_action() To call the 'bp_before_activity_delete' hook.
1357
+ * @uses bp_get_user_meta()
1358
+ * @uses bp_delete_user_meta()
1359
+ * @uses do_action() To call the 'bp_activity_delete' hook.
1360
+ * @uses do_action() To call the 'bp_activity_deleted_activities' hook.
1361
+ * @uses wp_cache_delete()
1362
+ *
1363
+ * @param array $args To delete specific activity items, use
1364
+ * $args = array( 'id' => $ids );
1365
+ * Otherwise, to use filters for item deletion, the argument format is
1366
+ * the same as BP_Activity_Activity::get(). See that method for a description.
1367
  * @return bool True on success, false on failure.
1368
  */
1369
  function bp_activity_delete( $args = '' ) {
1370
 
1371
+ // Pass one or more the of following variables to delete by those variables
1372
+ $defaults = array(
1373
  'id' => false,
1374
  'action' => false,
1375
  'content' => false,
1381
  'secondary_item_id' => false,
1382
  'date_recorded' => false,
1383
  'hide_sitewide' => false
1384
+ );
1385
+
1386
+ $args = wp_parse_args( $args, $defaults );
1387
 
 
 
 
 
 
 
 
1388
  do_action( 'bp_before_activity_delete', $args );
1389
 
1390
+ // Adjust the new mention count of any mentioned member
1391
  bp_activity_adjust_mention_count( $args['id'], 'delete' );
1392
 
1393
+ if ( !$activity_ids_deleted = BP_Activity_Activity::delete( $args ) )
 
1394
  return false;
 
1395
 
1396
+ // Check if the user's latest update has been deleted
1397
+ if ( empty( $args['user_id'] ) )
1398
+ $user_id = bp_loggedin_user_id();
1399
+ else
1400
+ $user_id = $args['user_id'];
1401
 
1402
  $latest_update = bp_get_user_meta( $user_id, 'bp_latest_update', true );
1403
  if ( !empty( $latest_update ) ) {
1406
  }
1407
  }
1408
 
 
 
 
 
 
 
 
1409
  do_action( 'bp_activity_delete', $args );
 
 
 
 
 
 
 
 
1410
  do_action( 'bp_activity_deleted_activities', $activity_ids_deleted );
1411
 
1412
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
1419
  *
1420
  * You should use bp_activity_delete() instead.
1421
  *
1422
+ * @since BuddyPress (1.1)
1423
+ * @deprecated BuddyPress (1.2)
1424
+ *
1425
+ * @uses wp_parse_args()
1426
+ * @uses bp_activity_delete()
1427
  *
1428
+ * @param array $args See BP_Activity_Activity::get for a description
1429
+ * of accepted arguments.
1430
  *
 
 
1431
  * @return bool True on success, false on failure.
1432
  */
1433
  function bp_activity_delete_by_item_id( $args = '' ) {
1434
 
1435
+ $defaults = array(
1436
  'item_id' => false,
1437
  'component' => false,
1438
  'type' => false,
1439
  'user_id' => false,
1440
  'secondary_item_id' => false
1441
+ );
1442
+ $r = wp_parse_args( $args, $defaults );
1443
+ extract( $r, EXTR_SKIP );
1444
 
1445
+ return bp_activity_delete( array( 'item_id' => $item_id, 'component' => $component, 'type' => $type, 'user_id' => $user_id, 'secondary_item_id' => $secondary_item_id ) );
1446
  }
1447
 
1448
  /**
1449
  * Delete an activity item by activity id.
1450
  *
1451
+ * @since BuddyPress (1.1)
1452
  *
1453
+ * @uses bp_activity_delete()
1454
  *
1455
+ * @param int ID of the activity item to be deleted.
1456
  * @return bool True on success, false on failure.
1457
  */
1458
  function bp_activity_delete_by_activity_id( $activity_id ) {
1464
  *
1465
  * You should use bp_activity_delete() instead.
1466
  *
1467
+ * @since BuddyPress (1.1)
1468
+ * @deprecated BuddyPress (1.2)
1469
  *
1470
+ * @uses bp_activity_delete()
1471
  *
1472
+ * @param int $user_id The user id.
1473
+ * @param string $content The activity id.
1474
  * @param string $component The activity component.
1475
+ * @param string $type The activity type.
1476
  * @return bool True on success, false on failure.
1477
  */
1478
  function bp_activity_delete_by_content( $user_id, $content, $component, $type ) {
1479
+ return bp_activity_delete( array( 'user_id' => $user_id, 'content' => $content, 'component' => $component, 'type' => $type ) );
 
 
 
 
 
1480
  }
1481
 
1482
  /**
1484
  *
1485
  * You should use bp_activity_delete() instead.
1486
  *
1487
+ * @since BuddyPress (1.1)
1488
+ * @deprecated BuddyPress (1.2)
1489
  *
1490
+ * @uses bp_activity_delete()
1491
  *
1492
+ * @param int $user_id The user id.
1493
  * @param string $component The activity component.
1494
  * @return bool True on success, false on failure.
1495
  */
1496
  function bp_activity_delete_for_user_by_component( $user_id, $component ) {
1497
+ return bp_activity_delete( array( 'user_id' => $user_id, 'component' => $component ) );
 
 
 
1498
  }
1499
 
1500
  /**
1501
  * Delete an activity comment.
1502
  *
1503
+ * @since BuddyPress (1.2)
1504
  *
1505
+ * @uses apply_filters() To call the 'bp_activity_delete_comment_pre' hook.
1506
+ * @uses bp_activity_delete_children()
1507
+ * @uses bp_activity_delete()
1508
+ * @uses BP_Activity_Activity::rebuild_activity_comment_tree() {@link BP_Activity_Activity}
1509
+ * @uses do_action() To call the 'bp_activity_delete_comment' hook.
1510
  * @todo Why is an activity id required? We could look this up.
1511
  * @todo Why do we encourage users to call this function directly? We could just
1512
  * as easily examine the activity type in bp_activity_delete() and then
1514
  *
1515
  * @param int $activity_id The ID of the "root" activity, ie the comment's
1516
  * oldest ancestor.
1517
+ * @param int $comment_id The ID of the comment to be deleted.
1518
+ * @return bool True on success, false on failure
1519
  */
1520
  function bp_activity_delete_comment( $activity_id, $comment_id ) {
1521
+ /***
 
 
 
 
1522
  * You may want to hook into this filter if you want to override this function and
1523
  * handle the deletion of child comments differently. Make sure you return false.
 
 
 
 
 
 
 
 
1524
  */
1525
+ if ( !apply_filters( 'bp_activity_delete_comment_pre', true, $activity_id, $comment_id ) )
1526
+ return false;
 
1527
 
1528
  // Delete any children of this comment.
1529
  bp_activity_delete_children( $activity_id, $comment_id );
1530
 
1531
+ // Delete the actual comment
1532
+ if ( !bp_activity_delete( array( 'id' => $comment_id, 'type' => 'activity_comment' ) ) )
1533
  return false;
 
 
 
 
 
 
1534
 
1535
+ // Recalculate the comment tree
1536
  BP_Activity_Activity::rebuild_activity_comment_tree( $activity_id );
1537
 
 
 
 
 
 
 
 
 
1538
  do_action( 'bp_activity_delete_comment', $activity_id, $comment_id );
1539
 
1540
+ return true;
1541
  }
1542
 
1543
  /**
1544
  * Delete an activity comment's children.
1545
  *
1546
+ * @since BuddyPress (1.2)
1547
  *
1548
+ * @uses BP_Activity_Activity::get_child_comments() {@link BP_Activity_Activity}
1549
+ * @uses bp_activity_delete_children()
1550
+ * @uses bp_activity_delete()
1551
  *
1552
  * @param int $activity_id The ID of the "root" activity, ie the
1553
  * comment's oldest ancestor.
1554
+ * @param int $comment_id The ID of the comment to be deleted.
1555
  */
1556
+ function bp_activity_delete_children( $activity_id, $comment_id) {
 
 
 
 
1557
  // Recursively delete all children of this comment.
1558
+ if ( $children = BP_Activity_Activity::get_child_comments( $comment_id ) ) {
1559
  foreach( (array) $children as $child ) {
1560
  bp_activity_delete_children( $activity_id, $child->id );
1561
  }
1562
  }
1563
+ bp_activity_delete( array( 'secondary_item_id' => $comment_id, 'type' => 'activity_comment', 'item_id' => $activity_id ) );
 
 
 
 
 
 
1564
  }
1565
 
1566
  /**
1571
  * be sure to pass the full $activity_obj parameter as well, if you already
1572
  * have it available.
1573
  *
1574
+ * @since BuddyPress (1.2)
1575
+ *
1576
+ * @uses bp_get_root_domain()
1577
+ * @uses bp_get_activity_root_slug()
1578
+ * @uses apply_filters_ref_array() To call the 'bp_activity_get_permalink' hook.
1579
  *
1580
+ * @param int $activity_id The unique id of the activity object.
1581
+ * @param object $activity_obj Optional. The activity object.
1582
  * @return string $link Permalink for the activity item.
1583
  */
1584
  function bp_activity_get_permalink( $activity_id, $activity_obj = false ) {
 
1585
 
1586
+ if ( empty( $activity_obj ) )
1587
  $activity_obj = new BP_Activity_Activity( $activity_id );
 
1588
 
1589
  if ( isset( $activity_obj->current_comment ) ) {
1590
  $activity_obj = $activity_obj->current_comment;
1591
  }
1592
 
1593
+ if ( 'new_blog_post' == $activity_obj->type || 'new_blog_comment' == $activity_obj->type || 'new_forum_topic' == $activity_obj->type || 'new_forum_post' == $activity_obj->type ) {
 
 
 
 
 
 
 
 
 
 
 
1594
  $link = $activity_obj->primary_link;
1595
  } else {
1596
  if ( 'activity_comment' == $activity_obj->type ) {
1597
+ $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->item_id . '/';
1598
  } else {
1599
  $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->id . '/';
1600
  }
1601
  }
1602
 
 
 
 
 
 
 
 
1603
  return apply_filters_ref_array( 'bp_activity_get_permalink', array( $link, &$activity_obj ) );
1604
  }
1605
 
1606
  /**
1607
  * Hide a user's activity.
1608
  *
1609
+ * @since BuddyPress (1.2)
1610
+ *
1611
+ * @uses BP_Activity_Activity::hide_all_for_user() {@link BP_Activity_Activity}
1612
  *
1613
  * @param int $user_id The ID of the user whose activity is being hidden.
1614
  * @return bool True on success, false on failure.
1627
  * through the content, grabs the first image and converts it to a thumbnail,
1628
  * and removes the rest of the images from the string.
1629
  *
1630
+ * @since BuddyPress (1.2)
1631
  *
1632
+ * @uses esc_attr()
1633
+ * @uses apply_filters() To call the 'bp_activity_thumbnail_content_images' hook
1634
  *
1635
+ * @param string $content The content of the activity item.
1636
+ * @param string $link Optional. The unescaped URL that the image should link
1637
+ * to. If absent, the image will not be a link.
1638
+ * @param array $activity_args Optional. The args passed to the activity
1639
  * creation function (eg bp_blogs_record_activity()).
1640
  * @return string $content The content with images stripped and replaced with a
1641
  * single thumb.
1644
 
1645
  preg_match_all( '/<img[^>]*>/Ui', $content, $matches );
1646
 
1647
+ // Remove <img> tags. Also remove caption shortcodes and caption text if present
1648
  $content = preg_replace('|(\[caption(.*?)\])?<img[^>]*>([^\[\[]*\[\/caption\])?|', '', $content );
1649
 
1650
  if ( !empty( $matches ) && !empty( $matches[0] ) ) {
1651
+ // Get the SRC value
1652
+ preg_match( '/<img.*?(src\=[\'|"]{0,1}.*?[\'|"]{0,1})[\s|>]{1}/i', $matches[0][0], $src );
1653
 
1654
+ // Get the width and height
 
 
 
1655
  preg_match( '/<img.*?(height\=[\'|"]{0,1}.*?[\'|"]{0,1})[\s|>]{1}/i', $matches[0][0], $height );
1656
  preg_match( '/<img.*?(width\=[\'|"]{0,1}.*?[\'|"]{0,1})[\s|>]{1}/i', $matches[0][0], $width );
1657
 
1658
+ if ( !empty( $src ) ) {
1659
+ $src = substr( substr( str_replace( 'src=', '', $src[1] ), 0, -1 ), 1 );
1660
+ $height = substr( substr( str_replace( 'height=', '', $height[1] ), 0, -1 ), 1 );
1661
+ $width = substr( substr( str_replace( 'width=', '', $width[1] ), 0, -1 ), 1 );
 
 
 
 
 
 
1662
 
1663
  if ( empty( $width ) || empty( $height ) ) {
1664
  $width = 100;
1678
  }
1679
  }
1680
 
 
 
 
 
 
 
 
 
 
1681
  return apply_filters( 'bp_activity_thumbnail_content_images', $content, $matches, $args );
1682
  }
1683
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1684
  /**
1685
  * Fetch whether the current user is allowed to mark items as spam.
1686
  *
1687
+ * @since BuddyPress (1.6)
1688
  *
1689
  * @return bool True if user is allowed to mark activity items as spam.
1690
  */
1691
  function bp_activity_user_can_mark_spam() {
 
 
 
 
 
 
 
 
1692
  return apply_filters( 'bp_activity_user_can_mark_spam', bp_current_user_can( 'bp_moderate' ) );
1693
  }
1694
 
1695
  /**
1696
  * Mark an activity item as spam.
1697
  *
1698
+ * @since BuddyPress (1.6)
1699
  *
1700
+ * @global object $bp BuddyPress global settings.
1701
  *
1702
  * @param BP_Activity_Activity $activity The activity item to be spammed.
1703
+ * @param string $source Optional. Default is "by_a_person" (ie, a person has
1704
+ * manually marked the activity as spam). BP core also
1705
+ * accepts 'by_akismet'.
1706
  */
1707
  function bp_activity_mark_as_spam( &$activity, $source = 'by_a_person' ) {
1708
+ global $bp;
1709
 
1710
  $activity->is_spam = 1;
1711
 
1712
+ // Clear the activity stream first page cache
1713
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
1714
 
1715
+ // Clear the activity comment cache for this activity item
1716
  wp_cache_delete( $activity->id, 'bp_activity_comments' );
1717
 
1718
+ // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity
1719
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
1720
+ remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4, 1 );
1721
 
1722
+ // Build data package for Akismet
1723
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
1724
 
1725
+ // Tell Akismet this is spam
1726
  $activity_data = $bp->activity->akismet->send_akismet_request( $activity_data, 'submit', 'spam' );
1727
 
1728
+ // Update meta
1729
  add_action( 'bp_activity_after_save', array( $bp->activity->akismet, 'update_activity_spam_meta' ), 1, 1 );
1730
  }
1731
 
 
 
 
 
 
 
 
 
 
1732
  do_action( 'bp_activity_mark_as_spam', $activity, $source );
1733
  }
1734
 
1735
  /**
1736
  * Mark an activity item as ham.
1737
  *
1738
+ * @since BuddyPress (1.6)
1739
  *
1740
+ * @global object $bp BuddyPress global settings.
1741
+ *
1742
+ * @param BP_Activity_Activity $activity The activity item to be hammed.
1743
+ * @param string $source Optional. Default is "by_a_person" (ie, a person has
1744
+ * manually marked the activity as spam). BP core also
1745
+ * accepts 'by_akismet'.
1746
  */
1747
  function bp_activity_mark_as_ham( &$activity, $source = 'by_a_person' ) {
1748
+ global $bp;
1749
 
1750
  $activity->is_spam = 0;
1751
 
1752
+ // Clear the activity stream first page cache
1753
  wp_cache_delete( 'bp_activity_sitewide_front', 'bp' );
1754
 
1755
+ // Clear the activity comment cache for this activity item
1756
  wp_cache_delete( $activity->id, 'bp_activity_comments' );
1757
 
1758
+ // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity
1759
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
1760
+ remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4, 1 );
1761
 
1762
+ // Build data package for Akismet
1763
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
1764
 
1765
+ // Tell Akismet this is spam
1766
  $activity_data = $bp->activity->akismet->send_akismet_request( $activity_data, 'submit', 'ham' );
1767
 
1768
+ // Update meta
1769
  add_action( 'bp_activity_after_save', array( $bp->activity->akismet, 'update_activity_ham_meta' ), 1, 1 );
1770
  }
1771
 
 
 
 
 
 
 
 
 
 
1772
  do_action( 'bp_activity_mark_as_ham', $activity, $source );
1773
  }
1774
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1775
 
1776
  /** Embeds *******************************************************************/
1777
 
1785
  * This does not cover recursive activity comments, as they do not use a real loop.
1786
  * For that, see {@link bp_activity_comment_embed()}.
1787
  *
1788
+ * @since BuddyPress (1.5)
1789
  *
1790
  * @see BP_Embed
1791
  * @see bp_embed_activity_cache()
1792
  * @see bp_embed_activity_save_cache()
1793
+ * @uses add_filter() To attach 'bp_get_activity_id' to 'embed_post_id'.
1794
+ * @uses add_filter() To attach 'bp_embed_activity_cache' to 'bp_embed_get_cache'.
1795
+ * @uses add_action() To attach 'bp_embed_activity_save_cache' to 'bp_embed_update_cache'.
1796
  */
1797
  function bp_activity_embed() {
1798
  add_filter( 'embed_post_id', 'bp_get_activity_id' );
 
1799
  add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 );
1800
  add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
1801
  }
1802
  add_action( 'activity_loop_start', 'bp_activity_embed' );
1803
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1804
  /**
1805
  * Set up activity oEmbed cache while recursing through activity comments.
1806
  *
1809
  * necessary to grab each comment's embeds from the cache, or put them in
1810
  * the cache if they are not there yet.
1811
  *
1812
+ * @since BuddyPress (1.5)
1813
  *
1814
  * @see BP_Embed
1815
  * @see bp_embed_activity_cache()
1816
  * @see bp_embed_activity_save_cache()
1817
+ * @uses add_filter() To attach 'bp_get_activity_comment_id' to 'embed_post_id'.
1818
+ * @uses add_filter() To attach 'bp_embed_activity_cache' to 'bp_embed_get_cache'.
1819
+ * @uses add_action() To attach 'bp_embed_activity_save_cache' to 'bp_embed_update_cache'.
1820
  */
1821
  function bp_activity_comment_embed() {
1822
  add_filter( 'embed_post_id', 'bp_get_activity_comment_id' );
1828
  /**
1829
  * When a user clicks on a "Read More" item, make sure embeds are correctly parsed and shown for the expanded content.
1830
  *
1831
+ * @since BuddyPress (1.5)
1832
  *
1833
  * @see BP_Embed
1834
+ * @global object $bp BuddyPress global settings
1835
+ * @uses add_filter() To attach create_function() to 'embed_post_id'.
1836
+ * @uses add_filter() To attach 'bp_embed_activity_cache' to 'bp_embed_get_cache'.
1837
+ * @uses add_action() To attach 'bp_embed_activity_save_cache' to 'bp_embed_update_cache'.
1838
  *
1839
  * @param object $activity The activity that is being expanded.
1840
  */
1841
  function bp_dtheme_embed_read_more( $activity ) {
1842
+ global $bp;
1843
 
1844
+ $bp->activity->read_more_id = $activity->id;
1845
+
1846
+ add_filter( 'embed_post_id', create_function( '', 'global $bp; return $bp->activity->read_more_id;' ) );
1847
+ add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 );
1848
+ add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
1849
  }
1850
+ add_action( 'bp_dtheme_get_single_activity_content', 'bp_dtheme_embed_read_more' );
 
1851
 
1852
  /**
1853
  * Clean up 'embed_post_id' filter after comment recursion.
1855
  * This filter must be removed so that the non-comment filters take over again
1856
  * once the comments are done being processed.
1857
  *
1858
+ * @since BuddyPress (1.5)
1859
  *
1860
  * @see bp_activity_comment_embed()
1861
+ * @uses remove_filter() To remove 'bp_get_activity_comment_id' from 'embed_post_id'.
1862
  */
1863
  function bp_activity_comment_embed_after_recurse() {
1864
  remove_filter( 'embed_post_id', 'bp_get_activity_comment_id' );
1870
  *
1871
  * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}.
1872
  *
1873
+ * @since BuddyPress (1.5)
1874
  *
1875
  * @see BP_Embed::parse_oembed()
1876
+ * @uses bp_activity_get_meta()
1877
  *
1878
+ * @param string $cache An empty string passed by BP_Embed::parse_oembed() for
1879
+ * functions like this one to filter.
1880
+ * @param int $id The ID of the activity item.
1881
  * @param string $cachekey The cache key generated in BP_Embed::parse_oembed().
1882
  * @return mixed The cached embeds for this activity item.
1883
  */
1890
  *
1891
  * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}.
1892
  *
1893
+ * @since BuddyPress (1.5)
1894
  *
1895
  * @see BP_Embed::parse_oembed()
1896
+ * @uses bp_activity_update_meta()
1897
  *
1898
+ * @param string $cache An empty string passed by BP_Embed::parse_oembed() for
1899
+ * functions like this one to filter.
1900
+ * @param int $id The ID of the activity item.
1901
  * @param string $cachekey The cache key generated in BP_Embed::parse_oembed().
1902
+ * @return bool True on success, false on failure.
1903
  */
1904
  function bp_embed_activity_save_cache( $cache, $cachekey, $id ) {
1905
  bp_activity_update_meta( $id, $cachekey, $cache );
 
 
 
 
 
 
1906
  }
1907
 
1908
  /**
1909
  * Should we use Heartbeat to refresh activities?
1910
  *
1911
+ * @since BuddyPress (2.0.0)
1912
+ *
1913
+ * @uses bp_is_activity_heartbeat_active() to check if heatbeat setting is on.
1914
+ * @uses bp_is_activity_directory() to check if the current page is the activity
1915
+ * directory.
1916
+ * @uses bp_is_active() to check if the group component is active.
1917
+ * @uses bp_is_group_activity() to check if on a single group, the current page
1918
+ * is the group activities.
1919
+ * @uses bp_is_group_home() to check if the current page is a single group home
1920
+ * page.
1921
  *
1922
  * @return bool True if activity heartbeat is enabled, otherwise false.
1923
  */
1924
  function bp_activity_do_heartbeat() {
1925
  $retval = false;
1926
 
1927
+ if ( ! bp_is_activity_heartbeat_active() ) {
1928
+ return $retval;
1929
+ }
1930
+
1931
+ if ( bp_is_activity_directory() ) {
1932
  $retval = true;
1933
  }
1934
 
1935
+ if ( bp_is_active( 'groups') ) {
1936
+ // If no custom front, then activities are loaded in group's home
1937
+ $has_custom_front = bp_locate_template( array( 'groups/single/front.php' ), false, true );
1938
+
1939
+ if ( bp_is_group_activity() || ( ! $has_custom_front && bp_is_group_home() ) ) {
1940
+ $retval = true;
1941
+ }
1942
+ }
1943
+
1944
+ return $retval;
1945
  }
bp-activity/bp-activity-loader.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Activity Streams Loader.
4
  *
@@ -6,16 +7,362 @@
6
  *
7
  * @package BuddyPress
8
  * @subpackage ActivityCore
9
- * @since 1.5.0
10
  */
11
 
12
- // Exit if accessed directly.
13
- defined( 'ABSPATH' ) || exit;
14
 
15
  /**
16
- * Set up the bp-activity component.
17
  *
18
- * @since 1.6.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  */
20
  function bp_setup_activity() {
21
  buddypress()->activity = new BP_Activity_Component();
1
  <?php
2
+
3
  /**
4
  * BuddyPress Activity Streams Loader.
5
  *
7
  *
8
  * @package BuddyPress
9
  * @subpackage ActivityCore
 
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( !defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
+ * Main Activity Class.
17
  *
18
+ * @since BuddyPress (1.5)
19
+ */
20
+ class BP_Activity_Component extends BP_Component {
21
+
22
+ /**
23
+ * Start the activity component setup process.
24
+ *
25
+ * @since BuddyPress (1.5)
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
+ )
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Include component files.
40
+ *
41
+ * @since BuddyPress (1.5)
42
+ *
43
+ * @see BP_Component::includes() for a description of arguments.
44
+ *
45
+ * @param array $includes See BP_Component::includes() for a description.
46
+ */
47
+ public function includes( $includes = array() ) {
48
+ // Files to include
49
+ $includes = array(
50
+ 'actions',
51
+ 'screens',
52
+ 'filters',
53
+ 'classes',
54
+ 'template',
55
+ 'functions',
56
+ 'notifications',
57
+ 'cache'
58
+ );
59
+
60
+ // Load Akismet support if Akismet is configured
61
+ $akismet_key = bp_get_option( 'wordpress_api_key' );
62
+ if ( defined( 'AKISMET_VERSION' ) && ( !empty( $akismet_key ) || defined( 'WPCOM_API_KEY' ) ) && apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) ) {
63
+ $includes[] = 'akismet';
64
+ }
65
+
66
+ if ( is_admin() ) {
67
+ $includes[] = 'admin';
68
+ }
69
+
70
+ parent::includes( $includes );
71
+ }
72
+
73
+ /**
74
+ * Set up component global variables.
75
+ *
76
+ * The BP_ACTIVITY_SLUG constant is deprecated, and only used here for
77
+ * backwards compatibility.
78
+ *
79
+ * @since BuddyPress (1.5)
80
+ *
81
+ * @see BP_Component::setup_globals() for a description of arguments.
82
+ *
83
+ * @param array $args See BP_Component::setup_globals() for a description.
84
+ */
85
+ public function setup_globals( $args = array() ) {
86
+ $bp = buddypress();
87
+
88
+ // Define a slug, if necessary
89
+ if ( !defined( 'BP_ACTIVITY_SLUG' ) )
90
+ define( 'BP_ACTIVITY_SLUG', $this->id );
91
+
92
+ // Global tables for activity component
93
+ $global_tables = array(
94
+ 'table_name' => $bp->table_prefix . 'bp_activity',
95
+ 'table_name_meta' => $bp->table_prefix . 'bp_activity_meta',
96
+ );
97
+
98
+ // Metadata tables for groups component
99
+ $meta_tables = array(
100
+ 'activity' => $bp->table_prefix . 'bp_activity_meta',
101
+ );
102
+
103
+ // All globals for activity component.
104
+ // Note that global_tables is included in this array.
105
+ $args = array(
106
+ 'slug' => BP_ACTIVITY_SLUG,
107
+ 'root_slug' => isset( $bp->pages->activity->slug ) ? $bp->pages->activity->slug : BP_ACTIVITY_SLUG,
108
+ 'has_directory' => true,
109
+ 'directory_title' => _x( 'Sitewide Activity', 'component directory title', 'buddypress' ),
110
+ 'notification_callback' => 'bp_activity_format_notifications',
111
+ 'search_string' => __( 'Search Activity...', 'buddypress' ),
112
+ 'global_tables' => $global_tables,
113
+ 'meta_tables' => $meta_tables,
114
+ );
115
+
116
+ parent::setup_globals( $args );
117
+ }
118
+
119
+ /**
120
+ * Set up component navigation.
121
+ *
122
+ * @since BuddyPress (1.5)
123
+ *
124
+ * @see BP_Component::setup_nav() for a description of arguments.
125
+ * @uses bp_is_active()
126
+ * @uses is_user_logged_in()
127
+ * @uses bp_get_friends_slug()
128
+ * @uses bp_get_groups_slug()
129
+ *
130
+ * @param array $main_nav Optional. See BP_Component::setup_nav() for
131
+ * description.
132
+ * @param array $sub_nav Optional. See BP_Component::setup_nav() for
133
+ * description.
134
+ */
135
+ public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
136
+
137
+ // Add 'Activity' to the main navigation
138
+ $main_nav = array(
139
+ 'name' => __( 'Activity', 'buddypress' ),
140
+ 'slug' => $this->slug,
141
+ 'position' => 10,
142
+ 'screen_function' => 'bp_activity_screen_my_activity',
143
+ 'default_subnav_slug' => 'just-me',
144
+ 'item_css_id' => $this->id
145
+ );
146
+
147
+ // Stop if there is no user displayed or logged in
148
+ if ( !is_user_logged_in() && !bp_displayed_user_id() )
149
+ return;
150
+
151
+ // Determine user to use
152
+ if ( bp_displayed_user_domain() ) {
153
+ $user_domain = bp_displayed_user_domain();
154
+ } elseif ( bp_loggedin_user_domain() ) {
155
+ $user_domain = bp_loggedin_user_domain();
156
+ } else {
157
+ return;
158
+ }
159
+
160
+ // User link
161
+ $activity_link = trailingslashit( $user_domain . $this->slug );
162
+
163
+ // Add the subnav items to the activity nav item if we are using a theme that supports this
164
+ $sub_nav[] = array(
165
+ 'name' => __( 'Personal', 'buddypress' ),
166
+ 'slug' => 'just-me',
167
+ 'parent_url' => $activity_link,
168
+ 'parent_slug' => $this->slug,
169
+ 'screen_function' => 'bp_activity_screen_my_activity',
170
+ 'position' => 10
171
+ );
172
+
173
+ // @ mentions
174
+ if ( bp_activity_do_mentions() ) {
175
+ $sub_nav[] = array(
176
+ 'name' => __( 'Mentions', 'buddypress' ),
177
+ 'slug' => 'mentions',
178
+ 'parent_url' => $activity_link,
179
+ 'parent_slug' => $this->slug,
180
+ 'screen_function' => 'bp_activity_screen_mentions',
181
+ 'position' => 20,
182
+ 'item_css_id' => 'activity-mentions'
183
+ );
184
+ }
185
+
186
+ // Favorite activity items
187
+ $sub_nav[] = array(
188
+ 'name' => __( 'Favorites', 'buddypress' ),
189
+ 'slug' => 'favorites',
190
+ 'parent_url' => $activity_link,
191
+ 'parent_slug' => $this->slug,
192
+ 'screen_function' => 'bp_activity_screen_favorites',
193
+ 'position' => 30,
194
+ 'item_css_id' => 'activity-favs'
195
+ );
196
+
197
+ // Additional menu if friends is active
198
+ if ( bp_is_active( 'friends' ) ) {
199
+ $sub_nav[] = array(
200
+ 'name' => __( 'Friends', 'buddypress' ),
201
+ 'slug' => bp_get_friends_slug(),
202
+ 'parent_url' => $activity_link,
203
+ 'parent_slug' => $this->slug,
204
+ 'screen_function' => 'bp_activity_screen_friends',
205
+ 'position' => 40,
206
+ 'item_css_id' => 'activity-friends'
207
+ ) ;
208
+ }
209
+
210
+ // Additional menu if groups is active
211
+ if ( bp_is_active( 'groups' ) ) {
212
+ $sub_nav[] = array(
213
+ 'name' => __( 'Groups', 'buddypress' ),
214
+ 'slug' => bp_get_groups_slug(),
215
+ 'parent_url' => $activity_link,
216
+ 'parent_slug' => $this->slug,
217
+ 'screen_function' => 'bp_activity_screen_groups',
218
+ 'position' => 50,
219
+ 'item_css_id' => 'activity-groups'
220
+ );
221
+ }
222
+
223
+ parent::setup_nav( $main_nav, $sub_nav );
224
+ }
225
+
226
+ /**
227
+ * Set up the component entries in the WordPress Admin Bar.
228
+ *
229
+ * @since BuddyPress (1.5)
230
+ *
231
+ * @see BP_Component::setup_nav() for a description of the $wp_admin_nav
232
+ * parameter array.
233
+ * @uses is_user_logged_in()
234
+ * @uses trailingslashit()
235
+ * @uses bp_get_total_mention_count_for_user()
236
+ * @uses bp_loggedin_user_id()
237
+ * @uses bp_is_active()
238
+ * @uses bp_get_friends_slug()
239
+ * @uses bp_get_groups_slug()
240
+ *
241
+ * @param array $wp_admin_nav See BP_Component::setup_admin_bar() for a
242
+ * description.
243
+ */
244
+ public function setup_admin_bar( $wp_admin_nav = array() ) {
245
+ $bp = buddypress();
246
+
247
+ // Menus for logged in user
248
+ if ( is_user_logged_in() ) {
249
+
250
+ // Setup the logged in user variables
251
+ $user_domain = bp_loggedin_user_domain();
252
+ $activity_link = trailingslashit( $user_domain . $this->slug );
253
+
254
+ // Unread message count
255
+ if ( bp_activity_do_mentions() ) {
256
+ $count = bp_get_total_mention_count_for_user( bp_loggedin_user_id() );
257
+ if ( !empty( $count ) ) {
258
+ $title = sprintf( __( 'Mentions <span class="count">%s</span>', 'buddypress' ), number_format_i18n( $count ) );
259
+ } else {
260
+ $title = __( 'Mentions', 'buddypress' );
261
+ }
262
+ }
263
+
264
+ // Add the "Activity" sub menu
265
+ $wp_admin_nav[] = array(
266
+ 'parent' => $bp->my_account_menu_id,
267
+ 'id' => 'my-account-' . $this->id,
268
+ 'title' => __( 'Activity', 'buddypress' ),
269
+ 'href' => trailingslashit( $activity_link )
270
+ );
271
+
272
+ // Personal
273
+ $wp_admin_nav[] = array(
274
+ 'parent' => 'my-account-' . $this->id,
275
+ 'id' => 'my-account-' . $this->id . '-personal',
276
+ 'title' => __( 'Personal', 'buddypress' ),
277
+ 'href' => trailingslashit( $activity_link )
278
+ );
279
+
280
+ // Mentions
281
+ if ( bp_activity_do_mentions() ) {
282
+ $wp_admin_nav[] = array(
283
+ 'parent' => 'my-account-' . $this->id,
284
+ 'id' => 'my-account-' . $this->id . '-mentions',
285
+ 'title' => $title,
286
+ 'href' => trailingslashit( $activity_link . 'mentions' )
287
+ );
288
+ }
289
+
290
+ // Favorites
291
+ $wp_admin_nav[] = array(
292
+ 'parent' => 'my-account-' . $this->id,
293
+ 'id' => 'my-account-' . $this->id . '-favorites',
294
+ 'title' => __( 'Favorites', 'buddypress' ),
295
+ 'href' => trailingslashit( $activity_link . 'favorites' )
296
+ );
297
+
298
+ // Friends?
299
+ if ( bp_is_active( 'friends' ) ) {
300
+ $wp_admin_nav[] = array(
301
+ 'parent' => 'my-account-' . $this->id,
302
+ 'id' => 'my-account-' . $this->id . '-friends',
303
+ 'title' => __( 'Friends', 'buddypress' ),
304
+ 'href' => trailingslashit( $activity_link . bp_get_friends_slug() )
305
+ );
306
+ }
307
+
308
+ // Groups?
309
+ if ( bp_is_active( 'groups' ) ) {
310
+ $wp_admin_nav[] = array(
311
+ 'parent' => 'my-account-' . $this->id,
312
+ 'id' => 'my-account-' . $this->id . '-groups',
313
+ 'title' => __( 'Groups', 'buddypress' ),
314
+ 'href' => trailingslashit( $activity_link . bp_get_groups_slug() )
315
+ );
316
+ }
317
+ }
318
+
319
+ parent::setup_admin_bar( $wp_admin_nav );
320
+ }
321
+
322
+ /**
323
+ * Set up the title for pages and <title>.
324
+ *
325
+ * @since BuddyPress (1.5)
326
+ *
327
+ * @uses bp_is_activity_component()
328
+ * @uses bp_is_my_profile()
329
+ * @uses bp_core_fetch_avatar()
330
+ */
331
+ public function setup_title() {
332
+ $bp = buddypress();
333
+
334
+ // Adjust title based on view
335
+ if ( bp_is_activity_component() ) {
336
+ if ( bp_is_my_profile() ) {
337
+ $bp->bp_options_title = __( 'My Activity', 'buddypress' );
338
+ } else {
339
+ $bp->bp_options_avatar = bp_core_fetch_avatar( array(
340
+ 'item_id' => bp_displayed_user_id(),
341
+ 'type' => 'thumb',
342
+ 'alt' => sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_get_displayed_user_fullname() )
343
+ ) );
344
+ $bp->bp_options_title = bp_get_displayed_user_fullname();
345
+ }
346
+ }
347
+
348
+ parent::setup_title();
349
+ }
350
+
351
+ /**
352
+ * Set up actions necessary for the component.
353
+ *
354
+ * @since BuddyPress (1.6)
355
+ */
356
+ public function setup_actions() {
357
+ // Spam prevention
358
+ add_action( 'bp_include', 'bp_activity_setup_akismet' );
359
+
360
+ parent::setup_actions();
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Bootstrap the Activity component.
366
  */
367
  function bp_setup_activity() {
368
  buddypress()->activity = new BP_Activity_Component();
bp-activity/bp-activity-notifications.php CHANGED
@@ -1,134 +1,304 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Activity Notifications.
4
  *
5
  * @package BuddyPress
6
  * @subpackage ActivityNotifications
7
- * @since 1.2.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
 
 
12
 
13
  /**
14
- * Format notifications related to activity.
15
  *
16
- * @since 1.5.0
17
  *
18
- * @param string $action The type of activity item. Just 'new_at_mention' for now.
19
- * @param int $item_id The activity ID.
20
- * @param int $secondary_item_id In the case of at-mentions, this is the mentioner's ID.
21
- * @param int $total_items The total number of notifications to format.
22
- * @param string $format 'string' to get a BuddyBar-compatible notification, 'array' otherwise.
23
- * @param int $id Optional. The notification ID.
24
- * @return string $return Formatted @mention notification.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  */
26
- function bp_activity_format_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string', $id = 0 ) {
27
- $action_filter = $action;
28
- $return = false;
29
- $activity_id = $item_id;
30
- $user_id = $secondary_item_id;
31
- $user_fullname = bp_core_get_user_displayname( $user_id );
32
 
33
- switch ( $action ) {
34
- case 'new_at_mention':
35
- $action_filter = 'at_mentions';
36
- $link = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/';
37
- $title = sprintf( __( '@%s Mentions', 'buddypress' ), bp_get_loggedin_user_username() );
38
- $amount = 'single';
39
 
40
- if ( (int) $total_items > 1 ) {
41
- $text = sprintf( __( 'You have %1$d new mentions', 'buddypress' ), (int) $total_items );
42
- $amount = 'multiple';
43
- } else {
44
- $text = sprintf( __( '%1$s mentioned you', 'buddypress' ), $user_fullname );
45
- }
46
- break;
47
 
48
- case 'update_reply':
49
- $link = bp_get_notifications_permalink();
50
- $title = __( 'New Activity reply', 'buddypress' );
51
- $amount = 'single';
52
 
53
- if ( (int) $total_items > 1 ) {
54
- $link = add_query_arg( 'type', $action, $link );
55
- $text = sprintf( __( 'You have %1$d new replies', 'buddypress' ), (int) $total_items );
56
- $amount = 'multiple';
57
- } else {
58
- $link = add_query_arg( 'nid', (int) $id, bp_activity_get_permalink( $activity_id ) );
59
- $text = sprintf( __( '%1$s commented on one of your updates', 'buddypress' ), $user_fullname );
60
- }
61
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
- case 'comment_reply':
64
- $link = bp_get_notifications_permalink();
65
- $title = __( 'New Activity comment reply', 'buddypress' );
66
- $amount = 'single';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  if ( (int) $total_items > 1 ) {
69
- $link = add_query_arg( 'type', $action, $link );
70
- $text = sprintf( __( 'You have %1$d new comment replies', 'buddypress' ), (int) $total_items );
71
- $amount = 'multiple';
72
  } else {
73
- $link = add_query_arg( 'nid', (int) $id, bp_activity_get_permalink( $activity_id ) );
74
- $text = sprintf( __( '%1$s replied to one your activity comments', 'buddypress' ), $user_fullname );
 
75
  }
76
  break;
77
  }
78
 
79
  if ( 'string' == $format ) {
80
-
81
- /**
82
- * Filters the activity notification for the string format.
83
- *
84
- * This is a variable filter that is dependent on how many items
85
- * need notified about. The two possible hooks are bp_activity_single_at_mentions_notification
86
- * or bp_activity_multiple_at_mentions_notification.
87
- *
88
- * @since 1.5.0
89
- * @since 2.6.0 use the $action_filter as a new dynamic portion of the filter name.
90
- *
91
- * @param string $string HTML anchor tag for the interaction.
92
- * @param string $link The permalink for the interaction.
93
- * @param int $total_items How many items being notified about.
94
- * @param int $activity_id ID of the activity item being formatted.
95
- * @param int $user_id ID of the user who inited the interaction.
96
- */
97
- $return = apply_filters( 'bp_activity_' . $amount . '_' . $action_filter . '_notification', '<a href="' . esc_url( $link ) . '" title="' . esc_attr( $title ) . '">' . esc_html( $text ) . '</a>', $link, (int) $total_items, $activity_id, $user_id );
98
  } else {
99
-
100
- /**
101
- * Filters the activity notification for any non-string format.
102
- *
103
- * This is a variable filter that is dependent on how many items need notified about.
104
- * The two possible hooks are bp_activity_single_at_mentions_notification
105
- * or bp_activity_multiple_at_mentions_notification.
106
- *
107
- * @since 1.5.0
108
- * @since 2.6.0 use the $action_filter as a new dynamic portion of the filter name.
109
- *
110
- * @param array $array Array holding the content and permalink for the interaction notification.
111
- * @param string $link The permalink for the interaction.
112
- * @param int $total_items How many items being notified about.
113
- * @param int $activity_id ID of the activity item being formatted.
114
- * @param int $user_id ID of the user who inited the interaction.
115
- */
116
- $return = apply_filters( 'bp_activity_' . $amount . '_' . $action_filter . '_notification', array(
117
  'text' => $text,
118
- 'link' => $link
119
- ), $link, (int) $total_items, $activity_id, $user_id );
120
  }
121
 
122
- /**
123
- * Fires right before returning the formatted activity notifications.
124
- *
125
- * @since 1.2.0
126
- *
127
- * @param string $action The type of activity item.
128
- * @param int $item_id The activity ID.
129
- * @param int $secondary_item_id The user ID who inited the interaction.
130
- * @param int $total_items Total amount of items to format.
131
- */
132
  do_action( 'activity_format_notifications', $action, $item_id, $secondary_item_id, $total_items );
133
 
134
  return $return;
@@ -142,16 +312,17 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
142
  * future when we separate emails from Notifications, this will need its own
143
  * 'bp_activity_at_name_send_emails' equivalent helper function.
144
  *
145
- * @since 1.9.0
146
  *
147
- * @param object $activity Activity object.
148
- * @param string $subject (not used) Notification subject.
149
- * @param string $message (not used) Notification message.
150
- * @param string $content (not used) Notification content.
151
- * @param int $receiver_user_id ID of user receiving notification.
152
  */
153
  function bp_activity_at_mention_add_notification( $activity, $subject, $message, $content, $receiver_user_id ) {
154
- bp_notifications_add_notification( array(
 
155
  'user_id' => $receiver_user_id,
156
  'item_id' => $activity->id,
157
  'secondary_item_id' => $activity->user_id,
@@ -159,183 +330,66 @@ function bp_activity_at_mention_add_notification( $activity, $subject, $message,
159
  'component_action' => 'new_at_mention',
160
  'date_notified' => bp_core_current_time(),
161
  'is_new' => 1,
162
- ) );
 
163
  }
164
  add_action( 'bp_activity_sent_mention_email', 'bp_activity_at_mention_add_notification', 10, 5 );
165
 
166
- /**
167
- * Notify a member one of their activity received a reply.
168
- *
169
- * @since 2.6.0
170
- *
171
- * @param BP_Activity_Activity $activity The original activity.
172
- * @param int $comment_id ID for the newly received comment.
173
- * @param int $commenter_id ID of the user who made the comment.
174
- */
175
- function bp_activity_update_reply_add_notification( $activity, $comment_id, $commenter_id ) {
176
- bp_notifications_add_notification( array(
177
- 'user_id' => $activity->user_id,
178
- 'item_id' => $comment_id,
179
- 'secondary_item_id' => $commenter_id,
180
- 'component_name' => buddypress()->activity->id,
181
- 'component_action' => 'update_reply',
182
- 'date_notified' => bp_core_current_time(),
183
- 'is_new' => 1,
184
- ) );
185
- }
186
- add_action( 'bp_activity_sent_reply_to_update_notification', 'bp_activity_update_reply_add_notification', 10, 3 );
187
-
188
- /**
189
- * Notify a member one of their activity comment received a reply.
190
- *
191
- * @since 2.6.0
192
- *
193
- * @param BP_Activity_Activity $activity_comment The parent activity.
194
- * @param int $comment_id ID for the newly received comment.
195
- * @param int $commenter_id ID of the user who made the comment.
196
- */
197
- function bp_activity_comment_reply_add_notification( $activity_comment, $comment_id, $commenter_id ) {
198
- bp_notifications_add_notification( array(
199
- 'user_id' => $activity_comment->user_id,
200
- 'item_id' => $comment_id,
201
- 'secondary_item_id' => $commenter_id,
202
- 'component_name' => buddypress()->activity->id,
203
- 'component_action' => 'comment_reply',
204
- 'date_notified' => bp_core_current_time(),
205
- 'is_new' => 1,
206
- ) );
207
- }
208
- add_action( 'bp_activity_sent_reply_to_reply_notification', 'bp_activity_comment_reply_add_notification', 10, 3 );
209
-
210
  /**
211
  * Mark at-mention notifications as read when users visit their Mentions page.
212
  *
213
- * @since 1.5.0
214
- * @since 2.5.0 Add the $user_id parameter
215
  *
216
- * @param int $user_id The id of the user whose notifications are marked as read.
217
  */
218
- function bp_activity_remove_screen_notifications( $user_id = 0 ) {
219
- // Only mark read if the current user is looking at his own mentions.
220
- if ( empty( $user_id ) || (int) $user_id !== (int) bp_loggedin_user_id() ) {
221
  return;
222
  }
223
 
224
- bp_notifications_mark_notifications_by_type( $user_id, buddypress()->activity->id, 'new_at_mention' );
 
 
 
 
 
225
  }
226
- add_action( 'bp_activity_clear_new_mentions', 'bp_activity_remove_screen_notifications', 10, 1 );
227
 
228
  /**
229
  * Mark at-mention notification as read when user visits the activity with the mention.
230
  *
231
- * @since 2.0.0
232
- *
233
- * @param BP_Activity_Activity $activity Activity object.
234
  */
235
  function bp_activity_remove_screen_notifications_single_activity_permalink( $activity ) {
236
- if ( ! is_user_logged_in() ) {
237
  return;
238
  }
239
 
240
- // Mark as read any notifications for the current user related to this activity item.
241
- bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), $activity->id, buddypress()->activity->id, 'new_at_mention' );
242
- }
243
- add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_screen_notifications_single_activity_permalink' );
244
-
245
- /**
246
- * Mark non-mention notifications as read when user visits our read permalink.
247
- *
248
- * In particular, 'update_reply' and 'comment_reply' notifications are handled
249
- * here. See {@link bp_activity_format_notifications()} for more info.
250
- *
251
- * @since 2.6.0
252
- */
253
- function bp_activity_remove_screen_notifications_for_non_mentions() {
254
- if ( false === is_singular() || false === is_user_logged_in() || empty( $_GET['nid'] ) ) {
255
  return;
256
  }
257
 
258
- // Mark notification as read.
259
- BP_Notifications_Notification::update(
260
- array(
261
- 'is_new' => false
262
- ),
263
- array(
264
- 'user_id' => bp_loggedin_user_id(),
265
- 'id' => (int) $_GET['nid']
266
- )
267
- );
268
  }
269
- add_action( 'bp_screens', 'bp_activity_remove_screen_notifications_for_non_mentions' );
270
 
271
  /**
272
  * Delete at-mention notifications when the corresponding activity item is deleted.
273
  *
274
- * @since 2.0.0
275
  *
276
  * @param array $activity_ids_deleted IDs of deleted activity items.
277
  */
278
  function bp_activity_at_mention_delete_notification( $activity_ids_deleted = array() ) {
279
  // Let's delete all without checking if content contains any mentions
280
- // to avoid a query to get the activity.
281
- if ( ! empty( $activity_ids_deleted ) ) {
282
  foreach ( $activity_ids_deleted as $activity_id ) {
283
  bp_notifications_delete_all_notifications_by_type( $activity_id, buddypress()->activity->id );
284
  }
285
  }
286
  }
287
  add_action( 'bp_activity_deleted_activities', 'bp_activity_at_mention_delete_notification', 10 );
288
-
289
- /**
290
- * Add a notification for post comments to the post author or post commenter.
291
- *
292
- * Requires "activity stream commenting on blog and forum posts" to be enabled.
293
- *
294
- * @since 2.6.0
295
- *
296
- * @param int $activity_id The activity comment ID.
297
- * @param WP_Comment $post_type_comment WP Comment object.
298
- * @param array $activity_args Activity comment arguments.
299
- * @param object $activity_post_object The post type tracking args object.
300
- */
301
- function bp_activity_add_notification_for_synced_blog_comment( $activity_id, $post_type_comment, $activity_args, $activity_post_object ) {
302
- // If activity comments are disabled for WP posts, stop now!
303
- if ( bp_disable_blogforum_comments() || empty( $activity_id ) ) {
304
- return;
305
- }
306
-
307
- // Send a notification to the blog post author.
308
- if ( (int) $post_type_comment->post->post_author !== (int) $activity_args['user_id'] ) {
309
- // Only add a notification if comment author is a registered user.
310
- // @todo Should we remove this restriction?
311
- if ( ! empty( $post_type_comment->user_id ) ) {
312
- bp_notifications_add_notification( array(
313
- 'user_id' => $post_type_comment->post->post_author,
314
- 'item_id' => $activity_id,
315
- 'secondary_item_id' => $post_type_comment->user_id,
316
- 'component_name' => buddypress()->activity->id,
317
- 'component_action' => 'update_reply',
318
- 'date_notified' => $post_type_comment->comment_date_gmt,
319
- 'is_new' => 1,
320
- ) );
321
- }
322
- }
323
-
324
- // Send a notification to the parent comment author for follow-up comments.
325
- if ( ! empty( $post_type_comment->comment_parent ) ) {
326
- $parent_comment = get_comment( $post_type_comment->comment_parent );
327
-
328
- if ( ! empty( $parent_comment->user_id ) && (int) $parent_comment->user_id !== (int) $activity_args['user_id'] ) {
329
- bp_notifications_add_notification( array(
330
- 'user_id' => $parent_comment->user_id,
331
- 'item_id' => $activity_id,
332
- 'secondary_item_id' => $post_type_comment->user_id,
333
- 'component_name' => buddypress()->activity->id,
334
- 'component_action' => 'comment_reply',
335
- 'date_notified' => $post_type_comment->comment_date_gmt,
336
- 'is_new' => 1,
337
- ) );
338
- }
339
- }
340
- }
341
- add_action( 'bp_blogs_comment_sync_activity_comment', 'bp_activity_add_notification_for_synced_blog_comment', 10, 4 );
1
  <?php
2
+
3
  /**
4
  * BuddyPress Activity Notifications.
5
  *
6
  * @package BuddyPress
7
  * @subpackage ActivityNotifications
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
+
13
+ /* Emails *********************************************************************/
14
 
15
  /**
16
+ * Send email and BP notifications when a user is mentioned in an update.
17
  *
18
+ * @since BuddyPress (1.2)
19
  *
20
+ * @uses bp_notifications_add_notification()
21
+ * @uses bp_get_user_meta()
22
+ * @uses bp_core_get_user_displayname()
23
+ * @uses bp_activity_get_permalink()
24
+ * @uses bp_core_get_user_domain()
25
+ * @uses bp_get_settings_slug()
26
+ * @uses bp_activity_filter_kses()
27
+ * @uses bp_core_get_core_userdata()
28
+ * @uses wp_specialchars_decode()
29
+ * @uses get_blog_option()
30
+ * @uses bp_is_active()
31
+ * @uses bp_is_group()
32
+ * @uses bp_get_current_group_name()
33
+ * @uses apply_filters() To call the 'bp_activity_at_message_notification_to' hook.
34
+ * @uses apply_filters() To call the 'bp_activity_at_message_notification_subject' hook.
35
+ * @uses apply_filters() To call the 'bp_activity_at_message_notification_message' hook.
36
+ * @uses wp_mail()
37
+ * @uses do_action() To call the 'bp_activity_sent_mention_email' hook
38
+ *
39
+ * @param int $activity_id The ID of the activity update.
40
+ * @param int $receiver_user_id The ID of the user who is receiving the update.
41
  */
42
+ function bp_activity_at_message_notification( $activity_id, $receiver_user_id ) {
 
 
 
 
 
43
 
44
+ // Don't leave multiple notifications for the same activity item
45
+ $notifications = BP_Core_Notification::get_all_for_user( $receiver_user_id, 'all' );
 
 
 
 
46
 
47
+ foreach( $notifications as $notification ) {
48
+ if ( $activity_id == $notification->item_id ) {
49
+ return;
50
+ }
51
+ }
 
 
52
 
53
+ $activity = new BP_Activity_Activity( $activity_id );
 
 
 
54
 
55
+ $subject = '';
56
+ $message = '';
57
+ $content = '';
58
+
59
+ // Now email the user with the contents of the message (if they have enabled email notifications)
60
+ if ( 'no' != bp_get_user_meta( $receiver_user_id, 'notification_activity_new_mention', true ) ) {
61
+ $poster_name = bp_core_get_user_displayname( $activity->user_id );
62
+
63
+ $message_link = bp_activity_get_permalink( $activity_id );
64
+ $settings_slug = function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings';
65
+ $settings_link = bp_core_get_user_domain( $receiver_user_id ) . $settings_slug . '/notifications/';
66
+
67
+ $poster_name = stripslashes( $poster_name );
68
+ $content = bp_activity_filter_kses( strip_tags( stripslashes( $activity->content ) ) );
69
+
70
+ // Set up and send the message
71
+ $ud = bp_core_get_core_userdata( $receiver_user_id );
72
+ $to = $ud->user_email;
73
+ $subject = bp_get_email_subject( array( 'text' => sprintf( __( '%s mentioned you in an update', 'buddypress' ), $poster_name ) ) );
74
+
75
+ if ( bp_is_active( 'groups' ) && bp_is_group() ) {
76
+ $message = sprintf( __(
77
+ '%1$s mentioned you in the group "%2$s":
78
+
79
+ "%3$s"
80
+
81
+ To view and respond to the message, log in and visit: %4$s
82
+
83
+ ---------------------
84
+ ', 'buddypress' ), $poster_name, bp_get_current_group_name(), $content, $message_link );
85
+ } else {
86
+ $message = sprintf( __(
87
+ '%1$s mentioned you in an update:
88
+
89
+ "%2$s"
90
+
91
+ To view and respond to the message, log in and visit: %3$s
92
+
93
+ ---------------------
94
+ ', 'buddypress' ), $poster_name, $content, $message_link );
95
+ }
96
+
97
+ // Only show the disable notifications line if the settings component is enabled
98
+ if ( bp_is_active( 'settings' ) ) {
99
+ $message .= sprintf( __( 'To disable these notifications please log in and go to: %s', 'buddypress' ), $settings_link );
100
+ }
101
+
102
+ // Send the message
103
+ $to = apply_filters( 'bp_activity_at_message_notification_to', $to );
104
+ $subject = apply_filters( 'bp_activity_at_message_notification_subject', $subject, $poster_name );
105
+ $message = apply_filters( 'bp_activity_at_message_notification_message', $message, $poster_name, $content, $message_link, $settings_link );
106
+
107
+ wp_mail( $to, $subject, $message );
108
+ }
109
+
110
+ do_action( 'bp_activity_sent_mention_email', $activity, $subject, $message, $content, $receiver_user_id );
111
+ }
112
+
113
+ /**
114
+ * Send email and BP notifications when an activity item receives a comment.
115
+ *
116
+ * @since BuddyPress (1.2)
117
+ *
118
+ * @uses bp_get_user_meta()
119
+ * @uses bp_core_get_user_displayname()
120
+ * @uses bp_activity_get_permalink()
121
+ * @uses bp_core_get_user_domain()
122
+ * @uses bp_get_settings_slug()
123
+ * @uses bp_activity_filter_kses()
124
+ * @uses bp_core_get_core_userdata()
125
+ * @uses wp_specialchars_decode()
126
+ * @uses get_blog_option()
127
+ * @uses bp_get_root_blog_id()
128
+ * @uses apply_filters() To call the 'bp_activity_new_comment_notification_to' hook
129
+ * @uses apply_filters() To call the 'bp_activity_new_comment_notification_subject' hook
130
+ * @uses apply_filters() To call the 'bp_activity_new_comment_notification_message' hook
131
+ * @uses wp_mail()
132
+ * @uses do_action() To call the 'bp_activity_sent_reply_to_update_email' hook
133
+ * @uses apply_filters() To call the 'bp_activity_new_comment_notification_comment_author_to' hook
134
+ * @uses apply_filters() To call the 'bp_activity_new_comment_notification_comment_author_subject' hook
135
+ * @uses apply_filters() To call the 'bp_activity_new_comment_notification_comment_author_message' hook
136
+ * @uses do_action() To call the 'bp_activity_sent_reply_to_reply_email' hook
137
+ *
138
+ * @param int $comment_id The comment id.
139
+ * @param int $commenter_id The ID of the user who posted the comment.
140
+ * @param array $params {@link bp_activity_new_comment()}
141
+ */
142
+ function bp_activity_new_comment_notification( $comment_id = 0, $commenter_id = 0, $params = array() ) {
143
+
144
+ // Set some default parameters
145
+ $activity_id = 0;
146
+ $parent_id = 0;
147
+
148
+ extract( $params );
149
+
150
+ $original_activity = new BP_Activity_Activity( $activity_id );
151
+
152
+ if ( $original_activity->user_id != $commenter_id && 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
153
+ $poster_name = bp_core_get_user_displayname( $commenter_id );
154
+ $thread_link = bp_activity_get_permalink( $activity_id );
155
+ $settings_slug = function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings';
156
+ $settings_link = bp_core_get_user_domain( $original_activity->user_id ) . $settings_slug . '/notifications/';
157
+
158
+ $poster_name = stripslashes( $poster_name );
159
+ $content = bp_activity_filter_kses( stripslashes($content) );
160
+
161
+ // Set up and send the message
162
+ $ud = bp_core_get_core_userdata( $original_activity->user_id );
163
+ $to = $ud->user_email;
164
+ $subject = bp_get_email_subject( array( 'text' => sprintf( __( '%s replied to one of your updates', 'buddypress' ), $poster_name ) ) );
165
+ $message = sprintf( __(
166
+ '%1$s replied to one of your updates:
167
+
168
+ "%2$s"
169
+
170
+ To view your original update and all comments, log in and visit: %3$s
171
+
172
+ ---------------------
173
+ ', 'buddypress' ), $poster_name, $content, $thread_link );
174
+
175
+ // Only show the disable notifications line if the settings component is enabled
176
+ if ( bp_is_active( 'settings' ) ) {
177
+ $message .= sprintf( __( 'To disable these notifications please log in and go to: %s', 'buddypress' ), $settings_link );
178
+ }
179
+
180
+ /* Send the message */
181
+ $to = apply_filters( 'bp_activity_new_comment_notification_to', $to );
182
+ $subject = apply_filters( 'bp_activity_new_comment_notification_subject', $subject, $poster_name );
183
+ $message = apply_filters( 'bp_activity_new_comment_notification_message', $message, $poster_name, $content, $thread_link, $settings_link );
184
+
185
+ wp_mail( $to, $subject, $message );
186
+
187
+ do_action( 'bp_activity_sent_reply_to_update_email', $original_activity->user_id, $subject, $message, $comment_id, $commenter_id, $params );
188
+ }
189
+
190
+ /***
191
+ * If this is a reply to another comment, send an email notification to the
192
+ * author of the immediate parent comment.
193
+ */
194
+ if ( empty( $parent_id ) || ( $activity_id == $parent_id ) ) {
195
+ return false;
196
+ }
197
+
198
+ $parent_comment = new BP_Activity_Activity( $parent_id );
199
+
200
+ if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id && 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
201
+ $poster_name = bp_core_get_user_displayname( $commenter_id );
202
+ $thread_link = bp_activity_get_permalink( $activity_id );
203
+ $settings_slug = function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings';
204
+ $settings_link = bp_core_get_user_domain( $parent_comment->user_id ) . $settings_slug . '/notifications/';
205
+
206
+ // Set up and send the message
207
+ $ud = bp_core_get_core_userdata( $parent_comment->user_id );
208
+ $to = $ud->user_email;
209
+ $subject = bp_get_email_subject( array( 'text' => sprintf( __( '%s replied to one of your comments', 'buddypress' ), $poster_name ) ) );
210
+
211
+ $poster_name = stripslashes( $poster_name );
212
+ $content = bp_activity_filter_kses( stripslashes( $content ) );
213
+
214
+ $message = sprintf( __(
215
+ '%1$s replied to one of your comments:
216
+
217
+ "%2$s"
218
+
219
+ To view the original activity, your comment and all replies, log in and visit: %3$s
220
+
221
+ ---------------------
222
+ ', 'buddypress' ), $poster_name, $content, $thread_link );
223
+
224
+ // Only show the disable notifications line if the settings component is enabled
225
+ if ( bp_is_active( 'settings' ) ) {
226
+ $message .= sprintf( __( 'To disable these notifications please log in and go to: %s', 'buddypress' ), $settings_link );
227
+ }
228
+
229
+ /* Send the message */
230
+ $to = apply_filters( 'bp_activity_new_comment_notification_comment_author_to', $to );
231
+ $subject = apply_filters( 'bp_activity_new_comment_notification_comment_author_subject', $subject, $poster_name );
232
+ $message = apply_filters( 'bp_activity_new_comment_notification_comment_author_message', $message, $poster_name, $content, $settings_link, $thread_link );
233
+
234
+ wp_mail( $to, $subject, $message );
235
+
236
+ do_action( 'bp_activity_sent_reply_to_reply_email', $original_activity->user_id, $subject, $message, $comment_id, $commenter_id, $params );
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Helper method to map action arguments to function parameters
242
+ *
243
+ * @since BuddyPress (1.9.0)
244
+ * @param int $comment_id
245
+ * @param array $params
246
+ */
247
+ function bp_activity_new_comment_notification_helper( $comment_id, $params ) {
248
+ bp_activity_new_comment_notification( $comment_id, $params['user_id'], $params );
249
+ }
250
+ add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_helper', 10, 2 );
251
 
252
+ /** Notifications *************************************************************/
253
+
254
+ /**
255
+ * Format notifications related to activity.
256
+ *
257
+ * @since BuddyPress (1.5)
258
+ *
259
+ * @uses bp_loggedin_user_domain()
260
+ * @uses bp_get_activity_slug()
261
+ * @uses bp_core_get_user_displayname()
262
+ * @uses apply_filters() To call the 'bp_activity_multiple_at_mentions_notification' hook.
263
+ * @uses apply_filters() To call the 'bp_activity_single_at_mentions_notification' hook.
264
+ * @uses do_action() To call 'activity_format_notifications' hook.
265
+ *
266
+ * @param string $action The type of activity item. Just 'new_at_mention' for now.
267
+ * @param int $item_id The activity ID.
268
+ * @param int $secondary_item_id In the case of at-mentions, this is the mentioner's ID.
269
+ * @param int $total_items The total number of notifications to format.
270
+ * @param string $format 'string' to get a BuddyBar-compatible notification, 'array' otherwise.
271
+ * @return string $return Formatted @mention notification.
272
+ */
273
+ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
274
+
275
+ switch ( $action ) {
276
+ case 'new_at_mention':
277
+ $activity_id = $item_id;
278
+ $poster_user_id = $secondary_item_id;
279
+ $at_mention_link = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/';
280
+ $at_mention_title = sprintf( __( '@%s Mentions', 'buddypress' ), bp_get_loggedin_user_username() );
281
 
282
  if ( (int) $total_items > 1 ) {
283
+ $text = sprintf( __( 'You have %1$d new mentions', 'buddypress' ), (int) $total_items );
284
+ $filter = 'bp_activity_multiple_at_mentions_notification';
 
285
  } else {
286
+ $user_fullname = bp_core_get_user_displayname( $poster_user_id );
287
+ $text = sprintf( __( '%1$s mentioned you', 'buddypress' ), $user_fullname );
288
+ $filter = 'bp_activity_single_at_mentions_notification';
289
  }
290
  break;
291
  }
292
 
293
  if ( 'string' == $format ) {
294
+ $return = apply_filters( $filter, '<a href="' . esc_url( $at_mention_link ) . '" title="' . esc_attr( $at_mention_title ) . '">' . esc_html( $text ) . '</a>', $at_mention_link, (int) $total_items, $activity_id, $poster_user_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  } else {
296
+ $return = apply_filters( $filter, array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  'text' => $text,
298
+ 'link' => $at_mention_link
299
+ ), $at_mention_link, (int) $total_items, $activity_id, $poster_user_id );
300
  }
301
 
 
 
 
 
 
 
 
 
 
 
302
  do_action( 'activity_format_notifications', $action, $item_id, $secondary_item_id, $total_items );
303
 
304
  return $return;
312
  * future when we separate emails from Notifications, this will need its own
313
  * 'bp_activity_at_name_send_emails' equivalent helper function.
314
  *
315
+ * @since BuddyPress (1.9.0)
316
  *
317
+ * @param obj $activity
318
+ * @param string $subject (not used)
319
+ * @param string $message (not used)
320
+ * @param string $content (not used)
321
+ * @param int $receiver_user_id
322
  */
323
  function bp_activity_at_mention_add_notification( $activity, $subject, $message, $content, $receiver_user_id ) {
324
+ if ( bp_is_active( 'notifications' ) ) {
325
+ bp_notifications_add_notification( array(
326
  'user_id' => $receiver_user_id,
327
  'item_id' => $activity->id,
328
  'secondary_item_id' => $activity->user_id,
330
  'component_action' => 'new_at_mention',
331
  'date_notified' => bp_core_current_time(),
332
  'is_new' => 1,
333
+ ) );
334
+ }
335
  }
336
  add_action( 'bp_activity_sent_mention_email', 'bp_activity_at_mention_add_notification', 10, 5 );
337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  /**
339
  * Mark at-mention notifications as read when users visit their Mentions page.
340
  *
341
+ * @since BuddyPress (1.5)
 
342
  *
343
+ * @uses bp_notifications_mark_all_notifications_by_type()
344
  */
345
+ function bp_activity_remove_screen_notifications() {
346
+ if ( ! bp_is_active( 'notifications' ) ) {
 
347
  return;
348
  }
349
 
350
+ // Only mark read if you're looking at your own mentions
351
+ if ( ! bp_is_my_profile() ) {
352
+ return;
353
+ }
354
+
355
+ bp_notifications_mark_notifications_by_type( bp_loggedin_user_id(), buddypress()->activity->id, 'new_at_mention' );
356
  }
357
+ add_action( 'bp_activity_screen_mentions', 'bp_activity_remove_screen_notifications' );
358
 
359
  /**
360
  * Mark at-mention notification as read when user visits the activity with the mention.
361
  *
362
+ * @since BuddyPress (2.0.0)
 
 
363
  */
364
  function bp_activity_remove_screen_notifications_single_activity_permalink( $activity ) {
365
+ if ( ! bp_is_active( 'notifications' ) ) {
366
  return;
367
  }
368
 
369
+ if ( ! is_user_logged_in() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  return;
371
  }
372
 
373
+ // Mark as read any notifications for the current user related to this
374
+ // activity item
375
+ bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), $activity->id, buddypress()->activity->id, 'new_at_mention' );
 
 
 
 
 
 
 
376
  }
377
+ add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_screen_notifications_single_activity_permalink' );
378
 
379
  /**
380
  * Delete at-mention notifications when the corresponding activity item is deleted.
381
  *
382
+ * @since BuddyPress (2.0.0)
383
  *
384
  * @param array $activity_ids_deleted IDs of deleted activity items.
385
  */
386
  function bp_activity_at_mention_delete_notification( $activity_ids_deleted = array() ) {
387
  // Let's delete all without checking if content contains any mentions
388
+ // to avoid a query to get the activity
389
+ if ( bp_is_active( 'notifications' ) && ! empty( $activity_ids_deleted ) ) {
390
  foreach ( $activity_ids_deleted as $activity_id ) {
391
  bp_notifications_delete_all_notifications_by_type( $activity_id, buddypress()->activity->id );
392
  }
393
  }
394
  }
395
  add_action( 'bp_activity_deleted_activities', 'bp_activity_at_mention_delete_notification', 10 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-screens.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Activity Screens.
4
  *
@@ -8,36 +9,30 @@
8
  *
9
  * @package BuddyPress
10
  * @subpackage ActivityScreens
11
- * @since 1.5.0
12
  */
13
 
14
- // Exit if accessed directly.
15
- defined( 'ABSPATH' ) || exit;
16
 
17
  /**
18
  * Load the Activity directory.
19
  *
20
- * @since 1.5.0
21
  *
 
 
 
 
 
 
 
22
  */
23
  function bp_activity_screen_index() {
24
  if ( bp_is_activity_directory() ) {
25
  bp_update_is_directory( true, 'activity' );
26
 
27
- /**
28
- * Fires right before the loading of the Activity directory screen template file.
29
- *
30
- * @since 1.5.0
31
- */
32
  do_action( 'bp_activity_screen_index' );
33
 
34
- /**
35
- * Filters the template to load for the Activity directory screen.
36
- *
37
- * @since 1.5.0
38
- *
39
- * @param string $template Path to the activity template to load.
40
- */
41
  bp_core_load_template( apply_filters( 'bp_activity_screen_index', 'activity/index' ) );
42
  }
43
  }
@@ -46,143 +41,101 @@ add_action( 'bp_screens', 'bp_activity_screen_index' );
46
  /**
47
  * Load the 'My Activity' page.
48
  *
49
- * @since 1.0.0
50
  *
 
 
 
51
  */
52
  function bp_activity_screen_my_activity() {
53
-
54
- /**
55
- * Fires right before the loading of the "My Activity" screen template file.
56
- *
57
- * @since 1.0.0
58
- */
59
  do_action( 'bp_activity_screen_my_activity' );
60
-
61
- /**
62
- * Filters the template to load for the "My Activity" screen.
63
- *
64
- * @since 1.0.0
65
- *
66
- * @param string $template Path to the activity template to load.
67
- */
68
  bp_core_load_template( apply_filters( 'bp_activity_template_my_activity', 'members/single/home' ) );
69
  }
70
 
71
  /**
72
  * Load the 'My Friends' activity page.
73
  *
74
- * @since 1.0.0
75
  *
 
 
 
 
 
 
76
  */
77
  function bp_activity_screen_friends() {
78
  if ( !bp_is_active( 'friends' ) )
79
  return false;
80
 
81
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
82
-
83
- /**
84
- * Fires right before the loading of the "My Friends" screen template file.
85
- *
86
- * @since 1.2.0
87
- */
88
  do_action( 'bp_activity_screen_friends' );
89
-
90
- /**
91
- * Filters the template to load for the "My Friends" screen.
92
- *
93
- * @since 1.0.0
94
- *
95
- * @param string $template Path to the activity template to load.
96
- */
97
  bp_core_load_template( apply_filters( 'bp_activity_template_friends_activity', 'members/single/home' ) );
98
  }
99
 
100
  /**
101
  * Load the 'My Groups' activity page.
102
  *
103
- * @since 1.2.0
104
  *
 
 
 
 
 
 
105
  */
106
  function bp_activity_screen_groups() {
107
  if ( !bp_is_active( 'groups' ) )
108
  return false;
109
 
110
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
111
-
112
- /**
113
- * Fires right before the loading of the "My Groups" screen template file.
114
- *
115
- * @since 1.2.0
116
- */
117
  do_action( 'bp_activity_screen_groups' );
118
-
119
- /**
120
- * Filters the template to load for the "My Groups" screen.
121
- *
122
- * @since 1.2.0
123
- *
124
- * @param string $template Path to the activity template to load.
125
- */
126
  bp_core_load_template( apply_filters( 'bp_activity_template_groups_activity', 'members/single/home' ) );
127
  }
128
 
129
  /**
130
  * Load the 'Favorites' activity page.
131
  *
132
- * @since 1.2.0
133
  *
 
 
 
 
 
134
  */
135
  function bp_activity_screen_favorites() {
136
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
137
-
138
- /**
139
- * Fires right before the loading of the "Favorites" screen template file.
140
- *
141
- * @since 1.2.0
142
- */
143
  do_action( 'bp_activity_screen_favorites' );
144
-
145
- /**
146
- * Filters the template to load for the "Favorites" screen.
147
- *
148
- * @since 1.2.0
149
- *
150
- * @param string $template Path to the activity template to load.
151
- */
152
  bp_core_load_template( apply_filters( 'bp_activity_template_favorite_activity', 'members/single/home' ) );
153
  }
154
 
155
  /**
156
  * Load the 'Mentions' activity page.
157
  *
158
- * @since 1.2.0
159
  *
 
 
 
 
 
160
  */
161
  function bp_activity_screen_mentions() {
162
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
163
-
164
- /**
165
- * Fires right before the loading of the "Mentions" screen template file.
166
- *
167
- * @since 1.2.0
168
- */
169
  do_action( 'bp_activity_screen_mentions' );
170
-
171
- /**
172
- * Filters the template to load for the "Mentions" screen.
173
- *
174
- * @since 1.2.0
175
- *
176
- * @param string $template Path to the activity template to load.
177
- */
178
  bp_core_load_template( apply_filters( 'bp_activity_template_mention_activity', 'members/single/home' ) );
179
  }
180
 
181
  /**
182
  * Reset the logged-in user's new mentions data when he visits his mentions screen.
183
  *
184
- * @since 1.5.0
185
  *
 
 
 
186
  */
187
  function bp_activity_reset_my_new_mentions() {
188
  if ( bp_is_my_profile() )
@@ -193,20 +146,40 @@ add_action( 'bp_activity_screen_mentions', 'bp_activity_reset_my_new_mentions' )
193
  /**
194
  * Load the page for a single activity item.
195
  *
196
- * @since 1.2.0
197
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  */
199
  function bp_activity_screen_single_activity_permalink() {
200
- $bp = buddypress();
201
 
202
- // No displayed user or not viewing activity component.
203
  if ( !bp_is_activity_component() )
204
  return false;
205
 
206
  if ( ! bp_current_action() || !is_numeric( bp_current_action() ) )
207
  return false;
208
 
209
- // Get the activity details.
210
  $activity = bp_activity_get_specific( array( 'activity_ids' => bp_current_action(), 'show_hidden' => true, 'spam' => 'ham_only', ) );
211
 
212
  // 404 if activity does not exist
@@ -218,26 +191,26 @@ function bp_activity_screen_single_activity_permalink() {
218
  $activity = $activity['activities'][0];
219
  }
220
 
221
- // Default access is true.
222
  $has_access = true;
223
 
224
- // If activity is from a group, do an extra cap check.
225
  if ( isset( $bp->groups->id ) && $activity->component == $bp->groups->id ) {
226
 
227
- // Activity is from a group, but groups is currently disabled.
228
  if ( !bp_is_active( 'groups') ) {
229
  bp_do_404();
230
  return;
231
  }
232
 
233
  // Check to see if the group is not public, if so, check the
234
- // user has access to see this activity.
235
- if ( $group = groups_get_group( $activity->item_id ) ) {
236
 
237
- // Group is not public.
238
  if ( 'public' != $group->status ) {
239
 
240
- // User is not a member of group.
241
  if ( !groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
242
  $has_access = false;
243
  }
@@ -245,57 +218,24 @@ function bp_activity_screen_single_activity_permalink() {
245
  }
246
  }
247
 
248
- // If activity author does not match displayed user, block access.
249
- if ( true === $has_access && bp_displayed_user_id() !== $activity->user_id ) {
250
- $has_access = false;
251
- }
252
-
253
- /**
254
- * Filters the access permission for a single activity view.
255
- *
256
- * @since 1.2.0
257
- *
258
- * @param array $access Array holding the current $has_access value and current activity item instance.
259
- */
260
  $has_access = apply_filters_ref_array( 'bp_activity_permalink_access', array( $has_access, &$activity ) );
261
 
262
- /**
263
- * Fires before the loading of a single activity template file.
264
- *
265
- * @since 1.2.0
266
- *
267
- * @param BP_Activity_Activity $activity Object representing the current activity item being displayed.
268
- * @param bool $has_access Whether or not the current user has access to view activity.
269
- */
270
  do_action( 'bp_activity_screen_single_activity_permalink', $activity, $has_access );
271
 
272
- // Access is specifically disallowed.
273
  if ( false === $has_access ) {
274
 
275
- // User feedback.
276
  bp_core_add_message( __( 'You do not have access to this activity.', 'buddypress' ), 'error' );
277
 
278
- // Redirect based on logged in status.
279
- if ( is_user_logged_in() ) {
280
- $url = bp_loggedin_user_domain();
281
-
282
- } else {
283
- $url = sprintf(
284
- site_url( 'wp-login.php?redirect_to=%s' ),
285
- urlencode( esc_url_raw( bp_activity_get_permalink( bp_current_action() ) ) )
286
- );
287
- }
288
-
289
- bp_core_redirect( $url );
290
  }
291
 
292
- /**
293
- * Filters the template to load for a single activity screen.
294
- *
295
- * @since 1.0.0
296
- *
297
- * @param string $template Path to the activity template to load.
298
- */
299
  bp_core_load_template( apply_filters( 'bp_activity_template_profile_activity_permalink', 'members/single/activity/permalink' ) );
300
  }
301
  add_action( 'bp_screens', 'bp_activity_screen_single_activity_permalink' );
@@ -303,8 +243,11 @@ add_action( 'bp_screens', 'bp_activity_screen_single_activity_permalink' );
303
  /**
304
  * Add activity notifications settings to the notifications settings page.
305
  *
306
- * @since 1.2.0
307
  *
 
 
 
308
  */
309
  function bp_activity_screen_notification_settings() {
310
 
@@ -335,38 +278,19 @@ function bp_activity_screen_notification_settings() {
335
  <tr id="activity-notification-settings-mentions">
336
  <td>&nbsp;</td>
337
  <td><?php printf( __( 'A member mentions you in an update using "@%s"', 'buddypress' ), bp_core_get_username( bp_displayed_user_id() ) ) ?></td>
338
- <td class="yes"><input type="radio" name="notifications[notification_activity_new_mention]" id="notification-activity-new-mention-yes" value="yes" <?php checked( $mention, 'yes', true ) ?>/><label for="notification-activity-new-mention-yes" class="bp-screen-reader-text"><?php
339
- /* translators: accessibility text */
340
- _e( 'Yes, send email', 'buddypress' );
341
- ?></label></td>
342
- <td class="no"><input type="radio" name="notifications[notification_activity_new_mention]" id="notification-activity-new-mention-no" value="no" <?php checked( $mention, 'no', true ) ?>/><label for="notification-activity-new-mention-no" class="bp-screen-reader-text"><?php
343
- /* translators: accessibility text */
344
- _e( 'No, do not send email', 'buddypress' );
345
- ?></label></td>
346
  </tr>
347
  <?php endif; ?>
348
 
349
  <tr id="activity-notification-settings-replies">
350
  <td>&nbsp;</td>
351
  <td><?php _e( "A member replies to an update or comment you've posted", 'buddypress' ) ?></td>
352
- <td class="yes"><input type="radio" name="notifications[notification_activity_new_reply]" id="notification-activity-new-reply-yes" value="yes" <?php checked( $reply, 'yes', true ) ?>/><label for="notification-activity-new-reply-yes" class="bp-screen-reader-text"><?php
353
- /* translators: accessibility text */
354
- _e( 'Yes, send email', 'buddypress' );
355
- ?></label></td>
356
- <td class="no"><input type="radio" name="notifications[notification_activity_new_reply]" id="notification-activity-new-reply-no" value="no" <?php checked( $reply, 'no', true ) ?>/><label for="notification-activity-new-reply-no" class="bp-screen-reader-text"><?php
357
- /* translators: accessibility text */
358
- _e( 'No, do not send email', 'buddypress' );
359
- ?></label></td>
360
  </tr>
361
 
362
- <?php
363
-
364
- /**
365
- * Fires inside the closing </tbody> tag for activity screen notification settings.
366
- *
367
- * @since 1.2.0
368
- */
369
- do_action( 'bp_activity_screen_notification_settings' ) ?>
370
  </tbody>
371
  </table>
372
 
@@ -374,6 +298,160 @@ function bp_activity_screen_notification_settings() {
374
  }
375
  add_action( 'bp_notification_settings', 'bp_activity_screen_notification_settings', 1 );
376
 
377
- /** Theme Compatibility *******************************************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  new BP_Activity_Theme_Compat();
1
  <?php
2
+
3
  /**
4
  * BuddyPress Activity Screens.
5
  *
9
  *
10
  * @package BuddyPress
11
  * @subpackage ActivityScreens
 
12
  */
13
 
14
+ // Exit if accessed directly
15
+ if ( !defined( 'ABSPATH' ) ) exit;
16
 
17
  /**
18
  * Load the Activity directory.
19
  *
20
+ * @since BuddyPress (1.5)
21
  *
22
+ * @uses bp_displayed_user_id()
23
+ * @uses bp_is_activity_component()
24
+ * @uses bp_current_action()
25
+ * @uses bp_update_is_directory()
26
+ * @uses do_action() To call the 'bp_activity_screen_index' hook.
27
+ * @uses bp_core_load_template()
28
+ * @uses apply_filters() To call the 'bp_activity_screen_index' hook.
29
  */
30
  function bp_activity_screen_index() {
31
  if ( bp_is_activity_directory() ) {
32
  bp_update_is_directory( true, 'activity' );
33
 
 
 
 
 
 
34
  do_action( 'bp_activity_screen_index' );
35
 
 
 
 
 
 
 
 
36
  bp_core_load_template( apply_filters( 'bp_activity_screen_index', 'activity/index' ) );
37
  }
38
  }
41
  /**
42
  * Load the 'My Activity' page.
43
  *
44
+ * @since BuddyPress (1.0)
45
  *
46
+ * @uses do_action() To call the 'bp_activity_screen_my_activity' hook.
47
+ * @uses bp_core_load_template()
48
+ * @uses apply_filters() To call the 'bp_activity_template_my_activity' hook.
49
  */
50
  function bp_activity_screen_my_activity() {
 
 
 
 
 
 
51
  do_action( 'bp_activity_screen_my_activity' );
 
 
 
 
 
 
 
 
52
  bp_core_load_template( apply_filters( 'bp_activity_template_my_activity', 'members/single/home' ) );
53
  }
54
 
55
  /**
56
  * Load the 'My Friends' activity page.
57
  *
58
+ * @since BuddyPress (1.0)
59
  *
60
+ * @uses bp_is_active()
61
+ * @uses bp_update_is_item_admin()
62
+ * @uses bp_current_user_can()
63
+ * @uses do_action() To call the 'bp_activity_screen_friends' hook.
64
+ * @uses bp_core_load_template()
65
+ * @uses apply_filters() To call the 'bp_activity_template_friends_activity' hook.
66
  */
67
  function bp_activity_screen_friends() {
68
  if ( !bp_is_active( 'friends' ) )
69
  return false;
70
 
71
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
 
 
 
 
 
 
72
  do_action( 'bp_activity_screen_friends' );
 
 
 
 
 
 
 
 
73
  bp_core_load_template( apply_filters( 'bp_activity_template_friends_activity', 'members/single/home' ) );
74
  }
75
 
76
  /**
77
  * Load the 'My Groups' activity page.
78
  *
79
+ * @since BuddyPress (1.2)
80
  *
81
+ * @uses bp_is_active()
82
+ * @uses bp_update_is_item_admin()
83
+ * @uses bp_current_user_can()
84
+ * @uses do_action() To call the 'bp_activity_screen_groups' hook
85
+ * @uses bp_core_load_template()
86
+ * @uses apply_filters() To call the 'bp_activity_template_groups_activity' hook
87
  */
88
  function bp_activity_screen_groups() {
89
  if ( !bp_is_active( 'groups' ) )
90
  return false;
91
 
92
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
 
 
 
 
 
 
93
  do_action( 'bp_activity_screen_groups' );
 
 
 
 
 
 
 
 
94
  bp_core_load_template( apply_filters( 'bp_activity_template_groups_activity', 'members/single/home' ) );
95
  }
96
 
97
  /**
98
  * Load the 'Favorites' activity page.
99
  *
100
+ * @since BuddyPress (1.2)
101
  *
102
+ * @uses bp_update_is_item_admin()
103
+ * @uses bp_current_user_can()
104
+ * @uses do_action() To call the 'bp_activity_screen_favorites' hook
105
+ * @uses bp_core_load_template()
106
+ * @uses apply_filters() To call the 'bp_activity_template_favorite_activity' hook
107
  */
108
  function bp_activity_screen_favorites() {
109
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
 
 
 
 
 
 
110
  do_action( 'bp_activity_screen_favorites' );
 
 
 
 
 
 
 
 
111
  bp_core_load_template( apply_filters( 'bp_activity_template_favorite_activity', 'members/single/home' ) );
112
  }
113
 
114
  /**
115
  * Load the 'Mentions' activity page.
116
  *
117
+ * @since BuddyPress (1.2)
118
  *
119
+ * @uses bp_update_is_item_admin()
120
+ * @uses bp_current_user_can()
121
+ * @uses do_action() To call the 'bp_activity_screen_mentions' hook
122
+ * @uses bp_core_load_template()
123
+ * @uses apply_filters() To call the 'bp_activity_template_mention_activity' hook
124
  */
125
  function bp_activity_screen_mentions() {
126
  bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
 
 
 
 
 
 
127
  do_action( 'bp_activity_screen_mentions' );
 
 
 
 
 
 
 
 
128
  bp_core_load_template( apply_filters( 'bp_activity_template_mention_activity', 'members/single/home' ) );
129
  }
130
 
131
  /**
132
  * Reset the logged-in user's new mentions data when he visits his mentions screen.
133
  *
134
+ * @since BuddyPress (1.5)
135
  *
136
+ * @uses bp_is_my_profile()
137
+ * @uses bp_activity_clear_new_mentions()
138
+ * @uses bp_loggedin_user_id()
139
  */
140
  function bp_activity_reset_my_new_mentions() {
141
  if ( bp_is_my_profile() )
146
  /**
147
  * Load the page for a single activity item.
148
  *
149
+ * @since BuddyPress (1.2)
150
  *
151
+ * @global object $bp BuddyPress global settings
152
+ * @uses bp_is_activity_component()
153
+ * @uses bp_activity_get_specific()
154
+ * @uses bp_current_action()
155
+ * @uses bp_action_variables()
156
+ * @uses bp_do_404()
157
+ * @uses bp_is_active()
158
+ * @uses groups_get_group()
159
+ * @uses groups_is_user_member()
160
+ * @uses apply_filters_ref_array() To call the 'bp_activity_permalink_access' hook
161
+ * @uses do_action() To call the 'bp_activity_screen_single_activity_permalink' hook
162
+ * @uses bp_core_add_message()
163
+ * @uses is_user_logged_in()
164
+ * @uses bp_core_redirect()
165
+ * @uses site_url()
166
+ * @uses esc_url()
167
+ * @uses bp_get_root_domain()
168
+ * @uses bp_get_activity_root_slug()
169
+ * @uses bp_core_load_template()
170
+ * @uses apply_filters() To call the 'bp_activity_template_profile_activity_permalink' hook
171
  */
172
  function bp_activity_screen_single_activity_permalink() {
173
+ global $bp;
174
 
175
+ // No displayed user or not viewing activity component
176
  if ( !bp_is_activity_component() )
177
  return false;
178
 
179
  if ( ! bp_current_action() || !is_numeric( bp_current_action() ) )
180
  return false;
181
 
182
+ // Get the activity details
183
  $activity = bp_activity_get_specific( array( 'activity_ids' => bp_current_action(), 'show_hidden' => true, 'spam' => 'ham_only', ) );
184
 
185
  // 404 if activity does not exist
191
  $activity = $activity['activities'][0];
192
  }
193
 
194
+ // Default access is true
195
  $has_access = true;
196
 
197
+ // If activity is from a group, do an extra cap check
198
  if ( isset( $bp->groups->id ) && $activity->component == $bp->groups->id ) {
199
 
200
+ // Activity is from a group, but groups is currently disabled
201
  if ( !bp_is_active( 'groups') ) {
202
  bp_do_404();
203
  return;
204
  }
205
 
206
  // Check to see if the group is not public, if so, check the
207
+ // user has access to see this activity
208
+ if ( $group = groups_get_group( array( 'group_id' => $activity->item_id ) ) ) {
209
 
210
+ // Group is not public
211
  if ( 'public' != $group->status ) {
212
 
213
+ // User is not a member of group
214
  if ( !groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
215
  $has_access = false;
216
  }
218
  }
219
  }
220
 
221
+ // Allow access to be filtered
 
 
 
 
 
 
 
 
 
 
 
222
  $has_access = apply_filters_ref_array( 'bp_activity_permalink_access', array( $has_access, &$activity ) );
223
 
224
+ // Allow additional code execution
 
 
 
 
 
 
 
225
  do_action( 'bp_activity_screen_single_activity_permalink', $activity, $has_access );
226
 
227
+ // Access is specifically disallowed
228
  if ( false === $has_access ) {
229
 
230
+ // User feedback
231
  bp_core_add_message( __( 'You do not have access to this activity.', 'buddypress' ), 'error' );
232
 
233
+ // Redirect based on logged in status
234
+ is_user_logged_in() ?
235
+ bp_core_redirect( bp_loggedin_user_domain() ) :
236
+ bp_core_redirect( site_url( 'wp-login.php?redirect_to=' . esc_url( bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . bp_current_action() . '/' ) ) );
 
 
 
 
 
 
 
 
237
  }
238
 
 
 
 
 
 
 
 
239
  bp_core_load_template( apply_filters( 'bp_activity_template_profile_activity_permalink', 'members/single/activity/permalink' ) );
240
  }
241
  add_action( 'bp_screens', 'bp_activity_screen_single_activity_permalink' );
243
  /**
244
  * Add activity notifications settings to the notifications settings page.
245
  *
246
+ * @since BuddyPress (1.2)
247
  *
248
+ * @uses bp_get_user_meta()
249
+ * @uses bp_core_get_username()
250
+ * @uses do_action() To call the 'bp_activity_screen_notification_settings' hook.
251
  */
252
  function bp_activity_screen_notification_settings() {
253
 
278
  <tr id="activity-notification-settings-mentions">
279
  <td>&nbsp;</td>
280
  <td><?php printf( __( 'A member mentions you in an update using "@%s"', 'buddypress' ), bp_core_get_username( bp_displayed_user_id() ) ) ?></td>
281
+ <td class="yes"><input type="radio" name="notifications[notification_activity_new_mention]" value="yes" <?php checked( $mention, 'yes', true ) ?>/></td>
282
+ <td class="no"><input type="radio" name="notifications[notification_activity_new_mention]" value="no" <?php checked( $mention, 'no', true ) ?>/></td>
 
 
 
 
 
 
283
  </tr>
284
  <?php endif; ?>
285
 
286
  <tr id="activity-notification-settings-replies">
287
  <td>&nbsp;</td>
288
  <td><?php _e( "A member replies to an update or comment you've posted", 'buddypress' ) ?></td>
289
+ <td class="yes"><input type="radio" name="notifications[notification_activity_new_reply]" value="yes" <?php checked( $reply, 'yes', true ) ?>/></td>
290
+ <td class="no"><input type="radio" name="notifications[notification_activity_new_reply]" value="no" <?php checked( $reply, 'no', true ) ?>/></td>
 
 
 
 
 
 
291
  </tr>
292
 
293
+ <?php do_action( 'bp_activity_screen_notification_settings' ) ?>
 
 
 
 
 
 
 
294
  </tbody>
295
  </table>
296
 
298
  }
299
  add_action( 'bp_notification_settings', 'bp_activity_screen_notification_settings', 1 );
300
 
301
+ /** Theme Compatability *******************************************************/
302
+
303
+ /**
304
+ * The main theme compat class for BuddyPress Activity.
305
+ *
306
+ * This class sets up the necessary theme compatability actions to safely output
307
+ * activity template parts to the_title and the_content areas of a theme.
308
+ *
309
+ * @since BuddyPress (1.7)
310
+ */
311
+ class BP_Activity_Theme_Compat {
312
+
313
+ /**
314
+ * Set up the activity component theme compatibility.
315
+ *
316
+ * @since BuddyPress (1.7)
317
+ */
318
+ public function __construct() {
319
+ add_action( 'bp_setup_theme_compat', array( $this, 'is_activity' ) );
320
+ }
321
+
322
+ /**
323
+ * Set up the theme compatibility hooks, if we're looking at an activity page.
324
+ *
325
+ * @since BuddyPress (1.7)
326
+ */
327
+ public function is_activity() {
328
+
329
+ // Bail if not looking at a group
330
+ if ( ! bp_is_activity_component() )
331
+ return;
332
+
333
+ // Activity Directory
334
+ if ( ! bp_displayed_user_id() && ! bp_current_action() ) {
335
+ bp_update_is_directory( true, 'activity' );
336
+
337
+ do_action( 'bp_activity_screen_index' );
338
+
339
+ add_filter( 'bp_get_buddypress_template', array( $this, 'directory_template_hierarchy' ) );
340
+ add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'directory_dummy_post' ) );
341
+ add_filter( 'bp_replace_the_content', array( $this, 'directory_content' ) );
342
+
343
+ // Single activity
344
+ } elseif ( bp_is_single_activity() ) {
345
+ add_filter( 'bp_get_buddypress_template', array( $this, 'single_template_hierarchy' ) );
346
+ add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'single_dummy_post' ) );
347
+ add_filter( 'bp_replace_the_content', array( $this, 'single_dummy_content' ) );
348
+ }
349
+ }
350
+
351
+ /** Directory *************************************************************/
352
 
353
+ /**
354
+ * Add template hierarchy to theme compat for the activity directory page.
355
+ *
356
+ * This is to mirror how WordPress has {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
357
+ *
358
+ * @since BuddyPress (1.8)
359
+ *
360
+ * @param string $templates The templates from bp_get_theme_compat_templates().
361
+ * @return array $templates Array of custom templates to look for.
362
+ */
363
+ public function directory_template_hierarchy( $templates ) {
364
+ // Setup our templates based on priority
365
+ $new_templates = apply_filters( 'bp_template_hierarchy_activity_directory', array(
366
+ 'activity/index-directory.php'
367
+ ) );
368
+
369
+ // Merge new templates with existing stack
370
+ // @see bp_get_theme_compat_templates()
371
+ $templates = array_merge( (array) $new_templates, $templates );
372
+
373
+ return $templates;
374
+ }
375
+
376
+ /**
377
+ * Update the global $post with directory data.
378
+ *
379
+ * @since BuddyPress (1.7)
380
+ */
381
+ public function directory_dummy_post() {
382
+ bp_theme_compat_reset_post( array(
383
+ 'ID' => 0,
384
+ 'post_title' => bp_get_directory_title( 'activity' ),
385
+ 'post_author' => 0,
386
+ 'post_date' => 0,
387
+ 'post_content' => '',
388
+ 'post_type' => 'bp_activity',
389
+ 'post_status' => 'publish',
390
+ 'is_page' => true,
391
+ 'comment_status' => 'closed'
392
+ ) );
393
+ }
394
+
395
+ /**
396
+ * Filter the_content with the groups index template part.
397
+ *
398
+ * @since BuddyPress (1.7)
399
+ */
400
+ public function directory_content() {
401
+ return bp_buffer_template_part( 'activity/index', null, false );
402
+ }
403
+
404
+ /** Single ****************************************************************/
405
+
406
+ /**
407
+ * Add custom template hierarchy to theme compat for activity permalink pages.
408
+ *
409
+ * This is to mirror how WordPress has {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
410
+ *
411
+ * @since BuddyPress (1.8)
412
+ *
413
+ * @param string $templates The templates from bp_get_theme_compat_templates().
414
+ * @return array $templates Array of custom templates to look for.
415
+ */
416
+ public function single_template_hierarchy( $templates ) {
417
+ // Setup our templates based on priority
418
+ $new_templates = apply_filters( 'bp_template_hierarchy_activity_single_item', array(
419
+ 'activity/single/index.php'
420
+ ) );
421
+
422
+ // Merge new templates with existing stack
423
+ // @see bp_get_theme_compat_templates()
424
+ $templates = array_merge( (array) $new_templates, $templates );
425
+
426
+ return $templates;
427
+ }
428
+
429
+ /**
430
+ * Update the global $post with the displayed user's data.
431
+ *
432
+ * @since BuddyPress (1.7)
433
+ */
434
+ public function single_dummy_post() {
435
+ bp_theme_compat_reset_post( array(
436
+ 'ID' => 0,
437
+ 'post_title' => __( 'Activity', 'buddypress' ),
438
+ 'post_author' => 0,
439
+ 'post_date' => 0,
440
+ 'post_content' => '',
441
+ 'post_type' => 'bp_activity',
442
+ 'post_status' => 'publish',
443
+ 'is_page' => true,
444
+ 'comment_status' => 'closed'
445
+ ) );
446
+ }
447
+
448
+ /**
449
+ * Filter the_content with the members' activity permalink template part.
450
+ *
451
+ * @since BuddyPress (1.7)
452
+ */
453
+ public function single_dummy_content() {
454
+ return bp_buffer_template_part( 'activity/single/home', null, false );
455
+ }
456
+ }
457
  new BP_Activity_Theme_Compat();
bp-activity/bp-activity-template.php CHANGED
@@ -1,20 +1,21 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Activity Template Functions.
4
  *
5
  * @package BuddyPress
6
  * @subpackage ActivityTemplate
7
- * @since 1.5.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Output the activity component slug.
15
  *
16
- * @since 1.5.0
17
  *
 
18
  */
19
  function bp_activity_slug() {
20
  echo bp_get_activity_slug();
@@ -22,28 +23,22 @@ function bp_activity_slug() {
22
  /**
23
  * Return the activity component slug.
24
  *
25
- * @since 1.5.0
26
  *
 
27
  *
28
  * @return string The activity component slug.
29
  */
30
  function bp_get_activity_slug() {
31
-
32
- /**
33
- * Filters the activity component slug.
34
- *
35
- * @since 1.5.0
36
- *
37
- * @param string $slug Activity component slug.
38
- */
39
  return apply_filters( 'bp_get_activity_slug', buddypress()->activity->slug );
40
  }
41
 
42
  /**
43
  * Output the activity component root slug.
44
  *
45
- * @since 1.5.0
46
  *
 
47
  */
48
  function bp_activity_root_slug() {
49
  echo bp_get_activity_root_slug();
@@ -51,52 +46,313 @@ function bp_activity_root_slug() {
51
  /**
52
  * Return the activity component root slug.
53
  *
54
- * @since 1.5.0
55
  *
 
56
  *
57
  * @return string The activity component root slug.
58
  */
59
  function bp_get_activity_root_slug() {
60
-
61
- /**
62
- * Filters the activity component root slug.
63
- *
64
- * @since 1.5.0
65
- *
66
- * @param string $root_slug Activity component root slug.
67
- */
68
  return apply_filters( 'bp_get_activity_root_slug', buddypress()->activity->root_slug );
69
  }
70
 
71
  /**
72
  * Output activity directory permalink.
73
  *
74
- * @since 1.5.0
75
  *
 
76
  */
77
  function bp_activity_directory_permalink() {
78
- echo esc_url( bp_get_activity_directory_permalink() );
79
  }
80
  /**
81
- * Return activity directory permalink.
82
  *
83
- * @since 1.5.0
84
  *
 
 
 
 
85
  *
86
  * @return string Activity directory permalink.
87
  */
88
  function bp_get_activity_directory_permalink() {
89
-
90
- /**
91
- * Filters the activity directory permalink.
92
- *
93
- * @since 1.5.0
94
- *
95
- * @param string $url Permalink url for the activity directory.
96
- */
97
  return apply_filters( 'bp_get_activity_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_activity_root_slug() ) );
98
  }
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  /**
101
  * Initialize the activity loop.
102
  *
@@ -104,268 +360,327 @@ function bp_activity_directory_permalink() {
104
  * $activities_template global, enabling the use of BuddyPress templates and
105
  * template functions to display a list of activity items.
106
  *
107
- * @since 1.0.0
108
- * @since 2.4.0 Introduced the `$fields` parameter.
109
  *
110
  * @global object $activities_template {@link BP_Activity_Template}
111
- *
112
- * @param array|string $args {
113
- * Arguments for limiting the contents of the activity loop. Most arguments
114
- * are in the same format as {@link BP_Activity_Activity::get()}. However,
115
- * because the format of the arguments accepted here differs in a number of
116
- * ways, and because bp_has_activities() determines some default arguments in
117
- * a dynamic fashion, we list all accepted arguments here as well.
118
- *
119
- * Arguments can be passed as an associative array, or as a URL querystring
120
- * (eg, 'user_id=4&display_comments=threaded').
121
- *
122
- * @type int $page Which page of results to fetch. Using page=1 without per_page will result
123
- * in no pagination. Default: 1.
124
- * @type int|bool $per_page Number of results per page. Default: 20.
125
- * @type string $page_arg String used as a query parameter in pagination links. Default: 'acpage'.
126
- * @type int|bool $max Maximum number of results to return. Default: false (unlimited).
127
- * @type string $fields Activity fields to retrieve. 'all' to fetch entire activity objects,
128
- * 'ids' to get only the activity IDs. Default 'all'.
129
- * @type string|bool $count_total If true, an additional DB query is run to count the total activity items
130
- * for the query. Default: false.
131
- * @type string $sort 'ASC' or 'DESC'. Default: 'DESC'.
132
- * @type array|bool $exclude Array of activity IDs to exclude. Default: false.
133
- * @type array|bool $in Array of IDs to limit query by (IN). 'in' is intended to be used in
134
- * conjunction with other filter parameters. Default: false.
135
- * @type array|bool $include Array of exact activity IDs to query. Providing an 'include' array will
136
- * override all other filters passed in the argument array. When viewing the
137
- * permalink page for a single activity item, this value defaults to the ID of
138
- * that item. Otherwise the default is false.
139
- * @type array $meta_query Limit by activitymeta by passing an array of meta_query conditions. See
140
- * {@link WP_Meta_Query::queries} for a description of the syntax.
141
- * @type array $date_query Limit by date by passing an array of date_query conditions. See first
142
- * parameter of {@link WP_Date_Query::__construct()} for syntax.
143
- * @type array $filter_query Advanced activity filtering. See {@link BP_Activity_Query::__construct()}.
144
- * @type string $search_terms Limit results by a search term. Default: false.
145
- * @type string $scope Use a BuddyPress pre-built filter.
146
- * - 'just-me' retrieves items belonging only to a user; this is equivalent
147
- * to passing a 'user_id' argument.
148
- * - 'friends' retrieves items belonging to the friends of a user.
149
- * - 'groups' retrieves items belonging to groups to which a user belongs to.
150
- * - 'favorites' retrieves a user's favorited activity items.
151
- * - 'mentions' retrieves items where a user has received an @-mention.
152
- * The default value of 'scope' is set to one of the above if that value
153
- * appears in the appropriate place in the URL; eg, 'scope' will be 'groups'
154
- * when visiting http://example.com/members/joe/activity/groups/. Otherwise
155
- * defaults to false.
156
- * @type int|array|bool $user_id The ID(s) of user(s) whose activity should be fetched. Pass a single ID or
157
- * an array of IDs. When viewing a user profile page (but not that user's
158
- * activity subpages, ie My Friends, My Groups, etc), 'user_id' defaults to
159
- * the ID of the displayed user. Otherwise the default is false.
160
- * @type string|array|bool $object Filters by the `component` column in the database, which is generally the
161
- * component ID in the case of BuddyPress components, or the plugin slug in
162
- * the case of plugins. For example, 'groups' will limit results to those that
163
- * are associated with the BP Groups component. Accepts a single component
164
- * string, or an array of multiple components. Defaults to 'groups' when
165
- * viewing the page of a single group, the My Groups activity filter, or the
166
- * Activity > Groups filter of a user profile. Otherwise defaults to false.
167
- * @type string|array|bool $action Filters by the `type` column in the database, which is a string
168
- * categorizing the activity item (eg, 'new_blog_post', 'created_group').
169
- * Accepts a comma-delimited string or an array of types. Default: false.
170
- * @type int|array|bool $primary_id Filters by the `item_id` column in the database. The meaning of
171
- * 'primary_id' differs between components/types; for example, in the case of
172
- * 'created_group', 'primary_id' is the ID of the group. Accepts a single ID,
173
- * or an array of multiple IDs. When viewing a single group, defaults to the
174
- * current group ID. When viewing a user's Groups stream page, defaults to the
175
- * IDs of the user's groups. Otherwise defaults to false.
176
- * @type int|array|bool $secondary_id Filters by the `secondary_item_id` column in the database. The meaning of
177
- * 'secondary_id' differs between components/types. Accepts a single ID, or an
178
- * array of multiple IDs. Defaults to false.
179
- * @type int $offset Return only activity items with an ID greater than or equal to this one.
180
- * Note that providing an offset will disable pagination. Default: false.
181
- * @type string|bool $display_comments How to handle activity comments. Possible values:
182
- * - 'threaded' - comments appear in a threaded tree, under their parent
183
- * items.
184
- * - 'stream' - the activity stream is presented in a flat manner, with
185
- * comments sorted in chronological order alongside other activity items.
186
- * - false - don't fetch activity comments at all.
187
- * Default: 'threaded'.
188
- * @type bool $show_hidden Whether to show items marked hide_sitewide. Defaults to false, except in
189
- * the following cases:
190
- * - User is viewing his own activity stream.
191
- * - User is viewing the activity stream of a non-public group of which he
192
- * is a member.
193
- * @type string|bool $spam Spam status. 'ham_only', 'spam_only', or false to show all activity
194
- * regardless of spam status. Default: 'ham_only'.
195
- * @type bool $populate_extras Whether to pre-fetch the activity metadata for the queried items.
196
- * Default: true.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  * }
198
  * @return bool Returns true when activities are found, otherwise false.
199
  */
200
  function bp_has_activities( $args = '' ) {
201
- global $activities_template;
202
-
203
- // Get BuddyPress.
204
- $bp = buddypress();
205
-
206
- /*
207
- * Smart Defaults.
208
- */
209
-
210
- // User filtering.
211
- $user_id = bp_displayed_user_id()
212
- ? bp_displayed_user_id()
213
- : false;
214
-
215
- // Group filtering.
216
- if ( bp_is_group() ) {
217
- $object = $bp->groups->id;
218
- $primary_id = bp_get_current_group_id();
219
- $show_hidden = (bool) ( groups_is_user_member( bp_loggedin_user_id(), $primary_id ) || bp_current_user_can( 'bp_moderate' ) );
220
- } else {
221
- $object = false;
222
- $primary_id = false;
223
- $show_hidden = false;
224
- }
225
-
226
- // The default scope should recognize custom slugs.
227
- $scope = array_key_exists( bp_current_action(), (array) $bp->loaded_components )
228
- ? $bp->loaded_components[ bp_current_action() ]
229
- : bp_current_action();
230
-
231
- // Support for permalinks on single item pages: /groups/my-group/activity/124/.
232
- $include = bp_is_current_action( bp_get_activity_slug() )
233
- ? bp_action_variable( 0 )
234
- : false;
235
-
236
- $search_terms_default = false;
237
- $search_query_arg = bp_core_get_component_search_query_arg( 'activity' );
238
- if ( ! empty( $_REQUEST[ $search_query_arg ] ) ) {
239
- $search_terms_default = stripslashes( $_REQUEST[ $search_query_arg ] );
240
- }
241
-
242
- /*
243
- * Parse Args.
244
- */
245
-
246
- // Note: any params used for filtering can be a single value, or multiple
247
- // values comma separated.
248
- $r = bp_parse_args( $args, array(
249
- 'display_comments' => 'threaded', // False for none, stream/threaded - show comments in the stream or threaded under items.
250
- 'include' => $include, // Pass an activity_id or string of IDs comma-separated.
251
- 'exclude' => false, // Pass an activity_id or string of IDs comma-separated.
252
- 'in' => false, // Comma-separated list or array of activity IDs among which to search.
253
- 'sort' => 'DESC', // Sort DESC or ASC.
254
- 'page' => 1, // Which page to load.
255
- 'per_page' => 20, // Number of items per page.
256
- 'page_arg' => 'acpage', // See https://buddypress.trac.wordpress.org/ticket/3679.
257
- 'max' => false, // Max number to return.
258
- 'fields' => 'all',
259
- 'count_total' => false,
260
  'show_hidden' => $show_hidden, // Show activity items that are hidden site-wide?
261
- 'spam' => 'ham_only', // Hide spammed items.
262
 
263
- // Scope - pre-built activity filters for a user (friends/groups/favorites/mentions).
 
 
264
  'scope' => $scope,
265
 
266
  // Filtering
267
- 'user_id' => $user_id, // user_id to filter on.
268
- 'object' => $object, // Object to filter on e.g. groups, profile, status, friends.
269
- 'action' => false, // Action to filter on e.g. activity_update, new_forum_post, profile_updated.
270
- 'primary_id' => $primary_id, // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
271
- 'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
272
- 'offset' => false, // Return only items >= this ID.
273
- 'since' => false, // Return only items recorded since this Y-m-d H:i:s date.
274
-
275
- 'meta_query' => false, // Filter on activity meta. See WP_Meta_Query for format.
276
- 'date_query' => false, // Filter by date. See first parameter of WP_Date_Query for format.
277
- 'filter_query' => false, // Advanced filtering. See BP_Activity_Query for format.
278
-
279
- // Searching.
280
- 'search_terms' => $search_terms_default,
281
  'update_meta_cache' => true,
282
- ), 'has_activities' );
283
 
284
- /*
285
- * Smart Overrides.
286
- */
287
 
288
  // Translate various values for 'display_comments'
289
  // This allows disabling comments via ?display_comments=0
290
- // or =none or =false. Final true is a strict type check. See #5029.
291
- if ( in_array( $r['display_comments'], array( 0, '0', 'none', 'false' ), true ) ) {
292
- $r['display_comments'] = false;
293
  }
294
 
295
- // Ignore pagination if an offset is passed.
296
- if ( ! empty( $r['offset'] ) ) {
297
- $r['page'] = 0;
298
  }
299
 
300
- // Search terms.
301
- if ( ! empty( $_REQUEST['s'] ) && empty( $r['search_terms'] ) ) {
302
- $r['search_terms'] = $_REQUEST['s'];
303
- }
304
 
305
- // Do not exceed the maximum per page.
306
- if ( ! empty( $r['max'] ) && ( (int) $r['per_page'] > (int) $r['max'] ) ) {
307
- $r['per_page'] = $r['max'];
308
- }
309
 
310
- /**
311
- * Filters whether BuddyPress should enable afilter support.
312
- *
313
- * Support for basic filters in earlier BP versions is disabled by default.
314
- * To enable, put add_filter( 'bp_activity_enable_afilter_support', '__return_true' );
315
- * into bp-custom.php or your theme's functions.php.
316
- *
317
- * @since 1.6.0
318
- *
319
- * @param bool $value True if BuddyPress should enable afilter support.
320
- */
321
- if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) ) {
322
- $r['filter'] = array(
323
- 'object' => $_GET['afilter']
324
- );
325
- } 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'] ) ) {
326
- $r['filter'] = array(
327
- 'user_id' => $r['user_id'],
328
- 'object' => $r['object'],
329
- 'action' => $r['action'],
330
- 'primary_id' => $r['primary_id'],
331
- 'secondary_id' => $r['secondary_id'],
332
- 'offset' => $r['offset'],
333
- 'since' => $r['since']
334
- );
335
- } else {
336
- $r['filter'] = false;
337
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
 
339
- // If specific activity items have been requested, override the $hide_spam
340
- // argument. This prevents backpat errors with AJAX.
341
- if ( ! empty( $r['include'] ) && ( 'ham_only' === $r['spam'] ) ) {
342
- $r['spam'] = 'all';
 
 
 
343
  }
344
 
345
- /*
346
- * Query
347
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
 
349
- $activities_template = new BP_Activity_Template( $r );
350
 
351
- /**
352
- * Filters whether or not there are activity items to display.
353
- *
354
- * @since 1.1.0
355
- *
356
- * @param bool $value Whether or not there are activity items to display.
357
- * @param string $activities_template Current activities template being used.
358
- * @param array $r Array of arguments passed into the BP_Activity_Template class.
359
- */
360
- return apply_filters( 'bp_has_activities', $activities_template->has_activities(), $activities_template, $r );
361
  }
362
 
363
  /**
364
  * Determine if there are still activities left in the loop.
365
  *
366
- * @since 1.0.0
367
  *
368
  * @global object $activities_template {@link BP_Activity_Template}
 
369
  *
370
  * @return bool Returns true when activities are found.
371
  */
@@ -377,9 +692,10 @@ function bp_activities() {
377
  /**
378
  * Get the current activity object in the loop.
379
  *
380
- * @since 1.0.0
381
  *
382
  * @global object $activities_template {@link BP_Activity_Template}
 
383
  *
384
  * @return object The current activity within the loop.
385
  */
@@ -388,45 +704,13 @@ function bp_the_activity() {
388
  return $activities_template->the_activity();
389
  }
390
 
391
- /**
392
- * Output the URL for the Load More link.
393
- *
394
- * @since 2.1.0
395
- */
396
- function bp_activity_load_more_link() {
397
- echo esc_url( bp_get_activity_load_more_link() );
398
- }
399
- /**
400
- * Get the URL for the Load More link.
401
- *
402
- * @since 2.1.0
403
- *
404
- * @return string $link
405
- */
406
- function bp_get_activity_load_more_link() {
407
- global $activities_template;
408
-
409
- $url = bp_get_requested_url();
410
- $link = add_query_arg( $activities_template->pag_arg, $activities_template->pag_page + 1, $url );
411
-
412
- /**
413
- * Filters the Load More link URL.
414
- *
415
- * @since 2.1.0
416
- *
417
- * @param string $link The "Load More" link URL with appropriate query args.
418
- * @param string $url The original URL.
419
- * @param object $activities_template The activity template loop global.
420
- */
421
- return apply_filters( 'bp_get_activity_load_more_link', $link, $url, $activities_template );
422
- }
423
-
424
  /**
425
  * Output the activity pagination count.
426
  *
427
- * @since 1.0.0
428
  *
429
  * @global object $activities_template {@link BP_Activity_Template}
 
430
  */
431
  function bp_activity_pagination_count() {
432
  echo bp_get_activity_pagination_count();
@@ -435,9 +719,10 @@ function bp_activity_pagination_count() {
435
  /**
436
  * Return the activity pagination count.
437
  *
438
- * @since 1.2.0
439
  *
440
  * @global object $activities_template {@link BP_Activity_Template}
 
441
  *
442
  * @return string The pagination text.
443
  */
@@ -449,20 +734,15 @@ function bp_activity_pagination_count() {
449
  $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 ) );
450
  $total = bp_core_number_format( $activities_template->total_activity_count );
451
 
452
- if ( 1 == $activities_template->total_activity_count ) {
453
- $message = __( 'Viewing 1 item', 'buddypress' );
454
- } else {
455
- $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 );
456
- }
457
-
458
- return $message;
459
  }
460
 
461
  /**
462
  * Output the activity pagination links.
463
  *
464
- * @since 1.0.0
465
  *
 
466
  */
467
  function bp_activity_pagination_links() {
468
  echo bp_get_activity_pagination_links();
@@ -471,64 +751,49 @@ function bp_activity_pagination_links() {
471
  /**
472
  * Return the activity pagination links.
473
  *
474
- * @since 1.0.0
475
  *
476
  * @global object $activities_template {@link BP_Activity_Template}
 
477
  *
478
  * @return string The pagination links.
479
  */
480
  function bp_get_activity_pagination_links() {
481
  global $activities_template;
482
 
483
- /**
484
- * Filters the activity pagination link output.
485
- *
486
- * @since 1.0.0
487
- *
488
- * @param string $pag_links Output for the activity pagination links.
489
- */
490
  return apply_filters( 'bp_get_activity_pagination_links', $activities_template->pag_links );
491
  }
492
 
493
  /**
494
  * Return true when there are more activity items to be shown than currently appear.
495
  *
496
- * @since 1.5.0
497
  *
498
  * @global object $activities_template {@link BP_Activity_Template}
 
499
  *
500
  * @return bool $has_more_items True if more items, false if not.
501
  */
502
  function bp_activity_has_more_items() {
503
  global $activities_template;
504
 
505
- if ( ! empty( $activities_template->has_more_items ) ) {
506
- $has_more_items = true;
507
- } else {
508
- $remaining_pages = 0;
509
-
510
- if ( ! empty( $activities_template->pag_page ) ) {
511
- $remaining_pages = floor( ( $activities_template->total_activity_count - 1 ) / ( $activities_template->pag_num * $activities_template->pag_page ) );
512
- }
513
 
514
- $has_more_items = (int) $remaining_pages > 0;
 
515
  }
516
 
517
- /**
518
- * Filters whether there are more activity items to display.
519
- *
520
- * @since 1.5.0
521
- *
522
- * @param bool $has_more_items Whether or not there are more activity items to display.
523
- */
524
  return apply_filters( 'bp_activity_has_more_items', $has_more_items );
525
  }
526
 
527
  /**
528
  * Output the activity count.
529
  *
530
- * @since 1.2.0
531
  *
 
532
  */
533
  function bp_activity_count() {
534
  echo bp_get_activity_count();
@@ -537,30 +802,25 @@ function bp_activity_count() {
537
  /**
538
  * Return the activity count.
539
  *
540
- * @since 1.2.0
541
  *
542
  * @global object $activities_template {@link BP_Activity_Template}
 
543
  *
544
  * @return int The activity count.
545
  */
546
  function bp_get_activity_count() {
547
  global $activities_template;
548
 
549
- /**
550
- * Filters the activity count for the activity template.
551
- *
552
- * @since 1.2.0
553
- *
554
- * @param int $activity_count The count for total activity.
555
- */
556
  return apply_filters( 'bp_get_activity_count', (int) $activities_template->activity_count );
557
  }
558
 
559
  /**
560
  * Output the number of activities per page.
561
  *
562
- * @since 1.2.0
563
  *
 
564
  */
565
  function bp_activity_per_page() {
566
  echo bp_get_activity_per_page();
@@ -569,30 +829,25 @@ function bp_activity_per_page() {
569
  /**
570
  * Return the number of activities per page.
571
  *
572
- * @since 1.2.0
573
  *
574
  * @global object $activities_template {@link BP_Activity_Template}
 
575
  *
576
  * @return int The activities per page.
577
  */
578
  function bp_get_activity_per_page() {
579
  global $activities_template;
580
 
581
- /**
582
- * Filters the activity posts per page value.
583
- *
584
- * @since 1.2.0
585
- *
586
- * @param int $pag_num How many post should be displayed for pagination.
587
- */
588
  return apply_filters( 'bp_get_activity_per_page', (int) $activities_template->pag_num );
589
  }
590
 
591
  /**
592
  * Output the activities title.
593
  *
594
- * @since 1.0.0
595
  *
 
596
  * @todo Deprecate.
597
  */
598
  function bp_activities_title() {
@@ -602,31 +857,26 @@ function bp_activities_title() {
602
  /**
603
  * Return the activities title.
604
  *
605
- * @since 1.0.0
606
  *
607
  * @global string $bp_activity_title
 
608
  * @todo Deprecate.
609
  *
610
- * @return string The activities title.
611
  */
612
  function bp_get_activities_title() {
613
  global $bp_activity_title;
614
 
615
- /**
616
- * Filters the activities title for the activity template.
617
- *
618
- * @since 1.0.0
619
- *
620
- * @param string $bp_activity_title The title to be displayed.
621
- */
622
  return apply_filters( 'bp_get_activities_title', $bp_activity_title );
623
  }
624
 
625
  /**
626
  * {@internal Missing Description}
627
  *
628
- * @since 1.0.0
629
  *
 
630
  * @todo Deprecate.
631
  */
632
  function bp_activities_no_activity() {
@@ -636,9 +886,10 @@ function bp_activities_no_activity() {
636
  /**
637
  * {@internal Missing Description}
638
  *
639
- * @since 1.0.0
640
  *
641
  * @global string $bp_activity_no_activity
 
642
  * @todo Deprecate.
643
  *
644
  * @return string
@@ -646,21 +897,15 @@ function bp_activities_no_activity() {
646
  function bp_get_activities_no_activity() {
647
  global $bp_activity_no_activity;
648
 
649
- /**
650
- * Filters the text used when there is no activity to display.
651
- *
652
- * @since 1.0.0
653
- *
654
- * @param string $bp_activity_no_activity Text to display for no activity.
655
- */
656
  return apply_filters( 'bp_get_activities_no_activity', $bp_activity_no_activity );
657
  }
658
 
659
  /**
660
  * Output the activity ID.
661
  *
662
- * @since 1.2.0
663
  *
 
664
  */
665
  function bp_activity_id() {
666
  echo bp_get_activity_id();
@@ -669,30 +914,24 @@ function bp_activity_id() {
669
  /**
670
  * Return the activity ID.
671
  *
672
- * @since 1.2.0
673
  *
674
  * @global object $activities_template {@link BP_Activity_Template}
 
675
  *
676
  * @return int The activity ID.
677
  */
678
  function bp_get_activity_id() {
679
  global $activities_template;
680
-
681
- /**
682
- * Filters the activity ID being displayed.
683
- *
684
- * @since 1.2.0
685
- *
686
- * @param int $id The activity ID.
687
- */
688
  return apply_filters( 'bp_get_activity_id', $activities_template->activity->id );
689
  }
690
 
691
  /**
692
  * Output the activity item ID.
693
  *
694
- * @since 1.2.0
695
  *
 
696
  */
697
  function bp_activity_item_id() {
698
  echo bp_get_activity_item_id();
@@ -701,30 +940,24 @@ function bp_activity_item_id() {
701
  /**
702
  * Return the activity item ID.
703
  *
704
- * @since 1.2.0
705
  *
706
  * @global object $activities_template {@link BP_Activity_Template}
 
707
  *
708
  * @return int The activity item ID.
709
  */
710
  function bp_get_activity_item_id() {
711
  global $activities_template;
712
-
713
- /**
714
- * Filters the activity item ID being displayed.
715
- *
716
- * @since 1.2.0
717
- *
718
- * @param int $item_id The activity item ID.
719
- */
720
  return apply_filters( 'bp_get_activity_item_id', $activities_template->activity->item_id );
721
  }
722
 
723
  /**
724
  * Output the activity secondary item ID.
725
  *
726
- * @since 1.2.0
727
  *
 
728
  */
729
  function bp_activity_secondary_item_id() {
730
  echo bp_get_activity_secondary_item_id();
@@ -733,30 +966,24 @@ function bp_activity_secondary_item_id() {
733
  /**
734
  * Return the activity secondary item ID.
735
  *
736
- * @since 1.2.0
737
  *
738
  * @global object $activities_template {@link BP_Activity_Template}
 
739
  *
740
  * @return int The activity secondary item ID.
741
  */
742
  function bp_get_activity_secondary_item_id() {
743
  global $activities_template;
744
-
745
- /**
746
- * Filters the activity secondary item ID being displayed.
747
- *
748
- * @since 1.2.0
749
- *
750
- * @param int $secondary_item_id The activity secondary item ID.
751
- */
752
  return apply_filters( 'bp_get_activity_secondary_item_id', $activities_template->activity->secondary_item_id );
753
  }
754
 
755
  /**
756
  * Output the date the activity was recorded.
757
  *
758
- * @since 1.2.0
759
  *
 
760
  */
761
  function bp_activity_date_recorded() {
762
  echo bp_get_activity_date_recorded();
@@ -765,66 +992,24 @@ function bp_activity_date_recorded() {
765
  /**
766
  * Return the date the activity was recorded.
767
  *
768
- * @since 1.2.0
769
  *
770
  * @global object $activities_template {@link BP_Activity_Template}
 
771
  *
772
  * @return string The date the activity was recorded.
773
  */
774
  function bp_get_activity_date_recorded() {
775
  global $activities_template;
776
-
777
- /**
778
- * Filters the date the activity was recorded.
779
- *
780
- * @since 1.2.0
781
- *
782
- * @param int $date_recorded The activity's date.
783
- */
784
  return apply_filters( 'bp_get_activity_date_recorded', $activities_template->activity->date_recorded );
785
  }
786
 
787
- /**
788
- * Output the display name of the member who posted the activity.
789
- *
790
- * @since 2.1.0
791
- *
792
- */
793
- function bp_activity_member_display_name() {
794
- echo bp_get_activity_member_display_name();
795
- }
796
-
797
- /**
798
- * Return the display name of the member who posted the activity.
799
- *
800
- * @since 2.1.0
801
- *
802
- * @global object $activities_template {@link BP_Activity_Template}
803
- *
804
- * @return string The date the activity was recorded.
805
- */
806
- function bp_get_activity_member_display_name() {
807
- global $activities_template;
808
-
809
- $retval = isset( $activities_template->activity->display_name )
810
- ? $activities_template->activity->display_name
811
- : '';
812
-
813
- /**
814
- * Filters the display name of the member who posted the activity.
815
- *
816
- * @since 2.1.0
817
- *
818
- * @param int $retval Display name for the member who posted.
819
- */
820
- return apply_filters( 'bp_get_activity_member_display_name', $retval );
821
- }
822
-
823
  /**
824
  * Output the activity object name.
825
  *
826
- * @since 1.2.0
827
  *
 
828
  */
829
  function bp_activity_object_name() {
830
  echo bp_get_activity_object_name();
@@ -833,30 +1018,24 @@ function bp_activity_object_name() {
833
  /**
834
  * Return the activity object name.
835
  *
836
- * @since 1.2.0
837
  *
838
  * @global object $activities_template {@link BP_Activity_Template}
 
839
  *
840
  * @return string The activity object name.
841
  */
842
  function bp_get_activity_object_name() {
843
  global $activities_template;
844
-
845
- /**
846
- * Filters the activity object name.
847
- *
848
- * @since 1.2.0
849
- *
850
- * @param string $activity_component The activity object name.
851
- */
852
  return apply_filters( 'bp_get_activity_object_name', $activities_template->activity->component );
853
  }
854
 
855
  /**
856
  * Output the activity type.
857
  *
858
- * @since 1.2.0
859
  *
 
860
  */
861
  function bp_activity_type() {
862
  echo bp_get_activity_type();
@@ -865,22 +1044,15 @@ function bp_activity_type() {
865
  /**
866
  * Return the activity type.
867
  *
868
- * @since 1.2.0
869
  *
870
  * @global object $activities_template {@link BP_Activity_Template}
 
871
  *
872
  * @return string The activity type.
873
  */
874
  function bp_get_activity_type() {
875
  global $activities_template;
876
-
877
- /**
878
- * Filters the activity type.
879
- *
880
- * @since 1.2.0
881
- *
882
- * @param string $activity_type The activity type.
883
- */
884
  return apply_filters( 'bp_get_activity_type', $activities_template->activity->type );
885
  }
886
 
@@ -889,12 +1061,13 @@ function bp_activity_type() {
889
  *
890
  * Just a wrapper for bp_activity_type().
891
  *
892
- * @since 1.2.0
893
- * @deprecated 1.5.0
894
  *
895
  * @todo Properly deprecate in favor of bp_activity_type() and
896
- * remove redundant echo
897
  *
 
898
  */
899
  function bp_activity_action_name() { echo bp_activity_type(); }
900
 
@@ -903,11 +1076,12 @@ function bp_activity_type() {
903
  *
904
  * Just a wrapper for bp_get_activity_type().
905
  *
906
- * @since 1.2.0
907
- * @deprecated 1.5.0
908
  *
909
  * @todo Properly deprecate in favor of bp_get_activity_type().
910
  *
 
911
  *
912
  * @return string The activity type.
913
  */
@@ -916,8 +1090,9 @@ function bp_activity_type() {
916
  /**
917
  * Output the activity user ID.
918
  *
919
- * @since 1.1.0
920
  *
 
921
  */
922
  function bp_activity_user_id() {
923
  echo bp_get_activity_user_id();
@@ -926,30 +1101,24 @@ function bp_activity_user_id() {
926
  /**
927
  * Return the activity user ID.
928
  *
929
- * @since 1.1.0
930
  *
931
  * @global object $activities_template {@link BP_Activity_Template}
 
932
  *
933
  * @return int The activity user ID.
934
  */
935
  function bp_get_activity_user_id() {
936
  global $activities_template;
937
-
938
- /**
939
- * Filters the activity user ID.
940
- *
941
- * @since 1.1.0
942
- *
943
- * @param int $user_id The activity user ID.
944
- */
945
  return apply_filters( 'bp_get_activity_user_id', $activities_template->activity->user_id );
946
  }
947
 
948
  /**
949
  * Output the activity user link.
950
  *
951
- * @since 1.2.0
952
  *
 
953
  */
954
  function bp_activity_user_link() {
955
  echo bp_get_activity_user_link();
@@ -958,39 +1127,34 @@ function bp_activity_user_link() {
958
  /**
959
  * Return the activity user link.
960
  *
961
- * @since 1.2.0
962
  *
963
  * @global object $activities_template {@link BP_Activity_Template}
 
 
964
  *
965
  * @return string $link The activity user link.
966
  */
967
  function bp_get_activity_user_link() {
968
  global $activities_template;
969
 
970
- if ( empty( $activities_template->activity->user_id ) || empty( $activities_template->activity->user_nicename ) || empty( $activities_template->activity->user_login ) ) {
971
  $link = $activities_template->activity->primary_link;
972
- } else {
973
  $link = bp_core_get_user_domain( $activities_template->activity->user_id, $activities_template->activity->user_nicename, $activities_template->activity->user_login );
974
- }
975
 
976
- /**
977
- * Filters the activity user link.
978
- *
979
- * @since 1.2.0
980
- *
981
- * @param string $link The activity user link.
982
- */
983
  return apply_filters( 'bp_get_activity_user_link', $link );
984
  }
985
 
986
  /**
987
  * Output the avatar of the user that performed the action.
988
  *
989
- * @since 1.1.0
990
  *
991
  * @see bp_get_activity_avatar() for description of arguments.
 
992
  *
993
- * @param array|string $args See {@link bp_get_activity_avatar()} for description.
994
  */
995
  function bp_activity_avatar( $args = '' ) {
996
  echo bp_get_activity_avatar( $args );
@@ -998,23 +1162,30 @@ function bp_activity_avatar( $args = '' ) {
998
  /**
999
  * Return the avatar of the user that performed the action.
1000
  *
1001
- * @since 1.1.0
1002
  *
1003
  * @see bp_core_fetch_avatar() For a description of the arguments.
1004
  * @global object $activities_template {@link BP_Activity_Template}
1005
- *
1006
- * @param array|string $args {
 
 
 
 
 
 
 
1007
  * Arguments are listed here with an explanation of their defaults.
1008
  * For more information about the arguments, see
1009
  * {@link bp_core_fetch_avatar()}.
1010
- * @type string $alt Default: 'Profile picture of [user name]' if
1011
- * activity user name is available, otherwise 'Profile picture'.
1012
- * @type string $class Default: 'avatar'.
1013
- * @type string|bool $email Default: Email of the activity's
1014
- * associated user, if available. Otherwise false.
1015
- * @type string $type Default: 'full' when viewing a single activity
1016
- * permalink page, otherwise 'thumb'.
1017
- * @type int|bool $user_id Default: ID of the activity's user.
1018
  * }
1019
  * @return string User avatar string.
1020
  */
@@ -1023,17 +1194,17 @@ function bp_activity_avatar( $args = '' ) {
1023
 
1024
  $bp = buddypress();
1025
 
1026
- // On activity permalink pages, default to the full-size avatar.
1027
  $type_default = bp_is_single_activity() ? 'full' : 'thumb';
1028
 
1029
  // Within the activity comment loop, the current activity should be set
1030
  // to current_comment. Otherwise, just use activity.
1031
  $current_activity_item = isset( $activities_template->activity->current_comment ) ? $activities_template->activity->current_comment : $activities_template->activity;
1032
 
1033
- // Activity user display name.
1034
  $dn_default = isset( $current_activity_item->display_name ) ? $current_activity_item->display_name : '';
1035
 
1036
- // Prepend some descriptive text to alt.
1037
  $alt_default = !empty( $dn_default ) ? sprintf( __( 'Profile picture of %s', 'buddypress' ), $dn_default ) : __( 'Profile picture', 'buddypress' );
1038
 
1039
  $defaults = array(
@@ -1049,14 +1220,14 @@ function bp_activity_avatar( $args = '' ) {
1049
 
1050
  if ( !isset( $height ) && !isset( $width ) ) {
1051
 
1052
- // Backpat.
1053
  if ( isset( $bp->avatar->full->height ) || isset( $bp->avatar->thumb->height ) ) {
1054
  $height = ( 'full' == $type ) ? $bp->avatar->full->height : $bp->avatar->thumb->height;
1055
  } else {
1056
  $height = 20;
1057
  }
1058
 
1059
- // Backpat.
1060
  if ( isset( $bp->avatar->full->width ) || isset( $bp->avatar->thumb->width ) ) {
1061
  $width = ( 'full' == $type ) ? $bp->avatar->full->width : $bp->avatar->thumb->width;
1062
  } else {
@@ -1064,41 +1235,15 @@ function bp_activity_avatar( $args = '' ) {
1064
  }
1065
  }
1066
 
1067
- /**
1068
- * Filters the activity avatar object based on current activity item component.
1069
- *
1070
- * This is a variable filter dependent on the component used.
1071
- * Possible hooks are bp_get_activity_avatar_object_blog,
1072
- * bp_get_activity_avatar_object_group, and bp_get_activity_avatar_object_user.
1073
- *
1074
- * @since 1.1.0
1075
- *
1076
- * @param string $component Component being displayed.
1077
- */
1078
  $object = apply_filters( 'bp_get_activity_avatar_object_' . $current_activity_item->component, 'user' );
1079
  $item_id = !empty( $user_id ) ? $user_id : $current_activity_item->user_id;
1080
-
1081
- /**
1082
- * Filters the activity avatar item ID.
1083
- *
1084
- * @since 1.2.10
1085
- *
1086
- * @param int $item_id Item ID for the activity avatar.
1087
- */
1088
  $item_id = apply_filters( 'bp_get_activity_avatar_item_id', $item_id );
1089
 
1090
- // If this is a user object pass the users' email address for Gravatar so we don't have to prefetch it.
1091
- if ( 'user' == $object && empty( $user_id ) && empty( $email ) && isset( $current_activity_item->user_email ) ) {
1092
  $email = $current_activity_item->user_email;
1093
- }
1094
 
1095
- /**
1096
- * Filters the value returned by bp_core_fetch_avatar.
1097
- *
1098
- * @since 1.1.3
1099
- *
1100
- * @param array $value HTML image element containing the activity avatar.
1101
- */
1102
  return apply_filters( 'bp_get_activity_avatar', bp_core_fetch_avatar( array(
1103
  'item_id' => $item_id,
1104
  'object' => $object,
@@ -1114,35 +1259,42 @@ function bp_activity_avatar( $args = '' ) {
1114
  /**
1115
  * Output the avatar of the object that action was performed on.
1116
  *
1117
- * @since 1.2.0
1118
  *
1119
  * @see bp_get_activity_secondary_avatar() for description of arguments.
 
1120
  *
1121
- * @param array|string $args See {@link bp_get_activity_secondary_avatar} for description.
1122
  */
1123
  function bp_activity_secondary_avatar( $args = '' ) {
1124
  echo bp_get_activity_secondary_avatar( $args );
1125
  }
1126
 
1127
  /**
1128
- * Return the avatar of the object that action was performed on.
1129
  *
1130
- * @since 1.2.0
1131
  *
1132
  * @see bp_core_fetch_avatar() for description of arguments.
1133
  * @global object $activities_template {@link BP_Activity_Template}
1134
- *
1135
- * @param array|string $args {
 
 
 
 
 
 
1136
  * For a complete description of arguments, see {@link bp_core_fetch_avatar()}.
1137
- * @type string $alt Default value varies based on current activity
1138
- * item component.
1139
- * @type string $type Default: 'full' when viewing a single activity
1140
- * permalink page, otherwise 'thumb'.
1141
- * @type string $class Default: 'avatar'.
1142
- * @type string|bool $email Default: email of the activity's user.
1143
- * @type int|bool $user_id Default: ID of the activity's user.
1144
  * }
1145
- * @return string The secondary avatar.
1146
  */
1147
  function bp_get_activity_secondary_avatar( $args = '' ) {
1148
  global $activities_template;
@@ -1159,21 +1311,21 @@ function bp_activity_secondary_avatar( $args = '' ) {
1159
  ) );
1160
  extract( $r, EXTR_SKIP );
1161
 
1162
- // Set item_id and object (default to user).
1163
  switch ( $activities_template->activity->component ) {
1164
  case 'groups' :
1165
- if ( bp_disable_group_avatar_uploads() ) {
1166
- return false;
1167
- }
1168
-
1169
  $object = 'group';
1170
  $item_id = $activities_template->activity->item_id;
1171
  $link = '';
1172
  $name = '';
1173
 
1174
- // Only if groups is active.
1175
  if ( bp_is_active( 'groups' ) ) {
1176
- $group = groups_get_group( $item_id );
 
 
 
 
1177
  $link = bp_get_group_permalink( $group );
1178
  $name = $group->name;
1179
  }
@@ -1220,34 +1372,16 @@ function bp_activity_secondary_avatar( $args = '' ) {
1220
  break;
1221
  }
1222
 
1223
- /**
1224
- * Filters the activity secondary avatar object based on current activity item component.
1225
- *
1226
- * This is a variable filter dependent on the component used. Possible hooks are
1227
- * bp_get_activity_secondary_avatar_object_blog, bp_get_activity_secondary_avatar_object_group,
1228
- * and bp_get_activity_secondary_avatar_object_user.
1229
- *
1230
- * @since 1.2.10
1231
- *
1232
- * @param string $object Component being displayed.
1233
- */
1234
  $object = apply_filters( 'bp_get_activity_secondary_avatar_object_' . $activities_template->activity->component, $object );
1235
-
1236
- /**
1237
- * Filters the activity secondary avatar item ID.
1238
- *
1239
- * @since 1.2.10
1240
- *
1241
- * @param int $item_id ID for the secondary avatar item.
1242
- */
1243
  $item_id = apply_filters( 'bp_get_activity_secondary_avatar_item_id', $item_id );
1244
 
1245
- // If we have no item_id or object, there is no avatar to display.
1246
  if ( empty( $item_id ) || empty( $object ) ) {
1247
  return false;
1248
  }
1249
 
1250
- // Get the avatar.
1251
  $avatar = bp_core_fetch_avatar( array(
1252
  'item_id' => $item_id,
1253
  'object' => $object,
@@ -1260,142 +1394,102 @@ function bp_activity_secondary_avatar( $args = '' ) {
1260
  ) );
1261
 
1262
  if ( !empty( $linked ) ) {
1263
-
1264
- /**
1265
- * Filters the secondary avatar link for current activity.
1266
- *
1267
- * @since 1.7.0
1268
- *
1269
- * @param string $link Link to wrap the avatar image in.
1270
- * @param string $component Activity component being acted on.
1271
- */
1272
  $link = apply_filters( 'bp_get_activity_secondary_avatar_link', $link, $activities_template->activity->component );
1273
 
1274
- /**
1275
- * Filters the determined avatar for the secondary activity item.
1276
- *
1277
- * @since 1.2.10
1278
- *
1279
- * @param string $avatar Formatted HTML <img> element, or raw avatar URL.
1280
- */
1281
- $avatar = apply_filters( 'bp_get_activity_secondary_avatar', $avatar );
1282
-
1283
  return sprintf( '<a href="%s" class="%s">%s</a>',
1284
  $link,
1285
  $link_class,
1286
- $avatar
1287
  );
1288
  }
1289
 
1290
- /** This filter is documented in bp-activity/bp-activity-template.php */
1291
  return apply_filters( 'bp_get_activity_secondary_avatar', $avatar );
1292
  }
1293
 
1294
  /**
1295
- * Output the activity action.
1296
  *
1297
- * @since 1.2.0
1298
  *
1299
- * @param array $args See bp_get_activity_action().
 
1300
  */
1301
  function bp_activity_action( $args = array() ) {
1302
  echo bp_get_activity_action( $args );
1303
  }
1304
 
1305
  /**
1306
- * Return the activity action.
1307
  *
1308
- * @since 1.2.0
1309
  *
1310
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
1311
  *
1312
  * @param array $args {
1313
  * @type bool $no_timestamp Whether to exclude the timestamp.
1314
  * }
1315
- *
1316
  * @return string The activity action.
1317
  */
1318
  function bp_get_activity_action( $args = array() ) {
1319
  global $activities_template;
1320
 
1321
- $r = wp_parse_args( $args, array(
1322
  'no_timestamp' => false,
1323
- ) );
1324
 
1325
- /**
1326
- * Filters the activity action before the action is inserted as meta.
1327
- *
1328
- * @since 1.2.10
1329
- *
1330
- * @param array $value Array containing the current action, the current activity, and the $args array passed into the function.
1331
- */
1332
- $action = apply_filters_ref_array( 'bp_get_activity_action_pre_meta', array(
1333
- $activities_template->activity->action,
1334
- &$activities_template->activity,
1335
- $r
1336
- ) );
1337
 
1338
- // Prepend the activity action meta (link, time since, etc...).
1339
- if ( ! empty( $action ) && empty( $r['no_timestamp'] ) ) {
1340
  $action = bp_insert_activity_meta( $action );
1341
- }
1342
 
1343
- /**
1344
- * Filters the activity action after the action has been inserted as meta.
1345
- *
1346
- * @since 1.2.0
1347
- *
1348
- * @param array $value Array containing the current action, the current activity, and the $args array passed into the function.
1349
- */
1350
- return apply_filters_ref_array( 'bp_get_activity_action', array(
1351
- $action,
1352
- &$activities_template->activity,
1353
- $r
1354
- ) );
1355
  }
1356
 
1357
  /**
1358
- * Output the activity content body.
1359
  *
1360
- * @since 1.2.0
1361
  *
 
1362
  */
1363
  function bp_activity_content_body() {
1364
  echo bp_get_activity_content_body();
1365
  }
1366
 
1367
  /**
1368
- * Return the activity content body.
1369
  *
1370
- * @since 1.2.0
1371
  *
1372
  * @global object $activities_template {@link BP_Activity_Template}
 
 
1373
  *
1374
  * @return string The activity content body.
1375
  */
1376
  function bp_get_activity_content_body() {
1377
  global $activities_template;
1378
 
1379
- // Backwards compatibility if action is not being used.
1380
- if ( empty( $activities_template->activity->action ) && ! empty( $activities_template->activity->content ) ) {
1381
  $activities_template->activity->content = bp_insert_activity_meta( $activities_template->activity->content );
1382
- }
1383
 
1384
- /**
1385
- * Filters the activity content body.
1386
- *
1387
- * @since 1.2.0
1388
- *
1389
- * @param string $content Content body.
1390
- * @param object $activity Activity object. Passed by reference.
1391
- */
1392
  return apply_filters_ref_array( 'bp_get_activity_content_body', array( $activities_template->activity->content, &$activities_template->activity ) );
1393
  }
1394
 
1395
  /**
1396
  * Does the activity have content?
1397
  *
1398
- * @since 1.2.0
1399
  *
1400
  * @global object $activities_template {@link BP_Activity_Template}
1401
  *
@@ -1404,9 +1498,8 @@ function bp_activity_content_body() {
1404
  function bp_activity_has_content() {
1405
  global $activities_template;
1406
 
1407
- if ( ! empty( $activities_template->activity->content ) ) {
1408
  return true;
1409
- }
1410
 
1411
  return false;
1412
  }
@@ -1414,11 +1507,12 @@ function bp_activity_has_content() {
1414
  /**
1415
  * Output the activity content.
1416
  *
1417
- * @since 1.0.0
1418
- * @deprecated 1.5.0
1419
  *
1420
  * @todo properly deprecate this function.
1421
  *
 
1422
  */
1423
  function bp_activity_content() {
1424
  echo bp_get_activity_content();
@@ -1427,22 +1521,25 @@ function bp_activity_content() {
1427
  /**
1428
  * Return the activity content.
1429
  *
1430
- * @since 1.0.0
1431
- * @deprecated 1.5.0
1432
  *
1433
  * @todo properly deprecate this function.
1434
  *
 
 
 
1435
  *
1436
  * @return string The activity content.
1437
  */
1438
  function bp_get_activity_content() {
1439
-
1440
  /**
1441
  * If you want to filter activity update content, please use
1442
- * the filter 'bp_get_activity_content_body'.
1443
  *
1444
- * This function is mainly for backwards compatibility.
1445
  */
 
1446
  $content = bp_get_activity_action() . ' ' . bp_get_activity_content_body();
1447
  return apply_filters( 'bp_get_activity_content', $content );
1448
  }
@@ -1453,145 +1550,81 @@ function bp_activity_content() {
1453
  * This metadata includes the time since the item was posted (which will appear
1454
  * as a link to the item's permalink).
1455
  *
1456
- * @since 1.2.0
1457
  *
1458
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
 
 
 
1459
  *
1460
  * @param string $content The activity content.
1461
  * @return string The activity content with the metadata string attached.
1462
  */
1463
- function bp_insert_activity_meta( $content = '' ) {
1464
  global $activities_template;
1465
 
1466
- // Strip any legacy time since placeholders from BP 1.0-1.1.
1467
- $new_content = str_replace( '<span class="time-since">%s</span>', '', $content );
1468
-
1469
- // Get the time since this activity was recorded.
1470
- $date_recorded = bp_core_time_since( $activities_template->activity->date_recorded );
1471
-
1472
- // Set up 'time-since' <span>.
1473
- $time_since = sprintf(
1474
- '<span class="time-since" data-livestamp="%1$s">%2$s</span>',
1475
- bp_core_get_iso8601_date( $activities_template->activity->date_recorded ),
1476
- $date_recorded
1477
- );
1478
-
1479
- /**
1480
- * Filters the activity item time since markup.
1481
- *
1482
- * @since 1.2.0
1483
- *
1484
- * @param array $value Array containing the time since markup and the current activity component.
1485
- */
1486
- $time_since = apply_filters_ref_array( 'bp_activity_time_since', array(
1487
- $time_since,
1488
- &$activities_template->activity
1489
- ) );
1490
 
1491
- // Insert the permalink.
1492
- if ( ! bp_is_single_activity() ) {
1493
-
1494
- // Setup variables for activity meta.
1495
- $activity_permalink = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
1496
- $activity_meta = sprintf( '%1$s <a href="%2$s" class="view activity-time-since" title="%3$s">%4$s</a>',
1497
- $new_content,
1498
- $activity_permalink,
1499
- esc_attr__( 'View Discussion', 'buddypress' ),
1500
- $time_since
1501
- );
1502
 
1503
- /**
1504
- * Filters the activity permalink to be added to the activity content.
1505
- *
1506
- * @since 1.2.0
1507
- *
1508
- * @param array $value Array containing the html markup for the activity permalink, after being parsed by
1509
- * sprintf and current activity component.
1510
- */
1511
- $new_content = apply_filters_ref_array( 'bp_activity_permalink', array(
1512
- $activity_meta,
1513
- &$activities_template->activity
1514
- ) );
1515
- } else {
1516
- $new_content .= str_pad( $time_since, strlen( $time_since ) + 2, ' ', STR_PAD_BOTH );
1517
- }
1518
 
1519
- /**
1520
- * Filters the activity content after activity metadata has been attached.
1521
- *
1522
- * @since 1.2.0
1523
- *
1524
- * @param string $content Activity content with the activity metadata added.
1525
- */
1526
- return apply_filters( 'bp_insert_activity_meta', $new_content, $content );
1527
  }
1528
 
1529
  /**
1530
  * Determine if the current user can delete an activity item.
1531
  *
1532
- * @since 1.2.0
1533
  *
1534
  * @global object $activities_template {@link BP_Activity_Template}
 
1535
  *
1536
- * @param BP_Activity_Activity $activity Optional. Falls back on the current item in the loop.
1537
  * @return bool True if can delete, false otherwise.
1538
  */
1539
  function bp_activity_user_can_delete( $activity = false ) {
1540
  global $activities_template;
1541
 
1542
- // Try to use current activity if none was passed.
1543
- if ( empty( $activity ) && ! empty( $activities_template->activity ) ) {
1544
  $activity = $activities_template->activity;
1545
- }
1546
 
1547
- // If current_comment is set, we'll use that in place of the main activity.
1548
- if ( isset( $activity->current_comment ) ) {
1549
  $activity = $activity->current_comment;
1550
- }
1551
 
1552
- // Assume the user cannot delete the activity item.
1553
  $can_delete = false;
1554
 
1555
- // Only logged in users can delete activity.
1556
- if ( is_user_logged_in() ) {
1557
 
1558
- // Community moderators can always delete activity (at least for now).
1559
- if ( bp_current_user_can( 'bp_moderate' ) ) {
1560
- $can_delete = true;
1561
- }
1562
-
1563
- // Users are allowed to delete their own activity. This is actually
1564
- // quite powerful, because doing so also deletes all comments to that
1565
- // activity item. We should revisit this eventually.
1566
- if ( isset( $activity->user_id ) && ( $activity->user_id === bp_loggedin_user_id() ) ) {
1567
- $can_delete = true;
1568
- }
1569
 
1570
- // Viewing a single item, and this user is an admin of that item.
1571
- if ( bp_is_single_item() && bp_is_item_admin() ) {
1572
- $can_delete = true;
1573
- }
1574
- }
1575
 
1576
- /**
1577
- * Filters whether the current user can delete an activity item.
1578
- *
1579
- * @since 1.5.0
1580
- *
1581
- * @param bool $can_delete Whether the user can delete the item.
1582
- * @param object $activity Current activity item object.
1583
- */
1584
- return (bool) apply_filters( 'bp_activity_user_can_delete', $can_delete, $activity );
1585
  }
1586
 
1587
  /**
1588
  * Output the activity parent content.
1589
  *
1590
- * @since 1.2.0
1591
  *
1592
  * @see bp_get_activity_parent_content() for a description of arguments.
 
1593
  *
1594
- * @param array|string $args See {@link bp_get_activity_parent_content} for description.
1595
  */
1596
  function bp_activity_parent_content( $args = '' ) {
1597
  echo bp_get_activity_parent_content($args);
@@ -1600,62 +1633,60 @@ function bp_activity_parent_content( $args = '' ) {
1600
  /**
1601
  * Return the activity content.
1602
  *
1603
- * @since 1.2.0
1604
  *
1605
  * @global object $activities_template {@link BP_Activity_Template}
 
 
1606
  *
1607
- * @param string $args Unused. Left over from an earlier implementation.
1608
- * @return mixed False on failure, otherwise the activity parent content.
 
 
 
1609
  */
1610
  function bp_get_activity_parent_content( $args = '' ) {
1611
  global $activities_template;
1612
 
1613
- // Bail if no activity on no item ID.
1614
- if ( empty( $activities_template->activity ) || empty( $activities_template->activity->item_id ) ) {
1615
- return false;
1616
- }
1617
 
1618
- // Get the ID of the parent activity content.
1619
- $parent_id = $activities_template->activity->item_id;
1620
 
1621
- // Bail if no parent content.
1622
- if ( empty( $activities_template->activity_parents[ $parent_id ] ) ) {
1623
  return false;
1624
- }
1625
 
1626
- // Bail if no action.
1627
- if ( empty( $activities_template->activity_parents[ $parent_id ]->action ) ) {
 
 
 
 
1628
  return false;
1629
- }
1630
 
1631
- // Content always includes action.
1632
- $content = $activities_template->activity_parents[ $parent_id ]->action;
1633
 
1634
- // Maybe append activity content, if it exists.
1635
- if ( ! empty( $activities_template->activity_parents[ $parent_id ]->content ) ) {
1636
- $content .= ' ' . $activities_template->activity_parents[ $parent_id ]->content;
1637
- }
1638
 
1639
- // Remove the time since content for backwards compatibility.
1640
  $content = str_replace( '<span class="time-since">%s</span>', '', $content );
1641
 
1642
- // Remove images.
1643
  $content = preg_replace( '/<img[^>]*>/Ui', '', $content );
1644
 
1645
- /**
1646
- * Filters the activity parent content.
1647
- *
1648
- * @since 1.2.0
1649
- *
1650
- * @param string $content Content set to be displayed as parent content.
1651
- */
1652
  return apply_filters( 'bp_get_activity_parent_content', $content );
1653
  }
1654
 
1655
  /**
1656
  * Output the parent activity's user ID.
1657
  *
1658
- * @since 1.7.0
1659
  */
1660
  function bp_activity_parent_user_id() {
1661
  echo bp_get_activity_parent_user_id();
@@ -1664,51 +1695,43 @@ function bp_activity_parent_user_id() {
1664
  /**
1665
  * Return the parent activity's user ID.
1666
  *
1667
- * @since 1.7.0
1668
  *
1669
  * @global BP_Activity_Template $activities_template
1670
  *
1671
  * @return bool|int False if parent activity can't be found, otherwise
1672
- * the parent activity's user ID.
1673
  */
1674
  function bp_get_activity_parent_user_id() {
1675
  global $activities_template;
1676
 
1677
- // Bail if no activity on no item ID.
1678
- if ( empty( $activities_template->activity ) || empty( $activities_template->activity->item_id ) ) {
1679
  return false;
1680
- }
1681
 
1682
- // Get the ID of the parent activity content.
1683
- $parent_id = $activities_template->activity->item_id;
 
1684
 
1685
- // Bail if no parent item.
1686
- if ( empty( $activities_template->activity_parents[ $parent_id ] ) ) {
1687
  return false;
1688
- }
1689
 
1690
- // Bail if no parent user ID.
1691
- if ( empty( $activities_template->activity_parents[ $parent_id ]->user_id ) ) {
1692
  return false;
1693
- }
1694
 
1695
- $retval = $activities_template->activity_parents[ $parent_id ]->user_id;
1696
 
1697
- /**
1698
- * Filters the activity parent item's user ID.
1699
- *
1700
- * @since 1.7.0
1701
- *
1702
- * @param int $retval ID for the activity parent's user.
1703
- */
1704
  return (int) apply_filters( 'bp_get_activity_parent_user_id', $retval );
1705
  }
1706
 
1707
  /**
1708
  * Output whether or not the current activity is in a current user's favorites.
1709
  *
1710
- * @since 1.2.0
1711
  *
 
1712
  */
1713
  function bp_activity_is_favorite() {
1714
  echo bp_get_activity_is_favorite();
@@ -1717,33 +1740,27 @@ function bp_activity_is_favorite() {
1717
  /**
1718
  * Return whether the current activity is in a current user's favorites.
1719
  *
1720
- * @since 1.2.0
1721
  *
1722
  * @global object $activities_template {@link BP_Activity_Template}
 
1723
  *
1724
  * @return bool True if user favorite, false otherwise.
1725
  */
1726
  function bp_get_activity_is_favorite() {
1727
  global $activities_template;
1728
 
1729
- /**
1730
- * Filters whether the current activity item is in the current user's favorites.
1731
- *
1732
- * @since 1.2.0
1733
- *
1734
- * @param bool $value Whether or not the current activity item is in the current user's favorites.
1735
- */
1736
- return (bool) apply_filters( 'bp_get_activity_is_favorite', in_array( $activities_template->activity->id, (array) $activities_template->my_favs ) );
1737
  }
1738
 
1739
  /**
1740
  * Output the comment markup for an activity item.
1741
  *
1742
- * @since 1.2.0
1743
  *
1744
  * @todo deprecate $args param
1745
  *
1746
- * @param array|string $args See {@link bp_activity_get_comments} for description.
1747
  */
1748
  function bp_activity_comments( $args = '' ) {
1749
  echo bp_activity_get_comments( $args );
@@ -1752,62 +1769,52 @@ function bp_activity_comments( $args = '' ) {
1752
  /**
1753
  * Get the comment markup for an activity item.
1754
  *
1755
- * @since 1.2.0
1756
  *
1757
  * @todo deprecate $args param
 
1758
  * @todo Given that checks for children already happen in bp_activity_recurse_comments(),
1759
- * this function can probably be streamlined or removed.
1760
  *
1761
- * @global object $activities_template {@link BP_Activity_Template}
1762
  *
1763
- * @param string $args Unused. Left over from an earlier implementation.
1764
- * @return bool
1765
  */
1766
  function bp_activity_get_comments( $args = '' ) {
1767
  global $activities_template;
1768
 
1769
- if ( empty( $activities_template->activity->children ) ) {
1770
  return false;
1771
- }
1772
 
1773
  bp_activity_recurse_comments( $activities_template->activity );
1774
  }
1775
 
1776
  /**
1777
- * Loops through a level of activity comments and loads the template for each.
1778
  *
1779
  * Note: The recursion itself used to happen entirely in this function. Now it is
1780
  * split between here and the comment.php template.
1781
  *
1782
- * @since 1.2.0
1783
  *
1784
- * @global object $activities_template {@link BP_Activity_Template}
1785
  *
1786
- * @param object $comment The activity object currently being recursed.
1787
- * @return bool|string
1788
  */
1789
  function bp_activity_recurse_comments( $comment ) {
1790
  global $activities_template;
1791
 
1792
- if ( empty( $comment ) ) {
1793
  return false;
1794
- }
1795
 
1796
- if ( empty( $comment->children ) ) {
1797
  return false;
1798
- }
1799
 
1800
- /**
1801
- * Filters the opening tag for the template that lists activity comments.
1802
- *
1803
- * @since 1.6.0
1804
- *
1805
- * @param string $value Opening tag for the HTML markup to use.
1806
- */
1807
- echo apply_filters( 'bp_activity_recurse_comments_start_ul', '<ul>' );
1808
  foreach ( (array) $comment->children as $comment_child ) {
1809
-
1810
- // Put the comment into the global so it's available to filters.
1811
  $activities_template->activity->current_comment = $comment_child;
1812
 
1813
  $template = bp_locate_template( 'activity/comment.php', false, false );
@@ -1824,41 +1831,25 @@ function bp_activity_comments( $args = '' ) {
1824
 
1825
  unset( $activities_template->activity->current_comment );
1826
  }
1827
-
1828
- /**
1829
- * Filters the closing tag for the template that list activity comments.
1830
- *
1831
- * @since 1.6.0
1832
- *
1833
- * @param string $value Closing tag for the HTML markup to use.
1834
- */
1835
- echo apply_filters( 'bp_activity_recurse_comments_end_ul', '</ul>' );
1836
  }
1837
 
1838
  /**
1839
  * Utility function that returns the comment currently being recursed.
1840
  *
1841
- * @since 1.5.0
1842
  *
1843
  * @global object $activities_template {@link BP_Activity_Template}
 
1844
  *
1845
  * @return object|bool $current_comment The activity comment currently being
1846
- * displayed. False on failure.
1847
  */
1848
  function bp_activity_current_comment() {
1849
  global $activities_template;
1850
 
1851
- $current_comment = !empty( $activities_template->activity->current_comment )
1852
- ? $activities_template->activity->current_comment
1853
- : false;
1854
 
1855
- /**
1856
- * Filters the current comment being recursed.
1857
- *
1858
- * @since 1.5.0
1859
- *
1860
- * @param object|bool $current_comment The activity comment currently being displayed. False on failure.
1861
- */
1862
  return apply_filters( 'bp_activity_current_comment', $current_comment );
1863
  }
1864
 
@@ -1866,8 +1857,9 @@ function bp_activity_current_comment() {
1866
  /**
1867
  * Output the ID of the activity comment currently being displayed.
1868
  *
1869
- * @since 1.5.0
1870
  *
 
1871
  */
1872
  function bp_activity_comment_id() {
1873
  echo bp_get_activity_comment_id();
@@ -1876,33 +1868,28 @@ function bp_activity_comment_id() {
1876
  /**
1877
  * Return the ID of the activity comment currently being displayed.
1878
  *
1879
- * @since 1.5.0
1880
  *
1881
  * @global object $activities_template {@link BP_Activity_Template}
 
1882
  *
1883
- * @return int|bool $comment_id The ID of the activity comment currently
1884
- * being displayed, false if none is found.
1885
  */
1886
  function bp_get_activity_comment_id() {
1887
  global $activities_template;
1888
 
1889
  $comment_id = isset( $activities_template->activity->current_comment->id ) ? $activities_template->activity->current_comment->id : false;
1890
 
1891
- /**
1892
- * Filters the ID of the activity comment currently being displayed.
1893
- *
1894
- * @since 1.5.0
1895
- *
1896
- * @param int|bool $comment_id ID for the comment currently being displayed.
1897
- */
1898
  return apply_filters( 'bp_activity_comment_id', $comment_id );
1899
  }
1900
 
1901
  /**
1902
  * Output the ID of the author of the activity comment currently being displayed.
1903
  *
1904
- * @since 1.5.0
1905
  *
 
1906
  */
1907
  function bp_activity_comment_user_id() {
1908
  echo bp_get_activity_comment_user_id();
@@ -1911,33 +1898,28 @@ function bp_activity_comment_user_id() {
1911
  /**
1912
  * Return the ID of the author of the activity comment currently being displayed.
1913
  *
1914
- * @since 1.5.0
1915
  *
1916
  * @global object $activities_template {@link BP_Activity_Template}
 
1917
  *
1918
  * @return int|bool $user_id The user_id of the author of the displayed
1919
- * activity comment. False on failure.
1920
  */
1921
  function bp_get_activity_comment_user_id() {
1922
  global $activities_template;
1923
 
1924
  $user_id = isset( $activities_template->activity->current_comment->user_id ) ? $activities_template->activity->current_comment->user_id : false;
1925
 
1926
- /**
1927
- * Filters the ID of the author of the activity comment currently being displayed.
1928
- *
1929
- * @since 1.5.0
1930
- *
1931
- * @param int|bool $user_id ID for the author of the comment currently being displayed.
1932
- */
1933
  return apply_filters( 'bp_activity_comment_user_id', $user_id );
1934
  }
1935
 
1936
  /**
1937
  * Output the author link for the activity comment currently being displayed.
1938
  *
1939
- * @since 1.5.0
1940
  *
 
1941
  */
1942
  function bp_activity_comment_user_link() {
1943
  echo bp_get_activity_comment_user_link();
@@ -1946,29 +1928,26 @@ function bp_activity_comment_user_link() {
1946
  /**
1947
  * Return the author link for the activity comment currently being displayed.
1948
  *
1949
- * @since 1.5.0
1950
  *
 
 
 
1951
  *
1952
  * @return string $user_link The URL of the activity comment author's profile.
1953
  */
1954
  function bp_get_activity_comment_user_link() {
1955
  $user_link = bp_core_get_user_domain( bp_get_activity_comment_user_id() );
1956
 
1957
- /**
1958
- * Filters the author link for the activity comment currently being displayed.
1959
- *
1960
- * @since 1.5.0
1961
- *
1962
- * @param string $user_link Link for the author of the activity comment currently being displayed.
1963
- */
1964
  return apply_filters( 'bp_activity_comment_user_link', $user_link );
1965
  }
1966
 
1967
  /**
1968
  * Output the author name for the activity comment currently being displayed.
1969
  *
1970
- * @since 1.5.0
1971
  *
 
1972
  */
1973
  function bp_activity_comment_name() {
1974
  echo bp_get_activity_comment_name();
@@ -1980,133 +1959,96 @@ function bp_activity_comment_name() {
1980
  * The use of the 'bp_acomment_name' filter is deprecated. Please use
1981
  * 'bp_activity_comment_name'.
1982
  *
1983
- * @since 1.5.0
1984
  *
1985
  * @global object $activities_template {@link BP_Activity_Template}
 
 
1986
  *
1987
  * @return string $name The full name of the activity comment author.
1988
  */
1989
  function bp_get_activity_comment_name() {
1990
  global $activities_template;
1991
 
1992
- if ( isset( $activities_template->activity->current_comment->user_fullname ) ) {
1993
-
1994
- $name = apply_filters( 'bp_acomment_name', $activities_template->activity->current_comment->user_fullname, $activities_template->activity->current_comment ); // Backward compatibility.
1995
- } else {
1996
  $name = $activities_template->activity->current_comment->display_name;
1997
- }
1998
 
1999
- /**
2000
- * Filters the name of the author for the activity comment.
2001
- *
2002
- * @since 1.5.0
2003
- *
2004
- * @param string $name Name to be displayed with the activity comment.
2005
- */
2006
  return apply_filters( 'bp_activity_comment_name', $name );
2007
  }
2008
 
2009
  /**
2010
- * Output the formatted date_recorded of the activity comment currently being displayed.
2011
  *
2012
- * @since 1.5.0
2013
  *
 
2014
  */
2015
  function bp_activity_comment_date_recorded() {
2016
  echo bp_get_activity_comment_date_recorded();
2017
  }
2018
 
2019
- /**
2020
- * Return the formatted date_recorded for the activity comment currently being displayed.
2021
- *
2022
- * @since 1.5.0
2023
- *
2024
- *
2025
- * @return string|bool $date_recorded Time since the activity was recorded,
2026
- * in the form "%s ago". False on failure.
2027
- */
2028
- function bp_get_activity_comment_date_recorded() {
2029
-
2030
- /**
2031
- * Filters the recorded date of the activity comment currently being displayed.
2032
- *
2033
- * @since 1.5.0
2034
- *
2035
- * @param string|bool Date for the activity comment currently being displayed.
2036
- */
2037
- return apply_filters( 'bp_activity_comment_date_recorded', bp_core_time_since( bp_get_activity_comment_date_recorded_raw() ) );
2038
- }
2039
-
2040
- /**
2041
- * Output the date_recorded of the activity comment currently being displayed.
2042
- *
2043
- * @since 2.3.0
2044
- *
2045
- */
2046
- function bp_activity_comment_date_recorded_raw() {
2047
- echo bp_get_activity_comment_date_recorded_raw();
2048
- }
2049
-
2050
  /**
2051
  * Return the date_recorded for the activity comment currently being displayed.
2052
  *
2053
- * @since 2.3.0
2054
  *
2055
  * @global object $activities_template {@link BP_Activity_Template}
 
 
2056
  *
2057
  * @return string|bool $date_recorded Time since the activity was recorded,
2058
- * in the form "%s ago". False on failure.
2059
  */
2060
- function bp_get_activity_comment_date_recorded_raw() {
2061
  global $activities_template;
2062
 
2063
- /**
2064
- * Filters the raw recorded date of the activity comment currently being displayed.
2065
- *
2066
- * @since 2.3.0
2067
- *
2068
- * @param string|bool Raw date for the activity comment currently being displayed.
2069
- */
2070
- return apply_filters( 'bp_activity_comment_date_recorded', $activities_template->activity->current_comment->date_recorded );
2071
  }
2072
 
2073
  /**
2074
  * Output the 'delete' URL for the activity comment currently being displayed.
2075
  *
2076
- * @since 1.5.0
2077
  *
 
2078
  */
2079
  function bp_activity_comment_delete_link() {
2080
  echo bp_get_activity_comment_delete_link();
2081
  }
2082
 
2083
  /**
2084
- * Gets the 'delete' URL for the activity comment currently being displayed.
2085
  *
2086
- * @since 1.5.0
2087
  *
 
 
 
 
 
2088
  *
2089
  * @return string $link The nonced URL for deleting the current
2090
- * activity comment.
2091
  */
2092
  function bp_get_activity_comment_delete_link() {
2093
- $link = wp_nonce_url( bp_get_activity_directory_permalink() . 'delete/' . bp_get_activity_comment_id() . '?cid=' . bp_get_activity_comment_id(), 'bp_activity_delete_link' );
2094
 
2095
- /**
2096
- * Filters the link used for deleting the activity comment currently being displayed.
2097
- *
2098
- * @since 1.5.0
2099
- *
2100
- * @param string $link Link to use for deleting the currently displayed activity comment.
2101
- */
2102
  return apply_filters( 'bp_activity_comment_delete_link', $link );
2103
  }
2104
 
2105
  /**
2106
  * Output the content of the activity comment currently being displayed.
2107
  *
2108
- * @since 1.5.0
2109
  *
 
2110
  */
2111
  function bp_activity_comment_content() {
2112
  echo bp_get_activity_comment_content();
@@ -2120,184 +2062,119 @@ function bp_activity_comment_content() {
2120
  * 'bp_activity_comment_content' to modify the content of activity
2121
  * comments only.
2122
  *
2123
- * @since 1.5.0
2124
  *
2125
  * @global object $activities_template {@link BP_Activity_Template}
 
 
2126
  *
2127
  * @return string $content The content of the current activity comment.
2128
  */
2129
  function bp_get_activity_comment_content() {
2130
  global $activities_template;
2131
 
2132
- /** This filter is documented in bp-activity/bp-activity-template.php */
2133
  $content = apply_filters( 'bp_get_activity_content', $activities_template->activity->current_comment->content );
2134
 
2135
- /**
2136
- * Filters the content of the current activity comment.
2137
- *
2138
- * @since 1.2.0
2139
- *
2140
- * @param string $content The content of the current activity comment.
2141
- */
2142
  return apply_filters( 'bp_activity_comment_content', $content );
2143
  }
2144
 
2145
  /**
2146
  * Output the activity comment count.
2147
  *
2148
- * @since 1.2.0
2149
  *
 
2150
  */
2151
  function bp_activity_comment_count() {
2152
  echo bp_activity_get_comment_count();
2153
  }
2154
 
2155
  /**
2156
- * Return the comment count of an activity item.
 
 
 
 
 
2157
  *
2158
- * @since 1.2.0
2159
  *
2160
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
2161
  *
2162
- * @param array|null $deprecated Deprecated.
2163
  * @return int $count The activity comment count.
2164
  */
2165
- function bp_activity_get_comment_count( $deprecated = null ) {
2166
  global $activities_template;
2167
 
2168
- // Deprecated notice about $args.
2169
- if ( ! empty( $deprecated ) ) {
2170
- _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__ ) );
2171
- }
2172
 
2173
- // Get the count using the purpose-built recursive function.
2174
- $count = ! empty( $activities_template->activity->children )
2175
- ? bp_activity_recurse_comment_count( $activities_template->activity )
2176
- : 0;
2177
 
2178
- /**
2179
- * Filters the activity comment count.
2180
- *
2181
- * @since 1.2.0
2182
- *
2183
- * @param int $count The activity comment count.
2184
- */
2185
  return apply_filters( 'bp_activity_get_comment_count', (int) $count );
2186
  }
2187
 
2188
  /**
2189
- * Return the total number of comments to the current comment.
2190
  *
2191
- * This function recursively adds the total number of comments each
2192
- * activity child has, and returns them.
 
 
2193
  *
2194
- * @since 1.2.0
2195
  *
 
 
 
2196
  *
2197
  * @param object $comment Activity comment object.
2198
- * @param int $count The current iteration count.
2199
  * @return int $count The activity comment count.
2200
  */
2201
  function bp_activity_recurse_comment_count( $comment, $count = 0 ) {
2202
 
2203
- // Copy the count.
2204
- $new_count = $count;
2205
 
2206
- // Loop through children and recursively count comments.
2207
- if ( ! empty( $comment->children ) ) {
2208
- foreach ( (array) $comment->children as $comment ) {
2209
- $new_count++;
2210
- $new_count = bp_activity_recurse_comment_count( $comment, $new_count );
2211
- }
2212
  }
2213
 
2214
- /**
2215
- * Filters the total number of comments for the current comment.
2216
- *
2217
- * @since 2.1.0
2218
- *
2219
- * @param int $new_count New total count for the current comment.
2220
- * @param object $comment Activity comment object.
2221
- * @param int $count Current iteration count for the current comment.
2222
- */
2223
- return apply_filters( 'bp_activity_recurse_comment_count', $new_count, $comment, $count );
2224
  }
2225
 
2226
  /**
2227
  * Output the depth of the current activity comment.
2228
  *
2229
- * @since 2.0.0
2230
- * @since 2.8.0 Added $comment as a parameter.
2231
- *
2232
- * @param object|int $comment Object of the activity comment or activity comment ID. Usually unnecessary
2233
- * when used in activity comment loop.
2234
  */
2235
- function bp_activity_comment_depth( $comment = 0 ) {
2236
- echo bp_activity_get_comment_depth( $comment );
2237
  }
2238
-
2239
  /**
2240
  * Return the current activity comment depth.
2241
  *
2242
- * @since 2.0.0
2243
- * @since 2.8.0 Added $comment as a parameter.
2244
  *
2245
- * @param object|int $comment Object of the activity comment or activity comment ID. Usually unnecessary
2246
- * when used in activity comment loop.
2247
  * @return int
2248
  */
2249
- function bp_activity_get_comment_depth( $comment = 0 ) {
2250
- $depth = 0;
2251
-
2252
- // Activity comment loop takes precedence.
2253
- if ( isset( $GLOBALS['activities_template']->activity->current_comment->depth ) ) {
2254
- $depth = $GLOBALS['activities_template']->activity->current_comment->depth;
2255
-
2256
- // Get depth for activity comment manually.
2257
- } elseif ( ! empty( $comment ) ) {
2258
- // We passed an activity ID, so fetch the activity object.
2259
- if ( is_int( $comment ) ) {
2260
- $comment = new BP_Activity_Activity( $comment );
2261
- }
2262
-
2263
- // Recurse through activity tree to find the depth.
2264
- if ( is_object( $comment ) && isset( $comment->type ) && 'activity_comment' === $comment->type ) {
2265
- // Fetch the entire root comment tree... ugh.
2266
- $comments = BP_Activity_Activity::get_activity_comments( $comment->item_id, 1, constant( 'PHP_INT_MAX' ) );
2267
-
2268
- // Recursively find our comment object from the comment tree.
2269
- $iterator = new RecursiveArrayIterator( $comments );
2270
- $recursive = new RecursiveIteratorIterator( $iterator, RecursiveIteratorIterator::SELF_FIRST );
2271
- foreach ( $recursive as $cid => $cobj ) {
2272
- // Skip items that are not a comment object.
2273
- if ( ! is_numeric( $cid ) || ! is_object( $cobj ) ) {
2274
- continue;
2275
- }
2276
-
2277
- // We found the activity comment! Set the depth.
2278
- if ( $cid === $comment->id && isset( $cobj->depth ) ) {
2279
- $depth = $cobj->depth;
2280
- break;
2281
- }
2282
- }
2283
- }
2284
- }
2285
-
2286
- /**
2287
- * Filters the comment depth of the current activity comment.
2288
- *
2289
- * @since 2.0.0
2290
- *
2291
- * @param int $depth Depth for the current activity comment.
2292
- */
2293
- return apply_filters( 'bp_activity_get_comment_depth', $depth );
2294
  }
2295
 
2296
  /**
2297
  * Output the activity comment link.
2298
  *
2299
- * @since 1.2.0
2300
  *
 
2301
  */
2302
  function bp_activity_comment_link() {
2303
  echo bp_get_activity_comment_link();
@@ -2306,51 +2183,43 @@ function bp_activity_comment_link() {
2306
  /**
2307
  * Return the activity comment link.
2308
  *
2309
- * @since 1.2.0
2310
  *
2311
  * @global object $activities_template {@link BP_Activity_Template}
 
2312
  *
2313
  * @return string The activity comment link.
2314
  */
2315
  function bp_get_activity_comment_link() {
2316
  global $activities_template;
2317
-
2318
- /**
2319
- * Filters the comment link for the current activity comment.
2320
- *
2321
- * @since 1.2.0
2322
- *
2323
- * @param string $value Constructed URL parameters with activity IDs.
2324
- */
2325
  return apply_filters( 'bp_get_activity_comment_link', '?ac=' . $activities_template->activity->id . '/#ac-form-' . $activities_template->activity->id );
2326
  }
2327
 
2328
  /**
2329
- * Output the activity comment form no JavaScript display CSS.
2330
  *
2331
- * @since 1.2.0
2332
  *
 
2333
  */
2334
  function bp_activity_comment_form_nojs_display() {
2335
  echo bp_get_activity_comment_form_nojs_display();
2336
  }
2337
 
2338
  /**
2339
- * Return the activity comment form no JavaScript display CSS.
2340
  *
2341
- * @since 1.2.0
2342
  *
2343
  * @global object $activities_template {@link BP_Activity_Template}
2344
  *
2345
- * @return string|bool The activity comment form no JavaScript
2346
- * display CSS. False on failure.
2347
  */
2348
  function bp_get_activity_comment_form_nojs_display() {
2349
  global $activities_template;
2350
-
2351
- if ( isset( $_GET['ac'] ) && ( $_GET['ac'] === ( $activities_template->activity->id . '/' ) ) ) {
2352
  return 'style="display: block"';
2353
- }
2354
 
2355
  return false;
2356
  }
@@ -2358,8 +2227,9 @@ function bp_activity_comment_form_nojs_display() {
2358
  /**
2359
  * Output the activity comment form action.
2360
  *
2361
- * @since 1.2.0
2362
  *
 
2363
  */
2364
  function bp_activity_comment_form_action() {
2365
  echo bp_get_activity_comment_form_action();
@@ -2368,28 +2238,24 @@ function bp_activity_comment_form_action() {
2368
  /**
2369
  * Return the activity comment form action.
2370
  *
2371
- * @since 1.2.0
2372
  *
 
 
 
2373
  *
2374
  * @return string The activity comment form action.
2375
  */
2376
  function bp_get_activity_comment_form_action() {
2377
-
2378
- /**
2379
- * Filters the activity comment form action URL.
2380
- *
2381
- * @since 1.2.0
2382
- *
2383
- * @param string $value URL to use in the comment form's action attribute.
2384
- */
2385
  return apply_filters( 'bp_get_activity_comment_form_action', home_url( bp_get_activity_root_slug() . '/reply/' ) );
2386
  }
2387
 
2388
  /**
2389
  * Output the activity permalink ID.
2390
  *
2391
- * @since 1.2.0
2392
  *
 
2393
  */
2394
  function bp_activity_permalink_id() {
2395
  echo bp_get_activity_permalink_id();
@@ -2398,38 +2264,34 @@ function bp_activity_permalink_id() {
2398
  /**
2399
  * Return the activity permalink ID.
2400
  *
2401
- * @since 1.2.0
2402
  *
 
2403
  *
2404
  * @return string The activity permalink ID.
2405
  */
2406
  function bp_get_activity_permalink_id() {
2407
-
2408
- /**
2409
- * Filters the activity action permalink ID.
2410
- *
2411
- * @since 1.2.0
2412
- *
2413
- * @param string $value Current action for the activity item.
2414
- */
2415
  return apply_filters( 'bp_get_activity_permalink_id', bp_current_action() );
2416
  }
2417
 
2418
  /**
2419
  * Output the activity thread permalink.
2420
  *
2421
- * @since 1.2.0
2422
  *
 
2423
  */
2424
  function bp_activity_thread_permalink() {
2425
- echo esc_url( bp_get_activity_thread_permalink() );
2426
  }
2427
 
2428
  /**
2429
  * Return the activity thread permalink.
2430
  *
2431
- * @since 1.2.0
2432
  *
 
 
2433
  *
2434
  * @return string $link The activity thread permalink.
2435
  */
@@ -2438,58 +2300,43 @@ function bp_activity_thread_permalink() {
2438
 
2439
  $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
2440
 
2441
- /**
2442
- * Filters the activity thread permalink.
2443
- *
2444
- * @since 1.2.0
2445
- *
2446
- * @param string $link The activity thread permalink.
2447
- */
2448
- return apply_filters( 'bp_get_activity_thread_permalink', $link );
2449
  }
2450
 
2451
  /**
2452
  * Output the activity comment permalink.
2453
  *
2454
- * @since 1.8.0
2455
  *
 
2456
  */
2457
  function bp_activity_comment_permalink() {
2458
- echo esc_url( bp_get_activity_comment_permalink() );
2459
  }
2460
  /**
2461
  * Return the activity comment permalink.
2462
  *
2463
- * @since 1.8.0
 
 
 
2464
  *
2465
  * @return string $link The activity comment permalink.
2466
  */
2467
  function bp_get_activity_comment_permalink() {
2468
  global $activities_template;
2469
 
2470
- $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
2471
-
2472
- // Used for filter below.
2473
- $comment_id = isset( $activities_template->activity->current_comment->id )
2474
- ? $activities_template->activity->current_comment->id
2475
- : 0;
2476
 
2477
- /**
2478
- * Filters the activity comment permalink.
2479
- *
2480
- * @since 1.8.0
2481
- *
2482
- * @param string $link Activity comment permalink.
2483
- * @param int $comment_id ID for the current activity comment.
2484
- */
2485
- return apply_filters( 'bp_get_activity_comment_permalink', $link, $comment_id );
2486
  }
2487
 
2488
  /**
2489
  * Output the activity favorite link.
2490
  *
2491
- * @since 1.2.0
2492
  *
 
2493
  */
2494
  function bp_activity_favorite_link() {
2495
  echo bp_get_activity_favorite_link();
@@ -2498,30 +2345,27 @@ function bp_activity_favorite_link() {
2498
  /**
2499
  * Return the activity favorite link.
2500
  *
2501
- * @since 1.2.0
2502
  *
2503
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
2504
  *
2505
  * @return string The activity favorite link.
2506
  */
2507
  function bp_get_activity_favorite_link() {
2508
  global $activities_template;
2509
-
2510
- /**
2511
- * Filters the activity favorite link.
2512
- *
2513
- * @since 1.2.0
2514
- *
2515
- * @param string $value Constructed link for favoriting the activity comment.
2516
- */
2517
  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' ) );
2518
  }
2519
 
2520
  /**
2521
  * Output the activity unfavorite link.
2522
  *
2523
- * @since 1.2.0
2524
  *
 
2525
  */
2526
  function bp_activity_unfavorite_link() {
2527
  echo bp_get_activity_unfavorite_link();
@@ -2530,30 +2374,27 @@ function bp_activity_unfavorite_link() {
2530
  /**
2531
  * Return the activity unfavorite link.
2532
  *
2533
- * @since 1.2.0
2534
  *
2535
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
2536
  *
2537
  * @return string The activity unfavorite link.
2538
  */
2539
  function bp_get_activity_unfavorite_link() {
2540
  global $activities_template;
2541
-
2542
- /**
2543
- * Filters the activity unfavorite link.
2544
- *
2545
- * @since 1.2.0
2546
- *
2547
- * @param string $value Constructed link for unfavoriting the activity comment.
2548
- */
2549
  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' ) );
2550
  }
2551
 
2552
  /**
2553
  * Output the activity CSS class.
2554
  *
2555
- * @since 1.0.0
2556
  *
 
2557
  */
2558
  function bp_activity_css_class() {
2559
  echo bp_get_activity_css_class();
@@ -2562,22 +2403,19 @@ function bp_activity_css_class() {
2562
  /**
2563
  * Return the current activity item's CSS class.
2564
  *
2565
- * @since 1.0.0
2566
  *
2567
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
2568
  *
2569
  * @return string The activity item's CSS class.
2570
  */
2571
  function bp_get_activity_css_class() {
2572
  global $activities_template;
2573
 
2574
- /**
2575
- * Filters the available mini activity actions available as CSS classes.
2576
- *
2577
- * @since 1.2.0
2578
- *
2579
- * @param array $value Array of classes used to determine classes applied to HTML element.
2580
- */
2581
  $mini_activity_actions = apply_filters( 'bp_activity_mini_activity_types', array(
2582
  'friendship_accepted',
2583
  'friendship_created',
@@ -2587,115 +2425,69 @@ function bp_activity_css_class() {
2587
  'new_member'
2588
  ) );
2589
 
2590
- $class = ' activity-item';
2591
-
2592
- if ( in_array( $activities_template->activity->type, (array) $mini_activity_actions ) || empty( $activities_template->activity->content ) ) {
2593
- $class .= ' mini';
2594
- }
2595
-
2596
- if ( bp_activity_get_comment_count() && bp_activity_can_comment() ) {
2597
- $class .= ' has-comments';
2598
- }
2599
-
2600
- /**
2601
- * Filters the determined classes to add to the HTML element.
2602
- *
2603
- * @since 1.0.0
2604
- *
2605
- * @param string $value Classes to be added to the HTML element.
2606
- */
2607
- return apply_filters( 'bp_get_activity_css_class', $activities_template->activity->component . ' ' . $activities_template->activity->type . $class );
2608
- }
2609
-
2610
- /**
2611
- * Output the activity delete link.
2612
- *
2613
- * @since 1.1.0
2614
- *
2615
- */
2616
- function bp_activity_delete_link() {
2617
- echo bp_get_activity_delete_link();
2618
- }
2619
-
2620
- /**
2621
- * Return the activity delete link.
2622
- *
2623
- * @since 1.1.0
2624
- *
2625
- * @global object $activities_template {@link BP_Activity_Template}
2626
- *
2627
- * @return string $link Activity delete link. Contains $redirect_to arg
2628
- * if on single activity page.
2629
- */
2630
- function bp_get_activity_delete_link() {
2631
-
2632
- $url = bp_get_activity_delete_url();
2633
- $class = 'delete-activity';
2634
-
2635
- // Determine if we're on a single activity page, and customize accordingly.
2636
- if ( bp_is_activity_component() && is_numeric( bp_current_action() ) ) {
2637
- $class = 'delete-activity-single';
2638
- }
2639
 
2640
- $link = '<a href="' . esc_url( $url ) . '" class="button item-button bp-secondary-action ' . $class . ' confirm" rel="nofollow">' . __( 'Delete', 'buddypress' ) . '</a>';
 
2641
 
2642
- /**
2643
- * Filters the activity delete link.
2644
- *
2645
- * @since 1.1.0
2646
- *
2647
- * @param string $link Activity delete HTML link.
2648
- */
2649
- return apply_filters( 'bp_get_activity_delete_link', $link );
2650
  }
2651
 
2652
  /**
2653
- * Output the URL to delete a single activity stream item.
2654
  *
2655
- * @since 2.1.0
2656
  *
 
2657
  */
2658
- function bp_activity_delete_url() {
2659
- echo esc_url( bp_get_activity_delete_url() );
2660
  }
 
2661
  /**
2662
- * Return the URL to delete a single activity item.
2663
  *
2664
- * @since 2.1.0
2665
  *
2666
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
 
 
 
 
2667
  *
2668
  * @return string $link Activity delete link. Contains $redirect_to arg
2669
- * if on single activity page.
2670
  */
2671
- function bp_get_activity_delete_url() {
2672
  global $activities_template;
2673
 
2674
- $url = trailingslashit( bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/delete/' . $activities_template->activity->id );
 
2675
 
2676
- // Determine if we're on a single activity page, and customize accordingly.
2677
  if ( bp_is_activity_component() && is_numeric( bp_current_action() ) ) {
2678
- $url = add_query_arg( array( 'redirect_to' => wp_get_referer() ), $url );
 
2679
  }
2680
 
2681
- $url = wp_nonce_url( $url, 'bp_activity_delete_link' );
2682
-
2683
- /**
2684
- * Filters the activity delete URL.
2685
- *
2686
- * @since 2.1.0
2687
- *
2688
- * @param string $url Activity delete URL.
2689
- */
2690
- return apply_filters( 'bp_get_activity_delete_url', $url );
2691
  }
2692
 
2693
  /**
2694
  * Output the activity latest update link.
2695
  *
2696
- * @since 1.2.0
2697
  *
2698
  * @see bp_get_activity_latest_update() for description of parameters.
 
2699
  *
2700
  * @param int $user_id See {@link bp_get_activity_latest_update()} for description.
2701
  */
@@ -2706,65 +2498,47 @@ function bp_activity_latest_update( $user_id = 0 ) {
2706
  /**
2707
  * Return the activity latest update link.
2708
  *
2709
- * @since 1.2.0
2710
  *
 
 
 
 
 
 
 
 
2711
  *
2712
  * @param int $user_id If empty, will fall back on displayed user.
2713
  * @return string|bool $latest_update The activity latest update link.
2714
- * False on failure.
2715
  */
2716
  function bp_get_activity_latest_update( $user_id = 0 ) {
2717
 
2718
- if ( empty( $user_id ) ) {
2719
  $user_id = bp_displayed_user_id();
2720
- }
2721
 
2722
- if ( bp_is_user_inactive( $user_id ) ) {
2723
  return false;
2724
- }
2725
 
2726
- if ( !$update = bp_get_user_meta( $user_id, 'bp_latest_update', true ) ) {
2727
  return false;
2728
- }
2729
-
2730
- /**
2731
- * Filters the latest update excerpt.
2732
- *
2733
- * @since 1.2.10
2734
- * @since 2.6.0 Added the `$user_id` parameter.
2735
- *
2736
- * @param string $value The excerpt for the latest update.
2737
- * @param int $user_id ID of the queried user.
2738
- */
2739
- $latest_update = apply_filters( 'bp_get_activity_latest_update_excerpt', trim( strip_tags( bp_create_excerpt( $update['content'], bp_activity_get_excerpt_length() ) ) ), $user_id );
2740
 
2741
- $latest_update = sprintf(
2742
- '%s <a href="%s">%s</a>',
2743
- $latest_update,
2744
- esc_url_raw( bp_activity_get_permalink( $update['id'] ) ),
2745
- esc_attr__( 'View', 'buddypress' )
2746
- );
2747
 
2748
- /**
2749
- * Filters the latest update excerpt with view link appended to the end.
2750
- *
2751
- * @since 1.2.0
2752
- * @since 2.6.0 Added the `$user_id` parameter.
2753
- *
2754
- * @param string $latest_update The latest update with "view" link appended to it.
2755
- * @param int $user_id ID of the queried user.
2756
- */
2757
- return apply_filters( 'bp_get_activity_latest_update', $latest_update, $user_id );
2758
  }
2759
 
2760
  /**
2761
  * Output the activity filter links.
2762
  *
2763
- * @since 1.1.0
2764
  *
2765
  * @see bp_get_activity_filter_links() for description of parameters.
 
2766
  *
2767
- * @param array|bool $args See {@link bp_get_activity_filter_links()} for description.
2768
  */
2769
  function bp_activity_filter_links( $args = false ) {
2770
  echo bp_get_activity_filter_links( $args );
@@ -2773,48 +2547,55 @@ function bp_activity_filter_links( $args = false ) {
2773
  /**
2774
  * Return the activity filter links.
2775
  *
2776
- * @since 1.1.0
2777
  *
 
 
 
 
 
 
 
2778
  *
2779
- * @param array|bool $args {
2780
  * @type string $style The type of markup to use for the links.
2781
- * 'list', 'paragraph', or 'span'. Default: 'list'.
2782
  * }
2783
  * @return string|bool $component_links The activity filter links.
2784
  * False on failure.
2785
  */
2786
  function bp_get_activity_filter_links( $args = false ) {
2787
 
2788
- $r = wp_parse_args( $args, array(
2789
  'style' => 'list'
2790
- ) );
 
 
 
2791
 
2792
- // Define local variable.
2793
  $component_links = array();
2794
 
2795
- // Fetch the names of components that have activity recorded in the DB.
2796
  $components = BP_Activity_Activity::get_recorded_components();
2797
 
2798
- if ( empty( $components ) ) {
2799
  return false;
2800
- }
2801
 
2802
  foreach ( (array) $components as $component ) {
2803
 
2804
- // Skip the activity comment filter.
2805
- if ( 'activity' == $component ) {
2806
  continue;
2807
- }
2808
 
2809
- if ( isset( $_GET['afilter'] ) && $component == $_GET['afilter'] ) {
2810
  $selected = ' class="selected"';
2811
- } else {
2812
- $selected = '';
2813
- }
2814
 
2815
  $component = esc_attr( $component );
2816
 
2817
- switch ( $r['style'] ) {
2818
  case 'list':
2819
  $tag = 'li';
2820
  $before = '<li id="afilter-' . $component . '"' . $selected . '>';
@@ -2834,148 +2615,92 @@ function bp_activity_filter_links( $args = false ) {
2834
 
2835
  $link = add_query_arg( 'afilter', $component );
2836
  $link = remove_query_arg( 'acpage' , $link );
2837
-
2838
- /**
2839
- * Filters the activity filter link URL for the current activity component.
2840
- *
2841
- * @since 1.1.0
2842
- *
2843
- * @param string $link The URL for the current component.
2844
- * @param string $component The current component getting links constructed for.
2845
- */
2846
  $link = apply_filters( 'bp_get_activity_filter_link_href', $link, $component );
2847
 
2848
- $component_links[] = $before . '<a href="' . esc_url( $link ) . '">' . ucwords( $component ) . '</a>' . $after;
2849
  }
2850
 
2851
  $link = remove_query_arg( 'afilter' , $link );
2852
 
2853
- if ( isset( $_GET['afilter'] ) ) {
2854
- $component_links[] = '<' . $tag . ' id="afilter-clear"><a href="' . esc_url( $link ) . '">' . __( 'Clear Filter', 'buddypress' ) . '</a></' . $tag . '>';
2855
- }
2856
 
2857
- /**
2858
- * Filters all of the constructed filter links.
2859
- *
2860
- * @since 1.1.0
2861
- * @since 2.6.0 Added the `$r` parameter.
2862
- *
2863
- * @param string $value All of the links to be displayed to the user.
2864
- * @param array $r Array of parsed arguments.
2865
- */
2866
- return apply_filters( 'bp_get_activity_filter_links', implode( "\n", $component_links ), $r );
2867
  }
2868
 
2869
  /**
2870
  * Determine if a comment can be made on an activity item.
2871
  *
2872
- * @since 1.2.0
2873
  *
2874
  * @global object $activities_template {@link BP_Activity_Template}
 
 
2875
  *
2876
  * @return bool $can_comment True if item can receive comments.
2877
  */
2878
  function bp_activity_can_comment() {
2879
  global $activities_template;
2880
- $bp = buddypress();
2881
 
2882
- // Determine ability to comment based on activity type name.
2883
- $activity_type = bp_get_activity_type();
2884
 
2885
- // Get the 'comment-reply' support for the current activity type.
2886
- $can_comment = bp_activity_type_supports( $activity_type, 'comment-reply' );
 
 
2887
 
2888
- // Neutralize activity_comment.
2889
- if ( 'activity_comment' === $activity_type ) {
2890
  $can_comment = false;
2891
- }
2892
 
2893
- /**
2894
- * Filters whether a comment can be made on an activity item.
2895
- *
2896
- * @since 1.5.0
2897
- * @since 2.5.0 Use $activity_type instead of $activity_name for the second parameter.
2898
- *
2899
- * @param bool $can_comment Status on if activity can be commented on.
2900
- * @param string $activity_type Current activity type being checked on.
2901
- */
2902
- return apply_filters( 'bp_activity_can_comment', $can_comment, $activity_type );
2903
  }
2904
 
2905
  /**
2906
- * Determine whether a comment can be made on an activity reply item.
 
 
 
 
2907
  *
2908
- * @since 1.5.0
2909
  *
2910
- * @param bool|object $comment Activity comment.
2911
- * @return bool $can_comment True if comment can receive comments,
2912
- * otherwise false.
2913
  */
2914
- function bp_activity_can_comment_reply( $comment = false ) {
2915
-
2916
- // Assume activity can be commented on.
2917
  $can_comment = true;
2918
 
2919
- // Check that comment exists.
2920
- if ( empty( $comment ) ) {
2921
- $comment = bp_activity_current_comment();
2922
- }
2923
-
2924
- if ( ! empty( $comment ) ) {
2925
-
2926
- // Fall back on current comment in activity loop.
2927
- $comment_depth = isset( $comment->depth )
2928
- ? intval( $comment->depth )
2929
- : bp_activity_get_comment_depth( $comment );
2930
-
2931
- // Threading is turned on, so check the depth.
2932
- if ( get_option( 'thread_comments' ) ) {
2933
- $can_comment = (bool) ( $comment_depth < get_option( 'thread_comments_depth' ) );
2934
-
2935
- // No threading for comment replies if no threading for comments.
2936
- } else {
2937
- $can_comment = false;
2938
- }
2939
  }
2940
 
2941
- /**
2942
- * Filters whether a comment can be made on an activity reply item.
2943
- *
2944
- * @since 1.5.0
2945
- *
2946
- * @param bool $can_comment Status on if activity reply can be commented on.
2947
- * @param string $comment Current comment being checked on.
2948
- */
2949
- return (bool) apply_filters( 'bp_activity_can_comment_reply', $can_comment, $comment );
2950
  }
2951
 
2952
  /**
2953
- * Determine whether favorites are allowed.
2954
  *
2955
  * Defaults to true, but can be modified by plugins.
2956
  *
2957
- * @since 1.5.0
2958
  *
2959
- * @return bool True if comment can receive comments.
 
 
2960
  */
2961
  function bp_activity_can_favorite() {
 
2962
 
2963
- /**
2964
- * Filters whether or not users can favorite activity items.
2965
- *
2966
- * @since 1.5.0
2967
- *
2968
- * @param bool $value Whether or not favoriting is enabled.
2969
- */
2970
- return apply_filters( 'bp_activity_can_favorite', true );
2971
  }
2972
 
2973
  /**
2974
  * Output the total favorite count for a specified user.
2975
  *
2976
- * @since 1.2.0
2977
  *
2978
  * @see bp_get_total_favorite_count_for_user() for description of parameters.
 
2979
  *
2980
  * @param int $user_id See {@link bp_get_total_favorite_count_for_user()}.
2981
  */
@@ -2986,46 +2711,30 @@ function bp_total_favorite_count_for_user( $user_id = 0 ) {
2986
  /**
2987
  * Return the total favorite count for a specified user.
2988
  *
2989
- * @since 1.2.0
2990
  *
 
 
2991
  *
2992
  * @param int $user_id ID of user being queried. Default: displayed user ID.
2993
  * @return int The total favorite count for the specified user.
2994
  */
2995
  function bp_get_total_favorite_count_for_user( $user_id = 0 ) {
2996
- $retval = false;
2997
-
2998
- if ( bp_activity_can_favorite() ) {
2999
- // Default to displayed user if none is passed.
3000
- $user_id = empty( $user_id )
3001
- ? bp_displayed_user_id()
3002
- : $user_id;
3003
-
3004
- // Get user meta if user ID exists.
3005
- if ( ! empty( $user_id ) ) {
3006
- $retval = bp_activity_total_favorites_for_user( $user_id );
3007
- }
3008
  }
3009
 
3010
- /**
3011
- * Filters the total favorite count for a user.
3012
- *
3013
- * @since 1.2.0
3014
- * @since 2.6.0 Added the `$user_id` parameter.
3015
- *
3016
- * @param int|bool $retval Total favorite count for a user. False on no favorites.
3017
- * @param int $user_id ID of the queried user.
3018
- */
3019
- return apply_filters( 'bp_get_total_favorite_count_for_user', $retval, $user_id );
3020
  }
3021
-
3022
 
3023
  /**
3024
  * Output the total mention count for a specified user.
3025
  *
3026
- * @since 1.2.0
3027
  *
3028
  * @see bp_get_total_mention_count_for_user() for description of parameters.
 
3029
  *
3030
  * @param int $user_id See {@link bp_get_total_mention_count_for_user()}.
3031
  */
@@ -3036,79 +2745,60 @@ function bp_total_mention_count_for_user( $user_id = 0 ) {
3036
  /**
3037
  * Return the total mention count for a specified user.
3038
  *
3039
- * @since 1.2.0
3040
  *
 
 
3041
  *
3042
  * @param int $user_id ID of user being queried. Default: displayed user ID.
3043
  * @return int The total mention count for the specified user.
3044
  */
3045
  function bp_get_total_mention_count_for_user( $user_id = 0 ) {
 
 
 
3046
 
3047
- // Default to displayed user if none is passed.
3048
- $user_id = empty( $user_id )
3049
- ? bp_displayed_user_id()
3050
- : $user_id;
3051
-
3052
- // Get user meta if user ID exists.
3053
- $retval = ! empty( $user_id )
3054
- ? bp_get_user_meta( $user_id, 'bp_new_mention_count', true )
3055
- : false;
3056
-
3057
- /**
3058
- * Filters the total mention count for a user.
3059
- *
3060
- * @since 1.2.0
3061
- * @since 2.6.0 Added the `$user_id` parameter.
3062
- *
3063
- * @param int|bool $retval Total mention count for a user. False on no mentions.
3064
- * @param int $user_id ID of the queried user.
3065
- */
3066
- return apply_filters( 'bp_get_total_mention_count_for_user', $retval, $user_id );
3067
  }
 
3068
 
3069
  /**
3070
  * Output the public message link for displayed user.
3071
  *
3072
- * @since 1.2.0
3073
  *
 
3074
  */
3075
  function bp_send_public_message_link() {
3076
- echo esc_url( bp_get_send_public_message_link() );
3077
  }
3078
 
3079
  /**
3080
  * Return the public message link for the displayed user.
3081
  *
3082
- * @since 1.2.0
3083
  *
 
 
 
 
 
 
3084
  *
3085
  * @return string The public message link for the displayed user.
3086
  */
3087
  function bp_get_send_public_message_link() {
3088
 
3089
- // No link if not logged in, not looking at someone else's profile.
3090
- if ( ! is_user_logged_in() || ! bp_is_user() || bp_is_my_profile() ) {
3091
- $retval = '';
3092
- } else {
3093
- $args = array( 'r' => bp_get_displayed_user_mentionname() );
3094
- $url = add_query_arg( $args, bp_get_activity_directory_permalink() );
3095
- $retval = wp_nonce_url( $url );
3096
- }
3097
 
3098
- /**
3099
- * Filters the public message link for the displayed user.
3100
- *
3101
- * @since 1.2.0
3102
- *
3103
- * @param string $retval The URL for the public message link.
3104
- */
3105
- return apply_filters( 'bp_get_send_public_message_link', $retval );
3106
  }
3107
 
3108
  /**
3109
  * Recurse through all activity comments and return the activity comment IDs.
3110
  *
3111
- * @since 2.0.0
3112
  *
3113
  * @param array $activity Array of activities generated from {@link bp_activity_get()}.
3114
  * @param array $activity_ids Used for recursion purposes in this function.
@@ -3135,54 +2825,44 @@ function bp_activity_recurse_comments_activity_ids( $activity = array(), $activi
3135
  /**
3136
  * Output the mentioned user display name.
3137
  *
3138
- * @since 1.2.0
3139
  *
3140
  * @see bp_get_mentioned_user_display_name() for description of parameters.
 
3141
  *
3142
- * @param int|string|bool $user_id_or_username See {@link bp_get_mentioned_user_display_name()}.
3143
  */
3144
- function bp_mentioned_user_display_name( $user_id_or_username = false ) {
3145
  echo bp_get_mentioned_user_display_name( $user_id_or_username );
3146
  }
3147
 
3148
  /**
3149
- * Returns the mentioned user display name.
3150
  *
3151
- * @since 1.2.0
3152
  *
 
 
3153
  *
3154
- * @param int|string|bool $user_id_or_username User ID or username.
3155
  * @return string The mentioned user's display name.
3156
  */
3157
- function bp_get_mentioned_user_display_name( $user_id_or_username = false ) {
3158
-
3159
- // Get user display name.
3160
- $name = bp_core_get_user_displayname( $user_id_or_username );
3161
-
3162
- // If user somehow has no name, return this really lame string.
3163
- if ( empty( $name ) ) {
3164
  $name = __( 'a user', 'buddypress' );
3165
- }
3166
 
3167
- /**
3168
- * Filters the mentioned user display name.
3169
- *
3170
- * @since 1.2.0
3171
- *
3172
- * @param string $name Display name for the mentioned user.
3173
- * @param int|string $user_id_or_username User ID or username use for query.
3174
- */
3175
  return apply_filters( 'bp_get_mentioned_user_display_name', $name, $user_id_or_username );
3176
  }
3177
 
3178
  /**
3179
  * Output button for sending a public message (an @-mention).
3180
  *
3181
- * @since 1.2.0
3182
  *
3183
  * @see bp_get_send_public_message_button() for description of parameters.
 
3184
  *
3185
- * @param array|string $args See {@link bp_get_send_public_message_button()}.
3186
  */
3187
  function bp_send_public_message_button( $args = '' ) {
3188
  echo bp_get_send_public_message_button( $args );
@@ -3191,52 +2871,55 @@ function bp_send_public_message_button( $args = '' ) {
3191
  /**
3192
  * Return button for sending a public message (an @-mention).
3193
  *
3194
- * @since 1.2.0
3195
  *
 
 
 
 
3196
  *
3197
- * @param array|string $args {
3198
  * All arguments are optional. See {@link BP_Button} for complete
3199
  * descriptions.
3200
- * @type string $id Default: 'public_message'.
3201
- * @type string $component Default: 'activity'.
3202
- * @type bool $must_be_logged_in Default: true.
3203
- * @type bool $block_self Default: true.
3204
- * @type string $wrapper_id Default: 'post-mention'.
3205
- * @type string $link_href Default: the public message link for
3206
- * the current member in the loop.
3207
- * @type string $link_text Default: 'Public Message'.
3208
- * @type string $link_class Default: 'activity-button mention'.
 
 
3209
  * }
3210
  * @return string The button for sending a public message.
3211
  */
3212
  function bp_get_send_public_message_button( $args = '' ) {
3213
-
3214
- $r = bp_parse_args( $args, array(
3215
  'id' => 'public_message',
3216
  'component' => 'activity',
3217
  'must_be_logged_in' => true,
3218
  'block_self' => true,
3219
  'wrapper_id' => 'post-mention',
3220
  'link_href' => bp_get_send_public_message_link(),
 
3221
  'link_text' => __( 'Public Message', 'buddypress' ),
3222
  'link_class' => 'activity-button mention'
3223
- ) );
3224
 
3225
- /**
3226
- * Filters the public message button HTML.
3227
- *
3228
- * @since 1.2.10
3229
- *
3230
- * @param array $r Array of arguments for the public message button HTML.
3231
- */
3232
- return bp_get_button( apply_filters( 'bp_get_send_public_message_button', $r ) );
3233
  }
3234
 
3235
  /**
3236
  * Output the activity post form action.
3237
  *
3238
- * @since 1.2.0
3239
  *
 
3240
  */
3241
  function bp_activity_post_form_action() {
3242
  echo bp_get_activity_post_form_action();
@@ -3245,20 +2928,15 @@ function bp_activity_post_form_action() {
3245
  /**
3246
  * Return the activity post form action.
3247
  *
3248
- * @since 1.2.0
3249
  *
 
 
 
3250
  *
3251
  * @return string The activity post form action.
3252
  */
3253
  function bp_get_activity_post_form_action() {
3254
-
3255
- /**
3256
- * Filters the action url used for the activity post form.
3257
- *
3258
- * @since 1.2.0
3259
- *
3260
- * @param string $value URL to be used for the activity post form.
3261
- */
3262
  return apply_filters( 'bp_get_activity_post_form_action', home_url( bp_get_activity_root_slug() . '/post/' ) );
3263
  }
3264
 
@@ -3270,142 +2948,82 @@ function bp_activity_post_form_action() {
3270
  * Avatars are wrapped in <li> elements, but you've got to provide your own
3271
  * <ul> or <ol> wrapper markup.
3272
  *
3273
- * @since 1.7.0
3274
  *
3275
  * @see bp_core_fetch_avatar() for a description of arguments.
3276
  *
3277
  * @param array $args See {@link bp_core_fetch_avatar()}.
3278
  */
3279
  function bp_activity_comments_user_avatars( $args = array() ) {
3280
-
3281
- $r = bp_parse_args( $args, array(
3282
  'height' => false,
3283
  'html' => true,
3284
  'type' => 'thumb',
3285
  'width' => false,
3286
- ) );
3287
-
3288
- // Get the user IDs of everyone who has left a comment to the current activity item.
3289
- $user_ids = bp_activity_get_comments_user_ids();
3290
- $output = array();
3291
- $retval = '';
3292
-
3293
- if ( ! empty( $user_ids ) ) {
3294
- foreach ( (array) $user_ids as $user_id ) {
3295
-
3296
- // Skip an empty user ID.
3297
- if ( empty( $user_id ) ) {
3298
- continue;
3299
- }
3300
 
3301
- // Get profile link for this user.
3302
- $profile_link = bp_core_get_user_domain( $user_id );
3303
 
3304
- // Get avatar for this user.
3305
- $image_html = bp_core_fetch_avatar( array(
3306
- 'item_id' => $user_id,
3307
- 'height' => $r['height'],
3308
- 'html' => $r['html'],
3309
- 'type' => $r['type'],
3310
- 'width' => $r['width']
3311
- ) );
3312
 
3313
- // If user has link & avatar, add them to the output array.
3314
- if ( ! empty( $profile_link ) && ! empty( $image_html ) ) {
3315
- $output[] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $profile_link ), $image_html );
3316
- }
3317
- }
3318
 
3319
- // If output array is not empty, wrap everything in some list items.
3320
- if ( ! empty( $output ) ) {
3321
- $retval = '<li>' . implode( '</li><li>', $output ) . '</li>';
3322
- }
3323
  }
3324
 
3325
- /**
3326
- * Filters the list of linked avatars for users who have commented on the current activity item.
3327
- *
3328
- * @since 1.7.0
3329
- *
3330
- * @param string $retval HTML markup for the list of avatars.
3331
- * @param array $r Array of arguments used for each avatar.
3332
- * @param array $output Array of each avatar found, before imploded into single string.
3333
- */
3334
- echo apply_filters( 'bp_activity_comments_user_avatars', $retval, $r, $output );
3335
  }
3336
 
3337
  /**
3338
  * Return the IDs of every user who's left a comment on the current activity item.
3339
  *
3340
- * @since 1.7.0
3341
  *
3342
  * @return bool|array An array of IDs, or false if none are found.
3343
  */
3344
  function bp_activity_get_comments_user_ids() {
3345
- global $activities_template;
3346
-
3347
- $user_ids = ! empty( $activities_template->activity->children )
3348
- ? (array) bp_activity_recurse_comments_user_ids( $activities_template->activity->children )
3349
- : array();
3350
 
3351
- /**
3352
- * Filters the list of user IDs for the current activity item.
3353
- *
3354
- * @since 1.7.0
3355
- *
3356
- * @param array $value Array of unique user IDs for the current activity item.
3357
- */
3358
  return apply_filters( 'bp_activity_get_comments_user_ids', array_unique( $user_ids ) );
3359
  }
3360
 
3361
  /**
3362
  * Recurse through all activity comments and collect the IDs of the users who wrote them.
3363
  *
3364
- * @since 1.7.0
3365
  *
3366
  * @param array $comments Array of {@link BP_Activity_Activity} items.
3367
  * @return array Array of user IDs.
3368
  */
3369
- function bp_activity_recurse_comments_user_ids( array $comments = array() ) {
3370
-
3371
- // Default user ID's array.
3372
  $user_ids = array();
3373
 
3374
- // Loop through comments and try to get user ID's.
3375
- if ( ! empty( $comments ) ) {
3376
- foreach ( $comments as $comment ) {
3377
-
3378
- // If a user is a spammer, their activity items will have been
3379
- // automatically marked as spam. Skip these.
3380
- if ( ! empty( $comment->is_spam ) ) {
3381
- continue;
3382
- }
3383
 
3384
- // Add user ID to array.
3385
- $user_ids[] = $comment->user_id;
3386
 
3387
- // Check for commentception.
3388
- if ( ! empty( $comment->children ) ) {
3389
- $user_ids = array_merge( $user_ids, bp_activity_recurse_comments_user_ids( $comment->children ) );
3390
- }
3391
- }
3392
  }
3393
 
3394
- /**
3395
- * Filters the list of user IDs for the current activity comment item.
3396
- *
3397
- * @since 2.1.0
3398
- *
3399
- * @param array $user_ids Array of user IDs for the current activity comment item.
3400
- * @param array $comments Array of comments being checked for user IDs.
3401
- */
3402
- return apply_filters( 'bp_activity_recurse_comments_user_ids', $user_ids, $comments );
3403
  }
3404
 
3405
  /**
3406
  * Output the mentionname for the displayed user.
3407
  *
3408
- * @since 1.9.0
3409
  */
3410
  function bp_displayed_user_mentionname() {
3411
  echo bp_get_displayed_user_mentionname();
@@ -3413,82 +3031,58 @@ function bp_displayed_user_mentionname() {
3413
  /**
3414
  * Get the mentionname for the displayed user.
3415
  *
3416
- * @since 1.9.0
3417
  *
3418
  * @return string Mentionname for the displayed user, if available.
3419
  */
3420
  function bp_get_displayed_user_mentionname() {
3421
-
3422
- /**
3423
- * Filters the mentionname for the displayed user.
3424
- *
3425
- * @since 1.9.0
3426
- *
3427
- * @param string $value The mentionanme for the displayed user.
3428
- */
3429
  return apply_filters( 'bp_get_displayed_user_mentionname', bp_activity_get_user_mentionname( bp_displayed_user_id() ) );
3430
  }
3431
 
3432
  /**
3433
  * Echo a list of all registered activity types for use in dropdowns or checkbox lists.
3434
  *
3435
- * @since 1.7.0
3436
  *
3437
- * @param string $output Optional. Either 'select' or 'checkbox'. Default: 'select'.
3438
- * @param array|string $args {
3439
  * Optional extra arguments.
3440
- * @type string $checkbox_name When returning checkboxes, sets the 'name'
3441
- * attribute.
3442
- * @type array|string $selected A list of types that should be checked/
3443
- * selected.
3444
  * }
3445
  */
3446
  function bp_activity_types_list( $output = 'select', $args = '' ) {
3447
-
3448
- $args = bp_parse_args( $args, array(
3449
  'checkbox_name' => 'bp_activity_types',
3450
  'selected' => array(),
3451
- ) );
 
3452
 
3453
  $activities = bp_activity_get_types();
3454
  natsort( $activities );
3455
 
3456
- // Loop through the activity types and output markup.
3457
  foreach ( $activities as $type => $description ) {
3458
 
3459
- // See if we need to preselect the current type.
3460
  $checked = checked( true, in_array( $type, (array) $args['selected'] ), false );
3461
  $selected = selected( true, in_array( $type, (array) $args['selected'] ), false );
3462
 
3463
- // Switch output based on the element.
3464
- switch ( $output ) {
3465
- case 'select' :
3466
- printf( '<option value="%1$s" %2$s>%3$s</option>', esc_attr( $type ), $selected, esc_html( $description ) );
3467
- break;
3468
- case 'checkbox' :
3469
- printf( '<label style="" for="%1$s[]">%2$s<input type="checkbox" id="%1$s[]" name="%1$s[]" value="%3$s" %4$s/></label>', esc_attr( $args['checkbox_name'] ), esc_html( $description ), esc_attr( $args['checkbox_name'] ), esc_attr( $args['checkbox_name'] ), esc_attr( $type ), $checked );
3470
- break;
3471
- }
3472
 
3473
- /**
3474
- * Fires at the end of the listing of activity types.
3475
- *
3476
- * This is a variable action hook. The actual hook to use will depend on the output type specified.
3477
- * Two default hooks are bp_activity_types_list_select and bp_activity_types_list_checkbox.
3478
- *
3479
- * @since 1.7.0
3480
- *
3481
- * @param array $args Array of arguments passed into function.
3482
- * @param string $type Activity type being rendered in the output.
3483
- * @param string $description Description of the activity type being rendered.
3484
- */
3485
  do_action( 'bp_activity_types_list_' . $output, $args, $type, $description );
3486
  }
3487
 
3488
- // Backpat with BP-Default for dropdown boxes only.
3489
- if ( 'select' === $output ) {
3490
  do_action( 'bp_activity_filter_options' );
3491
- }
3492
  }
3493
 
3494
 
@@ -3497,8 +3091,9 @@ function bp_activity_types_list( $output = 'select', $args = '' ) {
3497
  /**
3498
  * Output the sitewide activity feed link.
3499
  *
3500
- * @since 1.0.0
3501
  *
 
3502
  */
3503
  function bp_sitewide_activity_feed_link() {
3504
  echo bp_get_sitewide_activity_feed_link();
@@ -3507,28 +3102,24 @@ function bp_sitewide_activity_feed_link() {
3507
  /**
3508
  * Returns the sitewide activity feed link.
3509
  *
3510
- * @since 1.0.0
3511
  *
 
 
 
3512
  *
3513
  * @return string The sitewide activity feed link.
3514
  */
3515
  function bp_get_sitewide_activity_feed_link() {
3516
-
3517
- /**
3518
- * Filters the sidewide activity feed link.
3519
- *
3520
- * @since 1.0.0
3521
- *
3522
- * @param string $value The feed link for sitewide activity.
3523
- */
3524
  return apply_filters( 'bp_get_sitewide_activity_feed_link', bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/feed/' );
3525
  }
3526
 
3527
  /**
3528
  * Output the member activity feed link.
3529
  *
3530
- * @since 1.2.0
3531
  *
 
3532
  */
3533
  function bp_member_activity_feed_link() {
3534
  echo bp_get_member_activity_feed_link();
@@ -3537,67 +3128,58 @@ function bp_member_activity_feed_link() {
3537
  /**
3538
  * Output the member activity feed link.
3539
  *
3540
- * @since 1.0.0
3541
- * @deprecated 1.2.0
3542
  *
3543
  * @todo properly deprecate in favor of bp_member_activity_feed_link().
3544
  *
 
3545
  */
3546
  function bp_activities_member_rss_link() { echo bp_get_member_activity_feed_link(); }
3547
 
3548
  /**
3549
  * Return the member activity feed link.
3550
  *
3551
- * @since 1.2.0
3552
  *
 
 
 
 
 
 
 
 
3553
  *
3554
  * @return string $link The member activity feed link.
3555
  */
3556
  function bp_get_member_activity_feed_link() {
3557
 
3558
- // Single member activity feed link.
3559
- if ( bp_is_profile_component() || bp_is_current_action( 'just-me' ) ) {
3560
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/feed/';
3561
-
3562
- // Friend feed link.
3563
- } elseif ( bp_is_active( 'friends' ) && bp_is_current_action( bp_get_friends_slug() ) ) {
3564
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_friends_slug() . '/feed/';
3565
-
3566
- // Group feed link.
3567
- } elseif ( bp_is_active( 'groups' ) && bp_is_current_action( bp_get_groups_slug() ) ) {
3568
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_groups_slug() . '/feed/';
3569
-
3570
- // Favorites activity feed link.
3571
- } elseif ( 'favorites' === bp_current_action() ) {
3572
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/favorites/feed/';
3573
-
3574
- // Mentions activity feed link.
3575
- } elseif ( ( 'mentions' === bp_current_action() ) && bp_activity_do_mentions() ) {
3576
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/mentions/feed/';
3577
-
3578
- // No feed link.
3579
- } else {
3580
  $link = '';
3581
- }
3582
 
3583
- /**
3584
- * Filters the member activity feed link.
3585
- *
3586
- * @since 1.0.0
3587
- *
3588
- * @param string $link URL for the member activity feed.
3589
- */
3590
  return apply_filters( 'bp_get_activities_member_rss_link', $link );
3591
  }
3592
 
3593
  /**
3594
  * Return the member activity feed link.
3595
  *
3596
- * @since 1.0.0
3597
- * @deprecated 1.2.0
3598
  *
3599
  * @todo properly deprecate in favor of bp_get_member_activity_feed_link().
3600
  *
 
3601
  *
3602
  * @return string The member activity feed link.
3603
  */
@@ -3609,8 +3191,9 @@ function bp_activities_member_rss_link() { echo bp_get_member_activity_feed_link
3609
  /**
3610
  * Outputs the activity feed item guid.
3611
  *
3612
- * @since 1.0.0
3613
  *
 
3614
  */
3615
  function bp_activity_feed_item_guid() {
3616
  echo bp_get_activity_feed_item_guid();
@@ -3619,30 +3202,25 @@ function bp_activity_feed_item_guid() {
3619
  /**
3620
  * Returns the activity feed item guid.
3621
  *
3622
- * @since 1.2.0
3623
  *
3624
  * @global object $activities_template {@link BP_Activity_Template}
 
3625
  *
3626
  * @return string The activity feed item guid.
3627
  */
3628
  function bp_get_activity_feed_item_guid() {
3629
  global $activities_template;
3630
 
3631
- /**
3632
- * Filters the activity feed item guid.
3633
- *
3634
- * @since 1.1.3
3635
- *
3636
- * @param string $value Calculated md5 value for the activity feed item.
3637
- */
3638
  return apply_filters( 'bp_get_activity_feed_item_guid', md5( $activities_template->activity->date_recorded . '-' . $activities_template->activity->content ) );
3639
  }
3640
 
3641
  /**
3642
  * Output the activity feed item title.
3643
  *
3644
- * @since 1.0.0
3645
  *
 
3646
  */
3647
  function bp_activity_feed_item_title() {
3648
  echo bp_get_activity_feed_item_title();
@@ -3651,83 +3229,69 @@ function bp_activity_feed_item_title() {
3651
  /**
3652
  * Return the activity feed item title.
3653
  *
3654
- * @since 1.0.0
3655
  *
3656
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
 
3657
  *
3658
  * @return string $title The activity feed item title.
3659
  */
3660
  function bp_get_activity_feed_item_title() {
3661
  global $activities_template;
3662
 
3663
- if ( !empty( $activities_template->activity->action ) ) {
3664
  $content = $activities_template->activity->action;
3665
- } else {
3666
  $content = $activities_template->activity->content;
3667
- }
3668
 
3669
  $content = explode( '<span', $content );
3670
- $title = strip_tags( ent2ncr( trim( convert_chars( $content[0] ) ) ) );
3671
 
3672
- if ( ':' === substr( $title, -1 ) ) {
3673
  $title = substr( $title, 0, -1 );
3674
- }
3675
 
3676
- if ( 'activity_update' === $activities_template->activity->type ) {
3677
  $title .= ': ' . strip_tags( ent2ncr( trim( convert_chars( bp_create_excerpt( $activities_template->activity->content, 70, array( 'ending' => " [&#133;]" ) ) ) ) ) );
3678
- }
3679
 
3680
- /**
3681
- * Filters the activity feed item title.
3682
- *
3683
- * @since 1.0.0
3684
- *
3685
- * @param string $title The title for the activity feed item.
3686
- */
3687
  return apply_filters( 'bp_get_activity_feed_item_title', $title );
3688
  }
3689
 
3690
  /**
3691
- * Output the activity feed item link.
3692
  *
3693
- * @since 1.0.0
3694
  *
 
3695
  */
3696
  function bp_activity_feed_item_link() {
3697
  echo bp_get_activity_feed_item_link();
3698
  }
3699
 
3700
  /**
3701
- * Return the activity feed item link.
3702
  *
3703
- * @since 1.0.0
3704
  *
3705
  * @global object $activities_template {@link BP_Activity_Template}
 
3706
  *
3707
  * @return string The activity feed item link.
3708
  */
3709
  function bp_get_activity_feed_item_link() {
3710
  global $activities_template;
3711
 
3712
- $retval = ! empty( $activities_template->activity->primary_link )
3713
- ? $activities_template->activity->primary_link
3714
- : '';
3715
-
3716
- /**
3717
- * Filters the activity feed item link.
3718
- *
3719
- * @since 1.0.0
3720
- *
3721
- * @param string $retval The URL for the activity feed item.
3722
- */
3723
- return apply_filters( 'bp_get_activity_feed_item_link', $retval );
3724
  }
3725
 
3726
  /**
3727
  * Output the activity feed item date.
3728
  *
3729
- * @since 1.0.0
3730
  *
 
3731
  */
3732
  function bp_activity_feed_item_date() {
3733
  echo bp_get_activity_feed_item_date();
@@ -3736,34 +3300,25 @@ function bp_activity_feed_item_date() {
3736
  /**
3737
  * Return the activity feed item date.
3738
  *
3739
- * @since 1.0.0
3740
  *
3741
  * @global object $activities_template {@link BP_Activity_Template}
 
3742
  *
3743
  * @return string The activity feed item date.
3744
  */
3745
  function bp_get_activity_feed_item_date() {
3746
  global $activities_template;
3747
 
3748
- $retval = ! empty( $activities_template->activity->date_recorded )
3749
- ? $activities_template->activity->date_recorded
3750
- : '';
3751
-
3752
- /**
3753
- * Filters the activity feed item date.
3754
- *
3755
- * @since 1.0.0
3756
- *
3757
- * @param string $retval The date for the activity feed item.
3758
- */
3759
- return apply_filters( 'bp_get_activity_feed_item_date', $retval );
3760
  }
3761
 
3762
  /**
3763
  * Output the activity feed item description.
3764
  *
3765
- * @since 1.0.0
3766
  *
 
3767
  */
3768
  function bp_activity_feed_item_description() {
3769
  echo bp_get_activity_feed_item_description();
@@ -3772,40 +3327,32 @@ function bp_activity_feed_item_description() {
3772
  /**
3773
  * Return the activity feed item description.
3774
  *
3775
- * @since 1.0.0
3776
  *
3777
  * @global object $activities_template {@link BP_Activity_Template}
 
 
 
3778
  *
3779
  * @return string The activity feed item description.
3780
  */
3781
  function bp_get_activity_feed_item_description() {
3782
  global $activities_template;
3783
 
3784
- // Get the content, if exists.
3785
- $content = ! empty( $activities_template->activity->content )
3786
- ? $activities_template->activity->content
3787
- : '';
3788
-
3789
- // Perform a few string conversions on the content, if it's not empty.
3790
- if ( ! empty( $content ) ) {
3791
- $content = ent2ncr( convert_chars( str_replace( '%s', '', $content ) ) );
3792
- }
3793
 
3794
- /**
3795
- * Filters the activity feed item description.
3796
- *
3797
- * @since 1.0.0
3798
- *
3799
- * @param string $content The description for the activity feed item.
3800
- */
3801
- return apply_filters( 'bp_get_activity_feed_item_description', $content );
3802
  }
3803
 
3804
  /**
3805
  * Template tag so we can hook activity feed to <head>.
3806
  *
3807
- * @since 1.5.0
3808
  *
 
 
3809
  */
3810
  function bp_activity_sitewide_feed() {
3811
  ?>
@@ -3815,67 +3362,3 @@ function bp_activity_sitewide_feed() {
3815
  <?php
3816
  }
3817
  add_action( 'bp_head', 'bp_activity_sitewide_feed' );
3818
-
3819
- /**
3820
- * Display available filters depending on the scope.
3821
- *
3822
- * @since 2.1.0
3823
- *
3824
- * @param string $context The current context. 'activity', 'member',
3825
- * 'member_groups', 'group'.
3826
- */
3827
- function bp_activity_show_filters( $context = '' ) {
3828
- echo bp_get_activity_show_filters( $context );
3829
- }
3830
- /**
3831
- * Get available filters depending on the scope.
3832
- *
3833
- * @since 2.1.0
3834
- *
3835
- * @param string $context The current context. 'activity', 'member',
3836
- * 'member_groups', 'group'.
3837
- *
3838
- * @return string HTML for <option> values.
3839
- */
3840
- function bp_get_activity_show_filters( $context = '' ) {
3841
- $filters = array();
3842
- $actions = bp_activity_get_actions_for_context( $context );
3843
- foreach ( $actions as $action ) {
3844
- // Friends activity collapses two filters into one.
3845
- if ( in_array( $action['key'], array( 'friendship_accepted', 'friendship_created' ) ) ) {
3846
- $action['key'] = 'friendship_accepted,friendship_created';
3847
- }
3848
-
3849
- $filters[ $action['key'] ] = $action['label'];
3850
- }
3851
-
3852
- /**
3853
- * Filters the options available in the activity filter dropdown.
3854
- *
3855
- * @since 2.2.0
3856
- *
3857
- * @param array $filters Array of filter options for the given context, in the following format: $option_value => $option_name.
3858
- * @param string $context Context for the filter. 'activity', 'member', 'member_groups', 'group'.
3859
- */
3860
- $filters = apply_filters( 'bp_get_activity_show_filters_options', $filters, $context );
3861
-
3862
- // Build the options output.
3863
- $output = '';
3864
-
3865
- if ( ! empty( $filters ) ) {
3866
- foreach ( $filters as $value => $filter ) {
3867
- $output .= '<option value="' . esc_attr( $value ) . '">' . esc_html( $filter ) . '</option>' . "\n";
3868
- }
3869
- }
3870
-
3871
- /**
3872
- * Filters the HTML markup result for the activity filter dropdown.
3873
- *
3874
- * @since 2.1.0
3875
- *
3876
- * @param string $output HTML output for the activity filter dropdown.
3877
- * @param array $filters Array of filter options for the given context, in the following format: $option_value => $option_name.
3878
- * @param string $context Context for the filter. 'activity', 'member', 'member_groups', 'group'.
3879
- */
3880
- return apply_filters( 'bp_get_activity_show_filters', $output, $filters, $context );
3881
- }
1
  <?php
2
+
3
  /**
4
  * BuddyPress Activity Template Functions.
5
  *
6
  * @package BuddyPress
7
  * @subpackage ActivityTemplate
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
  * Output the activity component slug.
15
  *
16
+ * @since BuddyPress (1.5)
17
  *
18
+ * @uses bp_get_activity_slug()
19
  */
20
  function bp_activity_slug() {
21
  echo bp_get_activity_slug();
23
  /**
24
  * Return the activity component slug.
25
  *
26
+ * @since BuddyPress (1.5)
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
  return apply_filters( 'bp_get_activity_slug', buddypress()->activity->slug );
34
  }
35
 
36
  /**
37
  * Output the activity component root slug.
38
  *
39
+ * @since BuddyPress (1.5)
40
  *
41
+ * @uses bp_get_activity_root_slug()
42
  */
43
  function bp_activity_root_slug() {
44
  echo bp_get_activity_root_slug();
46
  /**
47
  * Return the activity component root slug.
48
  *
49
+ * @since BuddyPress (1.5)
50
  *
51
+ * @uses apply_filters() To call the 'bp_get_activity_root_slug' hook.
52
  *
53
  * @return string The activity component root slug.
54
  */
55
  function bp_get_activity_root_slug() {
 
 
 
 
 
 
 
 
56
  return apply_filters( 'bp_get_activity_root_slug', buddypress()->activity->root_slug );
57
  }
58
 
59
  /**
60
  * Output activity directory permalink.
61
  *
62
+ * @since BuddyPress (1.5)
63
  *
64
+ * @uses bp_get_activity_directory_permalink()
65
  */
66
  function bp_activity_directory_permalink() {
67
+ echo bp_get_activity_directory_permalink();
68
  }
69
  /**
70
+ * Return activity directory permalink
71
  *
72
+ * @since BuddyPress (1.5)
73
  *
74
+ * @uses traisingslashit()
75
+ * @uses bp_get_root_domain()
76
+ * @uses bp_get_activity_root_slug()
77
+ * @uses apply_filters() To call the 'bp_get_activity_directory_permalink' hook.
78
  *
79
  * @return string Activity directory permalink.
80
  */
81
  function bp_get_activity_directory_permalink() {
 
 
 
 
 
 
 
 
82
  return apply_filters( 'bp_get_activity_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_activity_root_slug() ) );
83
  }
84
 
85
+ /**
86
+ * The main activity template loop class.
87
+ *
88
+ * This is responsible for loading a group of activity items and displaying them.
89
+ *
90
+ * @since BuddyPress (1.0)
91
+ */
92
+ class BP_Activity_Template {
93
+ var $current_activity = -1;
94
+ var $activity_count;
95
+ var $total_activity_count;
96
+ var $activities;
97
+ var $activity;
98
+
99
+ var $in_the_loop;
100
+
101
+ var $pag_page;
102
+ var $pag_num;
103
+ var $pag_links;
104
+
105
+ var $full_name;
106
+
107
+ /**
108
+ * Constructor method.
109
+ *
110
+ * The arguments passed to this class constructor are of the same
111
+ * format as {@link BP_Activity_Activity::get()}.
112
+ *
113
+ * @see BP_Activity_Activity::get() for a description of the argument
114
+ * structure, as well as default values.
115
+ *
116
+ * @param array $args {
117
+ * Array of arguments. Supports all arguments from
118
+ * BP_Activity_Activity::get(), as well as 'page_arg' and
119
+ * 'include'. Default values for 'per_page' and 'display_comments'
120
+ * differ from the originating function, and are described below.
121
+ * @type string $page_arg The string used as a query parameter in
122
+ * pagination links. Default: 'acpage'.
123
+ * @type array|bool $include Pass an array of activity IDs to
124
+ * retrieve only those items, or false to noop the 'include'
125
+ * parameter. 'include' differs from 'in' in that 'in' forms
126
+ * an IN clause that works in conjunction with other filters
127
+ * passed to the function, while 'include' is interpreted as
128
+ * an exact list of items to retrieve, which skips all other
129
+ * filter-related parameters. Default: false.
130
+ * @type int|bool $per_page Default: 20.
131
+ * @type string|bool $display_comments Default: 'threaded'.
132
+ * }
133
+ */
134
+ function __construct( $args ) {
135
+ global $bp;
136
+
137
+ // Backward compatibility with old method of passing arguments
138
+ if ( !is_array( $args ) || func_num_args() > 1 ) {
139
+ _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__ ) );
140
+
141
+ $old_args_keys = array(
142
+ 0 => 'page',
143
+ 1 => 'per_page',
144
+ 2 => 'max',
145
+ 3 => 'include',
146
+ 4 => 'sort',
147
+ 5 => 'filter',
148
+ 6 => 'search_terms',
149
+ 7 => 'display_comments',
150
+ 8 => 'show_hidden',
151
+ 9 => 'exclude',
152
+ 10 => 'in',
153
+ 11 => 'spam',
154
+ 12 => 'page_arg'
155
+ );
156
+
157
+ $func_args = func_get_args();
158
+ $args = bp_core_parse_args_array( $old_args_keys, $func_args );
159
+ }
160
+
161
+ $defaults = array(
162
+ 'page' => 1,
163
+ 'per_page' => 20,
164
+ 'page_arg' => 'acpage',
165
+ 'max' => false,
166
+ 'sort' => false,
167
+ 'include' => false,
168
+ 'exclude' => false,
169
+ 'in' => false,
170
+ 'filter' => false,
171
+ 'search_terms' => false,
172
+ 'meta_query' => false,
173
+ 'display_comments' => 'threaded',
174
+ 'show_hidden' => false,
175
+ 'spam' => 'ham_only',
176
+ 'update_meta_cache' => true,
177
+ );
178
+ $r = wp_parse_args( $args, $defaults );
179
+ extract( $r );
180
+
181
+ $this->pag_page = isset( $_REQUEST[$page_arg] ) ? intval( $_REQUEST[$page_arg] ) : $page;
182
+ $this->pag_num = isset( $_REQUEST['num'] ) ? intval( $_REQUEST['num'] ) : $per_page;
183
+
184
+ // Check if blog/forum replies are disabled
185
+ $this->disable_blogforum_replies = isset( $bp->site_options['bp-disable-blogforum-comments'] ) ? $bp->site_options['bp-disable-blogforum-comments'] : false;
186
+
187
+ // Get an array of the logged in user's favorite activities
188
+ $this->my_favs = maybe_unserialize( bp_get_user_meta( bp_loggedin_user_id(), 'bp_favorite_activities', true ) );
189
+
190
+ // Fetch specific activity items based on ID's
191
+ if ( !empty( $include ) ) {
192
+ $this->activities = bp_activity_get_specific( array(
193
+ 'activity_ids' => explode( ',', $include ),
194
+ 'max' => $max,
195
+ 'page' => $this->pag_page,
196
+ 'per_page' => $this->pag_num,
197
+ 'sort' => $sort,
198
+ 'display_comments' => $display_comments,
199
+ 'show_hidden' => $show_hidden,
200
+ 'spam' => $spam,
201
+ 'update_meta_cache' => $update_meta_cache,
202
+ ) );
203
+
204
+ // Fetch all activity items
205
+ } else {
206
+ $this->activities = bp_activity_get( array(
207
+ 'display_comments' => $display_comments,
208
+ 'max' => $max,
209
+ 'per_page' => $this->pag_num,
210
+ 'page' => $this->pag_page,
211
+ 'sort' => $sort,
212
+ 'search_terms' => $search_terms,
213
+ 'meta_query' => $meta_query,
214
+ 'filter' => $filter,
215
+ 'show_hidden' => $show_hidden,
216
+ 'exclude' => $exclude,
217
+ 'in' => $in,
218
+ 'spam' => $spam,
219
+ 'update_meta_cache' => $update_meta_cache,
220
+ ) );
221
+ }
222
+
223
+ if ( !$max || $max >= (int) $this->activities['total'] )
224
+ $this->total_activity_count = (int) $this->activities['total'];
225
+ else
226
+ $this->total_activity_count = (int) $max;
227
+
228
+ $this->activities = $this->activities['activities'];
229
+
230
+ if ( $max ) {
231
+ if ( $max >= count($this->activities) ) {
232
+ $this->activity_count = count( $this->activities );
233
+ } else {
234
+ $this->activity_count = (int) $max;
235
+ }
236
+ } else {
237
+ $this->activity_count = count( $this->activities );
238
+ }
239
+
240
+ $this->full_name = bp_get_displayed_user_fullname();
241
+
242
+ // Fetch parent content for activity comments so we do not have to query in the loop
243
+ foreach ( (array) $this->activities as $activity ) {
244
+ if ( 'activity_comment' != $activity->type )
245
+ continue;
246
+
247
+ $parent_ids[] = $activity->item_id;
248
+ }
249
+
250
+ if ( !empty( $parent_ids ) )
251
+ $activity_parents = bp_activity_get_specific( array( 'activity_ids' => $parent_ids ) );
252
+
253
+ if ( !empty( $activity_parents['activities'] ) ) {
254
+ foreach( $activity_parents['activities'] as $parent )
255
+ $this->activity_parents[$parent->id] = $parent;
256
+
257
+ unset( $activity_parents );
258
+ }
259
+
260
+ if ( (int) $this->total_activity_count && (int) $this->pag_num ) {
261
+ $this->pag_links = paginate_links( array(
262
+ 'base' => add_query_arg( $page_arg, '%#%' ),
263
+ 'format' => '',
264
+ 'total' => ceil( (int) $this->total_activity_count / (int) $this->pag_num ),
265
+ 'current' => (int) $this->pag_page,
266
+ 'prev_text' => _x( '&larr;', 'Activity pagination previous text', 'buddypress' ),
267
+ 'next_text' => _x( '&rarr;', 'Activity pagination next text', 'buddypress' ),
268
+ 'mid_size' => 1
269
+ ) );
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Whether there are activity items available in the loop.
275
+ *
276
+ * @see bp_has_activities()
277
+ *
278
+ * @return bool True if there are items in the loop, otherwise false.
279
+ */
280
+ function has_activities() {
281
+ if ( $this->activity_count )
282
+ return true;
283
+
284
+ return false;
285
+ }
286
+
287
+ /**
288
+ * Set up the next activity item and iterate index.
289
+ *
290
+ * @return object The next activity item to iterate over.
291
+ */
292
+ function next_activity() {
293
+ $this->current_activity++;
294
+ $this->activity = $this->activities[$this->current_activity];
295
+
296
+ return $this->activity;
297
+ }
298
+
299
+ /**
300
+ * Rewind the posts and reset post index.
301
+ */
302
+ function rewind_activities() {
303
+ $this->current_activity = -1;
304
+ if ( $this->activity_count > 0 ) {
305
+ $this->activity = $this->activities[0];
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Whether there are activity items left in the loop to iterate over.
311
+ *
312
+ * This method is used by {@link bp_activities()} as part of the while loop
313
+ * that controls iteration inside the activities loop, eg:
314
+ * while ( bp_activities() ) { ...
315
+ *
316
+ * @see bp_activities()
317
+ *
318
+ * @return bool True if there are more activity items to show,
319
+ * otherwise false.
320
+ */
321
+ function user_activities() {
322
+ if ( $this->current_activity + 1 < $this->activity_count ) {
323
+ return true;
324
+ } elseif ( $this->current_activity + 1 == $this->activity_count ) {
325
+ do_action('activity_loop_end');
326
+ // Do some cleaning up after the loop
327
+ $this->rewind_activities();
328
+ }
329
+
330
+ $this->in_the_loop = false;
331
+ return false;
332
+ }
333
+
334
+ /**
335
+ * Set up the current activity item inside the loop.
336
+ *
337
+ * Used by {@link bp_the_activity()} to set up the current activity item
338
+ * data while looping, so that template tags used during that iteration
339
+ * make reference to the current activity item.
340
+ *
341
+ * @see bp_the_activity()
342
+ */
343
+ function the_activity() {
344
+
345
+ $this->in_the_loop = true;
346
+ $this->activity = $this->next_activity();
347
+
348
+ if ( is_array( $this->activity ) )
349
+ $this->activity = (object) $this->activity;
350
+
351
+ if ( $this->current_activity == 0 ) // loop has just started
352
+ do_action('activity_loop_start');
353
+ }
354
+ }
355
+
356
  /**
357
  * Initialize the activity loop.
358
  *
360
  * $activities_template global, enabling the use of BuddyPress templates and
361
  * template functions to display a list of activity items.
362
  *
363
+ * @since BuddyPress (1.0)
 
364
  *
365
  * @global object $activities_template {@link BP_Activity_Template}
366
+ * @global object $bp BuddyPress global settings.
367
+ * @uses groups_is_user_member()
368
+ * @uses bp_current_action()
369
+ * @uses bp_is_current_action()
370
+ * @uses bp_get_activity_slug()
371
+ * @uses bp_action_variable()
372
+ * @uses wp_parse_args()
373
+ * @uses bp_is_active()
374
+ * @uses friends_get_friend_user_ids()
375
+ * @uses groups_get_user_groups()
376
+ * @uses bp_activity_get_user_favorites()
377
+ * @uses apply_filters() To call the 'bp_has_activities' hook.
378
+ *
379
+ * @param array $args {
380
+ * Arguments for limiting the contents of the activity loop. Most
381
+ * arguments are in the same format as {@link BP_Activity_Activity::get()}.
382
+ * However, because the format of the arguments accepted here differs in
383
+ * a number of ways, and because bp_has_activities() determines some
384
+ * default arguments in a dynamic fashion, we list all accepted arguments
385
+ * here as well.
386
+ *
387
+ * Arguments can be passed as an associative array, or as a URL query
388
+ * string (eg, 'user_id=4&display_comments=threaded').
389
+ *
390
+ * @type int $page Which page of results to fetch. Using page=1 without
391
+ * per_page will result in no pagination. Default: 1.
392
+ * @type int|bool $per_page Number of results per page. Default: 20.
393
+ * @type string $page_arg The string used as a query parameter in
394
+ * pagination links. Default: 'acpage'.
395
+ * @type int|bool $max Maximum number of results to return.
396
+ * Default: false (unlimited).
397
+ * @type string $sort 'ASC' or 'DESC'. Default: 'DESC'.
398
+ * @type array|bool $exclude Array of activity IDs to exclude. Default: false.
399
+ * @type array|bool $in Array of IDs to limit query by (IN). 'in' is
400
+ * intended to be used in conjunction with other filter parameters.
401
+ * Default: false.
402
+ * @type array|bool $include Array of exact activity IDs to query.
403
+ * Providing an 'include' array will override all other filters
404
+ * passed in the argument array. When viewing a the permalink page
405
+ * for a single activity item, this value defaults to the ID of that
406
+ * item. Otherwise the default is false.
407
+ * @type array $meta_query Limit by activitymeta by passing an array of
408
+ * meta_query conditions. See {@link WP_Meta_Query::queries} for a
409
+ * description of the syntax.
410
+ * @type string $search_terms Limit results by a search term. Default: false.
411
+ * @type string|bool $scope Use one of BuddyPress's pre-built filters. In
412
+ * each case, the term 'current user' refers to the displayed user
413
+ * when looking at a user profile, and otherwise to the logged-in user.
414
+ * - 'just-me' retrieves items belonging only to the logged-in user;
415
+ * this is equivalent to passing a 'user_id' argument
416
+ * - 'friends' retrieves items belonging to the friends of the
417
+ * current user
418
+ * - 'groups' retrieves items associated with the groups to which
419
+ * the current user belongs
420
+ * - 'favorites' retrieves the current user's favorited activity
421
+ * items
422
+ * - 'mentions' retrieves activity items where the current user has
423
+ * received an @-mention
424
+ * The default value of 'scope' is set to one of the above if that
425
+ * value appears in the appropriate place in the URL; eg, 'scope' will
426
+ * be 'groups' when visiting http://example.com/members/joe/activity/groups/.
427
+ * Otherwise defaults to false.
428
+ * @type int|array|bool $user_id The ID(s) of user(s) whose activity should
429
+ * be fetched. Pass a single ID or an array of IDs. When viewing a
430
+ * user profile page (but not that user's activity subpages, ie My
431
+ * Friends, My Groups, etc), 'user_id' defaults to the ID of the
432
+ * displayed user. Otherwise the default is false.
433
+ * @type string|array|bool $object Filters by the `component` column in the
434
+ * database, which is generally the component ID in the case of
435
+ * BuddyPress components, or the plugin slug in the case of plugins.
436
+ * For example, 'groups' will limit results to those that are
437
+ * associated with the BP Groups component. Accepts a single
438
+ * component string, or an array of multiple components. Defaults to
439
+ * 'groups' when viewing the page of a single group, the My Groups
440
+ * activity filter, or the Activity > Groups filter of a user profile.
441
+ * Otherwise defaults to false.
442
+ * @type string|array|bool $action Filters by the `type` column in the
443
+ * database, which is a string categorizing the activity item (eg,
444
+ * 'new_blog_post', 'created_group'). Accepts a single type string,
445
+ * or an array of multiple types. Defaults to false.
446
+ * @type int|array|bool $primary_id Filters by the `item_id` column in the
447
+ * database. The meaning of 'primary_id' differs between components/
448
+ * types; for example, in the case of 'created_group', 'primary_id'
449
+ * is the ID of the group. Accepts a single ID, or an array of
450
+ * multiple IDs. When viewing a single group, defaults to the current
451
+ * group ID. When viewing a user's Groups stream page, defaults to
452
+ * the IDs of the user's groups. Otherwise defaults to false.
453
+ * @type int|array|bool $secondary_id Filters by the `secondary_item_id`
454
+ * column in the database. The meaning of 'secondary_id' differs
455
+ * between components/types. Accepts a single ID, or an array of
456
+ * multiple IDs. Defaults to false.
457
+ * @type int $offset Return only activity items with an ID greater than or
458
+ * equal to this one. Note that providing an offset will disable
459
+ * pagination. Default: false.
460
+ * @type string|bool $display_comments How to handle activity comments.
461
+ * Possible values:
462
+ * - 'threaded' - comments appear in a threaded tree, under their
463
+ * parent items
464
+ * - 'stream' - the activity stream is presented in a flat manner,
465
+ * with comments sorted in chronological order alongside other
466
+ * activity items
467
+ * - false - don't fetch activity comments at all
468
+ * Default: 'threaded'.
469
+ * @type bool $show_hidden Whether to show items marked hide_sitewide.
470
+ * Defaults to false, except in the following cases:
471
+ * - User is viewing his own activity stream
472
+ * - User is viewing the activity stream of a non-public group of
473
+ * which he is a member
474
+ * @type bool $show_hidden Normally defaults to false, except when:
475
+ * - a user is viewing his own activity stream
476
+ * - a user is viewing the activity stream of a non-public group of
477
+ * which he is a member
478
+ * @type string|bool $spam Spam status. 'ham_only', 'spam_only', or false
479
+ * to show all activity regardless of spam status. Default: 'ham_only'.
480
+ * @type bool $populate_extras Whether to pre-fetch the activity metadata
481
+ * for the queried items. Default: true.
482
  * }
483
  * @return bool Returns true when activities are found, otherwise false.
484
  */
485
  function bp_has_activities( $args = '' ) {
486
+ global $activities_template, $bp;
487
+
488
+ /***
489
+ * Set the defaults based on the current page. Any of these will be overridden
490
+ * if arguments are directly passed into the loop. Custom plugins should always
491
+ * pass their parameters directly to the loop.
492
+ */
493
+ $user_id = false;
494
+ $include = false;
495
+ $exclude = false;
496
+ $in = false;
497
+ $show_hidden = false;
498
+ $object = false;
499
+ $primary_id = false;
500
+
501
+ // User filtering
502
+ if ( bp_displayed_user_id() )
503
+ $user_id = bp_displayed_user_id();
504
+
505
+ // Group filtering
506
+ if ( !empty( $bp->groups->current_group ) ) {
507
+ $object = $bp->groups->id;
508
+ $primary_id = $bp->groups->current_group->id;
509
+
510
+ if ( ( 'public' != $bp->groups->current_group->status ) && ( groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) || bp_current_user_can( 'bp_moderate' ) ) )
511
+ $show_hidden = true;
512
+ }
513
+
514
+ // The default scope should recognize custom slugs
515
+ if ( array_key_exists( bp_current_action(), (array) $bp->loaded_components ) ) {
516
+ $scope = $bp->loaded_components[bp_current_action()];
517
+ }
518
+ else
519
+ $scope = bp_current_action();
520
+
521
+ // Support for permalinks on single item pages: /groups/my-group/activity/124/
522
+ if ( bp_is_current_action( bp_get_activity_slug() ) )
523
+ $include = bp_action_variable( 0 );
524
+
525
+ // Note: any params used for filtering can be a single value, or multiple values comma separated.
526
+ $defaults = array(
527
+ 'display_comments' => 'threaded', // false for none, stream/threaded - show comments in the stream or threaded under items
528
+ 'include' => $include, // pass an activity_id or string of IDs comma-separated
529
+ 'exclude' => $exclude, // pass an activity_id or string of IDs comma-separated
530
+ 'in' => $in, // comma-separated list or array of activity IDs among which to search
531
+ 'sort' => 'DESC', // sort DESC or ASC
532
+ 'page' => 1, // which page to load
533
+ 'per_page' => 20, // number of items per page
534
+ 'max' => false, // max number to return
 
 
 
 
 
 
 
 
 
 
535
  'show_hidden' => $show_hidden, // Show activity items that are hidden site-wide?
536
+ 'spam' => 'ham_only', // Hide spammed items
537
 
538
+ 'page_arg' => 'acpage', // See https://buddypress.trac.wordpress.org/ticket/3679
539
+
540
+ // Scope - pre-built activity filters for a user (friends/groups/favorites/mentions)
541
  'scope' => $scope,
542
 
543
  // Filtering
544
+ 'user_id' => $user_id, // user_id to filter on
545
+ 'object' => $object, // object to filter on e.g. groups, profile, status, friends
546
+ 'action' => false, // action to filter on e.g. activity_update, new_forum_post, profile_updated
547
+ 'primary_id' => $primary_id, // object ID to filter on e.g. a group_id or forum_id or blog_id etc.
548
+ 'secondary_id' => false, // secondary object ID to filter on e.g. a post_id
549
+ 'offset' => false, // return only items >= this ID
550
+ 'since' => false, // return only items recorded since this Y-m-d H:i:s date
551
+
552
+ 'meta_query' => false, // filter on activity meta. See WP_Meta_Query for format
553
+
554
+ // Searching
555
+ 'search_terms' => false, // specify terms to search on
 
 
556
  'update_meta_cache' => true,
557
+ );
558
 
559
+ $r = bp_parse_args( $args, $defaults, 'has_activities' );
560
+ extract( $r );
 
561
 
562
  // Translate various values for 'display_comments'
563
  // This allows disabling comments via ?display_comments=0
564
+ // or =none or =false. Final true is a strict type check. See #5029
565
+ if ( in_array( $display_comments, array( 0, '0', 'none', 'false' ), true ) ) {
566
+ $display_comments = false;
567
  }
568
 
569
+ // Ignore pagination if an offset is passed
570
+ if ( ! empty( $offset ) ) {
571
+ $page = 0;
572
  }
573
 
574
+ if ( empty( $search_terms ) && ! empty( $_REQUEST['s'] ) )
575
+ $search_terms = $_REQUEST['s'];
 
 
576
 
577
+ // If you have passed a "scope" then this will override any filters you have passed.
578
+ if ( 'just-me' == $scope || 'friends' == $scope || 'groups' == $scope || 'favorites' == $scope || 'mentions' == $scope ) {
579
+ if ( 'just-me' == $scope )
580
+ $display_comments = 'stream';
581
 
582
+ // determine which user_id applies
583
+ if ( empty( $user_id ) )
584
+ $user_id = bp_displayed_user_id() ? bp_displayed_user_id() : bp_loggedin_user_id();
585
+
586
+ // are we displaying user specific activity?
587
+ if ( is_numeric( $user_id ) ) {
588
+ $show_hidden = ( $user_id == bp_loggedin_user_id() && $scope != 'friends' ) ? 1 : 0;
589
+
590
+ switch ( $scope ) {
591
+ case 'friends':
592
+ if ( bp_is_active( 'friends' ) )
593
+ $friends = friends_get_friend_user_ids( $user_id );
594
+ if ( empty( $friends ) )
595
+ return false;
596
+
597
+ $user_id = implode( ',', (array) $friends );
598
+ break;
599
+ case 'groups':
600
+ if ( bp_is_active( 'groups' ) ) {
601
+ $groups = groups_get_user_groups( $user_id );
602
+ if ( empty( $groups['groups'] ) )
603
+ return false;
604
+
605
+ $object = $bp->groups->id;
606
+ $primary_id = implode( ',', (array) $groups['groups'] );
607
+
608
+ $user_id = 0;
609
+ }
610
+ break;
611
+ case 'favorites':
612
+ $favs = bp_activity_get_user_favorites( $user_id );
613
+ if ( empty( $favs ) )
614
+ return false;
615
+
616
+ $in = implode( ',', (array) $favs );
617
+ $display_comments = true;
618
+ $user_id = 0;
619
+ break;
620
+ case 'mentions':
621
+
622
+ // Are mentions disabled?
623
+ if ( ! bp_activity_do_mentions() ) {
624
+ return false;
625
+ }
626
 
627
+ // Start search at @ symbol and stop search at closing tag delimiter.
628
+ $search_terms = '@' . bp_activity_get_user_mentionname( $user_id ) . '<';
629
+ $display_comments = 'stream';
630
+ $user_id = 0;
631
+ break;
632
+ }
633
+ }
634
  }
635
 
636
+ // Do not exceed the maximum per page
637
+ if ( !empty( $max ) && ( (int) $per_page > (int) $max ) )
638
+ $per_page = $max;
639
+
640
+ // Support for basic filters in earlier BP versions is disabled by default. To enable, put
641
+ // add_filter( 'bp_activity_enable_afilter_support', '__return_true' );
642
+ // into bp-custom.php or your theme's functions.php
643
+ if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) )
644
+ $filter = array( 'object' => $_GET['afilter'] );
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 );
647
+ else
648
+ $filter = false;
649
+
650
+ // If specific activity items have been requested, override the $hide_spam argument. This prevents backpat errors with AJAX.
651
+ if ( !empty( $include ) && ( 'ham_only' == $spam ) )
652
+ $spam = 'all';
653
+
654
+ $template_args = array(
655
+ 'page' => $page,
656
+ 'per_page' => $per_page,
657
+ 'page_arg' => $page_arg,
658
+ 'max' => $max,
659
+ 'sort' => $sort,
660
+ 'include' => $include,
661
+ 'exclude' => $exclude,
662
+ 'in' => $in,
663
+ 'filter' => $filter,
664
+ 'search_terms' => $search_terms,
665
+ 'meta_query' => $meta_query,
666
+ 'display_comments' => $display_comments,
667
+ 'show_hidden' => $show_hidden,
668
+ 'spam' => $spam,
669
+ 'update_meta_cache' => $update_meta_cache,
670
+ );
671
 
672
+ $activities_template = new BP_Activity_Template( $template_args );
673
 
674
+ return apply_filters( 'bp_has_activities', $activities_template->has_activities(), $activities_template, $template_args );
 
 
 
 
 
 
 
 
 
675
  }
676
 
677
  /**
678
  * Determine if there are still activities left in the loop.
679
  *
680
+ * @since BuddyPress (1.0)
681
  *
682
  * @global object $activities_template {@link BP_Activity_Template}
683
+ * @uses BP_Activity_Template::user_activities() {@link BP_Activity_Template::user_activities()}
684
  *
685
  * @return bool Returns true when activities are found.
686
  */
692
  /**
693
  * Get the current activity object in the loop.
694
  *
695
+ * @since BuddyPress (1.0)
696
  *
697
  * @global object $activities_template {@link BP_Activity_Template}
698
+ * @uses BP_Activity_Template::the_activity() {@link BP_Activity_Template::the_activity()}
699
  *
700
  * @return object The current activity within the loop.
701
  */
704
  return $activities_template->the_activity();
705
  }
706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  /**
708
  * Output the activity pagination count.
709
  *
710
+ * @since BuddyPress (1.0)
711
  *
712
  * @global object $activities_template {@link BP_Activity_Template}
713
+ * @uses BP_Activity_Template::the_activity() {@link BP_Activity_Template::the_activity()}
714
  */
715
  function bp_activity_pagination_count() {
716
  echo bp_get_activity_pagination_count();
719
  /**
720
  * Return the activity pagination count.
721
  *
722
+ * @since BuddyPress (1.2)
723
  *
724
  * @global object $activities_template {@link BP_Activity_Template}
725
+ * @uses bp_core_number_format()
726
  *
727
  * @return string The pagination text.
728
  */
734
  $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 ) );
735
  $total = bp_core_number_format( $activities_template->total_activity_count );
736
 
737
+ return sprintf( _n( 'Viewing item %1$s to %2$s (of %3$s item)', 'Viewing item %1$s to %2$s (of %3$s items)', $total, 'buddypress' ), $from_num, $to_num, $total );
 
 
 
 
 
 
738
  }
739
 
740
  /**
741
  * Output the activity pagination links.
742
  *
743
+ * @since BuddyPress (1.0)
744
  *
745
+ * @uses bp_get_activity_pagination_links()
746
  */
747
  function bp_activity_pagination_links() {
748
  echo bp_get_activity_pagination_links();
751
  /**
752
  * Return the activity pagination links.
753
  *
754
+ * @since BuddyPress (1.0)
755
  *
756
  * @global object $activities_template {@link BP_Activity_Template}
757
+ * @uses apply_filters() To call the 'bp_get_activity_pagination_links' hook.
758
  *
759
  * @return string The pagination links.
760
  */
761
  function bp_get_activity_pagination_links() {
762
  global $activities_template;
763
 
 
 
 
 
 
 
 
764
  return apply_filters( 'bp_get_activity_pagination_links', $activities_template->pag_links );
765
  }
766
 
767
  /**
768
  * Return true when there are more activity items to be shown than currently appear.
769
  *
770
+ * @since BuddyPress (1.5)
771
  *
772
  * @global object $activities_template {@link BP_Activity_Template}
773
+ * @uses apply_filters() To call the 'bp_activity_has_more_items' hook.
774
  *
775
  * @return bool $has_more_items True if more items, false if not.
776
  */
777
  function bp_activity_has_more_items() {
778
  global $activities_template;
779
 
780
+ $remaining_pages = 0;
 
 
 
 
 
 
 
781
 
782
+ if ( ! empty( $activities_template->pag_page ) ) {
783
+ $remaining_pages = floor( ( $activities_template->total_activity_count - 1 ) / ( $activities_template->pag_num * $activities_template->pag_page ) );
784
  }
785
 
786
+ $has_more_items = (int) $remaining_pages ? true : false;
787
+
 
 
 
 
 
788
  return apply_filters( 'bp_activity_has_more_items', $has_more_items );
789
  }
790
 
791
  /**
792
  * Output the activity count.
793
  *
794
+ * @since BuddyPress (1.2)
795
  *
796
+ * @uses bp_get_activity_count()
797
  */
798
  function bp_activity_count() {
799
  echo bp_get_activity_count();
802
  /**
803
  * Return the activity count.
804
  *
805
+ * @since BuddyPress (1.2)
806
  *
807
  * @global object $activities_template {@link BP_Activity_Template}
808
+ * @uses apply_filters() To call the 'bp_get_activity_count' hook.
809
  *
810
  * @return int The activity count.
811
  */
812
  function bp_get_activity_count() {
813
  global $activities_template;
814
 
 
 
 
 
 
 
 
815
  return apply_filters( 'bp_get_activity_count', (int) $activities_template->activity_count );
816
  }
817
 
818
  /**
819
  * Output the number of activities per page.
820
  *
821
+ * @since BuddyPress (1.2)
822
  *
823
+ * @uses bp_get_activity_per_page()
824
  */
825
  function bp_activity_per_page() {
826
  echo bp_get_activity_per_page();
829
  /**
830
  * Return the number of activities per page.
831
  *
832
+ * @since BuddyPress (1.2)
833
  *
834
  * @global object $activities_template {@link BP_Activity_Template}
835
+ * @uses apply_filters() To call the 'bp_get_activity_per_page' hook.
836
  *
837
  * @return int The activities per page.
838
  */
839
  function bp_get_activity_per_page() {
840
  global $activities_template;
841
 
 
 
 
 
 
 
 
842
  return apply_filters( 'bp_get_activity_per_page', (int) $activities_template->pag_num );
843
  }
844
 
845
  /**
846
  * Output the activities title.
847
  *
848
+ * @since BuddyPress (1.0)
849
  *
850
+ * @uses bp_get_activities_title()
851
  * @todo Deprecate.
852
  */
853
  function bp_activities_title() {
857
  /**
858
  * Return the activities title.
859
  *
860
+ * @since BuddyPress (1.0)
861
  *
862
  * @global string $bp_activity_title
863
+ * @uses apply_filters() To call the 'bp_get_activities_title' hook.
864
  * @todo Deprecate.
865
  *
866
+ * @return int The activities title.
867
  */
868
  function bp_get_activities_title() {
869
  global $bp_activity_title;
870
 
 
 
 
 
 
 
 
871
  return apply_filters( 'bp_get_activities_title', $bp_activity_title );
872
  }
873
 
874
  /**
875
  * {@internal Missing Description}
876
  *
877
+ * @since BuddyPress (1.0)
878
  *
879
+ * @uses bp_get_activities_no_activity()
880
  * @todo Deprecate.
881
  */
882
  function bp_activities_no_activity() {
886
  /**
887
  * {@internal Missing Description}
888
  *
889
+ * @since BuddyPress (1.0)
890
  *
891
  * @global string $bp_activity_no_activity
892
+ * @uses apply_filters() To call the 'bp_get_activities_no_activity' hook
893
  * @todo Deprecate.
894
  *
895
  * @return string
897
  function bp_get_activities_no_activity() {
898
  global $bp_activity_no_activity;
899
 
 
 
 
 
 
 
 
900
  return apply_filters( 'bp_get_activities_no_activity', $bp_activity_no_activity );
901
  }
902
 
903
  /**
904
  * Output the activity ID.
905
  *
906
+ * @since BuddyPress (1.2)
907
  *
908
+ * @uses bp_get_activity_id()
909
  */
910
  function bp_activity_id() {
911
  echo bp_get_activity_id();
914
  /**
915
  * Return the activity ID.
916
  *
917
+ * @since BuddyPress (1.2)
918
  *
919
  * @global object $activities_template {@link BP_Activity_Template}
920
+ * @uses apply_filters() To call the 'bp_get_activity_id' hook.
921
  *
922
  * @return int The activity ID.
923
  */
924
  function bp_get_activity_id() {
925
  global $activities_template;
 
 
 
 
 
 
 
 
926
  return apply_filters( 'bp_get_activity_id', $activities_template->activity->id );
927
  }
928
 
929
  /**
930
  * Output the activity item ID.
931
  *
932
+ * @since BuddyPress (1.2)
933
  *
934
+ * @uses bp_get_activity_item_id()
935
  */
936
  function bp_activity_item_id() {
937
  echo bp_get_activity_item_id();
940
  /**
941
  * Return the activity item ID.
942
  *
943
+ * @since BuddyPress (1.2)
944
  *
945
  * @global object $activities_template {@link BP_Activity_Template}
946
+ * @uses apply_filters() To call the 'bp_get_activity_item_id' hook.
947
  *
948
  * @return int The activity item ID.
949
  */
950
  function bp_get_activity_item_id() {
951
  global $activities_template;
 
 
 
 
 
 
 
 
952
  return apply_filters( 'bp_get_activity_item_id', $activities_template->activity->item_id );
953
  }
954
 
955
  /**
956
  * Output the activity secondary item ID.
957
  *
958
+ * @since BuddyPress (1.2)
959
  *
960
+ * @uses bp_get_activity_secondary_item_id()
961
  */
962
  function bp_activity_secondary_item_id() {
963
  echo bp_get_activity_secondary_item_id();
966
  /**
967
  * Return the activity secondary item ID.
968
  *
969
+ * @since BuddyPress (1.2)
970
  *
971
  * @global object $activities_template {@link BP_Activity_Template}
972
+ * @uses apply_filters() To call the 'bp_get_activity_secondary_item_id' hook.
973
  *
974
  * @return int The activity secondary item ID.
975
  */
976
  function bp_get_activity_secondary_item_id() {
977
  global $activities_template;
 
 
 
 
 
 
 
 
978
  return apply_filters( 'bp_get_activity_secondary_item_id', $activities_template->activity->secondary_item_id );
979
  }
980
 
981
  /**
982
  * Output the date the activity was recorded.
983
  *
984
+ * @since BuddyPress (1.2)
985
  *
986
+ * @uses bp_get_activity_date_recorded()
987
  */
988
  function bp_activity_date_recorded() {
989
  echo bp_get_activity_date_recorded();
992
  /**
993
  * Return the date the activity was recorded.
994
  *
995
+ * @since BuddyPress (1.2)
996
  *
997
  * @global object $activities_template {@link BP_Activity_Template}
998
+ * @uses apply_filters() To call the 'bp_get_activity_date_recorded' hook.
999
  *
1000
  * @return string The date the activity was recorded.
1001
  */
1002
  function bp_get_activity_date_recorded() {
1003
  global $activities_template;
 
 
 
 
 
 
 
 
1004
  return apply_filters( 'bp_get_activity_date_recorded', $activities_template->activity->date_recorded );
1005
  }
1006
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1007
  /**
1008
  * Output the activity object name.
1009
  *
1010
+ * @since BuddyPress (1.2)
1011
  *
1012
+ * @uses bp_get_activity_object_name()
1013
  */
1014
  function bp_activity_object_name() {
1015
  echo bp_get_activity_object_name();
1018
  /**
1019
  * Return the activity object name.
1020
  *
1021
+ * @since BuddyPress (1.2)
1022
  *
1023
  * @global object $activities_template {@link BP_Activity_Template}
1024
+ * @uses apply_filters() To call the 'bp_get_activity_object_name' hook.
1025
  *
1026
  * @return string The activity object name.
1027
  */
1028
  function bp_get_activity_object_name() {
1029
  global $activities_template;
 
 
 
 
 
 
 
 
1030
  return apply_filters( 'bp_get_activity_object_name', $activities_template->activity->component );
1031
  }
1032
 
1033
  /**
1034
  * Output the activity type.
1035
  *
1036
+ * @since BuddyPress (1.2)
1037
  *
1038
+ * @uses bp_get_activity_type()
1039
  */
1040
  function bp_activity_type() {
1041
  echo bp_get_activity_type();
1044
  /**
1045
  * Return the activity type.
1046
  *
1047
+ * @since BuddyPress (1.2)
1048
  *
1049
  * @global object $activities_template {@link BP_Activity_Template}
1050
+ * @uses apply_filters() To call the 'bp_get_activity_type' hook.
1051
  *
1052
  * @return string The activity type.
1053
  */
1054
  function bp_get_activity_type() {
1055
  global $activities_template;
 
 
 
 
 
 
 
 
1056
  return apply_filters( 'bp_get_activity_type', $activities_template->activity->type );
1057
  }
1058
 
1061
  *
1062
  * Just a wrapper for bp_activity_type().
1063
  *
1064
+ * @since BuddyPress (1.2)
1065
+ * @deprecated BuddyPress (1.5)
1066
  *
1067
  * @todo Properly deprecate in favor of bp_activity_type() and
1068
+ * remove redundant echo
1069
  *
1070
+ * @uses bp_activity_type()
1071
  */
1072
  function bp_activity_action_name() { echo bp_activity_type(); }
1073
 
1076
  *
1077
  * Just a wrapper for bp_get_activity_type().
1078
  *
1079
+ * @since BuddyPress (1.2)
1080
+ * @deprecated BuddyPress (1.5)
1081
  *
1082
  * @todo Properly deprecate in favor of bp_get_activity_type().
1083
  *
1084
+ * @uses bp_get_activity_type()
1085
  *
1086
  * @return string The activity type.
1087
  */
1090
  /**
1091
  * Output the activity user ID.
1092
  *
1093
+ * @since BuddyPress (1.1)
1094
  *
1095
+ * @uses bp_get_activity_user_id()
1096
  */
1097
  function bp_activity_user_id() {
1098
  echo bp_get_activity_user_id();
1101
  /**
1102
  * Return the activity user ID.
1103
  *
1104
+ * @since BuddyPress (1.1)
1105
  *
1106
  * @global object $activities_template {@link BP_Activity_Template}
1107
+ * @uses apply_filters() To call the 'bp_get_activity_user_id' hook.
1108
  *
1109
  * @return int The activity user ID.
1110
  */
1111
  function bp_get_activity_user_id() {
1112
  global $activities_template;
 
 
 
 
 
 
 
 
1113
  return apply_filters( 'bp_get_activity_user_id', $activities_template->activity->user_id );
1114
  }
1115
 
1116
  /**
1117
  * Output the activity user link.
1118
  *
1119
+ * @since BuddyPress (1.2)
1120
  *
1121
+ * @uses bp_get_activity_user_link()
1122
  */
1123
  function bp_activity_user_link() {
1124
  echo bp_get_activity_user_link();
1127
  /**
1128
  * Return the activity user link.
1129
  *
1130
+ * @since BuddyPress (1.2)
1131
  *
1132
  * @global object $activities_template {@link BP_Activity_Template}
1133
+ * @uses bp_core_get_user_domain()
1134
+ * @uses apply_filters() To call the 'bp_get_activity_user_link' hook.
1135
  *
1136
  * @return string $link The activity user link.
1137
  */
1138
  function bp_get_activity_user_link() {
1139
  global $activities_template;
1140
 
1141
+ if ( empty( $activities_template->activity->user_id ) )
1142
  $link = $activities_template->activity->primary_link;
1143
+ else
1144
  $link = bp_core_get_user_domain( $activities_template->activity->user_id, $activities_template->activity->user_nicename, $activities_template->activity->user_login );
 
1145
 
 
 
 
 
 
 
 
1146
  return apply_filters( 'bp_get_activity_user_link', $link );
1147
  }
1148
 
1149
  /**
1150
  * Output the avatar of the user that performed the action.
1151
  *
1152
+ * @since BuddyPress (1.1)
1153
  *
1154
  * @see bp_get_activity_avatar() for description of arguments.
1155
+ * @uses bp_get_activity_avatar()
1156
  *
1157
+ * @param array $args See {@link bp_get_activity_avatar()} for description.
1158
  */
1159
  function bp_activity_avatar( $args = '' ) {
1160
  echo bp_get_activity_avatar( $args );
1162
  /**
1163
  * Return the avatar of the user that performed the action.
1164
  *
1165
+ * @since BuddyPress (1.1)
1166
  *
1167
  * @see bp_core_fetch_avatar() For a description of the arguments.
1168
  * @global object $activities_template {@link BP_Activity_Template}
1169
+ * @global object $bp BuddyPress global settings
1170
+ * @uses bp_is_single_activity()
1171
+ * @uses wp_parse_args()
1172
+ * @uses apply_filters() To call the 'bp_get_activity_avatar_object_' . $current_activity_item->component hook
1173
+ * @uses apply_filters() To call the 'bp_get_activity_avatar_item_id' hook
1174
+ * @uses bp_core_fetch_avatar()
1175
+ * @uses apply_filters() To call the 'bp_get_activity_avatar' hook
1176
+ *
1177
+ * @param array $args {
1178
  * Arguments are listed here with an explanation of their defaults.
1179
  * For more information about the arguments, see
1180
  * {@link bp_core_fetch_avatar()}.
1181
+ * @type string $alt Default: 'Profile picture of [user name]' if
1182
+ * activity user name is available, otherwise 'Profile picture'.
1183
+ * @type string $class Default: 'avatar'.
1184
+ * @type string|bool $email Default: Email of the activity's
1185
+ * associated user, if available. Otherwise false.
1186
+ * @type string $type Default: 'full' when viewing a single activity
1187
+ * permalink page, otherwise 'thumb'.
1188
+ * @type int|bool $user_id Default: ID of the activity's user.
1189
  * }
1190
  * @return string User avatar string.
1191
  */
1194
 
1195
  $bp = buddypress();
1196
 
1197
+ // On activity permalink pages, default to the full-size avatar
1198
  $type_default = bp_is_single_activity() ? 'full' : 'thumb';
1199
 
1200
  // Within the activity comment loop, the current activity should be set
1201
  // to current_comment. Otherwise, just use activity.
1202
  $current_activity_item = isset( $activities_template->activity->current_comment ) ? $activities_template->activity->current_comment : $activities_template->activity;
1203
 
1204
+ // Activity user display name
1205
  $dn_default = isset( $current_activity_item->display_name ) ? $current_activity_item->display_name : '';
1206
 
1207
+ // Prepend some descriptive text to alt
1208
  $alt_default = !empty( $dn_default ) ? sprintf( __( 'Profile picture of %s', 'buddypress' ), $dn_default ) : __( 'Profile picture', 'buddypress' );
1209
 
1210
  $defaults = array(
1220
 
1221
  if ( !isset( $height ) && !isset( $width ) ) {
1222
 
1223
+ // Backpat
1224
  if ( isset( $bp->avatar->full->height ) || isset( $bp->avatar->thumb->height ) ) {
1225
  $height = ( 'full' == $type ) ? $bp->avatar->full->height : $bp->avatar->thumb->height;
1226
  } else {
1227
  $height = 20;
1228
  }
1229
 
1230
+ // Backpat
1231
  if ( isset( $bp->avatar->full->width ) || isset( $bp->avatar->thumb->width ) ) {
1232
  $width = ( 'full' == $type ) ? $bp->avatar->full->width : $bp->avatar->thumb->width;
1233
  } else {
1235
  }
1236
  }
1237
 
1238
+ // Primary activity avatar is always a user, but can be modified via a filter
 
 
 
 
 
 
 
 
 
 
1239
  $object = apply_filters( 'bp_get_activity_avatar_object_' . $current_activity_item->component, 'user' );
1240
  $item_id = !empty( $user_id ) ? $user_id : $current_activity_item->user_id;
 
 
 
 
 
 
 
 
1241
  $item_id = apply_filters( 'bp_get_activity_avatar_item_id', $item_id );
1242
 
1243
+ // If this is a user object pass the users' email address for Gravatar so we don't have to refetch it.
1244
+ if ( 'user' == $object && empty( $user_id ) && empty( $email ) && isset( $current_activity_item->user_email ) )
1245
  $email = $current_activity_item->user_email;
 
1246
 
 
 
 
 
 
 
 
1247
  return apply_filters( 'bp_get_activity_avatar', bp_core_fetch_avatar( array(
1248
  'item_id' => $item_id,
1249
  'object' => $object,
1259
  /**
1260
  * Output the avatar of the object that action was performed on.
1261
  *
1262
+ * @since BuddyPress (1.2)
1263
  *
1264
  * @see bp_get_activity_secondary_avatar() for description of arguments.
1265
+ * @uses bp_get_activity_secondary_avatar()
1266
  *
1267
+ * @param array $args See {@link bp_get_activity_secondary_avatar} for description.
1268
  */
1269
  function bp_activity_secondary_avatar( $args = '' ) {
1270
  echo bp_get_activity_secondary_avatar( $args );
1271
  }
1272
 
1273
  /**
1274
+ * Return the avatar of the object that action was performed on
1275
  *
1276
+ * @since BuddyPress (1.2)
1277
  *
1278
  * @see bp_core_fetch_avatar() for description of arguments.
1279
  * @global object $activities_template {@link BP_Activity_Template}
1280
+ * @uses wp_parse_args()
1281
+ * @uses get_blog_option()
1282
+ * @uses apply_filters() To call the 'bp_get_activity_secondary_avatar_object_' . $activities_template->activity->component hook.
1283
+ * @uses apply_filters() To call the 'bp_get_activity_secondary_avatar_item_id' hook.
1284
+ * @uses bp_core_fetch_avatar()
1285
+ * @uses apply_filters() To call the 'bp_get_activity_secondary_avatar' hook.
1286
+ *
1287
+ * @param array $args {
1288
  * For a complete description of arguments, see {@link bp_core_fetch_avatar()}.
1289
+ * @type string $alt Default value varies based on current activity
1290
+ * item component.
1291
+ * @type string $type Default: 'full' when viewing a single activity
1292
+ * permalink page, otherwise 'thumb'.
1293
+ * @type string $class Default: 'avatar'.
1294
+ * @type string|bool $email Default: email of the activity's user.
1295
+ * @type int|bool $user_id Default: ID of the activity's user.
1296
  * }
1297
+ * @return string The secondary avatar
1298
  */
1299
  function bp_get_activity_secondary_avatar( $args = '' ) {
1300
  global $activities_template;
1311
  ) );
1312
  extract( $r, EXTR_SKIP );
1313
 
1314
+ // Set item_id and object (default to user)
1315
  switch ( $activities_template->activity->component ) {
1316
  case 'groups' :
 
 
 
 
1317
  $object = 'group';
1318
  $item_id = $activities_template->activity->item_id;
1319
  $link = '';
1320
  $name = '';
1321
 
1322
+ // Only if groups is active
1323
  if ( bp_is_active( 'groups' ) ) {
1324
+ $group = groups_get_group( array(
1325
+ 'group_id' => $item_id,
1326
+ 'populate_extras' => false,
1327
+ 'update_meta_cache' => false,
1328
+ ) );
1329
  $link = bp_get_group_permalink( $group );
1330
  $name = $group->name;
1331
  }
1372
  break;
1373
  }
1374
 
1375
+ // Allow object, item_id, and link to be filtered
 
 
 
 
 
 
 
 
 
 
1376
  $object = apply_filters( 'bp_get_activity_secondary_avatar_object_' . $activities_template->activity->component, $object );
 
 
 
 
 
 
 
 
1377
  $item_id = apply_filters( 'bp_get_activity_secondary_avatar_item_id', $item_id );
1378
 
1379
+ // If we have no item_id or object, there is no avatar to display
1380
  if ( empty( $item_id ) || empty( $object ) ) {
1381
  return false;
1382
  }
1383
 
1384
+ // Get the avatar
1385
  $avatar = bp_core_fetch_avatar( array(
1386
  'item_id' => $item_id,
1387
  'object' => $object,
1394
  ) );
1395
 
1396
  if ( !empty( $linked ) ) {
 
 
 
 
 
 
 
 
 
1397
  $link = apply_filters( 'bp_get_activity_secondary_avatar_link', $link, $activities_template->activity->component );
1398
 
 
 
 
 
 
 
 
 
 
1399
  return sprintf( '<a href="%s" class="%s">%s</a>',
1400
  $link,
1401
  $link_class,
1402
+ apply_filters( 'bp_get_activity_secondary_avatar', $avatar )
1403
  );
1404
  }
1405
 
1406
+ // else
1407
  return apply_filters( 'bp_get_activity_secondary_avatar', $avatar );
1408
  }
1409
 
1410
  /**
1411
+ * Output the activity action
1412
  *
1413
+ * @since BuddyPress (1.2)
1414
  *
1415
+ * @param array $args See bp_get_activity_action()
1416
+ * @uses bp_get_activity_action()
1417
  */
1418
  function bp_activity_action( $args = array() ) {
1419
  echo bp_get_activity_action( $args );
1420
  }
1421
 
1422
  /**
1423
+ * Return the activity action
1424
  *
1425
+ * @since BuddyPress (1.2)
1426
  *
1427
  * @global object $activities_template {@link BP_Activity_Template}
1428
+ * @param array $args Only parameter is "no_timestamp". If true, timestamp is shown in output.
1429
+ * @uses apply_filters_ref_array() To call the 'bp_get_activity_action_pre_meta' hook
1430
+ * @uses bp_insert_activity_meta()
1431
+ * @uses apply_filters_ref_array() To call the 'bp_get_activity_action' hook.
1432
  *
1433
  * @param array $args {
1434
  * @type bool $no_timestamp Whether to exclude the timestamp.
1435
  * }
 
1436
  * @return string The activity action.
1437
  */
1438
  function bp_get_activity_action( $args = array() ) {
1439
  global $activities_template;
1440
 
1441
+ $defaults = array(
1442
  'no_timestamp' => false,
1443
+ );
1444
 
1445
+ $args = wp_parse_args( $args, $defaults );
1446
+ extract( $args, EXTR_SKIP );
1447
+
1448
+ $action = $activities_template->activity->action;
1449
+ $action = apply_filters_ref_array( 'bp_get_activity_action_pre_meta', array( $action, &$activities_template->activity, $args ) );
 
 
 
 
 
 
 
1450
 
1451
+ if ( ! empty( $action ) && ! $no_timestamp )
 
1452
  $action = bp_insert_activity_meta( $action );
 
1453
 
1454
+ return apply_filters_ref_array( 'bp_get_activity_action', array( $action, &$activities_template->activity, $args ) );
 
 
 
 
 
 
 
 
 
 
 
1455
  }
1456
 
1457
  /**
1458
+ * Output the activity content body
1459
  *
1460
+ * @since BuddyPress (1.2)
1461
  *
1462
+ * @uses bp_get_activity_content_body()
1463
  */
1464
  function bp_activity_content_body() {
1465
  echo bp_get_activity_content_body();
1466
  }
1467
 
1468
  /**
1469
+ * Return the activity content body
1470
  *
1471
+ * @since BuddyPress (1.2)
1472
  *
1473
  * @global object $activities_template {@link BP_Activity_Template}
1474
+ * @uses bp_insert_activity_meta()
1475
+ * @uses apply_filters_ref_array() To call the 'bp_get_activity_content_body' hook.
1476
  *
1477
  * @return string The activity content body.
1478
  */
1479
  function bp_get_activity_content_body() {
1480
  global $activities_template;
1481
 
1482
+ // Backwards compatibility if action is not being used
1483
+ if ( empty( $activities_template->activity->action ) && !empty( $activities_template->activity->content ) )
1484
  $activities_template->activity->content = bp_insert_activity_meta( $activities_template->activity->content );
 
1485
 
 
 
 
 
 
 
 
 
1486
  return apply_filters_ref_array( 'bp_get_activity_content_body', array( $activities_template->activity->content, &$activities_template->activity ) );
1487
  }
1488
 
1489
  /**
1490
  * Does the activity have content?
1491
  *
1492
+ * @since BuddyPress (1.2)
1493
  *
1494
  * @global object $activities_template {@link BP_Activity_Template}
1495
  *
1498
  function bp_activity_has_content() {
1499
  global $activities_template;
1500
 
1501
+ if ( !empty( $activities_template->activity->content ) )
1502
  return true;
 
1503
 
1504
  return false;
1505
  }
1507
  /**
1508
  * Output the activity content.
1509
  *
1510
+ * @since BuddyPress (1.0)
1511
+ * @deprecated BuddyPress (1.5)
1512
  *
1513
  * @todo properly deprecate this function.
1514
  *
1515
+ * @uses bp_get_activity_content()
1516
  */
1517
  function bp_activity_content() {
1518
  echo bp_get_activity_content();
1521
  /**
1522
  * Return the activity content.
1523
  *
1524
+ * @since BuddyPress (1.0)
1525
+ * @deprecated BuddyPress (1.5)
1526
  *
1527
  * @todo properly deprecate this function.
1528
  *
1529
+ * @uses bp_get_activity_action()
1530
+ * @uses bp_get_activity_content_body()
1531
+ * @uses apply_filters() To call the 'bp_get_activity_content' hook.
1532
  *
1533
  * @return string The activity content.
1534
  */
1535
  function bp_get_activity_content() {
 
1536
  /**
1537
  * If you want to filter activity update content, please use
1538
+ * the filter 'bp_get_activity_content_body'
1539
  *
1540
+ * This function is mainly for backwards comptibility.
1541
  */
1542
+
1543
  $content = bp_get_activity_action() . ' ' . bp_get_activity_content_body();
1544
  return apply_filters( 'bp_get_activity_content', $content );
1545
  }
1550
  * This metadata includes the time since the item was posted (which will appear
1551
  * as a link to the item's permalink).
1552
  *
1553
+ * @since BuddyPress (1.2)
1554
  *
1555
  * @global object $activities_template {@link BP_Activity_Template}
1556
+ * @uses bp_core_time_since()
1557
+ * @uses apply_filters_ref_array() To call the 'bp_activity_time_since' hook.
1558
+ * @uses bp_is_single_activity()
1559
+ * @uses bp_activity_get_permalink()
1560
+ * @uses esc_attr__()
1561
+ * @uses apply_filters_ref_array() To call the 'bp_activity_permalink' hook.
1562
+ * @uses apply_filters() To call the 'bp_insert_activity_meta' hook.
1563
  *
1564
  * @param string $content The activity content.
1565
  * @return string The activity content with the metadata string attached.
1566
  */
1567
+ function bp_insert_activity_meta( $content ) {
1568
  global $activities_template;
1569
 
1570
+ // Strip any legacy time since placeholders from BP 1.0-1.1
1571
+ $content = str_replace( '<span class="time-since">%s</span>', '', $content );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1572
 
1573
+ // Insert the time since.
1574
+ $time_since = apply_filters_ref_array( 'bp_activity_time_since', array( '<span class="time-since">' . bp_core_time_since( $activities_template->activity->date_recorded ) . '</span>', &$activities_template->activity ) );
 
 
 
 
 
 
 
 
 
1575
 
1576
+ // Insert the permalink
1577
+ if ( !bp_is_single_activity() )
1578
+ $content = apply_filters_ref_array( 'bp_activity_permalink', array( sprintf( '%1$s <a href="%2$s" class="view activity-time-since" title="%3$s">%4$s</a>', $content, bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity ), esc_attr__( 'View Discussion', 'buddypress' ), $time_since ), &$activities_template->activity ) );
1579
+ else
1580
+ $content .= str_pad( $time_since, strlen( $time_since ) + 2, ' ', STR_PAD_BOTH );
 
 
 
 
 
 
 
 
 
 
1581
 
1582
+ return apply_filters( 'bp_insert_activity_meta', $content );
 
 
 
 
 
 
 
1583
  }
1584
 
1585
  /**
1586
  * Determine if the current user can delete an activity item.
1587
  *
1588
+ * @since BuddyPress (1.2)
1589
  *
1590
  * @global object $activities_template {@link BP_Activity_Template}
1591
+ * @uses apply_filters() To call the 'bp_activity_user_can_delete' hook
1592
  *
1593
+ * @param object $activity Optional. Falls back on the current item in the loop.
1594
  * @return bool True if can delete, false otherwise.
1595
  */
1596
  function bp_activity_user_can_delete( $activity = false ) {
1597
  global $activities_template;
1598
 
1599
+ if ( !$activity )
 
1600
  $activity = $activities_template->activity;
 
1601
 
1602
+ if ( isset( $activity->current_comment ) )
 
1603
  $activity = $activity->current_comment;
 
1604
 
 
1605
  $can_delete = false;
1606
 
1607
+ if ( bp_current_user_can( 'bp_moderate' ) )
1608
+ $can_delete = true;
1609
 
1610
+ if ( is_user_logged_in() && $activity->user_id == bp_loggedin_user_id() )
1611
+ $can_delete = true;
 
 
 
 
 
 
 
 
 
1612
 
1613
+ if ( bp_is_item_admin() && bp_is_single_item() )
1614
+ $can_delete = true;
 
 
 
1615
 
1616
+ return apply_filters( 'bp_activity_user_can_delete', $can_delete, $activity );
 
 
 
 
 
 
 
 
1617
  }
1618
 
1619
  /**
1620
  * Output the activity parent content.
1621
  *
1622
+ * @since BuddyPress (1.2)
1623
  *
1624
  * @see bp_get_activity_parent_content() for a description of arguments.
1625
+ * @uses bp_get_activity_parent_content()
1626
  *
1627
+ * @param array $args See {@link bp_get_activity_parent_content} for description.
1628
  */
1629
  function bp_activity_parent_content( $args = '' ) {
1630
  echo bp_get_activity_parent_content($args);
1633
  /**
1634
  * Return the activity content.
1635
  *
1636
+ * @since BuddyPress (1.2)
1637
  *
1638
  * @global object $activities_template {@link BP_Activity_Template}
1639
+ * @uses wp_parse_args()
1640
+ * @uses apply_filters() To call the 'bp_get_activity_parent_content' hook.
1641
  *
1642
+ * @param array $args {
1643
+ * Array of optional arguments.
1644
+ * @deprecated bool $hide_user No longer used.
1645
+ * }
1646
+ * @return mixed False on failure, otherwise the activity parent content
1647
  */
1648
  function bp_get_activity_parent_content( $args = '' ) {
1649
  global $activities_template;
1650
 
1651
+ $defaults = array(
1652
+ 'hide_user' => false
1653
+ );
 
1654
 
1655
+ $r = wp_parse_args( $args, $defaults );
1656
+ extract( $r, EXTR_SKIP );
1657
 
1658
+ // Get the ID of the parent activity content
1659
+ if ( !$parent_id = $activities_template->activity->item_id )
1660
  return false;
 
1661
 
1662
+ // Bail if no parent content
1663
+ if ( empty( $activities_template->activity_parents[$parent_id] ) )
1664
+ return false;
1665
+
1666
+ // Bail if no action
1667
+ if ( empty( $activities_template->activity_parents[$parent_id]->action ) )
1668
  return false;
 
1669
 
1670
+ // Content always includes action
1671
+ $content = $activities_template->activity_parents[$parent_id]->action;
1672
 
1673
+ // Maybe append activity content, if it exists
1674
+ if ( ! empty( $activities_template->activity_parents[$parent_id]->content ) )
1675
+ $content .= ' ' . $activities_template->activity_parents[$parent_id]->content;
 
1676
 
1677
+ // Remove the time since content for backwards compatibility
1678
  $content = str_replace( '<span class="time-since">%s</span>', '', $content );
1679
 
1680
+ // Remove images
1681
  $content = preg_replace( '/<img[^>]*>/Ui', '', $content );
1682
 
 
 
 
 
 
 
 
1683
  return apply_filters( 'bp_get_activity_parent_content', $content );
1684
  }
1685
 
1686
  /**
1687
  * Output the parent activity's user ID.
1688
  *
1689
+ * @since BuddyPress (1.7)
1690
  */
1691
  function bp_activity_parent_user_id() {
1692
  echo bp_get_activity_parent_user_id();
1695
  /**
1696
  * Return the parent activity's user ID.
1697
  *
1698
+ * @since BuddyPress (1.7)
1699
  *
1700
  * @global BP_Activity_Template $activities_template
1701
  *
1702
  * @return bool|int False if parent activity can't be found, otherwise
1703
+ * the parent activity's user ID.
1704
  */
1705
  function bp_get_activity_parent_user_id() {
1706
  global $activities_template;
1707
 
1708
+ // Bail if no activity on no item ID
1709
+ if ( empty( $activities_template->activity ) || empty( $activities_template->activity->item_id ) )
1710
  return false;
 
1711
 
1712
+ // Get the ID of the parent activity content
1713
+ if ( !$parent_id = $activities_template->activity->item_id )
1714
+ return false;
1715
 
1716
+ // Bail if no parent item
1717
+ if ( empty( $activities_template->activity_parents[$parent_id] ) )
1718
  return false;
 
1719
 
1720
+ // Bail if no parent user ID
1721
+ if ( empty( $activities_template->activity_parents[$parent_id]->user_id ) )
1722
  return false;
 
1723
 
1724
+ $retval = $activities_template->activity_parents[$parent_id]->user_id;
1725
 
 
 
 
 
 
 
 
1726
  return (int) apply_filters( 'bp_get_activity_parent_user_id', $retval );
1727
  }
1728
 
1729
  /**
1730
  * Output whether or not the current activity is in a current user's favorites.
1731
  *
1732
+ * @since BuddyPress (1.2)
1733
  *
1734
+ * @uses bp_get_activity_is_favorite()
1735
  */
1736
  function bp_activity_is_favorite() {
1737
  echo bp_get_activity_is_favorite();
1740
  /**
1741
  * Return whether the current activity is in a current user's favorites.
1742
  *
1743
+ * @since BuddyPress (1.2)
1744
  *
1745
  * @global object $activities_template {@link BP_Activity_Template}
1746
+ * @uses apply_filters() To call the 'bp_get_activity_is_favorite' hook.
1747
  *
1748
  * @return bool True if user favorite, false otherwise.
1749
  */
1750
  function bp_get_activity_is_favorite() {
1751
  global $activities_template;
1752
 
1753
+ return apply_filters( 'bp_get_activity_is_favorite', in_array( $activities_template->activity->id, (array) $activities_template->my_favs ) );
 
 
 
 
 
 
 
1754
  }
1755
 
1756
  /**
1757
  * Output the comment markup for an activity item.
1758
  *
1759
+ * @since BuddyPress (1.2)
1760
  *
1761
  * @todo deprecate $args param
1762
  *
1763
+ * @param string $args Unused. Appears to be left over from an earlier implementation.
1764
  */
1765
  function bp_activity_comments( $args = '' ) {
1766
  echo bp_activity_get_comments( $args );
1769
  /**
1770
  * Get the comment markup for an activity item.
1771
  *
1772
+ * @since BuddyPress (1.2)
1773
  *
1774
  * @todo deprecate $args param
1775
+ *
1776
  * @todo Given that checks for children already happen in bp_activity_recurse_comments(),
1777
+ * this function can probably be streamlined or removed.
1778
  *
1779
+ * @param string $args Unused. Appears to be left over from an earlier implementation.
1780
  *
1781
+ * @global object $activities_template {@link BP_Activity_Template}
1782
+ * @uses bp_activity_recurse_comments()
1783
  */
1784
  function bp_activity_get_comments( $args = '' ) {
1785
  global $activities_template;
1786
 
1787
+ if ( !isset( $activities_template->activity->children ) || !$activities_template->activity->children )
1788
  return false;
 
1789
 
1790
  bp_activity_recurse_comments( $activities_template->activity );
1791
  }
1792
 
1793
  /**
1794
+ * Loops through a level of activity comments and loads the template for each
1795
  *
1796
  * Note: The recursion itself used to happen entirely in this function. Now it is
1797
  * split between here and the comment.php template.
1798
  *
1799
+ * @since BuddyPress (1.2)
1800
  *
1801
+ * @param object $comment The activity object currently being recursed
1802
  *
1803
+ * @global object $activities_template {@link BP_Activity_Template}
1804
+ * @uses locate_template()
1805
  */
1806
  function bp_activity_recurse_comments( $comment ) {
1807
  global $activities_template;
1808
 
1809
+ if ( empty( $comment ) )
1810
  return false;
 
1811
 
1812
+ if ( empty( $comment->children ) )
1813
  return false;
 
1814
 
1815
+ echo apply_filters( 'bp_activity_recurse_comments_start_ul', '<ul>');
 
 
 
 
 
 
 
1816
  foreach ( (array) $comment->children as $comment_child ) {
1817
+ // Put the comment into the global so it's available to filters
 
1818
  $activities_template->activity->current_comment = $comment_child;
1819
 
1820
  $template = bp_locate_template( 'activity/comment.php', false, false );
1831
 
1832
  unset( $activities_template->activity->current_comment );
1833
  }
1834
+ echo apply_filters( 'bp_activity_recurse_comments_end_ul', '</ul>');
 
 
 
 
 
 
 
 
1835
  }
1836
 
1837
  /**
1838
  * Utility function that returns the comment currently being recursed.
1839
  *
1840
+ * @since BuddyPress (1.5)
1841
  *
1842
  * @global object $activities_template {@link BP_Activity_Template}
1843
+ * @uses apply_filters() To call the 'bp_activity_current_comment' hook.
1844
  *
1845
  * @return object|bool $current_comment The activity comment currently being
1846
+ * displayed. False on failure.
1847
  */
1848
  function bp_activity_current_comment() {
1849
  global $activities_template;
1850
 
1851
+ $current_comment = !empty( $activities_template->activity->current_comment ) ? $activities_template->activity->current_comment : false;
 
 
1852
 
 
 
 
 
 
 
 
1853
  return apply_filters( 'bp_activity_current_comment', $current_comment );
1854
  }
1855
 
1857
  /**
1858
  * Output the ID of the activity comment currently being displayed.
1859
  *
1860
+ * @since BuddyPress (1.5)
1861
  *
1862
+ * @uses bp_get_activity_comment_id()
1863
  */
1864
  function bp_activity_comment_id() {
1865
  echo bp_get_activity_comment_id();
1868
  /**
1869
  * Return the ID of the activity comment currently being displayed.
1870
  *
1871
+ * @since BuddyPress (1.5)
1872
  *
1873
  * @global object $activities_template {@link BP_Activity_Template}
1874
+ * @uses apply_filters() To call the 'bp_activity_comment_id' hook.
1875
  *
1876
+ * @return int|bool $comment_id The ID of the activity comment
1877
+ * currently being displayed, false if none is found.
1878
  */
1879
  function bp_get_activity_comment_id() {
1880
  global $activities_template;
1881
 
1882
  $comment_id = isset( $activities_template->activity->current_comment->id ) ? $activities_template->activity->current_comment->id : false;
1883
 
 
 
 
 
 
 
 
1884
  return apply_filters( 'bp_activity_comment_id', $comment_id );
1885
  }
1886
 
1887
  /**
1888
  * Output the ID of the author of the activity comment currently being displayed.
1889
  *
1890
+ * @since BuddyPress (1.5)
1891
  *
1892
+ * @uses bp_get_activity_comment_user_id()
1893
  */
1894
  function bp_activity_comment_user_id() {
1895
  echo bp_get_activity_comment_user_id();
1898
  /**
1899
  * Return the ID of the author of the activity comment currently being displayed.
1900
  *
1901
+ * @since BuddyPress (1.5)
1902
  *
1903
  * @global object $activities_template {@link BP_Activity_Template}
1904
+ * @uses apply_filters() To call the 'bp_activity_comment_user_id' hook.
1905
  *
1906
  * @return int|bool $user_id The user_id of the author of the displayed
1907
+ * activity comment. False on failure.
1908
  */
1909
  function bp_get_activity_comment_user_id() {
1910
  global $activities_template;
1911
 
1912
  $user_id = isset( $activities_template->activity->current_comment->user_id ) ? $activities_template->activity->current_comment->user_id : false;
1913
 
 
 
 
 
 
 
 
1914
  return apply_filters( 'bp_activity_comment_user_id', $user_id );
1915
  }
1916
 
1917
  /**
1918
  * Output the author link for the activity comment currently being displayed.
1919
  *
1920
+ * @since BuddyPress (1.5)
1921
  *
1922
+ * @uses bp_get_activity_comment_user_link()
1923
  */
1924
  function bp_activity_comment_user_link() {
1925
  echo bp_get_activity_comment_user_link();
1928
  /**
1929
  * Return the author link for the activity comment currently being displayed.
1930
  *
1931
+ * @since BuddyPress (1.5)
1932
  *
1933
+ * @uses bp_core_get_user_domain()
1934
+ * @uses bp_get_activity_comment_user_id()
1935
+ * @uses apply_filters() To call the 'bp_activity_comment_user_link' hook
1936
  *
1937
  * @return string $user_link The URL of the activity comment author's profile.
1938
  */
1939
  function bp_get_activity_comment_user_link() {
1940
  $user_link = bp_core_get_user_domain( bp_get_activity_comment_user_id() );
1941
 
 
 
 
 
 
 
 
1942
  return apply_filters( 'bp_activity_comment_user_link', $user_link );
1943
  }
1944
 
1945
  /**
1946
  * Output the author name for the activity comment currently being displayed.
1947
  *
1948
+ * @since BuddyPress (1.5)
1949
  *
1950
+ * @uses bp_get_activity_comment_name()
1951
  */
1952
  function bp_activity_comment_name() {
1953
  echo bp_get_activity_comment_name();
1959
  * The use of the 'bp_acomment_name' filter is deprecated. Please use
1960
  * 'bp_activity_comment_name'.
1961
  *
1962
+ * @since BuddyPress (1.5)
1963
  *
1964
  * @global object $activities_template {@link BP_Activity_Template}
1965
+ * @uses apply_filters() To call the 'bp_acomment_name' hook.
1966
+ * @uses apply_filters() To call the 'bp_activity_comment_name' hook.
1967
  *
1968
  * @return string $name The full name of the activity comment author.
1969
  */
1970
  function bp_get_activity_comment_name() {
1971
  global $activities_template;
1972
 
1973
+ if ( isset( $activities_template->activity->current_comment->user_fullname ) )
1974
+ $name = apply_filters( 'bp_acomment_name', $activities_template->activity->current_comment->user_fullname, $activities_template->activity->current_comment ); // backward compatibility
1975
+ else
 
1976
  $name = $activities_template->activity->current_comment->display_name;
 
1977
 
 
 
 
 
 
 
 
1978
  return apply_filters( 'bp_activity_comment_name', $name );
1979
  }
1980
 
1981
  /**
1982
+ * Output the date_recorded of the activity comment currently being displayed.
1983
  *
1984
+ * @since BuddyPress (1.5)
1985
  *
1986
+ * @uses bp_get_activity_comment_date_recorded()
1987
  */
1988
  function bp_activity_comment_date_recorded() {
1989
  echo bp_get_activity_comment_date_recorded();
1990
  }
1991
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1992
  /**
1993
  * Return the date_recorded for the activity comment currently being displayed.
1994
  *
1995
+ * @since BuddyPress (1.5)
1996
  *
1997
  * @global object $activities_template {@link BP_Activity_Template}
1998
+ * @uses bp_core_time_since()
1999
+ * @uses apply_filters() To call the 'bp_activity_comment_date_recorded' hook
2000
  *
2001
  * @return string|bool $date_recorded Time since the activity was recorded,
2002
+ * in the form "%s ago". False on failure.
2003
  */
2004
+ function bp_get_activity_comment_date_recorded() {
2005
  global $activities_template;
2006
 
2007
+ if ( empty( $activities_template->activity->current_comment->date_recorded ) )
2008
+ return false;
2009
+
2010
+ $date_recorded = bp_core_time_since( $activities_template->activity->current_comment->date_recorded );
2011
+
2012
+ return apply_filters( 'bp_activity_comment_date_recorded', $date_recorded );
 
 
2013
  }
2014
 
2015
  /**
2016
  * Output the 'delete' URL for the activity comment currently being displayed.
2017
  *
2018
+ * @since BuddyPress (1.5)
2019
  *
2020
+ * @uses bp_get_activity_comment_delete_link()
2021
  */
2022
  function bp_activity_comment_delete_link() {
2023
  echo bp_get_activity_comment_delete_link();
2024
  }
2025
 
2026
  /**
2027
+ * Gets the 'delete' URL for the activity comment currently being displayed
2028
  *
2029
+ * @since BuddyPress (1.5)
2030
  *
2031
+ * @uses wp_nonce_url()
2032
+ * @uses bp_get_root_domain()
2033
+ * @uses bp_get_activity_slug()
2034
+ * @uses bp_get_activity_comment_id()
2035
+ * @uses apply_filters() To call the 'bp_activity_comment_delete_link' hook.
2036
  *
2037
  * @return string $link The nonced URL for deleting the current
2038
+ * activity comment.
2039
  */
2040
  function bp_get_activity_comment_delete_link() {
2041
+ $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' );
2042
 
 
 
 
 
 
 
 
2043
  return apply_filters( 'bp_activity_comment_delete_link', $link );
2044
  }
2045
 
2046
  /**
2047
  * Output the content of the activity comment currently being displayed.
2048
  *
2049
+ * @since BuddyPress (1.5)
2050
  *
2051
+ * @uses bp_get_activity_comment_content()
2052
  */
2053
  function bp_activity_comment_content() {
2054
  echo bp_get_activity_comment_content();
2062
  * 'bp_activity_comment_content' to modify the content of activity
2063
  * comments only.
2064
  *
2065
+ * @since BuddyPress (1.5)
2066
  *
2067
  * @global object $activities_template {@link BP_Activity_Template}
2068
+ * @uses apply_filters() To call the 'bp_get_activity_content' hook.
2069
+ * @uses apply_filters() To call the 'bp_activity_comment_content' hook.
2070
  *
2071
  * @return string $content The content of the current activity comment.
2072
  */
2073
  function bp_get_activity_comment_content() {
2074
  global $activities_template;
2075
 
 
2076
  $content = apply_filters( 'bp_get_activity_content', $activities_template->activity->current_comment->content );
2077
 
 
 
 
 
 
 
 
2078
  return apply_filters( 'bp_activity_comment_content', $content );
2079
  }
2080
 
2081
  /**
2082
  * Output the activity comment count.
2083
  *
2084
+ * @since BuddyPress (1.2)
2085
  *
2086
+ * @uses bp_activity_get_comment_count()
2087
  */
2088
  function bp_activity_comment_count() {
2089
  echo bp_activity_get_comment_count();
2090
  }
2091
 
2092
  /**
2093
+ * Return the content of the activity comment currently being displayed.
2094
+ *
2095
+ * The content is run through two filters. 'bp_get_activity_content'
2096
+ * will apply all filters applied to activity items in general. Use
2097
+ * 'bp_activity_comment_content' to modify the content of activity
2098
+ * comments only.
2099
  *
2100
+ * @since BuddyPress (1.2)
2101
  *
2102
  * @global object $activities_template {@link BP_Activity_Template}
2103
+ * @uses bp_activity_recurse_comment_count()
2104
+ * @uses apply_filters() To call the 'bp_activity_get_comment_count' hook.
2105
+ * @todo deprecate $args
2106
  *
2107
+ * @param array $args Deprecated.
2108
  * @return int $count The activity comment count.
2109
  */
2110
+ function bp_activity_get_comment_count( $args = '' ) {
2111
  global $activities_template;
2112
 
2113
+ if ( !isset( $activities_template->activity->children ) || !$activities_template->activity->children )
2114
+ return 0;
 
 
2115
 
2116
+ $count = bp_activity_recurse_comment_count( $activities_template->activity );
 
 
 
2117
 
 
 
 
 
 
 
 
2118
  return apply_filters( 'bp_activity_get_comment_count', (int) $count );
2119
  }
2120
 
2121
  /**
2122
+ * Return the content of the activity comment currently being displayed.
2123
  *
2124
+ * The content is run through two filters. 'bp_get_activity_content'
2125
+ * will apply all filters applied to activity items in general.
2126
+ * Use bp_activity_comment_content to modify the content of
2127
+ * activity comments only.
2128
  *
2129
+ * @since BuddyPress (1.2)
2130
  *
2131
+ * @uses bp_activity_recurse_comment_count()
2132
+ * @uses apply_filters() To call the 'bp_activity_get_comment_count' hook
2133
+ * @todo investigate why bp_activity_recurse_comment_count() is used while being declared
2134
  *
2135
  * @param object $comment Activity comment object.
2136
+ * @param int $count The current iteration count.
2137
  * @return int $count The activity comment count.
2138
  */
2139
  function bp_activity_recurse_comment_count( $comment, $count = 0 ) {
2140
 
2141
+ if ( empty( $comment->children ) )
2142
+ return $count;
2143
 
2144
+ foreach ( (array) $comment->children as $comment ) {
2145
+ $count++;
2146
+ $count = bp_activity_recurse_comment_count( $comment, $count );
 
 
 
2147
  }
2148
 
2149
+ return $count;
 
 
 
 
 
 
 
 
 
2150
  }
2151
 
2152
  /**
2153
  * Output the depth of the current activity comment.
2154
  *
2155
+ * @since BuddyPress (2.0.0)
 
 
 
 
2156
  */
2157
+ function bp_activity_comment_depth() {
2158
+ echo bp_activity_get_comment_depth();
2159
  }
 
2160
  /**
2161
  * Return the current activity comment depth.
2162
  *
2163
+ * @since BuddyPress (2.0.0)
 
2164
  *
 
 
2165
  * @return int
2166
  */
2167
+ function bp_activity_get_comment_depth() {
2168
+ global $activities_template;
2169
+ return apply_filters( 'bp_activity_get_comment_depth', $activities_template->activity->current_comment->depth );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2170
  }
2171
 
2172
  /**
2173
  * Output the activity comment link.
2174
  *
2175
+ * @since BuddyPress (1.2)
2176
  *
2177
+ * @uses bp_get_activity_comment_link()
2178
  */
2179
  function bp_activity_comment_link() {
2180
  echo bp_get_activity_comment_link();
2183
  /**
2184
  * Return the activity comment link.
2185
  *
2186
+ * @since BuddyPress (1.2)
2187
  *
2188
  * @global object $activities_template {@link BP_Activity_Template}
2189
+ * @uses apply_filters() To call the 'bp_get_activity_comment_link' hook.
2190
  *
2191
  * @return string The activity comment link.
2192
  */
2193
  function bp_get_activity_comment_link() {
2194
  global $activities_template;
 
 
 
 
 
 
 
 
2195
  return apply_filters( 'bp_get_activity_comment_link', '?ac=' . $activities_template->activity->id . '/#ac-form-' . $activities_template->activity->id );
2196
  }
2197
 
2198
  /**
2199
+ * Output the activity comment form no javascript display CSS.
2200
  *
2201
+ * @since BuddyPress (1.2)
2202
  *
2203
+ * @uses bp_get_activity_comment_form_nojs_display()
2204
  */
2205
  function bp_activity_comment_form_nojs_display() {
2206
  echo bp_get_activity_comment_form_nojs_display();
2207
  }
2208
 
2209
  /**
2210
+ * Return the activity comment form no javascript display CSS.
2211
  *
2212
+ * @since BuddyPress (1.2)
2213
  *
2214
  * @global object $activities_template {@link BP_Activity_Template}
2215
  *
2216
+ * @return string|bool The activity comment form no javascript
2217
+ * display CSS. False on failure
2218
  */
2219
  function bp_get_activity_comment_form_nojs_display() {
2220
  global $activities_template;
2221
+ if ( isset( $_GET['ac'] ) && $_GET['ac'] == $activities_template->activity->id . '/' )
 
2222
  return 'style="display: block"';
 
2223
 
2224
  return false;
2225
  }
2227
  /**
2228
  * Output the activity comment form action.
2229
  *
2230
+ * @since BuddyPress (1.2)
2231
  *
2232
+ * @uses bp_get_activity_comment_form_action()
2233
  */
2234
  function bp_activity_comment_form_action() {
2235
  echo bp_get_activity_comment_form_action();
2238
  /**
2239
  * Return the activity comment form action.
2240
  *
2241
+ * @since BuddyPress (1.2)
2242
  *
2243
+ * @uses home_url()
2244
+ * @uses bp_get_activity_root_slug()
2245
+ * @uses apply_filters() To call the 'bp_get_activity_comment_form_action' hook.
2246
  *
2247
  * @return string The activity comment form action.
2248
  */
2249
  function bp_get_activity_comment_form_action() {
 
 
 
 
 
 
 
 
2250
  return apply_filters( 'bp_get_activity_comment_form_action', home_url( bp_get_activity_root_slug() . '/reply/' ) );
2251
  }
2252
 
2253
  /**
2254
  * Output the activity permalink ID.
2255
  *
2256
+ * @since BuddyPress (1.2)
2257
  *
2258
+ * @uses bp_get_activity_permalink_id()
2259
  */
2260
  function bp_activity_permalink_id() {
2261
  echo bp_get_activity_permalink_id();
2264
  /**
2265
  * Return the activity permalink ID.
2266
  *
2267
+ * @since BuddyPress (1.2)
2268
  *
2269
+ * @uses apply_filters() To call the 'bp_get_activity_permalink_id' hook.
2270
  *
2271
  * @return string The activity permalink ID.
2272
  */
2273
  function bp_get_activity_permalink_id() {
 
 
 
 
 
 
 
 
2274
  return apply_filters( 'bp_get_activity_permalink_id', bp_current_action() );
2275
  }
2276
 
2277
  /**
2278
  * Output the activity thread permalink.
2279
  *
2280
+ * @since BuddyPress (1.2)
2281
  *
2282
+ * @uses bp_get_activity_permalink_id()
2283
  */
2284
  function bp_activity_thread_permalink() {
2285
+ echo bp_get_activity_thread_permalink();
2286
  }
2287
 
2288
  /**
2289
  * Return the activity thread permalink.
2290
  *
2291
+ * @since BuddyPress (1.2)
2292
  *
2293
+ * @uses bp_activity_get_permalink()
2294
+ * @uses apply_filters() To call the 'bp_get_activity_thread_permalink' hook.
2295
  *
2296
  * @return string $link The activity thread permalink.
2297
  */
2300
 
2301
  $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
2302
 
2303
+ return apply_filters( 'bp_get_activity_thread_permalink', $link );
 
 
 
 
 
 
 
2304
  }
2305
 
2306
  /**
2307
  * Output the activity comment permalink.
2308
  *
2309
+ * @since BuddyPress (1.8)
2310
  *
2311
+ * @uses bp_get_activity_permalink_id()
2312
  */
2313
  function bp_activity_comment_permalink() {
2314
+ echo bp_get_activity_comment_permalink();
2315
  }
2316
  /**
2317
  * Return the activity comment permalink.
2318
  *
2319
+ * @since BuddyPress (1.8)
2320
+ *
2321
+ * @uses bp_activity_get_permalink()
2322
+ * @uses apply_filters() To call the 'bp_get_activity_comment_permalink' hook.
2323
  *
2324
  * @return string $link The activity comment permalink.
2325
  */
2326
  function bp_get_activity_comment_permalink() {
2327
  global $activities_template;
2328
 
2329
+ $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity ) . '#acomment-' . $activities_template->activity->current_comment->id;
 
 
 
 
 
2330
 
2331
+ return apply_filters( 'bp_get_activity_comment_permalink', $link );
 
 
 
 
 
 
 
 
2332
  }
2333
 
2334
  /**
2335
  * Output the activity favorite link.
2336
  *
2337
+ * @since BuddyPress (1.2)
2338
  *
2339
+ * @uses bp_get_activity_favorite_link()
2340
  */
2341
  function bp_activity_favorite_link() {
2342
  echo bp_get_activity_favorite_link();
2345
  /**
2346
  * Return the activity favorite link.
2347
  *
2348
+ * @since BuddyPress (1.2)
2349
  *
2350
  * @global object $activities_template {@link BP_Activity_Template}
2351
+ * @uses wp_nonce_url()
2352
+ * @uses home_url()
2353
+ * @uses bp_get_activity_root_slug()
2354
+ * @uses apply_filters() To call the 'bp_get_activity_favorite_link' hook
2355
  *
2356
  * @return string The activity favorite link.
2357
  */
2358
  function bp_get_activity_favorite_link() {
2359
  global $activities_template;
 
 
 
 
 
 
 
 
2360
  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' ) );
2361
  }
2362
 
2363
  /**
2364
  * Output the activity unfavorite link.
2365
  *
2366
+ * @since BuddyPress (1.2)
2367
  *
2368
+ * @uses bp_get_activity_unfavorite_link()
2369
  */
2370
  function bp_activity_unfavorite_link() {
2371
  echo bp_get_activity_unfavorite_link();
2374
  /**
2375
  * Return the activity unfavorite link.
2376
  *
2377
+ * @since BuddyPress (1.2)
2378
  *
2379
  * @global object $activities_template {@link BP_Activity_Template}
2380
+ * @uses wp_nonce_url()
2381
+ * @uses home_url()
2382
+ * @uses bp_get_activity_root_slug()
2383
+ * @uses apply_filters() To call the 'bp_get_activity_unfavorite_link' hook.
2384
  *
2385
  * @return string The activity unfavorite link.
2386
  */
2387
  function bp_get_activity_unfavorite_link() {
2388
  global $activities_template;
 
 
 
 
 
 
 
 
2389
  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' ) );
2390
  }
2391
 
2392
  /**
2393
  * Output the activity CSS class.
2394
  *
2395
+ * @since BuddyPress (1.0)
2396
  *
2397
+ * @uses bp_get_activity_css_class()
2398
  */
2399
  function bp_activity_css_class() {
2400
  echo bp_get_activity_css_class();
2403
  /**
2404
  * Return the current activity item's CSS class.
2405
  *
2406
+ * @since BuddyPress (1.0)
2407
  *
2408
  * @global object $activities_template {@link BP_Activity_Template}
2409
+ * @uses apply_filters() To call the 'bp_activity_mini_activity_types' hook.
2410
+ * @uses bp_activity_get_comment_count()
2411
+ * @uses bp_activity_can_comment()
2412
+ * @uses apply_filters() To call the 'bp_get_activity_css_class' hook.
2413
  *
2414
  * @return string The activity item's CSS class.
2415
  */
2416
  function bp_get_activity_css_class() {
2417
  global $activities_template;
2418
 
 
 
 
 
 
 
 
2419
  $mini_activity_actions = apply_filters( 'bp_activity_mini_activity_types', array(
2420
  'friendship_accepted',
2421
  'friendship_created',
2425
  'new_member'
2426
  ) );
2427
 
2428
+ $class = ' activity-item';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2429
 
2430
+ if ( in_array( $activities_template->activity->type, (array) $mini_activity_actions ) || empty( $activities_template->activity->content ) )
2431
+ $class .= ' mini';
2432
 
2433
+ if ( bp_activity_get_comment_count() && bp_activity_can_comment() )
2434
+ $class .= ' has-comments';
2435
+
2436
+ return apply_filters( 'bp_get_activity_css_class', $activities_template->activity->component . ' ' . $activities_template->activity->type . $class );
 
 
 
 
2437
  }
2438
 
2439
  /**
2440
+ * Output the activity delete link.
2441
  *
2442
+ * @since BuddyPress (1.1)
2443
  *
2444
+ * @uses bp_get_activity_delete_link()
2445
  */
2446
+ function bp_activity_delete_link() {
2447
+ echo bp_get_activity_delete_link();
2448
  }
2449
+
2450
  /**
2451
+ * Return the activity delete link.
2452
  *
2453
+ * @since BuddyPress (1.1)
2454
  *
2455
  * @global object $activities_template {@link BP_Activity_Template}
2456
+ * @uses bp_get_root_domain()
2457
+ * @uses bp_get_activity_root_slug()
2458
+ * @uses bp_is_activity_component()
2459
+ * @uses bp_current_action()
2460
+ * @uses add_query_arg()
2461
+ * @uses wp_get_referer()
2462
+ * @uses wp_nonce_url()
2463
+ * @uses apply_filters() To call the 'bp_get_activity_delete_link' hook.
2464
  *
2465
  * @return string $link Activity delete link. Contains $redirect_to arg
2466
+ * if on single activity page.
2467
  */
2468
+ function bp_get_activity_delete_link() {
2469
  global $activities_template;
2470
 
2471
+ $url = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/delete/' . $activities_template->activity->id;
2472
+ $class = 'delete-activity';
2473
 
2474
+ // Determine if we're on a single activity page, and customize accordingly
2475
  if ( bp_is_activity_component() && is_numeric( bp_current_action() ) ) {
2476
+ $url = add_query_arg( array( 'redirect_to' => wp_get_referer() ), $url );
2477
+ $class = 'delete-activity-single';
2478
  }
2479
 
2480
+ $link = '<a href="' . wp_nonce_url( $url, 'bp_activity_delete_link' ) . '" class="button item-button bp-secondary-action ' . $class . ' confirm" rel="nofollow">' . __( 'Delete', 'buddypress' ) . '</a>';
2481
+ return apply_filters( 'bp_get_activity_delete_link', $link );
 
 
 
 
 
 
 
 
2482
  }
2483
 
2484
  /**
2485
  * Output the activity latest update link.
2486
  *
2487
+ * @since BuddyPress (1.2)
2488
  *
2489
  * @see bp_get_activity_latest_update() for description of parameters.
2490
+ * @uses bp_get_activity_latest_update()
2491
  *
2492
  * @param int $user_id See {@link bp_get_activity_latest_update()} for description.
2493
  */
2498
  /**
2499
  * Return the activity latest update link.
2500
  *
2501
+ * @since BuddyPress (1.2)
2502
  *
2503
+ * @uses bp_is_user_inactive()
2504
+ * @uses bp_core_is_user_deleted()
2505
+ * @uses bp_get_user_meta()
2506
+ * @uses apply_filters() To call the 'bp_get_activity_latest_update_excerpt' hook
2507
+ * @uses bp_create_excerpt()
2508
+ * @uses bp_get_root_domain()
2509
+ * @uses bp_get_activity_root_slug()
2510
+ * @uses apply_filters() To call the 'bp_get_activity_latest_update' hook
2511
  *
2512
  * @param int $user_id If empty, will fall back on displayed user.
2513
  * @return string|bool $latest_update The activity latest update link.
2514
+ * False on failure
2515
  */
2516
  function bp_get_activity_latest_update( $user_id = 0 ) {
2517
 
2518
+ if ( empty( $user_id ) )
2519
  $user_id = bp_displayed_user_id();
 
2520
 
2521
+ if ( bp_is_user_inactive( $user_id ) )
2522
  return false;
 
2523
 
2524
+ if ( !$update = bp_get_user_meta( $user_id, 'bp_latest_update', true ) )
2525
  return false;
 
 
 
 
 
 
 
 
 
 
 
 
2526
 
2527
+ $latest_update = apply_filters( 'bp_get_activity_latest_update_excerpt', trim( strip_tags( bp_create_excerpt( $update['content'], 358 ) ) ) );
2528
+ $latest_update .= ' <a href="' . bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $update['id'] . '/"> ' . __( 'View', 'buddypress' ) . '</a>';
 
 
 
 
2529
 
2530
+ return apply_filters( 'bp_get_activity_latest_update', $latest_update );
 
 
 
 
 
 
 
 
 
2531
  }
2532
 
2533
  /**
2534
  * Output the activity filter links.
2535
  *
2536
+ * @since BuddyPress (1.1)
2537
  *
2538
  * @see bp_get_activity_filter_links() for description of parameters.
2539
+ * @uses bp_get_activity_filter_links()
2540
  *
2541
+ * @param array $args See {@link bp_get_activity_filter_links()} for description.
2542
  */
2543
  function bp_activity_filter_links( $args = false ) {
2544
  echo bp_get_activity_filter_links( $args );
2547
  /**
2548
  * Return the activity filter links.
2549
  *
2550
+ * @since BuddyPress (1.1)
2551
  *
2552
+ * @uses wp_parse_args()
2553
+ * @uses BP_Activity_Activity::get_recorded_components() {@link BP_Activity_Activity}
2554
+ * @uses esc_attr()
2555
+ * @uses add_query_arg()
2556
+ * @uses remove_query_arg()
2557
+ * @uses apply_filters() To call the 'bp_get_activity_filter_link_href' hook.
2558
+ * @uses apply_filters() To call the 'bp_get_activity_filter_links' hook.
2559
  *
2560
+ * @param array $args {
2561
  * @type string $style The type of markup to use for the links.
2562
+ * 'list', 'paragraph', or 'span'. Default: 'list'.
2563
  * }
2564
  * @return string|bool $component_links The activity filter links.
2565
  * False on failure.
2566
  */
2567
  function bp_get_activity_filter_links( $args = false ) {
2568
 
2569
+ $defaults = array(
2570
  'style' => 'list'
2571
+ );
2572
+
2573
+ $r = wp_parse_args( $args, $defaults );
2574
+ extract( $r, EXTR_SKIP );
2575
 
2576
+ // Define local variable
2577
  $component_links = array();
2578
 
2579
+ // Fetch the names of components that have activity recorded in the DB
2580
  $components = BP_Activity_Activity::get_recorded_components();
2581
 
2582
+ if ( empty( $components ) )
2583
  return false;
 
2584
 
2585
  foreach ( (array) $components as $component ) {
2586
 
2587
+ // Skip the activity comment filter
2588
+ if ( 'activity' == $component )
2589
  continue;
 
2590
 
2591
+ if ( isset( $_GET['afilter'] ) && $component == $_GET['afilter'] )
2592
  $selected = ' class="selected"';
2593
+ else
2594
+ unset($selected);
 
2595
 
2596
  $component = esc_attr( $component );
2597
 
2598
+ switch ( $style ) {
2599
  case 'list':
2600
  $tag = 'li';
2601
  $before = '<li id="afilter-' . $component . '"' . $selected . '>';
2615
 
2616
  $link = add_query_arg( 'afilter', $component );
2617
  $link = remove_query_arg( 'acpage' , $link );
 
 
 
 
 
 
 
 
 
2618
  $link = apply_filters( 'bp_get_activity_filter_link_href', $link, $component );
2619
 
2620
+ $component_links[] = $before . '<a href="' . esc_attr( $link ) . '">' . ucwords( $component ) . '</a>' . $after;
2621
  }
2622
 
2623
  $link = remove_query_arg( 'afilter' , $link );
2624
 
2625
+ if ( isset( $_GET['afilter'] ) )
2626
+ $component_links[] = '<' . $tag . ' id="afilter-clear"><a href="' . esc_attr( $link ) . '">' . __( 'Clear Filter', 'buddypress' ) . '</a></' . $tag . '>';
 
2627
 
2628
+ return apply_filters( 'bp_get_activity_filter_links', implode( "\n", $component_links ) );
 
 
 
 
 
 
 
 
 
2629
  }
2630
 
2631
  /**
2632
  * Determine if a comment can be made on an activity item.
2633
  *
2634
+ * @since BuddyPress (1.2)
2635
  *
2636
  * @global object $activities_template {@link BP_Activity_Template}
2637
+ * @uses bp_get_activity_action_name()
2638
+ * @uses apply_filters() To call the 'bp_activity_can_comment' hook.
2639
  *
2640
  * @return bool $can_comment True if item can receive comments.
2641
  */
2642
  function bp_activity_can_comment() {
2643
  global $activities_template;
 
2644
 
2645
+ $can_comment = true;
 
2646
 
2647
+ if ( false === $activities_template->disable_blogforum_replies || (int) $activities_template->disable_blogforum_replies ) {
2648
+ if ( 'new_blog_post' == bp_get_activity_action_name() || 'new_blog_comment' == bp_get_activity_action_name() || 'new_forum_topic' == bp_get_activity_action_name() || 'new_forum_post' == bp_get_activity_action_name() )
2649
+ $can_comment = false;
2650
+ }
2651
 
2652
+ if ( 'activity_comment' == bp_get_activity_action_name() )
 
2653
  $can_comment = false;
 
2654
 
2655
+ return apply_filters( 'bp_activity_can_comment', $can_comment );
 
 
 
 
 
 
 
 
 
2656
  }
2657
 
2658
  /**
2659
+ * Determine if a comment can be made on an activity reply item.
2660
+ *
2661
+ * Defaults to true, but can be modified by plugins.
2662
+ *
2663
+ * @since BuddyPress (1.5)
2664
  *
2665
+ * @uses apply_filters() To call the 'bp_activity_can_comment_reply' hook
2666
  *
2667
+ * @param object $comment Activity comment.
2668
+ * @return bool $can_comment True if comment can receive comments.
 
2669
  */
2670
+ function bp_activity_can_comment_reply( $comment ) {
 
 
2671
  $can_comment = true;
2672
 
2673
+ if ( get_option( 'thread_comments' ) && bp_activity_get_comment_depth() >= get_option( 'thread_comments_depth' ) ) {
2674
+ $can_comment = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2675
  }
2676
 
2677
+ return apply_filters( 'bp_activity_can_comment_reply', $can_comment, $comment );
 
 
 
 
 
 
 
 
2678
  }
2679
 
2680
  /**
2681
+ * Determine if an favorites are allowed.
2682
  *
2683
  * Defaults to true, but can be modified by plugins.
2684
  *
2685
+ * @since BuddyPress (1.5)
2686
  *
2687
+ * @uses apply_filters() To call the 'bp_activity_can_favorite' hook.
2688
+ *
2689
+ * @return bool $can_favorite True if comment can receive comments.
2690
  */
2691
  function bp_activity_can_favorite() {
2692
+ $can_favorite = true;
2693
 
2694
+ return apply_filters( 'bp_activity_can_favorite', $can_favorite );
 
 
 
 
 
 
 
2695
  }
2696
 
2697
  /**
2698
  * Output the total favorite count for a specified user.
2699
  *
2700
+ * @since BuddyPress (1.2)
2701
  *
2702
  * @see bp_get_total_favorite_count_for_user() for description of parameters.
2703
+ * @uses bp_get_total_favorite_count_for_user()
2704
  *
2705
  * @param int $user_id See {@link bp_get_total_favorite_count_for_user()}.
2706
  */
2711
  /**
2712
  * Return the total favorite count for a specified user.
2713
  *
2714
+ * @since BuddyPress (1.2)
2715
  *
2716
+ * @uses bp_activity_total_favorites_for_user()
2717
+ * @uses apply_filters() To call the 'bp_get_total_favorite_count_for_user' hook
2718
  *
2719
  * @param int $user_id ID of user being queried. Default: displayed user ID.
2720
  * @return int The total favorite count for the specified user.
2721
  */
2722
  function bp_get_total_favorite_count_for_user( $user_id = 0 ) {
2723
+ if ( ! $user_id ) {
2724
+ $user_id = bp_displayed_user_id();
 
 
 
 
 
 
 
 
 
 
2725
  }
2726
 
2727
+ return apply_filters( 'bp_get_total_favorite_count_for_user', bp_activity_total_favorites_for_user( $user_id ) );
 
 
 
 
 
 
 
 
 
2728
  }
2729
+ add_filter( 'bp_get_total_favorite_count_for_user', 'bp_core_number_format' );
2730
 
2731
  /**
2732
  * Output the total mention count for a specified user.
2733
  *
2734
+ * @since BuddyPress (1.2)
2735
  *
2736
  * @see bp_get_total_mention_count_for_user() for description of parameters.
2737
+ * @uses bp_get_total_favorite_count_for_user()
2738
  *
2739
  * @param int $user_id See {@link bp_get_total_mention_count_for_user()}.
2740
  */
2745
  /**
2746
  * Return the total mention count for a specified user.
2747
  *
2748
+ * @since BuddyPress (1.2)
2749
  *
2750
+ * @uses bp_get_user_meta()
2751
+ * @uses apply_filters() To call the 'bp_get_total_mention_count_for_user' hook.
2752
  *
2753
  * @param int $user_id ID of user being queried. Default: displayed user ID.
2754
  * @return int The total mention count for the specified user.
2755
  */
2756
  function bp_get_total_mention_count_for_user( $user_id = 0 ) {
2757
+ if ( ! $user_id ) {
2758
+ $user_id = bp_displayed_user_id();
2759
+ }
2760
 
2761
+ return apply_filters( 'bp_get_total_mention_count_for_user', bp_get_user_meta( $user_id, 'bp_new_mention_count', true ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2762
  }
2763
+ add_filter( 'bp_get_total_mention_count_for_user', 'bp_core_number_format' );
2764
 
2765
  /**
2766
  * Output the public message link for displayed user.
2767
  *
2768
+ * @since BuddyPress (1.2)
2769
  *
2770
+ * @uses bp_get_send_public_message_link()
2771
  */
2772
  function bp_send_public_message_link() {
2773
+ echo bp_get_send_public_message_link();
2774
  }
2775
 
2776
  /**
2777
  * Return the public message link for the displayed user.
2778
  *
2779
+ * @since BuddyPress (1.2)
2780
  *
2781
+ * @uses is_user_logged_in()
2782
+ * @uses bp_is_my_profile()
2783
+ * @uses bp_is_user()
2784
+ * @uses wp_nonce_url()
2785
+ * @uses bp_get_activity_directory_permalink()
2786
+ * @uses apply_filters() To call the 'bp_get_send_public_message_link' hook
2787
  *
2788
  * @return string The public message link for the displayed user.
2789
  */
2790
  function bp_get_send_public_message_link() {
2791
 
2792
+ if ( ! is_user_logged_in() || ! bp_is_user() || bp_is_my_profile() )
2793
+ return false;
 
 
 
 
 
 
2794
 
2795
+ return apply_filters( 'bp_get_send_public_message_link', wp_nonce_url( bp_get_activity_directory_permalink() . '?r=' . bp_get_displayed_user_mentionname() ) );
 
 
 
 
 
 
 
2796
  }
2797
 
2798
  /**
2799
  * Recurse through all activity comments and return the activity comment IDs.
2800
  *
2801
+ * @since BuddyPress (2.0.0)
2802
  *
2803
  * @param array $activity Array of activities generated from {@link bp_activity_get()}.
2804
  * @param array $activity_ids Used for recursion purposes in this function.
2825
  /**
2826
  * Output the mentioned user display name.
2827
  *
2828
+ * @since BuddyPress (1.2)
2829
  *
2830
  * @see bp_get_mentioned_user_display_name() for description of parameters.
2831
+ * @uses bp_get_mentioned_user_display_name()
2832
  *
2833
+ * @param int|string $user_id_or_username See {@link bp_get_mentioned_user_display_name()}.
2834
  */
2835
+ function bp_mentioned_user_display_name( $user_id_or_username ) {
2836
  echo bp_get_mentioned_user_display_name( $user_id_or_username );
2837
  }
2838
 
2839
  /**
2840
+ * Returns the mentioned user display name
2841
  *
2842
+ * @since BuddyPress (1.2)
2843
  *
2844
+ * @uses bp_core_get_user_displayname()
2845
+ * @uses apply_filters() To call the 'bp_get_mentioned_user_display_name' hook.
2846
  *
2847
+ * @param int|string User ID or username.
2848
  * @return string The mentioned user's display name.
2849
  */
2850
+ function bp_get_mentioned_user_display_name( $user_id_or_username ) {
2851
+ if ( !$name = bp_core_get_user_displayname( $user_id_or_username ) )
 
 
 
 
 
2852
  $name = __( 'a user', 'buddypress' );
 
2853
 
 
 
 
 
 
 
 
 
2854
  return apply_filters( 'bp_get_mentioned_user_display_name', $name, $user_id_or_username );
2855
  }
2856
 
2857
  /**
2858
  * Output button for sending a public message (an @-mention).
2859
  *
2860
+ * @since BuddyPress (1.2)
2861
  *
2862
  * @see bp_get_send_public_message_button() for description of parameters.
2863
+ * @uses bp_get_send_public_message_button()
2864
  *
2865
+ * @param array $args See {@link bp_get_send_public_message_button()}.
2866
  */
2867
  function bp_send_public_message_button( $args = '' ) {
2868
  echo bp_get_send_public_message_button( $args );
2871
  /**
2872
  * Return button for sending a public message (an @-mention).
2873
  *
2874
+ * @since BuddyPress (1.2)
2875
  *
2876
+ * @uses bp_get_send_public_message_link()
2877
+ * @uses wp_parse_args()
2878
+ * @uses bp_get_button()
2879
+ * @uses apply_filters() To call the 'bp_get_send_public_message_button' hook.
2880
  *
2881
+ * @param array $args {
2882
  * All arguments are optional. See {@link BP_Button} for complete
2883
  * descriptions.
2884
+ * @type string $id Default: 'public_message'.
2885
+ * @type string $component Default: 'activity'.
2886
+ * @type bool $must_be_logged_in Default: true.
2887
+ * @type bool $block_self Default: true.
2888
+ * @type string $wrapper_id Default: 'post-mention'.
2889
+ * @type string $link_href Default: the public message link for
2890
+ * the current member in the loop.
2891
+ * @type string $link_title Default: 'Send a public message on your
2892
+ * activity stream.'.
2893
+ * @type string $link_text Default: 'Public Message'.
2894
+ * @type string $link_class Default: 'activity-button mention'.
2895
  * }
2896
  * @return string The button for sending a public message.
2897
  */
2898
  function bp_get_send_public_message_button( $args = '' ) {
2899
+ $defaults = array(
 
2900
  'id' => 'public_message',
2901
  'component' => 'activity',
2902
  'must_be_logged_in' => true,
2903
  'block_self' => true,
2904
  'wrapper_id' => 'post-mention',
2905
  'link_href' => bp_get_send_public_message_link(),
2906
+ 'link_title' => __( 'Send a public message on your activity stream.', 'buddypress' ),
2907
  'link_text' => __( 'Public Message', 'buddypress' ),
2908
  'link_class' => 'activity-button mention'
2909
+ );
2910
 
2911
+ $button = wp_parse_args( $args, $defaults );
2912
+
2913
+ // Filter and return the HTML button
2914
+ return bp_get_button( apply_filters( 'bp_get_send_public_message_button', $button ) );
 
 
 
 
2915
  }
2916
 
2917
  /**
2918
  * Output the activity post form action.
2919
  *
2920
+ * @since BuddyPress (1.2)
2921
  *
2922
+ * @uses bp_get_activity_post_form_action()
2923
  */
2924
  function bp_activity_post_form_action() {
2925
  echo bp_get_activity_post_form_action();
2928
  /**
2929
  * Return the activity post form action.
2930
  *
2931
+ * @since BuddyPress (1.2)
2932
  *
2933
+ * @uses home_url()
2934
+ * @uses bp_get_activity_root_slug()
2935
+ * @uses apply_filters() To call the 'bp_get_activity_post_form_action' hook.
2936
  *
2937
  * @return string The activity post form action.
2938
  */
2939
  function bp_get_activity_post_form_action() {
 
 
 
 
 
 
 
 
2940
  return apply_filters( 'bp_get_activity_post_form_action', home_url( bp_get_activity_root_slug() . '/post/' ) );
2941
  }
2942
 
2948
  * Avatars are wrapped in <li> elements, but you've got to provide your own
2949
  * <ul> or <ol> wrapper markup.
2950
  *
2951
+ * @since BuddyPress (1.7)
2952
  *
2953
  * @see bp_core_fetch_avatar() for a description of arguments.
2954
  *
2955
  * @param array $args See {@link bp_core_fetch_avatar()}.
2956
  */
2957
  function bp_activity_comments_user_avatars( $args = array() ) {
2958
+ $defaults = array(
 
2959
  'height' => false,
2960
  'html' => true,
2961
  'type' => 'thumb',
2962
  'width' => false,
2963
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
2964
 
2965
+ $args = wp_parse_args( $args, $defaults );
2966
+ extract( $args, EXTR_SKIP );
2967
 
2968
+ // Get the user IDs of everyone who has left a comment to the current activity item
2969
+ $user_ids = bp_activity_get_comments_user_ids();
 
 
 
 
 
 
2970
 
2971
+ $output = array();
2972
+ foreach ( (array) $user_ids as $user_id ) {
2973
+ $profile_link = bp_core_get_user_domain( $user_id );
2974
+ $image_html = bp_core_fetch_avatar( array( 'item_id' => $user_id, 'height' => $height, 'html' => $html, 'type' => $type, 'width' => $width, ) );
 
2975
 
2976
+ $output[] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $profile_link ), $image_html );
 
 
 
2977
  }
2978
 
2979
+ echo apply_filters( 'bp_activity_comments_user_avatars', '<li>' . implode( '</li><li>', $output ) . '</li>', $args, $output );
 
 
 
 
 
 
 
 
 
2980
  }
2981
 
2982
  /**
2983
  * Return the IDs of every user who's left a comment on the current activity item.
2984
  *
2985
+ * @since BuddyPress (1.7)
2986
  *
2987
  * @return bool|array An array of IDs, or false if none are found.
2988
  */
2989
  function bp_activity_get_comments_user_ids() {
2990
+ if ( empty( $GLOBALS['activities_template']->activity ) || empty( $GLOBALS['activities_template']->activity->children ) )
2991
+ return false;
 
 
 
2992
 
2993
+ $user_ids = (array) bp_activity_recurse_comments_user_ids( $GLOBALS['activities_template']->activity->children );
 
 
 
 
 
 
2994
  return apply_filters( 'bp_activity_get_comments_user_ids', array_unique( $user_ids ) );
2995
  }
2996
 
2997
  /**
2998
  * Recurse through all activity comments and collect the IDs of the users who wrote them.
2999
  *
3000
+ * @since BuddyPress (1.7)
3001
  *
3002
  * @param array $comments Array of {@link BP_Activity_Activity} items.
3003
  * @return array Array of user IDs.
3004
  */
3005
+ function bp_activity_recurse_comments_user_ids( array $comments ) {
 
 
3006
  $user_ids = array();
3007
 
3008
+ foreach ( $comments as $comment ) {
3009
+ // If a user is a spammer, their activity items will have been automatically marked as spam. Skip these.
3010
+ if ( $comment->is_spam )
3011
+ continue;
 
 
 
 
 
3012
 
3013
+ $user_ids[] = $comment->user_id;
 
3014
 
3015
+ // Check for commentception
3016
+ if ( ! empty( $comment->children ) )
3017
+ $user_ids = array_merge( $user_ids, bp_activity_recurse_comments_user_ids( $comment->children ) );
 
 
3018
  }
3019
 
3020
+ return $user_ids;
 
 
 
 
 
 
 
 
3021
  }
3022
 
3023
  /**
3024
  * Output the mentionname for the displayed user.
3025
  *
3026
+ * @since BuddyPress (1.9.0)
3027
  */
3028
  function bp_displayed_user_mentionname() {
3029
  echo bp_get_displayed_user_mentionname();
3031
  /**
3032
  * Get the mentionname for the displayed user.
3033
  *
3034
+ * @since BuddyPress (1.9.0)
3035
  *
3036
  * @return string Mentionname for the displayed user, if available.
3037
  */
3038
  function bp_get_displayed_user_mentionname() {
 
 
 
 
 
 
 
 
3039
  return apply_filters( 'bp_get_displayed_user_mentionname', bp_activity_get_user_mentionname( bp_displayed_user_id() ) );
3040
  }
3041
 
3042
  /**
3043
  * Echo a list of all registered activity types for use in dropdowns or checkbox lists.
3044
  *
3045
+ * @since BuddyPress (1.7)
3046
  *
3047
+ * @param string $output Optional. Either 'select' or 'checkbox'. Default: 'select'.
3048
+ * @param array $args {
3049
  * Optional extra arguments.
3050
+ * @type string $checkbox_name When returning checkboxes, sets the 'name'
3051
+ * attribute.
3052
+ * @type array|string $selected A list of types that should be checked/
3053
+ * selected.
3054
  * }
3055
  */
3056
  function bp_activity_types_list( $output = 'select', $args = '' ) {
3057
+ $defaults = array(
 
3058
  'checkbox_name' => 'bp_activity_types',
3059
  'selected' => array(),
3060
+ );
3061
+ $args = wp_parse_args( $args, $defaults );
3062
 
3063
  $activities = bp_activity_get_types();
3064
  natsort( $activities );
3065
 
3066
+ // Loop through the activity types and output markup
3067
  foreach ( $activities as $type => $description ) {
3068
 
3069
+ // See if we need to preselect the current type
3070
  $checked = checked( true, in_array( $type, (array) $args['selected'] ), false );
3071
  $selected = selected( true, in_array( $type, (array) $args['selected'] ), false );
3072
 
3073
+ if ( 'select' == $output )
3074
+ printf( '<option value="%1$s" %2$s>%3$s</option>', esc_attr( $type ), $selected, esc_html( $description ) );
 
 
 
 
 
 
 
3075
 
3076
+ elseif ( 'checkbox' == $output )
3077
+ printf( '<label style="">%1$s<input type="checkbox" name="%2$s[]" value="%3$s" %4$s/></label>', esc_html( $description ), esc_attr( $args['checkbox_name'] ), esc_attr( $type ), $checked );
3078
+
3079
+ // Allow custom markup
 
 
 
 
 
 
 
 
3080
  do_action( 'bp_activity_types_list_' . $output, $args, $type, $description );
3081
  }
3082
 
3083
+ // Backpat with BP-Default for dropdown boxes only
3084
+ if ( 'select' == $output )
3085
  do_action( 'bp_activity_filter_options' );
 
3086
  }
3087
 
3088
 
3091
  /**
3092
  * Output the sitewide activity feed link.
3093
  *
3094
+ * @since BuddyPress (1.0)
3095
  *
3096
+ * @uses bp_get_sitewide_activity_feed_link()
3097
  */
3098
  function bp_sitewide_activity_feed_link() {
3099
  echo bp_get_sitewide_activity_feed_link();
3102
  /**
3103
  * Returns the sitewide activity feed link.
3104
  *
3105
+ * @since BuddyPress (1.0)
3106
  *
3107
+ * @uses home_url()
3108
+ * @uses bp_get_activity_root_slug()
3109
+ * @uses apply_filters() To call the 'bp_get_sitewide_activity_feed_link' hook.
3110
  *
3111
  * @return string The sitewide activity feed link.
3112
  */
3113
  function bp_get_sitewide_activity_feed_link() {
 
 
 
 
 
 
 
 
3114
  return apply_filters( 'bp_get_sitewide_activity_feed_link', bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/feed/' );
3115
  }
3116
 
3117
  /**
3118
  * Output the member activity feed link.
3119
  *
3120
+ * @since BuddyPress (1.2)
3121
  *
3122
+ * @uses bp_get_member_activity_feed_link()
3123
  */
3124
  function bp_member_activity_feed_link() {
3125
  echo bp_get_member_activity_feed_link();
3128
  /**
3129
  * Output the member activity feed link.
3130
  *
3131
+ * @since BuddyPress (1.0)
3132
+ * @deprecated BuddyPress (1.2)
3133
  *
3134
  * @todo properly deprecate in favor of bp_member_activity_feed_link().
3135
  *
3136
+ * @uses bp_get_member_activity_feed_link()
3137
  */
3138
  function bp_activities_member_rss_link() { echo bp_get_member_activity_feed_link(); }
3139
 
3140
  /**
3141
  * Return the member activity feed link.
3142
  *
3143
+ * @since BuddyPress (1.2)
3144
  *
3145
+ * @uses bp_is_profile_component()
3146
+ * @uses bp_is_current_action()
3147
+ * @uses bp_displayed_user_domain()
3148
+ * @uses bp_get_activity_slug()
3149
+ * @uses bp_is_active()
3150
+ * @uses bp_get_friends_slug()
3151
+ * @uses bp_get_groups_slug()
3152
+ * @uses apply_filters() To call the 'bp_get_activities_member_rss_link' hook.
3153
  *
3154
  * @return string $link The member activity feed link.
3155
  */
3156
  function bp_get_member_activity_feed_link() {
3157
 
3158
+ if ( bp_is_profile_component() || bp_is_current_action( 'just-me' ) )
 
3159
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/feed/';
3160
+ elseif ( bp_is_active( 'friends' ) && bp_is_current_action( bp_get_friends_slug() ) )
 
 
3161
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_friends_slug() . '/feed/';
3162
+ elseif ( bp_is_active( 'groups' ) && bp_is_current_action( bp_get_groups_slug() ) )
 
 
3163
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_groups_slug() . '/feed/';
3164
+ elseif ( 'favorites' == bp_current_action() )
 
 
3165
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/favorites/feed/';
3166
+ elseif ( 'mentions' == bp_current_action() && bp_activity_do_mentions() )
 
 
3167
  $link = bp_displayed_user_domain() . bp_get_activity_slug() . '/mentions/feed/';
3168
+ else
 
 
3169
  $link = '';
 
3170
 
 
 
 
 
 
 
 
3171
  return apply_filters( 'bp_get_activities_member_rss_link', $link );
3172
  }
3173
 
3174
  /**
3175
  * Return the member activity feed link.
3176
  *
3177
+ * @since BuddyPress (1.0)
3178
+ * @deprecated BuddyPress (1.2)
3179
  *
3180
  * @todo properly deprecate in favor of bp_get_member_activity_feed_link().
3181
  *
3182
+ * @uses bp_get_member_activity_feed_link()
3183
  *
3184
  * @return string The member activity feed link.
3185
  */
3191
  /**
3192
  * Outputs the activity feed item guid.
3193
  *
3194
+ * @since BuddyPress (1.0)
3195
  *
3196
+ * @uses bp_activity_feed_item_guid()
3197
  */
3198
  function bp_activity_feed_item_guid() {
3199
  echo bp_get_activity_feed_item_guid();
3202
  /**
3203
  * Returns the activity feed item guid.
3204
  *
3205
+ * @since BuddyPress (1.2)
3206
  *
3207
  * @global object $activities_template {@link BP_Activity_Template}
3208
+ * @uses apply_filters() To call the 'bp_get_activity_feed_item_guid' hook.
3209
  *
3210
  * @return string The activity feed item guid.
3211
  */
3212
  function bp_get_activity_feed_item_guid() {
3213
  global $activities_template;
3214
 
 
 
 
 
 
 
 
3215
  return apply_filters( 'bp_get_activity_feed_item_guid', md5( $activities_template->activity->date_recorded . '-' . $activities_template->activity->content ) );
3216
  }
3217
 
3218
  /**
3219
  * Output the activity feed item title.
3220
  *
3221
+ * @since BuddyPress (1.0)
3222
  *
3223
+ * @uses bp_get_activity_feed_item_title()
3224
  */
3225
  function bp_activity_feed_item_title() {
3226
  echo bp_get_activity_feed_item_title();
3229
  /**
3230
  * Return the activity feed item title.
3231
  *
3232
+ * @since BuddyPress (1.0)
3233
  *
3234
  * @global object $activities_template {@link BP_Activity_Template}
3235
+ * @uses ent2ncr()
3236
+ * @uses convert_chars()
3237
+ * @uses bp_create_excerpt()
3238
+ * @uses apply_filters() To call the 'bp_get_activity_feed_item_title' hook.
3239
  *
3240
  * @return string $title The activity feed item title.
3241
  */
3242
  function bp_get_activity_feed_item_title() {
3243
  global $activities_template;
3244
 
3245
+ if ( !empty( $activities_template->activity->action ) )
3246
  $content = $activities_template->activity->action;
3247
+ else
3248
  $content = $activities_template->activity->content;
 
3249
 
3250
  $content = explode( '<span', $content );
3251
+ $title = strip_tags( ent2ncr( trim( convert_chars( $content[0] ) ) ) );
3252
 
3253
+ if ( ':' == substr( $title, -1 ) )
3254
  $title = substr( $title, 0, -1 );
 
3255
 
3256
+ if ( 'activity_update' == $activities_template->activity->type )
3257
  $title .= ': ' . strip_tags( ent2ncr( trim( convert_chars( bp_create_excerpt( $activities_template->activity->content, 70, array( 'ending' => " [&#133;]" ) ) ) ) ) );
 
3258
 
 
 
 
 
 
 
 
3259
  return apply_filters( 'bp_get_activity_feed_item_title', $title );
3260
  }
3261
 
3262
  /**
3263
+ * Output the activity feed item link
3264
  *
3265
+ * @since BuddyPress (1.0)
3266
  *
3267
+ * @uses bp_get_activity_feed_item_link()
3268
  */
3269
  function bp_activity_feed_item_link() {
3270
  echo bp_get_activity_feed_item_link();
3271
  }
3272
 
3273
  /**
3274
+ * Return the activity feed item link
3275
  *
3276
+ * @since BuddyPress (1.0)
3277
  *
3278
  * @global object $activities_template {@link BP_Activity_Template}
3279
+ * @uses apply_filters() To call the 'bp_get_activity_feed_item_link' hook.
3280
  *
3281
  * @return string The activity feed item link.
3282
  */
3283
  function bp_get_activity_feed_item_link() {
3284
  global $activities_template;
3285
 
3286
+ return apply_filters( 'bp_get_activity_feed_item_link', $activities_template->activity->primary_link );
 
 
 
 
 
 
 
 
 
 
 
3287
  }
3288
 
3289
  /**
3290
  * Output the activity feed item date.
3291
  *
3292
+ * @since BuddyPress (1.0)
3293
  *
3294
+ * @uses bp_get_activity_feed_item_date()
3295
  */
3296
  function bp_activity_feed_item_date() {
3297
  echo bp_get_activity_feed_item_date();
3300
  /**
3301
  * Return the activity feed item date.
3302
  *
3303
+ * @since BuddyPress (1.0)
3304
  *
3305
  * @global object $activities_template {@link BP_Activity_Template}
3306
+ * @uses apply_filters() To call the 'bp_get_activity_feed_item_date' hook.
3307
  *
3308
  * @return string The activity feed item date.
3309
  */
3310
  function bp_get_activity_feed_item_date() {
3311
  global $activities_template;
3312
 
3313
+ return apply_filters( 'bp_get_activity_feed_item_date', $activities_template->activity->date_recorded );
 
 
 
 
 
 
 
 
 
 
 
3314
  }
3315
 
3316
  /**
3317
  * Output the activity feed item description.
3318
  *
3319
+ * @since BuddyPress (1.0)
3320
  *
3321
+ * @uses bp_get_activity_feed_item_description()
3322
  */
3323
  function bp_activity_feed_item_description() {
3324
  echo bp_get_activity_feed_item_description();
3327
  /**
3328
  * Return the activity feed item description.
3329
  *
3330
+ * @since BuddyPress (1.0)
3331
  *
3332
  * @global object $activities_template {@link BP_Activity_Template}
3333
+ * @uses ent2ncr()
3334
+ * @uses convert_chars()
3335
+ * @uses apply_filters() To call the 'bp_get_activity_feed_item_description' hook.
3336
  *
3337
  * @return string The activity feed item description.
3338
  */
3339
  function bp_get_activity_feed_item_description() {
3340
  global $activities_template;
3341
 
3342
+ $content = '';
3343
+ if ( ! empty( $activities_template->activity->content ) )
3344
+ $content = $activities_template->activity->content;
 
 
 
 
 
 
3345
 
3346
+ return apply_filters( 'bp_get_activity_feed_item_description', ent2ncr( convert_chars( str_replace( '%s', '', $content ) ) ) );
 
 
 
 
 
 
 
3347
  }
3348
 
3349
  /**
3350
  * Template tag so we can hook activity feed to <head>.
3351
  *
3352
+ * @since BuddyPress (1.5)
3353
  *
3354
+ * @uses bloginfo()
3355
+ * @uses bp_sitewide_activity_feed_link()
3356
  */
3357
  function bp_activity_sitewide_feed() {
3358
  ?>
3362
  <?php
3363
  }
3364
  add_action( 'bp_head', 'bp_activity_sitewide_feed' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-activity.php DELETED
@@ -1,1871 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Classes
4
- *
5
- * @package BuddyPress
6
- * @subpackage Activity
7
- * @since 1.0.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- /**
14
- * Database interaction class for the BuddyPress activity component.
15
- * Instance methods are available for creating/editing an activity,
16
- * static methods for querying activities.
17
- *
18
- * @since 1.0.0
19
- */
20
- class BP_Activity_Activity {
21
-
22
- /** Properties ************************************************************/
23
-
24
- /**
25
- * ID of the activity item.
26
- *
27
- * @since 1.0.0
28
- * @var int
29
- */
30
- var $id;
31
-
32
- /**
33
- * ID of the associated item.
34
- *
35
- * @since 1.0.0
36
- * @var int
37
- */
38
- var $item_id;
39
-
40
- /**
41
- * ID of the associated secondary item.
42
- *
43
- * @since 1.0.0
44
- * @var int
45
- */
46
- var $secondary_item_id;
47
-
48
- /**
49
- * ID of user associated with the activity item.
50
- *
51
- * @since 1.0.0
52
- * @var int
53
- */
54
- var $user_id;
55
-
56
- /**
57
- * The primary URL for the activity in RSS feeds.
58
- *
59
- * @since 1.0.0
60
- * @var string
61
- */
62
- var $primary_link;
63
-
64
- /**
65
- * BuddyPress component the activity item relates to.
66
- *
67
- * @since 1.2.0
68
- * @var string
69
- */
70
- var $component;
71
-
72
- /**
73
- * Activity type, eg 'new_blog_post'.
74
- *
75
- * @since 1.2.0
76
- * @var string
77
- */
78
- var $type;
79
-
80
- /**
81
- * Description of the activity, eg 'Alex updated his profile.'.
82
- *
83
- * @since 1.2.0
84
- * @var string
85
- */
86
- var $action;
87
-
88
- /**
89
- * The content of the activity item.
90
- *
91
- * @since 1.2.0
92
- * @var string
93
- */
94
- var $content;
95
-
96
- /**
97
- * The date the activity item was recorded, in 'Y-m-d h:i:s' format.
98
- *
99
- * @since 1.0.0
100
- * @var string
101
- */
102
- var $date_recorded;
103
-
104
- /**
105
- * Whether the item should be hidden in sitewide streams.
106
- *
107
- * @since 1.1.0
108
- * @var int
109
- */
110
- var $hide_sitewide = 0;
111
-
112
- /**
113
- * Node boundary start for activity or activity comment.
114
- *
115
- * @since 1.5.0
116
- * @var int
117
- */
118
- var $mptt_left;
119
-
120
- /**
121
- * Node boundary end for activity or activity comment.
122
- *
123
- * @since 1.5.0
124
- * @var int
125
- */
126
- var $mptt_right;
127
-
128
- /**
129
- * Whether this item is marked as spam.
130
- *
131
- * @since 1.6.0
132
- * @var int
133
- */
134
- var $is_spam;
135
-
136
- /**
137
- * Error holder.
138
- *
139
- * @since 2.6.0
140
- *
141
- * @var WP_Error
142
- */
143
- public $errors;
144
-
145
- /**
146
- * Error type to return. Either 'bool' or 'wp_error'.
147
- *
148
- * @since 2.6.0
149
- *
150
- * @var string
151
- */
152
- public $error_type = 'bool';
153
-
154
- /**
155
- * Constructor method.
156
- *
157
- * @since 1.5.0
158
- *
159
- * @param int|bool $id Optional. The ID of a specific activity item.
160
- */
161
- public function __construct( $id = false ) {
162
- // Instantiate errors object.
163
- $this->errors = new WP_Error;
164
-
165
- if ( !empty( $id ) ) {
166
- $this->id = (int) $id;
167
- $this->populate();
168
- }
169
- }
170
-
171
- /**
172
- * Populate the object with data about the specific activity item.
173
- *
174
- * @since 1.0.0
175
- */
176
- public function populate() {
177
- global $wpdb;
178
-
179
- $row = wp_cache_get( $this->id, 'bp_activity' );
180
-
181
- if ( false === $row ) {
182
- $bp = buddypress();
183
- $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE id = %d", $this->id ) );
184
-
185
- wp_cache_set( $this->id, $row, 'bp_activity' );
186
- }
187
-
188
- if ( empty( $row ) ) {
189
- $this->id = 0;
190
- return;
191
- }
192
-
193
- $this->id = (int) $row->id;
194
- $this->item_id = (int) $row->item_id;
195
- $this->secondary_item_id = (int) $row->secondary_item_id;
196
- $this->user_id = (int) $row->user_id;
197
- $this->primary_link = $row->primary_link;
198
- $this->component = $row->component;
199
- $this->type = $row->type;
200
- $this->action = $row->action;
201
- $this->content = $row->content;
202
- $this->date_recorded = $row->date_recorded;
203
- $this->hide_sitewide = (int) $row->hide_sitewide;
204
- $this->mptt_left = (int) $row->mptt_left;
205
- $this->mptt_right = (int) $row->mptt_right;
206
- $this->is_spam = (int) $row->is_spam;
207
-
208
- // Generate dynamic 'action' when possible.
209
- $action = bp_activity_generate_action_string( $this );
210
- if ( false !== $action ) {
211
- $this->action = $action;
212
-
213
- // If no callback is available, use the literal string from
214
- // the database row.
215
- } elseif ( ! empty( $row->action ) ) {
216
- $this->action = $row->action;
217
-
218
- // Provide a fallback to avoid PHP notices.
219
- } else {
220
- $this->action = '';
221
- }
222
- }
223
-
224
- /**
225
- * Save the activity item to the database.
226
- *
227
- * @since 1.0.0
228
- *
229
- * @return bool True on success.
230
- */
231
- public function save() {
232
- global $wpdb;
233
-
234
- $bp = buddypress();
235
-
236
- $this->id = apply_filters_ref_array( 'bp_activity_id_before_save', array( $this->id, &$this ) );
237
- $this->item_id = apply_filters_ref_array( 'bp_activity_item_id_before_save', array( $this->item_id, &$this ) );
238
- $this->secondary_item_id = apply_filters_ref_array( 'bp_activity_secondary_item_id_before_save', array( $this->secondary_item_id, &$this ) );
239
- $this->user_id = apply_filters_ref_array( 'bp_activity_user_id_before_save', array( $this->user_id, &$this ) );
240
- $this->primary_link = apply_filters_ref_array( 'bp_activity_primary_link_before_save', array( $this->primary_link, &$this ) );
241
- $this->component = apply_filters_ref_array( 'bp_activity_component_before_save', array( $this->component, &$this ) );
242
- $this->type = apply_filters_ref_array( 'bp_activity_type_before_save', array( $this->type, &$this ) );
243
- $this->action = apply_filters_ref_array( 'bp_activity_action_before_save', array( $this->action, &$this ) );
244
- $this->content = apply_filters_ref_array( 'bp_activity_content_before_save', array( $this->content, &$this ) );
245
- $this->date_recorded = apply_filters_ref_array( 'bp_activity_date_recorded_before_save', array( $this->date_recorded, &$this ) );
246
- $this->hide_sitewide = apply_filters_ref_array( 'bp_activity_hide_sitewide_before_save', array( $this->hide_sitewide, &$this ) );
247
- $this->mptt_left = apply_filters_ref_array( 'bp_activity_mptt_left_before_save', array( $this->mptt_left, &$this ) );
248
- $this->mptt_right = apply_filters_ref_array( 'bp_activity_mptt_right_before_save', array( $this->mptt_right, &$this ) );
249
- $this->is_spam = apply_filters_ref_array( 'bp_activity_is_spam_before_save', array( $this->is_spam, &$this ) );
250
-
251
- /**
252
- * Fires before the current activity item gets saved.
253
- *
254
- * Please use this hook to filter the properties above. Each part will be passed in.
255
- *
256
- * @since 1.0.0
257
- *
258
- * @param BP_Activity_Activity $this Current instance of the activity item being saved. Passed by reference.
259
- */
260
- do_action_ref_array( 'bp_activity_before_save', array( &$this ) );
261
-
262
- if ( 'wp_error' === $this->error_type && $this->errors->get_error_code() ) {
263
- return $this->errors;
264
- }
265
-
266
- if ( empty( $this->component ) || empty( $this->type ) ) {
267
- if ( 'bool' === $this->error_type ) {
268
- return false;
269
- } else {
270
- if ( empty( $this->component ) ) {
271
- $this->errors->add( 'bp_activity_missing_component' );
272
- } else {
273
- $this->errors->add( 'bp_activity_missing_type' );
274
- }
275
-
276
- return $this->errors;
277
- }
278
- }
279
-
280
- if ( empty( $this->primary_link ) ) {
281
- $this->primary_link = bp_loggedin_user_domain();
282
- }
283
-
284
- // If we have an existing ID, update the activity item, otherwise insert it.
285
- if ( ! empty( $this->id ) ) {
286
- $q = $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET user_id = %d, component = %s, type = %s, action = %s, content = %s, primary_link = %s, date_recorded = %s, item_id = %d, secondary_item_id = %d, hide_sitewide = %d, is_spam = %d WHERE id = %d", $this->user_id, $this->component, $this->type, $this->action, $this->content, $this->primary_link, $this->date_recorded, $this->item_id, $this->secondary_item_id, $this->hide_sitewide, $this->is_spam, $this->id );
287
- } else {
288
- $q = $wpdb->prepare( "INSERT INTO {$bp->activity->table_name} ( user_id, component, type, action, content, primary_link, date_recorded, item_id, secondary_item_id, hide_sitewide, is_spam ) VALUES ( %d, %s, %s, %s, %s, %s, %s, %d, %d, %d, %d )", $this->user_id, $this->component, $this->type, $this->action, $this->content, $this->primary_link, $this->date_recorded, $this->item_id, $this->secondary_item_id, $this->hide_sitewide, $this->is_spam );
289
- }
290
-
291
- if ( false === $wpdb->query( $q ) ) {
292
- return false;
293
- }
294
-
295
- // If this is a new activity item, set the $id property.
296
- if ( empty( $this->id ) ) {
297
- $this->id = $wpdb->insert_id;
298
-
299
- // If an existing activity item, prevent any changes to the content generating new @mention notifications.
300
- } else {
301
- add_filter( 'bp_activity_at_name_do_notifications', '__return_false' );
302
- }
303
-
304
- /**
305
- * Fires after an activity item has been saved to the database.
306
- *
307
- * @since 1.0.0
308
- *
309
- * @param BP_Activity_Activity $this Current instance of activity item being saved. Passed by reference.
310
- */
311
- do_action_ref_array( 'bp_activity_after_save', array( &$this ) );
312
-
313
- return true;
314
- }
315
-
316
- /** Static Methods ***************************************************/
317
-
318
- /**
319
- * Get activity items, as specified by parameters.
320
- *
321
- * @since 1.2.0
322
- * @since 2.4.0 Introduced the `$fields` parameter.
323
- *
324
- * @see BP_Activity_Activity::get_filter_sql() for a description of the
325
- * 'filter' parameter.
326
- * @see WP_Meta_Query::queries for a description of the 'meta_query'
327
- * parameter format.
328
- *
329
- * @param array $args {
330
- * An array of arguments. All items are optional.
331
- * @type int $page Which page of results to fetch. Using page=1 without per_page will result
332
- * in no pagination. Default: 1.
333
- * @type int|bool $per_page Number of results per page. Default: 25.
334
- * @type int|bool $max Maximum number of results to return. Default: false (unlimited).
335
- * @type string $fields Activity fields to return. Pass 'ids' to get only the activity IDs.
336
- * 'all' returns full activity objects.
337
- * @type string $sort ASC or DESC. Default: 'DESC'.
338
- * @type array $exclude Array of activity IDs to exclude. Default: false.
339
- * @type array $in Array of ids to limit query by (IN). Default: false.
340
- * @type array $meta_query Array of meta_query conditions. See WP_Meta_Query::queries.
341
- * @type array $date_query Array of date_query conditions. See first parameter of
342
- * WP_Date_Query::__construct().
343
- * @type array $filter_query Array of advanced query conditions. See BP_Activity_Query::__construct().
344
- * @type string|array $scope Pre-determined set of activity arguments.
345
- * @type array $filter See BP_Activity_Activity::get_filter_sql().
346
- * @type string $search_terms Limit results by a search term. Default: false.
347
- * @type bool $display_comments Whether to include activity comments. Default: false.
348
- * @type bool $show_hidden Whether to show items marked hide_sitewide. Default: false.
349
- * @type string $spam Spam status. Default: 'ham_only'.
350
- * @type bool $update_meta_cache Whether to pre-fetch metadata for queried activity items. Default: true.
351
- * @type string|bool $count_total If true, an additional DB query is run to count the total activity items
352
- * for the query. Default: false.
353
- * }
354
- * @return array The array returned has two keys:
355
- * - 'total' is the count of located activities
356
- * - 'activities' is an array of the located activities
357
- */
358
- public static function get( $args = array() ) {
359
- global $wpdb;
360
-
361
- // Backward compatibility with old method of passing arguments.
362
- if ( !is_array( $args ) || func_num_args() > 1 ) {
363
- _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__ ) );
364
-
365
- $old_args_keys = array(
366
- 0 => 'max',
367
- 1 => 'page',
368
- 2 => 'per_page',
369
- 3 => 'sort',
370
- 4 => 'search_terms',
371
- 5 => 'filter',
372
- 6 => 'display_comments',
373
- 7 => 'show_hidden',
374
- 8 => 'exclude',
375
- 9 => 'in',
376
- 10 => 'spam'
377
- );
378
-
379
- $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
380
- }
381
-
382
- $bp = buddypress();
383
- $r = wp_parse_args( $args, array(
384
- 'page' => 1, // The current page.
385
- 'per_page' => 25, // Activity items per page.
386
- 'max' => false, // Max number of items to return.
387
- 'fields' => 'all', // Fields to include.
388
- 'sort' => 'DESC', // ASC or DESC.
389
- 'exclude' => false, // Array of ids to exclude.
390
- 'in' => false, // Array of ids to limit query by (IN).
391
- 'meta_query' => false, // Filter by activitymeta.
392
- 'date_query' => false, // Filter by date.
393
- 'filter_query' => false, // Advanced filtering - see BP_Activity_Query.
394
- 'filter' => false, // See self::get_filter_sql().
395
- 'scope' => false, // Preset activity arguments.
396
- 'search_terms' => false, // Terms to search by.
397
- 'display_comments' => false, // Whether to include activity comments.
398
- 'show_hidden' => false, // Show items marked hide_sitewide.
399
- 'spam' => 'ham_only', // Spam status.
400
- 'update_meta_cache' => true, // Whether or not to update meta cache.
401
- 'count_total' => false, // Whether or not to use count_total.
402
- ) );
403
-
404
- // Select conditions.
405
- $select_sql = "SELECT DISTINCT a.id";
406
-
407
- $from_sql = " FROM {$bp->activity->table_name} a";
408
-
409
- $join_sql = '';
410
-
411
- // Where conditions.
412
- $where_conditions = array();
413
-
414
- // Excluded types.
415
- $excluded_types = array();
416
-
417
- // Scope takes precedence.
418
- if ( ! empty( $r['scope'] ) ) {
419
- $scope_query = self::get_scope_query_sql( $r['scope'], $r );
420
-
421
- // Add our SQL conditions if matches were found.
422
- if ( ! empty( $scope_query['sql'] ) ) {
423
- $where_conditions['scope_query_sql'] = $scope_query['sql'];
424
- }
425
-
426
- // Override some arguments if needed.
427
- if ( ! empty( $scope_query['override'] ) ) {
428
- $r = array_replace_recursive( $r, $scope_query['override'] );
429
- }
430
-
431
- // Advanced filtering.
432
- } elseif ( ! empty( $r['filter_query'] ) ) {
433
- $filter_query = new BP_Activity_Query( $r['filter_query'] );
434
- $sql = $filter_query->get_sql();
435
- if ( ! empty( $sql ) ) {
436
- $where_conditions['filter_query_sql'] = $sql;
437
- }
438
- }
439
-
440
- // Regular filtering.
441
- if ( $r['filter'] && $filter_sql = BP_Activity_Activity::get_filter_sql( $r['filter'] ) ) {
442
- $where_conditions['filter_sql'] = $filter_sql;
443
- }
444
-
445
- // Spam.
446
- if ( 'ham_only' == $r['spam'] ) {
447
- $where_conditions['spam_sql'] = 'a.is_spam = 0';
448
- } elseif ( 'spam_only' == $r['spam'] ) {
449
- $where_conditions['spam_sql'] = 'a.is_spam = 1';
450
- }
451
-
452
- // Searching.
453
- if ( $r['search_terms'] ) {
454
- $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%';
455
- $where_conditions['search_sql'] = $wpdb->prepare( 'a.content LIKE %s', $search_terms_like );
456
- }
457
-
458
- // Sorting.
459
- $sort = $r['sort'];
460
- if ( $sort != 'ASC' && $sort != 'DESC' ) {
461
- $sort = 'DESC';
462
- }
463
-
464
- // Hide Hidden Items?
465
- if ( ! $r['show_hidden'] ) {
466
- $where_conditions['hidden_sql'] = "a.hide_sitewide = 0";
467
- }
468
-
469
- // Exclude specified items.
470
- if ( ! empty( $r['exclude'] ) ) {
471
- $exclude = implode( ',', wp_parse_id_list( $r['exclude'] ) );
472
- $where_conditions['exclude'] = "a.id NOT IN ({$exclude})";
473
- }
474
-
475
- // The specific ids to which you want to limit the query.
476
- if ( ! empty( $r['in'] ) ) {
477
- $in = implode( ',', wp_parse_id_list( $r['in'] ) );
478
- $where_conditions['in'] = "a.id IN ({$in})";
479
- }
480
-
481
- // Process meta_query into SQL.
482
- $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] );
483
-
484
- if ( ! empty( $meta_query_sql['join'] ) ) {
485
- $join_sql .= $meta_query_sql['join'];
486
- }
487
-
488
- if ( ! empty( $meta_query_sql['where'] ) ) {
489
- $where_conditions[] = $meta_query_sql['where'];
490
- }
491
-
492
- // Process date_query into SQL.
493
- $date_query_sql = self::get_date_query_sql( $r['date_query'] );
494
-
495
- if ( ! empty( $date_query_sql ) ) {
496
- $where_conditions['date'] = $date_query_sql;
497
- }
498
-
499
- // Alter the query based on whether we want to show activity item
500
- // comments in the stream like normal comments or threaded below
501
- // the activity.
502
- if ( false === $r['display_comments'] || 'threaded' === $r['display_comments'] ) {
503
- $excluded_types[] = 'activity_comment';
504
- }
505
-
506
- // Exclude 'last_activity' items unless the 'action' filter has
507
- // been explicitly set.
508
- if ( empty( $r['filter']['object'] ) ) {
509
- $excluded_types[] = 'last_activity';
510
- }
511
-
512
- // Build the excluded type sql part.
513
- if ( ! empty( $excluded_types ) ) {
514
- $not_in = "'" . implode( "', '", esc_sql( $excluded_types ) ) . "'";
515
- $where_conditions['excluded_types'] = "a.type NOT IN ({$not_in})";
516
- }
517
-
518
- /**
519
- * Filters the MySQL WHERE conditions for the Activity items get method.
520
- *
521
- * @since 1.9.0
522
- *
523
- * @param array $where_conditions Current conditions for MySQL WHERE statement.
524
- * @param array $r Parsed arguments passed into method.
525
- * @param string $select_sql Current SELECT MySQL statement at point of execution.
526
- * @param string $from_sql Current FROM MySQL statement at point of execution.
527
- * @param string $join_sql Current INNER JOIN MySQL statement at point of execution.
528
- */
529
- $where_conditions = apply_filters( 'bp_activity_get_where_conditions', $where_conditions, $r, $select_sql, $from_sql, $join_sql );
530
-
531
- // Join the where conditions together.
532
- $where_sql = 'WHERE ' . join( ' AND ', $where_conditions );
533
-
534
- /**
535
- * Filter the MySQL JOIN clause for the main activity query.
536
- *
537
- * @since 2.5.0
538
- *
539
- * @param string $join_sql JOIN clause.
540
- * @param array $r Method parameters.
541
- * @param string $select_sql Current SELECT MySQL statement.
542
- * @param string $from_sql Current FROM MySQL statement.
543
- * @param string $where_sql Current WHERE MySQL statement.
544
- */
545
- $join_sql = apply_filters( 'bp_activity_get_join_sql', $join_sql, $r, $select_sql, $from_sql, $where_sql );
546
-
547
- /**
548
- * Filters the preferred order of indexes for activity item.
549
- *
550
- * @since 1.6.0
551
- *
552
- * @param array $value Array of indexes in preferred order.
553
- */
554
- $indexes = apply_filters( 'bp_activity_preferred_index_order', array( 'user_id', 'item_id', 'secondary_item_id', 'date_recorded', 'component', 'type', 'hide_sitewide', 'is_spam' ) );
555
-
556
- foreach( $indexes as $key => $index ) {
557
- if ( false !== strpos( $where_sql, $index ) ) {
558
- $the_index = $index;
559
- break; // Take the first one we find.
560
- }
561
- }
562
-
563
- if ( !empty( $the_index ) ) {
564
- $index_hint_sql = "USE INDEX ({$the_index})";
565
- } else {
566
- $index_hint_sql = '';
567
- }
568
-
569
- // Sanitize page and per_page parameters.
570
- $page = absint( $r['page'] );
571
- $per_page = absint( $r['per_page'] );
572
-
573
- $retval = array(
574
- 'activities' => null,
575
- 'total' => null,
576
- 'has_more_items' => null,
577
- );
578
-
579
- /**
580
- * Filters if BuddyPress should use legacy query structure over current structure for version 2.0+.
581
- *
582
- * It is not recommended to use the legacy structure, but allowed to if needed.
583
- *
584
- * @since 2.0.0
585
- *
586
- * @param bool $value Whether to use legacy structure or not.
587
- * @param BP_Activity_Activity $value Current method being called.
588
- * @param array $r Parsed arguments passed into method.
589
- */
590
- if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, $r ) ) {
591
-
592
- // Legacy queries joined against the user table.
593
- $select_sql = "SELECT DISTINCT a.*, u.user_email, u.user_nicename, u.user_login, u.display_name";
594
- $from_sql = " FROM {$bp->activity->table_name} a LEFT JOIN {$wpdb->users} u ON a.user_id = u.ID";
595
-
596
- if ( ! empty( $page ) && ! empty( $per_page ) ) {
597
- $pag_sql = $wpdb->prepare( "LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page );
598
-
599
- /** This filter is documented in bp-activity/bp-activity-classes.php */
600
- $activities = $wpdb->get_results( apply_filters( 'bp_activity_get_user_join_filter', "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}, a.id {$sort} {$pag_sql}", $select_sql, $from_sql, $where_sql, $sort, $pag_sql ) );
601
- } else {
602
- $pag_sql = '';
603
-
604
- /**
605
- * Filters the legacy MySQL query statement so plugins can alter before results are fetched.
606
- *
607
- * @since 1.5.0
608
- *
609
- * @param string $value Concatenated MySQL statement pieces to be query results with for legacy query.
610
- * @param string $select_sql Final SELECT MySQL statement portion for legacy query.
611
- * @param string $from_sql Final FROM MySQL statement portion for legacy query.
612
- * @param string $where_sql Final WHERE MySQL statement portion for legacy query.
613
- * @param string $sort Final sort direction for legacy query.
614
- */
615
- $activities = $wpdb->get_results( apply_filters( 'bp_activity_get_user_join_filter', "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}, a.id {$sort}", $select_sql, $from_sql, $where_sql, $sort, $pag_sql ) );
616
- }
617
-
618
- // Integer casting for legacy activity query.
619
- foreach ( (array) $activities as $i => $ac ) {
620
- $activities[ $i ]->id = (int) $ac->id;
621
- $activities[ $i ]->item_id = (int) $ac->item_id;
622
- $activities[ $i ]->secondary_item_id = (int) $ac->secondary_item_id;
623
- $activities[ $i ]->user_id = (int) $ac->user_id;
624
- $activities[ $i ]->hide_sitewide = (int) $ac->hide_sitewide;
625
- $activities[ $i ]->mptt_left = (int) $ac->mptt_left;
626
- $activities[ $i ]->mptt_right = (int) $ac->mptt_right;
627
- $activities[ $i ]->is_spam = (int) $ac->is_spam;
628
- }
629
-
630
- } else {
631
- // Query first for activity IDs.
632
- $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}, a.id {$sort}";
633
-
634
- if ( ! empty( $per_page ) && ! empty( $page ) ) {
635
- // We query for $per_page + 1 items in order to
636
- // populate the has_more_items flag.
637
- $activity_ids_sql .= $wpdb->prepare( " LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page + 1 );
638
- }
639
-
640
- /**
641
- * Filters the paged activities MySQL statement.
642
- *
643
- * @since 2.0.0
644
- *
645
- * @param string $activity_ids_sql MySQL statement used to query for Activity IDs.
646
- * @param array $r Array of arguments passed into method.
647
- */
648
- $activity_ids_sql = apply_filters( 'bp_activity_paged_activities_sql', $activity_ids_sql, $r );
649
-
650
- /*
651
- * Queries that include 'last_activity' are cached separately,
652
- * since they are generally much less long-lived.
653
- */
654
- if ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $activity_ids_sql ) ) {
655
- $cache_group = 'bp_activity';
656
- } else {
657
- $cache_group = 'bp_activity_with_last_activity';
658
- }
659
-
660
- $cached = bp_core_get_incremented_cache( $activity_ids_sql, $cache_group );
661
- if ( false === $cached ) {
662
- $activity_ids = $wpdb->get_col( $activity_ids_sql );
663
- bp_core_set_incremented_cache( $activity_ids_sql, $cache_group, $activity_ids );
664
- } else {
665
- $activity_ids = $cached;
666
- }
667
-
668
- $retval['has_more_items'] = ! empty( $per_page ) && count( $activity_ids ) > $per_page;
669
-
670
- // If we've fetched more than the $per_page value, we
671
- // can discard the extra now.
672
- if ( ! empty( $per_page ) && count( $activity_ids ) === $per_page + 1 ) {
673
- array_pop( $activity_ids );
674
- }
675
-
676
- if ( 'ids' === $r['fields'] ) {
677
- $activities = array_map( 'intval', $activity_ids );
678
- } else {
679
- $activities = self::get_activity_data( $activity_ids );
680
- }
681
- }
682
-
683
- if ( 'ids' !== $r['fields'] ) {
684
- // Get the fullnames of users so we don't have to query in the loop.
685
- $activities = self::append_user_fullnames( $activities );
686
-
687
- // Get activity meta.
688
- $activity_ids = array();
689
- foreach ( (array) $activities as $activity ) {
690
- $activity_ids[] = $activity->id;
691
- }
692
-
693
- if ( ! empty( $activity_ids ) && $r['update_meta_cache'] ) {
694
- bp_activity_update_meta_cache( $activity_ids );
695
- }
696
-
697
- if ( $activities && $r['display_comments'] ) {
698
- $activities = BP_Activity_Activity::append_comments( $activities, $r['spam'] );
699
- }
700
-
701
- // Pre-fetch data associated with activity users and other objects.
702
- BP_Activity_Activity::prefetch_object_data( $activities );
703
-
704
- // Generate action strings.
705
- $activities = BP_Activity_Activity::generate_action_strings( $activities );
706
- }
707
-
708
- $retval['activities'] = $activities;
709
-
710
- // If $max is set, only return up to the max results.
711
- if ( ! empty( $r['count_total'] ) ) {
712
-
713
- /**
714
- * Filters the total activities MySQL statement.
715
- *
716
- * @since 1.5.0
717
- *
718
- * @param string $value MySQL statement used to query for total activities.
719
- * @param string $where_sql MySQL WHERE statement portion.
720
- * @param string $sort Sort direction for query.
721
- */
722
- $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
723
- $cached = bp_core_get_incremented_cache( $total_activities_sql, $cache_group );
724
- if ( false === $cached ) {
725
- $total_activities = $wpdb->get_var( $total_activities_sql );
726
- bp_core_set_incremented_cache( $total_activities_sql, $cache_group, $total_activities );
727
- } else {
728
- $total_activities = $cached;
729
- }
730
-
731
- if ( !empty( $r['max'] ) ) {
732
- if ( (int) $total_activities > (int) $r['max'] ) {
733
- $total_activities = $r['max'];
734
- }
735
- }
736
-
737
- $retval['total'] = $total_activities;
738
- }
739
-
740
- return $retval;
741
- }
742
-
743
- /**
744
- * Convert activity IDs to activity objects, as expected in template loop.
745
- *
746
- * @since 2.0.0
747
- *
748
- * @param array $activity_ids Array of activity IDs.
749
- * @return array
750
- */
751
- protected static function get_activity_data( $activity_ids = array() ) {
752
- global $wpdb;
753
-
754
- // Bail if no activity ID's passed.
755
- if ( empty( $activity_ids ) ) {
756
- return array();
757
- }
758
-
759
- // Get BuddyPress.
760
- $bp = buddypress();
761
-
762
- $activities = array();
763
- $uncached_ids = bp_get_non_cached_ids( $activity_ids, 'bp_activity' );
764
-
765
- // Prime caches as necessary.
766
- if ( ! empty( $uncached_ids ) ) {
767
- // Format the activity ID's for use in the query below.
768
- $uncached_ids_sql = implode( ',', wp_parse_id_list( $uncached_ids ) );
769
-
770
- // Fetch data from activity table, preserving order.
771
- $queried_adata = $wpdb->get_results( "SELECT * FROM {$bp->activity->table_name} WHERE id IN ({$uncached_ids_sql})");
772
-
773
- // Put that data into the placeholders created earlier,
774
- // and add it to the cache.
775
- foreach ( (array) $queried_adata as $adata ) {
776
- wp_cache_set( $adata->id, $adata, 'bp_activity' );
777
- }
778
- }
779
-
780
- // Now fetch data from the cache.
781
- foreach ( $activity_ids as $activity_id ) {
782
- // Integer casting.
783
- $activity = wp_cache_get( $activity_id, 'bp_activity' );
784
- if ( ! empty( $activity ) ) {
785
- $activity->id = (int) $activity->id;
786
- $activity->user_id = (int) $activity->user_id;
787
- $activity->item_id = (int) $activity->item_id;
788
- $activity->secondary_item_id = (int) $activity->secondary_item_id;
789
- $activity->hide_sitewide = (int) $activity->hide_sitewide;
790
- $activity->mptt_left = (int) $activity->mptt_left;
791
- $activity->mptt_right = (int) $activity->mptt_right;
792
- $activity->is_spam = (int) $activity->is_spam;
793
- }
794
-
795
- $activities[] = $activity;
796
- }
797
-
798
- // Then fetch user data.
799
- $user_query = new BP_User_Query( array(
800
- 'user_ids' => wp_list_pluck( $activities, 'user_id' ),
801
- 'populate_extras' => false,
802
- ) );
803
-
804
- // Associated located user data with activity items.
805
- foreach ( $activities as $a_index => $a_item ) {
806
- $a_user_id = intval( $a_item->user_id );
807
- $a_user = isset( $user_query->results[ $a_user_id ] ) ? $user_query->results[ $a_user_id ] : '';
808
-
809
- if ( !empty( $a_user ) ) {
810
- $activities[ $a_index ]->user_email = $a_user->user_email;
811
- $activities[ $a_index ]->user_nicename = $a_user->user_nicename;
812
- $activities[ $a_index ]->user_login = $a_user->user_login;
813
- $activities[ $a_index ]->display_name = $a_user->display_name;
814
- }
815
- }
816
-
817
- return $activities;
818
- }
819
-
820
- /**
821
- * Append xProfile fullnames to an activity array.
822
- *
823
- * @since 2.0.0
824
- *
825
- * @param array $activities Activities array.
826
- * @return array
827
- */
828
- protected static function append_user_fullnames( $activities ) {
829
-
830
- if ( bp_is_active( 'xprofile' ) && ! empty( $activities ) ) {
831
- $activity_user_ids = wp_list_pluck( $activities, 'user_id' );
832
-
833
- if ( ! empty( $activity_user_ids ) ) {
834
- $fullnames = bp_core_get_user_displaynames( $activity_user_ids );
835
- if ( ! empty( $fullnames ) ) {
836
- foreach ( (array) $activities as $i => $activity ) {
837
- if ( ! empty( $fullnames[ $activity->user_id ] ) ) {
838
- $activities[ $i ]->user_fullname = $fullnames[ $activity->user_id ];
839
- }
840
- }
841
- }
842
- }
843
- }
844
-
845
- return $activities;
846
- }
847
-
848
- /**
849
- * Pre-fetch data for objects associated with activity items.
850
- *
851
- * Activity items are associated with users, and often with other
852
- * BuddyPress data objects. Here, we pre-fetch data about these
853
- * associated objects, so that inline lookups - done primarily when
854
- * building action strings - do not result in excess database queries.
855
- *
856
- * The only object data required for activity component activity types
857
- * (activity_update and activity_comment) is related to users, and that
858
- * info is fetched separately in BP_Activity_Activity::get_activity_data().
859
- * So this method contains nothing but a filter that allows other
860
- * components, such as bp-friends and bp-groups, to hook in and prime
861
- * their own caches at the beginning of an activity loop.
862
- *
863
- * @since 2.0.0
864
- *
865
- * @param array $activities Array of activities.
866
- * @return array $activities Array of activities.
867
- */
868
- protected static function prefetch_object_data( $activities ) {
869
-
870
- /**
871
- * Filters inside prefetch_object_data method to aid in pre-fetching object data associated with activity item.
872
- *
873
- * @since 2.0.0
874
- *
875
- * @param array $activities Array of activities.
876
- */
877
- return apply_filters( 'bp_activity_prefetch_object_data', $activities );
878
- }
879
-
880
- /**
881
- * Generate action strings for the activities located in BP_Activity_Activity::get().
882
- *
883
- * If no string can be dynamically generated for a given item
884
- * (typically because the activity type has not been properly
885
- * registered), the static 'action' value pulled from the database will
886
- * be left in place.
887
- *
888
- * @since 2.0.0
889
- *
890
- * @param array $activities Array of activities.
891
- * @return array
892
- */
893
- protected static function generate_action_strings( $activities ) {
894
- foreach ( $activities as $key => $activity ) {
895
- $generated_action = bp_activity_generate_action_string( $activity );
896
- if ( false !== $generated_action ) {
897
- $activity->action = $generated_action;
898
- }
899
-
900
- $activities[ $key ] = $activity;
901
- }
902
-
903
- return $activities;
904
- }
905
-
906
- /**
907
- * Get the SQL for the 'meta_query' param in BP_Activity_Activity::get().
908
- *
909
- * We use WP_Meta_Query to do the heavy lifting of parsing the
910
- * meta_query array and creating the necessary SQL clauses. However,
911
- * since BP_Activity_Activity::get() builds its SQL differently than
912
- * WP_Query, we have to alter the return value (stripping the leading
913
- * AND keyword from the 'where' clause).
914
- *
915
- * @since 1.8.0
916
- *
917
- * @param array $meta_query An array of meta_query filters. See the
918
- * documentation for WP_Meta_Query for details.
919
- * @return array $sql_array 'join' and 'where' clauses.
920
- */
921
- public static function get_meta_query_sql( $meta_query = array() ) {
922
- global $wpdb;
923
-
924
- $sql_array = array(
925
- 'join' => '',
926
- 'where' => '',
927
- );
928
-
929
- if ( ! empty( $meta_query ) ) {
930
- $activity_meta_query = new WP_Meta_Query( $meta_query );
931
-
932
- // WP_Meta_Query expects the table name at
933
- // $wpdb->activitymeta.
934
- $wpdb->activitymeta = buddypress()->activity->table_name_meta;
935
-
936
- $meta_sql = $activity_meta_query->get_sql( 'activity', 'a', 'id' );
937
-
938
- // Strip the leading AND - BP handles it in get().
939
- $sql_array['where'] = preg_replace( '/^\sAND/', '', $meta_sql['where'] );
940
- $sql_array['join'] = $meta_sql['join'];
941
- }
942
-
943
- return $sql_array;
944
- }
945
-
946
- /**
947
- * Get the SQL for the 'date_query' param in BP_Activity_Activity::get().
948
- *
949
- * We use BP_Date_Query, which extends WP_Date_Query, to do the heavy lifting
950
- * of parsing the date_query array and creating the necessary SQL clauses.
951
- * However, since BP_Activity_Activity::get() builds its SQL differently than
952
- * WP_Query, we have to alter the return value (stripping the leading AND
953
- * keyword from the query).
954
- *
955
- * @since 2.1.0
956
- *
957
- * @param array $date_query An array of date_query parameters. See the
958
- * documentation for the first parameter of WP_Date_Query.
959
- * @return string
960
- */
961
- public static function get_date_query_sql( $date_query = array() ) {
962
- $sql = '';
963
-
964
- // Date query.
965
- if ( ! empty( $date_query ) && is_array( $date_query ) ) {
966
- $date_query = new BP_Date_Query( $date_query, 'date_recorded' );
967
- $sql = preg_replace( '/^\sAND/', '', $date_query->get_sql() );
968
- }
969
-
970
- return $sql;
971
- }
972
-
973
- /**
974
- * Get the SQL for the 'scope' param in BP_Activity_Activity::get().
975
- *
976
- * A scope is a predetermined set of activity arguments. This method is used
977
- * to grab these activity arguments and override any existing args if needed.
978
- *
979
- * Can handle multiple scopes.
980
- *
981
- * @since 2.2.0
982
- *
983
- * @param mixed $scope The activity scope. Accepts string or array of scopes.
984
- * @param array $r Current activity arguments. Same as those of BP_Activity_Activity::get(),
985
- * but merged with defaults.
986
- * @return array 'sql' WHERE SQL string and 'override' activity args.
987
- */
988
- public static function get_scope_query_sql( $scope = false, $r = array() ) {
989
-
990
- // Define arrays for future use.
991
- $query_args = array();
992
- $override = array();
993
- $retval = array();
994
-
995
- // Check for array of scopes.
996
- if ( is_array( $scope ) ) {
997
- $scopes = $scope;
998
-
999
- // Explode a comma separated string of scopes.
1000
- } elseif ( is_string( $scope ) ) {
1001
- $scopes = explode( ',', $scope );
1002
- }
1003
-
1004
- // Bail if no scope passed.
1005
- if ( empty( $scopes ) ) {
1006
- return false;
1007
- }
1008
-
1009
- // Helper to easily grab the 'user_id'.
1010
- if ( ! empty( $r['filter']['user_id'] ) ) {
1011
- $r['user_id'] = $r['filter']['user_id'];
1012
- }
1013
-
1014
- // Parse each scope; yes! we handle multiples!
1015
- foreach ( $scopes as $scope ) {
1016
- $scope_args = array();
1017
-
1018
- /**
1019
- * Plugins can hook here to set their activity arguments for custom scopes.
1020
- *
1021
- * This is a dynamic filter based on the activity scope. eg:
1022
- * - 'bp_activity_set_groups_scope_args'
1023
- * - 'bp_activity_set_friends_scope_args'
1024
- *
1025
- * To see how this filter is used, plugin devs should check out:
1026
- * - bp_groups_filter_activity_scope() - used for 'groups' scope
1027
- * - bp_friends_filter_activity_scope() - used for 'friends' scope
1028
- *
1029
- * @since 2.2.0
1030
- *
1031
- * @param array {
1032
- * Activity query clauses.
1033
- * @type array {
1034
- * Activity arguments for your custom scope.
1035
- * See {@link BP_Activity_Query::_construct()} for more details.
1036
- * }
1037
- * @type array $override Optional. Override existing activity arguments passed by $r.
1038
- * }
1039
- * }
1040
- * @param array $r Current activity arguments passed in BP_Activity_Activity::get().
1041
- */
1042
- $scope_args = apply_filters( "bp_activity_set_{$scope}_scope_args", array(), $r );
1043
-
1044
- if ( ! empty( $scope_args ) ) {
1045
- // Merge override properties from other scopes
1046
- // this might be a problem...
1047
- if ( ! empty( $scope_args['override'] ) ) {
1048
- $override = array_merge( $override, $scope_args['override'] );
1049
- unset( $scope_args['override'] );
1050
- }
1051
-
1052
- // Save scope args.
1053
- if ( ! empty( $scope_args ) ) {
1054
- $query_args[] = $scope_args;
1055
- }
1056
- }
1057
- }
1058
-
1059
- if ( ! empty( $query_args ) ) {
1060
- // Set relation to OR.
1061
- $query_args['relation'] = 'OR';
1062
-
1063
- $query = new BP_Activity_Query( $query_args );
1064
- $sql = $query->get_sql();
1065
- if ( ! empty( $sql ) ) {
1066
- $retval['sql'] = $sql;
1067
- }
1068
- }
1069
-
1070
- if ( ! empty( $override ) ) {
1071
- $retval['override'] = $override;
1072
- }
1073
-
1074
- return $retval;
1075
- }
1076
-
1077
- /**
1078
- * In BuddyPress 1.2.x, this was used to retrieve specific activity stream items (for example, on an activity's permalink page).
1079
- *
1080
- * As of 1.5.x, use BP_Activity_Activity::get() with an 'in' parameter instead.
1081
- *
1082
- * @since 1.2.0
1083
- *
1084
- * @deprecated 1.5
1085
- * @deprecated Use BP_Activity_Activity::get() with an 'in' parameter instead.
1086
- *
1087
- * @param mixed $activity_ids Array or comma-separated string of activity IDs to retrieve.
1088
- * @param int|bool $max Maximum number of results to return. (Optional; default is no maximum).
1089
- * @param int $page The set of results that the user is viewing. Used in pagination. (Optional; default is 1).
1090
- * @param int $per_page Specifies how many results per page. Used in pagination. (Optional; default is 25).
1091
- * @param string $sort MySQL column sort; ASC or DESC. (Optional; default is DESC).
1092
- * @param bool $display_comments Retrieve an activity item's associated comments or not. (Optional; default is false).
1093
- * @return array
1094
- */
1095
- public static function get_specific( $activity_ids, $max = false, $page = 1, $per_page = 25, $sort = 'DESC', $display_comments = false ) {
1096
- _deprecated_function( __FUNCTION__, '1.5', 'Use BP_Activity_Activity::get() with the "in" parameter instead.' );
1097
- return BP_Activity_Activity::get( $max, $page, $per_page, $sort, false, false, $display_comments, false, false, $activity_ids );
1098
- }
1099
-
1100
- /**
1101
- * Get the first activity ID that matches a set of criteria.
1102
- *
1103
- * @since 1.2.0
1104
- *
1105
- * @todo Should parameters be optional?
1106
- *
1107
- * @param int $user_id User ID to filter by.
1108
- * @param string $component Component to filter by.
1109
- * @param string $type Activity type to filter by.
1110
- * @param int $item_id Associated item to filter by.
1111
- * @param int $secondary_item_id Secondary associated item to filter by.
1112
- * @param string $action Action to filter by.
1113
- * @param string $content Content to filter by.
1114
- * @param string $date_recorded Date to filter by.
1115
- * @return int|bool Activity ID on success, false if none is found.
1116
- */
1117
- public static function get_id( $user_id, $component, $type, $item_id, $secondary_item_id, $action, $content, $date_recorded ) {
1118
- global $wpdb;
1119
-
1120
- $bp = buddypress();
1121
-
1122
- $where_args = false;
1123
-
1124
- if ( ! empty( $user_id ) ) {
1125
- $where_args[] = $wpdb->prepare( "user_id = %d", $user_id );
1126
- }
1127
-
1128
- if ( ! empty( $component ) ) {
1129
- $where_args[] = $wpdb->prepare( "component = %s", $component );
1130
- }
1131
-
1132
- if ( ! empty( $type ) ) {
1133
- $where_args[] = $wpdb->prepare( "type = %s", $type );
1134
- }
1135
-
1136
- if ( ! empty( $item_id ) ) {
1137
- $where_args[] = $wpdb->prepare( "item_id = %d", $item_id );
1138
- }
1139
-
1140
- if ( ! empty( $secondary_item_id ) ) {
1141
- $where_args[] = $wpdb->prepare( "secondary_item_id = %d", $secondary_item_id );
1142
- }
1143
-
1144
- if ( ! empty( $action ) ) {
1145
- $where_args[] = $wpdb->prepare( "action = %s", $action );
1146
- }
1147
-
1148
- if ( ! empty( $content ) ) {
1149
- $where_args[] = $wpdb->prepare( "content = %s", $content );
1150
- }
1151
-
1152
- if ( ! empty( $date_recorded ) ) {
1153
- $where_args[] = $wpdb->prepare( "date_recorded = %s", $date_recorded );
1154
- }
1155
-
1156
- if ( ! empty( $where_args ) ) {
1157
- $where_sql = 'WHERE ' . join( ' AND ', $where_args );
1158
- $result = $wpdb->get_var( "SELECT id FROM {$bp->activity->table_name} {$where_sql}" );
1159
-
1160
- return is_numeric( $result ) ? (int) $result : false;
1161
- }
1162
-
1163
- return false;
1164
- }
1165
-
1166
- /**
1167
- * Delete activity items from the database.
1168
- *
1169
- * To delete a specific activity item, pass an 'id' parameter.
1170
- * Otherwise use the filters.
1171
- *
1172
- * @since 1.2.0
1173
- *
1174
- * @param array $args {
1175
- * @int $id Optional. The ID of a specific item to delete.
1176
- * @string $action Optional. The action to filter by.
1177
- * @string $content Optional. The content to filter by.
1178
- * @string $component Optional. The component name to filter by.
1179
- * @string $type Optional. The activity type to filter by.
1180
- * @string $primary_link Optional. The primary URL to filter by.
1181
- * @int $user_id Optional. The user ID to filter by.
1182
- * @int $item_id Optional. The associated item ID to filter by.
1183
- * @int $secondary_item_id Optional. The secondary associated item ID to filter by.
1184
- * @string $date_recorded Optional. The date to filter by.
1185
- * @int $hide_sitewide Optional. Default: false.
1186
- * }
1187
- * @return array|bool An array of deleted activity IDs on success, false on failure.
1188
- */
1189
- public static function delete( $args = array() ) {
1190
- global $wpdb;
1191
-
1192
- $bp = buddypress();
1193
- $r = wp_parse_args( $args, array(
1194
- 'id' => false,
1195
- 'action' => false,
1196
- 'content' => false,
1197
- 'component' => false,
1198
- 'type' => false,
1199
- 'primary_link' => false,
1200
- 'user_id' => false,
1201
- 'item_id' => false,
1202
- 'secondary_item_id' => false,
1203
- 'date_recorded' => false,
1204
- 'hide_sitewide' => false
1205
- ) );
1206
-
1207
- // Setup empty array from where query arguments.
1208
- $where_args = array();
1209
-
1210
- // ID.
1211
- if ( ! empty( $r['id'] ) ) {
1212
- $where_args[] = $wpdb->prepare( "id = %d", $r['id'] );
1213
- }
1214
-
1215
- // User ID.
1216
- if ( ! empty( $r['user_id'] ) ) {
1217
- $where_args[] = $wpdb->prepare( "user_id = %d", $r['user_id'] );
1218
- }
1219
-
1220
- // Action.
1221
- if ( ! empty( $r['action'] ) ) {
1222
- $where_args[] = $wpdb->prepare( "action = %s", $r['action'] );
1223
- }
1224
-
1225
- // Content.
1226
- if ( ! empty( $r['content'] ) ) {
1227
- $where_args[] = $wpdb->prepare( "content = %s", $r['content'] );
1228
- }
1229
-
1230
- // Component.
1231
- if ( ! empty( $r['component'] ) ) {
1232
- $where_args[] = $wpdb->prepare( "component = %s", $r['component'] );
1233
- }
1234
-
1235
- // Type.
1236
- if ( ! empty( $r['type'] ) ) {
1237
- $where_args[] = $wpdb->prepare( "type = %s", $r['type'] );
1238
- }
1239
-
1240
- // Primary Link.
1241
- if ( ! empty( $r['primary_link'] ) ) {
1242
- $where_args[] = $wpdb->prepare( "primary_link = %s", $r['primary_link'] );
1243
- }
1244
-
1245
- // Item ID.
1246
- if ( ! empty( $r['item_id'] ) ) {
1247
- $where_args[] = $wpdb->prepare( "item_id = %d", $r['item_id'] );
1248
- }
1249
-
1250
- // Secondary item ID.
1251
- if ( ! empty( $r['secondary_item_id'] ) ) {
1252
- $where_args[] = $wpdb->prepare( "secondary_item_id = %d", $r['secondary_item_id'] );
1253
- }
1254
-
1255
- // Date Recorded.
1256
- if ( ! empty( $r['date_recorded'] ) ) {
1257
- $where_args[] = $wpdb->prepare( "date_recorded = %s", $r['date_recorded'] );
1258
- }
1259
-
1260
- // Hidden sitewide.
1261
- if ( ! empty( $r['hide_sitewide'] ) ) {
1262
- $where_args[] = $wpdb->prepare( "hide_sitewide = %d", $r['hide_sitewide'] );
1263
- }
1264
-
1265
- // Bail if no where arguments.
1266
- if ( empty( $where_args ) ) {
1267
- return false;
1268
- }
1269
-
1270
- // Join the where arguments for querying.
1271
- $where_sql = 'WHERE ' . join( ' AND ', $where_args );
1272
-
1273
- // Fetch all activities being deleted so we can perform more actions.
1274
- $activities = $wpdb->get_results( "SELECT * FROM {$bp->activity->table_name} {$where_sql}" );
1275
-
1276
- /**
1277
- * Action to allow intercepting activity items to be deleted.
1278
- *
1279
- * @since 2.3.0
1280
- *
1281
- * @param array $activities Array of activities.
1282
- * @param array $r Array of parsed arguments.
1283
- */
1284
- do_action_ref_array( 'bp_activity_before_delete', array( $activities, $r ) );
1285
-
1286
- // Attempt to delete activities from the database.
1287
- $deleted = $wpdb->query( "DELETE FROM {$bp->activity->table_name} {$where_sql}" );
1288
-
1289
- // Bail if nothing was deleted.
1290
- if ( empty( $deleted ) ) {
1291
- return false;
1292
- }
1293
-
1294
- /**
1295
- * Action to allow intercepting activity items just deleted.
1296
- *
1297
- * @since 2.3.0
1298
- *
1299
- * @param array $activities Array of activities.
1300
- * @param array $r Array of parsed arguments.
1301
- */
1302
- do_action_ref_array( 'bp_activity_after_delete', array( $activities, $r ) );
1303
-
1304
- // Pluck the activity IDs out of the $activities array.
1305
- $activity_ids = wp_parse_id_list( wp_list_pluck( $activities, 'id' ) );
1306
-
1307
- // Handle accompanying activity comments and meta deletion.
1308
- if ( ! empty( $activity_ids ) ) {
1309
-
1310
- // Delete all activity meta entries for activity items.
1311
- BP_Activity_Activity::delete_activity_meta_entries( $activity_ids );
1312
-
1313
- // Setup empty array for comments.
1314
- $comment_ids = array();
1315
-
1316
- // Loop through activity ids and attempt to delete comments.
1317
- foreach ( $activity_ids as $activity_id ) {
1318
-
1319
- // Attempt to delete comments.
1320
- $comments = BP_Activity_Activity::delete( array(
1321
- 'type' => 'activity_comment',
1322
- 'item_id' => $activity_id
1323
- ) );
1324
-
1325
- // Merge IDs together.
1326
- if ( ! empty( $comments ) ) {
1327
- $comment_ids = array_merge( $comment_ids, $comments );
1328
- }
1329
- }
1330
-
1331
- // Merge activity IDs with any deleted comment IDs.
1332
- if ( ! empty( $comment_ids ) ) {
1333
- $activity_ids = array_unique( array_merge( $activity_ids, $comment_ids ) );
1334
- }
1335
- }
1336
-
1337
- return $activity_ids;
1338
- }
1339
-
1340
- /**
1341
- * Delete the comments associated with a set of activity items.
1342
- *
1343
- * This method is no longer used by BuddyPress, and it is recommended not to
1344
- * use it going forward, and use BP_Activity_Activity::delete() instead.
1345
- *
1346
- * @since 1.2.0
1347
- *
1348
- * @deprecated 2.3.0
1349
- *
1350
- * @param array $activity_ids Activity IDs whose comments should be deleted.
1351
- * @param bool $delete_meta Should we delete the activity meta items for these comments.
1352
- * @return bool True on success.
1353
- */
1354
- public static function delete_activity_item_comments( $activity_ids = array(), $delete_meta = true ) {
1355
- global $wpdb;
1356
-
1357
- $bp = buddypress();
1358
-
1359
- $delete_meta = (bool) $delete_meta;
1360
- $activity_ids = implode( ',', wp_parse_id_list( $activity_ids ) );
1361
-
1362
- if ( $delete_meta ) {
1363
- // Fetch the activity comment IDs for our deleted activity items.
1364
- $activity_comment_ids = $wpdb->get_col( "SELECT id FROM {$bp->activity->table_name} WHERE type = 'activity_comment' AND item_id IN ({$activity_ids})" );
1365
-
1366
- if ( ! empty( $activity_comment_ids ) ) {
1367
- self::delete_activity_meta_entries( $activity_comment_ids );
1368
- }
1369
- }
1370
-
1371
- return $wpdb->query( "DELETE FROM {$bp->activity->table_name} WHERE type = 'activity_comment' AND item_id IN ({$activity_ids})" );
1372
- }
1373
-
1374
- /**
1375
- * Delete the meta entries associated with a set of activity items.
1376
- *
1377
- * @since 1.2.0
1378
- *
1379
- * @param array $activity_ids Activity IDs whose meta should be deleted.
1380
- * @return bool True on success.
1381
- */
1382
- public static function delete_activity_meta_entries( $activity_ids = array() ) {
1383
- $activity_ids = wp_parse_id_list( $activity_ids );
1384
-
1385
- foreach ( $activity_ids as $activity_id ) {
1386
- bp_activity_delete_meta( $activity_id );
1387
- }
1388
-
1389
- return true;
1390
- }
1391
-
1392
- /**
1393
- * Append activity comments to their associated activity items.
1394
- *
1395
- * @since 1.2.0
1396
- *
1397
- * @global wpdb $wpdb WordPress database object.
1398
- *
1399
- * @param array $activities Activities to fetch comments for.
1400
- * @param string $spam Optional. 'ham_only' (default), 'spam_only' or 'all'.
1401
- * @return array The updated activities with nested comments.
1402
- */
1403
- public static function append_comments( $activities, $spam = 'ham_only' ) {
1404
- $activity_comments = array();
1405
-
1406
- // Now fetch the activity comments and parse them into the correct position in the activities array.
1407
- foreach ( (array) $activities as $activity ) {
1408
- $top_level_parent_id = 'activity_comment' == $activity->type ? $activity->item_id : 0;
1409
- $activity_comments[$activity->id] = BP_Activity_Activity::get_activity_comments( $activity->id, $activity->mptt_left, $activity->mptt_right, $spam, $top_level_parent_id );
1410
- }
1411
-
1412
- // Merge the comments with the activity items.
1413
- foreach ( (array) $activities as $key => $activity ) {
1414
- if ( isset( $activity_comments[$activity->id] ) ) {
1415
- $activities[$key]->children = $activity_comments[$activity->id];
1416
- }
1417
- }
1418
-
1419
- return $activities;
1420
- }
1421
-
1422
- /**
1423
- * Get activity comments that are associated with a specific activity ID.
1424
- *
1425
- * @since 1.2.0
1426
- *
1427
- * @global wpdb $wpdb WordPress database object.
1428
- *
1429
- * @param int $activity_id Activity ID to fetch comments for.
1430
- * @param int $left Left-most node boundary.
1431
- * @param int $right Right-most node boundary.
1432
- * @param string $spam Optional. 'ham_only' (default), 'spam_only' or 'all'.
1433
- * @param int $top_level_parent_id Optional. The id of the root-level parent activity item.
1434
- * @return array The updated activities with nested comments.
1435
- */
1436
- public static function get_activity_comments( $activity_id, $left, $right, $spam = 'ham_only', $top_level_parent_id = 0 ) {
1437
- global $wpdb;
1438
-
1439
- if ( empty( $top_level_parent_id ) ) {
1440
- $top_level_parent_id = $activity_id;
1441
- }
1442
-
1443
- $comments = wp_cache_get( $activity_id, 'bp_activity_comments' );
1444
-
1445
- // We store the string 'none' to cache the fact that the
1446
- // activity item has no comments.
1447
- if ( 'none' === $comments ) {
1448
- $comments = false;
1449
-
1450
- // A true cache miss.
1451
- } elseif ( empty( $comments ) ) {
1452
-
1453
- $bp = buddypress();
1454
-
1455
- // Select the user's fullname with the query.
1456
- if ( bp_is_active( 'xprofile' ) ) {
1457
- $fullname_select = ", pd.value as user_fullname";
1458
- $fullname_from = ", {$bp->profile->table_name_data} pd ";
1459
- $fullname_where = "AND pd.user_id = a.user_id AND pd.field_id = 1";
1460
-
1461
- // Prevent debug errors.
1462
- } else {
1463
- $fullname_select = $fullname_from = $fullname_where = '';
1464
- }
1465
-
1466
- // Don't retrieve activity comments marked as spam.
1467
- if ( 'ham_only' == $spam ) {
1468
- $spam_sql = 'AND a.is_spam = 0';
1469
- } elseif ( 'spam_only' == $spam ) {
1470
- $spam_sql = 'AND a.is_spam = 1';
1471
- } else {
1472
- $spam_sql = '';
1473
- }
1474
-
1475
- // Legacy query - not recommended.
1476
-
1477
- /**
1478
- * Filters if BuddyPress should use the legacy activity query.
1479
- *
1480
- * @since 2.0.0
1481
- *
1482
- * @param bool $value Whether or not to use the legacy query.
1483
- * @param BP_Activity_Activity $value Magic method referring to currently called method.
1484
- * @param array $func_args Array of the method's argument list.
1485
- */
1486
- if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, func_get_args() ) ) {
1487
-
1488
- /**
1489
- * Filters the MySQL prepared statement for the legacy activity query.
1490
- *
1491
- * @since 1.5.0
1492
- *
1493
- * @param string $value Prepared statement for the activity query.
1494
- * @param int $activity_id Activity ID to fetch comments for.
1495
- * @param int $left Left-most node boundary.
1496
- * @param int $right Right-most node boundary.
1497
- * @param string $spam_sql SQL Statement portion to differentiate between ham or spam.
1498
- */
1499
- $sql = apply_filters( 'bp_activity_comments_user_join_filter', $wpdb->prepare( "SELECT a.*, u.user_email, u.user_nicename, u.user_login, u.display_name{$fullname_select} FROM {$bp->activity->table_name} a, {$wpdb->users} u{$fullname_from} WHERE u.ID = a.user_id {$fullname_where} AND a.type = 'activity_comment' {$spam_sql} AND a.item_id = %d AND a.mptt_left > %d AND a.mptt_left < %d ORDER BY a.date_recorded ASC", $top_level_parent_id, $left, $right ), $activity_id, $left, $right, $spam_sql );
1500
-
1501
- $descendants = $wpdb->get_results( $sql );
1502
-
1503
- // We use the mptt BETWEEN clause to limit returned
1504
- // descendants to the correct part of the tree.
1505
- } else {
1506
- $sql = $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} a WHERE a.type = 'activity_comment' {$spam_sql} AND a.item_id = %d and a.mptt_left > %d AND a.mptt_left < %d ORDER BY a.date_recorded ASC", $top_level_parent_id, $left, $right );
1507
-
1508
- $descendant_ids = $wpdb->get_col( $sql );
1509
- $descendants = self::get_activity_data( $descendant_ids );
1510
- $descendants = self::append_user_fullnames( $descendants );
1511
- }
1512
-
1513
- $ref = array();
1514
-
1515
- // Loop descendants and build an assoc array.
1516
- foreach ( (array) $descendants as $d ) {
1517
- $d->children = array();
1518
-
1519
- // If we have a reference on the parent.
1520
- if ( isset( $ref[ $d->secondary_item_id ] ) ) {
1521
- $ref[ $d->secondary_item_id ]->children[ $d->id ] = $d;
1522
- $ref[ $d->id ] =& $ref[ $d->secondary_item_id ]->children[ $d->id ];
1523
-
1524
- // If we don't have a reference on the parent, put in the root level.
1525
- } else {
1526
- $comments[ $d->id ] = $d;
1527
- $ref[ $d->id ] =& $comments[ $d->id ];
1528
- }
1529
- }
1530
-
1531
- // Calculate depth for each item.
1532
- foreach ( $ref as &$r ) {
1533
- $depth = 1;
1534
- $parent_id = $r->secondary_item_id;
1535
-
1536
- while ( $parent_id !== $r->item_id ) {
1537
- $depth++;
1538
-
1539
- // When display_comments=stream, the parent comment may not be part of the
1540
- // returned results, so we manually fetch it.
1541
- if ( empty( $ref[ $parent_id ] ) ) {
1542
- $direct_parent = new BP_Activity_Activity( $parent_id );
1543
- if ( isset( $direct_parent->secondary_item_id ) ) {
1544
- // If the direct parent is not an activity update, that means we've reached
1545
- // the parent activity item (eg. new_blog_post).
1546
- if ( 'activity_update' !== $direct_parent->type ) {
1547
- $parent_id = $r->item_id;
1548
-
1549
- } else {
1550
- $parent_id = $direct_parent->secondary_item_id;
1551
- }
1552
-
1553
- } else {
1554
- // Something went wrong. Short-circuit the depth calculation.
1555
- $parent_id = $r->item_id;
1556
- }
1557
- } else {
1558
- $parent_id = $ref[ $parent_id ]->secondary_item_id;
1559
- }
1560
- }
1561
- $r->depth = $depth;
1562
- }
1563
-
1564
- // If we cache a value of false, it'll count as a cache
1565
- // miss the next time the activity comments are fetched.
1566
- // Storing the string 'none' is a hack workaround to
1567
- // avoid unnecessary queries.
1568
- if ( false === $comments ) {
1569
- $cache_value = 'none';
1570
- } else {
1571
- $cache_value = $comments;
1572
- }
1573
-
1574
- wp_cache_set( $activity_id, $cache_value, 'bp_activity_comments' );
1575
- }
1576
-
1577
- return $comments;
1578
- }
1579
-
1580
- /**
1581
- * Rebuild nested comment tree under an activity or activity comment.
1582
- *
1583
- * @since 1.2.0
1584
- *
1585
- * @global wpdb $wpdb WordPress database object.
1586
- *
1587
- * @param int $parent_id ID of an activity or activity comment.
1588
- * @param int $left Node boundary start for activity or activity comment.
1589
- * @return int Right Node boundary of activity or activity comment.
1590
- */
1591
- public static function rebuild_activity_comment_tree( $parent_id, $left = 1 ) {
1592
- global $wpdb;
1593
-
1594
- $bp = buddypress();
1595
-
1596
- // The right value of this node is the left value + 1.
1597
- $right = intval( $left + 1 );
1598
-
1599
- // Get all descendants of this node.
1600
- $comments = BP_Activity_Activity::get_child_comments( $parent_id );
1601
- $descendants = wp_list_pluck( $comments, 'id' );
1602
-
1603
- // Loop the descendants and recalculate the left and right values.
1604
- foreach ( (array) $descendants as $descendant_id ) {
1605
- $right = BP_Activity_Activity::rebuild_activity_comment_tree( $descendant_id, $right );
1606
- }
1607
-
1608
- // We've got the left value, and now that we've processed the children
1609
- // of this node we also know the right value.
1610
- if ( 1 === $left ) {
1611
- $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET mptt_left = %d, mptt_right = %d WHERE id = %d", $left, $right, $parent_id ) );
1612
- } else {
1613
- $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET mptt_left = %d, mptt_right = %d WHERE type = 'activity_comment' AND id = %d", $left, $right, $parent_id ) );
1614
- }
1615
-
1616
- // Return the right value of this node + 1.
1617
- return intval( $right + 1 );
1618
- }
1619
-
1620
- /**
1621
- * Get child comments of an activity or activity comment.
1622
- *
1623
- * @since 1.2.0
1624
- *
1625
- * @global wpdb $wpdb WordPress database object.
1626
- *
1627
- * @param int $parent_id ID of an activity or activity comment.
1628
- * @return object Numerically indexed array of child comments.
1629
- */
1630
- public static function get_child_comments( $parent_id ) {
1631
- global $wpdb;
1632
-
1633
- $bp = buddypress();
1634
-
1635
- return $wpdb->get_results( $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} WHERE type = 'activity_comment' AND secondary_item_id = %d", $parent_id ) );
1636
- }
1637
-
1638
- /**
1639
- * Get a list of components that have recorded activity associated with them.
1640
- *
1641
- * @since 1.2.0
1642
- *
1643
- * @param bool $skip_last_activity If true, components will not be
1644
- * included if the only activity type associated with them is
1645
- * 'last_activity'. (Since 2.0.0, 'last_activity' is stored in
1646
- * the activity table, but these items are not full-fledged
1647
- * activity items.) Default: true.
1648
- * @return array List of component names.
1649
- */
1650
- public static function get_recorded_components( $skip_last_activity = true ) {
1651
- global $wpdb;
1652
-
1653
- $bp = buddypress();
1654
-
1655
- if ( true === $skip_last_activity ) {
1656
- $components = $wpdb->get_col( "SELECT DISTINCT component FROM {$bp->activity->table_name} WHERE action != '' AND action != 'last_activity' ORDER BY component ASC" );
1657
- } else {
1658
- $components = $wpdb->get_col( "SELECT DISTINCT component FROM {$bp->activity->table_name} ORDER BY component ASC" );
1659
- }
1660
-
1661
- return $components;
1662
- }
1663
-
1664
- /**
1665
- * Get sitewide activity items for use in an RSS feed.
1666
- *
1667
- * @since 1.0.0
1668
- *
1669
- * @param int $limit Optional. Number of items to fetch. Default: 35.
1670
- * @return array $activity_feed List of activity items, with RSS data added.
1671
- */
1672
- public static function get_sitewide_items_for_feed( $limit = 35 ) {
1673
- $activities = bp_activity_get_sitewide( array( 'max' => $limit ) );
1674
- $activity_feed = array();
1675
-
1676
- for ( $i = 0, $count = count( $activities ); $i < $count; ++$i ) {
1677
- $title = explode( '<span', $activities[$i]['content'] );
1678
- $activity_feed[$i]['title'] = trim( strip_tags( $title[0] ) );
1679
- $activity_feed[$i]['link'] = $activities[$i]['primary_link'];
1680
- $activity_feed[$i]['description'] = @sprintf( $activities[$i]['content'], '' );
1681
- $activity_feed[$i]['pubdate'] = $activities[$i]['date_recorded'];
1682
- }
1683
-
1684
- return $activity_feed;
1685
- }
1686
-
1687
- /**
1688
- * Create SQL IN clause for filter queries.
1689
- *
1690
- * @since 1.5.0
1691
- *
1692
- * @see BP_Activity_Activity::get_filter_sql()
1693
- *
1694
- * @param string $field The database field.
1695
- * @param array|bool $items The values for the IN clause, or false when none are found.
1696
- * @return string|bool
1697
- */
1698
- public static function get_in_operator_sql( $field, $items ) {
1699
- global $wpdb;
1700
-
1701
- // Split items at the comma.
1702
- if ( ! is_array( $items ) ) {
1703
- $items = explode( ',', $items );
1704
- }
1705
-
1706
- // Array of prepared integers or quoted strings.
1707
- $items_prepared = array();
1708
-
1709
- // Clean up and format each item.
1710
- foreach ( $items as $item ) {
1711
- // Clean up the string.
1712
- $item = trim( $item );
1713
- // Pass everything through prepare for security and to safely quote strings.
1714
- $items_prepared[] = ( is_numeric( $item ) ) ? $wpdb->prepare( '%d', $item ) : $wpdb->prepare( '%s', $item );
1715
- }
1716
-
1717
- // Build IN operator sql syntax.
1718
- if ( count( $items_prepared ) )
1719
- return sprintf( '%s IN ( %s )', trim( $field ), implode( ',', $items_prepared ) );
1720
- else
1721
- return false;
1722
- }
1723
-
1724
- /**
1725
- * Create filter SQL clauses.
1726
- *
1727
- * @since 1.5.0
1728
- *
1729
- * @param array $filter_array {
1730
- * Fields and values to filter by.
1731
- *
1732
- * @type array|string|int $user_id User ID(s).
1733
- * @type array|string $object Corresponds to the 'component'
1734
- * column in the database.
1735
- * @type array|string $action Corresponds to the 'type' column
1736
- * in the database.
1737
- * @type array|string|int $primary_id Corresponds to the 'item_id'
1738
- * column in the database.
1739
- * @type array|string|int $secondary_id Corresponds to the
1740
- * 'secondary_item_id' column in the database.
1741
- * @type int $offset Return only those items with an ID greater
1742
- * than the offset value.
1743
- * @type string $since Return only those items that have a
1744
- * date_recorded value greater than a
1745
- * given MySQL-formatted date.
1746
- * }
1747
- * @return string The filter clause, for use in a SQL query.
1748
- */
1749
- public static function get_filter_sql( $filter_array ) {
1750
-
1751
- $filter_sql = array();
1752
-
1753
- if ( !empty( $filter_array['user_id'] ) ) {
1754
- $user_sql = BP_Activity_Activity::get_in_operator_sql( 'a.user_id', $filter_array['user_id'] );
1755
- if ( !empty( $user_sql ) )
1756
- $filter_sql[] = $user_sql;
1757
- }
1758
-
1759
- if ( !empty( $filter_array['object'] ) ) {
1760
- $object_sql = BP_Activity_Activity::get_in_operator_sql( 'a.component', $filter_array['object'] );
1761
- if ( !empty( $object_sql ) )
1762
- $filter_sql[] = $object_sql;
1763
- }
1764
-
1765
- if ( !empty( $filter_array['action'] ) ) {
1766
- $action_sql = BP_Activity_Activity::get_in_operator_sql( 'a.type', $filter_array['action'] );
1767
- if ( ! empty( $action_sql ) )
1768
- $filter_sql[] = $action_sql;
1769
- }
1770
-
1771
- if ( !empty( $filter_array['primary_id'] ) ) {
1772
- $pid_sql = BP_Activity_Activity::get_in_operator_sql( 'a.item_id', $filter_array['primary_id'] );
1773
- if ( !empty( $pid_sql ) )
1774
- $filter_sql[] = $pid_sql;
1775
- }
1776
-
1777
- if ( !empty( $filter_array['secondary_id'] ) ) {
1778
- $sid_sql = BP_Activity_Activity::get_in_operator_sql( 'a.secondary_item_id', $filter_array['secondary_id'] );
1779
- if ( !empty( $sid_sql ) )
1780
- $filter_sql[] = $sid_sql;
1781
- }
1782
-
1783
- if ( ! empty( $filter_array['offset'] ) ) {
1784
- $sid_sql = absint( $filter_array['offset'] );
1785
- $filter_sql[] = "a.id >= {$sid_sql}";
1786
- }
1787
-
1788
- if ( ! empty( $filter_array['since'] ) ) {
1789
- // Validate that this is a proper Y-m-d H:i:s date.
1790
- // Trick: parse to UNIX date then translate back.
1791
- $translated_date = date( 'Y-m-d H:i:s', strtotime( $filter_array['since'] ) );
1792
- if ( $translated_date === $filter_array['since'] ) {
1793
- $filter_sql[] = "a.date_recorded > '{$translated_date}'";
1794
- }
1795
- }
1796
-
1797
- if ( empty( $filter_sql ) )
1798
- return false;
1799
-
1800
- return join( ' AND ', $filter_sql );
1801
- }
1802
-
1803
- /**
1804
- * Get the date/time of last recorded activity.
1805
- *
1806
- * @since 1.2.0
1807
- *
1808
- * @return string ISO timestamp.
1809
- */
1810
- public static function get_last_updated() {
1811
- global $wpdb;
1812
-
1813
- $bp = buddypress();
1814
-
1815
- return $wpdb->get_var( "SELECT date_recorded FROM {$bp->activity->table_name} ORDER BY date_recorded DESC LIMIT 1" );
1816
- }
1817
-
1818
- /**
1819
- * Get favorite count for a given user.
1820
- *
1821
- * @since 1.2.0
1822
- *
1823
- * @param int $user_id The ID of the user whose favorites you're counting.
1824
- * @return int $value A count of the user's favorites.
1825
- */
1826
- public static function total_favorite_count( $user_id ) {
1827
-
1828
- // Get activities from user meta.
1829
- $favorite_activity_entries = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
1830
- if ( ! empty( $favorite_activity_entries ) ) {
1831
- return count( maybe_unserialize( $favorite_activity_entries ) );
1832
- }
1833
-
1834
- // No favorites.
1835
- return 0;
1836
- }
1837
-
1838
- /**
1839
- * Check whether an activity item exists with a given string content.
1840
- *
1841
- * @since 1.1.0
1842
- *
1843
- * @param string $content The content to filter by.
1844
- * @return int|bool The ID of the first matching item if found, otherwise false.
1845
- */
1846
- public static function check_exists_by_content( $content ) {
1847
- global $wpdb;
1848
-
1849
- $bp = buddypress();
1850
-
1851
- $result = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} WHERE content = %s", $content ) );
1852
-
1853
- return is_numeric( $result ) ? (int) $result : false;
1854
- }
1855
-
1856
- /**
1857
- * Hide all activity for a given user.
1858
- *
1859
- * @since 1.2.0
1860
- *
1861
- * @param int $user_id The ID of the user whose activity you want to mark hidden.
1862
- * @return mixed
1863
- */
1864
- public static function hide_all_for_user( $user_id ) {
1865
- global $wpdb;
1866
-
1867
- $bp = buddypress();
1868
-
1869
- return $wpdb->get_var( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET hide_sitewide = 1 WHERE user_id = %d", $user_id ) );
1870
- }
1871
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-component.php DELETED
@@ -1,384 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Streams Loader.
4
- *
5
- * An activity stream component, for users, groups, and site tracking.
6
- *
7
- * @package BuddyPress
8
- * @subpackage ActivityCore
9
- * @since 1.5.0
10
- */
11
-
12
- // Exit if accessed directly.
13
- defined( 'ABSPATH' ) || exit;
14
-
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
- 'features' => array( 'embeds' )
36
- )
37
- );
38
- }
39
-
40
- /**
41
- * Include component files.
42
- *
43
- * @since 1.5.0
44
- *
45
- * @see BP_Component::includes() for a description of arguments.
46
- *
47
- * @param array $includes See BP_Component::includes() for a description.
48
- */
49
- public function includes( $includes = array() ) {
50
-
51
- // Files to include.
52
- $includes = array(
53
- 'cssjs',
54
- 'actions',
55
- 'screens',
56
- 'filters',
57
- 'adminbar',
58
- 'template',
59
- 'functions',
60
- 'cache'
61
- );
62
-
63
- // Notifications support.
64
- if ( bp_is_active( 'notifications' ) ) {
65
- $includes[] = 'notifications';
66
- }
67
-
68
- // Load Akismet support if Akismet is configured.
69
- $akismet_key = bp_get_option( 'wordpress_api_key' );
70
-
71
- /** This filter is documented in bp-activity/bp-activity-akismet.php */
72
- if ( defined( 'AKISMET_VERSION' ) && class_exists( 'Akismet' ) && ( ! empty( $akismet_key ) || defined( 'WPCOM_API_KEY' ) ) && apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) ) {
73
- $includes[] = 'akismet';
74
- }
75
-
76
- // Embeds - only applicable for WP 4.5+
77
- if ( version_compare( $GLOBALS['wp_version'], '4.5', '>=' ) && bp_is_active( $this->id, 'embeds' ) ) {
78
- $includes[] = 'embeds';
79
- }
80
-
81
- if ( is_admin() ) {
82
- $includes[] = 'admin';
83
- }
84
-
85
- parent::includes( $includes );
86
- }
87
-
88
- /**
89
- * Set up component global variables.
90
- *
91
- * The BP_ACTIVITY_SLUG constant is deprecated, and only used here for
92
- * backwards compatibility.
93
- *
94
- * @since 1.5.0
95
- *
96
- * @see BP_Component::setup_globals() for a description of arguments.
97
- *
98
- * @param array $args See BP_Component::setup_globals() for a description.
99
- */
100
- public function setup_globals( $args = array() ) {
101
- $bp = buddypress();
102
-
103
- // Define a slug, if necessary.
104
- if ( ! defined( 'BP_ACTIVITY_SLUG' ) ) {
105
- define( 'BP_ACTIVITY_SLUG', $this->id );
106
- }
107
-
108
- // Global tables for activity component.
109
- $global_tables = array(
110
- 'table_name' => $bp->table_prefix . 'bp_activity',
111
- 'table_name_meta' => $bp->table_prefix . 'bp_activity_meta',
112
- );
113
-
114
- // Metadata tables for groups component.
115
- $meta_tables = array(
116
- 'activity' => $bp->table_prefix . 'bp_activity_meta',
117
- );
118
-
119
- // Fetch the default directory title.
120
- $default_directory_titles = bp_core_get_directory_page_default_titles();
121
- $default_directory_title = $default_directory_titles[$this->id];
122
-
123
- // All globals for activity component.
124
- // Note that global_tables is included in this array.
125
- $args = array(
126
- 'slug' => BP_ACTIVITY_SLUG,
127
- 'root_slug' => isset( $bp->pages->activity->slug ) ? $bp->pages->activity->slug : BP_ACTIVITY_SLUG,
128
- 'has_directory' => true,
129
- 'directory_title' => isset( $bp->pages->activity->title ) ? $bp->pages->activity->title : $default_directory_title,
130
- 'notification_callback' => 'bp_activity_format_notifications',
131
- 'search_string' => __( 'Search Activity...', 'buddypress' ),
132
- 'global_tables' => $global_tables,
133
- 'meta_tables' => $meta_tables,
134
- );
135
-
136
- parent::setup_globals( $args );
137
- }
138
-
139
- /**
140
- * Set up component navigation.
141
- *
142
- * @since 1.5.0
143
- *
144
- * @see BP_Component::setup_nav() for a description of arguments.
145
- *
146
- * @param array $main_nav Optional. See BP_Component::setup_nav() for description.
147
- * @param array $sub_nav Optional. See BP_Component::setup_nav() for description.
148
- */
149
- public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
150
-
151
- // Stop if there is no user displayed or logged in.
152
- if ( ! is_user_logged_in() && ! bp_displayed_user_id() ) {
153
- return;
154
- }
155
-
156
- // Determine user to use.
157
- if ( bp_displayed_user_domain() ) {
158
- $user_domain = bp_displayed_user_domain();
159
- } elseif ( bp_loggedin_user_domain() ) {
160
- $user_domain = bp_loggedin_user_domain();
161
- } else {
162
- return;
163
- }
164
-
165
- $slug = bp_get_activity_slug();
166
- $activity_link = trailingslashit( $user_domain . $slug );
167
-
168
- // Add 'Activity' to the main navigation.
169
- $main_nav = array(
170
- 'name' => _x( 'Activity', 'Profile activity screen nav', 'buddypress' ),
171
- 'slug' => $slug,
172
- 'position' => 10,
173
- 'screen_function' => 'bp_activity_screen_my_activity',
174
- 'default_subnav_slug' => 'just-me',
175
- 'item_css_id' => $this->id
176
- );
177
-
178
- // Add the subnav items to the activity nav item if we are using a theme that supports this.
179
- $sub_nav[] = array(
180
- 'name' => _x( 'Personal', 'Profile activity screen sub nav', 'buddypress' ),
181
- 'slug' => 'just-me',
182
- 'parent_url' => $activity_link,
183
- 'parent_slug' => $slug,
184
- 'screen_function' => 'bp_activity_screen_my_activity',
185
- 'position' => 10
186
- );
187
-
188
- // Check @mentions.
189
- if ( bp_activity_do_mentions() ) {
190
- $sub_nav[] = array(
191
- 'name' => _x( 'Mentions', 'Profile activity screen sub nav', 'buddypress' ),
192
- 'slug' => 'mentions',
193
- 'parent_url' => $activity_link,
194
- 'parent_slug' => $slug,
195
- 'screen_function' => 'bp_activity_screen_mentions',
196
- 'position' => 20,
197
- 'item_css_id' => 'activity-mentions'
198
- );
199
- }
200
-
201
- // Favorite activity items.
202
- if ( bp_activity_can_favorite() ) {
203
- $sub_nav[] = array(
204
- 'name' => _x( 'Favorites', 'Profile activity screen sub nav', 'buddypress' ),
205
- 'slug' => 'favorites',
206
- 'parent_url' => $activity_link,
207
- 'parent_slug' => $slug,
208
- 'screen_function' => 'bp_activity_screen_favorites',
209
- 'position' => 30,
210
- 'item_css_id' => 'activity-favs'
211
- );
212
- }
213
-
214
- // Additional menu if friends is active.
215
- if ( bp_is_active( 'friends' ) ) {
216
- $sub_nav[] = array(
217
- 'name' => _x( 'Friends', 'Profile activity screen sub nav', 'buddypress' ),
218
- 'slug' => bp_get_friends_slug(),
219
- 'parent_url' => $activity_link,
220
- 'parent_slug' => $slug,
221
- 'screen_function' => 'bp_activity_screen_friends',
222
- 'position' => 40,
223
- 'item_css_id' => 'activity-friends'
224
- ) ;
225
- }
226
-
227
- // Additional menu if groups is active.
228
- if ( bp_is_active( 'groups' ) ) {
229
- $sub_nav[] = array(
230
- 'name' => _x( 'Groups', 'Profile activity screen sub nav', 'buddypress' ),
231
- 'slug' => bp_get_groups_slug(),
232
- 'parent_url' => $activity_link,
233
- 'parent_slug' => $slug,
234
- 'screen_function' => 'bp_activity_screen_groups',
235
- 'position' => 50,
236
- 'item_css_id' => 'activity-groups'
237
- );
238
- }
239
-
240
- parent::setup_nav( $main_nav, $sub_nav );
241
- }
242
-
243
- /**
244
- * Set up the component entries in the WordPress Admin Bar.
245
- *
246
- * @since 1.5.0
247
- *
248
- * @see BP_Component::setup_nav() for a description of the $wp_admin_nav
249
- * parameter array.
250
- *
251
- * @param array $wp_admin_nav See BP_Component::setup_admin_bar() for a
252
- * description.
253
- */
254
- public function setup_admin_bar( $wp_admin_nav = array() ) {
255
-
256
- // Menus for logged in user.
257
- if ( is_user_logged_in() ) {
258
-
259
- // Setup the logged in user variables.
260
- $activity_link = trailingslashit( bp_loggedin_user_domain() . bp_get_activity_slug() );
261
-
262
- // Unread message count.
263
- if ( bp_activity_do_mentions() ) {
264
- $count = bp_get_total_mention_count_for_user( bp_loggedin_user_id() );
265
- if ( !empty( $count ) ) {
266
- $title = sprintf(
267
- /* translators: %s: Unread mention count for the current user */
268
- _x( 'Mentions %s', 'Toolbar Mention logged in user', 'buddypress' ),
269
- '<span class="count">' . bp_core_number_format( $count ) . '</span>'
270
- );
271
- } else {
272
- $title = _x( 'Mentions', 'Toolbar Mention logged in user', 'buddypress' );
273
- }
274
- }
275
-
276
- // Add the "Activity" sub menu.
277
- $wp_admin_nav[] = array(
278
- 'parent' => buddypress()->my_account_menu_id,
279
- 'id' => 'my-account-' . $this->id,
280
- 'title' => _x( 'Activity', 'My Account Activity sub nav', 'buddypress' ),
281
- 'href' => $activity_link
282
- );
283
-
284
- // Personal.
285
- $wp_admin_nav[] = array(
286
- 'parent' => 'my-account-' . $this->id,
287
- 'id' => 'my-account-' . $this->id . '-personal',
288
- 'title' => _x( 'Personal', 'My Account Activity sub nav', 'buddypress' ),
289
- 'href' => $activity_link,
290
- 'position' => 10
291
- );
292
-
293
- // Mentions.
294
- if ( bp_activity_do_mentions() ) {
295
- $wp_admin_nav[] = array(
296
- 'parent' => 'my-account-' . $this->id,
297
- 'id' => 'my-account-' . $this->id . '-mentions',
298
- 'title' => $title,
299
- 'href' => trailingslashit( $activity_link . 'mentions' ),
300
- 'position' => 20
301
- );
302
- }
303
-
304
- // Favorite activity items.
305
- if ( bp_activity_can_favorite() ) {
306
- $wp_admin_nav[] = array(
307
- 'parent' => 'my-account-' . $this->id,
308
- 'id' => 'my-account-' . $this->id . '-favorites',
309
- 'title' => _x( 'Favorites', 'My Account Activity sub nav', 'buddypress' ),
310
- 'href' => trailingslashit( $activity_link . 'favorites' ),
311
- 'position' => 30
312
- );
313
- }
314
-
315
- // Friends?
316
- if ( bp_is_active( 'friends' ) ) {
317
- $wp_admin_nav[] = array(
318
- 'parent' => 'my-account-' . $this->id,
319
- 'id' => 'my-account-' . $this->id . '-friends',
320
- 'title' => _x( 'Friends', 'My Account Activity sub nav', 'buddypress' ),
321
- 'href' => trailingslashit( $activity_link . bp_get_friends_slug() ),
322
- 'position' => 40
323
- );
324
- }
325
-
326
- // Groups?
327
- if ( bp_is_active( 'groups' ) ) {
328
- $wp_admin_nav[] = array(
329
- 'parent' => 'my-account-' . $this->id,
330
- 'id' => 'my-account-' . $this->id . '-groups',
331
- 'title' => _x( 'Groups', 'My Account Activity sub nav', 'buddypress' ),
332
- 'href' => trailingslashit( $activity_link . bp_get_groups_slug() ),
333
- 'position' => 50
334
- );
335
- }
336
- }
337
-
338
- parent::setup_admin_bar( $wp_admin_nav );
339
- }
340
-
341
- /**
342
- * Set up the title for pages and <title>.
343
- *
344
- * @since 1.5.0
345
- *
346
- */
347
- public function setup_title() {
348
-
349
- // Adjust title based on view.
350
- if ( bp_is_activity_component() ) {
351
- $bp = buddypress();
352
-
353
- if ( bp_is_my_profile() ) {
354
- $bp->bp_options_title = _x( 'My Activity', 'Page and <title>', 'buddypress' );
355
- } else {
356
- $bp->bp_options_avatar = bp_core_fetch_avatar( array(
357
- 'item_id' => bp_displayed_user_id(),
358
- 'type' => 'thumb',
359
- 'alt' => sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_get_displayed_user_fullname() )
360
- ) );
361
- $bp->bp_options_title = bp_get_displayed_user_fullname();
362
- }
363
- }
364
-
365
- parent::setup_title();
366
- }
367
-
368
- /**
369
- * Setup cache groups.
370
- *
371
- * @since 2.2.0
372
- */
373
- public function setup_cache_groups() {
374
-
375
- // Global groups.
376
- wp_cache_add_global_groups( array(
377
- 'bp_activity',
378
- 'bp_activity_comments',
379
- 'activity_meta'
380
- ) );
381
-
382
- parent::setup_cache_groups();
383
- }
384
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-feed.php DELETED
@@ -1,468 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Classes.
4
- *
5
- * @package BuddyPress
6
- * @subpackage ActivityFeeds
7
- * @since 1.8.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- /**
14
- * Create a RSS feed using the activity component.
15
- *
16
- * You should only construct a new feed when you've validated that you're on
17
- * the appropriate screen.
18
- *
19
- * @since 1.8.0
20
- *
21
- * See {@link bp_activity_action_sitewide_feed()} as an example.
22
- *
23
- * @param array $args {
24
- * @type string $id Required. Internal id for the feed; should be alphanumeric only.
25
- * @type string $title Optional. RSS feed title.
26
- * @type string $link Optional. Relevant link for the RSS feed.
27
- * @type string $description Optional. RSS feed description.
28
- * @type string $ttl Optional. Time-to-live. (see inline doc in constructor)
29
- * @type string $update_period Optional. Part of the syndication module.
30
- * (see inline doc in constructor for more info)
31
- * @type string $update_frequency Optional. Part of the syndication module.
32
- * (see inline doc in constructor for more info)
33
- * @type string $max Optional. Number of feed items to display.
34
- * @type array $activity_args Optional. Arguments passed to {@link bp_has_activities()}
35
- * }
36
- */
37
- class BP_Activity_Feed {
38
-
39
- /**
40
- * Holds our custom class properties.
41
- *
42
- * These variables are stored in a protected array that is magically
43
- * updated using PHP 5.2+ methods.
44
- *
45
- * @see BP_Feed::__construct() This is where $data is added.
46
- *
47
- * @since 1.8.0
48
- * @var array
49
- */
50
- protected $data;
51
-
52
- /**
53
- * Magic method for checking the existence of a certain data variable.
54
- *
55
- * @since 1.8.0
56
- *
57
- * @param string $key Property to check.
58
- * @return bool Whether or not data variable exists.
59
- */
60
- public function __isset( $key ) { return isset( $this->data[$key] ); }
61
-
62
- /**
63
- * Magic method for getting a certain data variable.
64
- *
65
- * @since 1.8.0
66
- *
67
- * @param string $key Property to get.
68
- * @return mixed Data in variable if available or null.
69
- */
70
- public function __get( $key ) { return isset( $this->data[$key] ) ? $this->data[$key] : null; }
71
-
72
- /**
73
- * Magic method for setting a certain data variable.
74
- *
75
- * @since 2.4.0
76
- *
77
- * @param string $key The property to set.
78
- * @param mixed $value The value to set.
79
- */
80
- public function __set( $key, $value ) { $this->data[$key] = $value; }
81
-
82
- /**
83
- * Constructor.
84
- *
85
- * @since 1.8.0
86
- *
87
- * @param array $args Optional.
88
- */
89
- public function __construct( $args = array() ) {
90
-
91
- /**
92
- * Filters if BuddyPress should consider feeds enabled. If disabled, it will return early.
93
- *
94
- * @since 1.8.0
95
- *
96
- * @param bool true Default true aka feeds are enabled.
97
- */
98
- if ( false === (bool) apply_filters( 'bp_activity_enable_feeds', true ) ) {
99
- global $wp_query;
100
-
101
- // Set feed flag to false.
102
- $wp_query->is_feed = false;
103
-
104
- return false;
105
- }
106
-
107
- // Setup data.
108
- $this->data = wp_parse_args( $args, array(
109
- // Internal identifier for the RSS feed - should be alphanumeric only.
110
- 'id' => '',
111
-
112
- // RSS title - should be plain-text.
113
- 'title' => '',
114
-
115
- // Relevant link for the RSS feed.
116
- 'link' => '',
117
-
118
- // RSS description - should be plain-text.
119
- 'description' => '',
120
-
121
- // Time-to-live - number of minutes to cache the data before an aggregator
122
- // requests it again. This is only acknowledged if the RSS client supports it
123
- //
124
- // See: http://www.rssboard.org/rss-profile#element-channel-ttl.
125
- // See: http://www.kbcafe.com/rss/rssfeedstate.html#ttl.
126
- 'ttl' => '30',
127
-
128
- // Syndication module - similar to ttl, but not really supported by RSS
129
- // clients
130
- //
131
- // See: http://web.resource.org/rss/1.0/modules/syndication/#description.
132
- // See: http://www.kbcafe.com/rss/rssfeedstate.html#syndicationmodule.
133
- 'update_period' => 'hourly',
134
- 'update_frequency' => 2,
135
-
136
- // Number of items to display.
137
- 'max' => 50,
138
-
139
- // Activity arguments passed to bp_has_activities().
140
- 'activity_args' => array()
141
- ) );
142
-
143
- /**
144
- * Fires before the feed is setup so plugins can modify.
145
- *
146
- * @since 1.8.0
147
- *
148
- * @param BP_Activity_Feed $this Current instance of activity feed. Passed by reference.
149
- */
150
- do_action_ref_array( 'bp_activity_feed_prefetch', array( &$this ) );
151
-
152
- // Setup class properties.
153
- $this->setup_properties();
154
-
155
- // Check if id is valid.
156
- if ( empty( $this->id ) ) {
157
- _doing_it_wrong( 'BP_Activity_Feed', __( "RSS feed 'id' must be defined", 'buddypress' ), 'BP 1.8' );
158
- return false;
159
- }
160
-
161
- /**
162
- * Fires after the feed is setup so plugins can modify.
163
- *
164
- * @since 1.8.0
165
- *
166
- * @param BP_Activity_Feed $this Current instance of activity feed. Passed by reference.
167
- */
168
- do_action_ref_array( 'bp_activity_feed_postfetch', array( &$this ) );
169
-
170
- // Setup feed hooks.
171
- $this->setup_hooks();
172
-
173
- // Output the feed.
174
- $this->output();
175
-
176
- // Kill the rest of the output.
177
- die();
178
- }
179
-
180
- /** SETUP ****************************************************************/
181
-
182
- /**
183
- * Setup and validate the class properties.
184
- *
185
- * @since 1.8.0
186
- */
187
- protected function setup_properties() {
188
- $this->id = sanitize_title( $this->id );
189
- $this->title = strip_tags( $this->title );
190
- $this->link = esc_url_raw( $this->link );
191
- $this->description = strip_tags( $this->description );
192
- $this->ttl = (int) $this->ttl;
193
- $this->update_period = strip_tags( $this->update_period );
194
- $this->update_frequency = (int) $this->update_frequency;
195
-
196
- $this->activity_args = wp_parse_args( $this->activity_args, array(
197
- 'max' => $this->max,
198
- 'per_page' => $this->max,
199
- 'display_comments' => 'stream'
200
- ) );
201
-
202
- }
203
-
204
- /**
205
- * Setup some hooks that are used in the feed.
206
- *
207
- * Currently, these hooks are used to maintain backwards compatibility with
208
- * the RSS feeds previous to BP 1.8.
209
- *
210
- * @since 1.8.0
211
- */
212
- protected function setup_hooks() {
213
- add_action( 'bp_activity_feed_rss_attributes', array( $this, 'backpat_rss_attributes' ) );
214
- add_action( 'bp_activity_feed_channel_elements', array( $this, 'backpat_channel_elements' ) );
215
- add_action( 'bp_activity_feed_item_elements', array( $this, 'backpat_item_elements' ) );
216
- }
217
-
218
- /** BACKPAT HOOKS ********************************************************/
219
-
220
- /**
221
- * Fire a hook to ensure backward compatibility for RSS attributes.
222
- *
223
- * @since 1.8.0
224
- */
225
- public function backpat_rss_attributes() {
226
-
227
- /**
228
- * Fires inside backpat_rss_attributes method for backwards compatibility related to RSS attributes.
229
- *
230
- * This hook was originally separated out for individual components but has since been abstracted into the BP_Activity_Feed class.
231
- *
232
- * @since 1.0.0
233
- */
234
- do_action( 'bp_activity_' . $this->id . '_feed' );
235
- }
236
-
237
- /**
238
- * Fire a hook to ensure backward compatibility for channel elements.
239
- *
240
- * @since 1.8.0
241
- */
242
- public function backpat_channel_elements() {
243
-
244
- /**
245
- * Fires inside backpat_channel_elements method for backwards compatibility related to RSS channel elements.
246
- *
247
- * This hook was originally separated out for individual components but has since been abstracted into the BP_Activity_Feed class.
248
- *
249
- * @since 1.0.0
250
- */
251
- do_action( 'bp_activity_' . $this->id . '_feed_head' );
252
- }
253
-
254
- /**
255
- * Fire a hook to ensure backward compatibility for item elements.
256
- *
257
- * @since 1.8.0
258
- */
259
- public function backpat_item_elements() {
260
- switch ( $this->id ) {
261
-
262
- // Sitewide and friends feeds use the 'personal' hook.
263
- case 'sitewide' :
264
- case 'friends' :
265
- $id = 'personal';
266
-
267
- break;
268
-
269
- default :
270
- $id = $this->id;
271
-
272
- break;
273
- }
274
-
275
- /**
276
- * Fires inside backpat_item_elements method for backwards compatibility related to RSS item elements.
277
- *
278
- * This hook was originally separated out for individual components but has since been abstracted into the BP_Activity_Feed class.
279
- *
280
- * @since 1.0.0
281
- */
282
- do_action( 'bp_activity_' . $id . '_feed_item' );
283
- }
284
-
285
- /** HELPERS **************************************************************/
286
-
287
- /**
288
- * Output the feed's item content.
289
- *
290
- * @since 1.8.0
291
- */
292
- protected function feed_content() {
293
- bp_activity_content_body();
294
-
295
- switch ( $this->id ) {
296
-
297
- // Also output parent activity item if we're on a specific feed.
298
- case 'favorites' :
299
- case 'friends' :
300
- case 'mentions' :
301
- case 'personal' :
302
-
303
- if ( 'activity_comment' == bp_get_activity_action_name() ) :
304
- ?>
305
- <strong><?php _e( 'In reply to', 'buddypress' ) ?></strong> -
306
- <?php bp_activity_parent_content() ?>
307
- <?php
308
- endif;
309
-
310
- break;
311
- }
312
- }
313
-
314
- /**
315
- * Sets various HTTP headers related to Content-Type and browser caching.
316
- *
317
- * Most of this class method is derived from {@link WP::send_headers()}.
318
- *
319
- * @since 1.9.0
320
- */
321
- protected function http_headers() {
322
- // Set up some additional headers if not on a directory page
323
- // this is done b/c BP uses pseudo-pages.
324
- if ( ! bp_is_directory() ) {
325
- global $wp_query;
326
-
327
- $wp_query->is_404 = false;
328
- status_header( 200 );
329
- }
330
-
331
- // Set content-type.
332
- @header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
333
- send_nosniff_header();
334
-
335
- // Cache-related variables.
336
- $last_modified = mysql2date( 'D, d M Y H:i:s O', bp_activity_get_last_updated(), false );
337
- $modified_timestamp = strtotime( $last_modified );
338
- $etag = md5( $last_modified );
339
-
340
- // Set cache-related headers.
341
- @header( 'Last-Modified: ' . $last_modified );
342
- @header( 'Pragma: no-cache' );
343
- @header( 'ETag: ' . '"' . $etag . '"' );
344
-
345
- // First commit of BuddyPress! (Easter egg).
346
- @header( 'Expires: Tue, 25 Mar 2008 17:13:55 GMT');
347
-
348
- // Get ETag from supported user agents.
349
- if ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ) {
350
- $client_etag = wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] );
351
-
352
- // Remove quotes from ETag.
353
- $client_etag = trim( $client_etag, '"' );
354
-
355
- // Strip suffixes from ETag if they exist (eg. "-gzip").
356
- $etag_suffix_pos = strpos( $client_etag, '-' );
357
- if ( ! empty( $etag_suffix_pos ) ) {
358
- $client_etag = substr( $client_etag, 0, $etag_suffix_pos );
359
- }
360
-
361
- // No ETag found.
362
- } else {
363
- $client_etag = false;
364
- }
365
-
366
- // Get client last modified timestamp from supported user agents.
367
- $client_last_modified = empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ? '' : trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
368
- $client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;
369
-
370
- // Set 304 status if feed hasn't been updated since last fetch.
371
- if ( ( $client_last_modified && $client_etag ) ?
372
- ( ( $client_modified_timestamp >= $modified_timestamp ) && ( $client_etag == $etag ) ) :
373
- ( ( $client_modified_timestamp >= $modified_timestamp ) || ( $client_etag == $etag ) ) ) {
374
- $status = 304;
375
- } else {
376
- $status = false;
377
- }
378
-
379
- // If feed hasn't changed as reported by the user agent, set 304 status header.
380
- if ( ! empty( $status ) ) {
381
- status_header( $status );
382
-
383
- // Cached response, so stop now!
384
- if ( $status == 304 ) {
385
- exit();
386
- }
387
- }
388
- }
389
-
390
- /** OUTPUT ***************************************************************/
391
-
392
- /**
393
- * Output the RSS feed.
394
- *
395
- * @since 1.8.0
396
- */
397
- protected function output() {
398
- $this->http_headers();
399
- echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?'.'>';
400
- ?>
401
-
402
- <rss version="2.0"
403
- xmlns:content="http://purl.org/rss/1.0/modules/content/"
404
- xmlns:atom="http://www.w3.org/2005/Atom"
405
- xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
406
- xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
407
- <?php
408
-
409
- /**
410
- * Fires at the end of the opening RSS tag for feed output so plugins can add extra attributes.
411
- *
412
- * @since 1.8.0
413
- */
414
- do_action( 'bp_activity_feed_rss_attributes' ); ?>
415
- >
416
-
417
- <channel>
418
- <title><?php echo $this->title; ?></title>
419
- <link><?php echo $this->link; ?></link>
420
- <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
421
- <description><?php echo $this->description ?></description>
422
- <lastBuildDate><?php echo mysql2date( 'D, d M Y H:i:s O', bp_activity_get_last_updated(), false ); ?></lastBuildDate>
423
- <generator>https://buddypress.org/?v=<?php bp_version(); ?></generator>
424
- <language><?php bloginfo_rss( 'language' ); ?></language>
425
- <ttl><?php echo $this->ttl; ?></ttl>
426
- <sy:updatePeriod><?php echo $this->update_period; ?></sy:updatePeriod>
427
- <sy:updateFrequency><?php echo $this->update_frequency; ?></sy:updateFrequency>
428
- <?php
429
-
430
- /**
431
- * Fires at the end of channel elements list in RSS feed so plugins can add extra channel elements.
432
- *
433
- * @since 1.8.0
434
- */
435
- do_action( 'bp_activity_feed_channel_elements' ); ?>
436
-
437
- <?php if ( bp_has_activities( $this->activity_args ) ) : ?>
438
- <?php while ( bp_activities() ) : bp_the_activity(); ?>
439
- <item>
440
- <guid isPermaLink="false"><?php bp_activity_feed_item_guid(); ?></guid>
441
- <title><?php echo stripslashes( bp_get_activity_feed_item_title() ); ?></title>
442
- <link><?php bp_activity_thread_permalink() ?></link>
443
- <pubDate><?php echo mysql2date( 'D, d M Y H:i:s O', bp_get_activity_feed_item_date(), false ); ?></pubDate>
444
-
445
- <?php if ( bp_get_activity_feed_item_description() ) : ?>
446
- <content:encoded><![CDATA[<?php $this->feed_content(); ?>]]></content:encoded>
447
- <?php endif; ?>
448
-
449
- <?php if ( bp_activity_can_comment() ) : ?>
450
- <slash:comments><?php bp_activity_comment_count(); ?></slash:comments>
451
- <?php endif; ?>
452
-
453
- <?php
454
-
455
- /**
456
- * Fires at the end of the individual RSS Item list in RSS feed so plugins can add extra item elements.
457
- *
458
- * @since 1.8.0
459
- */
460
- do_action( 'bp_activity_feed_item_elements' ); ?>
461
- </item>
462
- <?php endwhile; ?>
463
-
464
- <?php endif; ?>
465
- </channel>
466
- </rss><?php
467
- }
468
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-list-table.php DELETED
@@ -1,858 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity component admin list table.
4
- *
5
- * Props to WordPress core for the Comments admin screen, and its contextual
6
- * help text, on which this implementation is heavily based.
7
- *
8
- * @package BuddyPress
9
- * @subpackage ActivityAdmin
10
- * @since 1.6.0
11
- */
12
-
13
- // Exit if accessed directly.
14
- defined( 'ABSPATH' ) || exit;
15
-
16
- /**
17
- * List table class for the Activity component admin page.
18
- *
19
- * @since 1.6.0
20
- */
21
- class BP_Activity_List_Table extends WP_List_Table {
22
-
23
- /**
24
- * What type of view is being displayed?
25
- *
26
- * E.g. "all", "pending", "approved", "spam"...
27
- *
28
- * @since 1.6.0
29
- * @var string $view
30
- */
31
- public $view = 'all';
32
-
33
- /**
34
- * How many activity items have been marked as spam.
35
- *
36
- * @since 1.6.0
37
- * @var int $spam_count
38
- */
39
- public $spam_count = 0;
40
-
41
- /**
42
- * Store activity-to-user-ID mappings for use in the In Response To column.
43
- *
44
- * @since 1.6.0
45
- * @var array $activity_user_id
46
- */
47
- protected $activity_user_id = array();
48
-
49
- /**
50
- * If users can comment on blog & forum activity items.
51
- *
52
- * @link https://buddypress.trac.wordpress.org/ticket/6277
53
- *
54
- * @since 2.2.2
55
- * @var bool $disable_blogforum_comments
56
- */
57
- public $disable_blogforum_comments = false;
58
-
59
- /**
60
- * Constructor.
61
- *
62
- * @since 1.6.0
63
- */
64
- public function __construct() {
65
-
66
- // See if activity commenting is enabled for blog / forum activity items.
67
- $this->disable_blogforum_comments = bp_disable_blogforum_comments();
68
-
69
- // Define singular and plural labels, as well as whether we support AJAX.
70
- parent::__construct( array(
71
- 'ajax' => false,
72
- 'plural' => 'activities',
73
- 'singular' => 'activity',
74
- 'screen' => get_current_screen(),
75
- ) );
76
- }
77
-
78
- /**
79
- * Handle filtering of data, sorting, pagination, and any other data manipulation prior to rendering.
80
- *
81
- * @since 1.6.0
82
- */
83
- function prepare_items() {
84
-
85
- // Option defaults.
86
- $filter = array();
87
- $filter_query = false;
88
- $include_id = false;
89
- $search_terms = false;
90
- $sort = 'DESC';
91
- $spam = 'ham_only';
92
-
93
- // Set current page.
94
- $page = $this->get_pagenum();
95
-
96
- // Set per page from the screen options.
97
- $per_page = $this->get_items_per_page( str_replace( '-', '_', "{$this->screen->id}_per_page" ) );
98
-
99
- // Check if we're on the "Spam" view.
100
- if ( !empty( $_REQUEST['activity_status'] ) && 'spam' == $_REQUEST['activity_status'] ) {
101
- $spam = 'spam_only';
102
- $this->view = 'spam';
103
- }
104
-
105
- // Sort order.
106
- if ( !empty( $_REQUEST['order'] ) && 'desc' != $_REQUEST['order'] )
107
- $sort = 'ASC';
108
-
109
- // Order by.
110
- /*if ( !empty( $_REQUEST['orderby'] ) ) {
111
- }*/
112
-
113
- // Filter.
114
- if ( ! empty( $_REQUEST['activity_type'] ) ) {
115
- $filter = array( 'action' => $_REQUEST['activity_type'] );
116
-
117
- /**
118
- * Filter here to override the filter with a filter query
119
- *
120
- * @since 2.5.0
121
- *
122
- * @param array $filter
123
- */
124
- $has_filter_query = apply_filters( 'bp_activity_list_table_filter_activity_type_items', $filter );
125
-
126
- if ( ! empty( $has_filter_query['filter_query'] ) ) {
127
- // Reset the filter
128
- $filter = array();
129
-
130
- // And use the filter query instead
131
- $filter_query = $has_filter_query['filter_query'];
132
- }
133
- }
134
-
135
- // Are we doing a search?
136
- if ( !empty( $_REQUEST['s'] ) )
137
- $search_terms = $_REQUEST['s'];
138
-
139
- // Check if user has clicked on a specific activity (if so, fetch only that, and any related, activity).
140
- if ( !empty( $_REQUEST['aid'] ) )
141
- $include_id = (int) $_REQUEST['aid'];
142
-
143
- // Get the spam total (ignoring any search query or filter).
144
- $spams = bp_activity_get( array(
145
- 'display_comments' => 'stream',
146
- 'show_hidden' => true,
147
- 'spam' => 'spam_only',
148
- 'count_total' => 'count_query',
149
- ) );
150
- $this->spam_count = $spams['total'];
151
- unset( $spams );
152
-
153
- // Get the activities from the database.
154
- $activities = bp_activity_get( array(
155
- 'display_comments' => 'stream',
156
- 'filter' => $filter,
157
- 'in' => $include_id,
158
- 'page' => $page,
159
- 'per_page' => $per_page,
160
- 'search_terms' => $search_terms,
161
- 'filter_query' => $filter_query,
162
- 'show_hidden' => true,
163
- // 'sort' => $sort,
164
- 'spam' => $spam,
165
- 'count_total' => 'count_query',
166
- ) );
167
-
168
- // If we're viewing a specific activity, flatten all activities into a single array.
169
- if ( $include_id ) {
170
- $activities['activities'] = BP_Activity_List_Table::flatten_activity_array( $activities['activities'] );
171
- $activities['total'] = count( $activities['activities'] );
172
-
173
- // Sort the array by the activity object's date_recorded value.
174
- usort( $activities['activities'], function( $a, $b ) { return $a->date_recorded > $b->date_recorded; } );
175
- }
176
-
177
- // The bp_activity_get function returns an array of objects; cast these to arrays for WP_List_Table.
178
- $new_activities = array();
179
- foreach ( $activities['activities'] as $activity_item ) {
180
- $new_activities[] = (array) $activity_item;
181
-
182
- // Build an array of activity-to-user ID mappings for better efficiency in the In Response To column.
183
- $this->activity_user_id[$activity_item->id] = $activity_item->user_id;
184
- }
185
-
186
- // Set raw data to display.
187
- $this->items = $new_activities;
188
-
189
- // Store information needed for handling table pagination.
190
- $this->set_pagination_args( array(
191
- 'per_page' => $per_page,
192
- 'total_items' => $activities['total'],
193
- 'total_pages' => ceil( $activities['total'] / $per_page )
194
- ) );
195
-
196
- // Don't truncate activity items; bp_activity_truncate_entry() needs to be used inside a BP_Activity_Template loop.
197
- remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
198
- }
199
-
200
- /**
201
- * Get an array of all the columns on the page.
202
- *
203
- * @since 1.6.0
204
- *
205
- * @return array Column headers.
206
- */
207
- function get_column_info() {
208
- $this->_column_headers = array(
209
- $this->get_columns(),
210
- array(),
211
- $this->get_sortable_columns(),
212
- $this->get_default_primary_column_name(),
213
- );
214
-
215
- return $this->_column_headers;
216
- }
217
-
218
- /**
219
- * Get name of default primary column
220
- *
221
- * @since 2.3.3
222
- *
223
- * @return string
224
- */
225
- protected function get_default_primary_column_name() {
226
- return 'author';
227
- }
228
-
229
- /**
230
- * Display a message on screen when no items are found (e.g. no search matches).
231
- *
232
- * @since 1.6.0
233
- */
234
- function no_items() {
235
- _e( 'No activities found.', 'buddypress' );
236
- }
237
-
238
- /**
239
- * Output the Activity data table.
240
- *
241
- * @since 1.6.0
242
- */
243
- function display() {
244
- $this->display_tablenav( 'top' ); ?>
245
-
246
- <h2 class="screen-reader-text"><?php
247
- /* translators: accessibility text */
248
- _e( 'Activities list', 'buddypress' );
249
- ?></h2>
250
-
251
- <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>" cellspacing="0">
252
- <thead>
253
- <tr>
254
- <?php $this->print_column_headers(); ?>
255
- </tr>
256
- </thead>
257
-
258
- <tbody id="the-comment-list">
259
- <?php $this->display_rows_or_placeholder(); ?>
260
- </tbody>
261
-
262
- <tfoot>
263
- <tr>
264
- <?php $this->print_column_headers( false ); ?>
265
- </tr>
266
- </tfoot>
267
- </table>
268
- <?php
269
-
270
- $this->display_tablenav( 'bottom' );
271
- }
272
-
273
- /**
274
- * Generate content for a single row of the table.
275
- *
276
- * @since 1.6.0
277
- *
278
- * @param object $item The current item.
279
- */
280
- function single_row( $item ) {
281
- static $even = false;
282
-
283
- if ( $even ) {
284
- $row_class = ' class="even"';
285
- } else {
286
- $row_class = ' class="alternate odd"';
287
- }
288
-
289
- if ( 'activity_comment' === $item['type'] ) {
290
- $root_id = $item['item_id'];
291
- } else {
292
- $root_id = $item['id'];
293
- }
294
-
295
- echo '<tr' . $row_class . ' id="activity-' . esc_attr( $item['id'] ) . '" data-parent_id="' . esc_attr( $item['id'] ) . '" data-root_id="' . esc_attr( $root_id ) . '">';
296
- echo $this->single_row_columns( $item );
297
- echo '</tr>';
298
-
299
- $even = ! $even;
300
- }
301
-
302
- /**
303
- * Get the list of views available on this table (e.g. "all", "spam").
304
- *
305
- * @since 1.6.0
306
- */
307
- function get_views() {
308
- $url_base = add_query_arg( array( 'page' => 'bp-activity' ), bp_get_admin_url( 'admin.php' ) ); ?>
309
-
310
- <h2 class="screen-reader-text"><?php
311
- /* translators: accessibility text */
312
- _e( 'Filter activities list', 'buddypress' );
313
- ?></h2>
314
-
315
- <ul class="subsubsub">
316
- <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>
317
- <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>
318
-
319
- <?php
320
-
321
- /**
322
- * Fires inside listing of views so plugins can add their own.
323
- *
324
- * @since 1.6.0
325
- *
326
- * @param string $url_base Current URL base for view.
327
- * @param string $view Current view being displayed.
328
- */
329
- do_action( 'bp_activity_list_table_get_views', $url_base, $this->view ); ?>
330
- </ul>
331
- <?php
332
- }
333
-
334
- /**
335
- * Get bulk actions.
336
- *
337
- * @since 1.6.0
338
- *
339
- * @return array Key/value pairs for the bulk actions dropdown.
340
- */
341
- function get_bulk_actions() {
342
- $actions = array();
343
- $actions['bulk_spam'] = __( 'Mark as Spam', 'buddypress' );
344
- $actions['bulk_ham'] = __( 'Not Spam', 'buddypress' );
345
- $actions['bulk_delete'] = __( 'Delete Permanently', 'buddypress' );
346
-
347
- /**
348
- * Filters the default bulk actions so plugins can add custom actions.
349
- *
350
- * @since 1.6.0
351
- *
352
- * @param array $actions Default available actions for bulk operations.
353
- */
354
- return apply_filters( 'bp_activity_list_table_get_bulk_actions', $actions );
355
- }
356
-
357
- /**
358
- * Get the table column titles.
359
- *
360
- * @since 1.6.0
361
- *
362
- * @see WP_List_Table::single_row_columns()
363
- *
364
- * @return array The columns to appear in the Activity list table.
365
- */
366
- function get_columns() {
367
- /**
368
- * Filters the titles for the columns for the activity list table.
369
- *
370
- * @since 2.4.0
371
- *
372
- * @param array $value Array of slugs and titles for the columns.
373
- */
374
- return apply_filters( 'bp_activity_list_table_get_columns', array(
375
- 'cb' => '<input name type="checkbox" />',
376
- 'author' => _x('Author', 'Admin SWA column header', 'buddypress' ),
377
- 'comment' => _x( 'Activity', 'Admin SWA column header', 'buddypress' ),
378
- 'action' => _x( 'Action', 'Admin SWA column header', 'buddypress' ),
379
- 'response' => _x( 'In Response To', 'Admin SWA column header', 'buddypress' ),
380
- ) );
381
- }
382
-
383
- /**
384
- * Get the column names for sortable columns.
385
- *
386
- * Currently, returns an empty array (no columns are sortable).
387
- *
388
- * @since 1.6.0
389
- * @todo For this to work, BP_Activity_Activity::get() needs updating
390
- * to support ordering by specific fields.
391
- *
392
- * @return array The columns that can be sorted on the Activity screen.
393
- */
394
- function get_sortable_columns() {
395
- return array();
396
-
397
- /*return array(
398
- 'author' => array( 'activity_author', false ), // Intentionally not using "=>"
399
- );*/
400
- }
401
-
402
- /**
403
- * Markup for the "filter" part of the form (i.e. which activity type to display).
404
- *
405
- * @since 1.6.0
406
- *
407
- * @param string $which 'top' or 'bottom'.
408
- */
409
- function extra_tablenav( $which ) {
410
-
411
- // Bail on bottom table nav.
412
- if ( 'bottom' === $which ) {
413
- return;
414
- }
415
-
416
- // Is any filter currently selected?
417
- $selected = ( ! empty( $_REQUEST['activity_type'] ) ) ? $_REQUEST['activity_type'] : '';
418
-
419
- // Get the actions.
420
- $activity_actions = bp_activity_get_actions(); ?>
421
-
422
- <div class="alignleft actions">
423
- <label for="activity-type" class="screen-reader-text"><?php
424
- /* translators: accessibility text */
425
- _e( 'Filter by activity type', 'buddypress' );
426
- ?></label>
427
- <select name="activity_type" id="activity-type">
428
- <option value="" <?php selected( ! $selected ); ?>><?php _e( 'View all actions', 'buddypress' ); ?></option>
429
-
430
- <?php foreach ( $activity_actions as $component => $actions ) : ?>
431
- <?php
432
- // Older avatar activity items use 'profile' for component. See r4273.
433
- if ( $component === 'profile' ) {
434
- $component = 'xprofile';
435
- }
436
-
437
- if ( bp_is_active( $component ) ) {
438
- if ( $component === 'xprofile' ) {
439
- $component_name = buddypress()->profile->name;
440
- } else {
441
- $component_name = buddypress()->$component->name;
442
- }
443
-
444
- } else {
445
- // Prevent warnings by other plugins if a component is disabled but the activity type has been registered.
446
- $component_name = ucfirst( $component );
447
- }
448
- ?>
449
-
450
- <optgroup label="<?php echo esc_html( $component_name ); ?>">
451
-
452
- <?php foreach ( $actions as $action_key => $action_values ) : ?>
453
-
454
- <?php
455
-
456
- // Skip the incorrectly named pre-1.6 action.
457
- if ( 'friends_register_activity_action' !== $action_key ) : ?>
458
-
459
- <option value="<?php echo esc_attr( $action_key ); ?>" <?php selected( $action_key, $selected ); ?>><?php echo esc_html( $action_values[ 'value' ] ); ?></option>
460
-
461
- <?php endif; ?>
462
-
463
- <?php endforeach; ?>
464
-
465
- </optgroup>
466
-
467
- <?php endforeach; ?>
468
-
469
- </select>
470
-
471
- <?php submit_button( __( 'Filter', 'buddypress' ), 'secondary', false, false, array( 'id' => 'post-query-submit' ) ); ?>
472
- </div>
473
-
474
- <?php
475
- }
476
-
477
- /**
478
- * Override WP_List_Table::row_actions().
479
- *
480
- * Basically a duplicate of the row_actions() method, but removes the
481
- * unnecessary <button> addition.
482
- *
483
- * @since 2.3.3
484
- * @since 2.3.4 Visibility set to public for compatibility with WP < 4.0.0.
485
- *
486
- * @param array $actions The list of actions.
487
- * @param bool $always_visible Whether the actions should be always visible.
488
- * @return string
489
- */
490
- public function row_actions( $actions, $always_visible = false ) {
491
- $action_count = count( $actions );
492
- $i = 0;
493
-
494
- if ( !$action_count )
495
- return '';
496
-
497
- $out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
498
- foreach ( $actions as $action => $link ) {
499
- ++$i;
500
- ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
501
- $out .= "<span class='$action'>$link$sep</span>";
502
- }
503
- $out .= '</div>';
504
-
505
- return $out;
506
- }
507
-
508
- /**
509
- * Checkbox column markup.
510
- *
511
- * @since 1.6.0
512
- *
513
- * @see WP_List_Table::single_row_columns()
514
- *
515
- * @param array $item A singular item (one full row).
516
- */
517
- function column_cb( $item ) {
518
- /* translators: accessibility text */
519
- 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'] );
520
- }
521
-
522
- /**
523
- * Author column markup.
524
- *
525
- * @since 1.6.0
526
- *
527
- * @see WP_List_Table::single_row_columns()
528
- *
529
- * @param array $item A singular item (one full row).
530
- */
531
- function column_author( $item ) {
532
- echo '<strong>' . get_avatar( $item['user_id'], '32' ) . ' ' . bp_core_get_userlink( $item['user_id'] ) . '</strong>';
533
- }
534
-
535
- /**
536
- * Action column markup.
537
- *
538
- * @since 2.0.0
539
- *
540
- * @see WP_List_Table::single_row_columns()
541
- *
542
- * @param array $item A singular item (one full row).
543
- */
544
- function column_action( $item ) {
545
- $actions = bp_activity_admin_get_activity_actions();
546
-
547
- if ( isset( $actions[ $item['type'] ] ) ) {
548
- echo $actions[ $item['type'] ];
549
- } else {
550
- printf( __( 'Unregistered action - %s', 'buddypress' ), $item['type'] );
551
- }
552
- }
553
-
554
- /**
555
- * Content column, and "quick admin" rollover actions.
556
- *
557
- * Called "comment" in the CSS so we can re-use some WP core CSS.
558
- *
559
- * @since 1.6.0
560
- *
561
- * @see WP_List_Table::single_row_columns()
562
- *
563
- * @param array $item A singular item (one full row).
564
- */
565
- function column_comment( $item ) {
566
- // Determine what type of item (row) we're dealing with.
567
- if ( $item['is_spam'] )
568
- $item_status = 'spam';
569
- else
570
- $item_status = 'all';
571
-
572
- // Preorder items: Reply | Edit | Spam | Delete Permanently.
573
- $actions = array(
574
- 'reply' => '',
575
- 'edit' => '',
576
- 'spam' => '', 'unspam' => '',
577
- 'delete' => '',
578
- );
579
-
580
- // Build actions URLs.
581
- $base_url = bp_get_admin_url( 'admin.php?page=bp-activity&amp;aid=' . $item['id'] );
582
- $spam_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'spam-activity_' . $item['id'] ) );
583
-
584
- $delete_url = $base_url . "&amp;action=delete&amp;$spam_nonce";
585
- $edit_url = $base_url . '&amp;action=edit';
586
- $ham_url = $base_url . "&amp;action=ham&amp;$spam_nonce";
587
- $spam_url = $base_url . "&amp;action=spam&amp;$spam_nonce";
588
-
589
- // Rollover actions.
590
- // Reply - JavaScript only; implemented by AJAX.
591
- if ( 'spam' != $item_status ) {
592
- if ( $this->can_comment( $item ) ) {
593
- $actions['reply'] = sprintf( '<a href="#" class="reply hide-if-no-js">%s</a>', __( 'Reply', 'buddypress' ) );
594
- } else {
595
- $actions['reply'] = sprintf( '<span class="form-input-tip" title="%s">%s</span>', __( 'Replies are disabled for this activity item', 'buddypress' ), __( 'Replies disabled', 'buddypress' ) );
596
- }
597
-
598
- // Edit.
599
- $actions['edit'] = sprintf( '<a href="%s">%s</a>', $edit_url, __( 'Edit', 'buddypress' ) );
600
- }
601
-
602
- // Spam/unspam.
603
- if ( 'spam' == $item_status )
604
- $actions['unspam'] = sprintf( '<a href="%s">%s</a>', $ham_url, __( 'Not Spam', 'buddypress' ) );
605
- else
606
- $actions['spam'] = sprintf( '<a href="%s">%s</a>', $spam_url, __( 'Spam', 'buddypress' ) );
607
-
608
- // Delete.
609
- $actions['delete'] = sprintf( '<a href="%s" onclick="%s">%s</a>', $delete_url, "javascript:return confirm('" . esc_js( __( 'Are you sure?', 'buddypress' ) ) . "'); ", __( 'Delete Permanently', 'buddypress' ) );
610
-
611
- // Start timestamp.
612
- echo '<div class="submitted-on">';
613
-
614
- /**
615
- * Filters available actions for plugins to alter.
616
- *
617
- * @since 1.6.0
618
- *
619
- * @param array $actions Array of available actions user could use.
620
- * @param array $item Current item being added to page.
621
- */
622
- $actions = apply_filters( 'bp_activity_admin_comment_row_actions', array_filter( $actions ), $item );
623
-
624
- printf(
625
- /* translators: %s: activity date and time */
626
- __( 'Submitted on %s', 'buddypress' ),
627
- sprintf(
628
- '<a href="%1$s">%2$s</a>',
629
- bp_activity_get_permalink( $item['id'] ),
630
- sprintf(
631
- /* translators: 1: activity date, 2: activity time */
632
- __( '%1$s at %2$s', 'buddypress' ),
633
- date_i18n( bp_get_option( 'date_format' ), strtotime( $item['date_recorded'] ) ),
634
- get_date_from_gmt( $item['date_recorded'], bp_get_option( 'time_format' ) )
635
- )
636
- )
637
- );
638
-
639
- // End timestamp.
640
- echo '</div>';
641
-
642
- // Get activity content - if not set, use the action.
643
- if ( ! empty( $item['content'] ) ) {
644
- $activity = new BP_Activity_Activity( $item['id'] );
645
-
646
- /** This filter is documented in bp-activity/bp-activity-template.php */
647
- $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $item['content'], &$activity ) );
648
- } else {
649
- /**
650
- * Filters current activity item action.
651
- *
652
- * @since 1.2.0
653
- *
654
- * @var array $item Array index holding current activity item action.
655
- */
656
- $content = apply_filters_ref_array( 'bp_get_activity_action', array( $item['action'] ) );
657
- }
658
-
659
- /**
660
- * Filter here to add extra output to the activity content into the Administration.
661
- *
662
- * @since 2.4.0
663
- *
664
- * @param string $content The activity content.
665
- * @param array $item The activity object converted into an array.
666
- */
667
- echo apply_filters( 'bp_activity_admin_comment_content', $content, $item ) . ' ' . $this->row_actions( $actions );
668
- }
669
-
670
- /**
671
- * "In response to" column markup.
672
- *
673
- * @since 1.6.0
674
- *
675
- * @see WP_List_Table::single_row_columns()
676
- *
677
- * @param array $item A singular item (one full row).
678
- */
679
- function column_response( $item ) {
680
-
681
- // Is $item is a root activity?
682
- ?>
683
-
684
- <div class="response-links">
685
-
686
- <?php
687
- // Activity permalink.
688
- $activity_permalink = '';
689
- if ( ! $item['is_spam'] ) {
690
- $activity_permalink = '<a href="' . bp_activity_get_permalink( $item['id'], (object) $item ) . '" class="comments-view-item-link">' . __( 'View Activity', 'buddypress' ) . '</a>';
691
- }
692
-
693
- /**
694
- * Filters default list of default root activity types.
695
- *
696
- * @since 1.6.0
697
- *
698
- * @param array $value Array of default activity types.
699
- * @param array $item Current item being displayed.
700
- */
701
- if ( empty( $item['item_id'] ) || ! in_array( $item['type'], apply_filters( 'bp_activity_admin_root_activity_types', array( 'activity_comment' ), $item ) ) ) {
702
- echo $activity_permalink;
703
-
704
- $comment_count = !empty( $item['children'] ) ? bp_activity_recurse_comment_count( (object) $item ) : 0;
705
- $root_activity_url = bp_get_admin_url( 'admin.php?page=bp-activity&amp;aid=' . $item['id'] );
706
-
707
- // If the activity has comments, display a link to the activity's permalink, with its comment count in a speech bubble.
708
- if ( $comment_count ) {
709
- $title_attr = sprintf( _n( '%s related activity', '%s related activities', $comment_count, 'buddypress' ), number_format_i18n( $comment_count ) );
710
- 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 ) );
711
- }
712
-
713
- // For non-root activities, display a link to the replied-to activity's author's profile.
714
- } else {
715
- 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 />';
716
- echo $activity_permalink;
717
- }
718
- ?>
719
-
720
- </div>
721
-
722
- <?php
723
- }
724
-
725
- /**
726
- * Allow plugins to add their custom column.
727
- *
728
- * @since 2.4.0
729
- *
730
- * @param array $item Information about the current row.
731
- * @param string $column_name The column name.
732
- * @return string
733
- */
734
- public function column_default( $item = array(), $column_name = '' ) {
735
-
736
- /**
737
- * Filters a string to allow plugins to add custom column content.
738
- *
739
- * @since 2.4.0
740
- *
741
- * @param string $value Empty string.
742
- * @param string $column_name Name of the column being rendered.
743
- * @param array $item The current activity item in the loop.
744
- */
745
- return apply_filters( 'bp_activity_admin_get_custom_column', '', $column_name, $item );
746
- }
747
-
748
- /**
749
- * Get the user id associated with a given activity item.
750
- *
751
- * Wraps bp_activity_get_specific(), with some additional logic for
752
- * avoiding duplicate queries.
753
- *
754
- * @since 1.6.0
755
- *
756
- * @param int $activity_id Activity ID to retrieve User ID for.
757
- * @return int User ID of the activity item in question.
758
- */
759
- protected function get_activity_user_id( $activity_id ) {
760
- // If there is an existing activity/user ID mapping, just return the user ID.
761
- if ( ! empty( $this->activity_user_id[$activity_id] ) ) {
762
- return $this->activity_user_id[$activity_id];
763
-
764
- /*
765
- * We don't have a mapping. This means the $activity_id is not on the current
766
- * page of results, so fetch its details from the database.
767
- */
768
- } else {
769
- $activity = bp_activity_get_specific( array( 'activity_ids' => $activity_id, 'show_hidden' => true, 'spam' => 'all', ) );
770
-
771
- /*
772
- * If, somehow, the referenced activity has been deleted, leaving its associated
773
- * activities as orphans, use the logged in user's ID to avoid errors.
774
- */
775
- if ( empty( $activity['activities'] ) )
776
- return bp_loggedin_user_id();
777
-
778
- // Store the new activity/user ID mapping for any later re-use.
779
- $this->activity_user_id[ $activity['activities'][0]->id ] = $activity['activities'][0]->user_id;
780
-
781
- // Return the user ID.
782
- return $activity['activities'][0]->user_id;
783
- }
784
- }
785
-
786
- /**
787
- * Checks if an activity item can be replied to.
788
- *
789
- * This method merges functionality from {@link bp_activity_can_comment()} and
790
- * {@link bp_blogs_disable_activity_commenting()}. This is done because the activity
791
- * list table doesn't use a BuddyPress activity loop, which prevents those
792
- * functions from working as intended.
793
- *
794
- * @since 2.0.0
795
- * @since 2.5.0 Include Post type activities types
796
- *
797
- * @param array $item An array version of the BP_Activity_Activity object.
798
- * @return bool $can_comment
799
- */
800
- protected function can_comment( $item ) {
801
- $can_comment = bp_activity_type_supports( $item['type'], 'comment-reply' );
802
-
803
- if ( ! $this->disable_blogforum_comments && bp_is_active( 'blogs' ) ) {
804
- $parent_activity = false;
805
-
806
- if ( bp_activity_type_supports( $item['type'], 'post-type-comment-tracking' ) ) {
807
- $parent_activity = (object) $item;
808
- } elseif ( 'activity_comment' === $item['type'] ) {
809
- $parent_activity = new BP_Activity_Activity( $item['item_id'] );
810
- $can_comment = bp_activity_can_comment_reply( (object) $item );
811
- }
812
-
813
- if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
814
- // Fetch blog post comment depth and if the blog post's comments are open.
815
- bp_blogs_setup_activity_loop_globals( $parent_activity );
816
-
817
- $can_comment = bp_blogs_can_comment_reply( true, $item );
818
- }
819
- }
820
-
821
- /**
822
- * Filters if an activity item can be commented on or not.
823
- *
824
- * @since 2.0.0
825
- * @since 2.5.0 Add a second parameter to include the activity item into the filter.
826
- *
827
- * @param bool $can_comment Whether an activity item can be commented on or not.
828
- * @param array $item An array version of the BP_Activity_Activity object.
829
- */
830
- return apply_filters( 'bp_activity_list_table_can_comment', $can_comment, $item );
831
- }
832
-
833
- /**
834
- * Flatten the activity array.
835
- *
836
- * In some cases, BuddyPress gives us a structured tree of activity
837
- * items plus their comments. This method converts it to a flat array.
838
- *
839
- * @since 1.6.0
840
- *
841
- * @param array $tree Source array.
842
- * @return array Flattened array.
843
- */
844
- public static function flatten_activity_array( $tree ){
845
- foreach ( (array) $tree as $node ) {
846
- if ( isset( $node->children ) ) {
847
-
848
- foreach ( BP_Activity_List_Table::flatten_activity_array( $node->children ) as $child ) {
849
- $tree[] = $child;
850
- }
851
-
852
- unset( $node->children );
853
- }
854
- }
855
-
856
- return $tree;
857
- }
858
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-oembed-extension.php DELETED
@@ -1,329 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Classes.
4
- *
5
- * @package BuddyPress
6
- * @subpackage Embeds
7
- */
8
-
9
- // Exit if accessed directly.
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * oEmbed handler to respond and render single activity items.
14
- *
15
- * @since 2.6.0
16
- */
17
- class BP_Activity_oEmbed_Extension extends BP_Core_oEmbed_Extension {
18
- /**
19
- * Custom oEmbed slug endpoint.
20
- *
21
- * @since 2.6.0
22
- *
23
- * @var string
24
- */
25
- public $slug_endpoint = 'activity';
26
-
27
- /**
28
- * Custom hooks.
29
- *
30
- * @since 2.6.0
31
- */
32
- protected function custom_hooks() {
33
- add_action( 'oembed_dataparse', array( $this, 'use_custom_iframe_sandbox_attribute' ), 20, 3 );
34
- add_action( 'embed_content_meta', array( $this, 'embed_comments_button' ), 5 );
35
- add_action( 'get_template_part_assets/embeds/header', array( $this, 'on_activity_header' ), 10, 2 );
36
-
37
- add_filter( 'bp_activity_embed_html', array( $this, 'modify_iframe' ) );
38
- }
39
-
40
- /**
41
- * Add custom endpoint arguments.
42
- *
43
- * Currently, includes 'hide_media'.
44
- *
45
- * @since 2.6.0
46
- *
47
- * @return array
48
- */
49
- protected function set_route_args() {
50
- return array(
51
- 'hide_media' => array(
52
- 'default' => false,
53
- 'sanitize_callback' => 'wp_validate_boolean'
54
- )
55
- );
56
- }
57
-
58
- /**
59
- * Output our custom embed template part.
60
- *
61
- * @since 2.6.0
62
- */
63
- protected function content() {
64
- bp_get_asset_template_part( 'embeds/activity' );
65
- }
66
-
67
- /**
68
- * Check if we're on our single activity page.
69
- *
70
- * @since 2.6.0
71
- *
72
- * @return bool
73
- */
74
- protected function is_page() {
75
- return bp_is_single_activity();
76
- }
77
-
78
- /**
79
- * Validates the URL to determine if the activity item is valid.
80
- *
81
- * @since 2.6.0
82
- *
83
- * @param string $url The URL to check.
84
- * @return int|bool Activity ID on success; boolean false on failure.
85
- */
86
- protected function validate_url_to_item_id( $url ) {
87
- if ( bp_core_enable_root_profiles() ) {
88
- $domain = bp_get_root_domain();
89
- } else {
90
- $domain = bp_get_members_directory_permalink();
91
- }
92
-
93
- // Check the URL to see if this is a single activity URL.
94
- if ( 0 !== strpos( $url, $domain ) ) {
95
- return false;
96
- }
97
-
98
- // Check for activity slug.
99
- if ( false === strpos( $url, '/' . bp_get_activity_slug() . '/' ) ) {
100
- return false;
101
- }
102
-
103
- // Do more checks.
104
- $url = trim( untrailingslashit( $url ) );
105
-
106
- // Grab the activity ID.
107
- $activity_id = (int) substr(
108
- $url,
109
- strrpos( $url, '/' ) + 1
110
- );
111
-
112
- if ( ! empty( $activity_id ) ) {
113
- // Check if activity item still exists.
114
- $activity = new BP_Activity_Activity( $activity_id );
115
-
116
- // Okay, we're good to go!
117
- if ( ! empty( $activity->component ) && 0 === (int) $activity->is_spam ) {
118
- return $activity_id;
119
- }
120
- }
121
-
122
- return false;
123
- }
124
-
125
- /**
126
- * Sets the oEmbed response data for our activity item.
127
- *
128
- * @since 2.6.0
129
- *
130
- * @param int $item_id The activity ID.
131
- * @return array
132
- */
133
- protected function set_oembed_response_data( $item_id ) {
134
- $activity = new BP_Activity_Activity( $item_id );
135
-
136
- return array(
137
- 'content' => $activity->content,
138
- 'title' => __( 'Activity', 'buddypress' ),
139
- 'author_name' => bp_core_get_user_displayname( $activity->user_id ),
140
- 'author_url' => bp_core_get_user_domain( $activity->user_id ),
141
-
142
- // Custom identifier.
143
- 'x_buddypress' => 'activity'
144
- );
145
- }
146
-
147
- /**
148
- * Sets a custom <blockquote> for our oEmbed fallback HTML.
149
- *
150
- * @since 2.6.0
151
- *
152
- * @param int $item_id The activity ID.
153
- * @return string
154
- */
155
- protected function set_fallback_html( $item_id ) {
156
- $activity = new BP_Activity_Activity( $item_id );
157
- $mentionname = bp_activity_do_mentions() ? ' (@' . bp_activity_get_user_mentionname( $activity->user_id ) . ')' : '';
158
- $date = date_i18n( get_option( 'date_format' ), strtotime( $activity->date_recorded ) );
159
-
160
- // Make sure we can use some activity functions that depend on the loop.
161
- $GLOBALS['activities_template'] = new stdClass;
162
- $GLOBALS['activities_template']->activity = $activity;
163
-
164
- // 'wp-embedded-content' CSS class is necessary due to how the embed JS works.
165
- $blockquote = sprintf( '<blockquote class="wp-embedded-content bp-activity-item">%1$s%2$s %3$s</blockquote>',
166
- bp_activity_get_embed_excerpt( $activity->content ),
167
- '- ' . bp_core_get_user_displayname( $activity->user_id ) . $mentionname,
168
- '<a href="' . esc_url( bp_activity_get_permalink( $item_id ) ) . '">' . $date . '</a>'
169
- );
170
-
171
- // Clean up.
172
- unset( $GLOBALS['activities_template'] );
173
-
174
- /**
175
- * Filters the fallback HTML used when embedding a BP activity item.
176
- *
177
- * @since 2.6.0
178
- *
179
- * @param string $blockquote Current fallback HTML
180
- * @param BP_Activity_Activity $activity Activity object
181
- */
182
- return apply_filters( 'bp_activity_embed_fallback_html', $blockquote, $activity );
183
- }
184
-
185
- /**
186
- * Sets a custom <iframe> title for our oEmbed item.
187
- *
188
- * @since 2.6.0
189
- *
190
- * @param int $item_id The activity ID
191
- * @return string
192
- */
193
- protected function set_iframe_title( $item_id ) {
194
- return __( 'Embedded Activity Item', 'buddypress' );
195
- }
196
-
197
- /**
198
- * Use our custom <iframe> sandbox attribute in our oEmbed response.
199
- *
200
- * WordPress sets the <iframe> sandbox attribute to 'allow-scripts' regardless
201
- * of whatever the oEmbed response is in {@link wp_filter_oembed_result()}. We
202
- * need to add back our custom sandbox value so links will work.
203
- *
204
- * @since 2.6.0
205
- *
206
- * @see BP_Activity_Component::modify_iframe() where our custom sandbox value is set.
207
- *
208
- * @param string $result The oEmbed HTML result.
209
- * @param object $data A data object result from an oEmbed provider.
210
- * @param string $url The URL of the content to be embedded.
211
- * @return string
212
- */
213
- public function use_custom_iframe_sandbox_attribute( $result, $data, $url ) {
214
- // Make sure we are on a BuddyPress activity oEmbed request.
215
- if ( false === isset( $data->x_buddypress ) || 'activity' !== $data->x_buddypress ) {
216
- return $result;
217
- }
218
-
219
- // Get unfiltered sandbox attribute from our own oEmbed response.
220
- $sandbox_pos = strpos( $data->html, 'sandbox=' ) + 9;
221
- $sandbox = substr( $data->html, $sandbox_pos, strpos( $data->html, '"', $sandbox_pos ) - $sandbox_pos );
222
-
223
- // Replace only if our sandbox attribute contains 'allow-top-navigation'.
224
- if ( false !== strpos( $sandbox, 'allow-top-navigation' ) ) {
225
- $result = str_replace( ' sandbox="allow-scripts"', " sandbox=\"{$sandbox}\"", $result );
226
-
227
- // Also remove 'security' attribute; this is only used for IE < 10.
228
- $result = str_replace( 'security="restricted"', "", $result );
229
- }
230
-
231
- return $result;
232
- }
233
-
234
- /**
235
- * Modify various IFRAME-related items if embeds are allowed.
236
- *
237
- * HTML modified:
238
- * - Add sandbox="allow-top-navigation" attribute. This allows links to work
239
- * within the iframe sandbox attribute.
240
- *
241
- * JS modified:
242
- * - Remove IFRAME height restriction of 1000px. Fixes long embed items being
243
- * truncated.
244
- *
245
- * @since 2.6.0
246
- *
247
- * @param string $retval Current embed HTML.
248
- * @return string
249
- */
250
- public function modify_iframe( $retval ) {
251
- // Add 'allow-top-navigation' to allow links to be clicked.
252
- $retval = str_replace( 'sandbox="', 'sandbox="allow-top-navigation ', $retval );
253
-
254
- // See /wp-includes/js/wp-embed.js.
255
- if ( SCRIPT_DEBUG ) {
256
- // Removes WP's hardcoded IFRAME height restriction.
257
- $retval = str_replace( 'height = 1000;', 'height = height;', $retval );
258
-
259
- // This is for the WP build minified version.
260
- } else {
261
- $retval = str_replace( 'g=1e3', 'g=g', $retval );
262
- }
263
-
264
- return $retval;
265
- }
266
-
267
- /**
268
- * Do stuff when our oEmbed activity header template part is loading.
269
- *
270
- * Currently, removes wpautop() from the bp_activity_action() function.
271
- *
272
- * @since 2.6.0
273
- *
274
- * @param string $slug Template part slug requested.
275
- * @param string $name Template part name requested.
276
- */
277
- public function on_activity_header( $slug, $name ) {
278
- if ( false === $this->is_page() || 'activity' !== $name ) {
279
- return;
280
- }
281
-
282
- remove_filter( 'bp_get_activity_action', 'wpautop' );
283
- }
284
-
285
- /**
286
- * Prints the markup for the activity embed comments button.
287
- *
288
- * Basically a copy of {@link print_embed_comments_button()}, but modified for
289
- * the BP activity component.
290
- *
291
- * @since 2.6.0
292
- */
293
- public function embed_comments_button() {
294
- if ( ! did_action( 'bp_embed_content' ) || ! bp_is_single_activity() ) {
295
- return;
296
- }
297
-
298
- // Make sure our custom permalink shows up in the 'WordPress Embed' block.
299
- add_filter( 'the_permalink', array( $this, 'filter_embed_url' ) );
300
-
301
- // Only show comment bubble if we have some activity comments.
302
- $count = bp_activity_get_comment_count();
303
- if ( empty( $count ) ) {
304
- return;
305
- }
306
- ?>
307
-
308
- <div class="wp-embed-comments">
309
- <a href="<?php bp_activity_thread_permalink(); ?>">
310
- <span class="dashicons dashicons-admin-comments"></span>
311
- <?php
312
- printf(
313
- _n(
314
- /* translators: accessibility text */
315
- '%s <span class="screen-reader-text">Comment</span>',
316
- /* translators: accessibility text */
317
- '%s <span class="screen-reader-text">Comments</span>',
318
- $count,
319
- 'buddypress'
320
- ),
321
- number_format_i18n( $count )
322
- );
323
- ?>
324
- </a>
325
- </div>
326
-
327
- <?php
328
- }
329
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-query.php DELETED
@@ -1,247 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Classes
4
- *
5
- * @package BuddyPress
6
- * @subpackage ActivityQuery
7
- * @since 2.2.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- /**
14
- * Class for generating the WHERE SQL clause for advanced activity fetching.
15
- *
16
- * This is notably used in {@link BP_Activity_Activity::get()} with the
17
- * 'filter_query' parameter.
18
- *
19
- * @since 2.2.0
20
- */
21
- class BP_Activity_Query extends BP_Recursive_Query {
22
- /**
23
- * Array of activity queries.
24
- *
25
- * See {@see BP_Activity_Query::__construct()} for information on query arguments.
26
- *
27
- * @since 2.2.0
28
- * @var array
29
- */
30
- public $queries = array();
31
-
32
- /**
33
- * Table alias.
34
- *
35
- * @since 2.2.0
36
- * @var string
37
- */
38
- public $table_alias = '';
39
-
40
- /**
41
- * Supported DB columns.
42
- *
43
- * See the 'wp_bp_activity' DB table schema.
44
- *
45
- * @since 2.2.0
46
- * @var array
47
- */
48
- public $db_columns = array(
49
- 'id', 'user_id', 'component', 'type', 'action', 'content',
50
- 'item_id', 'secondary_item_id', 'hide_sitewide', 'is_spam',
51
- );
52
-
53
- /**
54
- * Constructor.
55
- *
56
- * @since 2.2.0
57
- *
58
- * @param array $query {
59
- * Array of query clauses.
60
- * @type array {
61
- * @type string $column Required. The column to query against. Basically, any DB column in the main
62
- * 'wp_bp_activity' table.
63
- * @type string $value Required. Value to filter by.
64
- * @type string $compare Optional. The comparison operator. Default '='.
65
- * Accepts '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'LIKE',
66
- * 'NOT LIKE', BETWEEN', 'NOT BETWEEN', 'REGEXP', 'NOT REGEXP', 'RLIKE'.
67
- * @type string $relation Optional. The boolean relationship between the activity queries.
68
- * Accepts 'OR', 'AND'. Default 'AND'.
69
- * @type array {
70
- * Optional. Another fully-formed activity query. See parameters above.
71
- * }
72
- * }
73
- * }
74
- */
75
- public function __construct( $query = array() ) {
76
- if ( ! is_array( $query ) ) {
77
- return;
78
- }
79
-
80
- $this->queries = $this->sanitize_query( $query );
81
- }
82
-
83
- /**
84
- * Generates WHERE SQL clause to be appended to a main query.
85
- *
86
- * @since 2.2.0
87
- *
88
- * @param string $alias An existing table alias that is compatible with the current query clause.
89
- * Default: 'a'. BP_Activity_Activity::get() uses 'a', so we default to that.
90
- * @return string SQL fragment to append to the main WHERE clause.
91
- */
92
- public function get_sql( $alias = 'a' ) {
93
- if ( ! empty( $alias ) ) {
94
- $this->table_alias = sanitize_title( $alias );
95
- }
96
-
97
- $sql = $this->get_sql_clauses();
98
-
99
- // We only need the 'where' clause.
100
- //
101
- // Also trim trailing "AND" clause from parent BP_Recursive_Query class
102
- // since it's not necessary for our needs.
103
- return preg_replace( '/^\sAND/', '', $sql['where'] );
104
- }
105
-
106
- /**
107
- * Generate WHERE clauses for a first-order clause.
108
- *
109
- * @since 2.2.0
110
- *
111
- * @param array $clause Array of arguments belonging to the clause.
112
- * @param array $parent_query Parent query to which the clause belongs.
113
- * @return array {
114
- * @type array $where Array of subclauses for the WHERE statement.
115
- * @type array $join Empty array. Not used.
116
- * }
117
- */
118
- protected function get_sql_for_clause( $clause, $parent_query ) {
119
- global $wpdb;
120
-
121
- $sql_chunks = array(
122
- 'where' => array(),
123
- 'join' => array(),
124
- );
125
-
126
- $column = isset( $clause['column'] ) ? $this->validate_column( $clause['column'] ) : '';
127
- $value = isset( $clause['value'] ) ? $clause['value'] : '';
128
- if ( empty( $column ) || ! isset( $clause['value'] ) ) {
129
- return $sql_chunks;
130
- }
131
-
132
- if ( isset( $clause['compare'] ) ) {
133
- $clause['compare'] = strtoupper( $clause['compare'] );
134
- } else {
135
- $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
136
- }
137
-
138
- // Default 'compare' to '=' if no valid operator is found.
139
- if ( ! in_array( $clause['compare'], array(
140
- '=', '!=', '>', '>=', '<', '<=',
141
- 'LIKE', 'NOT LIKE',
142
- 'IN', 'NOT IN',
143
- 'BETWEEN', 'NOT BETWEEN',
144
- 'REGEXP', 'NOT REGEXP', 'RLIKE'
145
- ) ) ) {
146
- $clause['compare'] = '=';
147
- }
148
-
149
- $compare = $clause['compare'];
150
-
151
- $alias = ! empty( $this->table_alias ) ? "{$this->table_alias}." : '';
152
-
153
- // Next, Build the WHERE clause.
154
- $where = '';
155
-
156
- // Value.
157
- if ( isset( $clause['value'] ) ) {
158
- if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) {
159
- if ( ! is_array( $value ) ) {
160
- $value = preg_split( '/[,\s]+/', $value );
161
- }
162
- }
163
-
164
- // Tinyint.
165
- if ( ! empty( $column ) && true === in_array( $column, array( 'hide_sitewide', 'is_spam' ) ) ) {
166
- $sql_chunks['where'][] = $wpdb->prepare( "{$alias}{$column} = %d", $value );
167
-
168
- } else {
169
- switch ( $compare ) {
170
- // IN uses different syntax.
171
- case 'IN' :
172
- case 'NOT IN' :
173
- $in_sql = BP_Activity_Activity::get_in_operator_sql( "{$alias}{$column}", $value );
174
-
175
- // 'NOT IN' operator is as easy as a string replace!
176
- if ( 'NOT IN' === $compare ) {
177
- $in_sql = str_replace( 'IN', 'NOT IN', $in_sql );
178
- }
179
-
180
- $sql_chunks['where'][] = $in_sql;
181
- break;
182
-
183
- case 'BETWEEN' :
184
- case 'NOT BETWEEN' :
185
- $value = array_slice( $value, 0, 2 );
186
- $where = $wpdb->prepare( '%s AND %s', $value );
187
- break;
188
-
189
- case 'LIKE' :
190
- case 'NOT LIKE' :
191
- $value = '%' . bp_esc_like( $value ) . '%';
192
- $where = $wpdb->prepare( '%s', $value );
193
- break;
194
-
195
- default :
196
- $where = $wpdb->prepare( '%s', $value );
197
- break;
198
-
199
- }
200
- }
201
-
202
- if ( $where ) {
203
- $sql_chunks['where'][] = "{$alias}{$column} {$compare} {$where}";
204
- }
205
- }
206
-
207
- /*
208
- * Multiple WHERE clauses should be joined in parentheses.
209
- */
210
- if ( 1 < count( $sql_chunks['where'] ) ) {
211
- $sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
212
- }
213
-
214
- return $sql_chunks;
215
- }
216
-
217
- /**
218
- * Determine whether a clause is first-order.
219
- *
220
- * @since 2.2.0
221
- *
222
- * @param array $query Clause to check.
223
- * @return bool
224
- */
225
- protected function is_first_order_clause( $query ) {
226
- return isset( $query['column'] ) || isset( $query['value'] );
227
- }
228
-
229
- /**
230
- * Validates a column name parameter.
231
- *
232
- * Column names are checked against a whitelist of known tables.
233
- * See {@link BP_Activity_Query::db_tables}.
234
- *
235
- * @since 2.2.0
236
- *
237
- * @param string $column The user-supplied column name.
238
- * @return string A validated column name value.
239
- */
240
- public function validate_column( $column = '' ) {
241
- if ( in_array( $column, $this->db_columns ) ) {
242
- return $column;
243
- } else {
244
- return '';
245
- }
246
- }
247
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-template.php DELETED
@@ -1,408 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Template.
4
- *
5
- * @package BuddyPress
6
- * @subpackage ActivityTemplate
7
- * @since 1.5.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- /**
14
- * The main activity template loop class.
15
- *
16
- * This is responsible for loading a group of activity items and displaying them.
17
- *
18
- * @since 1.0.0
19
- */
20
- class BP_Activity_Template {
21
-
22
- /**
23
- * The loop iterator.
24
- *
25
- * @since 1.0.0
26
- * @var int
27
- */
28
- public $current_activity = -1;
29
-
30
- /**
31
- * The activity count.
32
- *
33
- * @since 1.0.0
34
- * @var int
35
- */
36
- public $activity_count;
37
-
38
- /**
39
- * The total activity count.
40
- *
41
- * @since 1.0.0
42
- * @var int
43
- */
44
- public $total_activity_count;
45
-
46
- /**
47
- * Array of activities located by the query.
48
- *
49
- * @since 1.0.0
50
- * @var array
51
- */
52
- public $activities;
53
-
54
- /**
55
- * The activity object currently being iterated on.
56
- *
57
- * @since 1.0.0
58
- * @var object
59
- */
60
- public $activity;
61
-
62
- /**
63
- * A flag for whether the loop is currently being iterated.
64
- *
65
- * @since 1.0.0
66
- * @var bool
67
- */
68
- public $in_the_loop;
69
-
70
- /**
71
- * URL parameter key for activity pagination. Default: 'acpage'.
72
- *
73
- * @since 2.1.0
74
- * @var string
75
- */
76
- public $pag_arg;
77
-
78
- /**
79
- * The page number being requested.
80
- *
81
- * @since 1.0.0
82
- * @var int
83
- */
84
- public $pag_page;
85
-
86
- /**
87
- * The number of items being requested per page.
88
- *
89
- * @since 1.0.0
90
- * @var int
91
- */
92
- public $pag_num;
93
-
94
- /**
95
- * An HTML string containing pagination links.
96
- *
97
- * @since 1.0.0
98
- * @var string
99
- */
100
- public $pag_links;
101
-
102
- /**
103
- * The displayed user's full name.
104
- *
105
- * @since 1.0.0
106
- * @var string
107
- */
108
- public $full_name;
109
-
110
- /**
111
- * Constructor method.
112
- *
113
- * The arguments passed to this class constructor are of the same
114
- * format as {@link BP_Activity_Activity::get()}.
115
- *
116
- * @since 1.5.0
117
- *
118
- * @see BP_Activity_Activity::get() for a description of the argument
119
- * structure, as well as default values.
120
- *
121
- * @param array $args {
122
- * Array of arguments. Supports all arguments from
123
- * BP_Activity_Activity::get(), as well as 'page_arg' and
124
- * 'include'. Default values for 'per_page' and 'display_comments'
125
- * differ from the originating function, and are described below.
126
- * @type string $page_arg The string used as a query parameter in
127
- * pagination links. Default: 'acpage'.
128
- * @type array|bool $include Pass an array of activity IDs to
129
- * retrieve only those items, or false to noop the 'include'
130
- * parameter. 'include' differs from 'in' in that 'in' forms
131
- * an IN clause that works in conjunction with other filters
132
- * passed to the function, while 'include' is interpreted as
133
- * an exact list of items to retrieve, which skips all other
134
- * filter-related parameters. Default: false.
135
- * @type int|bool $per_page Default: 20.
136
- * @type string|bool $display_comments Default: 'threaded'.
137
- * }
138
- */
139
- public function __construct( $args ) {
140
- $bp = buddypress();
141
-
142
- // Backward compatibility with old method of passing arguments.
143
- if ( !is_array( $args ) || func_num_args() > 1 ) {
144
- _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__ ) );
145
-
146
- $old_args_keys = array(
147
- 0 => 'page',
148
- 1 => 'per_page',
149
- 2 => 'max',
150
- 3 => 'include',
151
- 4 => 'sort',
152
- 5 => 'filter',
153
- 6 => 'search_terms',
154
- 7 => 'display_comments',
155
- 8 => 'show_hidden',
156
- 9 => 'exclude',
157
- 10 => 'in',
158
- 11 => 'spam',
159
- 12 => 'page_arg'
160
- );
161
-
162
- $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
163
- }
164
-
165
- $defaults = array(
166
- 'page' => 1,
167
- 'per_page' => 20,
168
- 'page_arg' => 'acpage',
169
- 'max' => false,
170
- 'fields' => 'all',
171
- 'count_total' => false,
172
- 'sort' => false,
173
- 'include' => false,
174
- 'exclude' => false,
175
- 'in' => false,
176
- 'filter' => false,
177
- 'scope' => false,
178
- 'search_terms' => false,
179
- 'meta_query' => false,
180
- 'date_query' => false,
181
- 'filter_query' => false,
182
- 'display_comments' => 'threaded',
183
- 'show_hidden' => false,
184
- 'spam' => 'ham_only',
185
- 'update_meta_cache' => true,
186
- );
187
- $r = wp_parse_args( $args, $defaults );
188
- extract( $r );
189
-
190
- $this->pag_arg = sanitize_key( $r['page_arg'] );
191
- $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page'] );
192
- $this->pag_num = bp_sanitize_pagination_arg( 'num', $r['per_page'] );
193
-
194
- // Check if blog/forum replies are disabled.
195
- $this->disable_blogforum_replies = (bool) bp_core_get_root_option( 'bp-disable-blogforum-comments' );
196
-
197
- // Get an array of the logged in user's favorite activities.
198
- $this->my_favs = maybe_unserialize( bp_get_user_meta( bp_loggedin_user_id(), 'bp_favorite_activities', true ) );
199
-
200
- // Fetch specific activity items based on ID's.
201
- if ( !empty( $include ) ) {
202
- $this->activities = bp_activity_get_specific( array(
203
- 'activity_ids' => explode( ',', $include ),
204
- 'max' => $max,
205
- 'count_total' => $count_total,
206
- 'page' => $this->pag_page,
207
- 'per_page' => $this->pag_num,
208
- 'sort' => $sort,
209
- 'display_comments' => $display_comments,
210
- 'show_hidden' => $show_hidden,
211
- 'spam' => $spam,
212
- 'update_meta_cache' => $update_meta_cache,
213
- ) );
214
-
215
- // Fetch all activity items.
216
- } else {
217
- $this->activities = bp_activity_get( array(
218
- 'display_comments' => $display_comments,
219
- 'max' => $max,
220
- 'count_total' => $count_total,
221
- 'per_page' => $this->pag_num,
222
- 'page' => $this->pag_page,
223
- 'sort' => $sort,
224
- 'search_terms' => $search_terms,
225
- 'meta_query' => $meta_query,
226
- 'date_query' => $date_query,
227
- 'filter_query' => $filter_query,
228
- 'filter' => $filter,
229
- 'scope' => $scope,
230
- 'show_hidden' => $show_hidden,
231
- 'exclude' => $exclude,
232
- 'in' => $in,
233
- 'spam' => $spam,
234
- 'update_meta_cache' => $update_meta_cache,
235
- ) );
236
- }
237
-
238
- // The total_activity_count property will be set only if a
239
- // 'count_total' query has taken place.
240
- if ( ! is_null( $this->activities['total'] ) ) {
241
- if ( ! $max || $max >= (int) $this->activities['total'] ) {
242
- $this->total_activity_count = (int) $this->activities['total'];
243
- } else {
244
- $this->total_activity_count = (int) $max;
245
- }
246
- }
247
-
248
- $this->has_more_items = $this->activities['has_more_items'];
249
-
250
- $this->activities = $this->activities['activities'];
251
-
252
- if ( $max ) {
253
- if ( $max >= count($this->activities) ) {
254
- $this->activity_count = count( $this->activities );
255
- } else {
256
- $this->activity_count = (int) $max;
257
- }
258
- } else {
259
- $this->activity_count = count( $this->activities );
260
- }
261
-
262
- $this->full_name = bp_get_displayed_user_fullname();
263
-
264
- // Fetch parent content for activity comments so we do not have to query in the loop.
265
- foreach ( (array) $this->activities as $activity ) {
266
- if ( 'activity_comment' != $activity->type ) {
267
- continue;
268
- }
269
-
270
- $parent_ids[] = $activity->item_id;
271
- }
272
-
273
- if ( !empty( $parent_ids ) ) {
274
- $activity_parents = bp_activity_get_specific( array( 'activity_ids' => $parent_ids ) );
275
- }
276
-
277
- if ( !empty( $activity_parents['activities'] ) ) {
278
- foreach( $activity_parents['activities'] as $parent ) {
279
- $this->activity_parents[$parent->id] = $parent;
280
- }
281
-
282
- unset( $activity_parents );
283
- }
284
-
285
- if ( (int) $this->total_activity_count && (int) $this->pag_num ) {
286
- $this->pag_links = paginate_links( array(
287
- 'base' => add_query_arg( $this->pag_arg, '%#%' ),
288
- 'format' => '',
289
- 'total' => ceil( (int) $this->total_activity_count / (int) $this->pag_num ),
290
- 'current' => (int) $this->pag_page,
291
- 'prev_text' => _x( '&larr;', 'Activity pagination previous text', 'buddypress' ),
292
- 'next_text' => _x( '&rarr;', 'Activity pagination next text', 'buddypress' ),
293
- 'mid_size' => 1,
294
- 'add_args' => array(),
295
- ) );
296
- }
297
- }
298
-
299
- /**
300
- * Whether there are activity items available in the loop.
301
- *
302
- * @since 1.0.0
303
- *
304
- * @see bp_has_activities()
305
- *
306
- * @return bool True if there are items in the loop, otherwise false.
307
- */
308
- function has_activities() {
309
- if ( $this->activity_count ) {
310
- return true;
311
- }
312
-
313
- return false;
314
- }
315
-
316
- /**
317
- * Set up the next activity item and iterate index.
318
- *
319
- * @since 1.0.0
320
- *
321
- * @return object The next activity item to iterate over.
322
- */
323
- public function next_activity() {
324
- $this->current_activity++;
325
- $this->activity = $this->activities[ $this->current_activity ];
326
-
327
- return $this->activity;
328
- }
329
-
330
- /**
331
- * Rewind the posts and reset post index.
332
- *
333
- * @since 1.0.0
334
- */
335
- public function rewind_activities() {
336
- $this->current_activity = -1;
337
- if ( $this->activity_count > 0 ) {
338
- $this->activity = $this->activities[0];
339
- }
340
- }
341
-
342
- /**
343
- * Whether there are activity items left in the loop to iterate over.
344
- *
345
- * This method is used by {@link bp_activities()} as part of the while loop
346
- * that controls iteration inside the activities loop, eg:
347
- * while ( bp_activities() ) { ...
348
- *
349
- * @since 1.0.0
350
- *
351
- * @see bp_activities()
352
- *
353
- * @return bool True if there are more activity items to show,
354
- * otherwise false.
355
- */
356
- public function user_activities() {
357
- if ( ( $this->current_activity + 1 ) < $this->activity_count ) {
358
- return true;
359
- } elseif ( ( $this->current_activity + 1 ) == $this->activity_count ) {
360
-
361
- /**
362
- * Fires right before the rewinding of activity posts.
363
- *
364
- * @since 1.1.0
365
- */
366
- do_action( 'activity_loop_end' );
367
-
368
- // Do some cleaning up after the loop.
369
- $this->rewind_activities();
370
- }
371
-
372
- $this->in_the_loop = false;
373
-
374
- return false;
375
- }
376
-
377
- /**
378
- * Set up the current activity item inside the loop.
379
- *
380
- * Used by {@link bp_the_activity()} to set up the current activity item
381
- * data while looping, so that template tags used during that iteration
382
- * make reference to the current activity item.
383
- *
384
- * @since 1.0.0
385
- *
386
- * @see bp_the_activity()
387
- */
388
- public function the_activity() {
389
-
390
- $this->in_the_loop = true;
391
- $this->activity = $this->next_activity();
392
-
393
- if ( is_array( $this->activity ) ) {
394
- $this->activity = (object) $this->activity;
395
- }
396
-
397
- // Loop has just started.
398
- if ( $this->current_activity == 0 ) {
399
-
400
- /**
401
- * Fires if the current activity item is the first in the activity loop.
402
- *
403
- * @since 1.1.0
404
- */
405
- do_action('activity_loop_start');
406
- }
407
- }
408
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-activity-theme-compat.php DELETED
@@ -1,180 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Theme Compatibility.
4
- *
5
- * @package BuddyPress
6
- * @since 1.7.0
7
- */
8
-
9
- // Exit if accessed directly.
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * The main theme compat class for BuddyPress Activity.
14
- *
15
- * This class sets up the necessary theme compatibility actions to safely output
16
- * activity template parts to the_title and the_content areas of a theme.
17
- *
18
- * @since 1.7.0
19
- */
20
- class BP_Activity_Theme_Compat {
21
-
22
- /**
23
- * Set up the activity component theme compatibility.
24
- *
25
- * @since 1.7.0
26
- */
27
- public function __construct() {
28
- add_action( 'bp_setup_theme_compat', array( $this, 'is_activity' ) );
29
- }
30
-
31
- /**
32
- * Set up the theme compatibility hooks, if we're looking at an activity page.
33
- *
34
- * @since 1.7.0
35
- */
36
- public function is_activity() {
37
-
38
- // Bail if not looking at a group.
39
- if ( ! bp_is_activity_component() )
40
- return;
41
-
42
- // Activity Directory.
43
- if ( ! bp_displayed_user_id() && ! bp_current_action() ) {
44
- bp_update_is_directory( true, 'activity' );
45
-
46
- /** This action is documented in bp-activity/bp-activity-screens.php */
47
- do_action( 'bp_activity_screen_index' );
48
-
49
- add_filter( 'bp_get_buddypress_template', array( $this, 'directory_template_hierarchy' ) );
50
- add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'directory_dummy_post' ) );
51
- add_filter( 'bp_replace_the_content', array( $this, 'directory_content' ) );
52
-
53
- // Single activity.
54
- } elseif ( bp_is_single_activity() ) {
55
- add_filter( 'bp_get_buddypress_template', array( $this, 'single_template_hierarchy' ) );
56
- add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'single_dummy_post' ) );
57
- add_filter( 'bp_replace_the_content', array( $this, 'single_dummy_content' ) );
58
- }
59
- }
60
-
61
- /** Directory *************************************************************/
62
-
63
- /**
64
- * Add template hierarchy to theme compat for the activity directory page.
65
- *
66
- * This is to mirror how WordPress has {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
67
- *
68
- * @since 1.8.0
69
- *
70
- * @param string $templates The templates from bp_get_theme_compat_templates().
71
- * @return array $templates Array of custom templates to look for.
72
- */
73
- public function directory_template_hierarchy( $templates ) {
74
-
75
- /**
76
- * Filters the template hierarchy for the activity directory page.
77
- *
78
- * @since 1.8.0
79
- *
80
- * @param array $index-directory Array holding template names to be merged into template list.
81
- */
82
- $new_templates = apply_filters( 'bp_template_hierarchy_activity_directory', array(
83
- 'activity/index-directory.php'
84
- ) );
85
-
86
- // Merge new templates with existing stack
87
- // @see bp_get_theme_compat_templates().
88
- $templates = array_merge( (array) $new_templates, $templates );
89
-
90
- return $templates;
91
- }
92
-
93
- /**
94
- * Update the global $post with directory data.
95
- *
96
- * @since 1.7.0
97
- */
98
- public function directory_dummy_post() {
99
- bp_theme_compat_reset_post( array(
100
- 'ID' => 0,
101
- 'post_title' => bp_get_directory_title( 'activity' ),
102
- 'post_author' => 0,
103
- 'post_date' => 0,
104
- 'post_content' => '',
105
- 'post_type' => 'page',
106
- 'post_status' => 'publish',
107
- 'is_page' => true,
108
- 'comment_status' => 'closed'
109
- ) );
110
- }
111
-
112
- /**
113
- * Filter the_content with the groups index template part.
114
- *
115
- * @since 1.7.0
116
- */
117
- public function directory_content() {
118
- return bp_buffer_template_part( 'activity/index', null, false );
119
- }
120
-
121
- /** Single ****************************************************************/
122
-
123
- /**
124
- * Add custom template hierarchy to theme compat for activity permalink pages.
125
- *
126
- * This is to mirror how WordPress has {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
127
- *
128
- * @since 1.8.0
129
- *
130
- * @param string $templates The templates from bp_get_theme_compat_templates().
131
- * @return array $templates Array of custom templates to look for.
132
- */
133
- public function single_template_hierarchy( $templates ) {
134
-
135
- /**
136
- * Filters the template hierarchy for the activity permalink pages.
137
- *
138
- * @since 1.8.0
139
- *
140
- * @param array $index Array holding template names to be merged into template list.
141
- */
142
- $new_templates = apply_filters( 'bp_template_hierarchy_activity_single_item', array(
143
- 'activity/single/index.php'
144
- ) );
145
-
146
- // Merge new templates with existing stack
147
- // @see bp_get_theme_compat_templates().
148
- $templates = array_merge( (array) $new_templates, $templates );
149
-
150
- return $templates;
151
- }
152
-
153
- /**
154
- * Update the global $post with the displayed user's data.
155
- *
156
- * @since 1.7.0
157
- */
158
- public function single_dummy_post() {
159
- bp_theme_compat_reset_post( array(
160
- 'ID' => 0,
161
- 'post_title' => __( 'Activity', 'buddypress' ),
162
- 'post_author' => 0,
163
- 'post_date' => 0,
164
- 'post_content' => '',
165
- 'post_type' => 'page',
166
- 'post_status' => 'publish',
167
- 'is_page' => true,
168
- 'comment_status' => 'closed'
169
- ) );
170
- }
171
-
172
- /**
173
- * Filter the_content with the members' activity permalink template part.
174
- *
175
- * @since 1.7.0
176
- */
177
- public function single_dummy_content() {
178
- return bp_buffer_template_part( 'activity/single/home', null, false );
179
- }
180
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/classes/class-bp-akismet.php DELETED
@@ -1,651 +0,0 @@
1
- <?php
2
- /**
3
- * Akismet support for BuddyPress' Activity Stream.
4
- *
5
- * @package BuddyPress
6
- * @subpackage ActivityAkismet
7
- * @since 1.6.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- /**
14
- * Akismet support for the Activity component.
15
- *
16
- * @since 1.6.0
17
- * @since 2.3.0 We only support Akismet 3+.
18
- */
19
- class BP_Akismet {
20
-
21
- /**
22
- * The activity last marked as spam.
23
- *
24
- * @since 1.6.0
25
- * @var BP_Activity_Activity
26
- */
27
- protected $last_activity = null;
28
-
29
- /**
30
- * Constructor.
31
- *
32
- * @since 1.6.0
33
- */
34
- public function __construct() {
35
- $this->setup_actions();
36
- }
37
-
38
- /**
39
- * Hook Akismet into the activity stream.
40
- *
41
- * @since 1.6.0
42
- */
43
- protected function setup_actions() {
44
- // Add nonces to activity stream lists.
45
- add_action( 'bp_after_activity_post_form', array( $this, 'add_activity_stream_nonce' ) );
46
- add_action( 'bp_activity_entry_comments', array( $this, 'add_activity_stream_nonce' ) );
47
-
48
- // Add a "mark as spam" button to individual activity items.
49
- add_action( 'bp_activity_entry_meta', array( $this, 'add_activity_spam_button' ) );
50
- add_action( 'bp_activity_comment_options', array( $this, 'add_activity_comment_spam_button' ) );
51
-
52
- // Check activity for spam.
53
- add_action( 'bp_activity_before_save', array( $this, 'check_activity' ), 4, 1 );
54
-
55
- // Tidy up member's latest (activity) update.
56
- add_action( 'bp_activity_posted_update', array( $this, 'check_member_activity_update' ), 1, 3 );
57
-
58
- // Hooks to extend Activity core spam/ham functions for Akismet.
59
- add_action( 'bp_activity_mark_as_spam', array( $this, 'mark_as_spam' ), 10, 2 );
60
- add_action( 'bp_activity_mark_as_ham', array( $this, 'mark_as_ham' ), 10, 2 );
61
-
62
- // Hook into the Activity wp-admin screen.
63
- add_action( 'bp_activity_admin_comment_row_actions', array( $this, 'comment_row_action' ), 10, 2 );
64
- add_action( 'bp_activity_admin_load', array( $this, 'add_history_metabox' ) );
65
- }
66
-
67
- /**
68
- * Add a history item to the hover links in an activity's row.
69
- *
70
- * This function lifted with love from the Akismet WordPress plugin's
71
- * akismet_comment_row_action() function. Thanks!
72
- *
73
- * @since 1.6.0
74
- *
75
- * @param array $actions The hover links.
76
- * @param array $activity The activity for the current row being processed.
77
- * @return array The hover links.
78
- */
79
- function comment_row_action( $actions, $activity ) {
80
- $akismet_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_result' );
81
- $user_result = bp_activity_get_meta( $activity['id'], '_bp_akismet_user_result' );
82
- $desc = '';
83
-
84
- if ( !$user_result || $user_result == $akismet_result ) {
85
- // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same.
86
- if ( 'true' == $akismet_result && $activity['is_spam'] )
87
- $desc = __( 'Flagged as spam by Akismet', 'buddypress' );
88
-
89
- elseif ( 'false' == $akismet_result && !$activity['is_spam'] )
90
- $desc = __( 'Cleared by Akismet', 'buddypress' );
91
-
92
- } else {
93
- $who = bp_activity_get_meta( $activity['id'], '_bp_akismet_user' );
94
-
95
- if ( 'true' == $user_result )
96
- $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
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/css/mentions-rtl.css DELETED
@@ -1,92 +0,0 @@
1
- .atwho-view {
2
- background: rgba(204, 204, 204, 0.8);
3
- border-radius: 2px;
4
- border: 1px solid rgb(204, 204, 204);
5
- box-shadow: 0 0 5px rgba(204, 204, 204, 0.25), 0 0 1px #FFF;
6
- color: #D84800;
7
- display: none;
8
- font-family: sans-serif;
9
- margin-top: 18px;
10
- position: absolute;
11
- top: 0;
12
- z-index: 1000; /* >999 for wp-admin */
13
- }
14
- .atwho-view {
15
- left: 0;
16
- }
17
- .atwho-view ul {
18
- background: #FFF;
19
- list-style: none;
20
- margin: auto;
21
- padding: 0;
22
- }
23
- .atwho-view ul li {
24
- border-bottom: 1px solid #EFEFEF;
25
- box-sizing: content-box;
26
- cursor: pointer;
27
- display: block;
28
- font-size: 14px;
29
- height: 20px;
30
- line-height: 20px;
31
- margin: 0;
32
- overflow: hidden;
33
- padding: 5px 10px;
34
- }
35
- .atwho-view img {
36
- border-radius: 2px;
37
- float: left;
38
- height: 20px;
39
- margin-top:0;
40
- width: 20px;
41
- }
42
- .atwho-view strong {
43
- background: #EFEFEF;
44
- font-weight: bold;
45
- }
46
- .atwho-view .username strong {
47
- color: #D54E21;
48
- }
49
- .atwho-view small {
50
- color: #AAA;
51
- float: left;
52
- font-size: smaller;
53
- font-weight: normal;
54
- margin: 0 40px 0 10px;
55
- }
56
- .atwho-view .cur {
57
- background: rgba(239, 239, 239, 0.5);
58
- }
59
-
60
- @media (max-width: 900px) {
61
- .atwho-view img {
62
- float: right;
63
- margin: 0 0 0 10px;
64
- }
65
- }
66
- @media (max-width: 400px) {
67
- .atwho-view ul li {
68
- font-size: 16px;
69
- line-height: 23px;
70
- padding: 13px;
71
- }
72
- .atwho-view ul li img {
73
- height: 30px;
74
- margin-top: -5px;
75
- width: 30px;
76
- }
77
- .atwho-view {
78
- border-radius: 0;
79
- height: 100%;
80
- right: 0 !important;
81
- width: 100%;
82
- }
83
- .atwho-view ul li .username {
84
- display: inline-block;
85
- margin: -10px 0 0 0;
86
- padding: 10px 0;
87
- }
88
- .atwho-view ul li small {
89
- display: inline-block;
90
- margin-right: 20px;
91
- }
92
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/css/mentions-rtl.min.css DELETED
@@ -1 +0,0 @@
1
- .atwho-view{background:rgba(204,204,204,.8);border-radius:2px;border:1px solid #ccc;box-shadow:0 0 5px rgba(204,204,204,.25),0 0 1px #FFF;color:#D84800;display:none;font-family:sans-serif;margin-top:18px;position:absolute;top:0;z-index:1000;left:0}.atwho-view ul{background:#FFF;list-style:none;margin:auto;padding:0}.atwho-view ul li{border-bottom:1px solid #EFEFEF;box-sizing:content-box;cursor:pointer;display:block;font-size:14px;height:20px;line-height:20px;margin:0;overflow:hidden;padding:5px 10px}.atwho-view img{border-radius:2px;float:left;height:20px;margin-top:0;width:20px}.atwho-view strong{background:#EFEFEF;font-weight:700}.atwho-view .username strong{color:#D54E21}.atwho-view small{color:#AAA;float:left;font-size:smaller;font-weight:400;margin:0 40px 0 10px}.atwho-view .cur{background:rgba(239,239,239,.5)}@media (max-width:900px){.atwho-view img{float:right;margin:0 0 0 10px}}@media (max-width:400px){.atwho-view ul li{font-size:16px;line-height:23px;padding:13px}.atwho-view ul li img{height:30px;margin-top:-5px;width:30px}.atwho-view{border-radius:0;height:100%;right:0!important;width:100%}.atwho-view ul li .username{display:inline-block;margin:-10px 0 0;padding:10px 0}.atwho-view ul li small{display:inline-block;margin-right:20px}}
 
bp-activity/css/mentions.css DELETED
@@ -1,93 +0,0 @@
1
- .atwho-view {
2
- background: rgba(204, 204, 204, 0.8);
3
- border-radius: 2px;
4
- border: 1px solid rgb(204, 204, 204);
5
- box-shadow: 0 0 5px rgba(204, 204, 204, 0.25), 0 0 1px #FFF;
6
- color: #D84800;
7
- display: none;
8
- font-family: sans-serif;
9
- margin-top: 18px;
10
- position: absolute;
11
- top: 0;
12
- z-index: 1000; /* >999 for wp-admin */
13
- }
14
- /* rtl:ignore */
15
- .atwho-view {
16
- left: 0;
17
- }
18
- .atwho-view ul {
19
- background: #FFF;
20
- list-style: none;
21
- margin: auto;
22
- padding: 0;
23
- }
24
- .atwho-view ul li {
25
- border-bottom: 1px solid #EFEFEF;
26
- box-sizing: content-box;
27
- cursor: pointer;
28
- display: block;
29
- font-size: 14px;
30
- height: 20px;
31
- line-height: 20px;
32
- margin: 0;
33
- overflow: hidden;
34
- padding: 5px 10px;
35
- }
36
- .atwho-view img {
37
- border-radius: 2px;
38
- float: right;
39
- height: 20px;
40
- margin-top:0;
41
- width: 20px;
42
- }
43
- .atwho-view strong {
44
- background: #EFEFEF;
45
- font-weight: bold;
46
- }
47
- .atwho-view .username strong {
48
- color: #D54E21;
49
- }
50
- .atwho-view small {
51
- color: #AAA;
52
- float: right;
53
- font-size: smaller;
54
- font-weight: normal;
55
- margin: 0 10px 0 40px;
56
- }
57
- .atwho-view .cur {
58
- background: rgba(239, 239, 239, 0.5);
59
- }
60
-
61
- @media (max-width: 900px) {
62
- .atwho-view img {
63
- float: left;
64
- margin: 0 10px 0 0;
65
- }
66
- }
67
- @media (max-width: 400px) {
68
- .atwho-view ul li {
69
- font-size: 16px;
70
- line-height: 23px;
71
- padding: 13px;
72
- }
73
- .atwho-view ul li img {
74
- height: 30px;
75
- margin-top: -5px;
76
- width: 30px;
77
- }
78
- .atwho-view {
79
- border-radius: 0;
80
- height: 100%;
81
- left: 0 !important;
82
- width: 100%;
83
- }
84
- .atwho-view ul li .username {
85
- display: inline-block;
86
- margin: -10px 0 0 0;
87
- padding: 10px 0;
88
- }
89
- .atwho-view ul li small {
90
- display: inline-block;
91
- margin-left: 20px;
92
- }
93
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/css/mentions.min.css DELETED
@@ -1 +0,0 @@
1
- .atwho-view{background:rgba(204,204,204,.8);border-radius:2px;border:1px solid #ccc;box-shadow:0 0 5px rgba(204,204,204,.25),0 0 1px #FFF;color:#D84800;display:none;font-family:sans-serif;margin-top:18px;position:absolute;top:0;z-index:1000;left:0}.atwho-view ul{background:#FFF;list-style:none;margin:auto;padding:0}.atwho-view ul li{border-bottom:1px solid #EFEFEF;box-sizing:content-box;cursor:pointer;display:block;font-size:14px;height:20px;line-height:20px;margin:0;overflow:hidden;padding:5px 10px}.atwho-view img{border-radius:2px;float:right;height:20px;margin-top:0;width:20px}.atwho-view strong{background:#EFEFEF;font-weight:700}.atwho-view .username strong{color:#D54E21}.atwho-view small{color:#AAA;float:right;font-size:smaller;font-weight:400;margin:0 10px 0 40px}.atwho-view .cur{background:rgba(239,239,239,.5)}@media (max-width:900px){.atwho-view img{float:left;margin:0 10px 0 0}}@media (max-width:400px){.atwho-view ul li{font-size:16px;line-height:23px;padding:13px}.atwho-view ul li img{height:30px;margin-top:-5px;width:30px}.atwho-view{border-radius:0;height:100%;left:0!important;width:100%}.atwho-view ul li .username{display:inline-block;margin:-10px 0 0;padding:10px 0}.atwho-view ul li small{display:inline-block;margin-left:20px}}
 
bp-activity/js/mentions.js DELETED
@@ -1,255 +0,0 @@
1
- /* global bp */
2
-
3
- window.bp = window.bp || {};
4
-
5
- ( function( bp, $, undefined ) {
6
- var mentionsQueryCache = [],
7
- mentionsItem;
8
-
9
- bp.mentions = bp.mentions || {};
10
- bp.mentions.users = window.bp.mentions.users || [];
11
-
12
- if ( typeof window.BP_Suggestions === 'object' ) {
13
- bp.mentions.users = window.BP_Suggestions.friends || bp.mentions.users;
14
- }
15
-
16
- /**
17
- * Adds BuddyPress @mentions to form inputs.
18
- *
19
- * @param {array|object} options If array, becomes the suggestions' data source. If object, passed as config to $.atwho().
20
- * @since 2.1.0
21
- */
22
- $.fn.bp_mentions = function( options ) {
23
- if ( $.isArray( options ) ) {
24
- options = { data: options };
25
- }
26
-
27
- /**
28
- * Default options for at.js; see https://github.com/ichord/At.js/.
29
- */
30
- var suggestionsDefaults = {
31
- delay: 200,
32
- hide_without_suffix: true,
33
- insert_tpl: '</>${atwho-data-value}</>', // For contentEditable, the fake tags make jQuery insert a textNode.
34
- limit: 10,
35
- start_with_space: false,
36
- suffix: '',
37
-
38
- callbacks: {
39
- /**
40
- * Custom filter to only match the start of spaced words.
41
- * Based on the core/default one.
42
- *
43
- * @param {string} query
44
- * @param {array} data
45
- * @param {string} search_key
46
- * @return {array}
47
- * @since 2.1.0
48
- */
49
- filter: function( query, data, search_key ) {
50
- var item, _i, _len, _results = [],
51
- regxp = new RegExp( '^' + query + '| ' + query, 'ig' ); // start of string, or preceded by a space.
52
-
53
- for ( _i = 0, _len = data.length; _i < _len; _i++ ) {
54
- item = data[ _i ];
55
- if ( item[ search_key ].toLowerCase().match( regxp ) ) {
56
- _results.push( item );
57
- }
58
- }
59
-
60
- return _results;
61
- },
62
-
63
- /**
64
- * Removes some spaces around highlighted string and tweaks regex to allow spaces
65
- * (to match display_name). Based on the core default.
66
- *
67
- * @param {unknown} li
68
- * @param {string} query
69
- * @return {string}
70
- * @since 2.1.0
71
- */
72
- highlighter: function( li, query ) {
73
- if ( ! query ) {
74
- return li;
75
- }
76
-
77
- var regexp = new RegExp( '>(\\s*|[\\w\\s]*)(' + this.at.replace( '+', '\\+') + '?' + query.replace( '+', '\\+' ) + ')([\\w ]*)\\s*<', 'ig' );
78
- return li.replace( regexp, function( str, $1, $2, $3 ) {
79
- return '>' + $1 + '<strong>' + $2 + '</strong>' + $3 + '<';
80
- });
81
- },
82
-
83
- /**
84
- * Reposition the suggestion list dynamically.
85
- *
86
- * @param {unknown} offset
87
- * @since 2.1.0
88
- */
89
- before_reposition: function( offset ) {
90
- // get the iframe, if any, already applied with atwho
91
- var caret,
92
- line,
93
- iframeOffset,
94
- move,
95
- $view = $( '#atwho-ground-' + this.id + ' .atwho-view' ),
96
- $body = $( 'body' ),
97
- atwhoDataValue = this.$inputor.data( 'atwho' );
98
-
99
- if ( 'undefined' !== atwhoDataValue && 'undefined' !== atwhoDataValue.iframe && null !== atwhoDataValue.iframe ) {
100
- caret = this.$inputor.caret( 'offset', { iframe: atwhoDataValue.iframe } );
101
- // Caret.js no longer calculates iframe caret position from the window (it's now just within the iframe).
102
- // We need to get the iframe offset from the window and merge that into our object.
103
- iframeOffset = $( atwhoDataValue.iframe ).offset();
104
- if ( 'undefined' !== iframeOffset ) {
105
- caret.left += iframeOffset.left;
106
- caret.top += iframeOffset.top;
107
- }
108
- } else {
109
- caret = this.$inputor.caret( 'offset' );
110
- }
111
-
112
- // If the caret is past horizontal half, then flip it, yo
113
- if ( caret.left > ( $body.width() / 2 ) ) {
114
- $view.addClass( 'right' );
115
- move = caret.left - offset.left - this.view.$el.width();
116
- } else {
117
- $view.removeClass( 'right' );
118
- move = caret.left - offset.left + 1;
119
- }
120
-
121
- // If we're on a small screen, scroll to caret
122
- if ( $body.width() <= 400 ) {
123
- $( document ).scrollTop( caret.top - 6 );
124
- }
125
-
126
- // New position is under the caret (never above) and positioned to follow
127
- // Dynamic sizing based on the input area (remove 'px' from end)
128
- line = parseInt( this.$inputor.css( 'line-height' ).substr( 0, this.$inputor.css( 'line-height' ).length - 2 ), 10 );
129
- if ( !line || line < 5 ) { // sanity check, and catch no line-height
130
- line = 19;
131
- }
132
-
133
- offset.top = caret.top + line;
134
- offset.left += move;
135
- },
136
-
137
- /**
138
- * Override default behaviour which inserts junk tags in the WordPress Visual editor.
139
- *
140
- * @param {unknown} $inputor Element which we're inserting content into.
141
- * @param {string) content The content that will be inserted.
142
- * @param {string) suffix Applied to the end of the content string.
143
- * @return {string}
144
- * @since 2.1.0
145
- */
146
- inserting_wrapper: function( $inputor, content, suffix ) {
147
- return '' + content + suffix;
148
- }
149
- }
150
- },
151
-
152
- /**
153
- * Default options for our @mentions; see https://github.com/ichord/At.js/.
154
- */
155
- mentionsDefaults = {
156
- callbacks: {
157
- /**
158
- * If there are no matches for the query in this.data, then query BuddyPress.
159
- *
160
- * @param {string} query Partial @mention to search for.
161
- * @param {function} render_view Render page callback function.
162
- * @since 2.1.0
163
- */
164
- remote_filter: function( query, render_view ) {
165
- var self = $( this ),
166
- params = {};
167
-
168
- mentionsItem = mentionsQueryCache[ query ];
169
- if ( typeof mentionsItem === 'object' ) {
170
- render_view( mentionsItem );
171
- return;
172
- }
173
-
174
- if ( self.xhr ) {
175
- self.xhr.abort();
176
- }
177
-
178
- params = { 'action': 'bp_get_suggestions', 'term': query, 'type': 'members' };
179
-
180
- if ( $.isNumeric( this.$inputor.data( 'suggestions-group-id' ) ) ) {
181
- params['group-id'] = parseInt( this.$inputor.data( 'suggestions-group-id' ), 10 );
182
- }
183
-
184
- self.xhr = $.getJSON( ajaxurl, params )
185
- /**
186
- * Success callback for the @suggestions lookup.
187
- *
188
- * @param {object} response Details of users matching the query.
189
- * @since 2.1.0
190
- */
191
- .done(function( response ) {
192
- if ( ! response.success ) {
193
- return;
194
- }
195
-
196
- var data = $.map( response.data,
197
- /**
198
- * Create a composite index to determine ordering of results;
199
- * nicename matches will appear on top.
200
- *
201
- * @param {array} suggestion A suggestion's original data.
202
- * @return {array} A suggestion's new data.
203
- * @since 2.1.0
204
- */
205
- function( suggestion ) {
206
- suggestion.search = suggestion.search || suggestion.ID + ' ' + suggestion.name;
207
- return suggestion;
208
- }
209
- );
210
-
211
- mentionsQueryCache[ query ] = data;
212
- render_view( data );
213
- });
214
- }
215
- },
216
-
217
- data: $.map( options.data,
218
- /**
219
- * Create a composite index to search against of nicename + display name.
220
- * This will also determine ordering of results, so nicename matches will appear on top.
221
- *
222
- * @param {array} suggestion A suggestion's original data.
223
- * @return {array} A suggestion's new data.
224
- * @since 2.1.0
225
- */
226
- function( suggestion ) {
227
- suggestion.search = suggestion.search || suggestion.ID + ' ' + suggestion.name;
228
- return suggestion;
229
- }
230
- ),
231
-
232
- at: '@',
233
- search_key: 'search',
234
- tpl: '<li data-value="@${ID}"><img src="${image}" /><span class="username">@${ID}</span><small>${name}</small></li>'
235
- },
236
-
237
- opts = $.extend( true, {}, suggestionsDefaults, mentionsDefaults, options );
238
- return $.fn.atwho.call( this, opts );
239
- };
240
-
241
- $( document ).ready(function() {
242
- // Activity/reply, post comments, dashboard post 'text' editor.
243
- $( '.bp-suggestions, #comments form textarea, .wp-editor-area' ).bp_mentions( bp.mentions.users );
244
- });
245
-
246
- bp.mentions.tinyMCEinit = function() {
247
- if ( typeof window.tinyMCE === 'undefined' || window.tinyMCE.activeEditor === null || typeof window.tinyMCE.activeEditor === 'undefined' ) {
248
- return;
249
- } else {
250
- $( window.tinyMCE.activeEditor.contentDocument.activeElement )
251
- .atwho( 'setIframe', $( '.wp-editor-wrap iframe' )[0] )
252
- .bp_mentions( bp.mentions.users );
253
- }
254
- };
255
- })( bp, jQuery );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/js/mentions.min.js DELETED
@@ -1 +0,0 @@
1
- window.bp=window.bp||{},function(a,b,c){var d,e=[];a.mentions=a.mentions||{},a.mentions.users=window.bp.mentions.users||[],"object"==typeof window.BP_Suggestions&&(a.mentions.users=window.BP_Suggestions.friends||a.mentions.users),b.fn.bp_mentions=function(a){b.isArray(a)&&(a={data:a});var c={delay:200,hide_without_suffix:!0,insert_tpl:"</>${atwho-data-value}</>",limit:10,start_with_space:!1,suffix:"",callbacks:{filter:function(a,b,c){var d,e,f,g=[],h=new RegExp("^"+a+"| "+a,"ig");for(e=0,f=b.length;e<f;e++)d=b[e],d[c].toLowerCase().match(h)&&g.push(d);return g},highlighter:function(a,b){if(!b)return a;var c=new RegExp(">(\\s*|[\\w\\s]*)("+this.at.replace("+","\\+")+"?"+b.replace("+","\\+")+")([\\w ]*)\\s*<","ig");return a.replace(c,function(a,b,c,d){return">"+b+"<strong>"+c+"</strong>"+d+"<"})},before_reposition:function(a){var c,d,e,f,g=b("#atwho-ground-"+this.id+" .atwho-view"),h=b("body"),i=this.$inputor.data("atwho");"undefined"!==i&&"undefined"!==i.iframe&&null!==i.iframe?(c=this.$inputor.caret("offset",{iframe:i.iframe}),e=b(i.iframe).offset(),"undefined"!==e&&(c.left+=e.left,c.top+=e.top)):c=this.$inputor.caret("offset"),c.left>h.width()/2?(g.addClass("right"),f=c.left-a.left-this.view.$el.width()):(g.removeClass("right"),f=c.left-a.left+1),h.width()<=400&&b(document).scrollTop(c.top-6),d=parseInt(this.$inputor.css("line-height").substr(0,this.$inputor.css("line-height").length-2),10),(!d||d<5)&&(d=19),a.top=c.top+d,a.left+=f},inserting_wrapper:function(a,b,c){return""+b+c}}},f={callbacks:{remote_filter:function(a,c){var f=b(this),g={};return d=e[a],"object"==typeof d?void c(d):(f.xhr&&f.xhr.abort(),g={action:"bp_get_suggestions",term:a,type:"members"},b.isNumeric(this.$inputor.data("suggestions-group-id"))&&(g["group-id"]=parseInt(this.$inputor.data("suggestions-group-id"),10)),void(f.xhr=b.getJSON(ajaxurl,g).done(function(d){if(d.success){var f=b.map(d.data,function(a){return a.search=a.search||a.ID+" "+a.name,a});e[a]=f,c(f)}})))}},data:b.map(a.data,function(a){return a.search=a.search||a.ID+" "+a.name,a}),at:"@",search_key:"search",tpl:'<li data-value="@${ID}"><img src="${image}" /><span class="username">@${ID}</span><small>${name}</small></li>'},g=b.extend(!0,{},c,f,a);return b.fn.atwho.call(this,g)},b(document).ready(function(){b(".bp-suggestions, #comments form textarea, .wp-editor-area").bp_mentions(a.mentions.users)}),a.mentions.tinyMCEinit=function(){"undefined"!=typeof window.tinyMCE&&null!==window.tinyMCE.activeEditor&&"undefined"!=typeof window.tinyMCE.activeEditor&&b(window.tinyMCE.activeEditor.contentDocument.activeElement).atwho("setIframe",b(".wp-editor-wrap iframe")[0]).bp_mentions(a.mentions.users)}}(bp,jQuery);
 
bp-blogs/bp-blogs-actions.php CHANGED
@@ -1,32 +1,32 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Blogs Actions.
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsActions
7
- * @since 1.5.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Redirect to a random blog in the multisite network.
15
  *
16
- * @since 1.0.0
17
  */
18
  function bp_blogs_redirect_to_random_blog() {
19
 
20
- // Bail if not looking for a random blog.
21
  if ( ! bp_is_blogs_component() || ! isset( $_GET['random-blog'] ) )
22
  return;
23
 
24
- // Multisite is active so find a random blog.
25
  if ( is_multisite() ) {
26
  $blog = bp_blogs_get_random_blogs( 1, 1 );
27
  bp_core_redirect( get_home_url( $blog['blogs'][0]->blog_id ) );
28
 
29
- // No multisite and still called, always redirect to root.
30
  } else {
31
  bp_core_redirect( bp_core_get_root_domain() );
32
  }
1
  <?php
2
+
3
  /**
4
  * BuddyPress Blogs Actions.
5
  *
6
  * @package BuddyPress
7
  * @subpackage BlogsActions
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
  * Redirect to a random blog in the multisite network.
15
  *
16
+ * @since BuddyPress (1.0.0)
17
  */
18
  function bp_blogs_redirect_to_random_blog() {
19
 
20
+ // Bail if not looking for a random blog
21
  if ( ! bp_is_blogs_component() || ! isset( $_GET['random-blog'] ) )
22
  return;
23
 
24
+ // Multisite is active so find a random blog
25
  if ( is_multisite() ) {
26
  $blog = bp_blogs_get_random_blogs( 1, 1 );
27
  bp_core_redirect( get_home_url( $blog['blogs'][0]->blog_id ) );
28
 
29
+ // No multisite and still called, always redirect to root
30
  } else {
31
  bp_core_redirect( bp_core_get_root_domain() );
32
  }
bp-blogs/bp-blogs-activity.php CHANGED
@@ -1,127 +1,66 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Blogs Activity.
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsActivity
7
- * @since 1.5.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Register activity actions for the blogs component.
15
  *
16
- * @since 1.0.0
 
 
17
  *
18
  * @return bool|null Returns false if activity component is not active.
19
  */
20
  function bp_blogs_register_activity_actions() {
 
 
 
 
 
 
 
21
  if ( is_multisite() ) {
22
  bp_activity_set_action(
23
- buddypress()->blogs->id,
24
  'new_blog',
25
  __( 'New site created', 'buddypress' ),
26
- 'bp_blogs_format_activity_action_new_blog',
27
- __( 'New Sites', 'buddypress' ),
28
- array( 'activity', 'member' ),
29
- 0
30
  );
31
  }
32
 
33
- /**
34
- * Fires after the registry of the default blog component activity actions.
35
- *
36
- * @since 1.1.0
37
- */
38
- do_action( 'bp_blogs_register_activity_actions' );
39
- }
40
- add_action( 'bp_register_activity_actions', 'bp_blogs_register_activity_actions' );
41
-
42
- /**
43
- * Set up the tracking arguments for the 'post' post type.
44
- *
45
- * @since 2.5.0 This was moved out of the BP_Blogs_Component class.
46
- *
47
- * @see bp_activity_get_post_type_tracking_args() for information on parameters.
48
- *
49
- * @param object|null $params Tracking arguments.
50
- * @param string|int $post_type Post type to track.
51
- * @return object
52
- */
53
- function bp_blogs_register_post_tracking_args( $params = null, $post_type = 0 ) {
54
-
55
- /**
56
- * Filters the post types to track for the Blogs component.
57
- *
58
- * @since 1.5.0
59
- * @deprecated 2.3.0
60
- *
61
- * Make sure plugins still using 'bp_blogs_record_post_post_types'
62
- * to track their post types will generate new_blog_post activities
63
- * See https://buddypress.trac.wordpress.org/ticket/6306
64
- *
65
- * @param array $value Array of post types to track.
66
- */
67
- $post_types = apply_filters( 'bp_blogs_record_post_post_types', array( 'post' ) );
68
- $post_types_array = array_flip( $post_types );
69
-
70
- if ( ! isset( $post_types_array[ $post_type ] ) ) {
71
- return $params;
72
- }
73
 
74
- // Set specific params for the 'post' post type.
75
- $params->component_id = buddypress()->blogs->id;
76
- $params->action_id = 'new_blog_post';
77
- $params->admin_filter = __( 'New post published', 'buddypress' );
78
- $params->format_callback = 'bp_blogs_format_activity_action_new_blog_post';
79
- $params->front_filter = __( 'Posts', 'buddypress' );
80
- $params->contexts = array( 'activity', 'member' );
81
- $params->position = 5;
82
-
83
- if ( post_type_supports( $post_type, 'comments' ) ) {
84
- $params->comment_action_id = 'new_blog_comment';
85
-
86
- /**
87
- * Filters the post types to track for the Blogs component.
88
- *
89
- * @since 1.5.0
90
- * @deprecated 2.5.0
91
- *
92
- * Make sure plugins still using 'bp_blogs_record_comment_post_types'
93
- * to track comment about their post types will generate new_blog_comment activities
94
- * See https://buddypress.trac.wordpress.org/ticket/6306
95
- *
96
- * @param array $value Array of post types to track.
97
- */
98
- $comment_post_types = apply_filters( 'bp_blogs_record_comment_post_types', array( 'post' ) );
99
- $comment_post_types_array = array_flip( $comment_post_types );
100
-
101
- if ( isset( $comment_post_types_array[ $post_type ] ) ) {
102
- $params->comments_tracking = new stdClass();
103
- $params->comments_tracking->component_id = buddypress()->blogs->id;
104
- $params->comments_tracking->action_id = 'new_blog_comment';
105
- $params->comments_tracking->admin_filter = __( 'New post comment posted', 'buddypress' );
106
- $params->comments_tracking->format_callback = 'bp_blogs_format_activity_action_new_blog_comment';
107
- $params->comments_tracking->front_filter = __( 'Comments', 'buddypress' );
108
- $params->comments_tracking->contexts = array( 'activity', 'member' );
109
- $params->comments_tracking->position = 10;
110
- }
111
- }
112
 
113
- return $params;
114
  }
115
- add_filter( 'bp_activity_get_post_type_tracking_args', 'bp_blogs_register_post_tracking_args', 10, 2 );
116
 
117
  /**
118
  * Format 'new_blog' activity actions.
119
  *
120
- * @since 2.0.0
121
  *
122
- * @param string $action Static activity action.
123
- * @param object $activity Activity data object.
124
- * @return string
125
  */
126
  function bp_blogs_format_activity_action_new_blog( $action, $activity ) {
127
  $blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
@@ -129,7 +68,7 @@ function bp_blogs_format_activity_action_new_blog( $action, $activity ) {
129
 
130
  $action = sprintf( __( '%s created the site %s', 'buddypress' ), bp_core_get_userlink( $activity->user_id ), '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
131
 
132
- // Legacy filter - requires the BP_Blogs_Blog object.
133
  if ( has_filter( 'bp_blogs_activity_created_blog_action' ) ) {
134
  $user_blog = BP_Blogs_Blog::get_user_blog( $activity->user_id, $activity->item_id );
135
  if ( $user_blog ) {
@@ -141,25 +80,16 @@ function bp_blogs_format_activity_action_new_blog( $action, $activity ) {
141
  }
142
  }
143
 
144
- /**
145
- * Filters the new blog activity action for the new blog.
146
- *
147
- * @since 2.0.0
148
- *
149
- * @param string $action Constructed activity action.
150
- * @param object $activity Activity data object.
151
- */
152
  return apply_filters( 'bp_blogs_format_activity_action_new_blog', $action, $activity );
153
  }
154
 
155
  /**
156
  * Format 'new_blog_post' activity actions.
157
  *
158
- * @since 2.0.0
159
  *
160
- * @param string $action Static activity action.
161
- * @param object $activity Activity data object.
162
- * @return string Constructed activity action.
163
  */
164
  function bp_blogs_format_activity_action_new_blog_post( $action, $activity ) {
165
  $blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
@@ -173,75 +103,34 @@ function bp_blogs_format_activity_action_new_blog_post( $action, $activity ) {
173
  bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
174
  }
175
 
176
- /**
177
- * When the post is published we are faking an activity object
178
- * to which we add 2 properties :
179
- * - the post url
180
- * - the post title
181
- * This is done to build the 'post link' part of the activity
182
- * action string.
183
- * NB: in this case the activity has not yet been created.
184
- */
185
- if ( isset( $activity->post_url ) ) {
186
- $post_url = $activity->post_url;
187
-
188
- /**
189
- * The post_url property is not set, we need to build the url
190
- * thanks to the post id which is also saved as the secondary
191
- * item id property of the activity object.
192
- */
193
- } else {
194
- $post_url = add_query_arg( 'p', $activity->secondary_item_id, trailingslashit( $blog_url ) );
195
- }
196
 
197
- // Should be the case when the post has just been published.
198
- if ( isset( $activity->post_title ) ) {
199
- $post_title = $activity->post_title;
200
 
201
- // If activity already exists try to get the post title from activity meta.
202
- } else if ( ! empty( $activity->id ) ) {
203
- $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
204
- }
205
-
206
- /**
207
- * In case the post was published without a title
208
- * or the activity meta was not found.
209
- */
210
  if ( empty( $post_title ) ) {
211
- // Defaults to no title.
212
- $post_title = esc_html__( '(no title)', 'buddypress' );
213
-
214
  switch_to_blog( $activity->item_id );
215
 
216
  $post = get_post( $activity->secondary_item_id );
217
  if ( is_a( $post, 'WP_Post' ) ) {
218
- // Does the post have a title ?
219
- if ( ! empty( $post->post_title ) ) {
220
- $post_title = $post->post_title;
221
- }
222
-
223
- // Make sure the activity exists before saving the post title in activity meta.
224
- if ( ! empty( $activity->id ) ) {
225
- bp_activity_update_meta( $activity->id, 'post_title', $post_title );
226
- }
227
  }
228
 
229
  restore_current_blog();
230
  }
231
 
232
- // Build the 'post link' part of the activity action string.
233
- $post_link = '<a href="' . esc_url( $post_url ) . '">' . $post_title . '</a>';
234
 
235
  $user_link = bp_core_get_userlink( $activity->user_id );
236
 
237
- // Build the complete activity action string.
238
  if ( is_multisite() ) {
239
  $action = sprintf( __( '%1$s wrote a new post, %2$s, on the site %3$s', 'buddypress' ), $user_link, $post_link, '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
240
  } else {
241
  $action = sprintf( __( '%1$s wrote a new post, %2$s', 'buddypress' ), $user_link, $post_link );
242
  }
243
 
244
- // Legacy filter - requires the post object.
245
  if ( has_filter( 'bp_blogs_activity_new_post_action' ) ) {
246
  switch_to_blog( $activity->item_id );
247
  $post = get_post( $activity->secondary_item_id );
@@ -252,56 +141,20 @@ function bp_blogs_format_activity_action_new_blog_post( $action, $activity ) {
252
  }
253
  }
254
 
255
- /**
256
- * Filters the new blog post action for the new blog.
257
- *
258
- * @since 2.0.0
259
- *
260
- * @param string $action Constructed activity action.
261
- * @param object $activity Activity data object.
262
- */
263
  return apply_filters( 'bp_blogs_format_activity_action_new_blog_post', $action, $activity );
264
  }
265
 
266
  /**
267
  * Format 'new_blog_comment' activity actions.
268
  *
269
- * @since 2.0.0
270
  *
271
- * @param string $action Static activity action.
272
- * @param object $activity Activity data object.
273
- * @return string Constructed activity action.
274
  */
275
  function bp_blogs_format_activity_action_new_blog_comment( $action, $activity ) {
276
- /**
277
- * When the comment is published we are faking an activity object
278
- * to which we add 4 properties :
279
- * - the post url
280
- * - the post title
281
- * - the blog url
282
- * - the blog name
283
- * This is done to build the 'post link' part of the activity
284
- * action string.
285
- * NB: in this case the activity has not yet been created.
286
- */
287
-
288
- $blog_url = false;
289
-
290
- // Try to get the blog url from the activity object
291
- if ( isset( $activity->blog_url ) ) {
292
- $blog_url = $activity->blog_url;
293
- } else {
294
- $blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
295
- }
296
-
297
- $blog_name = false;
298
-
299
- // Try to get the blog name from the activity object
300
- if ( isset( $activity->blog_name ) ) {
301
- $blog_name = $activity->blog_name;
302
- } else {
303
- $blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
304
- }
305
 
306
  if ( empty( $blog_url ) || empty( $blog_name ) ) {
307
  $blog_url = get_home_url( $activity->item_id );
@@ -311,33 +164,10 @@ function bp_blogs_format_activity_action_new_blog_comment( $action, $activity )
311
  bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
312
  }
313
 
314
- $post_url = false;
315
-
316
- // Try to get the post url from the activity object
317
- if ( isset( $activity->post_url ) ) {
318
- $post_url = $activity->post_url;
319
 
320
- /**
321
- * The post_url property is not set, we need to build the url
322
- * thanks to the post id which is also saved as the secondary
323
- * item id property of the activity object.
324
- */
325
- } elseif ( ! empty( $activity->id ) ) {
326
- $post_url = bp_activity_get_meta( $activity->id, 'post_url' );
327
- }
328
-
329
- $post_title = false;
330
-
331
- // Should be the case when the comment has just been published
332
- if ( isset( $activity->post_title ) ) {
333
- $post_title = $activity->post_title;
334
-
335
- // If activity already exists try to get the post title from activity meta
336
- } elseif ( ! empty( $activity->id ) ) {
337
- $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
338
- }
339
-
340
- // Should only be empty at the time of post creation.
341
  if ( empty( $post_url ) || empty( $post_title ) ) {
342
  switch_to_blog( $activity->item_id );
343
 
@@ -358,7 +188,7 @@ function bp_blogs_format_activity_action_new_blog_comment( $action, $activity )
358
  restore_current_blog();
359
  }
360
 
361
- $post_link = '<a href="' . esc_url( $post_url ) . '">' . $post_title . '</a>';
362
  $user_link = bp_core_get_userlink( $activity->user_id );
363
 
364
  if ( is_multisite() ) {
@@ -367,7 +197,7 @@ function bp_blogs_format_activity_action_new_blog_comment( $action, $activity )
367
  $action = sprintf( __( '%1$s commented on the post, %2$s', 'buddypress' ), $user_link, $post_link );
368
  }
369
 
370
- // Legacy filter - requires the comment object.
371
  if ( has_filter( 'bp_blogs_activity_new_comment_action' ) ) {
372
  switch_to_blog( $activity->item_id );
373
  $comment = get_comment( $activity->secondary_item_id );
@@ -378,14 +208,6 @@ function bp_blogs_format_activity_action_new_blog_comment( $action, $activity )
378
  }
379
  }
380
 
381
- /**
382
- * Filters the new blog comment action for the new blog.
383
- *
384
- * @since 2.0.0
385
- *
386
- * @param string $action Constructed activity action.
387
- * @param object $activity Activity data object.
388
- */
389
  return apply_filters( 'bp_blogs_format_activity_action_new_blog_comment', $action, $activity );
390
  }
391
 
@@ -394,7 +216,7 @@ function bp_blogs_format_activity_action_new_blog_comment( $action, $activity )
394
  *
395
  * This reduces database overhead during the activity loop.
396
  *
397
- * @since 2.0.0
398
  *
399
  * @param array $activities Array of activity items.
400
  * @return array
@@ -425,11 +247,12 @@ add_filter( 'bp_activity_prefetch_object_data', 'bp_blogs_prefetch_activity_obje
425
  /**
426
  * Record blog-related activity to the activity stream.
427
  *
428
- * @since 1.0.0
429
  *
430
  * @see bp_activity_add() for description of parameters.
 
431
  *
432
- * @param array|string $args {
433
  * See {@link bp_activity_add()} for complete description of arguments.
434
  * The arguments listed here have different default values from
435
  * bp_activity_add().
@@ -438,12 +261,18 @@ add_filter( 'bp_activity_prefetch_object_data', 'bp_blogs_prefetch_activity_obje
438
  * @return int|bool On success, returns the activity ID. False on failure.
439
  */
440
  function bp_blogs_record_activity( $args = '' ) {
 
 
 
 
 
 
441
  $defaults = array(
442
  'user_id' => bp_loggedin_user_id(),
443
  'action' => '',
444
  'content' => '',
445
  'primary_link' => '',
446
- 'component' => buddypress()->blogs->id,
447
  'type' => false,
448
  'item_id' => false,
449
  'secondary_item_id' => false,
@@ -452,53 +281,39 @@ function bp_blogs_record_activity( $args = '' ) {
452
  );
453
 
454
  $r = wp_parse_args( $args, $defaults );
 
455
 
456
- if ( ! empty( $r['action'] ) ) {
 
 
457
 
458
- /**
459
- * Filters the action associated with activity for activity stream.
460
- *
461
- * @since 1.2.0
462
- *
463
- * @param string $value Action for the activity stream.
464
- */
465
- $r['action'] = apply_filters( 'bp_blogs_record_activity_action', $r['action'] );
466
- }
467
 
468
- if ( ! empty( $r['content'] ) ) {
469
-
470
- /**
471
- * Filters the content associated with activity for activity stream.
472
- *
473
- * @since 1.2.0
474
- *
475
- * @param string $value Generated summary from content for the activity stream.
476
- * @param string $value Content for the activity stream.
477
- * @param array $r Array of arguments used for the activity stream item.
478
- */
479
- $r['content'] = apply_filters( 'bp_blogs_record_activity_content', bp_activity_create_summary( $r['content'], $r ), $r['content'], $r );
480
- }
481
 
482
  // Check for an existing entry and update if one exists.
483
  $id = bp_activity_get_activity_id( array(
484
- 'user_id' => $r['user_id'],
485
- 'component' => $r['component'],
486
- 'type' => $r['type'],
487
- 'item_id' => $r['item_id'],
488
- 'secondary_item_id' => $r['secondary_item_id'],
489
  ) );
490
 
491
- return bp_activity_add( array( 'id' => $id, 'user_id' => $r['user_id'], 'action' => $r['action'], 'content' => $r['content'], 'primary_link' => $r['primary_link'], 'component' => $r['component'], 'type' => $r['type'], 'item_id' => $r['item_id'], 'secondary_item_id' => $r['secondary_item_id'], 'recorded_time' => $r['recorded_time'], 'hide_sitewide' => $r['hide_sitewide'] ) );
492
  }
493
 
494
  /**
495
  * Delete a blog-related activity stream item.
496
  *
497
- * @since 1.0.0
498
  *
499
  * @see bp_activity_delete() for description of parameters.
 
500
  *
501
- * @param array|string $args {
502
  * See {@link bp_activity_delete()} for complete description of arguments.
503
  * The arguments listed here have different default values from
504
  * bp_activity_add().
@@ -506,16 +321,31 @@ function bp_blogs_record_activity( $args = '' ) {
506
  * }
507
  * @return bool True on success, false on failure.
508
  */
509
- function bp_blogs_delete_activity( $args = '' ) {
510
- $r = bp_parse_args( $args, array(
 
 
 
 
 
 
511
  'item_id' => false,
512
- 'component' => buddypress()->blogs->id,
513
  'type' => false,
514
  'user_id' => false,
515
  'secondary_item_id' => false
516
- ) );
517
 
518
- bp_activity_delete_by_item_id( $r );
 
 
 
 
 
 
 
 
 
519
  }
520
 
521
  /**
@@ -529,9 +359,9 @@ function bp_blogs_delete_activity( $args = '' ) {
529
  * to blogmeta and checks the values in blogmeta instead. This is to prevent
530
  * multiple {@link switch_to_blog()} calls in the activity stream.
531
  *
532
- * @since 2.0.0
533
  *
534
- * @param object $activity The BP_Activity_Activity object.
535
  * @return bool
536
  */
537
  function bp_blogs_comments_open( $activity ) {
@@ -539,24 +369,24 @@ function bp_blogs_comments_open( $activity ) {
539
 
540
  $blog_id = $activity->item_id;
541
 
542
- // See if we've mirrored the close comments option before.
543
  $days_old = bp_blogs_get_blogmeta( $blog_id, 'close_comments_days_old' );
544
 
545
- // We've never cached these items before, so do it now.
546
  if ( '' === $days_old ) {
547
  switch_to_blog( $blog_id );
548
 
549
- // Use comments_open().
550
- remove_filter( 'comments_open', 'bp_comments_open', 10 );
551
  $open = comments_open( $activity->secondary_item_id );
552
  add_filter( 'comments_open', 'bp_comments_open', 10, 2 );
553
 
554
- // Might as well mirror values to blogmeta since we're here!
555
  $thread_depth = get_option( 'thread_comments' );
556
  if ( ! empty( $thread_depth ) ) {
557
  $thread_depth = get_option( 'thread_comments_depth' );
558
  } else {
559
- // Perhaps filter this?
560
  $thread_depth = 1;
561
  }
562
 
@@ -566,11 +396,11 @@ function bp_blogs_comments_open( $activity ) {
566
 
567
  restore_current_blog();
568
 
569
- // Check blogmeta and manually check activity item.
570
- // Basically a copy of _close_comments_for_old_post().
571
  } else {
572
 
573
- // Comments are closed.
574
  if ( 'closed' == bp_activity_get_meta( $activity->id, 'post_comment_status' ) ) {
575
  return false;
576
  }
@@ -584,8 +414,7 @@ function bp_blogs_comments_open( $activity ) {
584
  return $open;
585
  }
586
 
587
- /*
588
- Commenting out for now - needs some more thought...
589
  should we add the post type to activity meta?
590
 
591
  $post = get_post($post_id);
@@ -606,143 +435,6 @@ function bp_blogs_comments_open( $activity ) {
606
  return $open;
607
  }
608
 
609
- /** SITE TRACKING *******************************************************/
610
-
611
- /**
612
- * Add an activity entry for a newly-created site.
613
- *
614
- * Hooked to the 'bp_blogs_new_blog' action.
615
- *
616
- * @since 2.6.0
617
- *
618
- * @param BP_Blogs_Blog $recorded_blog Current site being recorded. Passed by reference.
619
- * @param bool $is_private Whether the current site being recorded is private.
620
- * @param bool $is_recorded Whether the current site was recorded.
621
- */
622
- function bp_blogs_record_activity_on_site_creation( $recorded_blog, $is_private, $is_recorded, $no_activity ) {
623
- // Only record this activity if the blog is public.
624
- if ( ! $is_private && ! $no_activity && bp_blogs_is_blog_trackable( $recorded_blog->blog_id, $recorded_blog->user_id ) ) {
625
- bp_blogs_record_activity( array(
626
- 'user_id' => $recorded_blog->user_id,
627
-
628
- /**
629
- * Filters the activity created blog primary link.
630
- *
631
- * @since 1.1.0
632
- *
633
- * @param string $value Blog primary link.
634
- * @param int $value Blog ID.
635
- */
636
- 'primary_link' => apply_filters( 'bp_blogs_activity_created_blog_primary_link', bp_blogs_get_blogmeta( $recorded_blog->blog_id, 'url' ), $recorded_blog->blog_id ),
637
- 'type' => 'new_blog',
638
- 'item_id' => $recorded_blog->blog_id
639
- ) );
640
- }
641
- }
642
- add_action( 'bp_blogs_new_blog', 'bp_blogs_record_activity_on_site_creation', 10, 4 );
643
-
644
- /**
645
- * Deletes the 'new_blog' activity entry when a site is deleted.
646
- *
647
- * @since 2.6.0
648
- *
649
- * @param int $blog_id Site ID.
650
- */
651
- function bp_blogs_delete_new_blog_activity_for_site( $blog_id, $user_id = 0 ) {
652
- $args = array(
653
- 'item_id' => $blog_id,
654
- 'component' => buddypress()->blogs->id,
655
- 'type' => 'new_blog'
656
- );
657
-
658
- /**
659
- * In the case a user is removed, make sure he is the author of the 'new_blog' activity
660
- * when trying to delete it.
661
- */
662
- if ( ! empty( $user_id ) ) {
663
- $args['user_id'] = $user_id;
664
- }
665
-
666
- bp_blogs_delete_activity( $args );
667
- }
668
- add_action( 'bp_blogs_remove_blog', 'bp_blogs_delete_new_blog_activity_for_site', 10, 1 );
669
- add_action( 'bp_blogs_remove_blog_for_user', 'bp_blogs_delete_new_blog_activity_for_site', 10, 2 );
670
-
671
- /**
672
- * Delete all 'blogs' activity items for a site when the site is deleted.
673
- *
674
- * @since 2.6.0
675
- *
676
- * @param int $blog_id Site ID.
677
- */
678
- function bp_blogs_delete_activity_for_site( $blog_id ) {
679
- bp_blogs_delete_activity( array(
680
- 'item_id' => $blog_id,
681
- 'component' => buddypress()->blogs->id,
682
- 'type' => false
683
- ) );
684
- }
685
- add_action( 'bp_blogs_remove_data_for_blog', 'bp_blogs_delete_activity_for_site' );
686
-
687
- /**
688
- * Remove a blog post activity item from the activity stream.
689
- *
690
- * @since 1.0.0
691
- *
692
- * @param int $post_id ID of the post to be removed.
693
- * @param int $blog_id Optional. Defaults to current blog ID.
694
- * @param int $user_id Optional. Defaults to the logged-in user ID. This param
695
- * is currently unused in the function (but is passed to hooks).
696
- * @return bool
697
- */
698
- function bp_blogs_remove_post( $post_id, $blog_id = 0, $user_id = 0 ) {
699
- global $wpdb;
700
-
701
- if ( empty( $wpdb->blogid ) ) {
702
- return false;
703
- }
704
-
705
- $post_id = (int) $post_id;
706
-
707
- if ( ! $blog_id ) {
708
- $blog_id = (int) $wpdb->blogid;
709
- }
710
-
711
- if ( ! $user_id ) {
712
- $user_id = bp_loggedin_user_id();
713
- }
714
-
715
- /**
716
- * Fires before removal of a blog post activity item from the activity stream.
717
- *
718
- * @since 1.5.0
719
- *
720
- * @param int $blog_id ID of the blog associated with the post that was removed.
721
- * @param int $post_id ID of the post that was removed.
722
- * @param int $user_id ID of the user having the blog removed for.
723
- */
724
- do_action( 'bp_blogs_before_remove_post', $blog_id, $post_id, $user_id );
725
-
726
- bp_blogs_delete_activity( array(
727
- 'item_id' => $blog_id,
728
- 'secondary_item_id' => $post_id,
729
- 'component' => buddypress()->blogs->id,
730
- 'type' => 'new_blog_post'
731
- ) );
732
-
733
- /**
734
- * Fires after removal of a blog post activity item from the activity stream.
735
- *
736
- * @since 1.0.0
737
- *
738
- * @param int $blog_id ID of the blog associated with the post that was removed.
739
- * @param int $post_id ID of the post that was removed.
740
- * @param int $user_id ID of the user having the blog removed for.
741
- */
742
- do_action( 'bp_blogs_remove_post', $blog_id, $post_id, $user_id );
743
- }
744
- add_action( 'delete_post', 'bp_blogs_remove_post' );
745
-
746
  /** POST COMMENT SYNCHRONIZATION ****************************************/
747
 
748
  /**
@@ -750,119 +442,93 @@ add_action( 'delete_post', 'bp_blogs_remove_post' );
750
  *
751
  * Note: This is only a one-way sync - activity comments -> blog comment.
752
  *
753
- * For blog post -> activity comment, see {@link bp_activity_post_type_comment()}.
754
  *
755
- * @since 2.0.0
756
- * @since 2.5.0 Allow custom post types to sync their comments with activity ones
757
  *
758
- * @param int $comment_id The activity ID for the posted activity comment.
759
- * @param array $params Parameters for the activity comment.
760
- * @param object $parent_activity Parameters of the parent activity item (in this case, the blog post).
761
  */
762
  function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_activity ) {
763
- // if parent activity isn't a post type having the buddypress-activity support, stop now!
764
- if ( ! bp_activity_type_supports( $parent_activity->type, 'post-type-comment-tracking' ) ) {
765
  return;
766
  }
767
 
768
- // If activity comments are disabled for blog posts, stop now!
769
  if ( bp_disable_blogforum_comments() ) {
770
  return;
771
  }
772
 
773
- // Do not sync if the activity comment was marked as spam.
774
- $activity = new BP_Activity_Activity( $comment_id );
775
- if ( $activity->is_spam ) {
776
- return;
777
- }
778
-
779
- // Get userdata.
780
  if ( $params['user_id'] == bp_loggedin_user_id() ) {
781
  $user = buddypress()->loggedin_user->userdata;
782
  } else {
783
  $user = bp_core_get_core_userdata( $params['user_id'] );
784
  }
785
 
786
- // Get associated post type and set default comment parent
787
- $post_type = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' );
788
- $comment_parent = 0;
789
-
790
- // See if a parent WP comment ID exists.
791
- if ( ! empty( $params['parent_id'] ) && ! empty( $post_type ) ) {
792
- $comment_parent = bp_activity_get_meta( $params['parent_id'], "bp_blogs_{$post_type}_comment_id" );
793
  }
794
 
795
- // Comment args.
796
  $args = array(
797
  'comment_post_ID' => $parent_activity->secondary_item_id,
798
  'comment_author' => bp_core_get_user_displayname( $params['user_id'] ),
799
  'comment_author_email' => $user->user_email,
800
  'comment_author_url' => bp_core_get_user_domain( $params['user_id'], $user->user_nicename, $user->user_login ),
801
  'comment_content' => $params['content'],
802
- 'comment_type' => '', // Could be interesting to add 'buddypress' here...
803
  'comment_parent' => (int) $comment_parent,
804
  'user_id' => $params['user_id'],
 
 
 
 
 
805
  'comment_approved' => 1
806
  );
807
 
808
- // Prevent separate activity entry being made.
809
- remove_action( 'comment_post', 'bp_activity_post_type_comment', 10 );
810
 
811
- // Handle multisite.
812
  switch_to_blog( $parent_activity->item_id );
813
 
814
- // Handle timestamps for the WP comment after we've switched to the blog.
815
  $args['comment_date'] = current_time( 'mysql' );
816
  $args['comment_date_gmt'] = current_time( 'mysql', 1 );
817
 
818
- // Post the comment.
819
  $post_comment_id = wp_insert_comment( $args );
820
 
821
- // Add meta to comment.
822
  add_comment_meta( $post_comment_id, 'bp_activity_comment_id', $comment_id );
823
 
824
- // Add meta to activity comment.
825
- if ( ! empty( $post_type ) ) {
826
- bp_activity_update_meta( $comment_id, "bp_blogs_{$post_type}_comment_id", $post_comment_id );
827
- }
828
 
829
- // Resave activity comment with WP comment permalink.
830
  //
831
  // in bp_blogs_activity_comment_permalink(), we change activity comment
832
  // permalinks to use the post comment link
833
  //
834
  // @todo since this is done after AJAX posting, the activity comment permalink
835
- // doesn't change on the front end until the next page refresh.
836
  $resave_activity = new BP_Activity_Activity( $comment_id );
837
  $resave_activity->primary_link = get_comment_link( $post_comment_id );
838
-
839
- /**
840
- * Now that the activity id exists and the post comment was created, we don't need to update
841
- * the content of the comment as there are no chances it has evolved.
842
- */
843
- remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
844
-
845
  $resave_activity->save();
846
 
847
- // Add the edit activity comment hook back.
848
- add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
849
-
850
- // Multisite again!
851
  restore_current_blog();
852
 
853
- // Add the comment hook back.
854
- add_action( 'comment_post', 'bp_activity_post_type_comment', 10, 2 );
855
-
856
- /**
857
- * Fires after activity comments have been synced and posted as blog comments.
858
- *
859
- * @since 2.0.0
860
- *
861
- * @param int $comment_id The activity ID for the posted activity comment.
862
- * @param array $args Array of args used for the comment syncing.
863
- * @param object $parent_activity Parameters of the blog post parent activity item.
864
- * @param object $user User data object for the blog comment.
865
- */
866
  do_action( 'bp_blogs_sync_add_from_activity_comment', $comment_id, $args, $parent_activity, $user );
867
  }
868
  add_action( 'bp_activity_comment_posted', 'bp_blogs_sync_add_from_activity_comment', 10, 3 );
@@ -874,124 +540,94 @@ add_action( 'bp_activity_comment_posted', 'bp_blogs_sync_add_from_activity_comme
874
  * of the 'bp_activity_delete_comment' action because we need to fetch the
875
  * activity comment children before they are deleted.
876
  *
877
- * @since 2.0.0
878
- * @since 2.5.0 Add the $delected parameter
879
  *
880
- * @param bool $retval Whether BuddyPress should continue or not.
881
- * @param int $parent_activity_id The parent activity ID for the activity comment.
882
- * @param int $activity_id The activity ID for the pending deleted activity comment.
883
- * @param bool $deleted Whether the comment was deleted or not.
884
- * @return bool
885
  */
886
- function bp_blogs_sync_delete_from_activity_comment( $retval, $parent_activity_id, $activity_id, &$deleted ) {
887
- // Check if parent activity is a blog post.
888
  $parent_activity = new BP_Activity_Activity( $parent_activity_id );
889
-
890
- // if parent activity isn't a post type having the buddypress-activity support, stop now!
891
- if ( ! bp_activity_type_supports( $parent_activity->type, 'post-type-comment-tracking' ) ) {
892
  return $retval;
893
  }
894
 
895
- // Fetch the activity comments for the activity item.
896
  $activity = bp_activity_get( array(
897
  'in' => $activity_id,
898
  'display_comments' => 'stream',
899
- 'spam' => 'all',
900
  ) );
901
 
902
- // Get all activity comment IDs for the pending deleted item.
903
  $activity_ids = bp_activity_recurse_comments_activity_ids( $activity );
904
  $activity_ids[] = $activity_id;
905
 
906
- // Handle multisite
907
- // switch to the blog where the comment was made.
908
  switch_to_blog( $parent_activity->item_id );
909
 
910
- // Remove associated blog comments.
911
  bp_blogs_remove_associated_blog_comments( $activity_ids, current_user_can( 'moderate_comments' ) );
912
 
913
- // Multisite again!
914
  restore_current_blog();
915
 
916
- // Rebuild activity comment tree
917
- // emulate bp_activity_delete_comment().
918
  BP_Activity_Activity::rebuild_activity_comment_tree( $parent_activity_id );
919
 
920
- // Avoid the error message although the comments were successfully deleted
921
- $deleted = true;
922
-
923
- // We're overriding the default bp_activity_delete_comment() functionality
924
- // so we need to return false.
925
  return false;
926
  }
927
- add_filter( 'bp_activity_delete_comment_pre', 'bp_blogs_sync_delete_from_activity_comment', 10, 4 );
928
 
929
  /**
930
  * Updates the blog comment when the associated activity comment is edited.
931
  *
932
- * @since 2.0.0
933
  *
934
  * @param BP_Activity_Activity $activity The activity object.
935
  */
936
  function bp_blogs_sync_activity_edit_to_post_comment( BP_Activity_Activity $activity ) {
937
- // This is a new entry, so stop!
938
- // We only want edits!
939
- if ( empty( $activity->id ) || bp_disable_blogforum_comments() ) {
940
  return;
941
  }
942
 
943
- // fetch parent activity item
944
- $parent_activity = new BP_Activity_Activity( $activity->item_id );
945
-
946
- // if parent activity isn't a post type having the buddypress-activity support for comments, stop now!
947
- if ( ! bp_activity_type_supports( $parent_activity->type, 'post-type-comment-tracking' ) ) {
948
  return;
949
  }
950
 
951
- $post_type = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' );
 
952
 
953
- // No associated post type for this activity comment, stop.
954
- if ( ! $post_type ) {
 
 
955
  return;
956
  }
957
 
958
- // Try to see if a corresponding blog comment exists.
959
- $post_comment_id = bp_activity_get_meta( $activity->id, "bp_blogs_{$post_type}_comment_id" );
960
 
961
- if ( empty( $post_comment_id ) ) {
 
962
  return;
963
  }
964
 
965
- // Handle multisite.
966
  switch_to_blog( $parent_activity->item_id );
967
 
968
- // Get the comment status
969
- $post_comment_status = wp_get_comment_status( $post_comment_id );
970
- $old_comment_status = $post_comment_status;
971
-
972
- // No need to edit the activity, as it's the activity who's updating the comment
973
- remove_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10 );
974
- remove_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment', 10 );
975
-
976
- if ( 1 === $activity->is_spam && 'spam' !== $post_comment_status ) {
977
- wp_spam_comment( $post_comment_id );
978
- } elseif ( ! $activity->is_spam ) {
979
- if ( 'spam' === $post_comment_status ) {
980
- wp_unspam_comment( $post_comment_id );
981
- } elseif ( 'trash' === $post_comment_status ) {
982
- wp_untrash_comment( $post_comment_id );
983
- } else {
984
- // Update the blog post comment.
985
- wp_update_comment( array(
986
- 'comment_ID' => $post_comment_id,
987
- 'comment_content' => $activity->content,
988
- ) );
989
- }
990
- }
991
-
992
- // Restore actions
993
- add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
994
- add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment', 10, 4 );
995
 
996
  restore_current_blog();
997
  }
@@ -1007,111 +643,19 @@ add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comm
1007
  * Since these activity entries are deleted, we need to remove the deleted
1008
  * activity comment IDs from each comment's meta when a post is trashed.
1009
  *
1010
- * @since 2.0.0
1011
  *
1012
- * @param int $post_id The post ID.
1013
- * @param array $comments Array of comment statuses. The key is comment ID, the
1014
- * value is the $comment->comment_approved value.
1015
  */
1016
- function bp_blogs_remove_activity_meta_for_trashed_comments( $post_id = 0, $comments = array() ) {
1017
- if ( ! empty( $comments ) ) {
1018
- foreach ( array_keys( $comments ) as $comment_id ) {
1019
- delete_comment_meta( $comment_id, 'bp_activity_comment_id' );
1020
- }
1021
  }
1022
  }
1023
  add_action( 'trashed_post_comments', 'bp_blogs_remove_activity_meta_for_trashed_comments', 10, 2 );
1024
 
1025
- /**
1026
- * Filter 'new_blog_comment' bp_has_activities() loop to include new- and old-style blog activity comment items.
1027
- *
1028
- * In BuddyPress 2.0, the schema for storing activity items related to blog
1029
- * posts changed. Instead creating new top-level 'new_blog_comment' activity
1030
- * items, blog comments are recorded in the activity stream as comments on the
1031
- * 'new_blog_post' activity items corresponding to the parent post. This filter
1032
- * ensures that the 'new_blog_comment' filter in bp_has_activities() (which
1033
- * powers the 'Comments' filter in the activity directory dropdown) includes
1034
- * both old-style and new-style activity comments.
1035
- *
1036
- * @since 2.1.0
1037
- * @since 2.5.0 Used for any synced Post type comments, in wp-admin or front-end contexts.
1038
- *
1039
- * @param array $args Arguments passed from bp_parse_args() in bp_has_activities().
1040
- * @return array $args
1041
- */
1042
- function bp_blogs_new_blog_comment_query_backpat( $args ) {
1043
- global $wpdb;
1044
- $bp = buddypress();
1045
-
1046
- // If activity comments are disabled for blog posts, stop now!
1047
- if ( bp_disable_blogforum_comments() ) {
1048
- return $args;
1049
- }
1050
-
1051
- // Get the associated post type
1052
- $post_type = bp_activity_post_type_get_tracking_arg( $args['action'], 'post_type' );
1053
-
1054
- // Bail if this is not an activity associated with a post type
1055
- if ( empty( $post_type ) ) {
1056
- return $args;
1057
- }
1058
-
1059
- // Bail if this is an activity about posts and not comments
1060
- if ( bp_activity_post_type_get_tracking_arg( $args['action'], 'comment_action_id' ) ) {
1061
- return $args;
1062
- }
1063
-
1064
- // Comment synced ?
1065
- $activity_ids = $wpdb->get_col( $wpdb->prepare( "SELECT activity_id FROM {$bp->activity->table_name_meta} WHERE meta_key = %s", "bp_blogs_{$post_type}_comment_id" ) );
1066
-
1067
- if ( empty( $activity_ids ) ) {
1068
- return $args;
1069
- }
1070
-
1071
- // Init the filter query.
1072
- $filter_query = array();
1073
-
1074
- if ( ! isset( $args['scope'] ) || 'null' === $args['scope'] ) {
1075
- $args['scope'] = '';
1076
- } elseif ( 'just-me' === $args['scope'] ) {
1077
- $filter_query = array(
1078
- 'relation' => 'AND',
1079
- array(
1080
- 'column' => 'user_id',
1081
- 'value' => bp_displayed_user_id(),
1082
- ),
1083
- );
1084
- $args['scope'] = '';
1085
- }
1086
-
1087
- $filter_query[] = array(
1088
- 'relation' => 'OR',
1089
- array(
1090
- 'column' => 'type',
1091
- 'value' => $args['action'],
1092
- ),
1093
- array(
1094
- 'column' => 'id',
1095
- 'value' => $activity_ids,
1096
- 'compare' => 'IN'
1097
- ),
1098
- );
1099
-
1100
- $args['filter_query'] = $filter_query;
1101
-
1102
- // Make sure to have comment in stream mode && avoid duplicate content.
1103
- $args['display_comments'] = 'stream';
1104
-
1105
- // Finally reset the action.
1106
- $args['action'] = '';
1107
- $args['type'] = '';
1108
-
1109
- // Return the original arguments.
1110
- return $args;
1111
- }
1112
- add_filter( 'bp_after_has_activities_parse_args', 'bp_blogs_new_blog_comment_query_backpat' );
1113
- add_filter( 'bp_activity_list_table_filter_activity_type_items', 'bp_blogs_new_blog_comment_query_backpat' );
1114
-
1115
  /**
1116
  * Utility function to set up some variables for use in the activity loop.
1117
  *
@@ -1120,20 +664,20 @@ add_filter( 'bp_activity_list_table_filter_activity_type_items', 'bp_blogs_new_b
1120
  *
1121
  * This is to prevent having to requery these items later on.
1122
  *
1123
- * @since 2.0.0
1124
  *
1125
  * @see bp_blogs_disable_activity_commenting()
1126
  * @see bp_blogs_setup_comment_loop_globals_on_ajax()
1127
  *
1128
- * @param object $activity The BP_Activity_Activity object.
1129
  */
1130
  function bp_blogs_setup_activity_loop_globals( $activity ) {
1131
  if ( ! is_object( $activity ) ) {
1132
  return;
1133
  }
1134
 
1135
- // The activity type does not support comments or replies ? stop now!
1136
- if ( ! bp_activity_type_supports( $activity->type, 'post-type-comment-reply' ) ) {
1137
  return;
1138
  }
1139
 
@@ -1141,7 +685,7 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1141
  return;
1142
  }
1143
 
1144
- // If we've already done this before, stop now!
1145
  if ( isset( buddypress()->blogs->allow_comments[ $activity->id ] ) ) {
1146
  return;
1147
  }
@@ -1149,8 +693,8 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1149
  $allow_comments = bp_blogs_comments_open( $activity );
1150
  $thread_depth = bp_blogs_get_blogmeta( $activity->item_id, 'thread_comments_depth' );
1151
 
1152
- // Initialize a local object so we won't have to query this again in the
1153
- // comment loop.
1154
  if ( empty( buddypress()->blogs->allow_comments ) ) {
1155
  buddypress()->blogs->allow_comments = array();
1156
  }
@@ -1158,7 +702,7 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1158
  buddypress()->blogs->thread_depth = array();
1159
  }
1160
 
1161
- // Cache comment settings in the buddypress() singleton to reference later in
1162
  // the activity comment loop
1163
  // @see bp_blogs_disable_activity_replies()
1164
  //
@@ -1172,12 +716,12 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1172
  /**
1173
  * Set up some globals used in the activity comment loop when AJAX is used.
1174
  *
1175
- * @since 2.0.0
1176
  *
1177
  * @see bp_blogs_setup_activity_loop_globals()
1178
  */
1179
  function bp_blogs_setup_comment_loop_globals_on_ajax() {
1180
- // Not AJAX? stop now!
1181
  if ( ! defined( 'DOING_AJAX' ) ) {
1182
  return;
1183
  }
@@ -1185,11 +729,11 @@ function bp_blogs_setup_comment_loop_globals_on_ajax() {
1185
  return;
1186
  }
1187
 
1188
- // Get the parent activity item.
1189
  $comment = bp_activity_current_comment();
1190
  $parent_activity = new BP_Activity_Activity( $comment->item_id );
1191
 
1192
- // Setup the globals.
1193
  bp_blogs_setup_activity_loop_globals( $parent_activity );
1194
  }
1195
  add_action( 'bp_before_activity_comment', 'bp_blogs_setup_comment_loop_globals_on_ajax' );
@@ -1204,78 +748,47 @@ add_action( 'bp_before_activity_comment', 'bp_blogs_setup_comment_loop_globals_o
1204
  * based on a certain age
1205
  * - the activity entry is a 'new_blog_comment' type
1206
  *
1207
- * @since 2.0.0
1208
  *
1209
- * @param bool $retval Is activity commenting enabled for this activity entry.
1210
  * @return bool
1211
  */
1212
  function bp_blogs_disable_activity_commenting( $retval ) {
1213
- global $activities_template;
1214
-
1215
- // If activity commenting is disabled, return current value.
1216
- if ( bp_disable_blogforum_comments() || ! isset( $activities_template->in_the_loop ) ) {
1217
  return $retval;
1218
  }
1219
 
1220
- $type = bp_get_activity_type();
 
1221
 
1222
- // It's a post type supporting comment tracking.
1223
- if ( bp_activity_type_supports( $type, 'post-type-comment-tracking' ) ) {
1224
- // The activity type is supporting comments or replies
1225
- if ( bp_activity_type_supports( $type, 'post-type-comment-reply' ) ) {
1226
- // Setup some globals we'll need to reference later.
1227
- bp_blogs_setup_activity_loop_globals( $activities_template->activity );
1228
-
1229
- // If comments are closed for the WP blog post, we should disable
1230
- // activity comments for this activity entry.
1231
- if ( empty( buddypress()->blogs->allow_comments[ bp_get_activity_id() ] ) ) {
1232
- $retval = false;
1233
- }
1234
- // The activity type does not support comments or replies
1235
- } else {
1236
  $retval = false;
1237
- }
1238
- }
1239
 
1240
- return $retval;
1241
- }
1242
- add_filter( 'bp_activity_can_comment', 'bp_blogs_disable_activity_commenting' );
1243
 
1244
- /**
1245
- * Limit the display of post type synced comments.
1246
- *
1247
- * @since 2.5.0
1248
- *
1249
- * When viewing the synced comments in stream mode, this prevents comments to
1250
- * be displayed twice, and avoids a Javascript error as the form to add replies
1251
- * is not available.
1252
- *
1253
- * @param int $retval The comment count for the activity.
1254
- * @return int The comment count, or 0 to hide activity comment replies.
1255
- */
1256
- function bp_blogs_post_type_comments_avoid_duplicates( $retval ) {
1257
- /**
1258
- * Only limit the display when Post type comments are synced with
1259
- * activity comments.
1260
- */
1261
- if ( bp_disable_blogforum_comments() ) {
1262
- return $retval;
1263
- }
1264
 
1265
- if ( 'activity_comment' !== bp_get_activity_type() ) {
1266
- return $retval;
1267
- }
1268
 
1269
- // Check the parent activity
1270
- $parent_activity = new BP_Activity_Activity( bp_get_activity_item_id() );
 
 
 
1271
 
1272
- if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
1273
- $retval = 0;
1274
  }
1275
 
1276
  return $retval;
1277
  }
1278
- add_filter( 'bp_activity_get_comment_count', 'bp_blogs_post_type_comments_avoid_duplicates' );
1279
 
1280
  /**
1281
  * Check if an activity comment associated with a blog post can be replied to.
@@ -1286,11 +799,10 @@ add_filter( 'bp_activity_get_comment_count', 'bp_blogs_post_type_comments_avoid_
1286
  * This check uses a locally-cached value set in {@link bp_blogs_disable_activity_commenting()}
1287
  * via {@link bp_blogs_setup_activity_loop_globals()}.
1288
  *
1289
- * @since 2.0.0
1290
- *
1291
- * @param bool $retval Are replies allowed for this activity reply.
1292
- * @param object|array $comment The activity comment object.
1293
  *
 
 
1294
  * @return bool
1295
  */
1296
  function bp_blogs_can_comment_reply( $retval, $comment ) {
@@ -1298,17 +810,17 @@ function bp_blogs_can_comment_reply( $retval, $comment ) {
1298
  $comment = (object) $comment;
1299
  }
1300
 
1301
- // Check comment depth and disable if depth is too large.
1302
  if ( isset( buddypress()->blogs->thread_depth[$comment->item_id] ) ){
1303
- if ( bp_activity_get_comment_depth( $comment ) >= buddypress()->blogs->thread_depth[$comment->item_id] ) {
1304
  $retval = false;
1305
  }
1306
  }
1307
 
1308
- // Check if we should disable activity replies based on the parent activity.
1309
  if ( isset( buddypress()->blogs->allow_comments[$comment->item_id] ) ){
1310
- // The blog post has closed off commenting, so we should disable all activity
1311
- // comments under the parent 'new_blog_post' activity entry.
1312
  if ( empty( buddypress()->blogs->allow_comments[$comment->item_id] ) ) {
1313
  $retval = false;
1314
  }
@@ -1325,21 +837,15 @@ add_filter( 'bp_activity_can_comment_reply', 'bp_blogs_can_comment_reply', 10, 2
1325
  * This is only done if activity commenting is allowed and whether the parent
1326
  * activity item is a 'new_blog_post' entry.
1327
  *
1328
- * @since 2.0.0
1329
  *
1330
- * @param string $retval The activity comment permalink.
1331
  * @return string
1332
  */
1333
- function bp_blogs_activity_comment_permalink( $retval = '' ) {
1334
  global $activities_template;
1335
 
1336
- // Get the current comment ID.
1337
- $item_id = isset( $activities_template->activity->current_comment->item_id )
1338
- ? $activities_template->activity->current_comment->item_id
1339
- : false;
1340
-
1341
- // Maybe adjust the link if item ID exists.
1342
- if ( ( false !== $item_id ) && isset( buddypress()->blogs->allow_comments[ $item_id ] ) ) {
1343
  $retval = $activities_template->activity->current_comment->primary_link;
1344
  }
1345
 
@@ -1352,10 +858,10 @@ add_filter( 'bp_get_activity_comment_permalink', 'bp_blogs_activity_comment_perm
1352
  *
1353
  * This is only done if the activity comment is associated with a blog comment.
1354
  *
1355
- * @since 2.0.1
1356
  *
1357
- * @param string $retval The activity permalink.
1358
- * @param BP_Activity_Activity $activity Activity object.
1359
  * @return string
1360
  */
1361
  function bp_blogs_activity_comment_single_permalink( $retval, $activity ) {
@@ -1363,13 +869,9 @@ function bp_blogs_activity_comment_single_permalink( $retval, $activity ) {
1363
  return $retval;
1364
  }
1365
 
1366
- if ( bp_disable_blogforum_comments() ) {
1367
- return $retval;
1368
- }
1369
-
1370
- $parent_activity = new BP_Activity_Activity( $activity->item_id );
1371
 
1372
- if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
1373
  $retval = $activity->primary_link;
1374
  }
1375
 
@@ -1382,10 +884,10 @@ add_filter( 'bp_activity_get_permalink', 'bp_blogs_activity_comment_single_perma
1382
  *
1383
  * This is only done if the activity comment is associated with a blog comment.
1384
  *
1385
- * @since 2.0.1
1386
  *
1387
- * @param string $retval The activity action.
1388
- * @param BP_Activity_Activity $activity Activity object.
1389
  * @return string
1390
  */
1391
  function bp_blogs_activity_comment_single_action( $retval, $activity ) {
@@ -1393,52 +895,23 @@ function bp_blogs_activity_comment_single_action( $retval, $activity ) {
1393
  return $retval;
1394
  }
1395
 
1396
- if ( bp_disable_blogforum_comments() ) {
1397
- return $retval;
1398
- }
1399
-
1400
- $parent_activity = new BP_Activity_Activity( $activity->item_id );
1401
-
1402
- if ( ! isset( $parent_activity->type ) ) {
1403
- return $retval;
1404
- }
1405
-
1406
- $post_type = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' );
1407
-
1408
- if ( ! $post_type ) {
1409
- return $retval;
1410
- }
1411
-
1412
- $blog_comment_id = bp_activity_get_meta( $activity->id, "bp_blogs_{$post_type}_comment_id" );
1413
 
1414
  if ( ! empty( $blog_comment_id ) ) {
1415
- $bp = buddypress();
1416
-
1417
- // Check if a comment action id is set for the parent activity
1418
- $comment_action_id = bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'comment_action_id' );
1419
-
1420
- // Use the action string callback for the activity type
1421
- if ( ! empty( $comment_action_id ) ) {
1422
- // Fake a 'new_{post_type}_comment' by cloning the activity object.
1423
- $object = clone $activity;
1424
 
1425
- // Set the type of the activity to be a comment about a post type
1426
- $object->type = $comment_action_id;
1427
 
1428
- // Use the blog ID as the item_id.
1429
- $object->item_id = $parent_activity->item_id;
1430
 
1431
- // Use comment ID as the secondary_item_id.
1432
- $object->secondary_item_id = $blog_comment_id;
1433
 
1434
- // Get the format callback for this activity comment
1435
- $format_callback = bp_activity_post_type_get_tracking_arg( $comment_action_id, 'format_callback' );
1436
-
1437
- // now format the activity action using the 'new_{post_type}_comment' action callback
1438
- if ( is_callable( $format_callback ) ) {
1439
- $retval = call_user_func_array( $format_callback, array( '', $object ) );
1440
- }
1441
- }
1442
  }
1443
 
1444
  return $retval;
1
  <?php
2
+
3
  /**
4
  * BuddyPress Blogs Activity.
5
  *
6
  * @package BuddyPress
7
  * @subpackage BlogsActivity
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
  * Register activity actions for the blogs component.
15
  *
16
+ * @since BuddyPress (1.0.0)
17
+ *
18
+ * @global object $bp The BuddyPress global settings object.
19
  *
20
  * @return bool|null Returns false if activity component is not active.
21
  */
22
  function bp_blogs_register_activity_actions() {
23
+ global $bp;
24
+
25
+ // Bail if activity is not active
26
+ if ( ! bp_is_active( 'activity' ) ) {
27
+ return false;
28
+ }
29
+
30
  if ( is_multisite() ) {
31
  bp_activity_set_action(
32
+ $bp->blogs->id,
33
  'new_blog',
34
  __( 'New site created', 'buddypress' ),
35
+ 'bp_blogs_format_activity_action_new_blog'
 
 
 
36
  );
37
  }
38
 
39
+ bp_activity_set_action(
40
+ $bp->blogs->id,
41
+ 'new_blog_post',
42
+ __( 'New post published', 'buddypress' ),
43
+ 'bp_blogs_format_activity_action_new_blog_post'
44
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ bp_activity_set_action(
47
+ $bp->blogs->id,
48
+ 'new_blog_comment',
49
+ __( 'New post comment posted', 'buddypress' ),
50
+ 'bp_blogs_format_activity_action_new_blog_comment'
51
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ do_action( 'bp_blogs_register_activity_actions' );
54
  }
55
+ add_action( 'bp_register_activity_actions', 'bp_blogs_register_activity_actions' );
56
 
57
  /**
58
  * Format 'new_blog' activity actions.
59
  *
60
+ * @since BuddyPress (2.0.0)
61
  *
62
+ * @param string $action Static activity action.
63
+ * @param obj $activity Activity data object.
 
64
  */
65
  function bp_blogs_format_activity_action_new_blog( $action, $activity ) {
66
  $blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
68
 
69
  $action = sprintf( __( '%s created the site %s', 'buddypress' ), bp_core_get_userlink( $activity->user_id ), '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
70
 
71
+ // Legacy filter - requires the BP_Blogs_Blog object
72
  if ( has_filter( 'bp_blogs_activity_created_blog_action' ) ) {
73
  $user_blog = BP_Blogs_Blog::get_user_blog( $activity->user_id, $activity->item_id );
74
  if ( $user_blog ) {
80
  }
81
  }
82
 
 
 
 
 
 
 
 
 
83
  return apply_filters( 'bp_blogs_format_activity_action_new_blog', $action, $activity );
84
  }
85
 
86
  /**
87
  * Format 'new_blog_post' activity actions.
88
  *
89
+ * @since BuddyPress (2.0.0)
90
  *
91
+ * @param string $action Static activity action.
92
+ * @param obj $activity Activity data object.
 
93
  */
94
  function bp_blogs_format_activity_action_new_blog_post( $action, $activity ) {
95
  $blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
103
  bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
104
  }
105
 
106
+ $post_url = add_query_arg( 'p', $activity->secondary_item_id, trailingslashit( $blog_url ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
+ $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
 
 
109
 
110
+ // Should only be empty at the time of post creation
 
 
 
 
 
 
 
 
111
  if ( empty( $post_title ) ) {
 
 
 
112
  switch_to_blog( $activity->item_id );
113
 
114
  $post = get_post( $activity->secondary_item_id );
115
  if ( is_a( $post, 'WP_Post' ) ) {
116
+ $post_title = $post->post_title;
117
+ bp_activity_update_meta( $activity->id, 'post_title', $post_title );
 
 
 
 
 
 
 
118
  }
119
 
120
  restore_current_blog();
121
  }
122
 
123
+ $post_link = '<a href="' . $post_url . '">' . $post_title . '</a>';
 
124
 
125
  $user_link = bp_core_get_userlink( $activity->user_id );
126
 
 
127
  if ( is_multisite() ) {
128
  $action = sprintf( __( '%1$s wrote a new post, %2$s, on the site %3$s', 'buddypress' ), $user_link, $post_link, '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
129
  } else {
130
  $action = sprintf( __( '%1$s wrote a new post, %2$s', 'buddypress' ), $user_link, $post_link );
131
  }
132
 
133
+ // Legacy filter - requires the post object
134
  if ( has_filter( 'bp_blogs_activity_new_post_action' ) ) {
135
  switch_to_blog( $activity->item_id );
136
  $post = get_post( $activity->secondary_item_id );
141
  }
142
  }
143
 
 
 
 
 
 
 
 
 
144
  return apply_filters( 'bp_blogs_format_activity_action_new_blog_post', $action, $activity );
145
  }
146
 
147
  /**
148
  * Format 'new_blog_comment' activity actions.
149
  *
150
+ * @since BuddyPress (2.0.0)
151
  *
152
+ * @param string $action Static activity action.
153
+ * @param obj $activity Activity data object.
 
154
  */
155
  function bp_blogs_format_activity_action_new_blog_comment( $action, $activity ) {
156
+ $blog_url = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
157
+ $blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
  if ( empty( $blog_url ) || empty( $blog_name ) ) {
160
  $blog_url = get_home_url( $activity->item_id );
164
  bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
165
  }
166
 
167
+ $post_url = bp_activity_get_meta( $activity->id, 'post_url' );
168
+ $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
 
 
 
169
 
170
+ // Should only be empty at the time of post creation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  if ( empty( $post_url ) || empty( $post_title ) ) {
172
  switch_to_blog( $activity->item_id );
173
 
188
  restore_current_blog();
189
  }
190
 
191
+ $post_link = '<a href="' . $post_url . '">' . $post_title . '</a>';
192
  $user_link = bp_core_get_userlink( $activity->user_id );
193
 
194
  if ( is_multisite() ) {
197
  $action = sprintf( __( '%1$s commented on the post, %2$s', 'buddypress' ), $user_link, $post_link );
198
  }
199
 
200
+ // Legacy filter - requires the comment object
201
  if ( has_filter( 'bp_blogs_activity_new_comment_action' ) ) {
202
  switch_to_blog( $activity->item_id );
203
  $comment = get_comment( $activity->secondary_item_id );
208
  }
209
  }
210
 
 
 
 
 
 
 
 
 
211
  return apply_filters( 'bp_blogs_format_activity_action_new_blog_comment', $action, $activity );
212
  }
213
 
216
  *
217
  * This reduces database overhead during the activity loop.
218
  *
219
+ * @since BuddyPress (2.0.0)
220
  *
221
  * @param array $activities Array of activity items.
222
  * @return array
247
  /**
248
  * Record blog-related activity to the activity stream.
249
  *
250
+ * @since BuddyPress (1.0.0)
251
  *
252
  * @see bp_activity_add() for description of parameters.
253
+ * @global object $bp The BuddyPress global settings object.
254
  *
255
+ * @param array $args {
256
  * See {@link bp_activity_add()} for complete description of arguments.
257
  * The arguments listed here have different default values from
258
  * bp_activity_add().
261
  * @return int|bool On success, returns the activity ID. False on failure.
262
  */
263
  function bp_blogs_record_activity( $args = '' ) {
264
+ global $bp;
265
+
266
+ // Bail if activity is not active
267
+ if ( ! bp_is_active( 'activity' ) )
268
+ return false;
269
+
270
  $defaults = array(
271
  'user_id' => bp_loggedin_user_id(),
272
  'action' => '',
273
  'content' => '',
274
  'primary_link' => '',
275
+ 'component' => $bp->blogs->id,
276
  'type' => false,
277
  'item_id' => false,
278
  'secondary_item_id' => false,
281
  );
282
 
283
  $r = wp_parse_args( $args, $defaults );
284
+ extract( $r, EXTR_SKIP );
285
 
286
+ // Remove large images and replace them with just one image thumbnail
287
+ if ( !empty( $content ) )
288
+ $content = bp_activity_thumbnail_content_images( $content, $primary_link, $r );
289
 
290
+ if ( !empty( $action ) )
291
+ $action = apply_filters( 'bp_blogs_record_activity_action', $action );
 
 
 
 
 
 
 
292
 
293
+ if ( !empty( $content ) )
294
+ $content = apply_filters( 'bp_blogs_record_activity_content', bp_create_excerpt( $content ), $content );
 
 
 
 
 
 
 
 
 
 
 
295
 
296
  // Check for an existing entry and update if one exists.
297
  $id = bp_activity_get_activity_id( array(
298
+ 'user_id' => $user_id,
299
+ 'component' => $component,
300
+ 'type' => $type,
301
+ 'item_id' => $item_id,
302
+ 'secondary_item_id' => $secondary_item_id
303
  ) );
304
 
305
+ return bp_activity_add( array( 'id' => $id, 'user_id' => $user_id, 'action' => $action, 'content' => $content, 'primary_link' => $primary_link, 'component' => $component, 'type' => $type, 'item_id' => $item_id, 'secondary_item_id' => $secondary_item_id, 'recorded_time' => $recorded_time, 'hide_sitewide' => $hide_sitewide ) );
306
  }
307
 
308
  /**
309
  * Delete a blog-related activity stream item.
310
  *
311
+ * @since BuddyPress (1.0.0)
312
  *
313
  * @see bp_activity_delete() for description of parameters.
314
+ * @global object $bp The BuddyPress global settings object.
315
  *
316
+ * @param array $args {
317
  * See {@link bp_activity_delete()} for complete description of arguments.
318
  * The arguments listed here have different default values from
319
  * bp_activity_add().
321
  * }
322
  * @return bool True on success, false on failure.
323
  */
324
+ function bp_blogs_delete_activity( $args = true ) {
325
+ global $bp;
326
+
327
+ // Bail if activity is not active
328
+ if ( ! bp_is_active( 'activity' ) )
329
+ return false;
330
+
331
+ $defaults = array(
332
  'item_id' => false,
333
+ 'component' => $bp->blogs->id,
334
  'type' => false,
335
  'user_id' => false,
336
  'secondary_item_id' => false
337
+ );
338
 
339
+ $params = wp_parse_args( $args, $defaults );
340
+ extract( $params, EXTR_SKIP );
341
+
342
+ bp_activity_delete_by_item_id( array(
343
+ 'item_id' => $item_id,
344
+ 'component' => $component,
345
+ 'type' => $type,
346
+ 'user_id' => $user_id,
347
+ 'secondary_item_id' => $secondary_item_id
348
+ ) );
349
  }
350
 
351
  /**
359
  * to blogmeta and checks the values in blogmeta instead. This is to prevent
360
  * multiple {@link switch_to_blog()} calls in the activity stream.
361
  *
362
+ * @since BuddyPress (2.0.0)
363
  *
364
+ * @param object $activity The BP_Activity_Activity object
365
  * @return bool
366
  */
367
  function bp_blogs_comments_open( $activity ) {
369
 
370
  $blog_id = $activity->item_id;
371
 
372
+ // see if we've mirrored the close comments option before
373
  $days_old = bp_blogs_get_blogmeta( $blog_id, 'close_comments_days_old' );
374
 
375
+ // we've never cached these items before, so do it now
376
  if ( '' === $days_old ) {
377
  switch_to_blog( $blog_id );
378
 
379
+ // use comments_open()
380
+ remove_filter( 'comments_open', 'bp_comments_open', 10, 2 );
381
  $open = comments_open( $activity->secondary_item_id );
382
  add_filter( 'comments_open', 'bp_comments_open', 10, 2 );
383
 
384
+ // might as well mirror values to blogmeta since we're here!
385
  $thread_depth = get_option( 'thread_comments' );
386
  if ( ! empty( $thread_depth ) ) {
387
  $thread_depth = get_option( 'thread_comments_depth' );
388
  } else {
389
+ // perhaps filter this?
390
  $thread_depth = 1;
391
  }
392
 
396
 
397
  restore_current_blog();
398
 
399
+ // check blogmeta and manually check activity item
400
+ // basically a copy of _close_comments_for_old_post()
401
  } else {
402
 
403
+ // comments are closed
404
  if ( 'closed' == bp_activity_get_meta( $activity->id, 'post_comment_status' ) ) {
405
  return false;
406
  }
414
  return $open;
415
  }
416
 
417
+ /* commenting out for now - needs some more thought...
 
418
  should we add the post type to activity meta?
419
 
420
  $post = get_post($post_id);
435
  return $open;
436
  }
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  /** POST COMMENT SYNCHRONIZATION ****************************************/
439
 
440
  /**
442
  *
443
  * Note: This is only a one-way sync - activity comments -> blog comment.
444
  *
445
+ * For blog post -> activity comment, see {@link bp_blogs_record_comment()}.
446
  *
447
+ * @since BuddyPress (2.0.0)
 
448
  *
449
+ * @param int $comment_id The activity ID for the posted activity comment.
450
+ * @param array $params Parameters for the activity comment.
451
+ * @param object Parameters of the parent activity item (in this case, the blog post).
452
  */
453
  function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_activity ) {
454
+ // if parent activity isn't a blog post, stop now!
455
+ if ( $parent_activity->type != 'new_blog_post' ) {
456
  return;
457
  }
458
 
459
+ // if activity comments are disabled for blog posts, stop now!
460
  if ( bp_disable_blogforum_comments() ) {
461
  return;
462
  }
463
 
464
+ // get userdata
 
 
 
 
 
 
465
  if ( $params['user_id'] == bp_loggedin_user_id() ) {
466
  $user = buddypress()->loggedin_user->userdata;
467
  } else {
468
  $user = bp_core_get_core_userdata( $params['user_id'] );
469
  }
470
 
471
+ // see if a parent WP comment ID exists
472
+ if ( ! empty( $params['parent_id'] ) ) {
473
+ $comment_parent = bp_activity_get_meta( $params['parent_id'], 'bp_blogs_post_comment_id' );
474
+ } else {
475
+ $comment_parent = 0;
 
 
476
  }
477
 
478
+ // comment args
479
  $args = array(
480
  'comment_post_ID' => $parent_activity->secondary_item_id,
481
  'comment_author' => bp_core_get_user_displayname( $params['user_id'] ),
482
  'comment_author_email' => $user->user_email,
483
  'comment_author_url' => bp_core_get_user_domain( $params['user_id'], $user->user_nicename, $user->user_login ),
484
  'comment_content' => $params['content'],
485
+ 'comment_type' => '', // could be interesting to add 'buddypress' here...
486
  'comment_parent' => (int) $comment_parent,
487
  'user_id' => $params['user_id'],
488
+
489
+ // commenting these out for now
490
+ //'comment_author_IP' => '127.0.0.1',
491
+ //'comment_agent' => '',
492
+
493
  'comment_approved' => 1
494
  );
495
 
496
+ // prevent separate activity entry being made
497
+ remove_action( 'comment_post', 'bp_blogs_record_comment', 10, 2 );
498
 
499
+ // handle multisite
500
  switch_to_blog( $parent_activity->item_id );
501
 
502
+ // handle timestamps for the WP comment after we've switched to the blog
503
  $args['comment_date'] = current_time( 'mysql' );
504
  $args['comment_date_gmt'] = current_time( 'mysql', 1 );
505
 
506
+ // post the comment
507
  $post_comment_id = wp_insert_comment( $args );
508
 
509
+ // add meta to comment
510
  add_comment_meta( $post_comment_id, 'bp_activity_comment_id', $comment_id );
511
 
512
+ // add meta to activity comment
513
+ bp_activity_update_meta( $comment_id, 'bp_blogs_post_comment_id', $post_comment_id );
 
 
514
 
515
+ // resave activity comment with WP comment permalink
516
  //
517
  // in bp_blogs_activity_comment_permalink(), we change activity comment
518
  // permalinks to use the post comment link
519
  //
520
  // @todo since this is done after AJAX posting, the activity comment permalink
521
+ // doesn't change on the frontend until the next page refresh.
522
  $resave_activity = new BP_Activity_Activity( $comment_id );
523
  $resave_activity->primary_link = get_comment_link( $post_comment_id );
 
 
 
 
 
 
 
524
  $resave_activity->save();
525
 
526
+ // multisite again!
 
 
 
527
  restore_current_blog();
528
 
529
+ // add the comment hook back
530
+ add_action( 'comment_post', 'bp_blogs_record_comment', 10, 2 );
531
+
 
 
 
 
 
 
 
 
 
 
532
  do_action( 'bp_blogs_sync_add_from_activity_comment', $comment_id, $args, $parent_activity, $user );
533
  }
534
  add_action( 'bp_activity_comment_posted', 'bp_blogs_sync_add_from_activity_comment', 10, 3 );
540
  * of the 'bp_activity_delete_comment' action because we need to fetch the
541
  * activity comment children before they are deleted.
542
  *
543
+ * @since BuddyPress (2.0.0)
 
544
  *
545
+ * @param bool $retval
546
+ * @param int $parent_activity_id The parent activity ID for the activity comment.
547
+ * @param int $activity_id The activity ID for the pending deleted activity comment.
 
 
548
  */
549
+ function bp_blogs_sync_delete_from_activity_comment( $retval, $parent_activity_id, $activity_id ) {
550
+ // check if parent activity is a blog post
551
  $parent_activity = new BP_Activity_Activity( $parent_activity_id );
552
+ if ( 'new_blog_post' != $parent_activity->type ) {
 
 
553
  return $retval;
554
  }
555
 
556
+ // fetch the activity comments for the activity item
557
  $activity = bp_activity_get( array(
558
  'in' => $activity_id,
559
  'display_comments' => 'stream',
 
560
  ) );
561
 
562
+ // get all activity comment IDs for the pending deleted item
563
  $activity_ids = bp_activity_recurse_comments_activity_ids( $activity );
564
  $activity_ids[] = $activity_id;
565
 
566
+ // handle multisite
567
+ // switch to the blog where the comment was made
568
  switch_to_blog( $parent_activity->item_id );
569
 
570
+ // remove associated blog comments
571
  bp_blogs_remove_associated_blog_comments( $activity_ids, current_user_can( 'moderate_comments' ) );
572
 
573
+ // multisite again!
574
  restore_current_blog();
575
 
576
+ // rebuild activity comment tree
577
+ // emulate bp_activity_delete_comment()
578
  BP_Activity_Activity::rebuild_activity_comment_tree( $parent_activity_id );
579
 
580
+ // we're overriding the default bp_activity_delete_comment() functionality
581
+ // so we need to return false
 
 
 
582
  return false;
583
  }
584
+ add_filter( 'bp_activity_delete_comment_pre', 'bp_blogs_sync_delete_from_activity_comment', 10, 3 );
585
 
586
  /**
587
  * Updates the blog comment when the associated activity comment is edited.
588
  *
589
+ * @since BuddyPress (2.0.0)
590
  *
591
  * @param BP_Activity_Activity $activity The activity object.
592
  */
593
  function bp_blogs_sync_activity_edit_to_post_comment( BP_Activity_Activity $activity ) {
594
+ // not an activity comment? stop now!
595
+ if ( 'activity_comment' !== $activity->type ) {
 
596
  return;
597
  }
598
 
599
+ // this is a new entry, so stop!
600
+ // we only want edits!
601
+ if ( empty( $activity->id ) ) {
 
 
602
  return;
603
  }
604
 
605
+ // prevent recursion
606
+ remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
607
 
608
+ // Try to see if a corresponding blog comment exists
609
+ $post_comment_id = bp_activity_get_meta( $activity->id, 'bp_blogs_post_comment_id' );
610
+
611
+ if ( empty( $post_comment_id ) ) {
612
  return;
613
  }
614
 
615
+ // fetch parent activity item
616
+ $parent_activity = new BP_Activity_Activity( $activity->item_id );
617
 
618
+ // sanity check
619
+ if ( 'new_blog_post' !== $parent_activity->type ) {
620
  return;
621
  }
622
 
623
+ // handle multisite
624
  switch_to_blog( $parent_activity->item_id );
625
 
626
+ // update the blog post comment
627
+ wp_update_comment( array(
628
+ 'comment_ID' => $post_comment_id,
629
+ 'comment_content' => $activity->content
630
+ ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
631
 
632
  restore_current_blog();
633
  }
643
  * Since these activity entries are deleted, we need to remove the deleted
644
  * activity comment IDs from each comment's meta when a post is trashed.
645
  *
646
+ * @since BuddyPress (2.0.0)
647
  *
648
+ * @param int $post_id The post ID
649
+ * @param array $statuses Array of comment statuses. The key is comment ID, the
650
+ * value is the $comment->comment_approved value.
651
  */
652
+ function bp_blogs_remove_activity_meta_for_trashed_comments( $post_id, $statuses ) {
653
+ foreach ( $statuses as $comment_id => $comment_approved ) {
654
+ delete_comment_meta( $comment_id, 'bp_activity_comment_id' );
 
 
655
  }
656
  }
657
  add_action( 'trashed_post_comments', 'bp_blogs_remove_activity_meta_for_trashed_comments', 10, 2 );
658
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
659
  /**
660
  * Utility function to set up some variables for use in the activity loop.
661
  *
664
  *
665
  * This is to prevent having to requery these items later on.
666
  *
667
+ * @since BuddyPress (2.0.0)
668
  *
669
  * @see bp_blogs_disable_activity_commenting()
670
  * @see bp_blogs_setup_comment_loop_globals_on_ajax()
671
  *
672
+ * @param object $activity The BP_Activity_Activity object
673
  */
674
  function bp_blogs_setup_activity_loop_globals( $activity ) {
675
  if ( ! is_object( $activity ) ) {
676
  return;
677
  }
678
 
679
+ // parent not a blog post? stop now!
680
+ if ( 'new_blog_post' !== $activity->type ) {
681
  return;
682
  }
683
 
685
  return;
686
  }
687
 
688
+ // if we've already done this before, stop now!
689
  if ( isset( buddypress()->blogs->allow_comments[ $activity->id ] ) ) {
690
  return;
691
  }
693
  $allow_comments = bp_blogs_comments_open( $activity );
694
  $thread_depth = bp_blogs_get_blogmeta( $activity->item_id, 'thread_comments_depth' );
695
 
696
+ // initialize a local object so we won't have to query this again in the
697
+ // comment loop
698
  if ( empty( buddypress()->blogs->allow_comments ) ) {
699
  buddypress()->blogs->allow_comments = array();
700
  }
702
  buddypress()->blogs->thread_depth = array();
703
  }
704
 
705
+ // cache comment settings in the buddypress() singleton to reference later in
706
  // the activity comment loop
707
  // @see bp_blogs_disable_activity_replies()
708
  //
716
  /**
717
  * Set up some globals used in the activity comment loop when AJAX is used.
718
  *
719
+ * @since BuddyPress (2.0.0)
720
  *
721
  * @see bp_blogs_setup_activity_loop_globals()
722
  */
723
  function bp_blogs_setup_comment_loop_globals_on_ajax() {
724
+ // not AJAX? stop now!
725
  if ( ! defined( 'DOING_AJAX' ) ) {
726
  return;
727
  }
729
  return;
730
  }
731
 
732
+ // get the parent activity item
733
  $comment = bp_activity_current_comment();
734
  $parent_activity = new BP_Activity_Activity( $comment->item_id );
735
 
736
+ // setup the globals
737
  bp_blogs_setup_activity_loop_globals( $parent_activity );
738
  }
739
  add_action( 'bp_before_activity_comment', 'bp_blogs_setup_comment_loop_globals_on_ajax' );
748
  * based on a certain age
749
  * - the activity entry is a 'new_blog_comment' type
750
  *
751
+ * @since BuddyPress (2.0.0)
752
  *
753
+ * @param bool $retval Is activity commenting enabled for this activity entry?
754
  * @return bool
755
  */
756
  function bp_blogs_disable_activity_commenting( $retval ) {
757
+ // if activity commenting is disabled, return current value
758
+ if ( bp_disable_blogforum_comments() ) {
 
 
759
  return $retval;
760
  }
761
 
762
+ // activity commenting is enabled for blog posts
763
+ switch ( bp_get_activity_action_name() ) {
764
 
765
+ // we still have to disable activity commenting for 'new_blog_comment' items
766
+ // commenting should only be done on the parent 'new_blog_post' item
767
+ case 'new_blog_comment' :
 
 
 
 
 
 
 
 
 
 
 
768
  $retval = false;
 
 
769
 
770
+ break;
 
 
771
 
772
+ // check if commenting is disabled for the WP blog post
773
+ // we should extrapolate this and automate this for plugins... or not
774
+ case 'new_blog_post' :
775
+ global $activities_template;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776
 
777
+ // setup some globals we'll need to reference later
778
+ bp_blogs_setup_activity_loop_globals( $activities_template->activity );
 
779
 
780
+ // if comments are closed for the WP blog post, we should disable
781
+ // activity comments for this activity entry
782
+ if ( empty( buddypress()->blogs->allow_comments[bp_get_activity_id()] ) ) {
783
+ $retval = false;
784
+ }
785
 
786
+ break;
 
787
  }
788
 
789
  return $retval;
790
  }
791
+ add_filter( 'bp_activity_can_comment', 'bp_blogs_disable_activity_commenting' );
792
 
793
  /**
794
  * Check if an activity comment associated with a blog post can be replied to.
799
  * This check uses a locally-cached value set in {@link bp_blogs_disable_activity_commenting()}
800
  * via {@link bp_blogs_setup_activity_loop_globals()}.
801
  *
802
+ * @since BuddyPress (2.0.0)
 
 
 
803
  *
804
+ * @param bool $retval Are replies allowed for this activity reply?
805
+ * @param object $comment The activity comment object
806
  * @return bool
807
  */
808
  function bp_blogs_can_comment_reply( $retval, $comment ) {
810
  $comment = (object) $comment;
811
  }
812
 
813
+ // check comment depth and disable if depth is too large
814
  if ( isset( buddypress()->blogs->thread_depth[$comment->item_id] ) ){
815
+ if ( $comment->mptt_left > buddypress()->blogs->thread_depth[$comment->item_id] ) {
816
  $retval = false;
817
  }
818
  }
819
 
820
+ // check if we should disable activity replies based on the parent activity
821
  if ( isset( buddypress()->blogs->allow_comments[$comment->item_id] ) ){
822
+ // the blog post has closed off commenting, so we should disable all activity
823
+ // comments under the parent 'new_blog_post' activity entry
824
  if ( empty( buddypress()->blogs->allow_comments[$comment->item_id] ) ) {
825
  $retval = false;
826
  }
837
  * This is only done if activity commenting is allowed and whether the parent
838
  * activity item is a 'new_blog_post' entry.
839
  *
840
+ * @since BuddyPress (2.0.0)
841
  *
842
+ * @param string $retval The activity comment permalink
843
  * @return string
844
  */
845
+ function bp_blogs_activity_comment_permalink( $retval ) {
846
  global $activities_template;
847
 
848
+ if ( isset( buddypress()->blogs->allow_comments[$activities_template->activity->current_comment->item_id] ) ){
 
 
 
 
 
 
849
  $retval = $activities_template->activity->current_comment->primary_link;
850
  }
851
 
858
  *
859
  * This is only done if the activity comment is associated with a blog comment.
860
  *
861
+ * @since BuddyPress (2.0.1)
862
  *
863
+ * @param string $retval The activity permalink
864
+ * @param BP_Activity_Activity $activity
865
  * @return string
866
  */
867
  function bp_blogs_activity_comment_single_permalink( $retval, $activity ) {
869
  return $retval;
870
  }
871
 
872
+ $blog_comment_id = bp_activity_get_meta( $activity->id, 'bp_blogs_post_comment_id' );
 
 
 
 
873
 
874
+ if ( ! empty( $blog_comment_id ) ) {
875
  $retval = $activity->primary_link;
876
  }
877
 
884
  *
885
  * This is only done if the activity comment is associated with a blog comment.
886
  *
887
+ * @since BuddyPress (2.0.1)
888
  *
889
+ * @param string $retval The activity action
890
+ * @param BP_Activity_Activity $activity
891
  * @return string
892
  */
893
  function bp_blogs_activity_comment_single_action( $retval, $activity ) {
895
  return $retval;
896
  }
897
 
898
+ $blog_comment_id = bp_activity_get_meta( $activity->id, 'bp_blogs_post_comment_id' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
899
 
900
  if ( ! empty( $blog_comment_id ) ) {
901
+ // fetch the parent blog post activity item
902
+ $parent_blog_post_activity = new BP_Activity_Activity( $activity->item_id );
 
 
 
 
 
 
 
903
 
904
+ // fake a 'new_blog_comment' activity object
905
+ $object = $activity;
906
 
907
+ // override 'item_id' to use blog ID
908
+ $object->item_id = $parent_blog_post_activity->item_id;
909
 
910
+ // override 'secondary_item_id' to use comment ID
911
+ $object->secondary_item_id = $blog_comment_id;
912
 
913
+ // now format the activity action using the 'new_blog_comment' action callback
914
+ $retval = bp_blogs_format_activity_action_new_blog_comment( '', $object );
 
 
 
 
 
 
915
  }
916
 
917
  return $retval;
bp-blogs/bp-blogs-buddybar.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * BuddyPress Blogs BuddyBar functions.
5
+ *
6
+ * @package BuddyPress
7
+ * @subpackage BlogsBuddyBar
8
+ */
9
+
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
+
13
+ /**
14
+ * Add a Sites menu to the BuddyBar.
15
+ *
16
+ * @since BuddyPress (1.0.0)
17
+ *
18
+ * @global object $bp The BuddyPress global settings object.
19
+ *
20
+ * @return bool|null Returns false on failure. Otherwise echoes the menu item.
21
+ */
22
+ function bp_adminbar_blogs_menu() {
23
+ global $bp;
24
+
25
+ if ( !is_user_logged_in() || !bp_is_active( 'blogs' ) )
26
+ return false;
27
+
28
+ if ( !is_multisite() )
29
+ return false;
30
+
31
+ $blogs = wp_cache_get( 'bp_blogs_of_user_' . bp_loggedin_user_id() . '_inc_hidden', 'bp' );
32
+ if ( empty( $blogs ) ) {
33
+ $blogs = bp_blogs_get_blogs_for_user( bp_loggedin_user_id(), true );
34
+ wp_cache_set( 'bp_blogs_of_user_' . bp_loggedin_user_id() . '_inc_hidden', $blogs, 'bp' );
35
+ }
36
+
37
+ $counter = 0;
38
+ if ( is_array( $blogs['blogs'] ) && (int) $blogs['count'] ) {
39
+
40
+ echo '<li id="bp-adminbar-blogs-menu"><a href="' . trailingslashit( bp_loggedin_user_domain() . bp_get_blogs_slug() ) . '">';
41
+
42
+ _e( 'My Sites', 'buddypress' );
43
+
44
+ echo '</a>';
45
+ echo '<ul>';
46
+
47
+ foreach ( (array) $blogs['blogs'] as $blog ) {
48
+ $alt = ( 0 == $counter % 2 ) ? ' class="alt"' : '';
49
+ $site_url = esc_attr( $blog->siteurl );
50
+
51
+ echo '<li' . $alt . '>';
52
+ echo '<a href="' . $site_url . '">' . esc_html( $blog->name ) . '</a>';
53
+ echo '<ul>';
54
+ echo '<li class="alt"><a href="' . $site_url . 'wp-admin/">' . __( 'Dashboard', 'buddypress' ) . '</a></li>';
55
+ echo '<li><a href="' . $site_url . 'wp-admin/post-new.php">' . __( 'New Post', 'buddypress' ) . '</a></li>';
56
+ echo '<li class="alt"><a href="' . $site_url . 'wp-admin/edit.php">' . __( 'Manage Posts', 'buddypress' ) . '</a></li>';
57
+ echo '<li><a href="' . $site_url . 'wp-admin/edit-comments.php">' . __( 'Manage Comments', 'buddypress' ) . '</a></li>';
58
+ echo '</ul>';
59
+
60
+ do_action( 'bp_adminbar_blog_items', $blog );
61
+
62
+ echo '</li>';
63
+ $counter++;
64
+ }
65
+
66
+ $alt = ( 0 == $counter % 2 ) ? ' class="alt"' : '';
67
+
68
+ if ( bp_blog_signup_enabled() ) {
69
+ echo '<li' . $alt . '>';
70
+ echo '<a href="' . bp_get_root_domain() . '/' . bp_get_blogs_root_slug() . '/create/">' . __( 'Create a Site!', 'buddypress' ) . '</a>';
71
+ echo '</li>';
72
+ }
73
+
74
+ echo '</ul>';
75
+ echo '</li>';
76
+ }
77
+ }
78
+ add_action( 'bp_adminbar_menus', 'bp_adminbar_blogs_menu', 6 );
bp-blogs/bp-blogs-cache.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Blogs Caching.
4
  *
@@ -7,11 +8,10 @@
7
  *
8
  * @package BuddyPress
9
  * @subpackage BlogsCache
10
- * @since 1.5.0
11
  */
12
 
13
- // Exit if accessed directly.
14
- defined( 'ABSPATH' ) || exit;
15
 
16
  /**
17
  * Slurp up blogmeta for a specified set of blogs.
@@ -20,16 +20,16 @@ defined( 'ABSPATH' ) || exit;
20
  * in $blog_ids and adds it to the WP cache. This improves efficiency when
21
  * using querying blogmeta inline.
22
  *
23
- * @param int|string|array|bool $blog_ids Accepts a single blog ID, or a comma-
24
- * separated list or array of blog IDs.
25
  */
26
  function bp_blogs_update_meta_cache( $blog_ids = false ) {
27
  $cache_args = array(
28
- 'object_ids' => $blog_ids,
29
- 'object_type' => buddypress()->blogs->id,
30
- 'object_column' => 'blog_id',
31
- 'cache_group' => 'blog_meta',
32
- 'meta_table' => buddypress()->blogs->table_name_blogmeta,
33
  );
34
 
35
  bp_update_meta_cache( $cache_args );
@@ -37,26 +37,34 @@ function bp_blogs_update_meta_cache( $blog_ids = false ) {
37
  /**
38
  * Clear the blog object cache.
39
  *
40
- * @since 1.0.0
41
  *
42
  * @param int $blog_id ID of the current blog.
43
  * @param int $user_id ID of the user whose blog cache should be cleared.
44
  */
45
- function bp_blogs_clear_blog_object_cache( $blog_id = 0, $user_id = 0 ) {
46
- if ( ! empty( $user_id ) ) {
47
- wp_cache_delete( 'bp_blogs_of_user_' . $user_id, 'bp' );
48
- wp_cache_delete( 'bp_total_blogs_for_user_' . $user_id, 'bp' );
49
- }
50
 
 
 
 
 
 
 
 
 
 
 
51
  wp_cache_delete( 'bp_total_blogs', 'bp' );
52
  }
53
 
54
- // List actions to clear object caches on.
55
  add_action( 'bp_blogs_remove_blog_for_user', 'bp_blogs_clear_blog_object_cache', 10, 2 );
56
- add_action( 'wpmu_new_blog', 'bp_blogs_clear_blog_object_cache', 10, 2 );
57
- add_action( 'bp_blogs_remove_blog', 'bp_blogs_clear_blog_object_cache' );
58
 
59
- // List actions to clear super cached pages on, if super cache is installed.
60
  add_action( 'bp_blogs_remove_data_for_blog', 'bp_core_clear_cache' );
61
  add_action( 'bp_blogs_remove_comment', 'bp_core_clear_cache' );
62
  add_action( 'bp_blogs_remove_post', 'bp_core_clear_cache' );
1
  <?php
2
+
3
  /**
4
  * BuddyPress Blogs Caching.
5
  *
8
  *
9
  * @package BuddyPress
10
  * @subpackage BlogsCache
 
11
  */
12
 
13
+ // Exit if accessed directly
14
+ if ( !defined( 'ABSPATH' ) ) exit;
15
 
16
  /**
17
  * Slurp up blogmeta for a specified set of blogs.
20
  * in $blog_ids and adds it to the WP cache. This improves efficiency when
21
  * using querying blogmeta inline.
22
  *
23
+ * @param int|str|array $blog_ids Accepts a single blog ID, or a comma-
24
+ * separated list or array of blog IDs.
25
  */
26
  function bp_blogs_update_meta_cache( $blog_ids = false ) {
27
  $cache_args = array(
28
+ 'object_ids' => $blog_ids,
29
+ 'object_type' => buddypress()->blogs->id,
30
+ 'object_column' => 'blog_id',
31
+ 'cache_group' => 'blog_meta',
32
+ 'meta_table' => buddypress()->blogs->table_name_blogmeta,
33
  );
34
 
35
  bp_update_meta_cache( $cache_args );
37
  /**
38
  * Clear the blog object cache.
39
  *
40
+ * @since BuddyPress (1.0.0)
41
  *
42
  * @param int $blog_id ID of the current blog.
43
  * @param int $user_id ID of the user whose blog cache should be cleared.
44
  */
45
+ function bp_blogs_clear_blog_object_cache( $blog_id, $user_id ) {
46
+ wp_cache_delete( 'bp_blogs_of_user_' . $user_id, 'bp' );
47
+ wp_cache_delete( 'bp_total_blogs_for_user_' . $user_id, 'bp' );
48
+ }
 
49
 
50
+ /**
51
+ * Clear cache when a new blog is created.
52
+ *
53
+ * @since BuddyPress (1.0.0)
54
+ *
55
+ * @param BP_Blogs_Blog $recorded_blog_obj The recorded blog, passed by
56
+ * 'bp_blogs_new_blog'.
57
+ */
58
+ function bp_blogs_format_clear_blog_cache( $recorded_blog_obj ) {
59
+ bp_blogs_clear_blog_object_cache( false, $recorded_blog_obj->user_id );
60
  wp_cache_delete( 'bp_total_blogs', 'bp' );
61
  }
62
 
63
+ // List actions to clear object caches on
64
  add_action( 'bp_blogs_remove_blog_for_user', 'bp_blogs_clear_blog_object_cache', 10, 2 );
65
+ add_action( 'bp_blogs_new_blog', 'bp_blogs_format_clear_blog_cache', 10, 2 );
 
66
 
67
+ // List actions to clear super cached pages on, if super cache is installed
68
  add_action( 'bp_blogs_remove_data_for_blog', 'bp_core_clear_cache' );
69
  add_action( 'bp_blogs_remove_comment', 'bp_core_clear_cache' );
70
  add_action( 'bp_blogs_remove_post', 'bp_core_clear_cache' );
bp-blogs/{classes/class-bp-blogs-blog.php → bp-blogs-classes.php} RENAMED
@@ -1,14 +1,14 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Blogs Classes.
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsClasses
7
- * @since 1.0.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * The main BuddyPress blog class.
@@ -16,39 +16,21 @@ defined( 'ABSPATH' ) || exit;
16
  * A BP_Blogs_Object represents a link between a specific WordPress blog on a
17
  * network and a specific user on that blog.
18
  *
19
- * @since 1.0.0
20
  */
21
  class BP_Blogs_Blog {
22
-
23
- /**
24
- * Site ID.
25
- *
26
- * @var int|null
27
- */
28
  public $id;
29
-
30
- /**
31
- * User ID.
32
- *
33
- * @var int
34
- */
35
  public $user_id;
36
-
37
- /**
38
- * Blog ID.
39
- *
40
- * @var int
41
- */
42
  public $blog_id;
43
 
44
  /**
45
  * Constructor method.
46
  *
47
- * @param int|null $id Optional. The ID of the blog.
48
  */
49
  public function __construct( $id = null ) {
50
  if ( !empty( $id ) ) {
51
- $this->id = (int) $id;
52
  $this->populate();
53
  }
54
  }
@@ -57,14 +39,12 @@ class BP_Blogs_Blog {
57
  * Populate the object with data about the specific activity item.
58
  */
59
  public function populate() {
60
- global $wpdb;
61
-
62
- $bp = buddypress();
63
 
64
  $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->blogs->table_name} WHERE id = %d", $this->id ) );
65
 
66
- $this->user_id = (int) $blog->user_id;
67
- $this->blog_id = (int) $blog->blog_id;
68
  }
69
 
70
  /**
@@ -73,37 +53,11 @@ class BP_Blogs_Blog {
73
  * @return bool True on success, false on failure.
74
  */
75
  public function save() {
76
- global $wpdb;
77
 
78
- /**
79
- * Filters the blog user ID before save.
80
- *
81
- * @since 1.0.0
82
- *
83
- * @param int $value User ID.
84
- * @param int $value Site ID.
85
- */
86
  $this->user_id = apply_filters( 'bp_blogs_blog_user_id_before_save', $this->user_id, $this->id );
87
-
88
- /**
89
- * Filters the blog blog ID before save.
90
- *
91
- * @since 1.0.0
92
- *
93
- * @param int $value Blog ID.
94
- * @param int $value Site ID.
95
- */
96
  $this->blog_id = apply_filters( 'bp_blogs_blog_id_before_save', $this->blog_id, $this->id );
97
 
98
- /**
99
- * Fires before the current blog item gets saved.
100
- *
101
- * Please use this hook to filter the properties above. Each part will be passed in.
102
- *
103
- * @since 1.0.0
104
- *
105
- * @param BP_Blogs_Blog $this Current instance of the blog item being saved. Passed by reference.
106
- */
107
  do_action_ref_array( 'bp_blogs_blog_before_save', array( &$this ) );
108
 
109
  // Don't try and save if there is no user ID or blog ID set.
@@ -114,28 +68,17 @@ class BP_Blogs_Blog {
114
  if ( !$this->id && $this->exists() )
115
  return false;
116
 
117
- $bp = buddypress();
118
-
119
  if ( $this->id ) {
120
- // Update.
121
  $sql = $wpdb->prepare( "UPDATE {$bp->blogs->table_name} SET user_id = %d, blog_id = %d WHERE id = %d", $this->user_id, $this->blog_id, $this->id );
122
  } else {
123
- // Save.
124
  $sql = $wpdb->prepare( "INSERT INTO {$bp->blogs->table_name} ( user_id, blog_id ) VALUES ( %d, %d )", $this->user_id, $this->blog_id );
125
  }
126
 
127
  if ( !$wpdb->query($sql) )
128
  return false;
129
 
130
- /**
131
- * Fires after the current blog item gets saved.
132
- *
133
- * Please use this hook to filter the properties above. Each part will be passed in.
134
- *
135
- * @since 1.0.0
136
- *
137
- * @param BP_Blogs_Blog $this Current instance of the blog item being saved. Passed by reference.
138
- */
139
  do_action_ref_array( 'bp_blogs_blog_after_save', array( &$this ) );
140
 
141
  if ( $this->id )
@@ -147,13 +90,11 @@ class BP_Blogs_Blog {
147
  /**
148
  * Check whether an association between this user and this blog exists.
149
  *
150
- * @return int $value The number of associations between the user and blog
151
- * saved in the blog component tables.
152
  */
153
  public function exists() {
154
- global $wpdb;
155
-
156
- $bp = buddypress();
157
 
158
  return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $this->user_id, $this->blog_id ) );
159
  }
@@ -163,27 +104,25 @@ class BP_Blogs_Blog {
163
  /**
164
  * Retrieve a set of blog-user associations.
165
  *
166
- * @param string $type The order in which results should be returned.
167
- * 'active', 'alphabetical', 'newest', or 'random'.
168
- * @param int|bool $limit Optional. The maximum records to return.
169
- * Default: false.
170
- * @param int|bool $page Optional. The page of records to return.
171
- * Default: false (unlimited results).
172
- * @param int $user_id Optional. ID of the user whose blogs are being
173
- * retrieved. Default: 0.
174
- * @param string|bool $search_terms Optional. Search by text stored in
175
- * blogmeta (such as the blog name). Default: false.
176
- * @param bool $update_meta_cache Whether to pre-fetch metadata for
177
- * blogs. Default: true.
178
- * @param array|bool $include_blog_ids Array of blog IDs to include.
179
  * @return array Multidimensional results array, structured as follows:
180
- * 'blogs' - Array of located blog objects
181
- * 'total' - A count of the total blogs matching the filter params
182
  */
183
  public static function get( $type, $limit = false, $page = false, $user_id = 0, $search_terms = false, $update_meta_cache = true, $include_blog_ids = false ) {
184
- global $wpdb;
185
-
186
- $bp = buddypress();
187
 
188
  if ( !is_user_logged_in() || ( !bp_current_user_can( 'bp_moderate' ) && ( $user_id != bp_loggedin_user_id() ) ) )
189
  $hidden_sql = "AND wb.public = 1";
@@ -199,7 +138,7 @@ class BP_Blogs_Blog {
199
  $order_sql = "ORDER BY bm.meta_value DESC";
200
  break;
201
  case 'alphabetical':
202
- $order_sql = "ORDER BY bm_name.meta_value ASC";
203
  break;
204
  case 'newest':
205
  $order_sql = "ORDER BY wb.registered DESC";
@@ -216,43 +155,15 @@ class BP_Blogs_Blog {
216
  $include_sql = " AND b.blog_id IN ({$blog_ids_sql})";
217
  }
218
 
219
- if ( ! empty( $search_terms ) ) {
220
- $search_terms_like = '%' . bp_esc_like( $search_terms ) . '%';
221
- $search_terms_sql = $wpdb->prepare( 'AND (bm_name.meta_value LIKE %s OR bm_description.meta_value LIKE %s)', $search_terms_like, $search_terms_like );
 
222
  } else {
223
- $search_terms_sql = '';
 
224
  }
225
 
226
- $paged_blogs = $wpdb->get_results( "
227
- SELECT b.blog_id, b.user_id as admin_user_id, u.user_email as admin_user_email, wb.domain, wb.path, bm.meta_value as last_activity, bm_name.meta_value as name
228
- FROM
229
- {$bp->blogs->table_name} b
230
- LEFT JOIN {$bp->blogs->table_name_blogmeta} bm ON (b.blog_id = bm.blog_id)
231
- LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_name ON (b.blog_id = bm_name.blog_id)
232
- LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_description ON (b.blog_id = bm_description.blog_id)
233
- LEFT JOIN {$wpdb->base_prefix}blogs wb ON (b.blog_id = wb.blog_id)
234
- LEFT JOIN {$wpdb->users} u ON (b.user_id = u.ID)
235
- WHERE
236
- wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql}
237
- AND bm.meta_key = 'last_activity' AND bm_name.meta_key = 'name' AND bm_description.meta_key = 'description'
238
- {$search_terms_sql} {$user_sql} {$include_sql}
239
- GROUP BY b.blog_id {$order_sql} {$pag_sql}
240
- " );
241
-
242
- $total_blogs = $wpdb->get_var( "
243
- SELECT COUNT(DISTINCT b.blog_id)
244
- FROM
245
- {$bp->blogs->table_name} b
246
- LEFT JOIN {$wpdb->base_prefix}blogs wb ON (b.blog_id = wb.blog_id)
247
- LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_name ON (b.blog_id = bm_name.blog_id)
248
- LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_description ON (b.blog_id = bm_description.blog_id)
249
- WHERE
250
- wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql}
251
- AND
252
- bm_name.meta_key = 'name' AND bm_description.meta_key = 'description'
253
- {$search_terms_sql} {$user_sql} {$include_sql}
254
- " );
255
-
256
  $blog_ids = array();
257
  foreach ( (array) $paged_blogs as $blog ) {
258
  $blog_ids[] = (int) $blog->blog_id;
@@ -260,12 +171,6 @@ class BP_Blogs_Blog {
260
 
261
  $paged_blogs = BP_Blogs_Blog::get_blog_extras( $paged_blogs, $blog_ids, $type );
262
 
263
- // Integer casting.
264
- foreach ( (array) $paged_blogs as $key => $data ) {
265
- $paged_blogs[ $key ]->blog_id = (int) $paged_blogs[ $key ]->blog_id;
266
- $paged_blogs[ $key ]->admin_user_id = (int) $paged_blogs[ $key ]->admin_user_id;
267
- }
268
-
269
  if ( $update_meta_cache ) {
270
  bp_blogs_update_meta_cache( $blog_ids );
271
  }
@@ -280,49 +185,43 @@ class BP_Blogs_Blog {
280
  * @return int|bool Number of rows deleted on success, false on failure.
281
  */
282
  public static function delete_blog_for_all( $blog_id ) {
283
- global $wpdb;
284
 
285
  bp_blogs_delete_blogmeta( $blog_id );
286
-
287
- $bp = buddypress();
288
-
289
  return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->blogs->table_name} WHERE blog_id = %d", $blog_id ) );
290
  }
291
 
292
  /**
293
  * Delete the record of a given blog for a specific user.
294
  *
295
- * @param int $blog_id The blog being removed.
296
- * @param int|null $user_id Optional. The ID of the user from whom the blog is
297
- * being removed. If absent, defaults to the logged-in user ID.
298
  * @return int|bool Number of rows deleted on success, false on failure.
299
  */
300
  public static function delete_blog_for_user( $blog_id, $user_id = null ) {
301
- global $wpdb;
302
 
303
  if ( !$user_id )
304
  $user_id = bp_loggedin_user_id();
305
 
306
- $bp = buddypress();
307
-
308
  return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $user_id, $blog_id ) );
309
  }
310
 
311
  /**
312
  * Delete all of a user's blog associations in the BP tables.
313
  *
314
- * @param int|null $user_id Optional. The ID of the user whose blog associations
315
- * are being deleted. If absent, defaults to logged-in user ID.
 
316
  * @return int|bool Number of rows deleted on success, false on failure.
317
  */
318
  public static function delete_blogs_for_user( $user_id = null ) {
319
- global $wpdb;
320
 
321
  if ( !$user_id )
322
  $user_id = bp_loggedin_user_id();
323
 
324
- $bp = buddypress();
325
-
326
  return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->blogs->table_name} WHERE user_id = %d", $user_id ) );
327
  }
328
 
@@ -334,18 +233,17 @@ class BP_Blogs_Blog {
334
  * blogs that have been recorded by BuddyPress, while the WP function
335
  * does a true query of a user's blog capabilities.
336
  *
337
- * @param int $user_id Optional. ID of the user whose blogs are being
338
- * queried. Defaults to logged-in user.
339
- * @param bool $show_hidden Optional. Whether to include blogs that are not marked
340
- * public. Defaults to true when viewing one's own profile.
 
341
  * @return array Multidimensional results array, structured as follows:
342
- * 'blogs' - Array of located blog objects.
343
- * 'total' - A count of the total blogs for the user.
344
  */
345
  public static function get_blogs_for_user( $user_id = 0, $show_hidden = false ) {
346
- global $wpdb;
347
-
348
- $bp = buddypress();
349
 
350
  if ( !$user_id )
351
  $user_id = bp_displayed_user_id();
@@ -361,8 +259,8 @@ class BP_Blogs_Blog {
361
  $user_blogs = array();
362
  foreach ( (array) $blogs as $blog ) {
363
  $user_blogs[$blog->blog_id] = new stdClass;
364
- $user_blogs[$blog->blog_id]->id = (int) $blog->id;
365
- $user_blogs[$blog->blog_id]->blog_id = (int) $blog->blog_id;
366
  $user_blogs[$blog->blog_id]->siteurl = ( is_ssl() ) ? 'https://' . $blog->domain . $blog->path : 'http://' . $blog->domain . $blog->path;
367
  $user_blogs[$blog->blog_id]->name = $blog->name;
368
  }
@@ -376,18 +274,16 @@ class BP_Blogs_Blog {
376
  * This method always includes hidden blogs.
377
  *
378
  * @param int $user_id Optional. ID of the user whose blogs are being
379
- * queried. Defaults to logged-in user.
380
  * @return int The number of blogs associated with the user.
381
  */
382
  public static function get_blog_ids_for_user( $user_id = 0 ) {
383
- global $wpdb;
384
-
385
- $bp = buddypress();
386
 
387
  if ( !$user_id )
388
  $user_id = bp_displayed_user_id();
389
 
390
- return array_map( 'intval', $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM {$bp->blogs->table_name} WHERE user_id = %d", $user_id ) ) );
391
  }
392
 
393
  /**
@@ -395,16 +291,12 @@ class BP_Blogs_Blog {
395
  *
396
  * @param int $blog_id ID of the blog being queried.
397
  * @return int|null The ID of the first located entry in the BP table
398
- * on success, otherwise null.
399
  */
400
  public static function is_recorded( $blog_id ) {
401
- global $wpdb;
402
-
403
- $bp = buddypress();
404
-
405
- $query = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->blogs->table_name} WHERE blog_id = %d", $blog_id ) );
406
 
407
- return is_numeric( $query ) ? (int) $query : $query;
408
  }
409
 
410
  /**
@@ -414,14 +306,12 @@ class BP_Blogs_Blog {
414
  * $user_id parameter, or when the logged-in user has the bp_moderate
415
  * cap.
416
  *
417
- * @param int|null $user_id Optional. ID of the user whose blogs are being
418
- * queried. Defaults to logged-in user.
419
  * @return int Blog count for the user.
420
  */
421
  public static function total_blog_count_for_user( $user_id = null ) {
422
- global $wpdb;
423
-
424
- $bp = buddypress();
425
 
426
  if ( !$user_id )
427
  $user_id = bp_displayed_user_id();
@@ -440,20 +330,19 @@ class BP_Blogs_Blog {
440
  * Matches against blog names and descriptions, as stored in the BP
441
  * blogmeta table.
442
  *
443
- * @param string $filter The search term.
444
- * @param int|null $limit Optional. The maximum number of items to return.
445
- * Default: null (no limit).
446
- * @param int|null $page Optional. The page of results to return. Default:
447
- * null (no limit).
448
  * @return array Multidimensional results array, structured as follows:
449
- * 'blogs' - Array of located blog objects.
450
- * 'total' - A count of the total blogs matching the query.
451
  */
452
  public static function search_blogs( $filter, $limit = null, $page = null ) {
453
- global $wpdb;
454
 
455
- $search_terms_like = '%' . bp_esc_like( $filter ) . '%';
456
- $search_terms_sql = $wpdb->prepare( 'bm.meta_value LIKE %s', $search_terms_like );
457
 
458
  $hidden_sql = '';
459
  if ( !bp_current_user_can( 'bp_moderate' ) )
@@ -464,17 +353,10 @@ class BP_Blogs_Blog {
464
  $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
465
  }
466
 
467
- $bp = buddypress();
 
468
 
469
- $paged_blogs = $wpdb->get_results( "SELECT DISTINCT bm.blog_id FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE ( ( bm.meta_key = 'name' OR bm.meta_key = 'description' ) AND {$search_terms_sql} ) {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY meta_value ASC{$pag_sql}" );
470
- $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT bm.blog_id) FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE ( ( bm.meta_key = 'name' OR bm.meta_key = 'description' ) AND {$search_terms_sql} ) {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY meta_value ASC" );
471
-
472
- // Integer casting.
473
- foreach ( (array) $paged_blogs as $key => $data ) {
474
- $paged_blogs[ $key ]->blog_id = (int) $paged_blogs[ $key ]->blog_id;
475
- }
476
-
477
- return array( 'blogs' => $paged_blogs, 'total' => (int) $total_blogs );
478
  }
479
 
480
  /**
@@ -483,31 +365,24 @@ class BP_Blogs_Blog {
483
  * Query will include hidden blogs if the logged-in user has the
484
  * 'bp_moderate' cap.
485
  *
486
- * @param int|null $limit Optional. The maximum number of items to return.
487
- * Default: null (no limit).
488
- * @param int|null $page Optional. The page of results to return. Default:
489
- * null (no limit).
490
  * @return array Multidimensional results array, structured as follows:
491
- * 'blogs' - Array of located blog objects.
492
- * 'total' - A count of the total blogs.
493
  */
494
  public static function get_all( $limit = null, $page = null ) {
495
- global $wpdb;
496
-
497
- $bp = buddypress();
498
 
499
  $hidden_sql = !bp_current_user_can( 'bp_moderate' ) ? "AND wb.public = 1" : '';
500
- $pag_sql = ( $limit && $page ) ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ) : '';
501
 
502
  $paged_blogs = $wpdb->get_results( "SELECT DISTINCT b.blog_id FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql} {$pag_sql}" );
503
  $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql}" );
504
 
505
- // Integer casting.
506
- foreach ( (array) $paged_blogs as $key => $data ) {
507
- $paged_blogs[ $key ]->blog_id = (int) $paged_blogs[ $key ]->blog_id;
508
- }
509
-
510
- return array( 'blogs' => $paged_blogs, 'total' => (int) $total_blogs );
511
  }
512
 
513
  /**
@@ -516,40 +391,31 @@ class BP_Blogs_Blog {
516
  * Query will include hidden blogs if the logged-in user has the
517
  * 'bp_moderate' cap.
518
  *
519
- * @param string $letter The letter you're looking for.
520
- * @param int|null $limit Optional. The maximum number of items to return.
521
- * Default: null (no limit).
522
- * @param int|null $page Optional. The page of results to return. Default:
523
- * null (no limit).
524
  * @return array Multidimensional results array, structured as follows:
525
- * 'blogs' - Array of located blog objects.
526
- * 'total' - A count of the total blogs matching the query.
527
  */
528
  public static function get_by_letter( $letter, $limit = null, $page = null ) {
529
- global $wpdb;
530
-
531
- $bp = buddypress();
532
 
533
- $letter_like = '%' . bp_esc_like( $letter ) . '%';
534
- $letter_sql = $wpdb->prepare( 'bm.meta_value LIKE %s', $letter_like );
535
 
536
  $hidden_sql = '';
537
  if ( !bp_current_user_can( 'bp_moderate' ) )
538
  $hidden_sql = "AND wb.public = 1";
539
 
540
- $pag_sql = '';
541
  if ( $limit && $page )
542
  $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
543
 
544
- $paged_blogs = $wpdb->get_results( "SELECT DISTINCT bm.blog_id FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE bm.meta_key = 'name' AND {$letter_sql} {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY bm.meta_value ASC{$pag_sql}" );
545
- $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT bm.blog_id) FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE bm.meta_key = 'name' AND {$letter_sql} {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY bm.meta_value ASC" );
546
-
547
- // Integer casting.
548
- foreach ( (array) $paged_blogs as $key => $data ) {
549
- $paged_blogs[ $key ]->blog_id = (int) $paged_blogs[ $key ]->blog_id;
550
- }
551
 
552
- return array( 'blogs' => $paged_blogs, 'total' => (int) $total_blogs );
553
  }
554
 
555
  /**
@@ -561,15 +427,13 @@ class BP_Blogs_Blog {
561
  * - The latest post for each blog, include Featured Image data
562
  * - The blog description
563
  *
564
- * @param array $paged_blogs Array of results from the original query.
565
- * @param array $blog_ids Array of IDs returned from the original query.
566
- * @param string|bool $type Not currently used. Default: false.
567
  * @return array $paged_blogs The located blogs array, with the extras added.
568
  */
569
  public static function get_blog_extras( &$paged_blogs, &$blog_ids, $type = false ) {
570
- global $wpdb;
571
-
572
- $bp = buddypress();
573
 
574
  if ( empty( $blog_ids ) )
575
  return $paged_blogs;
@@ -581,7 +445,7 @@ class BP_Blogs_Blog {
581
  $paged_blogs[$i]->latest_post = $wpdb->get_row( "SELECT ID, post_content, post_title, post_excerpt, guid FROM {$blog_prefix}posts WHERE post_status = 'publish' AND post_type = 'post' AND id != 1 ORDER BY id DESC LIMIT 1" );
582
  $images = array();
583
 
584
- // Add URLs to any Featured Image this post might have.
585
  if ( ! empty( $paged_blogs[$i]->latest_post ) && has_post_thumbnail( $paged_blogs[$i]->latest_post->ID ) ) {
586
 
587
  // Grab 4 sizes of the image. Thumbnail.
@@ -589,22 +453,22 @@ class BP_Blogs_Blog {
589
  if ( ! empty( $image ) )
590
  $images['thumbnail'] = $image[0];
591
 
592
- // Medium.
593
  $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'medium', false );
594
  if ( ! empty( $image ) )
595
  $images['medium'] = $image[0];
596
 
597
- // Large.
598
  $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'large', false );
599
  if ( ! empty( $image ) )
600
  $images['large'] = $image[0];
601
 
602
- // Post thumbnail.
603
  $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'post-thumbnail', false );
604
  if ( ! empty( $image ) )
605
  $images['post-thumbnail'] = $image[0];
606
 
607
- // Add the images to the latest_post object.
608
  $paged_blogs[$i]->latest_post->images = $images;
609
  }
610
  }
@@ -648,9 +512,7 @@ class BP_Blogs_Blog {
648
  * @return int|bool ID of user-blog link, or false if not found.
649
  */
650
  public static function get_user_blog( $user_id, $blog_id ) {
651
- global $wpdb;
652
-
653
- $bp = buddypress();
654
 
655
  $user_blog = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $user_id, $blog_id ) );
656
 
1
  <?php
2
+
3
  /**
4
  * BuddyPress Blogs Classes.
5
  *
6
  * @package BuddyPress
7
  * @subpackage BlogsClasses
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
  * The main BuddyPress blog class.
16
  * A BP_Blogs_Object represents a link between a specific WordPress blog on a
17
  * network and a specific user on that blog.
18
  *
19
+ * @since BuddyPress (1.0.0)
20
  */
21
  class BP_Blogs_Blog {
 
 
 
 
 
 
22
  public $id;
 
 
 
 
 
 
23
  public $user_id;
 
 
 
 
 
 
24
  public $blog_id;
25
 
26
  /**
27
  * Constructor method.
28
  *
29
+ * @param int $id Optional. The ID of the blog.
30
  */
31
  public function __construct( $id = null ) {
32
  if ( !empty( $id ) ) {
33
+ $this->id = $id;
34
  $this->populate();
35
  }
36
  }
39
  * Populate the object with data about the specific activity item.
40
  */
41
  public function populate() {
42
+ global $wpdb, $bp;
 
 
43
 
44
  $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->blogs->table_name} WHERE id = %d", $this->id ) );
45
 
46
+ $this->user_id = $blog->user_id;
47
+ $this->blog_id = $blog->blog_id;
48
  }
49
 
50
  /**
53
  * @return bool True on success, false on failure.
54
  */
55
  public function save() {
56
+ global $wpdb, $bp;
57
 
 
 
 
 
 
 
 
 
58
  $this->user_id = apply_filters( 'bp_blogs_blog_user_id_before_save', $this->user_id, $this->id );
 
 
 
 
 
 
 
 
 
59
  $this->blog_id = apply_filters( 'bp_blogs_blog_id_before_save', $this->blog_id, $this->id );
60
 
 
 
 
 
 
 
 
 
 
61
  do_action_ref_array( 'bp_blogs_blog_before_save', array( &$this ) );
62
 
63
  // Don't try and save if there is no user ID or blog ID set.
68
  if ( !$this->id && $this->exists() )
69
  return false;
70
 
 
 
71
  if ( $this->id ) {
72
+ // Update
73
  $sql = $wpdb->prepare( "UPDATE {$bp->blogs->table_name} SET user_id = %d, blog_id = %d WHERE id = %d", $this->user_id, $this->blog_id, $this->id );
74
  } else {
75
+ // Save
76
  $sql = $wpdb->prepare( "INSERT INTO {$bp->blogs->table_name} ( user_id, blog_id ) VALUES ( %d, %d )", $this->user_id, $this->blog_id );
77
  }
78
 
79
  if ( !$wpdb->query($sql) )
80
  return false;
81
 
 
 
 
 
 
 
 
 
 
82
  do_action_ref_array( 'bp_blogs_blog_after_save', array( &$this ) );
83
 
84
  if ( $this->id )
90
  /**
91
  * Check whether an association between this user and this blog exists.
92
  *
93
+ * @return int The number of associations between the user and blog
94
+ * saved in the blog component tables.
95
  */
96
  public function exists() {
97
+ global $bp, $wpdb;
 
 
98
 
99
  return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $this->user_id, $this->blog_id ) );
100
  }
104
  /**
105
  * Retrieve a set of blog-user associations.
106
  *
107
+ * @param string $type The order in which results should be returned.
108
+ * 'active', 'alphabetical', 'newest', or 'random'.
109
+ * @param int|bool $limit Optional. The maximum records to return.
110
+ * Default: false.
111
+ * @param int|bool $page Optional. The page of records to return.
112
+ * Default: false (unlimited results).
113
+ * @param int $user_id Optional. ID of the user whose blogs are being
114
+ * retrieved. Default: 0.
115
+ * @param string|bool $search_terms Optional. Search by text stored in
116
+ * blogmeta (such as the blog name). Default: false.
117
+ * @param bool $update_meta_cache Whether to pre-fetch metadata for
118
+ * blogs. Default: true.
119
+ * @param array $include_blog_ids Array of blog IDs to include.
120
  * @return array Multidimensional results array, structured as follows:
121
+ * 'blogs' - Array of located blog objects
122
+ * 'total' - A count of the total blogs matching the filter params
123
  */
124
  public static function get( $type, $limit = false, $page = false, $user_id = 0, $search_terms = false, $update_meta_cache = true, $include_blog_ids = false ) {
125
+ global $bp, $wpdb;
 
 
126
 
127
  if ( !is_user_logged_in() || ( !bp_current_user_can( 'bp_moderate' ) && ( $user_id != bp_loggedin_user_id() ) ) )
128
  $hidden_sql = "AND wb.public = 1";
138
  $order_sql = "ORDER BY bm.meta_value DESC";
139
  break;
140
  case 'alphabetical':
141
+ $order_sql = "ORDER BY bm2.meta_value ASC";
142
  break;
143
  case 'newest':
144
  $order_sql = "ORDER BY wb.registered DESC";
155
  $include_sql = " AND b.blog_id IN ({$blog_ids_sql})";
156
  }
157
 
158
+ if ( !empty( $search_terms ) ) {
159
+ $filter = esc_sql( like_escape( $search_terms ) );
160
+ $paged_blogs = $wpdb->get_results( "SELECT b.blog_id, b.user_id as admin_user_id, u.user_email as admin_user_email, wb.domain, wb.path, bm.meta_value as last_activity, bm2.meta_value as name FROM {$bp->blogs->table_name} b, {$bp->blogs->table_name_blogmeta} bm, {$bp->blogs->table_name_blogmeta} bm2, {$wpdb->base_prefix}blogs wb, {$wpdb->users} u WHERE b.blog_id = wb.blog_id AND b.user_id = u.ID AND b.blog_id = bm.blog_id AND b.blog_id = bm2.blog_id AND wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql} AND bm.meta_key = 'last_activity' AND bm2.meta_key = 'name' AND bm2.meta_value LIKE '%%$filter%%' {$user_sql} {$include_sql} GROUP BY b.blog_id {$order_sql} {$pag_sql}" );
161
+ $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b, {$wpdb->base_prefix}blogs wb, {$bp->blogs->table_name_blogmeta} bm, {$bp->blogs->table_name_blogmeta} bm2 WHERE b.blog_id = wb.blog_id AND bm.blog_id = b.blog_id AND bm2.blog_id = b.blog_id AND wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql} AND bm.meta_key = 'name' AND bm2.meta_key = 'description' AND ( bm.meta_value LIKE '%%$filter%%' || bm2.meta_value LIKE '%%$filter%%' ) {$user_sql} {$include_sql}" );
162
  } else {
163
+ $paged_blogs = $wpdb->get_results( "SELECT b.blog_id, b.user_id as admin_user_id, u.user_email as admin_user_email, wb.domain, wb.path, bm.meta_value as last_activity, bm2.meta_value as name FROM {$bp->blogs->table_name} b, {$bp->blogs->table_name_blogmeta} bm, {$bp->blogs->table_name_blogmeta} bm2, {$wpdb->base_prefix}blogs wb, {$wpdb->users} u WHERE b.blog_id = wb.blog_id AND b.user_id = u.ID AND b.blog_id = bm.blog_id AND b.blog_id = bm2.blog_id {$user_sql} AND wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql} AND bm.meta_key = 'last_activity' AND bm2.meta_key = 'name' {$include_sql} GROUP BY b.blog_id {$order_sql} {$pag_sql}" );
164
+ $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b, {$wpdb->base_prefix}blogs wb WHERE b.blog_id = wb.blog_id {$user_sql} AND wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$include_sql} {$hidden_sql}" );
165
  }
166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  $blog_ids = array();
168
  foreach ( (array) $paged_blogs as $blog ) {
169
  $blog_ids[] = (int) $blog->blog_id;
171
 
172
  $paged_blogs = BP_Blogs_Blog::get_blog_extras( $paged_blogs, $blog_ids, $type );
173
 
 
 
 
 
 
 
174
  if ( $update_meta_cache ) {
175
  bp_blogs_update_meta_cache( $blog_ids );
176
  }
185
  * @return int|bool Number of rows deleted on success, false on failure.
186
  */
187
  public static function delete_blog_for_all( $blog_id ) {
188
+ global $wpdb, $bp;
189
 
190
  bp_blogs_delete_blogmeta( $blog_id );
 
 
 
191
  return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->blogs->table_name} WHERE blog_id = %d", $blog_id ) );
192
  }
193
 
194
  /**
195
  * Delete the record of a given blog for a specific user.
196
  *
197
+ * @param int $blog_id The blog being removed.
198
+ * @param int $user_id Optional. The ID of the user from whom the blog
199
+ * is being removed. If absent, defaults to the logged-in user ID.
200
  * @return int|bool Number of rows deleted on success, false on failure.
201
  */
202
  public static function delete_blog_for_user( $blog_id, $user_id = null ) {
203
+ global $wpdb, $bp;
204
 
205
  if ( !$user_id )
206
  $user_id = bp_loggedin_user_id();
207
 
 
 
208
  return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $user_id, $blog_id ) );
209
  }
210
 
211
  /**
212
  * Delete all of a user's blog associations in the BP tables.
213
  *
214
+ * @param int $user_id Optional. The ID of the user whose blog
215
+ * associations are being deleted. If absent, defaults to
216
+ * logged-in user ID.
217
  * @return int|bool Number of rows deleted on success, false on failure.
218
  */
219
  public static function delete_blogs_for_user( $user_id = null ) {
220
+ global $wpdb, $bp;
221
 
222
  if ( !$user_id )
223
  $user_id = bp_loggedin_user_id();
224
 
 
 
225
  return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->blogs->table_name} WHERE user_id = %d", $user_id ) );
226
  }
227
 
233
  * blogs that have been recorded by BuddyPress, while the WP function
234
  * does a true query of a user's blog capabilities.
235
  *
236
+ * @param int $user_id Optional. ID of the user whose blogs are being
237
+ * queried. Defaults to logged-in user.
238
+ * @param bool $show_hidden Optional. Whether to include blogs that are
239
+ * not marked public. Defaults to true when viewing one's own
240
+ * profile.
241
  * @return array Multidimensional results array, structured as follows:
242
+ * 'blogs' - Array of located blog objects
243
+ * 'total' - A count of the total blogs for the user.
244
  */
245
  public static function get_blogs_for_user( $user_id = 0, $show_hidden = false ) {
246
+ global $bp, $wpdb;
 
 
247
 
248
  if ( !$user_id )
249
  $user_id = bp_displayed_user_id();
259
  $user_blogs = array();
260
  foreach ( (array) $blogs as $blog ) {
261
  $user_blogs[$blog->blog_id] = new stdClass;
262
+ $user_blogs[$blog->blog_id]->id = $blog->id;
263
+ $user_blogs[$blog->blog_id]->blog_id = $blog->blog_id;
264
  $user_blogs[$blog->blog_id]->siteurl = ( is_ssl() ) ? 'https://' . $blog->domain . $blog->path : 'http://' . $blog->domain . $blog->path;
265
  $user_blogs[$blog->blog_id]->name = $blog->name;
266
  }
274
  * This method always includes hidden blogs.
275
  *
276
  * @param int $user_id Optional. ID of the user whose blogs are being
277
+ * queried. Defaults to logged-in user.
278
  * @return int The number of blogs associated with the user.
279
  */
280
  public static function get_blog_ids_for_user( $user_id = 0 ) {
281
+ global $bp, $wpdb;
 
 
282
 
283
  if ( !$user_id )
284
  $user_id = bp_displayed_user_id();
285
 
286
+ return $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM {$bp->blogs->table_name} WHERE user_id = %d", $user_id ) );
287
  }
288
 
289
  /**
291
  *
292
  * @param int $blog_id ID of the blog being queried.
293
  * @return int|null The ID of the first located entry in the BP table
294
+ * on success, otherwise null.
295
  */
296
  public static function is_recorded( $blog_id ) {
297
+ global $bp, $wpdb;
 
 
 
 
298
 
299
+ return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->blogs->table_name} WHERE blog_id = %d", $blog_id ) );
300
  }
301
 
302
  /**
306
  * $user_id parameter, or when the logged-in user has the bp_moderate
307
  * cap.
308
  *
309
+ * @param int $user_id Optional. ID of the user whose blogs are being
310
+ * queried. Defaults to logged-in user.
311
  * @return int Blog count for the user.
312
  */
313
  public static function total_blog_count_for_user( $user_id = null ) {
314
+ global $bp, $wpdb;
 
 
315
 
316
  if ( !$user_id )
317
  $user_id = bp_displayed_user_id();
330
  * Matches against blog names and descriptions, as stored in the BP
331
  * blogmeta table.
332
  *
333
+ * @param string $filter The search term.
334
+ * @param int $limit Optional. The maximum number of items to return.
335
+ * Default: null (no limit).
336
+ * @param int $page Optional. The page of results to return. Default:
337
+ * null (no limit).
338
  * @return array Multidimensional results array, structured as follows:
339
+ * 'blogs' - Array of located blog objects
340
+ * 'total' - A count of the total blogs matching the query.
341
  */
342
  public static function search_blogs( $filter, $limit = null, $page = null ) {
343
+ global $wpdb, $bp;
344
 
345
+ $filter = esc_sql( like_escape( $filter ) );
 
346
 
347
  $hidden_sql = '';
348
  if ( !bp_current_user_can( 'bp_moderate' ) )
353
  $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
354
  }
355
 
356
+ $paged_blogs = $wpdb->get_results( "SELECT DISTINCT bm.blog_id FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE ( ( bm.meta_key = 'name' OR bm.meta_key = 'description' ) AND bm.meta_value LIKE '%%$filter%%' ) {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY meta_value ASC{$pag_sql}" );
357
+ $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT bm.blog_id) FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE ( ( bm.meta_key = 'name' OR bm.meta_key = 'description' ) AND bm.meta_value LIKE '%%$filter%%' ) {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY meta_value ASC" );
358
 
359
+ return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
 
 
 
 
 
 
 
 
360
  }
361
 
362
  /**
365
  * Query will include hidden blogs if the logged-in user has the
366
  * 'bp_moderate' cap.
367
  *
368
+ * @param int $limit Optional. The maximum number of items to return.
369
+ * Default: null (no limit).
370
+ * @param int $page Optional. The page of results to return. Default:
371
+ * null (no limit).
372
  * @return array Multidimensional results array, structured as follows:
373
+ * 'blogs' - Array of located blog objects
374
+ * 'total' - A count of the total blogs.
375
  */
376
  public static function get_all( $limit = null, $page = null ) {
377
+ global $bp, $wpdb;
 
 
378
 
379
  $hidden_sql = !bp_current_user_can( 'bp_moderate' ) ? "AND wb.public = 1" : '';
380
+ $pag_sql = ( $limit && $page ) ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ) : '';
381
 
382
  $paged_blogs = $wpdb->get_results( "SELECT DISTINCT b.blog_id FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql} {$pag_sql}" );
383
  $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql}" );
384
 
385
+ return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
 
 
 
 
 
386
  }
387
 
388
  /**
391
  * Query will include hidden blogs if the logged-in user has the
392
  * 'bp_moderate' cap.
393
  *
394
+ * @param string $letter. The letter you're looking for.
395
+ * @param int $limit Optional. The maximum number of items to return.
396
+ * Default: null (no limit).
397
+ * @param int $page Optional. The page of results to return. Default:
398
+ * null (no limit).
399
  * @return array Multidimensional results array, structured as follows:
400
+ * 'blogs' - Array of located blog objects.
401
+ * 'total' - A count of the total blogs matching the query.
402
  */
403
  public static function get_by_letter( $letter, $limit = null, $page = null ) {
404
+ global $bp, $wpdb;
 
 
405
 
406
+ $letter = esc_sql( like_escape( $letter ) );
 
407
 
408
  $hidden_sql = '';
409
  if ( !bp_current_user_can( 'bp_moderate' ) )
410
  $hidden_sql = "AND wb.public = 1";
411
 
 
412
  if ( $limit && $page )
413
  $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
414
 
415
+ $paged_blogs = $wpdb->get_results( "SELECT DISTINCT bm.blog_id FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE bm.meta_key = 'name' AND bm.meta_value LIKE '$letter%%' {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY bm.meta_value ASC{$pag_sql}" );
416
+ $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT bm.blog_id) FROM {$bp->blogs->table_name_blogmeta} bm LEFT JOIN {$wpdb->base_prefix}blogs wb ON bm.blog_id = wb.blog_id WHERE bm.meta_key = 'name' AND bm.meta_value LIKE '$letter%%' {$hidden_sql} AND wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 ORDER BY bm.meta_value ASC" );
 
 
 
 
 
417
 
418
+ return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
419
  }
420
 
421
  /**
427
  * - The latest post for each blog, include Featured Image data
428
  * - The blog description
429
  *
430
+ * @param array $paged_blogs Array of results from the original query.
431
+ * @param array $blog_ids Array of IDs returned from the original query.
432
+ * @param string|bool $type Not currently used. Default: false.
433
  * @return array $paged_blogs The located blogs array, with the extras added.
434
  */
435
  public static function get_blog_extras( &$paged_blogs, &$blog_ids, $type = false ) {
436
+ global $bp, $wpdb;
 
 
437
 
438
  if ( empty( $blog_ids ) )
439
  return $paged_blogs;
445
  $paged_blogs[$i]->latest_post = $wpdb->get_row( "SELECT ID, post_content, post_title, post_excerpt, guid FROM {$blog_prefix}posts WHERE post_status = 'publish' AND post_type = 'post' AND id != 1 ORDER BY id DESC LIMIT 1" );
446
  $images = array();
447
 
448
+ // Add URLs to any Featured Image this post might have
449
  if ( ! empty( $paged_blogs[$i]->latest_post ) && has_post_thumbnail( $paged_blogs[$i]->latest_post->ID ) ) {
450
 
451
  // Grab 4 sizes of the image. Thumbnail.
453
  if ( ! empty( $image ) )
454
  $images['thumbnail'] = $image[0];
455
 
456
+ // Medium
457
  $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'medium', false );
458
  if ( ! empty( $image ) )
459
  $images['medium'] = $image[0];
460
 
461
+ // Large
462
  $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'large', false );
463
  if ( ! empty( $image ) )
464
  $images['large'] = $image[0];
465
 
466
+ // Post thumbnail
467
  $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'post-thumbnail', false );
468
  if ( ! empty( $image ) )
469
  $images['post-thumbnail'] = $image[0];
470
 
471
+ // Add the images to the latest_post object
472
  $paged_blogs[$i]->latest_post->images = $images;
473
  }
474
  }
512
  * @return int|bool ID of user-blog link, or false if not found.
513
  */
514
  public static function get_user_blog( $user_id, $blog_id ) {
515
+ global $bp, $wpdb;
 
 
516
 
517
  $user_blog = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $user_id, $blog_id ) );
518
 
bp-blogs/bp-blogs-filters.php CHANGED
@@ -1,10 +1,11 @@
1
  <?php
 
2
  /**
3
  * Filters related to the Blogs component.
4
  *
5
  * @package BuddyPress
6
- * @subpackage BlogFilters
7
- * @since 1.6.0
8
  */
9
 
10
  /** Display Filters **********************************************************/
@@ -23,115 +24,15 @@ add_filter( 'bp_blog_latest_post_content', 'prepend_attachment' );
23
  /**
24
  * Ensure that the 'Create a new site' link at wp-admin/my-sites.php points to the BP blog signup.
25
  *
26
- * @since 1.6.0
27
  *
 
28
  * returned value.
29
  *
30
  * @param string $url The original URL (points to wp-signup.php by default).
31
  * @return string The new URL.
32
  */
33
  function bp_blogs_creation_location( $url ) {
34
-
35
- /**
36
- * Filters the 'Create a new site' link URL.
37
- *
38
- * @since 1.6.0
39
- *
40
- * @param string $value URL for the 'Create a new site' signup page.
41
- */
42
- return apply_filters( 'bp_blogs_creation_location', trailingslashit( bp_get_blogs_directory_permalink() . 'create' ), $url );
43
  }
44
  add_filter( 'wp_signup_location', 'bp_blogs_creation_location' );
45
-
46
- /**
47
- * Only select comments by ID instead of all fields when using get_comments().
48
- *
49
- * @since 2.1.0
50
- *
51
- * @see bp_blogs_update_post_activity_meta()
52
- *
53
- * @param array $retval Current SQL clauses in array format.
54
- * @return array
55
- */
56
- function bp_blogs_comments_clauses_select_by_id( $retval ) {
57
- $retval['fields'] = 'comment_ID';
58
-
59
- return $retval;
60
- }
61
-
62
- /**
63
- * Check whether the current activity about a post or a comment can be published.
64
- *
65
- * Abstracted from the deprecated `bp_blogs_record_post()`.
66
- *
67
- * @since 2.2.0
68
- *
69
- * @param bool $return Whether the post should be published.
70
- * @param int $blog_id ID of the blog.
71
- * @param int $post_id ID of the post.
72
- * @param int $user_id ID of the post author.
73
- * @return bool True to authorize the post to be published, otherwise false.
74
- */
75
- function bp_blogs_post_pre_publish( $return = true, $blog_id = 0, $post_id = 0, $user_id = 0 ) {
76
- $bp = buddypress();
77
-
78
- // If blog is not trackable, do not record the activity.
79
- if ( ! bp_blogs_is_blog_trackable( $blog_id, $user_id ) ) {
80
- return false;
81
- }
82
-
83
- /*
84
- * Stop infinite loops with WordPress MU Sitewide Tags.
85
- * That plugin changed the way its settings were stored at some point. Thus the dual check.
86
- */
87
- $sitewide_tags_blog_settings = bp_core_get_root_option( 'sitewide_tags_blog' );
88
- if ( ! empty( $sitewide_tags_blog_settings ) ) {
89
- $st_options = maybe_unserialize( $sitewide_tags_blog_settings );
90
- $tags_blog_id = isset( $st_options['tags_blog_id'] ) ? $st_options['tags_blog_id'] : 0;
91
- } else {
92
- $tags_blog_id = bp_core_get_root_option( 'sitewide_tags_blog' );
93
- $tags_blog_id = intval( $tags_blog_id );
94
- }
95
-
96
- /**
97
- * Filters whether or not BuddyPress should block sitewide tags activity.
98
- *
99
- * @since 2.2.0
100
- *
101
- * @param bool $value Current status of the sitewide tags activity.
102
- */
103
- if ( (int) $blog_id == $tags_blog_id && apply_filters( 'bp_blogs_block_sitewide_tags_activity', true ) ) {
104
- return false;
105
- }
106
-
107
- /**
108
- * Filters whether or not the current blog is public.
109
- *
110
- * @since 2.2.0
111
- *
112
- * @param int $value Value from the blog_public option for the current blog.
113
- */
114
- $is_blog_public = apply_filters( 'bp_is_blog_public', (int) get_blog_option( $blog_id, 'blog_public' ) );
115
-
116
- if ( 0 === $is_blog_public && is_multisite() ) {
117
- return false;
118
- }
119
-
120
- return $return;
121
- }
122
- add_filter( 'bp_activity_post_pre_publish', 'bp_blogs_post_pre_publish', 10, 4 );
123
- add_filter( 'bp_activity_post_pre_comment', 'bp_blogs_post_pre_publish', 10, 4 );
124
-
125
- /**
126
- * Registers our custom thumb size with WP's Site Icon feature.
127
- *
128
- * @since 2.7.0
129
- *
130
- * @param array $sizes Current array of custom site icon sizes.
131
- * @return array
132
- */
133
- function bp_blogs_register_custom_site_icon_size( $sizes ) {
134
- $sizes[] = bp_core_avatar_thumb_width();
135
- return $sizes;
136
- }
137
- add_filter( 'site_icon_image_sizes', 'bp_blogs_register_custom_site_icon_size' );
1
  <?php
2
+
3
  /**
4
  * Filters related to the Blogs component.
5
  *
6
  * @package BuddyPress
7
+ * @subpackage Blogs
8
+ * @since BuddyPress (1.6.0)
9
  */
10
 
11
  /** Display Filters **********************************************************/
24
  /**
25
  * Ensure that the 'Create a new site' link at wp-admin/my-sites.php points to the BP blog signup.
26
  *
27
+ * @since BuddyPress (1.6.0)
28
  *
29
+ * @uses apply_filters() Filter 'bp_blogs_creation_location' to alter the
30
  * returned value.
31
  *
32
  * @param string $url The original URL (points to wp-signup.php by default).
33
  * @return string The new URL.
34
  */
35
  function bp_blogs_creation_location( $url ) {
36
+ return apply_filters( 'bp_blogs_creation_location', trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() . '/create', $url ) );
 
 
 
 
 
 
 
 
37
  }
38
  add_filter( 'wp_signup_location', 'bp_blogs_creation_location' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-blogs/bp-blogs-functions.php CHANGED
@@ -4,239 +4,97 @@
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsFunctions
7
- * @since 1.5.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Check whether the $bp global lists an activity directory page.
15
  *
16
- * @since 1.5.0
 
 
17
  *
18
  * @return bool True if set, false if empty.
19
  */
20
  function bp_blogs_has_directory() {
21
- $bp = buddypress();
22
 
23
  return (bool) !empty( $bp->pages->blogs->id );
24
  }
25
 
26
  /**
27
- * Retrieve a set of blogs.
28
  *
29
  * @see BP_Blogs_Blog::get() for a description of arguments and return value.
30
  *
31
- * @param array|string $args {
32
  * Arguments are listed here with their default values. For more
33
  * information about the arguments, see {@link BP_Blogs_Blog::get()}.
34
- * @type string $type Default: 'active'.
35
- * @type int|bool $user_id Default: false.
36
- * @type array $include_blog_ids Default: false.
37
- * @type string|bool $search_terms Default: false.
38
- * @type int $per_page Default: 20.
39
- * @type int $page Default: 1.
40
- * @type bool $update_meta_cache Whether to pre-fetch blogmeta. Default: true.
41
  * }
42
  * @return array See {@link BP_Blogs_Blog::get()}.
43
  */
44
  function bp_blogs_get_blogs( $args = '' ) {
45
 
46
- // Parse query arguments.
47
- $r = bp_parse_args( $args, array(
48
- 'type' => 'active', // 'active', 'alphabetical', 'newest', or 'random'
49
- 'include_blog_ids' => false, // Array of blog IDs to include
50
- 'user_id' => false, // Limit to blogs this user can post to
51
- 'search_terms' => false, // Limit to blogs matching these search terms
52
  'per_page' => 20, // The number of results to return per page
53
  'page' => 1, // The page to return if limiting per page
54
- 'update_meta_cache' => true // Whether to pre-fetch blogmeta
55
- ), 'blogs_get_blogs' );
56
-
57
- // Get the blogs.
58
- $blogs = BP_Blogs_Blog::get(
59
- $r['type'],
60
- $r['per_page'],
61
- $r['page'],
62
- $r['user_id'],
63
- $r['search_terms'],
64
- $r['update_meta_cache'],
65
- $r['include_blog_ids']
66
  );
67
 
68
- /**
69
- * Filters a set of blogs.
70
- *
71
- * @since 1.2.0
72
- *
73
- * @param array $blogs Array of blog data.
74
- * @param array $r Parsed query arguments.
75
- */
76
- return apply_filters( 'bp_blogs_get_blogs', $blogs, $r );
77
  }
78
 
79
  /**
80
  * Populate the BP blogs table with existing blogs.
81
  *
82
- * Warning: By default, this will remove all existing records from the BP
83
- * blogs and blogmeta tables before re-populating the tables.
84
- *
85
- * @since 1.0.0
86
- * @since 2.6.0 Accepts $args as a parameter.
87
- *
88
- * @param array $args {
89
- * Array of arguments.
90
- * @type int $offset The offset to use.
91
- * @type int $limit The number of blogs to record at one time.
92
- * @type array $blog_ids Blog IDs to record. If empty, all blogs will be recorded.
93
- * @type array $site_id The network site ID to use.
94
- * }
95
- *
96
- * @return bool
97
  */
98
- function bp_blogs_record_existing_blogs( $args = array() ) {
99
- global $wpdb;
100
-
101
- // Query for all sites in network.
102
- $r = bp_parse_args( $args, array(
103
- 'offset' => false === bp_get_option( '_bp_record_blogs_offset' ) ? 0 : bp_get_option( '_bp_record_blogs_offset' ),
104
- 'limit' => 50,
105
- 'blog_ids' => array(),
106
- 'site_id' => $wpdb->siteid
107
- ), 'record_existing_blogs' );
108
-
109
- // Truncate all BP blogs tables if starting fresh
110
- if ( empty( $r['offset'] ) && empty( $r['blog_ids'] ) ) {
111
- $bp = buddypress();
112
-
113
- // Truncate user blogs table
114
- $truncate = $wpdb->query( "TRUNCATE {$bp->blogs->table_name}" );
115
- if ( is_wp_error( $truncate ) ) {
116
- return false;
117
- }
118
 
119
- // Truncate user blogmeta table
120
- $truncate = $wpdb->query( "TRUNCATE {$bp->blogs->table_name_blogmeta}" );
121
- if ( is_wp_error( $truncate ) ) {
122
- return false;
123
- }
124
- }
125
 
126
- // Multisite
127
  if ( is_multisite() ) {
128
- $sql = array();
129
- $sql['select'] = $wpdb->prepare( "SELECT blog_id, last_updated FROM {$wpdb->base_prefix}blogs WHERE mature = 0 AND spam = 0 AND deleted = 0 AND site_id = %d", $r['site_id'] );
130
-
131
- // Omit root blog if large network
132
- if ( wp_is_large_network( 'users' ) ) {
133
- $sql['omit_root_blog'] = $wpdb->prepare( "AND blog_id != %d", bp_get_root_blog_id() );
134
- }
135
-
136
- // Filter by selected blog IDs
137
- if ( ! empty( $r['blog_ids'] ) ) {
138
- $in = implode( ',', wp_parse_id_list( $r['blog_ids'] ) );
139
- $sql['in'] = "AND blog_id IN ({$in})";
140
- }
141
-
142
- $sql['orderby'] = 'ORDER BY blog_id ASC';
143
-
144
- $sql['limit'] = $wpdb->prepare( "LIMIT %d", $r['limit'] );
145
-
146
- if ( ! empty( $r['offset'] ) ) {
147
- $sql['offset'] = $wpdb->prepare( "OFFSET %d", $r['offset'] );
148
- }
149
-
150
- $blogs = $wpdb->get_results( implode( ' ', $sql ) );
151
-
152
- // Record a single site.
153
  } else {
154
- // Just record blog for the current user only.
155
- $record = bp_blogs_record_blog( $wpdb->blogid, get_current_user_id(), true );
156
-
157
- if ( false === $record ) {
158
- return false;
159
- } else {
160
- return true;
161
- }
162
- }
163
-
164
- // Bail if there are no blogs
165
- if ( empty( $blogs ) ) {
166
- // Make sure we remove our offset marker
167
- if ( is_multisite() ) {
168
- bp_delete_option( '_bp_record_blogs_offset' );
169
- }
170
-
171
- return false;
172
- }
173
-
174
- // Loop through users of blogs and record the relationship.
175
- foreach ( (array) $blogs as $blog ) {
176
-
177
- // Ensure that the cache is clear after the table TRUNCATE above.
178
- wp_cache_delete( $blog->blog_id, 'blog_meta' );
179
-
180
- // Get all users.
181
- $users = get_users( array(
182
- 'blog_id' => $blog->blog_id,
183
- 'fields' => 'ID'
184
- ) );
185
-
186
- // Continue on if no users exist for this site (how did this happen?).
187
- if ( empty( $users ) ) {
188
- continue;
189
- }
190
-
191
- // Loop through users and record their relationship to this blog.
192
- foreach ( (array) $users as $user_id ) {
193
- bp_blogs_add_user_to_blog( $user_id, false, $blog->blog_id );
194
-
195
- // Clear cache
196
- bp_blogs_clear_blog_object_cache( $blog->blog_id, $user_id );
197
- }
198
-
199
- // Update blog last activity timestamp
200
- if ( ! empty( $blog->last_updated ) && false !== strtotime( $blog->last_updated ) ) {
201
- bp_blogs_update_blogmeta( $blog->blog_id, 'last_activity', $blog->last_updated );
202
- }
203
  }
204
 
205
- // See if we need to do this again
206
- if ( is_multisite() && empty( $r['blog_ids'] ) ) {
207
- $sql['offset'] = $wpdb->prepare( " OFFSET %d", $r['limit'] + $r['offset'] );
208
-
209
- // Check if there are more blogs to record
210
- $blog_ids = $wpdb->get_results( implode( ' ', $sql ) );
211
-
212
- // We have more blogs; record offset and re-run function
213
- if ( ! empty( $blog_ids ) ) {
214
- bp_update_option( '_bp_record_blogs_offset', $r['limit'] + $r['offset'] );
215
- bp_blogs_record_existing_blogs( array(
216
- 'offset' => $r['limit'] + $r['offset'],
217
- 'limit' => $r['limit'],
218
- 'blog_ids' => $r['blog_ids'],
219
- 'site_id' => $r['site_id']
220
- ) );
221
-
222
- // Bail since we have more blogs to record.
223
- return;
224
 
225
- // No more blogs; delete offset marker
226
- } else {
227
- bp_delete_option( '_bp_record_blogs_offset' );
 
 
 
 
 
228
  }
229
  }
230
-
231
- /**
232
- * Fires after the BP blogs tables have been populated with existing blogs.
233
- *
234
- * @since 2.4.0
235
- */
236
- do_action( 'bp_blogs_recorded_existing_blogs' );
237
-
238
- // No errors.
239
- return true;
240
  }
241
 
242
  /**
@@ -245,7 +103,9 @@ function bp_blogs_record_existing_blogs( $args = array() ) {
245
  * If $user_id is provided, you can restrict site from being recordable
246
  * only to particular users.
247
  *
248
- * @since 1.7.0
 
 
249
  *
250
  * @param int $blog_id ID of the blog being checked.
251
  * @param int $user_id Optional. ID of the user for whom access is being checked.
@@ -253,26 +113,9 @@ function bp_blogs_record_existing_blogs( $args = array() ) {
253
  */
254
  function bp_blogs_is_blog_recordable( $blog_id, $user_id = 0 ) {
255
 
256
- /**
257
- * Filters whether or not a blog is globally activity stream recordable.
258
- *
259
- * @since 1.7.0
260
- *
261
- * @param bool $value Whether or not recordable. Default true.
262
- * @param int $blog_id Current blog ID.
263
- */
264
  $recordable_globally = apply_filters( 'bp_blogs_is_blog_recordable', true, $blog_id );
265
 
266
  if ( !empty( $user_id ) ) {
267
- /**
268
- * Filters whether or not a blog is globally activity stream recordable for user.
269
- *
270
- * @since 1.7.0
271
- *
272
- * @param bool $recordable_globally Whether or not recordable.
273
- * @param int $blog_id Current blog ID.
274
- * @param int $user_id Current user ID.
275
- */
276
  $recordable_for_user = apply_filters( 'bp_blogs_is_blog_recordable_for_user', $recordable_globally, $blog_id, $user_id );
277
  } else {
278
  $recordable_for_user = $recordable_globally;
@@ -291,7 +134,10 @@ function bp_blogs_is_blog_recordable( $blog_id, $user_id = 0 ) {
291
  * If $user_id is provided, the developer can restrict site from
292
  * being trackable only to particular users.
293
  *
294
- * @since 1.7.0
 
 
 
295
  *
296
  * @param int $blog_id ID of the blog being checked.
297
  * @param int $user_id Optional. ID of the user for whom access is being checked.
@@ -299,27 +145,9 @@ function bp_blogs_is_blog_recordable( $blog_id, $user_id = 0 ) {
299
  */
300
  function bp_blogs_is_blog_trackable( $blog_id, $user_id = 0 ) {
301
 
302
- /**
303
- * Filters whether or not a blog is globally trackable.
304
- *
305
- * @since 1.7.0
306
- *
307
- * @param bool $value Whether or not trackable.
308
- * @param int $blog_id Current blog ID.
309
- */
310
  $trackable_globally = apply_filters( 'bp_blogs_is_blog_trackable', bp_blogs_is_blog_recordable( $blog_id, $user_id ), $blog_id );
311
 
312
  if ( !empty( $user_id ) ) {
313
-
314
- /**
315
- * Filters whether or not a blog is globally trackable for user.
316
- *
317
- * @since 1.7.0
318
- *
319
- * @param bool $value Whether or not trackable.
320
- * @param int $blog_id Current blog ID.
321
- * @param int $user_id Current user ID.
322
- */
323
  $trackable_for_user = apply_filters( 'bp_blogs_is_blog_trackable_for_user', $trackable_globally, $blog_id, $user_id );
324
  } else {
325
  $trackable_for_user = $trackable_globally;
@@ -335,12 +163,14 @@ function bp_blogs_is_blog_trackable( $blog_id, $user_id = 0 ) {
335
  /**
336
  * Make BuddyPress aware of a new site so that it can track its activity.
337
  *
338
- * @since 1.0.0
339
  *
340
- * @param int $blog_id ID of the blog being recorded.
341
- * @param int $user_id ID of the user for whom the blog is being recorded.
 
 
342
  * @param bool $no_activity Optional. Whether to skip recording an activity
343
- * item about this blog creation. Default: false.
344
  * @return bool|null Returns false on failure.
345
  */
346
  function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
@@ -353,12 +183,12 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
353
  return false;
354
 
355
  $name = get_blog_option( $blog_id, 'blogname' );
356
- $url = get_home_url( $blog_id );
357
 
358
  if ( empty( $name ) ) {
359
- $name = $url;
360
  }
361
 
 
362
  $description = get_blog_option( $blog_id, 'blogdescription' );
363
  $close_old_posts = get_blog_option( $blog_id, 'close_comments_for_old_posts' );
364
  $close_days_old = get_blog_option( $blog_id, 'close_comments_days_old' );
@@ -367,7 +197,7 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
367
  if ( ! empty( $thread_depth ) ) {
368
  $thread_depth = get_blog_option( $blog_id, 'thread_comments_depth' );
369
  } else {
370
- // Perhaps filter this?
371
  $thread_depth = 1;
372
  }
373
 
@@ -386,28 +216,21 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
386
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'thread_comments_depth', $thread_depth );
387
 
388
  $is_private = !empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ? false : true;
389
-
390
- /**
391
- * Filters whether or not a new blog is public.
392
- *
393
- * @since 1.5.0
394
- *
395
- * @param bool $is_private Whether or not blog is public.
396
- */
397
  $is_private = !apply_filters( 'bp_is_new_blog_public', !$is_private );
398
 
399
- /**
400
- * Fires after BuddyPress has been made aware of a new site for activity tracking.
401
- *
402
- * @since 1.0.0
403
- * @since 2.6.0 Added $no_activity as a parameter.
404
- *
405
- * @param BP_Blogs_Blog $recorded_blog Current blog being recorded. Passed by reference.
406
- * @param bool $is_private Whether or not the current blog being recorded is private.
407
- * @param bool $is_recorded Whether or not the current blog was recorded.
408
- * @param bool $no_activity Whether to skip recording an activity item for this blog creation.
409
- */
410
- do_action_ref_array( 'bp_blogs_new_blog', array( &$recorded_blog, $is_private, $is_recorded, $no_activity ) );
 
411
  }
412
  add_action( 'wpmu_new_blog', 'bp_blogs_record_blog', 10, 2 );
413
 
@@ -417,7 +240,7 @@ add_action( 'wpmu_new_blog', 'bp_blogs_record_blog', 10, 2 );
417
  * @global object $wpdb DB Layer.
418
  *
419
  * @param string $oldvalue Value before save. Passed by do_action() but
420
- * unused here.
421
  * @param string $newvalue Value to change meta to.
422
  */
423
  function bp_blogs_update_option_blogname( $oldvalue, $newvalue ) {
@@ -428,12 +251,12 @@ function bp_blogs_update_option_blogname( $oldvalue, $newvalue ) {
428
  add_action( 'update_option_blogname', 'bp_blogs_update_option_blogname', 10, 2 );
429
 
430
  /**
431
- * Update blog description in BuddyPress blogmeta table.
432
  *
433
  * @global object $wpdb DB Layer.
434
  *
435
  * @param string $oldvalue Value before save. Passed by do_action() but
436
- * unused here.
437
  * @param string $newvalue Value to change meta to.
438
  */
439
  function bp_blogs_update_option_blogdescription( $oldvalue, $newvalue ) {
@@ -446,12 +269,12 @@ add_action( 'update_option_blogdescription', 'bp_blogs_update_option_blogdescrip
446
  /**
447
  * Update "Close comments for old posts" option in BuddyPress blogmeta table.
448
  *
449
- * @since 2.0.0
450
  *
451
  * @global object $wpdb DB Layer.
452
  *
453
  * @param string $oldvalue Value before save. Passed by do_action() but
454
- * unused here.
455
  * @param string $newvalue Value to change meta to.
456
  */
457
  function bp_blogs_update_option_close_comments_for_old_posts( $oldvalue, $newvalue ) {
@@ -464,15 +287,15 @@ add_action( 'update_option_close_comments_for_old_posts', 'bp_blogs_update_optio
464
  /**
465
  * Update "Close comments after days old" option in BuddyPress blogmeta table.
466
  *
467
- * @since 2.0.0
468
  *
469
  * @global object $wpdb DB Layer.
470
  *
471
  * @param string $oldvalue Value before save. Passed by do_action() but
472
- * unused here.
473
  * @param string $newvalue Value to change meta to.
474
  */
475
- function bp_blogs_update_option_close_comments_days_old( $oldvalue, $newvalue ) {
476
  global $wpdb;
477
 
478
  bp_blogs_update_blogmeta( $wpdb->blogid, 'close_comments_days_old', $newvalue );
@@ -482,12 +305,12 @@ add_action( 'update_option_close_comments_days_old', 'bp_blogs_update_option_clo
482
  /**
483
  * When toggling threaded comments, update thread depth in blogmeta table.
484
  *
485
- * @since 2.0.0
486
  *
487
  * @global object $wpdb DB Layer.
488
  *
489
  * @param string $oldvalue Value before save. Passed by do_action() but
490
- * unused here.
491
  * @param string $newvalue Value to change meta to.
492
  */
493
  function bp_blogs_update_option_thread_comments( $oldvalue, $newvalue ) {
@@ -506,12 +329,12 @@ add_action( 'update_option_thread_comments', 'bp_blogs_update_option_thread_comm
506
  /**
507
  * When updating comment depth, update thread depth in blogmeta table.
508
  *
509
- * @since 2.0.0
510
  *
511
  * @global object $wpdb DB Layer.
512
  *
513
  * @param string $oldvalue Value before save. Passed by do_action() but
514
- * unused here.
515
  * @param string $newvalue Value to change meta to.
516
  */
517
  function bp_blogs_update_option_thread_comments_depth( $oldvalue, $newvalue ) {
@@ -526,299 +349,354 @@ function bp_blogs_update_option_thread_comments_depth( $oldvalue, $newvalue ) {
526
  add_action( 'update_option_thread_comments_depth', 'bp_blogs_update_option_thread_comments_depth', 10, 2 );
527
 
528
  /**
529
- * Syncs site icon URLs to blogmeta.
530
  *
531
- * @since 2.7.0
 
 
532
  *
533
- * @param int|string $old_value Old value
534
- * @param int|string $new_value New value
535
- */
536
- function bp_blogs_update_option_site_icon( $old_value, $new_value ) {
537
- if ( 0 === $new_value ) {
538
- bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_thumb', 0 );
539
- bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_full', 0 );
540
- } else {
541
- // Save site icon URL as blogmeta.
542
- bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_thumb', get_site_icon_url( bp_core_avatar_thumb_width() ) );
543
- bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_full', get_site_icon_url( bp_core_avatar_full_width() ) );
544
- }
545
- }
546
- add_action( 'update_option_site_icon', 'bp_blogs_update_option_site_icon', 10, 2 );
547
-
548
- /**
549
- * Deletes the 'url' blogmeta for a site.
550
  *
551
- * Hooked to 'refresh_blog_details', which is notably used when editing a site
552
- * under "Network Admin > Sites".
553
  *
554
- * @since 2.3.0
555
  *
556
- * @param int $site_id The site ID.
 
 
557
  */
558
- function bp_blogs_delete_url_blogmeta( $site_id = 0 ) {
559
- bp_blogs_delete_blogmeta( (int) $site_id, 'url' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  }
561
- add_action( 'refresh_blog_details', 'bp_blogs_delete_url_blogmeta' );
562
 
563
  /**
564
- * Record activity metadata about a published blog post.
565
- *
566
- * @since 2.2.0
567
  *
568
- * @param int $activity_id ID of the activity item.
569
- * @param WP_Post $post Post object.
570
- * @param array $args Array of arguments.
 
 
571
  */
572
- function bp_blogs_publish_post_activity_meta( $activity_id, $post, $args ) {
573
- if ( empty( $activity_id ) || 'post' != $post->post_type ) {
574
- return;
575
- }
576
 
577
- bp_activity_update_meta( $activity_id, 'post_title', $post->post_title );
 
578
 
579
- if ( ! empty( $args['post_url'] ) ) {
580
- $post_permalink = $args['post_url'];
 
 
 
 
 
 
 
 
 
 
581
  } else {
582
- $post_permalink = $post->guid;
583
  }
584
 
585
- bp_activity_update_meta( $activity_id, 'post_url', $post_permalink );
 
 
 
 
 
586
 
587
- // Update the blog's last activity.
588
- bp_blogs_update_blogmeta( $args['item_id'], 'last_activity', bp_core_current_time() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
 
590
- /**
591
- * Fires after BuddyPress has recorded metadata about a published blog post.
592
- *
593
- * @since 1.0.0
594
- *
595
- * @param int $ID ID of the blog post being recorded.
596
- * @param WP_Post $post WP_Post object for the current blog post.
597
- * @param string $value ID of the user associated with the current blog post.
598
- */
599
- do_action( 'bp_blogs_new_blog_post', $post->ID, $post, $args['user_id'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  }
601
- add_action( 'bp_activity_post_type_published', 'bp_blogs_publish_post_activity_meta', 10, 3 );
602
 
603
  /**
604
- * Updates a blog post's activity meta entry during a post edit.
 
 
605
  *
606
- * @since 2.2.0
607
- * @since 2.5.0 Add the post type tracking args object parameter
608
  *
609
- * @param WP_Post $post Post object.
610
- * @param BP_Activity_Activity $activity Activity object.
611
- * @param object $activity_post_object The post type tracking args object.
612
  */
613
- function bp_blogs_update_post_activity_meta( $post, $activity, $activity_post_object ) {
614
- if ( empty( $activity->id ) || empty( $activity_post_object->action_id ) ) {
615
  return;
616
  }
617
 
618
- // Update post title in activity meta.
619
- $existing_title = bp_activity_get_meta( $activity->id, 'post_title' );
620
- if ( $post->post_title !== $existing_title ) {
621
- bp_activity_update_meta( $activity->id, 'post_title', $post->post_title );
622
-
623
- if ( ! empty( $activity_post_object->comments_tracking->action_id ) ) {
624
- // Now update activity meta for post comments... sigh.
625
- add_filter( 'comments_clauses', 'bp_blogs_comments_clauses_select_by_id' );
626
- $comments = get_comments( array( 'post_id' => $post->ID ) );
627
- remove_filter( 'comments_clauses', 'bp_blogs_comments_clauses_select_by_id' );
628
-
629
- if ( ! empty( $comments ) ) {
630
- $activity_ids = array();
631
- $comment_ids = wp_list_pluck( $comments, 'comment_ID' );
632
-
633
- // Set up activity args.
634
- $args = array(
635
- 'update_meta_cache' => false,
636
- 'show_hidden' => true,
637
- 'per_page' => 99999,
638
- );
639
-
640
- // Query for old-style "new_blog_comment" activity items.
641
- $args['filter'] = array(
642
- 'object' => $activity_post_object->comments_tracking->component_id,
643
- 'action' => $activity_post_object->comments_tracking->action_id,
644
- 'secondary_id' => implode( ',', $comment_ids ),
645
- );
646
-
647
- $activities = bp_activity_get( $args );
648
- if ( ! empty( $activities['activities'] ) ) {
649
- $activity_ids = (array) wp_list_pluck( $activities['activities'], 'id' );
650
- }
651
-
652
- // Query for activity comments connected to a blog post.
653
- unset( $args['filter'] );
654
- $args['meta_query'] = array( array(
655
- 'key' => 'bp_blogs_' . $post->post_type . '_comment_id',
656
- 'value' => $comment_ids,
657
- 'compare' => 'IN',
658
- ) );
659
- $args['type'] = 'activity_comment';
660
- $args['display_comments'] = 'stream';
661
-
662
- $activities = bp_activity_get( $args );
663
- if ( ! empty( $activities['activities'] ) ) {
664
- $activity_ids = array_merge( $activity_ids, (array) wp_list_pluck( $activities['activities'], 'id' ) );
665
- }
666
-
667
- // Update activity meta for all found activity items.
668
- if ( ! empty( $activity_ids ) ) {
669
- foreach ( $activity_ids as $aid ) {
670
- bp_activity_update_meta( $aid, 'post_title', $post->post_title );
671
- }
672
- }
673
 
674
- unset( $activities, $activity_ids, $comment_ids, $comments );
675
- }
676
- }
677
  }
678
 
679
- // Add post comment status to activity meta if closed.
 
 
 
 
 
680
  if( 'closed' == $post->comment_status ) {
681
- bp_activity_update_meta( $activity->id, 'post_comment_status', $post->comment_status );
682
  } else {
683
- bp_activity_delete_meta( $activity->id, 'post_comment_status' );
684
  }
685
  }
686
- add_action( 'bp_activity_post_type_updated', 'bp_blogs_update_post_activity_meta', 10, 3 );
687
 
688
  /**
689
- * Update Activity and blogs meta and eventually sync comment with activity comment
690
  *
691
- * @since 2.5.0
692
  *
693
- * @param int|bool $activity_id ID of recorded activity, or false if sync is active.
694
- * @param WP_Comment|null $comment The comment object.
695
- * @param array $activity_args Array of activity arguments.
696
- * @param object|null $activity_post_object The post type tracking args object.
697
- * @return int|bool Returns false if no activity, the activity id otherwise.
698
  */
699
- function bp_blogs_comment_sync_activity_comment( &$activity_id, $comment = null, $activity_args = array(), $activity_post_object = null ) {
700
- if ( empty( $activity_args ) || empty( $comment->post->ID ) || empty( $activity_post_object->comment_action_id ) ) {
701
- return false;
 
702
  }
703
 
704
- // Set the current blog id.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
  $blog_id = get_current_blog_id();
706
 
707
- // These activity metadatas are used to build the new_blog_comment action string
708
- if ( ! empty( $activity_id ) && ! empty( $activity_args['item_id'] ) && 'new_blog_comment' === $activity_post_object->comment_action_id ) {
709
- // add some post info in activity meta
710
- bp_activity_update_meta( $activity_id, 'post_title', $comment->post->post_title );
711
- bp_activity_update_meta( $activity_id, 'post_url', esc_url_raw( add_query_arg( 'p', $comment->post->ID, home_url( '/' ) ) ) );
712
- }
713
 
714
- // Sync comment - activity comment
715
- if ( ! bp_disable_blogforum_comments() ) {
716
 
717
- if ( ! empty( $_REQUEST['action'] ) ) {
718
- $existing_activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
719
 
720
- if ( ! empty( $existing_activity_id ) ) {
721
- $activity_args['id'] = $existing_activity_id;
722
- }
723
- }
724
 
725
- if ( empty( $activity_post_object ) ) {
726
- $activity_post_object = bp_activity_get_post_type_tracking_args( $comment->post->post_type );
727
- }
728
 
729
- if ( isset( $activity_post_object->action_id ) && isset( $activity_post_object->component_id ) ) {
730
- // find the parent 'new_post_type' activity entry
731
- $parent_activity_id = bp_activity_get_activity_id( array(
732
- 'component' => $activity_post_object->component_id,
733
- 'type' => $activity_post_object->action_id,
734
- 'item_id' => $blog_id,
735
- 'secondary_item_id' => $comment->comment_post_ID
736
- ) );
737
 
738
- // Try to create a new activity item for the parent blog post.
739
- if ( empty( $parent_activity_id ) ) {
740
- $parent_activity_id = bp_activity_post_type_publish( $comment->post->ID, $comment->post );
741
- }
742
- }
743
 
744
- // we found the parent activity entry
745
- // so let's go ahead and reconfigure some activity args
746
- if ( ! empty( $parent_activity_id ) ) {
747
- // set the parent activity entry ID
748
- $activity_args['activity_id'] = $parent_activity_id;
749
 
750
- // now see if the WP parent comment has a BP activity ID
751
- $comment_parent = 0;
752
- if ( ! empty( $comment->comment_parent ) ) {
753
- $comment_parent = get_comment_meta( $comment->comment_parent, 'bp_activity_comment_id', true );
754
- }
755
 
756
- // WP parent comment does not have a BP activity ID
757
- // so set to 'new_' . post_type activity ID
758
- if ( empty( $comment_parent ) ) {
759
- $comment_parent = $parent_activity_id;
760
- }
 
 
761
 
762
- $activity_args['parent_id'] = $comment_parent;
763
- $activity_args['skip_notification'] = true;
 
 
 
 
764
 
765
- // could not find corresponding parent activity entry
766
- // so wipe out $args array
 
 
 
767
  } else {
768
- $activity_args = array();
769
- }
 
 
770
 
771
- // Record in activity streams
772
- if ( ! empty( $activity_args ) ) {
773
- $activity_id = bp_activity_new_comment( $activity_args );
 
 
 
 
 
 
 
 
 
774
 
775
- if ( empty( $activity_args['id'] ) ) {
776
- // The activity metadata to inform about the corresponding comment ID
777
- bp_activity_update_meta( $activity_id, "bp_blogs_{$comment->post->post_type}_comment_id", $comment->comment_ID );
 
 
778
 
779
- // The comment metadata to inform about the corresponding activity ID
780
- add_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', $activity_id );
 
 
 
781
 
782
- // These activity metadatas are used to build the new_blog_comment action string
783
- if ( 'new_blog_comment' === $activity_post_object->comment_action_id ) {
784
- bp_activity_update_meta( $activity_id, 'post_title', $comment->post->post_title );
785
- bp_activity_update_meta( $activity_id, 'post_url', esc_url_raw( add_query_arg( 'p', $comment->post->ID, home_url( '/' ) ) ) );
786
  }
 
 
 
 
 
 
 
 
 
787
  }
788
 
789
- /**
790
- * Fires after an activity comment is added from a WP post comment.
791
- *
792
- * @since 2.6.0
793
- *
794
- * @param int $activity_id The activity comment ID.
795
- * @param WP_Comment $post_type_comment WP Comment object.
796
- * @param array $activity_args Activity comment arguments.
797
- * @param object $activity_post_object The post type tracking args object.
798
- */
799
- do_action( 'bp_blogs_comment_sync_activity_comment', $activity_id, $comment, $activity_args, $activity_post_object );
 
 
 
 
 
 
 
800
  }
801
- }
802
 
803
- // Update the blogs last active date
804
- bp_blogs_update_blogmeta( $blog_id, 'last_activity', bp_core_current_time() );
805
-
806
- if ( 'new_blog_comment' === $activity_post_object->comment_action_id ) {
807
- /**
808
- * Fires after BuddyPress has recorded metadata about a published blog post comment.
809
- *
810
- * @since 2.5.0
811
- *
812
- * @param int $value Comment ID of the blog post comment being recorded.
813
- * @param WP_Post $post WP_Comment object for the current blog post.
814
- * @param string $value ID of the user associated with the current blog post comment.
815
- */
816
- do_action( 'bp_blogs_new_blog_comment', $comment->comment_ID, $comment, bp_loggedin_user_id() );
817
  }
818
 
819
- return $activity_id;
820
  }
821
- add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment', 10, 4 );
 
822
 
823
  /**
824
  * Record a user's association with a blog.
@@ -827,84 +705,40 @@ add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_com
827
  * set/changed ('add_user_to_blog', 'profile_update', 'user_register'). It
828
  * parses the changes, and records them as necessary in the BP blog tracker.
829
  *
830
- * BuddyPress does not track blogs for users with the 'subscriber' role by
831
- * default, though as of 2.1.0 you can filter 'bp_blogs_get_allowed_roles' to
832
- * modify this behavior.
833
  *
834
- * @param int $user_id The ID of the user.
835
- * @param string|bool $role User's WordPress role for this blog ID.
836
- * @param int $blog_id Blog ID user is being added to.
 
 
837
  * @return bool|null False on failure.
838
  */
839
  function bp_blogs_add_user_to_blog( $user_id, $role = false, $blog_id = 0 ) {
840
  global $wpdb;
841
 
842
- // If no blog ID was passed, use the root blog ID.
843
  if ( empty( $blog_id ) ) {
844
  $blog_id = isset( $wpdb->blogid ) ? $wpdb->blogid : bp_get_root_blog_id();
845
  }
846
 
847
- // If no role was passed, try to find the blog role.
848
  if ( empty( $role ) ) {
 
849
 
850
- // Get user capabilities.
851
- $key = $wpdb->get_blog_prefix( $blog_id ). 'capabilities';
852
- $user_roles = array_keys( (array) bp_get_user_meta( $user_id, $key, true ) );
853
-
854
- // User has roles so lets.
855
- if ( ! empty( $user_roles ) ) {
856
-
857
- // Get blog roles.
858
- $blog_roles = array_keys( bp_get_current_blog_roles() );
859
-
860
- // Look for blog only roles of the user.
861
- $intersect_roles = array_intersect( $user_roles, $blog_roles );
862
 
863
- // If there's a role in the array, use the first one. This isn't
864
- // very smart, but since roles aren't exactly hierarchical, and
865
- // WordPress does not yet have a UI for multiple user roles, it's
866
- // fine for now.
867
- if ( ! empty( $intersect_roles ) ) {
868
- $role = array_shift( $intersect_roles );
869
- }
870
- }
871
- }
872
-
873
- // Bail if no role was found or role is not in the allowed roles array.
874
- if ( empty( $role ) || ! in_array( $role, bp_blogs_get_allowed_roles() ) ) {
875
- return false;
876
  }
877
 
878
- // Record the blog activity for this user being added to this blog.
879
- bp_blogs_record_blog( $blog_id, $user_id, true );
880
  }
881
  add_action( 'add_user_to_blog', 'bp_blogs_add_user_to_blog', 10, 3 );
882
  add_action( 'profile_update', 'bp_blogs_add_user_to_blog' );
883
  add_action( 'user_register', 'bp_blogs_add_user_to_blog' );
884
 
885
- /**
886
- * The allowed blog roles a member must have to be recorded into the
887
- * `bp_user_blogs` pointer table.
888
- *
889
- * This added and was made filterable in BuddyPress 2.1.0 to make it easier
890
- * to extend the functionality of the Blogs component.
891
- *
892
- * @since 2.1.0
893
- *
894
- * @return string
895
- */
896
- function bp_blogs_get_allowed_roles() {
897
-
898
- /**
899
- * Filters the allowed roles a member must have to be recorded into bp_user_blogs pointer table.
900
- *
901
- * @since 2.1.0
902
- *
903
- * @param array $value Array of potential roles user needs.
904
- */
905
- return apply_filters( 'bp_blogs_get_allowed_roles', array( 'contributor', 'author', 'editor', 'administrator' ) );
906
- }
907
-
908
  /**
909
  * Remove a blog-user pair from BP's blog tracker.
910
  *
@@ -914,23 +748,23 @@ function bp_blogs_get_allowed_roles() {
914
  function bp_blogs_remove_user_from_blog( $user_id, $blog_id = 0 ) {
915
  global $wpdb;
916
 
917
- if ( empty( $blog_id ) ) {
918
  $blog_id = $wpdb->blogid;
919
- }
920
 
921
  bp_blogs_remove_blog_for_user( $user_id, $blog_id );
922
  }
923
  add_action( 'remove_user_from_blog', 'bp_blogs_remove_user_from_blog', 10, 2 );
924
 
925
  /**
926
- * Rehook WP's maybe_add_existing_user_to_blog with a later priority.
927
  *
928
  * WordPress catches add-user-to-blog requests at init:10. In some cases, this
929
  * can precede BP's Blogs component. This function bumps the priority of the
930
  * core function, so that we can be sure that the Blogs component is loaded
931
- * first. See https://buddypress.trac.wordpress.org/ticket/3916.
932
  *
933
- * @since 1.6.0
 
934
  */
935
  function bp_blogs_maybe_add_user_to_blog() {
936
  if ( ! is_multisite() )
@@ -947,29 +781,16 @@ add_action( 'init', 'bp_blogs_maybe_add_user_to_blog', 1 );
947
  * @param int $blog_id ID of the blog being removed.
948
  */
949
  function bp_blogs_remove_blog( $blog_id ) {
 
950
 
951
  $blog_id = (int) $blog_id;
952
-
953
- /**
954
- * Fires before a "blog created" item is removed from blogs
955
- * tracker and activity stream.
956
- *
957
- * @since 1.5.0
958
- *
959
- * @param int $blog_id ID of the blog having its item removed.
960
- */
961
  do_action( 'bp_blogs_before_remove_blog', $blog_id );
962
 
963
  BP_Blogs_Blog::delete_blog_for_all( $blog_id );
964
 
965
- /**
966
- * Fires after a "blog created" item has been removed from blogs
967
- * tracker and activity stream.
968
- *
969
- * @since 1.0.0
970
- *
971
- * @param int $blog_id ID of the blog who had its item removed.
972
- */
973
  do_action( 'bp_blogs_remove_blog', $blog_id );
974
  }
975
  add_action( 'delete_blog', 'bp_blogs_remove_blog' );
@@ -981,62 +802,89 @@ add_action( 'delete_blog', 'bp_blogs_remove_blog' );
981
  * @param int $blog_id ID of the blog being removed.
982
  */
983
  function bp_blogs_remove_blog_for_user( $user_id, $blog_id ) {
 
984
 
985
  $blog_id = (int) $blog_id;
986
  $user_id = (int) $user_id;
987
 
988
- /**
989
- * Fires before a blog is removed from the tracker for a specific user.
990
- *
991
- * @since 1.5.0
992
- *
993
- * @param int $blog_id ID of the blog being removed.
994
- * @param int $user_id ID of the user having the blog removed for.
995
- */
996
  do_action( 'bp_blogs_before_remove_blog_for_user', $blog_id, $user_id );
997
 
998
  BP_Blogs_Blog::delete_blog_for_user( $blog_id, $user_id );
999
 
1000
- /**
1001
- * Fires after a blog has been removed from the tracker for a specific user.
1002
- *
1003
- * @since 1.0.0
1004
- *
1005
- * @param int $blog_id ID of the blog that was removed.
1006
- * @param int $user_id ID of the user having the blog removed for.
1007
- */
1008
  do_action( 'bp_blogs_remove_blog_for_user', $blog_id, $user_id );
1009
  }
1010
  add_action( 'remove_user_from_blog', 'bp_blogs_remove_blog_for_user', 10, 2 );
1011
 
1012
  /**
1013
- * Remove a synced activity comment from the activity stream.
1014
- *
1015
- * @since 2.5.0
1016
  *
1017
- * @param bool $deleted True when a comment post type activity was successfully removed.
1018
- * @param int $comment_id ID of the comment to be removed.
1019
- * @param object $activity_post_object The post type tracking args object.
1020
- * @param string $activity_type The post type comment activity type.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1021
  *
1022
- * @return bool True on success. False on error.
1023
  */
1024
- function bp_blogs_post_type_remove_comment( $deleted, $comment_id, $activity_post_object, $activity_type = '' ) {
1025
- // Remove synced activity comments, if needed.
1026
- if ( ! bp_disable_blogforum_comments() ) {
1027
- // Get associated activity ID from comment meta
 
 
 
 
 
 
 
 
 
 
 
 
 
1028
  $activity_id = get_comment_meta( $comment_id, 'bp_activity_comment_id', true );
1029
 
1030
- /**
1031
- * Delete the associated activity comment & also remove
1032
- * child post comments and associated activity comments.
1033
- */
1034
- if ( ! empty( $activity_id ) ) {
1035
  // fetch the activity comments for the activity item
1036
  $activity = bp_activity_get( array(
1037
  'in' => $activity_id,
1038
  'display_comments' => 'stream',
1039
- 'spam' => 'all',
1040
  ) );
1041
 
1042
  // get all activity comment IDs for the pending deleted item
@@ -1056,46 +904,29 @@ function bp_blogs_post_type_remove_comment( $deleted, $comment_id, $activity_pos
1056
 
1057
  // rebuild activity comment tree
1058
  BP_Activity_Activity::rebuild_activity_comment_tree( $activity['activities'][0]->item_id );
1059
-
1060
- // Set the result
1061
- $deleted = true;
1062
  }
1063
  }
1064
  }
1065
 
1066
- // Backcompat for comments about the 'post' post type.
1067
- if ( 'new_blog_comment' === $activity_type ) {
1068
- /**
1069
- * Fires after a blog comment activity item was removed from activity stream.
1070
- *
1071
- * @since 1.0.0
1072
- *
1073
- * @param int $value ID for the blog associated with the removed comment.
1074
- * @param int $comment_id ID of the comment being removed.
1075
- * @param int $value ID of the current logged in user.
1076
- */
1077
- do_action( 'bp_blogs_remove_comment', get_current_blog_id(), $comment_id, bp_loggedin_user_id() );
1078
- }
1079
-
1080
- return $deleted;
1081
  }
1082
- add_action( 'bp_activity_post_type_remove_comment', 'bp_blogs_post_type_remove_comment', 10, 4 );
1083
 
1084
  /**
1085
  * Removes blog comments that are associated with activity comments.
1086
  *
1087
- * @since 2.0.0
1088
  *
1089
- * @see bp_blogs_remove_synced_comment()
1090
  * @see bp_blogs_sync_delete_from_activity_comment()
1091
  *
1092
  * @param array $activity_ids The activity IDs to check association with blog
1093
- * comments.
1094
- * @param bool $force_delete Whether to force delete the comments. If false,
1095
- * comments are trashed instead.
1096
  */
1097
  function bp_blogs_remove_associated_blog_comments( $activity_ids = array(), $force_delete = true ) {
1098
- // Query args.
1099
  $query_args = array(
1100
  'meta_query' => array(
1101
  array(
@@ -1106,31 +937,109 @@ function bp_blogs_remove_associated_blog_comments( $activity_ids = array(), $for
1106
  )
1107
  );
1108
 
1109
- // Get comment.
1110
  $comment_query = new WP_Comment_Query;
1111
  $comments = $comment_query->query( $query_args );
1112
 
1113
- // Found the corresponding comments
1114
  // let's delete them!
1115
  foreach ( $comments as $comment ) {
1116
  wp_delete_comment( $comment->comment_ID, $force_delete );
1117
 
1118
- // If we're trashing the comment, remove the meta key as well.
1119
  if ( empty( $force_delete ) ) {
1120
  delete_comment_meta( $comment->comment_ID, 'bp_activity_comment_id' );
1121
  }
1122
  }
1123
  }
1124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1125
  /**
1126
  * Get the total number of blogs being tracked by BuddyPress.
1127
  *
1128
  * @return int $count Total blog count.
1129
  */
1130
  function bp_blogs_total_blogs() {
1131
- $count = wp_cache_get( 'bp_total_blogs', 'bp' );
1132
-
1133
- if ( false === $count ) {
1134
  $blogs = BP_Blogs_Blog::get_all();
1135
  $count = $blogs['total'];
1136
  wp_cache_set( 'bp_total_blogs', $count, 'bp' );
@@ -1141,24 +1050,16 @@ function bp_blogs_total_blogs() {
1141
  /**
1142
  * Get the total number of blogs being tracked by BP for a specific user.
1143
  *
1144
- * @since 1.2.0
1145
- *
1146
  * @param int $user_id ID of the user being queried. Default: on a user page,
1147
- * the displayed user. Otherwise, the logged-in user.
1148
  * @return int $count Total blog count for the user.
1149
  */
1150
  function bp_blogs_total_blogs_for_user( $user_id = 0 ) {
1151
- if ( empty( $user_id ) ) {
1152
- $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
1153
- }
1154
 
1155
- // No user ID? do not attempt to look at cache.
1156
- if ( empty( $user_id ) ) {
1157
- return 0;
1158
- }
1159
 
1160
- $count = wp_cache_get( 'bp_total_blogs_for_user_' . $user_id, 'bp' );
1161
- if ( false === $count ) {
1162
  $count = BP_Blogs_Blog::total_blog_count_for_user( $user_id );
1163
  wp_cache_set( 'bp_total_blogs_for_user_' . $user_id, $count, 'bp' );
1164
  }
@@ -1172,28 +1073,16 @@ function bp_blogs_total_blogs_for_user( $user_id = 0 ) {
1172
  * @param int $blog_id The ID of the blog to expunge.
1173
  */
1174
  function bp_blogs_remove_data_for_blog( $blog_id ) {
 
1175
 
1176
- /**
1177
- * Fires before all data related to a given blog is removed from blogs tracker
1178
- * and activity stream.
1179
- *
1180
- * @since 1.5.0
1181
- *
1182
- * @param int $blog_id ID of the blog whose data is being removed.
1183
- */
1184
  do_action( 'bp_blogs_before_remove_data_for_blog', $blog_id );
1185
 
1186
  // If this is regular blog, delete all data for that blog.
1187
  BP_Blogs_Blog::delete_blog_for_all( $blog_id );
1188
 
1189
- /**
1190
- * Fires after all data related to a given blog has been removed from blogs tracker
1191
- * and activity stream.
1192
- *
1193
- * @since 1.0.0
1194
- *
1195
- * @param int $blog_id ID of the blog whose data is being removed.
1196
- */
1197
  do_action( 'bp_blogs_remove_data_for_blog', $blog_id );
1198
  }
1199
  add_action( 'delete_blog', 'bp_blogs_remove_data_for_blog', 1 );
@@ -1204,7 +1093,7 @@ add_action( 'delete_blog', 'bp_blogs_remove_data_for_blog', 1 );
1204
  * @see BP_Blogs_Blog::get_blogs_for_user() for a description of parameters
1205
  * and return values.
1206
  *
1207
- * @param int $user_id See {@BP_Blogs_Blog::get_blogs_for_user()}.
1208
  * @param bool $show_hidden See {@BP_Blogs_Blog::get_blogs_for_user()}.
1209
  * @return array See {@BP_Blogs_Blog::get_blogs_for_user()}.
1210
  */
@@ -1217,8 +1106,8 @@ function bp_blogs_get_blogs_for_user( $user_id, $show_hidden = false ) {
1217
  *
1218
  * @see BP_Blogs_Blog::get_all() for a description of parameters and return values.
1219
  *
1220
- * @param int|null $limit See {@BP_Blogs_Blog::get_all()}.
1221
- * @param int|null $page See {@BP_Blogs_Blog::get_all()}.
1222
  * @return array See {@BP_Blogs_Blog::get_all()}.
1223
  */
1224
  function bp_blogs_get_all_blogs( $limit = null, $page = null ) {
@@ -1230,8 +1119,8 @@ function bp_blogs_get_all_blogs( $limit = null, $page = null ) {
1230
  *
1231
  * @see BP_Blogs_Blog::get() for a description of parameters and return values.
1232
  *
1233
- * @param int|null $limit See {@BP_Blogs_Blog::get()}.
1234
- * @param int|null $page See {@BP_Blogs_Blog::get()}.
1235
  * @return array See {@BP_Blogs_Blog::get()}.
1236
  */
1237
  function bp_blogs_get_random_blogs( $limit = null, $page = null ) {
@@ -1250,7 +1139,7 @@ function bp_blogs_is_blog_hidden( $blog_id ) {
1250
  return BP_Blogs_Blog::is_hidden( $blog_id );
1251
  }
1252
 
1253
- /*
1254
  * Blog meta functions
1255
  *
1256
  * These functions are used to store specific blogmeta in one global table,
@@ -1260,26 +1149,26 @@ function bp_blogs_is_blog_hidden( $blog_id ) {
1260
  */
1261
 
1262
  /**
1263
- * Delete a metadata from the DB for a blog.
1264
  *
1265
  * @global object $wpdb WordPress database access object.
1266
- *
1267
- * @param int $blog_id ID of the blog whose metadata is being deleted.
1268
- * @param string|bool $meta_key Optional. The key of the metadata being deleted. If
1269
- * omitted, all BP metadata associated with the blog will
1270
- * be deleted.
1271
- * @param string|bool $meta_value Optional. If present, the metadata will only be
1272
- * deleted if the meta_value matches this parameter.
1273
- * @param bool $delete_all Optional. If true, delete matching metadata entries for
1274
- * all objects, ignoring the specified blog_id. Otherwise, only
1275
- * delete matching metadata entries for the specified blog.
1276
- * Default: false.
1277
  * @return bool True on success, false on failure.
1278
  */
1279
  function bp_blogs_delete_blogmeta( $blog_id, $meta_key = false, $meta_value = false, $delete_all = false ) {
1280
- global $wpdb;
1281
 
1282
- // Legacy - if no meta_key is passed, delete all for the blog_id.
1283
  if ( empty( $meta_key ) ) {
1284
  $keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$wpdb->blogmeta} WHERE blog_id = %d", $blog_id ) );
1285
  $delete_all = false;
@@ -1302,17 +1191,18 @@ function bp_blogs_delete_blogmeta( $blog_id, $meta_key = false, $meta_value = fa
1302
  /**
1303
  * Get metadata for a given blog.
1304
  *
1305
- * @since 1.2.0
1306
  *
1307
  * @global object $wpdb WordPress database access object.
 
1308
  *
1309
- * @param int $blog_id ID of the blog whose metadata is being requested.
1310
  * @param string $meta_key Optional. If present, only the metadata matching
1311
- * that meta key will be returned. Otherwise, all
1312
- * metadata for the blog will be fetched.
1313
- * @param bool $single Optional. If true, return only the first value of the
1314
- * specified meta_key. This parameter has no effect if
1315
- * meta_key is not specified. Default: true.
1316
  * @return mixed The meta value(s) being requested.
1317
  */
1318
  function bp_blogs_get_blogmeta( $blog_id, $meta_key = '', $single = true ) {
@@ -1327,16 +1217,17 @@ function bp_blogs_get_blogmeta( $blog_id, $meta_key = '', $single = true ) {
1327
  * Update a piece of blog meta.
1328
  *
1329
  * @global object $wpdb WordPress database access object.
1330
- *
1331
- * @param int $blog_id ID of the blog whose metadata is being updated.
1332
- * @param string $meta_key Key of the metadata being updated.
1333
- * @param mixed $meta_value Value to be set.
1334
- * @param mixed $prev_value Optional. If specified, only update existing
1335
- * metadata entries with the specified value.
1336
- * Otherwise, update all entries.
 
1337
  * @return bool|int Returns false on failure. On successful update of existing
1338
- * metadata, returns true. On successful creation of new metadata,
1339
- * returns the integer ID of the new metadata row.
1340
  */
1341
  function bp_blogs_update_blogmeta( $blog_id, $meta_key, $meta_value, $prev_value = '' ) {
1342
  add_filter( 'query', 'bp_filter_metaid_column_name' );
@@ -1349,14 +1240,14 @@ function bp_blogs_update_blogmeta( $blog_id, $meta_key, $meta_value, $prev_value
1349
  /**
1350
  * Add a piece of blog metadata.
1351
  *
1352
- * @since 2.0.0
1353
  *
1354
- * @param int $blog_id ID of the blog.
1355
- * @param string $meta_key Metadata key.
1356
- * @param mixed $meta_value Metadata value.
1357
- * @param bool $unique Optional. Whether to enforce a single metadata value
1358
- * for the given key. If true, and the object already has a value for
1359
- * the key, no change will be made. Default: false.
1360
  * @return int|bool The meta ID on successful update, false on failure.
1361
  */
1362
  function bp_blogs_add_blogmeta( $blog_id, $meta_key, $meta_value, $unique = false ) {
@@ -1370,59 +1261,19 @@ function bp_blogs_add_blogmeta( $blog_id, $meta_key, $meta_value, $unique = fals
1370
  * Remove all blog associations for a given user.
1371
  *
1372
  * @param int $user_id ID whose blog data should be removed.
1373
- * @return bool Returns false on failure.
1374
  */
1375
  function bp_blogs_remove_data( $user_id ) {
1376
  if ( !is_multisite() )
1377
  return false;
1378
 
1379
- /**
1380
- * Fires before all blog associations are removed for a given user.
1381
- *
1382
- * @since 1.5.0
1383
- *
1384
- * @param int $user_id ID of the user whose blog associations are being removed.
1385
- */
1386
  do_action( 'bp_blogs_before_remove_data', $user_id );
1387
 
1388
  // If this is regular blog, delete all data for that blog.
1389
  BP_Blogs_Blog::delete_blogs_for_user( $user_id );
1390
 
1391
- /**
1392
- * Fires after all blog associations are removed for a given user.
1393
- *
1394
- * @since 1.0.0
1395
- *
1396
- * @param int $user_id ID of the user whose blog associations were removed.
1397
- */
1398
  do_action( 'bp_blogs_remove_data', $user_id );
1399
  }
1400
  add_action( 'wpmu_delete_user', 'bp_blogs_remove_data' );
1401
  add_action( 'delete_user', 'bp_blogs_remove_data' );
1402
  add_action( 'bp_make_spam_user', 'bp_blogs_remove_data' );
1403
-
1404
- /**
1405
- * Restore all blog associations for a given user.
1406
- *
1407
- * @since 2.2.0
1408
- *
1409
- * @param int $user_id ID whose blog data should be restored.
1410
- */
1411
- function bp_blogs_restore_data( $user_id = 0 ) {
1412
- if ( ! is_multisite() ) {
1413
- return;
1414
- }
1415
-
1416
- // Get the user's blogs.
1417
- $user_blogs = get_blogs_of_user( $user_id );
1418
- if ( empty( $user_blogs ) ) {
1419
- return;
1420
- }
1421
-
1422
- $blogs = array_keys( $user_blogs );
1423
-
1424
- foreach ( $blogs as $blog_id ) {
1425
- bp_blogs_add_user_to_blog( $user_id, false, $blog_id );
1426
- }
1427
- }
1428
- add_action( 'bp_make_ham_user', 'bp_blogs_restore_data', 10, 1 );
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsFunctions
 
7
  */
8
 
9
+ // Exit if accessed directly
10
+ if ( !defined( 'ABSPATH' ) ) exit;
11
 
12
  /**
13
  * Check whether the $bp global lists an activity directory page.
14
  *
15
+ * @since BuddyPress (1.5.0)
16
+ *
17
+ * @global BuddyPress $bp The one true BuddyPress instance.
18
  *
19
  * @return bool True if set, false if empty.
20
  */
21
  function bp_blogs_has_directory() {
22
+ global $bp;
23
 
24
  return (bool) !empty( $bp->pages->blogs->id );
25
  }
26
 
27
  /**
28
+ * Retrieve a set of blogs
29
  *
30
  * @see BP_Blogs_Blog::get() for a description of arguments and return value.
31
  *
32
+ * @param array $args {
33
  * Arguments are listed here with their default values. For more
34
  * information about the arguments, see {@link BP_Blogs_Blog::get()}.
35
+ * @type string $type Default: 'active'.
36
+ * @type int|bool $user_id Default: false.
37
+ * @type array $include_blog_ids Default: false.
38
+ * @type string|bool $search_terms Default: false.
39
+ * @type int $per_page Default: 20.
40
+ * @type int $page Default: 1.
41
+ * @type bool $update_meta_cache Whether to pre-fetch blogmeta. Default: true.
42
  * }
43
  * @return array See {@link BP_Blogs_Blog::get()}.
44
  */
45
  function bp_blogs_get_blogs( $args = '' ) {
46
 
47
+ $defaults = array(
48
+ 'type' => 'active', // active, alphabetical, newest, or random
49
+ 'user_id' => false, // Pass a user_id to limit to only blogs that this user has privilages higher than subscriber on
50
+ 'include_blog_ids' => false,
51
+ 'search_terms' => false, // Limit to blogs that match these search terms
 
52
  'per_page' => 20, // The number of results to return per page
53
  'page' => 1, // The page to return if limiting per page
54
+ 'update_meta_cache' => true,
 
 
 
 
 
 
 
 
 
 
 
55
  );
56
 
57
+ $params = wp_parse_args( $args, $defaults );
58
+ extract( $params, EXTR_SKIP );
59
+
60
+ return apply_filters( 'bp_blogs_get_blogs', BP_Blogs_Blog::get( $type, $per_page, $page, $user_id, $search_terms, $update_meta_cache, $include_blog_ids ), $params );
 
 
 
 
 
61
  }
62
 
63
  /**
64
  * Populate the BP blogs table with existing blogs.
65
  *
66
+ * @global object $bp BuddyPress global settings
67
+ * @global object $wpdb WordPress database object
68
+ * @uses get_users()
69
+ * @uses bp_blogs_record_blog()
 
 
 
 
 
 
 
 
 
 
 
70
  */
71
+ function bp_blogs_record_existing_blogs() {
72
+ global $bp, $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ // Truncate user blogs table and re-record.
75
+ $wpdb->query( "DELETE FROM {$bp->blogs->table_name} WHERE 1=1" );
 
 
 
 
76
 
 
77
  if ( is_multisite() ) {
78
+ $blog_ids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM {$wpdb->base_prefix}blogs WHERE mature = 0 AND spam = 0 AND deleted = 0 AND site_id = %d", $wpdb->siteid ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  } else {
80
+ $blog_ids = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
+ if ( !empty( $blog_ids ) ) {
84
+ foreach( (array) $blog_ids as $blog_id ) {
85
+ $users = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ID' ) );
86
+ $subscribers = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ID', 'role' => 'subscriber' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ if ( !empty( $users ) ) {
89
+ foreach ( (array) $users as $user ) {
90
+ // Don't record blogs for subscribers
91
+ if ( !in_array( $user, $subscribers ) ) {
92
+ bp_blogs_record_blog( $blog_id, $user, true );
93
+ }
94
+ }
95
+ }
96
  }
97
  }
 
 
 
 
 
 
 
 
 
 
98
  }
99
 
100
  /**
103
  * If $user_id is provided, you can restrict site from being recordable
104
  * only to particular users.
105
  *
106
+ * @since BuddyPress (1.7.0)
107
+ *
108
+ * @uses apply_filters()
109
  *
110
  * @param int $blog_id ID of the blog being checked.
111
  * @param int $user_id Optional. ID of the user for whom access is being checked.
113
  */
114
  function bp_blogs_is_blog_recordable( $blog_id, $user_id = 0 ) {
115
 
 
 
 
 
 
 
 
 
116
  $recordable_globally = apply_filters( 'bp_blogs_is_blog_recordable', true, $blog_id );
117
 
118
  if ( !empty( $user_id ) ) {
 
 
 
 
 
 
 
 
 
119
  $recordable_for_user = apply_filters( 'bp_blogs_is_blog_recordable_for_user', $recordable_globally, $blog_id, $user_id );
120
  } else {
121
  $recordable_for_user = $recordable_globally;
134
  * If $user_id is provided, the developer can restrict site from
135
  * being trackable only to particular users.
136
  *
137
+ * @since BuddyPress (1.7.0)
138
+ *
139
+ * @uses bp_blogs_is_blog_recordable
140
+ * @uses apply_filters()
141
  *
142
  * @param int $blog_id ID of the blog being checked.
143
  * @param int $user_id Optional. ID of the user for whom access is being checked.
145
  */
146
  function bp_blogs_is_blog_trackable( $blog_id, $user_id = 0 ) {
147
 
 
 
 
 
 
 
 
 
148
  $trackable_globally = apply_filters( 'bp_blogs_is_blog_trackable', bp_blogs_is_blog_recordable( $blog_id, $user_id ), $blog_id );
149
 
150
  if ( !empty( $user_id ) ) {
 
 
 
 
 
 
 
 
 
 
151
  $trackable_for_user = apply_filters( 'bp_blogs_is_blog_trackable_for_user', $trackable_globally, $blog_id, $user_id );
152
  } else {
153
  $trackable_for_user = $trackable_globally;
163
  /**
164
  * Make BuddyPress aware of a new site so that it can track its activity.
165
  *
166
+ * @since BuddyPress (1.0.0)
167
  *
168
+ * @uses BP_Blogs_Blog
169
+ *
170
+ * @param int $blog_id ID of the blog being recorded.
171
+ * @param int $user_id ID of the user for whom the blog is being recorded.
172
  * @param bool $no_activity Optional. Whether to skip recording an activity
173
+ * item about this blog creation. Default: false.
174
  * @return bool|null Returns false on failure.
175
  */
176
  function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
183
  return false;
184
 
185
  $name = get_blog_option( $blog_id, 'blogname' );
 
186
 
187
  if ( empty( $name ) ) {
188
+ return false;
189
  }
190
 
191
+ $url = get_home_url( $blog_id );
192
  $description = get_blog_option( $blog_id, 'blogdescription' );
193
  $close_old_posts = get_blog_option( $blog_id, 'close_comments_for_old_posts' );
194
  $close_days_old = get_blog_option( $blog_id, 'close_comments_days_old' );
197
  if ( ! empty( $thread_depth ) ) {
198
  $thread_depth = get_blog_option( $blog_id, 'thread_comments_depth' );
199
  } else {
200
+ // perhaps filter this?
201
  $thread_depth = 1;
202
  }
203
 
216
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'thread_comments_depth', $thread_depth );
217
 
218
  $is_private = !empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ? false : true;
 
 
 
 
 
 
 
 
219
  $is_private = !apply_filters( 'bp_is_new_blog_public', !$is_private );
220
 
221
+ // Only record this activity if the blog is public
222
+ if ( !$is_private && !$no_activity && bp_blogs_is_blog_trackable( $blog_id, $user_id ) ) {
223
+
224
+ // Record this in activity streams
225
+ bp_blogs_record_activity( array(
226
+ 'user_id' => $recorded_blog->user_id,
227
+ 'primary_link' => apply_filters( 'bp_blogs_activity_created_blog_primary_link', $url, $recorded_blog->blog_id ),
228
+ 'type' => 'new_blog',
229
+ 'item_id' => $recorded_blog->blog_id
230
+ ) );
231
+ }
232
+
233
+ do_action_ref_array( 'bp_blogs_new_blog', array( &$recorded_blog, $is_private, $is_recorded ) );
234
  }
235
  add_action( 'wpmu_new_blog', 'bp_blogs_record_blog', 10, 2 );
236
 
240
  * @global object $wpdb DB Layer.
241
  *
242
  * @param string $oldvalue Value before save. Passed by do_action() but
243
+ * unused here.
244
  * @param string $newvalue Value to change meta to.
245
  */
246
  function bp_blogs_update_option_blogname( $oldvalue, $newvalue ) {
251
  add_action( 'update_option_blogname', 'bp_blogs_update_option_blogname', 10, 2 );
252
 
253
  /**
254
+ * Update blog description in BuddyPress blogmeta table
255
  *
256
  * @global object $wpdb DB Layer.
257
  *
258
  * @param string $oldvalue Value before save. Passed by do_action() but
259
+ * unused here.
260
  * @param string $newvalue Value to change meta to.
261
  */
262
  function bp_blogs_update_option_blogdescription( $oldvalue, $newvalue ) {
269
  /**
270
  * Update "Close comments for old posts" option in BuddyPress blogmeta table.
271
  *
272
+ * @since BuddyPress (2.0.0)
273
  *
274
  * @global object $wpdb DB Layer.
275
  *
276
  * @param string $oldvalue Value before save. Passed by do_action() but
277
+ * unused here.
278
  * @param string $newvalue Value to change meta to.
279
  */
280
  function bp_blogs_update_option_close_comments_for_old_posts( $oldvalue, $newvalue ) {
287
  /**
288
  * Update "Close comments after days old" option in BuddyPress blogmeta table.
289
  *
290
+ * @since BuddyPress (2.0.0)
291
  *
292
  * @global object $wpdb DB Layer.
293
  *
294
  * @param string $oldvalue Value before save. Passed by do_action() but
295
+ * unused here.
296
  * @param string $newvalue Value to change meta to.
297
  */
298
+ function bp_blogs_update_option_close_close_comments_days_old( $oldvalue, $newvalue ) {
299
  global $wpdb;
300
 
301
  bp_blogs_update_blogmeta( $wpdb->blogid, 'close_comments_days_old', $newvalue );
305
  /**
306
  * When toggling threaded comments, update thread depth in blogmeta table.
307
  *
308
+ * @since BuddyPress (2.0.0)
309
  *
310
  * @global object $wpdb DB Layer.
311
  *
312
  * @param string $oldvalue Value before save. Passed by do_action() but
313
+ * unused here.
314
  * @param string $newvalue Value to change meta to.
315
  */
316
  function bp_blogs_update_option_thread_comments( $oldvalue, $newvalue ) {
329
  /**
330
  * When updating comment depth, update thread depth in blogmeta table.
331
  *
332
+ * @since BuddyPress (2.0.0)
333
  *
334
  * @global object $wpdb DB Layer.
335
  *
336
  * @param string $oldvalue Value before save. Passed by do_action() but
337
+ * unused here.
338
  * @param string $newvalue Value to change meta to.
339
  */
340
  function bp_blogs_update_option_thread_comments_depth( $oldvalue, $newvalue ) {
349
  add_action( 'update_option_thread_comments_depth', 'bp_blogs_update_option_thread_comments_depth', 10, 2 );
350
 
351
  /**
352
+ * Detect a change in post status, and initiate an activity update if necessary.
353
  *
354
+ * Posts get new activity updates when (a) they are being published, and (b)
355
+ * they have not already been published. This enables proper posting for
356
+ * regular posts as well as scheduled posts, while preventing post bumping.
357
  *
358
+ * See #4090, #3746, #2546 for background.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  *
360
+ * @since BuddyPress (2.0.0)
 
361
  *
362
+ * @todo Support untrashing better
363
  *
364
+ * @param string $new_status New status for the post.
365
+ * @param string $old_status Old status for the post.
366
+ * @param object $post Post data.
367
  */
368
+ function bp_blogs_catch_transition_post_status( $new_status, $old_status, $post ) {
369
+
370
+ // This is an edit
371
+ if ( $new_status === $old_status ) {
372
+ if ( $new_status == 'publish' ) {
373
+ bp_blogs_update_post( $post );
374
+ return;
375
+ }
376
+ }
377
+
378
+ // Publishing a previously unpublished post
379
+ if ( 'publish' === $new_status ) {
380
+ // Untrashing the post
381
+ // Nothing here yet
382
+ if ( 'trash' == $old_status ) {}
383
+
384
+ // Record the post
385
+ bp_blogs_record_post( $post->ID, $post );
386
+
387
+ // Unpublishing a previously published post
388
+ } else if ( 'publish' === $old_status ) {
389
+ // Some form of pending status
390
+ // Only remove the activity entry
391
+ bp_blogs_delete_activity( array(
392
+ 'item_id' => get_current_blog_id(),
393
+ 'secondary_item_id' => $post->ID,
394
+ 'component' => buddypress()->blogs->id,
395
+ 'type' => 'new_blog_post'
396
+ ) );
397
+ }
398
  }
399
+ add_action( 'transition_post_status', 'bp_blogs_catch_transition_post_status', 10, 3 );
400
 
401
  /**
402
+ * Record a new blog post in the BuddyPress activity stream.
 
 
403
  *
404
+ * @param int $post_id ID of the post being recorded.
405
+ * @param object $post The WP post object passed to the 'save_post' action.
406
+ * @param int $user_id Optional. The user to whom the activity item will be
407
+ * associated. Defaults to the post_author.
408
+ * @return bool|null Returns false on failure.
409
  */
410
+ function bp_blogs_record_post( $post_id, $post, $user_id = 0 ) {
411
+ global $bp, $wpdb;
 
 
412
 
413
+ $post_id = (int) $post_id;
414
+ $blog_id = (int) $wpdb->blogid;
415
 
416
+ // If blog is not trackable, do not record the activity.
417
+ if ( ! bp_blogs_is_blog_trackable( $blog_id, $user_id ) )
418
+ return false;
419
+
420
+ if ( !$user_id )
421
+ $user_id = (int) $post->post_author;
422
+
423
+ // Stop infinite loops with WordPress MU Sitewide Tags.
424
+ // That plugin changed the way its settings were stored at some point. Thus the dual check.
425
+ if ( !empty( $bp->site_options['sitewide_tags_blog'] ) ) {
426
+ $st_options = maybe_unserialize( $bp->site_options['sitewide_tags_blog'] );
427
+ $tags_blog_id = isset( $st_options['tags_blog_id'] ) ? $st_options['tags_blog_id'] : 0;
428
  } else {
429
+ $tags_blog_id = isset( $bp->site_options['tags_blog_id'] ) ? $bp->site_options['tags_blog_id'] : 0;
430
  }
431
 
432
+ if ( (int) $blog_id == $tags_blog_id && apply_filters( 'bp_blogs_block_sitewide_tags_activity', true ) )
433
+ return false;
434
+
435
+ // Don't record this if it's not a post
436
+ if ( !in_array( $post->post_type, apply_filters( 'bp_blogs_record_post_post_types', array( 'post' ) ) ) )
437
+ return false;
438
 
439
+ $is_blog_public = apply_filters( 'bp_is_blog_public', (int)get_blog_option( $blog_id, 'blog_public' ) );
440
+
441
+ if ( 'publish' == $post->post_status && empty( $post->post_password ) ) {
442
+ if ( $is_blog_public || !is_multisite() ) {
443
+
444
+ // Record this in activity streams
445
+ $post_permalink = add_query_arg(
446
+ 'p',
447
+ $post_id,
448
+ trailingslashit( get_home_url( $blog_id ) )
449
+ );
450
+
451
+ if ( is_multisite() )
452
+ $activity_action = sprintf( __( '%1$s wrote a new post, %2$s, on the site %3$s', 'buddypress' ), bp_core_get_userlink( (int) $post->post_author ), '<a href="' . $post_permalink . '">' . $post->post_title . '</a>', '<a href="' . get_blog_option( $blog_id, 'home' ) . '">' . get_blog_option( $blog_id, 'blogname' ) . '</a>' );
453
+ else
454
+ $activity_action = sprintf( __( '%1$s wrote a new post, %2$s', 'buddypress' ), bp_core_get_userlink( (int) $post->post_author ), '<a href="' . $post_permalink . '">' . $post->post_title . '</a>' );
455
+
456
+ // Make sure there's not an existing entry for this post (prevent bumping)
457
+ if ( bp_is_active( 'activity' ) ) {
458
+ $existing = bp_activity_get( array(
459
+ 'filter' => array(
460
+ 'action' => 'new_blog_post',
461
+ 'primary_id' => $blog_id,
462
+ 'secondary_id' => $post_id,
463
+ )
464
+ ) );
465
 
466
+ if ( !empty( $existing['activities'] ) ) {
467
+ return;
468
+ }
469
+ }
470
+
471
+ $activity_content = $post->post_content;
472
+
473
+ bp_blogs_record_activity( array(
474
+ 'user_id' => (int) $post->post_author,
475
+ 'content' => apply_filters( 'bp_blogs_activity_new_post_content', $activity_content, $post, $post_permalink ),
476
+ 'primary_link' => apply_filters( 'bp_blogs_activity_new_post_primary_link', $post_permalink, $post_id ),
477
+ 'type' => 'new_blog_post',
478
+ 'item_id' => $blog_id,
479
+ 'secondary_item_id' => $post_id,
480
+ 'recorded_time' => $post->post_date_gmt,
481
+ ));
482
+ }
483
+
484
+ // Update the blogs last activity
485
+ bp_blogs_update_blogmeta( $blog_id, 'last_activity', bp_core_current_time() );
486
+ } else {
487
+ bp_blogs_remove_post( $post_id, $blog_id, $user_id );
488
+ }
489
+
490
+ do_action( 'bp_blogs_new_blog_post', $post_id, $post, $user_id );
491
  }
 
492
 
493
  /**
494
+ * Updates a blog post's corresponding activity entry during a post edit.
495
+ *
496
+ * @since BuddyPress (2.0.0)
497
  *
498
+ * @see bp_blogs_catch_transition_post_status()
 
499
  *
500
+ * @param WP_Post $post
 
 
501
  */
502
+ function bp_blogs_update_post( $post ) {
503
+ if ( ! bp_is_active( 'activity' ) ) {
504
  return;
505
  }
506
 
507
+ $activity_id = bp_activity_get_activity_id( array(
508
+ 'component' => buddypress()->blogs->id,
509
+ 'item_id' => get_current_blog_id(),
510
+ 'secondary_item_id' => $post->ID,
511
+ 'type' => 'new_blog_post',
512
+ ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
 
514
+ // activity ID doesn't exist, so stop!
515
+ if ( empty( $activity_id ) ) {
516
+ return;
517
  }
518
 
519
+ // update the activity entry
520
+ $activity = new BP_Activity_Activity( $activity_id );
521
+ $activity->content = $post->post_content;
522
+ $activity->save();
523
+
524
+ // add post comment status to activity meta if closed
525
  if( 'closed' == $post->comment_status ) {
526
+ bp_activity_update_meta( $activity_id, 'post_comment_status', $post->comment_status );
527
  } else {
528
+ bp_activity_delete_meta( $activity_id, 'post_comment_status' );
529
  }
530
  }
 
531
 
532
  /**
533
+ * Record a new blog comment in the BuddyPress activity stream.
534
  *
535
+ * Only posts the item if blog is public and post is not password-protected.
536
  *
537
+ * @param int $comment_id ID of the comment being recorded.
538
+ * @param bool|string $is_approved Optional. The $is_approved value passed to
539
+ * the 'comment_post' action. Default: true.
540
+ * @return bool|object Returns false on failure, the comment object on success.
 
541
  */
542
+ function bp_blogs_record_comment( $comment_id, $is_approved = true ) {
543
+ // bail if activity component is not active
544
+ if ( ! bp_is_active( 'activity' ) ) {
545
+ return;
546
  }
547
 
548
+ // Get the users comment
549
+ $recorded_comment = get_comment( $comment_id );
550
+
551
+ // Don't record activity if the comment hasn't been approved
552
+ if ( empty( $is_approved ) )
553
+ return false;
554
+
555
+ // Don't record activity if no email address has been included
556
+ if ( empty( $recorded_comment->comment_author_email ) )
557
+ return false;
558
+
559
+ // Don't record activity if the comment has already been marked as spam
560
+ if ( 'spam' === $is_approved )
561
+ return false;
562
+
563
+ // Get the user by the comment author email.
564
+ $user = get_user_by( 'email', $recorded_comment->comment_author_email );
565
+
566
+ // If user isn't registered, don't record activity
567
+ if ( empty( $user ) )
568
+ return false;
569
+
570
+ // Get the user_id
571
+ $user_id = (int) $user->ID;
572
+
573
+ // Get blog and post data
574
  $blog_id = get_current_blog_id();
575
 
576
+ // If blog is not trackable, do not record the activity.
577
+ if ( ! bp_blogs_is_blog_trackable( $blog_id, $user_id ) )
578
+ return false;
 
 
 
579
 
580
+ $recorded_comment->post = get_post( $recorded_comment->comment_post_ID );
 
581
 
582
+ if ( empty( $recorded_comment->post ) || is_wp_error( $recorded_comment->post ) )
583
+ return false;
584
 
585
+ // If this is a password protected post, don't record the comment
586
+ if ( !empty( $recorded_comment->post->post_password ) )
587
+ return false;
 
588
 
589
+ // Don't record activity if the comment's associated post isn't a WordPress Post
590
+ if ( !in_array( $recorded_comment->post->post_type, apply_filters( 'bp_blogs_record_comment_post_types', array( 'post' ) ) ) )
591
+ return false;
592
 
593
+ $is_blog_public = apply_filters( 'bp_is_blog_public', (int)get_blog_option( $blog_id, 'blog_public' ) );
 
 
 
 
 
 
 
594
 
595
+ // If blog is public allow activity to be posted
596
+ if ( $is_blog_public ) {
 
 
 
597
 
598
+ // Get activity related links
599
+ $post_permalink = get_permalink( $recorded_comment->comment_post_ID );
600
+ $comment_link = get_comment_link( $recorded_comment->comment_ID );
 
 
601
 
602
+ // Setup activity args
603
+ $args = array();
 
 
 
604
 
605
+ $args['user_id'] = $user_id;
606
+ $args['content'] = apply_filters_ref_array( 'bp_blogs_activity_new_comment_content', array( $recorded_comment->comment_content, &$recorded_comment, $comment_link ) );
607
+ $args['primary_link'] = apply_filters_ref_array( 'bp_blogs_activity_new_comment_primary_link', array( $comment_link, &$recorded_comment ) );
608
+ $args['recorded_time'] = $recorded_comment->comment_date_gmt;
609
+
610
+ // Setup some different activity args depending if activity commenting is
611
+ // enabled or not
612
 
613
+ // if cannot comment, record separate activity entry
614
+ // this is the old way of doing things
615
+ if ( bp_disable_blogforum_comments() ) {
616
+ $args['type'] = 'new_blog_comment';
617
+ $args['item_id'] = $blog_id;
618
+ $args['secondary_item_id'] = $comment_id;
619
 
620
+ // record the activity entry
621
+ bp_blogs_record_activity( $args );
622
+
623
+ // record comment as BP activity comment under the parent 'new_blog_post'
624
+ // activity item
625
  } else {
626
+ // this is a comment edit
627
+ // check to see if corresponding activity entry already exists
628
+ if ( ! empty( $_REQUEST['action'] ) ) {
629
+ $existing_activity_id = get_comment_meta( $comment_id, 'bp_activity_comment_id', true );
630
 
631
+ if ( ! empty( $existing_activity_id ) ) {
632
+ $args['id'] = $existing_activity_id;
633
+ }
634
+ }
635
+
636
+ // find the parent 'new_blog_post' activity entry
637
+ $parent_activity_id = bp_activity_get_activity_id( array(
638
+ 'component' => 'blogs',
639
+ 'type' => 'new_blog_post',
640
+ 'item_id' => $blog_id,
641
+ 'secondary_item_id' => $recorded_comment->comment_post_ID
642
+ ) );
643
 
644
+ // we found the parent activity entry
645
+ // so let's go ahead and reconfigure some activity args
646
+ if ( ! empty( $parent_activity_id ) ) {
647
+ // set the 'item_id' with the parent activity entry ID
648
+ $args['item_id'] = $parent_activity_id;
649
 
650
+ // now see if the WP parent comment has a BP activity ID
651
+ $comment_parent = 0;
652
+ if ( ! empty( $recorded_comment->comment_parent ) ) {
653
+ $comment_parent = get_comment_meta( $recorded_comment->comment_parent, 'bp_activity_comment_id', true );
654
+ }
655
 
656
+ // WP parent comment does not have a BP activity ID
657
+ // so set to 'new_blog_post' activity ID
658
+ if ( empty( $comment_parent ) ) {
659
+ $comment_parent = $parent_activity_id;
660
  }
661
+
662
+ $args['secondary_item_id'] = $comment_parent;
663
+ $args['component'] = 'activity';
664
+ $args['type'] = 'activity_comment';
665
+
666
+ // could not find corresponding parent activity entry
667
+ // so wipe out $args array
668
+ } else {
669
+ $args = array();
670
  }
671
 
672
+ // Record in activity streams
673
+ if ( ! empty( $args ) ) {
674
+ // @todo should we use bp_activity_new_comment()? that function will also send
675
+ // an email to people in the activity comment thread
676
+ //
677
+ // what if a site already has some comment email notification plugin setup?
678
+ // this is why I decided to go with bp_activity_add() to avoid any conflict
679
+ // with existing comment email notification plugins
680
+ $comment_activity_id = bp_activity_add( $args );
681
+
682
+ if ( empty( $args['id'] ) ) {
683
+ // add meta to activity comment
684
+ bp_activity_update_meta( $comment_activity_id, 'bp_blogs_post_comment_id', $comment_id );
685
+
686
+ // add meta to comment
687
+ add_comment_meta( $comment_id, 'bp_activity_comment_id', $comment_activity_id );
688
+ }
689
+ }
690
  }
 
691
 
692
+ // Update the blogs last active date
693
+ bp_blogs_update_blogmeta( $blog_id, 'last_activity', bp_core_current_time() );
 
 
 
 
 
 
 
 
 
 
 
 
694
  }
695
 
696
+ return $recorded_comment;
697
  }
698
+ add_action( 'comment_post', 'bp_blogs_record_comment', 10, 2 );
699
+ add_action( 'edit_comment', 'bp_blogs_record_comment', 10 );
700
 
701
  /**
702
  * Record a user's association with a blog.
705
  * set/changed ('add_user_to_blog', 'profile_update', 'user_register'). It
706
  * parses the changes, and records them as necessary in the BP blog tracker.
707
  *
708
+ * BuddyPress does not track blogs for Subscribers.
 
 
709
  *
710
+ * @param int $user_id The ID of the user.
711
+ * @param string|bool $role The WP role being assigned to the user
712
+ * ('subscriber', 'contributor', 'author', 'editor', 'administrator', or
713
+ * a custom role). Defaults to false.
714
+ * @param int $blog_id Default: the current blog ID.
715
  * @return bool|null False on failure.
716
  */
717
  function bp_blogs_add_user_to_blog( $user_id, $role = false, $blog_id = 0 ) {
718
  global $wpdb;
719
 
 
720
  if ( empty( $blog_id ) ) {
721
  $blog_id = isset( $wpdb->blogid ) ? $wpdb->blogid : bp_get_root_blog_id();
722
  }
723
 
 
724
  if ( empty( $role ) ) {
725
+ $key = $wpdb->get_blog_prefix( $blog_id ). 'capabilities';
726
 
727
+ $roles = bp_get_user_meta( $user_id, $key, true );
 
 
 
 
 
 
 
 
 
 
 
728
 
729
+ if ( is_array( $roles ) )
730
+ $role = array_search( 1, $roles );
731
+ else
732
+ return false;
 
 
 
 
 
 
 
 
 
733
  }
734
 
735
+ if ( $role != 'subscriber' )
736
+ bp_blogs_record_blog( $blog_id, $user_id, true );
737
  }
738
  add_action( 'add_user_to_blog', 'bp_blogs_add_user_to_blog', 10, 3 );
739
  add_action( 'profile_update', 'bp_blogs_add_user_to_blog' );
740
  add_action( 'user_register', 'bp_blogs_add_user_to_blog' );
741
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
742
  /**
743
  * Remove a blog-user pair from BP's blog tracker.
744
  *
748
  function bp_blogs_remove_user_from_blog( $user_id, $blog_id = 0 ) {
749
  global $wpdb;
750
 
751
+ if ( empty( $blog_id ) )
752
  $blog_id = $wpdb->blogid;
 
753
 
754
  bp_blogs_remove_blog_for_user( $user_id, $blog_id );
755
  }
756
  add_action( 'remove_user_from_blog', 'bp_blogs_remove_user_from_blog', 10, 2 );
757
 
758
  /**
759
+ * Rehook WP's maybe_add_existing_user_to_blog with a later priority
760
  *
761
  * WordPress catches add-user-to-blog requests at init:10. In some cases, this
762
  * can precede BP's Blogs component. This function bumps the priority of the
763
  * core function, so that we can be sure that the Blogs component is loaded
764
+ * first. See http://buddypress.trac.wordpress.org/ticket/3916.
765
  *
766
+ * @since BuddyPress (1.6)
767
+ * @access private
768
  */
769
  function bp_blogs_maybe_add_user_to_blog() {
770
  if ( ! is_multisite() )
781
  * @param int $blog_id ID of the blog being removed.
782
  */
783
  function bp_blogs_remove_blog( $blog_id ) {
784
+ global $bp;
785
 
786
  $blog_id = (int) $blog_id;
 
 
 
 
 
 
 
 
 
787
  do_action( 'bp_blogs_before_remove_blog', $blog_id );
788
 
789
  BP_Blogs_Blog::delete_blog_for_all( $blog_id );
790
 
791
+ // Delete activity stream item
792
+ bp_blogs_delete_activity( array( 'item_id' => $blog_id, 'component' => $bp->blogs->id, 'type' => 'new_blog' ) );
793
+
 
 
 
 
 
794
  do_action( 'bp_blogs_remove_blog', $blog_id );
795
  }
796
  add_action( 'delete_blog', 'bp_blogs_remove_blog' );
802
  * @param int $blog_id ID of the blog being removed.
803
  */
804
  function bp_blogs_remove_blog_for_user( $user_id, $blog_id ) {
805
+ global $bp;
806
 
807
  $blog_id = (int) $blog_id;
808
  $user_id = (int) $user_id;
809
 
 
 
 
 
 
 
 
 
810
  do_action( 'bp_blogs_before_remove_blog_for_user', $blog_id, $user_id );
811
 
812
  BP_Blogs_Blog::delete_blog_for_user( $blog_id, $user_id );
813
 
814
+ // Delete activity stream item
815
+ bp_blogs_delete_activity( array(
816
+ 'item_id' => $blog_id,
817
+ 'component' => $bp->blogs->id,
818
+ 'type' => 'new_blog'
819
+ ) );
820
+
 
821
  do_action( 'bp_blogs_remove_blog_for_user', $blog_id, $user_id );
822
  }
823
  add_action( 'remove_user_from_blog', 'bp_blogs_remove_blog_for_user', 10, 2 );
824
 
825
  /**
826
+ * Remove a blog post activity item from the activity stream.
 
 
827
  *
828
+ * @param int $post_id ID of the post to be removed.
829
+ * @param int $blog_id Optional. Defaults to current blog ID.
830
+ * @param int $user_id Optional. Defaults to the logged-in user ID. This param
831
+ * is currently unused in the function (but is passed to hooks).
832
+ */
833
+ function bp_blogs_remove_post( $post_id, $blog_id = 0, $user_id = 0 ) {
834
+ global $wpdb, $bp;
835
+
836
+ if ( empty( $wpdb->blogid ) )
837
+ return false;
838
+
839
+ $post_id = (int) $post_id;
840
+
841
+ if ( !$blog_id )
842
+ $blog_id = (int) $wpdb->blogid;
843
+
844
+ if ( !$user_id )
845
+ $user_id = bp_loggedin_user_id();
846
+
847
+ do_action( 'bp_blogs_before_remove_post', $blog_id, $post_id, $user_id );
848
+
849
+ // Delete activity stream item
850
+ bp_blogs_delete_activity( array( 'item_id' => $blog_id, 'secondary_item_id' => $post_id, 'component' => $bp->blogs->id, 'type' => 'new_blog_post' ) );
851
+
852
+ do_action( 'bp_blogs_remove_post', $blog_id, $post_id, $user_id );
853
+ }
854
+ add_action( 'delete_post', 'bp_blogs_remove_post' );
855
+
856
+ /**
857
+ * Remove a blog comment activity item from the activity stream.
858
  *
859
+ * @param int $comment_id ID of the comment to be removed.
860
  */
861
+ function bp_blogs_remove_comment( $comment_id ) {
862
+ global $wpdb;
863
+
864
+ // activity comments are disabled for blog posts
865
+ // which means that individual activity items exist for blog comments
866
+ if ( bp_disable_blogforum_comments() ) {
867
+ // Delete the individual activity stream item
868
+ bp_blogs_delete_activity( array(
869
+ 'item_id' => $wpdb->blogid,
870
+ 'secondary_item_id' => $comment_id,
871
+ 'type' => 'new_blog_comment'
872
+ ) );
873
+
874
+ // activity comments are enabled for blog posts
875
+ // remove the associated activity item
876
+ } else {
877
+ // get associated activity ID from comment meta
878
  $activity_id = get_comment_meta( $comment_id, 'bp_activity_comment_id', true );
879
 
880
+ // delete the associated activity comment
881
+ //
882
+ // also removes child post comments and associated activity comments
883
+ if ( ! empty( $activity_id ) && bp_is_active( 'activity' ) ) {
 
884
  // fetch the activity comments for the activity item
885
  $activity = bp_activity_get( array(
886
  'in' => $activity_id,
887
  'display_comments' => 'stream',
 
888
  ) );
889
 
890
  // get all activity comment IDs for the pending deleted item
904
 
905
  // rebuild activity comment tree
906
  BP_Activity_Activity::rebuild_activity_comment_tree( $activity['activities'][0]->item_id );
 
 
 
907
  }
908
  }
909
  }
910
 
911
+ do_action( 'bp_blogs_remove_comment', $wpdb->blogid, $comment_id, bp_loggedin_user_id() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
  }
913
+ add_action( 'delete_comment', 'bp_blogs_remove_comment' );
914
 
915
  /**
916
  * Removes blog comments that are associated with activity comments.
917
  *
918
+ * @since BuddyPress (2.0.0)
919
  *
920
+ * @see bp_blogs_remove_comment()
921
  * @see bp_blogs_sync_delete_from_activity_comment()
922
  *
923
  * @param array $activity_ids The activity IDs to check association with blog
924
+ * comments.
925
+ * @param bool $force_delete Whether to force delete the comments. If false,
926
+ * comments are trashed instead.
927
  */
928
  function bp_blogs_remove_associated_blog_comments( $activity_ids = array(), $force_delete = true ) {
929
+ // query args
930
  $query_args = array(
931
  'meta_query' => array(
932
  array(
937
  )
938
  );
939
 
940
+ // get comment
941
  $comment_query = new WP_Comment_Query;
942
  $comments = $comment_query->query( $query_args );
943
 
944
+ // found the corresponding comments
945
  // let's delete them!
946
  foreach ( $comments as $comment ) {
947
  wp_delete_comment( $comment->comment_ID, $force_delete );
948
 
949
+ // if we're trashing the comment, remove the meta key as well
950
  if ( empty( $force_delete ) ) {
951
  delete_comment_meta( $comment->comment_ID, 'bp_activity_comment_id' );
952
  }
953
  }
954
  }
955
 
956
+ /**
957
+ * When a blog comment status transition occurs, update the relevant activity's status.
958
+ *
959
+ * @since BuddyPress (1.6.0)
960
+ *
961
+ * @global object $bp BuddyPress global settings.
962
+ *
963
+ * @param string $new_status New comment status.
964
+ * @param string $old_status Previous comment status.
965
+ * @param object $comment Comment data.
966
+ */
967
+ function bp_blogs_transition_activity_status( $new_status, $old_status, $comment ) {
968
+ global $bp;
969
+
970
+ // Check the Activity component is active
971
+ if ( ! bp_is_active( 'activity' ) )
972
+ return;
973
+
974
+ /**
975
+ * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
976
+ *
977
+ * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
978
+ * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
979
+ * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
980
+ * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
981
+ * Otherwise, record the comment into the activity stream.
982
+ */
983
+
984
+ // This clause was moved in from bp_blogs_remove_comment() in BuddyPress 1.6. It handles delete/hold.
985
+ if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
986
+ return bp_blogs_remove_comment( $comment->comment_ID );
987
+
988
+ // These clauses handle trash, spam, and un-spams.
989
+ } elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
990
+ $action = 'spam_activity';
991
+ } elseif ( 'approved' == $new_status ) {
992
+ $action = 'ham_activity';
993
+ }
994
+
995
+ // Get the activity
996
+ if ( bp_disable_blogforum_comments() ) {
997
+ $activity_id = bp_activity_get_activity_id( array( 'component' => $bp->blogs->id, 'item_id' => get_current_blog_id(), 'secondary_item_id' => $comment->comment_ID, 'type' => 'new_blog_comment', ) );
998
+ } else {
999
+ $activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
1000
+ }
1001
+
1002
+ // Check activity item exists
1003
+ if ( empty( $activity_id ) ) {
1004
+ // If no activity exists, but the comment has been approved, record it into the activity table.
1005
+ if ( 'approved' == $new_status ) {
1006
+ return bp_blogs_record_comment( $comment->comment_ID, true );
1007
+ }
1008
+
1009
+ return;
1010
+ }
1011
+
1012
+ // Create an activity object
1013
+ $activity = new BP_Activity_Activity( $activity_id );
1014
+ if ( empty( $activity->component ) )
1015
+ return;
1016
+
1017
+ // Spam/ham the activity if it's not already in that state
1018
+ if ( 'spam_activity' == $action && ! $activity->is_spam ) {
1019
+ bp_activity_mark_as_spam( $activity );
1020
+ } elseif ( 'ham_activity' == $action) {
1021
+ bp_activity_mark_as_ham( $activity );
1022
+ }
1023
+
1024
+ // Add "new_blog_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
1025
+ $comment_akismet_history = create_function( '$t', '$t[] = "new_blog_comment"; return $t;' );
1026
+ add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
1027
+
1028
+ // Save the updated activity
1029
+ $activity->save();
1030
+
1031
+ // Remove the "new_blog_comment" activity type whitelist so we don't break anything
1032
+ remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
1033
+ }
1034
+ add_action( 'transition_comment_status', 'bp_blogs_transition_activity_status', 10, 3 );
1035
+
1036
  /**
1037
  * Get the total number of blogs being tracked by BuddyPress.
1038
  *
1039
  * @return int $count Total blog count.
1040
  */
1041
  function bp_blogs_total_blogs() {
1042
+ if ( !$count = wp_cache_get( 'bp_total_blogs', 'bp' ) ) {
 
 
1043
  $blogs = BP_Blogs_Blog::get_all();
1044
  $count = $blogs['total'];
1045
  wp_cache_set( 'bp_total_blogs', $count, 'bp' );
1050
  /**
1051
  * Get the total number of blogs being tracked by BP for a specific user.
1052
  *
 
 
1053
  * @param int $user_id ID of the user being queried. Default: on a user page,
1054
+ * the displayed user. Otherwise, the logged-in user.
1055
  * @return int $count Total blog count for the user.
1056
  */
1057
  function bp_blogs_total_blogs_for_user( $user_id = 0 ) {
 
 
 
1058
 
1059
+ if ( empty( $user_id ) )
1060
+ $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
 
 
1061
 
1062
+ if ( !$count = wp_cache_get( 'bp_total_blogs_for_user_' . $user_id, 'bp' ) ) {
 
1063
  $count = BP_Blogs_Blog::total_blog_count_for_user( $user_id );
1064
  wp_cache_set( 'bp_total_blogs_for_user_' . $user_id, $count, 'bp' );
1065
  }
1073
  * @param int $blog_id The ID of the blog to expunge.
1074
  */
1075
  function bp_blogs_remove_data_for_blog( $blog_id ) {
1076
+ global $bp;
1077
 
 
 
 
 
 
 
 
 
1078
  do_action( 'bp_blogs_before_remove_data_for_blog', $blog_id );
1079
 
1080
  // If this is regular blog, delete all data for that blog.
1081
  BP_Blogs_Blog::delete_blog_for_all( $blog_id );
1082
 
1083
+ // Delete activity stream item
1084
+ bp_blogs_delete_activity( array( 'item_id' => $blog_id, 'component' => $bp->blogs->id, 'type' => false ) );
1085
+
 
 
 
 
 
1086
  do_action( 'bp_blogs_remove_data_for_blog', $blog_id );
1087
  }
1088
  add_action( 'delete_blog', 'bp_blogs_remove_data_for_blog', 1 );
1093
  * @see BP_Blogs_Blog::get_blogs_for_user() for a description of parameters
1094
  * and return values.
1095
  *
1096
+ * @param int $user_id See {@BP_Blogs_Blog::get_blogs_for_user()}.
1097
  * @param bool $show_hidden See {@BP_Blogs_Blog::get_blogs_for_user()}.
1098
  * @return array See {@BP_Blogs_Blog::get_blogs_for_user()}.
1099
  */
1106
  *
1107
  * @see BP_Blogs_Blog::get_all() for a description of parameters and return values.
1108
  *
1109
+ * @param int $limit See {@BP_Blogs_Blog::get_all()}.
1110
+ * @param int $page See {@BP_Blogs_Blog::get_all()}.
1111
  * @return array See {@BP_Blogs_Blog::get_all()}.
1112
  */
1113
  function bp_blogs_get_all_blogs( $limit = null, $page = null ) {
1119
  *
1120
  * @see BP_Blogs_Blog::get() for a description of parameters and return values.
1121
  *
1122
+ * @param int $limit See {@BP_Blogs_Blog::get()}.
1123
+ * @param int $page See {@BP_Blogs_Blog::get()}.
1124
  * @return array See {@BP_Blogs_Blog::get()}.
1125
  */
1126
  function bp_blogs_get_random_blogs( $limit = null, $page = null ) {
1139
  return BP_Blogs_Blog::is_hidden( $blog_id );
1140
  }
1141
 
1142
+ /*******************************************************************************
1143
  * Blog meta functions
1144
  *
1145
  * These functions are used to store specific blogmeta in one global table,
1149
  */
1150
 
1151
  /**
1152
+ * Delete a metadta from the DB for a blog.
1153
  *
1154
  * @global object $wpdb WordPress database access object.
1155
+ * @global object $bp BuddyPress global settings.
1156
+ *
1157
+ * @param int $blog_id ID of the blog whose metadata is being deleted.
1158
+ * @param string $meta_key Optional. The key of the metadata being deleted. If
1159
+ * omitted, all BP metadata associated with the blog will be deleted.
1160
+ * @param string $meta_value Optional. If present, the metadata will only be
1161
+ * deleted if the meta_value matches this parameter.
1162
+ * @param bool $delete_all Optional. If true, delete matching metadata entries
1163
+ * for all objects, ignoring the specified blog_id. Otherwise, only
1164
+ * delete matching metadata entries for the specified blog.
1165
+ * Default: false.
1166
  * @return bool True on success, false on failure.
1167
  */
1168
  function bp_blogs_delete_blogmeta( $blog_id, $meta_key = false, $meta_value = false, $delete_all = false ) {
1169
+ global $wpdb, $bp;
1170
 
1171
+ // Legacy - if no meta_key is passed, delete all for the blog_id
1172
  if ( empty( $meta_key ) ) {
1173
  $keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$wpdb->blogmeta} WHERE blog_id = %d", $blog_id ) );
1174
  $delete_all = false;
1191
  /**
1192
  * Get metadata for a given blog.
1193
  *
1194
+ * @since BuddyPress (1.2.0)
1195
  *
1196
  * @global object $wpdb WordPress database access object.
1197
+ * @global object $bp BuddyPress global settings.
1198
  *
1199
+ * @param int $blog_id ID of the blog whose metadata is being requested.
1200
  * @param string $meta_key Optional. If present, only the metadata matching
1201
+ * that meta key will be returned. Otherwise, all metadata for the
1202
+ * blog will be fetched.
1203
+ * @param bool $single Optional. If true, return only the first value of the
1204
+ * specified meta_key. This parameter has no effect if meta_key is not
1205
+ * specified. Default: true.
1206
  * @return mixed The meta value(s) being requested.
1207
  */
1208
  function bp_blogs_get_blogmeta( $blog_id, $meta_key = '', $single = true ) {
1217
  * Update a piece of blog meta.
1218
  *
1219
  * @global object $wpdb WordPress database access object.
1220
+ * @global object $bp BuddyPress global settings.
1221
+ *
1222
+ * @param int $blog_id ID of the blog whose metadata is being updated.
1223
+ * @param string $meta_key Key of the metadata being updated.
1224
+ * @param mixed $meta_value Value to be set.
1225
+ * @param mixed $prev_value Optional. If specified, only update existing
1226
+ * metadata entries with the specified value. Otherwise, update all
1227
+ * entries.
1228
  * @return bool|int Returns false on failure. On successful update of existing
1229
+ * metadata, returns true. On successful creation of new metadata,
1230
+ * returns the integer ID of the new metadata row.
1231
  */
1232
  function bp_blogs_update_blogmeta( $blog_id, $meta_key, $meta_value, $prev_value = '' ) {
1233
  add_filter( 'query', 'bp_filter_metaid_column_name' );
1240
  /**
1241
  * Add a piece of blog metadata.
1242
  *
1243
+ * @since BuddyPress (2.0.0)
1244
  *
1245
+ * @param int $blog_id ID of the blog.
1246
+ * @param string $meta_key Metadata key.
1247
+ * @param mixed $meta_value Metadata value.
1248
+ * @param bool $unique. Optional. Whether to enforce a single metadata value
1249
+ * for the given key. If true, and the object already has a value for
1250
+ * the key, no change will be made. Default: false.
1251
  * @return int|bool The meta ID on successful update, false on failure.
1252
  */
1253
  function bp_blogs_add_blogmeta( $blog_id, $meta_key, $meta_value, $unique = false ) {
1261
  * Remove all blog associations for a given user.
1262
  *
1263
  * @param int $user_id ID whose blog data should be removed.
1264
+ * @return bool|null Returns false on failure.
1265
  */
1266
  function bp_blogs_remove_data( $user_id ) {
1267
  if ( !is_multisite() )
1268
  return false;
1269
 
 
 
 
 
 
 
 
1270
  do_action( 'bp_blogs_before_remove_data', $user_id );
1271
 
1272
  // If this is regular blog, delete all data for that blog.
1273
  BP_Blogs_Blog::delete_blogs_for_user( $user_id );
1274
 
 
 
 
 
 
 
 
1275
  do_action( 'bp_blogs_remove_data', $user_id );
1276
  }
1277
  add_action( 'wpmu_delete_user', 'bp_blogs_remove_data' );
1278
  add_action( 'delete_user', 'bp_blogs_remove_data' );
1279
  add_action( 'bp_make_spam_user', 'bp_blogs_remove_data' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-blogs/bp-blogs-loader.php CHANGED
@@ -1,23 +1,250 @@
1
  <?php
 
2
  /**
3
- * BuddyPress Blogs Loader
4
  *
5
- * The blogs component tracks posts and comments to member activity streams,
6
- * shows blogs the member can post to in their profiles, and caches useful
7
- * information from those blogs to make querying blogs in bulk more performant.
8
  *
9
  * @package BuddyPress
10
- * @subpackage BlogsCore
11
- * @since 1.5.0
12
  */
13
 
14
- // Exit if accessed directly.
15
- defined( 'ABSPATH' ) || exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  /**
18
  * Set up the bp-blogs component.
19
- *
20
- * @since 1.5.0
21
  */
22
  function bp_setup_blogs() {
23
  buddypress()->blogs = new BP_Blogs_Component();
1
  <?php
2
+
3
  /**
4
+ * BuddyPress Blogs Streams Loader
5
  *
6
+ * An blogs stream component, for users, groups, and blog tracking.
 
 
7
  *
8
  * @package BuddyPress
9
+ * @subpackage Blogs Core
 
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( !defined( 'ABSPATH' ) ) exit;
14
+
15
+ class BP_Blogs_Component extends BP_Component {
16
+
17
+ /**
18
+ * Start the blogs component creation process.
19
+ *
20
+ * @since BuddyPress (1.5.0)
21
+ */
22
+ public function __construct() {
23
+ parent::start(
24
+ 'blogs',
25
+ __( 'Site Tracking', 'buddypress' ),
26
+ buddypress()->plugin_dir,
27
+ array(
28
+ 'adminbar_myaccount_order' => 30
29
+ )
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Set up global settings for the blogs component.
35
+ *
36
+ * The BP_BLOGS_SLUG constant is deprecated, and only used here for
37
+ * backwards compatibility.
38
+ *
39
+ * @since BuddyPress (1.5.0)
40
+ *
41
+ * @see BP_Component::setup_globals() for description of parameters.
42
+ *
43
+ * @param array $args See {@link BP_Component::setup_globals()}.
44
+ */
45
+ public function setup_globals( $args = array() ) {
46
+ $bp = buddypress();
47
+
48
+ if ( !defined( 'BP_BLOGS_SLUG' ) )
49
+ define ( 'BP_BLOGS_SLUG', $this->id );
50
+
51
+ // Global tables for messaging component
52
+ $global_tables = array(
53
+ 'table_name' => $bp->table_prefix . 'bp_user_blogs',
54
+ 'table_name_blogmeta' => $bp->table_prefix . 'bp_user_blogs_blogmeta',
55
+ );
56
+
57
+ $meta_tables = array(
58
+ 'blog' => $bp->table_prefix . 'bp_user_blogs_blogmeta',
59
+ );
60
+
61
+ // All globals for messaging component.
62
+ // Note that global_tables is included in this array.
63
+ $args = array(
64
+ 'slug' => BP_BLOGS_SLUG,
65
+ 'root_slug' => isset( $bp->pages->blogs->slug ) ? $bp->pages->blogs->slug : BP_BLOGS_SLUG,
66
+ 'has_directory' => is_multisite(), // Non-multisite installs don't need a top-level Sites directory, since there's only one site
67
+ 'notification_callback' => 'bp_blogs_format_notifications',
68
+ 'search_string' => __( 'Search sites...', 'buddypress' ),
69
+ 'autocomplete_all' => defined( 'BP_MESSAGES_AUTOCOMPLETE_ALL' ),
70
+ 'global_tables' => $global_tables,
71
+ 'meta_tables' => $meta_tables,
72
+ );
73
+
74
+ // Setup the globals
75
+ parent::setup_globals( $args );
76
+ }
77
+
78
+ /**
79
+ * Include bp-blogs files.
80
+ *
81
+ * @see BP_Component::includes() for description of parameters.
82
+ *
83
+ * @param array $includes See {@link BP_Component::includes()}.
84
+ */
85
+ public function includes( $includes = array() ) {
86
+ // Files to include
87
+ $includes = array(
88
+ 'cache',
89
+ 'actions',
90
+ 'screens',
91
+ 'classes',
92
+ 'template',
93
+ 'filters',
94
+ 'activity',
95
+ 'functions',
96
+ 'buddybar'
97
+ );
98
+
99
+ if ( is_multisite() )
100
+ $includes[] = 'widgets';
101
+
102
+ // Include the files
103
+ parent::includes( $includes );
104
+ }
105
+
106
+ /**
107
+ * Set up component navigation for bp-blogs.
108
+ *
109
+ * @see BP_Component::setup_nav() for a description of arguments.
110
+ *
111
+ * @param array $main_nav Optional. See BP_Component::setup_nav() for
112
+ * description.
113
+ * @param array $sub_nav Optional. See BP_Component::setup_nav() for
114
+ * description.
115
+ */
116
+ public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
117
+ $bp = buddypress();
118
+
119
+ /**
120
+ * Blog/post/comment menus should not appear on single WordPress setups.
121
+ * Although comments and posts made by users will still show on their
122
+ * activity stream.
123
+ */
124
+ if ( !is_multisite() )
125
+ return false;
126
+
127
+ // Add 'Sites' to the main navigation
128
+ $main_nav = array(
129
+ 'name' => sprintf( __( 'Sites <span>%d</span>', 'buddypress' ), bp_blogs_total_blogs_for_user() ),
130
+ 'slug' => $this->slug,
131
+ 'position' => 30,
132
+ 'screen_function' => 'bp_blogs_screen_my_blogs',
133
+ 'default_subnav_slug' => 'my-sites',
134
+ 'item_css_id' => $this->id
135
+ );
136
+
137
+ // Determine user to use
138
+ if ( bp_displayed_user_domain() ) {
139
+ $user_domain = bp_displayed_user_domain();
140
+ } elseif ( bp_loggedin_user_domain() ) {
141
+ $user_domain = bp_loggedin_user_domain();
142
+ } else {
143
+ return;
144
+ }
145
+
146
+ $parent_url = trailingslashit( $user_domain . bp_get_blogs_slug() );
147
+
148
+ $sub_nav[] = array(
149
+ 'name' => __( 'My Sites', 'buddypress' ),
150
+ 'slug' => 'my-sites',
151
+ 'parent_url' => $parent_url,
152
+ 'parent_slug' => $bp->blogs->slug,
153
+ 'screen_function' => 'bp_blogs_screen_my_blogs',
154
+ 'position' => 10
155
+ );
156
+
157
+ // Setup navigation
158
+ parent::setup_nav( $main_nav, $sub_nav );
159
+ }
160
+
161
+ /**
162
+ * Set up bp-blogs integration with the WordPress admin bar.
163
+ *
164
+ * @since BuddyPress (1.5.0)
165
+ *
166
+ * @see BP_Component::setup_admin_bar() for a description of arguments.
167
+ *
168
+ * @param array $wp_admin_nav See BP_Component::setup_admin_bar()
169
+ * for description.
170
+ */
171
+ public function setup_admin_bar( $wp_admin_nav = array() ) {
172
+ $bp = buddypress();
173
+
174
+ /**
175
+ * Site/post/comment menus should not appear on single WordPress setups.
176
+ * Although comments and posts made by users will still show on their
177
+ * activity stream.
178
+ */
179
+ if ( !is_multisite() )
180
+ return false;
181
+
182
+ // Menus for logged in user
183
+ if ( is_user_logged_in() ) {
184
+
185
+ $blogs_link = trailingslashit( bp_loggedin_user_domain() . $this->slug );
186
+
187
+ // Add the "Sites" sub menu
188
+ $wp_admin_nav[] = array(
189
+ 'parent' => $bp->my_account_menu_id,
190
+ 'id' => 'my-account-' . $this->id,
191
+ 'title' => __( 'Sites', 'buddypress' ),
192
+ 'href' => trailingslashit( $blogs_link )
193
+ );
194
+
195
+ // My Sites
196
+ $wp_admin_nav[] = array(
197
+ 'parent' => 'my-account-' . $this->id,
198
+ 'id' => 'my-account-' . $this->id . '-my-sites',
199
+ 'title' => __( 'My Sites', 'buddypress' ),
200
+ 'href' => trailingslashit( $blogs_link )
201
+ );
202
+
203
+ // Create a Site
204
+ if ( bp_blog_signup_enabled() ) {
205
+ $wp_admin_nav[] = array(
206
+ 'parent' => 'my-account-' . $this->id,
207
+ 'id' => 'my-account-' . $this->id . '-create',
208
+ 'title' => __( 'Create a Site', 'buddypress' ),
209
+ 'href' => trailingslashit( bp_get_blogs_directory_permalink() . 'create' )
210
+ );
211
+ }
212
+ }
213
+
214
+ parent::setup_admin_bar( $wp_admin_nav );
215
+ }
216
+
217
+ /**
218
+ * Set up the title for pages and <title>
219
+ */
220
+ public function setup_title() {
221
+ $bp = buddypress();
222
+
223
+ // Set up the component options navigation for Site
224
+ if ( bp_is_blogs_component() ) {
225
+ if ( bp_is_my_profile() ) {
226
+ if ( bp_is_active( 'xprofile' ) ) {
227
+ $bp->bp_options_title = __( 'My Sites', 'buddypress' );
228
+ }
229
+
230
+ // If we are not viewing the logged in user, set up the current
231
+ // users avatar and name
232
+ } else {
233
+ $bp->bp_options_avatar = bp_core_fetch_avatar( array(
234
+ 'item_id' => bp_displayed_user_id(),
235
+ 'type' => 'thumb',
236
+ 'alt' => sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_get_displayed_user_fullname() )
237
+ ) );
238
+ $bp->bp_options_title = bp_get_displayed_user_fullname();
239
+ }
240
+ }
241
+
242
+ parent::setup_title();
243
+ }
244
+ }
245
 
246
  /**
247
  * Set up the bp-blogs component.
 
 
248
  */
249
  function bp_setup_blogs() {
250
  buddypress()->blogs = new BP_Blogs_Component();
bp-blogs/bp-blogs-screens.php CHANGED
@@ -1,14 +1,14 @@
1
  <?php
 
2
  /**
3
- * BuddyPress Blogs Screens.
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsScreens
7
- * @since 1.5.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Load the "My Blogs" screen.
@@ -17,11 +17,6 @@ function bp_blogs_screen_my_blogs() {
17
  if ( !is_multisite() )
18
  return false;
19
 
20
- /**
21
- * Fires right before the loading of the My Blogs screen template file.
22
- *
23
- * @since 1.0.0
24
- */
25
  do_action( 'bp_blogs_screen_my_blogs' );
26
 
27
  bp_core_load_template( apply_filters( 'bp_blogs_template_my_blogs', 'members/single/home' ) );
@@ -38,11 +33,6 @@ function bp_blogs_screen_create_a_blog() {
38
  if ( !is_user_logged_in() || !bp_blog_signup_enabled() )
39
  return false;
40
 
41
- /**
42
- * Fires right before the loading of the Create A Blog screen template file.
43
- *
44
- * @since 1.0.0
45
- */
46
  do_action( 'bp_blogs_screen_create_a_blog' );
47
 
48
  bp_core_load_template( apply_filters( 'bp_blogs_template_create_a_blog', 'blogs/create' ) );
@@ -56,11 +46,6 @@ function bp_blogs_screen_index() {
56
  if ( bp_is_blogs_directory() ) {
57
  bp_update_is_directory( true, 'blogs' );
58
 
59
- /**
60
- * Fires right before the loading of the top-level Blogs screen template file.
61
- *
62
- * @since 1.0.0
63
- */
64
  do_action( 'bp_blogs_screen_index' );
65
 
66
  bp_core_load_template( apply_filters( 'bp_blogs_screen_index', 'blogs/index' ) );
@@ -68,6 +53,179 @@ function bp_blogs_screen_index() {
68
  }
69
  add_action( 'bp_screens', 'bp_blogs_screen_index', 2 );
70
 
71
- /** Theme Compatibility *******************************************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  new BP_Blogs_Theme_Compat();
1
  <?php
2
+
3
  /**
4
+ * BuddyPress Blogs Screens
5
  *
6
  * @package BuddyPress
7
  * @subpackage BlogsScreens
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
  * Load the "My Blogs" screen.
17
  if ( !is_multisite() )
18
  return false;
19
 
 
 
 
 
 
20
  do_action( 'bp_blogs_screen_my_blogs' );
21
 
22
  bp_core_load_template( apply_filters( 'bp_blogs_template_my_blogs', 'members/single/home' ) );
33
  if ( !is_user_logged_in() || !bp_blog_signup_enabled() )
34
  return false;
35
 
 
 
 
 
 
36
  do_action( 'bp_blogs_screen_create_a_blog' );
37
 
38
  bp_core_load_template( apply_filters( 'bp_blogs_template_create_a_blog', 'blogs/create' ) );
46
  if ( bp_is_blogs_directory() ) {
47
  bp_update_is_directory( true, 'blogs' );
48
 
 
 
 
 
 
49
  do_action( 'bp_blogs_screen_index' );
50
 
51
  bp_core_load_template( apply_filters( 'bp_blogs_screen_index', 'blogs/index' ) );
53
  }
54
  add_action( 'bp_screens', 'bp_blogs_screen_index', 2 );
55
 
56
+ /** Theme Compatability *******************************************************/
57
+
58
+ /**
59
+ * The main theme compat class for BuddyPress Blogs
60
+ *
61
+ * This class sets up the necessary theme compatability actions to safely output
62
+ * group template parts to the_title and the_content areas of a theme.
63
+ *
64
+ * @since BuddyPress (1.7.0)
65
+ */
66
+ class BP_Blogs_Theme_Compat {
67
+
68
+ /**
69
+ * Set up theme compatibility for the Blogs component.
70
+ *
71
+ * @since BuddyPress (1.7.0)
72
+ */
73
+ public function __construct() {
74
+ add_action( 'bp_setup_theme_compat', array( $this, 'is_blogs' ) );
75
+ }
76
+
77
+ /**
78
+ * Are we looking at something that needs Blogs theme compatability?
79
+ *
80
+ * @since BuddyPress (1.7.0)
81
+ */
82
+ public function is_blogs() {
83
+
84
+ // Bail if not looking at a group
85
+ if ( ! bp_is_blogs_component() )
86
+ return;
87
+
88
+ // Bail if looking at a users sites
89
+ if ( bp_is_user() )
90
+ return;
91
+
92
+ // Blog Directory
93
+ if ( is_multisite() && ! bp_current_action() ) {
94
+ bp_update_is_directory( true, 'blogs' );
95
+
96
+ do_action( 'bp_blogs_screen_index' );
97
+
98
+ add_filter( 'bp_get_buddypress_template', array( $this, 'directory_template_hierarchy' ) );
99
+ add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'directory_dummy_post' ) );
100
+ add_filter( 'bp_replace_the_content', array( $this, 'directory_content' ) );
101
+
102
+ // Create blog
103
+ } elseif ( is_user_logged_in() && bp_blog_signup_enabled() ) {
104
+ add_filter( 'bp_get_buddypress_template', array( $this, 'create_template_hierarchy' ) );
105
+ add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'create_dummy_post' ) );
106
+ add_filter( 'bp_replace_the_content', array( $this, 'create_content' ) );
107
+ }
108
+ }
109
+
110
+ /** Directory *************************************************************/
111
+
112
+ /**
113
+ * Add template hierarchy to theme compat for the blog directory page.
114
+ *
115
+ * This is to mirror how WordPress has
116
+ * {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
117
+ *
118
+ * @since BuddyPress (1.8.0)
119
+ *
120
+ * @param string $templates The templates from
121
+ * bp_get_theme_compat_templates().
122
+ * @return array $templates Array of custom templates to look for.
123
+ */
124
+ public function directory_template_hierarchy( $templates ) {
125
+ // Setup our templates based on priority
126
+ $new_templates = apply_filters( 'bp_template_hierarchy_blogs_create', array(
127
+ 'blogs/index-directory.php'
128
+ ) );
129
+
130
+ // Merge new templates with existing stack
131
+ // @see bp_get_theme_compat_templates()
132
+ $templates = array_merge( (array) $new_templates, $templates );
133
 
134
+ return $templates;
135
+ }
136
+
137
+ /**
138
+ * Update the global $post with directory data.
139
+ *
140
+ * @since BuddyPress (1.7.0)
141
+ */
142
+ public function directory_dummy_post() {
143
+
144
+ $title = apply_filters( 'bp_blogs_directory_header', __( 'Sites', 'buddypress' ) );
145
+
146
+ bp_theme_compat_reset_post( array(
147
+ 'ID' => 0,
148
+ 'post_title' => $title,
149
+ 'post_author' => 0,
150
+ 'post_date' => 0,
151
+ 'post_content' => '',
152
+ 'post_type' => 'bp_blogs',
153
+ 'post_status' => 'publish',
154
+ 'is_page' => true,
155
+ 'comment_status' => 'closed'
156
+ ) );
157
+ }
158
+
159
+ /**
160
+ * Filter the_content with the groups index template part.
161
+ *
162
+ * @since BuddyPress (1.7.0)
163
+ */
164
+ public function directory_content() {
165
+ return bp_buffer_template_part( 'blogs/index', null, false );
166
+ }
167
+
168
+ /** Create ****************************************************************/
169
+
170
+ /**
171
+ * Add custom template hierarchy to theme compat for the blog create page.
172
+ *
173
+ * This is to mirror how WordPress has
174
+ * {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
175
+ *
176
+ * @since BuddyPress (1.8.0)
177
+ *
178
+ * @param string $templates The templates from
179
+ * bp_get_theme_compat_templates().
180
+ * @return array $templates Array of custom templates to look for.
181
+ */
182
+ public function create_template_hierarchy( $templates ) {
183
+ // Setup our templates based on priority
184
+ $new_templates = apply_filters( 'bp_template_hierarchy_blogs_create', array(
185
+ 'blogs/index-create.php'
186
+ ) );
187
+
188
+ // Merge new templates with existing stack
189
+ // @see bp_get_theme_compat_templates()
190
+ $templates = array_merge( (array) $new_templates, $templates );
191
+
192
+ return $templates;
193
+ }
194
+
195
+ /**
196
+ * Update the global $post with create screen data.
197
+ *
198
+ * @since BuddyPress (1.7.0)
199
+ */
200
+ public function create_dummy_post() {
201
+
202
+ // Title based on ability to create blogs
203
+ if ( is_user_logged_in() && bp_blog_signup_enabled() ) {
204
+ $title = '<a class="button bp-title-button" href="' . trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() ) . '">' . __( 'Sites', 'buddypress' ) . '</a>&nbsp;' . __( 'Create a Site', 'buddypress' );
205
+ } else {
206
+ $title = __( 'Sites', 'buddypress' );
207
+ }
208
+
209
+ bp_theme_compat_reset_post( array(
210
+ 'ID' => 0,
211
+ 'post_title' => $title,
212
+ 'post_author' => 0,
213
+ 'post_date' => 0,
214
+ 'post_content' => '',
215
+ 'post_type' => 'bp_group',
216
+ 'post_status' => 'publish',
217
+ 'is_page' => true,
218
+ 'comment_status' => 'closed'
219
+ ) );
220
+ }
221
+
222
+ /**
223
+ * Filter the_content with the create screen template part.
224
+ *
225
+ * @since BuddyPress (1.7.0)
226
+ */
227
+ public function create_content() {
228
+ return bp_buffer_template_part( 'blogs/create', null, false );
229
+ }
230
+ }
231
  new BP_Blogs_Theme_Compat();
bp-blogs/bp-blogs-template.php CHANGED
@@ -1,20 +1,21 @@
1
  <?php
 
2
  /**
3
  * BuddyPress Blogs Template Tags.
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsTemplate
7
- * @since 1.5.0
8
  */
9
 
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
 
13
  /**
14
  * Output the blogs component slug.
15
  *
16
- * @since 1.5.0
17
  *
 
18
  */
19
  function bp_blogs_slug() {
20
  echo bp_get_blogs_slug();
@@ -22,27 +23,20 @@ function bp_blogs_slug() {
22
  /**
23
  * Return the blogs component slug.
24
  *
25
- * @since 1.5.0
26
  *
27
  * @return string The 'blogs' slug.
28
  */
29
  function bp_get_blogs_slug() {
30
-
31
- /**
32
- * Filters the blogs component slug.
33
- *
34
- * @since 1.5.0
35
- *
36
- * @param string $slug Slug for the blogs component.
37
- */
38
  return apply_filters( 'bp_get_blogs_slug', buddypress()->blogs->slug );
39
  }
40
 
41
  /**
42
  * Output the blogs component root slug.
43
  *
44
- * @since 1.5.0
45
  *
 
46
  */
47
  function bp_blogs_root_slug() {
48
  echo bp_get_blogs_root_slug();
@@ -50,51 +44,263 @@ function bp_blogs_root_slug() {
50
  /**
51
  * Return the blogs component root slug.
52
  *
53
- * @since 1.5.0
54
  *
55
  * @return string The 'blogs' root slug.
56
  */
57
  function bp_get_blogs_root_slug() {
58
-
59
- /**
60
- * Filters the blogs component root slug.
61
- *
62
- * @since 1.5.0
63
- *
64
- * @param string $root_slug Root slug for the blogs component.
65
- */
66
  return apply_filters( 'bp_get_blogs_root_slug', buddypress()->blogs->root_slug );
67
  }
68
 
69
  /**
70
  * Output blog directory permalink.
71
  *
72
- * @since 1.5.0
73
  *
 
74
  */
75
  function bp_blogs_directory_permalink() {
76
- echo esc_url( bp_get_blogs_directory_permalink() );
77
  }
78
  /**
79
  * Return blog directory permalink.
80
  *
81
- * @since 1.5.0
82
- *
83
  *
 
 
 
 
84
  * @return string The URL of the Blogs directory.
85
  */
86
  function bp_get_blogs_directory_permalink() {
87
-
88
- /**
89
- * Filters the blog directory permalink.
90
- *
91
- * @since 1.5.0
92
- *
93
- * @param string $value Permalink URL for the blog directory.
94
- */
95
  return apply_filters( 'bp_get_blogs_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() ) );
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  /**
99
  * Rewind the blogs and reset blog index.
100
  */
@@ -113,7 +319,7 @@ function bp_rewind_blogs() {
113
  *
114
  * @global object $blogs_template {@link BP_Blogs_Template}
115
  *
116
- * @param array|string $args {
117
  * Arguments for limiting the contents of the blogs loop. Most arguments
118
  * are in the same format as {@link BP_Blogs_Blog::get()}. However, because
119
  * the format of the arguments accepted here differs in a number of ways,
@@ -123,68 +329,72 @@ function bp_rewind_blogs() {
123
  * Arguments can be passed as an associative array, or as a URL query
124
  * string (eg, 'user_id=4&per_page=3').
125
  *
126
- * @type int $page Which page of results to fetch. Using page=1 without
127
- * per_page will result in no pagination. Default: 1.
128
- * @type int|bool $per_page Number of results per page. Default: 20.
129
- * @type string $page_arg The string used as a query parameter in
130
- * pagination links. Default: 'bpage'.
131
- * @type int|bool $max Maximum number of results to return.
132
- * Default: false (unlimited).
133
- * @type string $type The order in which results should be fetched.
134
- * 'active', 'alphabetical', 'newest', or 'random'.
135
- * @type array $include_blog_ids Array of blog IDs to limit results to.
136
- * @type string $sort 'ASC' or 'DESC'. Default: 'DESC'.
137
- * @type string $search_terms Limit results by a search term. Default: the value of `$_REQUEST['s']` or
138
- * `$_REQUEST['sites_search']`, if present.
139
- * @type int $user_id The ID of the user whose blogs should be retrieved.
140
- * When viewing a user profile page, 'user_id' defaults to the
141
- * ID of the displayed user. Otherwise the default is false.
142
  * }
143
  * @return bool Returns true when blogs are found, otherwise false.
144
  */
145
  function bp_has_blogs( $args = '' ) {
146
  global $blogs_template;
147
 
148
- // Check for and use search terms.
149
- $search_terms_default = false;
150
- $search_query_arg = bp_core_get_component_search_query_arg( 'blogs' );
151
- if ( ! empty( $_REQUEST[ $search_query_arg ] ) ) {
152
- $search_terms_default = stripslashes( $_REQUEST[ $search_query_arg ] );
153
- } elseif ( ! empty( $_REQUEST['s'] ) ) {
154
- $search_terms_default = stripslashes( $_REQUEST['s'] );
155
- }
156
 
157
- // Parse argu
1
  <?php
2
+
3
  /**
4
  * BuddyPress Blogs Template Tags.
5
  *
6
  * @package BuddyPress
7
  * @subpackage BlogsTemplate
 
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  /**
14
  * Output the blogs component slug.
15
  *
16
+ * @since BuddyPress (1.5.0)
17
  *
18
+ * @uses bp_get_blogs_slug()
19
  */
20
  function bp_blogs_slug() {
21
  echo bp_get_blogs_slug();
23
  /**
24
  * Return the blogs component slug.
25
  *
26
+ * @since BuddyPress (1.5.0)
27
  *
28
  * @return string The 'blogs' slug.
29
  */
30
  function bp_get_blogs_slug() {
 
 
 
 
 
 
 
 
31
  return apply_filters( 'bp_get_blogs_slug', buddypress()->blogs->slug );
32
  }
33
 
34
  /**
35
  * Output the blogs component root slug.
36
  *
37
+ * @since BuddyPress (1.5.0)
38
  *
39
+ * @uses bp_get_blogs_root_slug()
40
  */
41
  function bp_blogs_root_slug() {
42
  echo bp_get_blogs_root_slug();
44
  /**
45
  * Return the blogs component root slug.
46
  *
47
+ * @since BuddyPress (1.5.0)
48
  *
49
  * @return string The 'blogs' root slug.
50
  */
51
  function bp_get_blogs_root_slug() {
 
 
 
 
 
 
 
 
52
  return apply_filters( 'bp_get_blogs_root_slug', buddypress()->blogs->root_slug );
53
  }
54
 
55
  /**
56
  * Output blog directory permalink.
57
  *
58
+ * @since BuddyPress (1.5.0)
59
  *
60
+ * @uses bp_get_blogs_directory_permalink()
61
  */
62
  function bp_blogs_directory_permalink() {
63
+ echo bp_get_blogs_directory_permalink();
64
  }
65
  /**
66
  * Return blog directory permalink.
67
  *
68
+ * @since BuddyPress (1.5.0)
 
69
  *
70
+ * @uses apply_filters()
71
+ * @uses trailingslashit()
72
+ * @uses bp_get_root_domain()
73
+ * @uses bp_get_blogs_root_slug()
74
  * @return string The URL of the Blogs directory.
75
  */
76
  function bp_get_blogs_directory_permalink() {
 
 
 
 
 
 
 
 
77
  return apply_filters( 'bp_get_blogs_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() ) );
78
  }
79
 
80
+ /**
81
+ * The main blog template loop class.
82
+ *
83
+ * Responsible for loading a group of blogs into a loop for display.
84
+ */
85
+ class BP_Blogs_Template {
86
+
87
+ /**
88
+ * The loop iterator.
89
+ *
90
+ * @access public
91
+ * @var int
92
+ */
93
+ var $current_blog = -1;
94
+
95
+ /**
96
+ * The number of blogs returned by the paged query.
97
+ *
98
+ * @access public
99
+ * @var int
100
+ */
101
+ var $blog_count;
102
+
103
+ /**
104
+ * Array of blogs located by the query..
105
+ *
106
+ * @access public
107
+ * @var array
108
+ */
109
+ var $blogs;
110
+
111
+ /**
112
+ * The blog object currently being iterated on.
113
+ *
114
+ * @access public
115
+ * @var object
116
+ */
117
+ var $blog;
118
+
119
+ /**
120
+ * A flag for whether the loop is currently being iterated.
121
+ *
122
+ * @access public
123
+ * @var bool
124
+ */
125
+ var $in_the_loop;
126
+
127
+ /**
128
+ * The page number being requested.
129
+ *
130
+ * @access public
131
+ * @var public
132
+ */
133
+ var $pag_page;
134
+
135
+ /**
136
+ * The number of items being requested per page.
137
+ *
138
+ * @access public
139
+ * @var public
140
+ */
141
+ var $pag_num;
142
+
143
+ /**
144
+ * An HTML string containing pagination links.
145
+ *
146
+ * @access public
147
+ * @var string
148
+ */
149
+ var $pag_links;
150
+
151
+ /**
152
+ * The total number of blogs matching the query parameters.
153
+ *
154
+ * @access public
155
+ * @var int
156
+ */
157
+ var $total_blog_count;
158
+
159
+ /**
160
+ * Constructor method.
161
+ *
162
+ * @see BP_Blogs_Blog::get() for a description of parameters.
163
+ *
164
+ * @param string $type See {@link BP_Blogs_Blog::get()}.
165
+ * @param string $page See {@link BP_Blogs_Blog::get()}.
166
+ * @param string $per_page See {@link BP_Blogs_Blog::get()}.
167
+ * @param string $max See {@link BP_Blogs_Blog::get()}.
168
+ * @param string $user_id See {@link BP_Blogs_Blog::get()}.
169
+ * @param string $search_terms See {@link BP_Blogs_Blog::get()}.
170
+ * @param string $page_arg The string used as a query parameter in
171
+ * pagination links. Default: 'bpage'.
172
+ * @param bool $update_meta_cache Whether to pre-fetch metadata for
173
+ * queried blogs.
174
+ * @param array $include_blog_ids Array of blog IDs to include.
175
+ */
176
+ function __construct( $type, $page, $per_page, $max, $user_id, $search_terms, $page_arg = 'bpage', $update_meta_cache = true, $include_blog_ids = false ) {
177
+
178
+ $this->pag_page = isset( $_REQUEST[$page_arg] ) ? intval( $_REQUEST[$page_arg] ) : $page;
179
+ $this->pag_num = isset( $_REQUEST['num'] ) ? intval( $_REQUEST['num'] ) : $per_page;
180
+
181
+ if ( isset( $_REQUEST['letter'] ) && '' != $_REQUEST['letter'] ) {
182
+ $this->blogs = BP_Blogs_Blog::get_by_letter( $_REQUEST['letter'], $this->pag_num, $this->pag_page );
183
+ } else {
184
+ $this->blogs = bp_blogs_get_blogs( array(
185
+ 'type' => $type,
186
+ 'per_page' => $this->pag_num,
187
+ 'page' => $this->pag_page,
188
+ 'user_id' => $user_id,
189
+ 'search_terms' => $search_terms,
190
+ 'update_meta_cache' => $update_meta_cache,
191
+ 'include_blog_ids' => $include_blog_ids,
192
+ ) );
193
+ }
194
+
195
+ if ( !$max || $max >= (int) $this->blogs['total'] )
196
+ $this->total_blog_count = (int) $this->blogs['total'];
197
+ else
198
+ $this->total_blog_count = (int) $max;
199
+
200
+ $this->blogs = $this->blogs['blogs'];
201
+
202
+ if ( $max ) {
203
+ if ( $max >= count($this->blogs) ) {
204
+ $this->blog_count = count( $this->blogs );
205
+ } else {
206
+ $this->blog_count = (int) $max;
207
+ }
208
+ } else {
209
+ $this->blog_count = count( $this->blogs );
210
+ }
211
+
212
+ if ( (int) $this->total_blog_count && (int) $this->pag_num ) {
213
+ $this->pag_links = paginate_links( array(
214
+ 'base' => add_query_arg( $page_arg, '%#%' ),
215
+ 'format' => '',
216
+ 'total' => ceil( (int) $this->total_blog_count / (int) $this->pag_num ),
217
+ 'current' => (int) $this->pag_page,
218
+ 'prev_text' => _x( '&larr;', 'Blog pagination previous text', 'buddypress' ),
219
+ 'next_text' => _x( '&rarr;', 'Blog pagination next text', 'buddypress' ),
220
+ 'mid_size' => 1
221
+ ) );
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Whether there are blogs available in the loop.
227
+ *
228
+ * @see bp_has_blogs()
229
+ *
230
+ * @return bool True if there are items in the loop, otherwise false.
231
+ */
232
+ function has_blogs() {
233
+ if ( $this->blog_count )
234
+ return true;
235
+
236
+ return false;
237
+ }
238
+
239
+ /**
240
+ * Set up the next blog and iterate index.
241
+ *
242
+ * @return object The next blog to iterate over.
243
+ */
244
+ function next_blog() {
245
+ $this->current_blog++;
246
+ $this->blog = $this->blogs[$this->current_blog];
247
+
248
+ return $this->blog;
249
+ }
250
+
251
+ /**
252
+ * Rewind the blogs and reset blog index.
253
+ */
254
+ function rewind_blogs() {
255
+ $this->current_blog = -1;
256
+ if ( $this->blog_count > 0 ) {
257
+ $this->blog = $this->blogs[0];
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Whether there are blogs left in the loop to iterate over.
263
+ *
264
+ * This method is used by {@link bp_blogs()} as part of the while loop
265
+ * that controls iteration inside the blogs loop, eg:
266
+ * while ( bp_blogs() ) { ...
267
+ *
268
+ * @see bp_blogs()
269
+ *
270
+ * @return bool True if there are more blogs to show, otherwise false.
271
+ */
272
+ function blogs() {
273
+ if ( $this->current_blog + 1 < $this->blog_count ) {
274
+ return true;
275
+ } elseif ( $this->current_blog + 1 == $this->blog_count ) {
276
+ do_action('blog_loop_end');
277
+ // Do some cleaning up after the loop
278
+ $this->rewind_blogs();
279
+ }
280
+
281
+ $this->in_the_loop = false;
282
+ return false;
283
+ }
284
+
285
+ /**
286
+ * Set up the current blog inside the loop.
287
+ *
288
+ * Used by {@link bp_the_blog()} to set up the current blog data while
289
+ * looping, so that template tags used during that iteration make
290
+ * reference to the current blog.
291
+ *
292
+ * @see bp_the_blog()
293
+ */
294
+ function the_blog() {
295
+
296
+ $this->in_the_loop = true;
297
+ $this->blog = $this->next_blog();
298
+
299
+ if ( 0 == $this->current_blog ) // loop has just started
300
+ do_action('blog_loop_start');
301
+ }
302
+ }
303
+
304
  /**
305
  * Rewind the blogs and reset blog index.
306
  */
319
  *
320
  * @global object $blogs_template {@link BP_Blogs_Template}
321
  *
322
+ * @param array $args {
323
  * Arguments for limiting the contents of the blogs loop. Most arguments
324
  * are in the same format as {@link BP_Blogs_Blog::get()}. However, because
325
  * the format of the arguments accepted here differs in a number of ways,
329
  * Arguments can be passed as an associative array, or as a URL query
330
  * string (eg, 'user_id=4&per_page=3').
331
  *
332
+ * @type int $page Which page of results to fetch. Using page=1 without
333
+ * per_page will result in no pagination. Default: 1.
334
+ * @type int|bool $per_page Number of results per page. Default: 20.
335
+ * @type string $page_arg The string used as a query parameter in
336
+ * pagination links. Default: 'bpage'.
337
+ * @type int|bool $max Maximum number of results to return.
338
+ * Default: false (unlimited).
339
+ * @type string $type The order in which results should be fetched.
340
+ * 'active', 'alphabetical', 'newest', or 'random'.
341
+ * @type array $include_blog_ids Array of blog IDs to limit results to.
342
+ * @type string $sort 'ASC' or 'DESC'. Default: 'DESC'.
343
+ * @type string $search_terms Limit results by a search term. Default: null.
344
+ * @type int $user_id The ID of the user whose blogs should be retrieved.
345
+ * When viewing a user profile page, 'user_id' defaults to the ID of
346
+ * the displayed user. Otherwise the default is false.
 
347
  * }
348
  * @return bool Returns true when blogs are found, otherwise false.
349
  */
350
  function bp_has_blogs( $args = '' ) {
351
  global $blogs_template;
352
 
353
+ /***
354
+ * Set the defaults based on the current page. Any of these will be overridden
355
+ * if arguments are directly passed into the loop. Custom plugins should always
356
+ * pass their parameters directly to the loop.
357
+ */
358
+ $type = 'active';
359
+ $user_id = 0;
360
+ $search_terms = null;
361