BuddyPress - Version 3.0.0-beta1

Version Description

= 2.9.4 = See: https://codex.buddypress.org/releases/version-2-9-4/

Download this release

Release Info

Developer DJPaul
Plugin Icon 128x128 BuddyPress
Version 3.0.0-beta1
Comparing to
See all releases

Code changes from version 2.6.0-beta1 to 3.0.0-beta1

Files changed (221) hide show
  1. bp-activity/actions/delete.php +72 -0
  2. bp-activity/actions/favorite.php +31 -0
  3. bp-activity/actions/feeds.php +183 -0
  4. bp-activity/actions/post.php +97 -0
  5. bp-activity/actions/reply.php +60 -0
  6. bp-activity/actions/spam.php +77 -0
  7. bp-activity/actions/unfavorite.php +31 -0
  8. bp-activity/admin/css/admin-rtl.css +23 -5
  9. bp-activity/admin/css/admin-rtl.min.css +1 -1
  10. bp-activity/admin/css/admin.css +23 -5
  11. bp-activity/admin/css/admin.min.css +1 -1
  12. bp-activity/admin/js/admin.min.js +1 -1
  13. bp-activity/bp-activity-actions.php +0 -889
  14. bp-activity/bp-activity-admin.php +16 -20
  15. bp-activity/bp-activity-akismet.php +21 -2
  16. bp-activity/bp-activity-cache.php +21 -0
  17. bp-activity/bp-activity-classes.php +0 -20
  18. bp-activity/bp-activity-embeds.php +4 -6
  19. bp-activity/bp-activity-filters.php +22 -23
  20. bp-activity/bp-activity-functions.php +670 -98
  21. bp-activity/bp-activity-loader.php +1 -5
  22. bp-activity/bp-activity-notifications.php +111 -252
  23. bp-activity/bp-activity-screens.php +0 -378
  24. bp-activity/bp-activity-template.php +82 -78
  25. bp-activity/classes/class-bp-activity-activity.php +124 -123
  26. bp-activity/classes/class-bp-activity-component.php +72 -22
  27. bp-activity/classes/class-bp-activity-list-table.php +30 -16
  28. bp-activity/classes/class-bp-activity-oembed-extension.php +2 -0
  29. bp-activity/classes/class-bp-activity-query.php +1 -1
  30. bp-activity/classes/class-bp-activity-template.php +3 -4
  31. bp-activity/classes/class-bp-akismet.php +18 -5
  32. bp-activity/css/mentions-rtl.css +24 -10
  33. bp-activity/css/mentions-rtl.min.css +1 -1
  34. bp-activity/css/mentions.css +25 -10
  35. bp-activity/css/mentions.min.css +1 -1
  36. bp-activity/js/mentions.js +10 -9
  37. bp-activity/js/mentions.min.js +1 -1
  38. bp-activity/screens/directory.php +37 -0
  39. bp-activity/screens/favorites.php +33 -0
  40. bp-activity/screens/friends.php +36 -0
  41. bp-activity/screens/groups.php +36 -0
  42. bp-activity/screens/just-me.php +32 -0
  43. bp-activity/screens/mentions.php +45 -0
  44. bp-activity/screens/permalink.php +166 -0
  45. bp-activity/screens/settings-email.php +83 -0
  46. bp-blogs/{bp-blogs-actions.php → actions/random.php} +3 -6
  47. bp-blogs/bp-blogs-activity.php +59 -22
  48. bp-blogs/bp-blogs-classes.php +0 -13
  49. bp-blogs/bp-blogs-filters.php +14 -0
  50. bp-blogs/bp-blogs-functions.php +119 -21
  51. bp-blogs/bp-blogs-loader.php +2 -4
  52. bp-blogs/bp-blogs-screens.php +0 -77
  53. bp-blogs/bp-blogs-template.php +109 -32
  54. bp-blogs/bp-blogs-widgets.php +1 -5
  55. bp-blogs/classes/class-bp-blogs-blog.php +50 -10
  56. bp-blogs/classes/class-bp-blogs-component.php +46 -7
  57. bp-blogs/screens/create.php +32 -0
  58. bp-blogs/screens/directory.php +29 -0
  59. bp-blogs/screens/my-blogs.php +27 -0
  60. bp-core/admin/bp-core-admin-classes.php +0 -13
  61. bp-core/admin/bp-core-admin-components.php +14 -16
  62. bp-core/admin/bp-core-admin-functions.php +64 -24
  63. bp-core/admin/bp-core-admin-schema.php +19 -26
  64. bp-core/admin/bp-core-admin-settings.php +35 -37
  65. bp-core/admin/bp-core-admin-slugs.php +11 -4
  66. bp-core/admin/bp-core-admin-tools.php +22 -31
  67. bp-core/admin/css/common-rtl.css +490 -91
  68. bp-core/admin/css/common-rtl.min.css +1 -1
  69. bp-core/admin/css/common.css +490 -91
  70. bp-core/admin/css/common.min.css +1 -1
  71. bp-core/admin/css/customizer-controls-rtl.css +3 -3
  72. bp-core/admin/css/customizer-controls-rtl.min.css +1 -1
  73. bp-core/admin/css/customizer-controls.css +3 -3
  74. bp-core/admin/css/customizer-controls.min.css +1 -1
  75. bp-core/admin/images/autolink-feature.png +0 -0
  76. bp-core/admin/images/bp-emails-feature.png +0 -0
  77. bp-core/admin/images/emoji-feature.png +0 -0
  78. bp-core/admin/images/post-type.png +0 -0
  79. bp-core/admin/images/twentytwelve.png +0 -0
  80. bp-core/admin/js/customizer-controls.min.js +1 -1
  81. bp-core/admin/js/customizer-receiver-emails.min.js +1 -1
  82. bp-core/admin/js/dismissible-admin-notices.js +16 -0
  83. bp-core/admin/js/dismissible-admin-notices.min.js +1 -0
  84. bp-core/bp-core-actions.php +23 -6
  85. bp-core/bp-core-admin.php +27 -23
  86. bp-core/bp-core-adminbar.php +5 -8
  87. bp-core/bp-core-attachments.php +129 -64
  88. bp-core/bp-core-avatars.php +83 -145
  89. bp-core/bp-core-buddybar.php +43 -40
  90. bp-core/bp-core-cache.php +133 -6
  91. bp-core/bp-core-caps.php +65 -20
  92. bp-core/bp-core-catchuri.php +123 -26
  93. bp-core/bp-core-classes.php +0 -40
  94. bp-core/bp-core-cssjs.php +147 -22
  95. bp-core/bp-core-customizer-email.php +3 -18
  96. bp-core/bp-core-dependency.php +18 -30
  97. bp-core/bp-core-filters.php +77 -53
  98. bp-core/bp-core-functions.php +534 -123
  99. bp-core/bp-core-loader.php +1 -8
  100. bp-core/bp-core-moderation.php +5 -5
  101. bp-core/bp-core-options.php +27 -130
  102. bp-core/bp-core-taxonomy.php +116 -8
  103. bp-core/bp-core-template-loader.php +16 -7
  104. bp-core/bp-core-template.php +111 -115
  105. bp-core/bp-core-theme-compatibility.php +30 -15
  106. bp-core/bp-core-update.php +109 -24
  107. bp-core/bp-core-widgets.php +1 -5
  108. bp-core/bp-core-wpabstraction.php +5 -12
  109. bp-core/classes/class-bp-admin.php +171 -132
  110. bp-core/classes/class-bp-attachment-avatar.php +15 -6
  111. bp-core/classes/class-bp-attachment-cover-image.php +2 -35
  112. bp-core/classes/class-bp-attachment.php +45 -37
  113. bp-core/classes/class-bp-button.php +238 -76
  114. bp-core/classes/class-bp-component.php +14 -0
  115. bp-core/classes/class-bp-core-bp-nav-backcompat.php +1 -1
  116. bp-core/classes/class-bp-core-html-element.php +127 -0
  117. bp-core/classes/class-bp-core-login-widget.php +2 -2
  118. bp-core/classes/class-bp-core-nav-item.php +0 -19
  119. bp-core/classes/class-bp-core-nav.php +22 -20
  120. bp-core/classes/class-bp-core-oembed-extension.php +23 -15
  121. bp-core/classes/class-bp-core-sort-by-key-callback.php +0 -83
  122. bp-core/classes/class-bp-core-user.php +24 -27
  123. bp-core/classes/class-bp-core.php +3 -5
  124. bp-core/classes/class-bp-email.php +1 -1
  125. bp-core/classes/class-bp-embed.php +0 -5
  126. bp-core/classes/class-bp-media-extractor.php +1 -1
  127. bp-core/classes/class-bp-members-suggestions.php +5 -4
  128. bp-core/classes/class-bp-phpmailer.php +13 -2
  129. bp-core/classes/class-bp-theme-compat.php +1 -1
  130. bp-core/classes/class-bp-user-query.php +24 -21
  131. bp-core/classes/class-bp-walker-nav-menu.php +1 -3
  132. bp-core/css/admin-bar-rtl.css +20 -5
  133. bp-core/css/admin-bar-rtl.min.css +1 -1
  134. bp-core/css/admin-bar.css +20 -5
  135. bp-core/css/admin-bar.min.css +1 -1
  136. bp-core/css/avatar-rtl.css +23 -16
  137. bp-core/css/avatar-rtl.min.css +1 -1
  138. bp-core/css/avatar.css +23 -16
  139. bp-core/css/avatar.min.css +1 -1
  140. bp-core/css/buddybar-rtl.css +39 -5
  141. bp-core/css/buddybar-rtl.min.css +1 -1
  142. bp-core/css/buddybar.css +39 -5
  143. bp-core/css/buddybar.min.css +1 -1
  144. bp-core/deprecated/1.2.php +1 -1
  145. bp-core/deprecated/1.5.php +1 -14
  146. bp-core/deprecated/1.6.php +7 -2
  147. bp-core/deprecated/1.7.php +1 -1
  148. bp-core/deprecated/1.9.php +19 -16
  149. bp-core/deprecated/2.1.php +4 -4
  150. bp-core/deprecated/2.5.php +3 -3
  151. bp-core/deprecated/2.7.php +26 -0
  152. bp-core/deprecated/2.8.php +203 -0
  153. bp-core/deprecated/2.9.php +30 -0
  154. bp-core/deprecated/3.0.php +187 -0
  155. bp-core/js/avatar.min.js +1 -1
  156. bp-core/js/bp-plupload.js +6 -1
  157. bp-core/js/bp-plupload.min.js +1 -1
  158. bp-core/js/confirm.js +3 -3
  159. bp-core/js/confirm.min.js +1 -1
  160. bp-core/js/cover-image.min.js +1 -1
  161. bp-core/js/jquery-cookie.min.js +0 -1
  162. bp-core/js/jquery-query.min.js +1 -1
  163. bp-core/js/jquery-scroll-to.min.js +0 -1
  164. bp-core/js/jquery.atwho.js +0 -875
  165. bp-core/js/jquery.atwho.min.js +0 -1
  166. bp-core/js/jquery.caret.min.js +0 -1
  167. bp-core/js/{jquery-cookie.js → vendor/jquery-cookie.js} +0 -0
  168. bp-core/js/vendor/jquery-cookie.min.js +1 -0
  169. bp-core/js/{jquery-scroll-to.js → vendor/jquery-scroll-to.js} +0 -0
  170. bp-core/js/vendor/jquery-scroll-to.min.js +1 -0
  171. bp-core/js/vendor/jquery.atwho.js +1212 -0
  172. bp-core/js/vendor/jquery.atwho.min.js +1 -0
  173. bp-core/js/{jquery.atwho.txt → vendor/jquery.atwho.txt} +0 -0
  174. bp-core/js/{jquery.caret.js → vendor/jquery.caret.js} +32 -1
  175. bp-core/js/vendor/jquery.caret.min.js +1 -0
  176. bp-core/js/{jquery.caret.txt → vendor/jquery.caret.txt} +0 -0
  177. bp-core/js/vendor/livestamp.js +129 -0
  178. bp-core/js/vendor/livestamp.min.js +1 -0
  179. bp-core/js/vendor/moment-js/locale/af.js +73 -0
  180. bp-core/js/vendor/moment-js/locale/af.min.js +1 -0
  181. bp-core/js/vendor/moment-js/locale/ar-ly.js +122 -0
  182. bp-core/js/vendor/moment-js/locale/ar-ly.min.js +1 -0
  183. bp-core/js/vendor/moment-js/locale/ar-ma.js +60 -0
  184. bp-core/js/vendor/moment-js/locale/ar-ma.min.js +1 -0
  185. bp-core/js/vendor/moment-js/locale/ar-sa.js +104 -0
  186. bp-core/js/vendor/moment-js/locale/ar-sa.min.js +1 -0
  187. bp-core/js/vendor/moment-js/locale/ar-tn.js +59 -0
  188. bp-core/js/vendor/moment-js/locale/ar-tn.min.js +1 -0
  189. bp-core/js/vendor/moment-js/locale/ar.js +137 -0
  190. bp-core/js/vendor/moment-js/locale/ar.min.js +1 -0
  191. bp-core/js/vendor/moment-js/locale/az.js +105 -0
  192. bp-core/js/vendor/moment-js/locale/az.min.js +1 -0
  193. bp-core/js/vendor/moment-js/locale/be.js +134 -0
  194. bp-core/js/vendor/moment-js/locale/be.min.js +1 -0
  195. bp-core/js/vendor/moment-js/locale/bg.js +90 -0
  196. bp-core/js/vendor/moment-js/locale/bg.min.js +1 -0
  197. bp-core/js/vendor/moment-js/locale/bn.js +119 -0
  198. bp-core/js/vendor/moment-js/locale/bn.min.js +1 -0
  199. bp-core/js/vendor/moment-js/locale/bo.js +119 -0
  200. bp-core/js/vendor/moment-js/locale/bo.min.js +1 -0
  201. bp-core/js/vendor/moment-js/locale/br.js +108 -0
  202. bp-core/js/vendor/moment-js/locale/br.min.js +1 -0
  203. bp-core/js/vendor/moment-js/locale/bs.js +143 -0
  204. bp-core/js/vendor/moment-js/locale/bs.min.js +1 -0
  205. bp-core/js/vendor/moment-js/locale/ca.js +81 -0
  206. bp-core/js/vendor/moment-js/locale/ca.min.js +1 -0
  207. bp-core/js/vendor/moment-js/locale/cs.js +172 -0
  208. bp-core/js/vendor/moment-js/locale/cs.min.js +1 -0
  209. bp-core/js/vendor/moment-js/locale/cv.js +63 -0
  210. bp-core/js/vendor/moment-js/locale/cv.min.js +1 -0
  211. bp-core/js/vendor/moment-js/locale/cy.js +81 -0
  212. bp-core/js/vendor/moment-js/locale/cy.min.js +1 -0
  213. bp-core/js/vendor/moment-js/locale/da.js +60 -0
  214. bp-core/js/vendor/moment-js/locale/da.min.js +1 -0
  215. bp-core/js/vendor/moment-js/locale/de-at.js +79 -0
  216. bp-core/js/vendor/moment-js/locale/de-at.min.js +1 -0
  217. bp-core/js/vendor/moment-js/locale/de.js +78 -0
  218. bp-core/js/vendor/moment-js/locale/de.min.js +1 -0
  219. bp-core/js/vendor/moment-js/locale/dv.js +99 -0
  220. bp-core/js/vendor/moment-js/locale/dv.min.js +1 -0
  221. bp-core/js/vendor/moment-js/locale/el.js +0 -0
bp-activity/actions/delete.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Delete action
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Delete specific activity item and redirect to previous page.
12
+ *
13
+ * @since 1.1.0
14
+ *
15
+ * @param int $activity_id Activity id to be deleted. Defaults to 0.
16
+ * @return bool False on failure.
17
+ */
18
+ function bp_activity_action_delete_activity( $activity_id = 0 ) {
19
+ // Not viewing activity or action is not delete.
20
+ if ( !bp_is_activity_component() || !bp_is_current_action( 'delete' ) )
21
+ return false;
22
+
23
+ if ( empty( $activity_id ) && bp_action_variable( 0 ) )
24
+ $activity_id = (int) bp_action_variable( 0 );
25
+
26
+ // Not viewing a specific activity item.
27
+ if ( empty( $activity_id ) )
28
+ return false;
29
+
30
+ // Check the nonce.
31
+ check_admin_referer( 'bp_activity_delete_link' );
32
+
33
+ // Load up the activity item.
34
+ $activity = new BP_Activity_Activity( $activity_id );
35
+
36
+ // Check access.
37
+ if ( ! bp_activity_user_can_delete( $activity ) )
38
+ return false;
39
+
40
+ /**
41
+ * Fires before the deletion so plugins can still fetch information about it.
42
+ *
43
+ * @since 1.5.0
44
+ *
45
+ * @param int $activity_id The activity ID.
46
+ * @param int $user_id The user associated with the activity.
47
+ */
48
+ do_action( 'bp_activity_before_action_delete_activity', $activity_id, $activity->user_id );
49
+
50
+ // Delete the activity item and provide user feedback.
51
+ if ( bp_activity_delete( array( 'id' => $activity_id, 'user_id' => $activity->user_id ) ) )
52
+ bp_core_add_message( __( 'Activity deleted successfully', 'buddypress' ) );
53
+ else
54
+ bp_core_add_message( __( 'There was an error when deleting that activity', 'buddypress' ), 'error' );
55
+
56
+ /**
57
+ * Fires after the deletion so plugins can act afterwards based on the activity.
58
+ *
59
+ * @since 1.1.0
60
+ *
61
+ * @param int $activity_id The activity ID.
62
+ * @param int $user_id The user associated with the activity.
63
+ */
64
+ do_action( 'bp_activity_action_delete_activity', $activity_id, $activity->user_id );
65
+
66
+ // Check for the redirect query arg, otherwise let WP handle things.
67
+ if ( !empty( $_GET['redirect_to'] ) )
68
+ bp_core_redirect( esc_url( $_GET['redirect_to'] ) );
69
+ else
70
+ bp_core_redirect( wp_get_referer() );
71
+ }
72
+ add_action( 'bp_actions', 'bp_activity_action_delete_activity' );
bp-activity/actions/favorite.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Favorite action
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Mark activity as favorite.
12
+ *
13
+ * @since 1.2.0
14
+ *
15
+ * @return bool False on failure.
16
+ */
17
+ function bp_activity_action_mark_favorite() {
18
+ if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'favorite' ) )
19
+ return false;
20
+
21
+ // Check the nonce.
22
+ check_admin_referer( 'mark_favorite' );
23
+
24
+ if ( bp_activity_add_user_favorite( bp_action_variable( 0 ) ) )
25
+ bp_core_add_message( __( 'Activity marked as favorite.', 'buddypress' ) );
26
+ else
27
+ bp_core_add_message( __( 'There was an error marking that activity as a favorite. Please try again.', 'buddypress' ), 'error' );
28
+
29
+ bp_core_redirect( wp_get_referer() . '#activity-' . bp_action_variable( 0 ) );
30
+ }
31
+ add_action( 'bp_actions', 'bp_activity_action_mark_favorite' );
bp-activity/actions/feeds.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: RSS feed actions
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the sitewide activity feed.
12
+ *
13
+ * @since 1.0.0
14
+ *
15
+ * @return bool False on failure.
16
+ */
17
+ function bp_activity_action_sitewide_feed() {
18
+ $bp = buddypress();
19
+
20
+ if ( ! bp_is_activity_component() || ! bp_is_current_action( 'feed' ) || bp_is_user() || ! empty( $bp->groups->current_group ) )
21
+ return false;
22
+
23
+ // Setup the feed.
24
+ buddypress()->activity->feed = new BP_Activity_Feed( array(
25
+ 'id' => 'sitewide',
26
+
27
+ /* translators: Sitewide activity RSS title - "[Site Name] | Site Wide Activity" */
28
+ 'title' => sprintf( __( '%s | Site-Wide Activity', 'buddypress' ), bp_get_site_name() ),
29
+
30
+ 'link' => bp_get_activity_directory_permalink(),
31
+ 'description' => __( 'Activity feed for the entire site.', 'buddypress' ),
32
+ 'activity_args' => 'display_comments=threaded'
33
+ ) );
34
+ }
35
+ add_action( 'bp_actions', 'bp_activity_action_sitewide_feed' );
36
+
37
+ /**
38
+ * Load a user's personal activity feed.
39
+ *
40
+ * @since 1.0.0
41
+ *
42
+ * @return bool False on failure.
43
+ */
44
+ function bp_activity_action_personal_feed() {
45
+ if ( ! bp_is_user_activity() || ! bp_is_current_action( 'feed' ) ) {
46
+ return false;
47
+ }
48
+
49
+ // Setup the feed.
50
+ buddypress()->activity->feed = new BP_Activity_Feed( array(
51
+ 'id' => 'personal',
52
+
53
+ /* translators: Personal activity RSS title - "[Site Name] | [User Display Name] | Activity" */
54
+ 'title' => sprintf( __( '%1$s | %2$s | Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
55
+
56
+ 'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() ),
57
+ 'description' => sprintf( __( 'Activity feed for %s.', 'buddypress' ), bp_get_displayed_user_fullname() ),
58
+ 'activity_args' => 'user_id=' . bp_displayed_user_id()
59
+ ) );
60
+ }
61
+ add_action( 'bp_actions', 'bp_activity_action_personal_feed' );
62
+
63
+ /**
64
+ * Load a user's friends' activity feed.
65
+ *
66
+ * @since 1.0.0
67
+ *
68
+ * @return bool False on failure.
69
+ */
70
+ function bp_activity_action_friends_feed() {
71
+ if ( ! bp_is_active( 'friends' ) || ! bp_is_user_activity() || ! bp_is_current_action( bp_get_friends_slug() ) || ! bp_is_action_variable( 'feed', 0 ) ) {
72
+ return false;
73
+ }
74
+
75
+ // Setup the feed.
76
+ buddypress()->activity->feed = new BP_Activity_Feed( array(
77
+ 'id' => 'friends',
78
+
79
+ /* translators: Friends activity RSS title - "[Site Name] | [User Display Name] | Friends Activity" */
80
+ 'title' => sprintf( __( '%1$s | %2$s | Friends Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
81
+
82
+ 'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_friends_slug() ),
83
+ 'description' => sprintf( __( "Activity feed for %s's friends.", 'buddypress' ), bp_get_displayed_user_fullname() ),
84
+ 'activity_args' => 'scope=friends'
85
+ ) );
86
+ }
87
+ add_action( 'bp_actions', 'bp_activity_action_friends_feed' );
88
+
89
+ /**
90
+ * Load the activity feed for a user's groups.
91
+ *
92
+ * @since 1.2.0
93
+ *
94
+ * @return bool False on failure.
95
+ */
96
+ function bp_activity_action_my_groups_feed() {
97
+ if ( ! bp_is_active( 'groups' ) || ! bp_is_user_activity() || ! bp_is_current_action( bp_get_groups_slug() ) || ! bp_is_action_variable( 'feed', 0 ) ) {
98
+ return false;
99
+ }
100
+
101
+ // Get displayed user's group IDs.
102
+ $groups = groups_get_user_groups();
103
+ $group_ids = implode( ',', $groups['groups'] );
104
+
105
+ // Setup the feed.
106
+ buddypress()->activity->feed = new BP_Activity_Feed( array(
107
+ 'id' => 'mygroups',
108
+
109
+ /* translators: Member groups activity RSS title - "[Site Name] | [User Display Name] | Groups Activity" */
110
+ 'title' => sprintf( __( '%1$s | %2$s | Group Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
111
+
112
+ 'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_groups_slug() ),
113
+ 'description' => sprintf( __( "Public group activity feed of which %s is a member.", 'buddypress' ), bp_get_displayed_user_fullname() ),
114
+ 'activity_args' => array(
115
+ 'object' => buddypress()->groups->id,
116
+ 'primary_id' => $group_ids,
117
+ 'display_comments' => 'threaded'
118
+ )
119
+ ) );
120
+ }
121
+ add_action( 'bp_actions', 'bp_activity_action_my_groups_feed' );
122
+
123
+ /**
124
+ * Load a user's @mentions feed.
125
+ *
126
+ * @since 1.2.0
127
+ *
128
+ * @return bool False on failure.
129
+ */
130
+ function bp_activity_action_mentions_feed() {
131
+ if ( ! bp_activity_do_mentions() ) {
132
+ return false;
133
+ }
134
+
135
+ if ( !bp_is_user_activity() || ! bp_is_current_action( 'mentions' ) || ! bp_is_action_variable( 'feed', 0 ) ) {
136
+ return false;
137
+ }
138
+
139
+ // Setup the feed.
140
+ buddypress()->activity->feed = new BP_Activity_Feed( array(
141
+ 'id' => 'mentions',
142
+
143
+ /* translators: User mentions activity RSS title - "[Site Name] | [User Display Name] | Mentions" */
144
+ 'title' => sprintf( __( '%1$s | %2$s | Mentions', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
145
+
146
+ 'link' => bp_displayed_user_domain() . bp_get_activity_slug() . '/mentions/',
147
+ 'description' => sprintf( __( "Activity feed mentioning %s.", 'buddypress' ), bp_get_displayed_user_fullname() ),
148
+ 'activity_args' => array(
149
+ 'search_terms' => '@' . bp_core_get_username( bp_displayed_user_id() )
150
+ )
151
+ ) );
152
+ }
153
+ add_action( 'bp_actions', 'bp_activity_action_mentions_feed' );
154
+
155
+ /**
156
+ * Load a user's favorites feed.
157
+ *
158
+ * @since 1.2.0
159
+ *
160
+ * @return bool False on failure.
161
+ */
162
+ function bp_activity_action_favorites_feed() {
163
+ if ( ! bp_is_user_activity() || ! bp_is_current_action( 'favorites' ) || ! bp_is_action_variable( 'feed', 0 ) ) {
164
+ return false;
165
+ }
166
+
167
+ // Get displayed user's favorite activity IDs.
168
+ $favs = bp_activity_get_user_favorites( bp_displayed_user_id() );
169
+ $fav_ids = implode( ',', (array) $favs );
170
+
171
+ // Setup the feed.
172
+ buddypress()->activity->feed = new BP_Activity_Feed( array(
173
+ 'id' => 'favorites',
174
+
175
+ /* translators: User activity favorites RSS title - "[Site Name] | [User Display Name] | Favorites" */
176
+ 'title' => sprintf( __( '%1$s | %2$s | Favorites', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
177
+
178
+ 'link' => bp_displayed_user_domain() . bp_get_activity_slug() . '/favorites/',
179
+ 'description' => sprintf( __( "Activity feed of %s's favorites.", 'buddypress' ), bp_get_displayed_user_fullname() ),
180
+ 'activity_args' => 'include=' . $fav_ids
181
+ ) );
182
+ }
183
+ add_action( 'bp_actions', 'bp_activity_action_favorites_feed' );
bp-activity/actions/post.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Post action
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Post user/group activity update.
12
+ *
13
+ * @since 1.2.0
14
+ *
15
+ * @return bool False on failure.
16
+ */
17
+ function bp_activity_action_post_update() {
18
+ // Do not proceed if user is not logged in, not viewing activity, or not posting.
19
+ if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'post' ) )
20
+ return false;
21
+
22
+ // Check the nonce.
23
+ check_admin_referer( 'post_update', '_wpnonce_post_update' );
24
+
25
+ /**
26
+ * Filters the content provided in the activity input field.
27
+ *
28
+ * @since 1.2.0
29
+ *
30
+ * @param string $value Activity message being posted.
31
+ */
32
+ $content = apply_filters( 'bp_activity_post_update_content', $_POST['whats-new'] );
33
+
34
+ if ( ! empty( $_POST['whats-new-post-object'] ) ) {
35
+
36
+ /**
37
+ * Filters the item type that the activity update should be associated with.
38
+ *
39
+ * @since 1.2.0
40
+ *
41
+ * @param string $value Item type to associate with.
42
+ */
43
+ $object = apply_filters( 'bp_activity_post_update_object', $_POST['whats-new-post-object'] );
44
+ }
45
+
46
+ if ( ! empty( $_POST['whats-new-post-in'] ) ) {
47
+
48
+ /**
49
+ * Filters what component the activity is being to.
50
+ *
51
+ * @since 1.2.0
52
+ *
53
+ * @param string $value Chosen component to post activity to.
54
+ */
55
+ $item_id = apply_filters( 'bp_activity_post_update_item_id', $_POST['whats-new-post-in'] );
56
+ }
57
+
58
+ // No activity content so provide feedback and redirect.
59
+ if ( empty( $content ) ) {
60
+ bp_core_add_message( __( 'Please enter some content to post.', 'buddypress' ), 'error' );
61
+ bp_core_redirect( wp_get_referer() );
62
+ }
63
+
64
+ // No existing item_id.
65
+ if ( empty( $item_id ) ) {
66
+ $activity_id = bp_activity_post_update( array( 'content' => $content ) );
67
+
68
+ // Post to groups object.
69
+ } elseif ( 'groups' == $object && bp_is_active( 'groups' ) ) {
70
+ if ( (int) $item_id ) {
71
+ $activity_id = groups_post_update( array( 'content' => $content, 'group_id' => $item_id ) );
72
+ }
73
+
74
+ } else {
75
+
76
+ /**
77
+ * Filters activity object for BuddyPress core and plugin authors before posting activity update.
78
+ *
79
+ * @since 1.2.0
80
+ *
81
+ * @param string $object Activity item being associated to.
82
+ * @param string $item_id Component ID being posted to.
83
+ * @param string $content Activity content being posted.
84
+ */
85
+ $activity_id = apply_filters( 'bp_activity_custom_update', $object, $item_id, $content );
86
+ }
87
+
88
+ // Provide user feedback.
89
+ if ( !empty( $activity_id ) )
90
+ bp_core_add_message( __( 'Update Posted!', 'buddypress' ) );
91
+ else
92
+ bp_core_add_message( __( 'There was an error when posting your update. Please try again.', 'buddypress' ), 'error' );
93
+
94
+ // Redirect.
95
+ bp_core_redirect( wp_get_referer() );
96
+ }
97
+ add_action( 'bp_actions', 'bp_activity_action_post_update' );
bp-activity/actions/reply.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Reply action
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Post new activity comment.
12
+ *
13
+ * @since 1.2.0
14
+ *
15
+ * @return bool False on failure.
16
+ */
17
+ function bp_activity_action_post_comment() {
18
+ if ( !is_user_logged_in() || !bp_is_activity_component() || !bp_is_current_action( 'reply' ) )
19
+ return false;
20
+
21
+ // Check the nonce.
22
+ check_admin_referer( 'new_activity_comment', '_wpnonce_new_activity_comment' );
23
+
24
+ /**
25
+ * Filters the activity ID a comment will be in reply to.
26
+ *
27
+ * @since 1.2.0
28
+ *
29
+ * @param string $value ID of the activity being replied to.
30
+ */
31
+ $activity_id = apply_filters( 'bp_activity_post_comment_activity_id', $_POST['comment_form_id'] );
32
+
33
+ /**
34
+ * Filters the comment content for a comment reply.
35
+ *
36
+ * @since 1.2.0
37
+ *
38
+ * @param string $value Comment content being posted.
39
+ */
40
+ $content = apply_filters( 'bp_activity_post_comment_content', $_POST['ac_input_' . $activity_id] );
41
+
42
+ if ( empty( $content ) ) {
43
+ bp_core_add_message( __( 'Please do not leave the comment area blank.', 'buddypress' ), 'error' );
44
+ bp_core_redirect( wp_get_referer() . '#ac-form-' . $activity_id );
45
+ }
46
+
47
+ $comment_id = bp_activity_new_comment( array(
48
+ 'content' => $content,
49
+ 'activity_id' => $activity_id,
50
+ 'parent_id' => false
51
+ ));
52
+
53
+ if ( !empty( $comment_id ) )
54
+ bp_core_add_message( __( 'Reply Posted!', 'buddypress' ) );
55
+ else
56
+ bp_core_add_message( __( 'There was an error posting that reply. Please try again.', 'buddypress' ), 'error' );
57
+
58
+ bp_core_redirect( wp_get_referer() . '#ac-form-' . $activity_id );
59
+ }
60
+ add_action( 'bp_actions', 'bp_activity_action_post_comment' );
bp-activity/actions/spam.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Spam action
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Mark specific activity item as spam and redirect to previous page.
12
+ *
13
+ * @since 1.6.0
14
+ *
15
+ * @param int $activity_id Activity id to be deleted. Defaults to 0.
16
+ * @return bool False on failure.
17
+ */
18
+ function bp_activity_action_spam_activity( $activity_id = 0 ) {
19
+ $bp = buddypress();
20
+
21
+ // Not viewing activity, or action is not spam, or Akismet isn't present.
22
+ if ( !bp_is_activity_component() || !bp_is_current_action( 'spam' ) || empty( $bp->activity->akismet ) )
23
+ return false;
24
+
25
+ if ( empty( $activity_id ) && bp_action_variable( 0 ) )
26
+ $activity_id = (int) bp_action_variable( 0 );
27
+
28
+ // Not viewing a specific activity item.
29
+ if ( empty( $activity_id ) )
30
+ return false;
31
+
32
+ // Is the current user allowed to spam items?
33
+ if ( !bp_activity_user_can_mark_spam() )
34
+ return false;
35
+
36
+ // Load up the activity item.
37
+ $activity = new BP_Activity_Activity( $activity_id );
38
+ if ( empty( $activity->id ) )
39
+ return false;
40
+
41
+ // Check nonce.
42
+ check_admin_referer( 'bp_activity_akismet_spam_' . $activity->id );
43
+
44
+ /**
45
+ * Fires before the marking activity as spam so plugins can modify things if they want to.
46
+ *
47
+ * @since 1.6.0
48
+ *
49
+ * @param int $activity_id Activity ID to be marked as spam.
50
+ * @param object $activity Activity object for the ID to be marked as spam.
51
+ */
52
+ do_action( 'bp_activity_before_action_spam_activity', $activity->id, $activity );
53
+
54
+ // Mark as spam.
55
+ bp_activity_mark_as_spam( $activity );
56
+ $activity->save();
57
+
58
+ // Tell the user the spamming has been successful.
59
+ bp_core_add_message( __( 'The activity item has been marked as spam and is no longer visible.', 'buddypress' ) );
60
+
61
+ /**
62
+ * Fires after the marking activity as spam so plugins can act afterwards based on the activity.
63
+ *
64
+ * @since 1.6.0
65
+ *
66
+ * @param int $activity_id Activity ID that was marked as spam.
67
+ * @param int $user_id User ID associated with activity.
68
+ */
69
+ do_action( 'bp_activity_action_spam_activity', $activity_id, $activity->user_id );
70
+
71
+ // Check for the redirect query arg, otherwise let WP handle things.
72
+ if ( !empty( $_GET['redirect_to'] ) )
73
+ bp_core_redirect( esc_url( $_GET['redirect_to'] ) );
74
+ else
75
+ bp_core_redirect( wp_get_referer() );
76
+ }
77
+ add_action( 'bp_actions', 'bp_activity_action_spam_activity' );
bp-activity/actions/unfavorite.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Unfavorite action
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityActions
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Remove activity from favorites.
12
+ *
13
+ * @since 1.2.0
14
+ *
15
+ * @return bool False on failure.
16
+ */
17
+ function bp_activity_action_remove_favorite() {
18
+ if ( ! is_user_logged_in() || ! bp_is_activity_component() || ! bp_is_current_action( 'unfavorite' ) )
19
+ return false;
20
+
21
+ // Check the nonce.
22
+ check_admin_referer( 'unmark_favorite' );
23
+
24
+ if ( bp_activity_remove_user_favorite( bp_action_variable( 0 ) ) )
25
+ bp_core_add_message( __( 'Activity removed as favorite.', 'buddypress' ) );
26
+ else
27
+ bp_core_add_message( __( 'There was an error removing that activity as a favorite. Please try again.', 'buddypress' ), 'error' );
28
+
29
+ bp_core_redirect( wp_get_referer() . '#activity-' . bp_action_variable( 0 ) );
30
+ }
31
+ add_action( 'bp_actions', 'bp_activity_action_remove_favorite' );
bp-activity/admin/css/admin-rtl.css CHANGED
@@ -1,16 +1,20 @@
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
  }
@@ -18,36 +22,43 @@
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;
@@ -57,31 +68,38 @@
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
- }
1
  .akismet-status {
2
  float: left;
3
  }
4
+
5
  .akismet-status a {
6
+ color: #aaa;
7
  font-style: italic;
8
  }
9
+
10
  .akismet-history {
11
  margin: 13px;
12
  }
13
+
14
  .akismet-history div {
15
  margin-bottom: 13px;
16
  }
17
+
18
  .akismet-history span {
19
  color: #999;
20
  }
22
  #wp-bp-activities-wrap {
23
  padding: 5px 0;
24
  }
25
+
26
  #bp-activities {
27
  height: 120px;
28
  }
29
+
30
  #bp-replyhead {
31
  font-size: 1em;
32
+ line-height: 1.4;
33
  margin: 0;
34
  }
35
+
36
  #bp-replysubmit {
37
  margin: 0;
38
  padding: 0 0 3px;
39
  text-align: center;
40
  }
41
+
42
  #bp-replysubmit .error {
43
+ color: #f00;
44
  line-height: 21px;
45
  text-align: center;
46
  vertical-align: center;
47
  }
48
+
49
  #bp-replysubmit img.waiting {
50
  float: left;
51
  padding: 4px 10px 0;
52
  vertical-align: top;
53
  }
54
+
55
  #bp-activities-form .column-response img {
56
  float: right;
57
  margin-bottom: 5px;
58
  margin-left: 10px;
59
  margin-top: 1px;
60
  }
61
+
62
  .activity-errors {
63
  list-style-type: disc;
64
  margin-right: 2em;
68
  #bp_activity_content div.inside {
69
  line-height: 0;
70
  }
71
+
72
  #bp_activity_action h3,
73
  #bp_activity_content h3 {
74
  cursor: auto;
75
  }
76
+
77
  #bp_activity_action td.mceIframeContainer,
78
  #bp_activity_content td.mceIframeContainer {
79
+ background-color: #fff;
80
  }
81
+
82
  #post-body #bp-activities-action_resize,
83
  #post-body #bp-activities-content_resize {
84
  position: inherit;
85
  margin-top: -2px;
86
  }
87
+
88
  #bp_activity_link input {
89
  width: 99%;
90
  }
91
+
92
  #bp-activities-primaryid {
93
  margin-bottom: 1em;
94
  }
95
+
96
  .column-action {
97
  width: 12%;
98
  }
99
 
100
  @media screen and (max-width: 782px) {
101
+
102
  body.toplevel_page_bp-activity .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column) {
103
  display: table-cell;
104
  }
105
+ }
bp-activity/admin/css/admin-rtl.min.css CHANGED
@@ -1 +1 @@
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}}
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.4;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
@@ -1,16 +1,20 @@
1
  .akismet-status {
2
  float: right;
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
  }
@@ -18,36 +22,43 @@
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: right;
42
  padding: 4px 10px 0;
43
  vertical-align: top;
44
  }
 
45
  #bp-activities-form .column-response img {
46
  float: left;
47
  margin-bottom: 5px;
48
  margin-right: 10px;
49
  margin-top: 1px;
50
  }
 
51
  .activity-errors {
52
  list-style-type: disc;
53
  margin-left: 2em;
@@ -57,31 +68,38 @@
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
- }
1
  .akismet-status {
2
  float: right;
3
  }
4
+
5
  .akismet-status a {
6
+ color: #aaa;
7
  font-style: italic;
8
  }
9
+
10
  .akismet-history {
11
  margin: 13px;
12
  }
13
+
14
  .akismet-history div {
15
  margin-bottom: 13px;
16
  }
17
+
18
  .akismet-history span {
19
  color: #999;
20
  }
22
  #wp-bp-activities-wrap {
23
  padding: 5px 0;
24
  }
25
+
26
  #bp-activities {
27
  height: 120px;
28
  }
29
+
30
  #bp-replyhead {
31
  font-size: 1em;
32
+ line-height: 1.4;
33
  margin: 0;
34
  }
35
+
36
  #bp-replysubmit {
37
  margin: 0;
38
  padding: 0 0 3px;
39
  text-align: center;
40
  }
41
+
42
  #bp-replysubmit .error {
43
+ color: #f00;
44
  line-height: 21px;
45
  text-align: center;
46
  vertical-align: center;
47
  }
48
+
49
  #bp-replysubmit img.waiting {
50
  float: right;
51
  padding: 4px 10px 0;
52
  vertical-align: top;
53
  }
54
+
55
  #bp-activities-form .column-response img {
56
  float: left;
57
  margin-bottom: 5px;
58
  margin-right: 10px;
59
  margin-top: 1px;
60
  }
61
+
62
  .activity-errors {
63
  list-style-type: disc;
64
  margin-left: 2em;
68
  #bp_activity_content div.inside {
69
  line-height: 0;
70
  }
71
+
72
  #bp_activity_action h3,
73
  #bp_activity_content h3 {
74
  cursor: auto;
75
  }
76
+
77
  #bp_activity_action td.mceIframeContainer,
78
  #bp_activity_content td.mceIframeContainer {
79
+ background-color: #fff;
80
  }
81
+
82
  #post-body #bp-activities-action_resize,
83
  #post-body #bp-activities-content_resize {
84
  position: inherit;
85
  margin-top: -2px;
86
  }
87
+
88
  #bp_activity_link input {
89
  width: 99%;
90
  }
91
+
92
  #bp-activities-primaryid {
93
  margin-bottom: 1em;
94
  }
95
+
96
  .column-action {
97
  width: 12%;
98
  }
99
 
100
  @media screen and (max-width: 782px) {
101
+
102
  body.toplevel_page_bp-activity .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column) {
103
  display: table-cell;
104
  }
105
+ }
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.4;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}}
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(i){var t={init:function(){i(document).on("click",".row-actions a.reply",t.open),i(document).on("click","#bp-activities-container a.cancel",t.close),i(document).on("click","#bp-activities-container a.save",t.send),i(document).on("keyup","#bp-activities:visible",function(i){27===i.which&&t.close()})},open:function(){var t=i("#bp-activities-container").hide();return i(this).parents("tr").after(t),t.fadeIn("300"),i("#bp-activities").focus(),!1},close:function(){return i("#bp-activities-container").fadeOut("200",function(){i("#bp-activities").val("").blur(),i("#bp-replysubmit .error").html("").hide(),i("#bp-replysubmit .waiting").hide()}),!1},send:function(){i("#bp-replysubmit .error").hide(),i("#bp-replysubmit .waiting").show();var e={};return e["_ajax_nonce-bp-activity-admin-reply"]=i('#bp-activities-container input[name="_ajax_nonce-bp-activity-admin-reply"]').val(),e.action="bp-activity-admin-reply",e.content=i("#bp-activities").val(),e.parent_id=i("#bp-activities-container").prev().data("parent_id"),e.root_id=i("#bp-activities-container").prev().data("root_id"),i.ajax({data:e,type:"POST",url:ajaxurl,error:function(i){t.error(i)},success:function(i){t.show(i)}}),!1},error:function(t){var e=t.statusText;i("#bp-replysubmit .waiting").hide(),t.responseText&&(e=t.responseText.replace(/<.[^<>]*?>/g,"")),e&&i("#bp-replysubmit .error").html(e).show()},show:function(e){var n,a,r;return"string"==typeof e?(t.error({responseText:e}),!1):(r=wpAjax.parseAjaxResponse(e)).errors?(t.error({responseText:wpAjax.broken}),!1):(r=r.responses[0],void i("#bp-activities-container").fadeOut("200",function(){i("#bp-activities").val("").blur(),i("#bp-replysubmit .error").html("").hide(),i("#bp-replysubmit .waiting").hide(),i("#bp-activities-container").before(r.data),a=i("#activity-"+r.id),n=a.closest(".widefat").css("backgroundColor"),a.animate({backgroundColor:"#CEB"},300).animate({backgroundColor:n},300)}))}};i(document).ready(function(){t.init(),i("#bp_activity_action h3, #bp_activity_content h3").unbind("click"),"undefined"!=typeof postboxes&&postboxes.add_postbox_toggles(bp_activity_admin_vars.page)})}(jQuery);
bp-activity/bp-activity-actions.php DELETED
@@ -1,889 +0,0 @@
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
5
- * user back to the default screen after execution.
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 );
31
-
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
53
- if ( empty( $activity['activities'][0] ) ) {
54
- bp_do_404();
55
- return;
56
- } else {
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( array( 'group_id' => $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' );
106
-
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() );
169
- }
170
- add_action( 'bp_actions', 'bp_activity_action_delete_activity' );
171
-
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
-
194
- // Is the current user allowed to spam items?
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() );
238
- }
239
- add_action( 'bp_actions', 'bp_activity_action_spam_activity' );
240
-
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' );
330
-
331
- /**
332
- * Post new activity comment.
333
- *
334
- * @since 1.2.0
335
- *
336
- * @return bool False on failure.
337
- */
338
- function bp_activity_action_post_comment() {
339
-
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 ) ) {
365
- bp_core_add_message( __( 'Please do not leave the comment area blank.', 'buddypress' ), 'error' );
366
- bp_core_redirect( wp_get_referer() . '#ac-form-' . $activity_id );
367
- }
368
-
369
- $comment_id = bp_activity_new_comment( array(
370
- 'content' => $content,
371
- 'activity_id' => $activity_id,
372
- 'parent_id' => false
373
- ));
374
-
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
- }
382
- add_action( 'bp_actions', 'bp_activity_action_post_comment' );
383
-
384
- /**
385
- * Mark activity as favorite.
386
- *
387
- * @since 1.2.0
388
- *
389
- * @return bool False on failure.
390
- */
391
- function bp_activity_action_mark_favorite() {
392
-
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
- }
406
- add_action( 'bp_actions', 'bp_activity_action_mark_favorite' );
407
-
408
- /**
409
- * Remove activity from favorites.
410
- *
411
- * @since 1.2.0
412
- *
413
- * @return bool False on failure.
414
- */
415
- function bp_activity_action_remove_favorite() {
416
-
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
- }
430
- add_action( 'bp_actions', 'bp_activity_action_remove_favorite' );
431
-
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' ),
454
- 'activity_args' => 'display_comments=threaded'
455
- ) );
456
- }
457
- add_action( 'bp_actions', 'bp_activity_action_sitewide_feed' );
458
-
459
- /**
460
- * Load a user's personal activity feed.
461
- *
462
- * @since 1.0.0
463
- *
464
- * @return bool False on failure.
465
- */
466
- function bp_activity_action_personal_feed() {
467
- if ( ! bp_is_user_activity() || ! bp_is_current_action( 'feed' ) ) {
468
- return false;
469
- }
470
-
471
- // Setup the feed.
472
- buddypress()->activity->feed = new BP_Activity_Feed( array(
473
- 'id' => 'personal',
474
-
475
- /* translators: Personal activity RSS title - "[Site Name] | [User Display Name] | Activity" */
476
- 'title' => sprintf( __( '%1$s | %2$s | Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
477
-
478
- 'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() ),
479
- 'description' => sprintf( __( 'Activity feed for %s.', 'buddypress' ), bp_get_displayed_user_fullname() ),
480
- 'activity_args' => 'user_id=' . bp_displayed_user_id()
481
- ) );
482
- }
483
- add_action( 'bp_actions', 'bp_activity_action_personal_feed' );
484
-
485
- /**
486
- * Load a user's friends' activity feed.
487
- *
488
- * @since 1.0.0
489
- *
490
- * @return bool False on failure.
491
- */
492
- function bp_activity_action_friends_feed() {
493
- if ( ! bp_is_active( 'friends' ) || ! bp_is_user_activity() || ! bp_is_current_action( bp_get_friends_slug() ) || ! bp_is_action_variable( 'feed', 0 ) ) {
494
- return false;
495
- }
496
-
497
- // Setup the feed.
498
- buddypress()->activity->feed = new BP_Activity_Feed( array(
499
- 'id' => 'friends',
500
-
501
- /* translators: Friends activity RSS title - "[Site Name] | [User Display Name] | Friends Activity" */
502
- 'title' => sprintf( __( '%1$s | %2$s | Friends Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
503
-
504
- 'link' => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_friends_slug() ),
505
- 'description' => sprintf( __( "Activity feed for %s's friends.", 'buddypress' ), bp_get_displayed_user_fullname() ),
506
- 'activity_args' => 'scope=friends'
507
- ) );
508
- }
509
- add_action( 'bp_actions', 'bp_activity_action_friends_feed' );
510
-
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
- */
518
- function bp_activity_action_my_groups_feed() {
519
- if ( ! bp_is_active( 'groups' ) || ! bp_is_user_activity() || ! bp_is_current_action( bp_get_groups_slug() ) || ! bp_is_action_variable( 'feed', 0 ) ) {
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
-
531
- /* translators: Member groups activity RSS title - "[Site Name] | [User Display Name] | Groups Activity" */
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,
539
- 'display_comments' => 'threaded'
540
- )
541
- ) );
542
- }
543
- add_action( 'bp_actions', 'bp_activity_action_my_groups_feed' );
544
-
545
- /**
546
- * Load a user's @mentions feed.
547
- *
548
- * @since 1.2.0
549
- *
550
- * @return bool False on failure.
551
- */
552
- function bp_activity_action_mentions_feed() {
553
- if ( ! bp_activity_do_mentions() ) {
554
- return false;
555
- }
556
-
557
- if ( !bp_is_user_activity() || ! bp_is_current_action( 'mentions' ) || ! bp_is_action_variable( 'feed', 0 ) ) {
558
- return false;
559
- }
560
-
561
- // Setup the feed.
562
- buddypress()->activity->feed = new BP_Activity_Feed( array(
563
- 'id' => 'mentions',
564
-
565
- /* translators: User mentions activity RSS title - "[Site Name] | [User Display Name] | Mentions" */
566
- 'title' => sprintf( __( '%1$s | %2$s | Mentions', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
567
-
568
- 'link' => bp_displayed_user_domain() . bp_get_activity_slug() . '/mentions/',
569
- 'description' => sprintf( __( "Activity feed mentioning %s.", 'buddypress' ), bp_get_displayed_user_fullname() ),
570
- 'activity_args' => array(
571
- 'search_terms' => '@' . bp_core_get_username( bp_displayed_user_id() )
572
- )
573
- ) );
574
- }
575
- add_action( 'bp_actions', 'bp_activity_action_mentions_feed' );
576
-
577
- /**
578
- * Load a user's favorites feed.
579
- *
580
- * @since 1.2.0
581
- *
582
- * @return bool False on failure.
583
- */
584
- function bp_activity_action_favorites_feed() {
585
- if ( ! bp_is_user_activity() || ! bp_is_current_action( 'favorites' ) || ! bp_is_action_variable( 'feed', 0 ) ) {
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
-
597
- /* translators: User activity favorites RSS title - "[Site Name] | [User Display Name] | Favorites" */
598
- 'title' => sprintf( __( '%1$s | %2$s | Favorites', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
599
-
600
- 'link' => bp_displayed_user_domain() . bp_get_activity_slug() . '/favorites/',
601
- 'description' => sprintf( __( "Activity feed of %s's favorites.", 'buddypress' ), bp_get_displayed_user_fullname() ),
602
- 'activity_args' => 'include=' . $fav_ids
603
- ) );
604
- }
605
- add_action( 'bp_actions', 'bp_activity_action_favorites_feed' );
606
-
607
- /**
608
- * Loads Akismet filtering for activity.
609
- *
610
- * @since 1.6.0
611
- * @since 2.3.0 We only support Akismet 3+.
612
- */
613
- function bp_activity_setup_akismet() {
614
- $bp = buddypress();
615
-
616
- // Bail if Akismet is not active.
617
- if ( ! defined( 'AKISMET_VERSION' ) ) {
618
- return;
619
- }
620
-
621
- // Bail if older version of Akismet.
622
- if ( ! class_exists( 'Akismet' ) ) {
623
- return;
624
- }
625
-
626
- // Bail if no Akismet key is set.
627
- if ( ! bp_get_option( 'wordpress_api_key' ) && ! defined( 'WPCOM_API_KEY' ) ) {
628
- return;
629
- }
630
-
631
- /**
632
- * Filters if BuddyPress Activity Akismet support has been disabled by another plugin.
633
- *
634
- * @since 1.6.0
635
- *
636
- * @param bool $value Return value of bp_is_akismet_active boolean function.
637
- */
638
- if ( ! apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) ) {
639
- return;
640
- }
641
-
642
- // Instantiate Akismet for BuddyPress.
643
- $bp->activity->akismet = new BP_Akismet();
644
- }
645
-
646
- /**
647
- * AJAX endpoint for Suggestions API lookups.
648
- *
649
- * @since 2.1.0
650
- */
651
- function bp_ajax_get_suggestions() {
652
- if ( ! bp_is_user_active() || empty( $_GET['term'] ) || empty( $_GET['type'] ) ) {
653
- wp_send_json_error( 'missing_parameter' );
654
- exit;
655
- }
656
-
657
- $args = array(
658
- 'term' => sanitize_text_field( $_GET['term'] ),
659
- 'type' => sanitize_text_field( $_GET['type'] ),
660
- );
661
-
662
- // Support per-Group suggestions.
663
- if ( ! empty( $_GET['group-id'] ) ) {
664
- $args['group_id'] = absint( $_GET['group-id'] );
665
- }
666
-
667
- $results = bp_core_get_suggestions( $args );
668
-
669
- if ( is_wp_error( $results ) ) {
670
- wp_send_json_error( $results->get_error_message() );
671
- exit;
672
- }
673
-
674
- wp_send_json_success( $results );
675
- }
676
- add_action( 'wp_ajax_bp_get_suggestions', 'bp_ajax_get_suggestions' );
677
-
678
- /**
679
- * Detect a change in post type status, and initiate an activity update if necessary.
680
- *
681
- * @since 2.2.0
682
- *
683
- * @todo Support untrashing better.
684
- *
685
- * @param string $new_status New status for the post.
686
- * @param string $old_status Old status for the post.
687
- * @param object $post Post data.
688
- */
689
- function bp_activity_catch_transition_post_type_status( $new_status, $old_status, $post ) {
690
- if ( ! post_type_supports( $post->post_type, 'buddypress-activity' ) ) {
691
- return;
692
- }
693
-
694
- // This is an edit.
695
- if ( $new_status === $old_status ) {
696
- // An edit of an existing post should update the existing activity item.
697
- if ( $new_status == 'publish' ) {
698
- $edit = bp_activity_post_type_update( $post );
699
-
700
- // Post was never recorded into activity stream, so record it now!
701
- if ( null === $edit ) {
702
- bp_activity_post_type_publish( $post->ID, $post );
703
- }
704
-
705
- // Allow plugins to eventually deal with other post statuses.
706
- } else {
707
- /**
708
- * Fires when editing the post and the new status is not 'publish'.
709
- *
710
- * This is a variable filter that is dependent on the post type
711
- * being untrashed.
712
- *
713
- * @since 2.5.0
714
- *
715
- * @param WP_Post $post Post data.
716
- * @param string $new_status New status for the post.
717
- * @param string $old_status Old status for the post.
718
- */
719
- do_action( 'bp_activity_post_type_edit_' . $post->post_type, $post, $new_status, $old_status );
720
- }
721
-
722
- return;
723
- }
724
-
725
- // Publishing a previously unpublished post.
726
- if ( 'publish' === $new_status ) {
727
- // Untrashing the post type - nothing here yet.
728
- if ( 'trash' == $old_status ) {
729
-
730
- /**
731
- * Fires if untrashing post in a post type.
732
- *
733
- * This is a variable filter that is dependent on the post type
734
- * being untrashed.
735
- *
736
- * @since 2.2.0
737
- *
738
- * @param WP_Post $post Post data.
739
- */
740
- do_action( 'bp_activity_post_type_untrash_' . $post->post_type, $post );
741
- } else {
742
- // Record the post.
743
- bp_activity_post_type_publish( $post->ID, $post );
744
- }
745
-
746
- // Unpublishing a previously published post.
747
- } elseif ( 'publish' === $old_status ) {
748
- // Some form of pending status - only remove the activity entry.
749
- bp_activity_post_type_unpublish( $post->ID, $post );
750
-
751
- // For any other cases, allow plugins to eventually deal with it.
752
- } else {
753
- /**
754
- * Fires when the old and the new post status are not 'publish'.
755
- *
756
- * This is a variable filter that is dependent on the post type
757
- * being untrashed.
758
- *
759
- * @since 2.5.0
760
- *
761
- * @param WP_Post $post Post data.
762
- * @param string $new_status New status for the post.
763
- * @param string $old_status Old status for the post.
764
- */
765
- do_action( 'bp_activity_post_type_transition_status_' . $post->post_type, $post, $new_status, $old_status );
766
- }
767
- }
768
- add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 );
769
-
770
- /**
771
- * When a post type comment status transition occurs, update the relevant activity's status.
772
- *
773
- * @since 2.5.0
774
- *
775
- * @param string $new_status New comment status.
776
- * @param string $old_status Previous comment status.
777
- * @param WP_Comment $comment Comment data.
778
- */
779
- function bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment ) {
780
- $post_type = get_post_type( $comment->comment_post_ID );
781
- if ( ! $post_type ) {
782
- return;
783
- }
784
-
785
- // Get the post type tracking args.
786
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
787
-
788
- // Bail if the activity type does not exist
789
- if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
790
- return false;
791
-
792
- // Set the $activity_comment_object
793
- } else {
794
- $activity_comment_object = $activity_post_object->comments_tracking;
795
- }
796
-
797
- // Init an empty activity ID
798
- $activity_id = 0;
799
-
800
- /**
801
- * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
802
- *
803
- * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
804
- * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
805
- * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
806
- * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
807
- * Otherwise, record the comment into the activity stream.
808
- */
809
-
810
- // This clause handles delete/hold.
811
- if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
812
- return bp_activity_post_type_remove_comment( $comment->comment_ID, $activity_post_object );
813
-
814
- // These clauses handle trash, spam, and un-spams.
815
- } elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
816
- $action = 'spam_activity';
817
- } elseif ( 'approved' == $new_status ) {
818
- $action = 'ham_activity';
819
- }
820
-
821
- // Get the activity
822
- if ( bp_disable_blogforum_comments() ) {
823
- $activity_id = bp_activity_get_activity_id( array(
824
- 'component' => $activity_comment_object->component_id,
825
- 'item_id' => get_current_blog_id(),
826
- 'secondary_item_id' => $comment->comment_ID,
827
- 'type' => $activity_comment_object->action_id,
828
- ) );
829
- } else {
830
- $activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
831
- }
832
-
833
- /**
834
- * Leave a chance to plugins to manage activity comments differently.
835
- *
836
- * @since 2.5.0
837
- *
838
- * @param bool $value True to override BuddyPress management.
839
- * @param string $post_type The post type name.
840
- * @param int $activity_id The post type activity (0 if not found).
841
- * @param string $new_status The new status of the post type comment.
842
- * @param string $old_status The old status of the post type comment.
843
- * @param WP_Comment $comment Comment data.
844
- */
845
- if ( true === apply_filters( 'bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment ) ) {
846
- return false;
847
- }
848
-
849
- // Check activity item exists
850
- if ( empty( $activity_id ) ) {
851
- // If no activity exists, but the comment has been approved, record it into the activity table.
852
- if ( 'approved' == $new_status ) {
853
- return bp_activity_post_type_comment( $comment->comment_ID, true, $activity_post_object );
854
- }
855
-
856
- return;
857
- }
858
-
859
- // Create an activity object
860
- $activity = new BP_Activity_Activity( $activity_id );
861
- if ( empty( $activity->component ) ) {
862
- return;
863
- }
864
-
865
- // Spam/ham the activity if it's not already in that state
866
- if ( 'spam_activity' === $action && ! $activity->is_spam ) {
867
- bp_activity_mark_as_spam( $activity );
868
- } elseif ( 'ham_activity' == $action) {
869
- bp_activity_mark_as_ham( $activity );
870
- }
871
-
872
- // Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
873
- $post_type_comment_action = $activity_comment_object->action_id;
874
- $comment_akismet_history = create_function( '$t', '$t[] = $post_type_comment_action; return $t;' );
875
- add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
876
-
877
- // Make sure the activity change won't edit the comment if sync is on
878
- remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
879
-
880
- // Save the updated activity
881
- $activity->save();
882
-
883
- // Restore the action
884
- add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
885
-
886
- // Remove the "new_blog_comment" activity type whitelist so we don't break anything
887
- remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
888
- }
889
- add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-admin.php CHANGED
@@ -16,10 +16,6 @@ defined( 'ABSPATH' ) || exit;
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
- if ( ! buddypress()->do_autoload ) {
20
- require dirname( __FILE__ ) . '/classes/class-bp-activity-list-table.php';
21
- }
22
-
23
  // Per_page screen option. Has to be hooked in extremely early.
24
  if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-activity' == $_REQUEST['page'] )
25
  add_filter( 'set-screen-option', 'bp_activity_admin_screen_options', 10, 3 );
@@ -98,7 +94,7 @@ function bp_activity_admin_reply() {
98
 
99
  // @todo: Check if user is allowed to create new activity items
100
  // if ( ! current_user_can( 'bp_new_activity' ) )
101
- if ( ! current_user_can( 'bp_moderate' ) )
102
  die( '-1' );
103
 
104
  // Add new activity comment.
@@ -145,7 +141,7 @@ add_action( 'wp_ajax_bp-activity-admin-reply', 'bp_activity_admin_reply' );
145
  * @param string $value Will always be false unless another plugin filters it first.
146
  * @param string $option Screen option name.
147
  * @param string $new_value Screen option form value.
148
- * @return string Option value. False to abandon update.
149
  */
150
  function bp_activity_admin_screen_options( $value, $option, $new_value ) {
151
  if ( 'toplevel_page_bp_activity_per_page' != $option && 'toplevel_page_bp_activity_network_per_page' != $option )
@@ -169,8 +165,9 @@ function bp_activity_admin_screen_options( $value, $option, $new_value ) {
169
  * @return array Hidden Meta Boxes.
170
  */
171
  function bp_activity_admin_edit_hidden_metaboxes( $hidden, $screen ) {
172
- if ( empty( $screen->id ) || 'toplevel_page_bp-activity' != $screen->id && 'toplevel_page_bp-activity_network' != $screen->id )
173
  return $hidden;
 
174
 
175
  // Hide the primary link meta box by default.
176
  $hidden = array_merge( (array) $hidden, array( 'bp_activity_itemids', 'bp_activity_link', 'bp_activity_type', 'bp_activity_userid', ) );
@@ -235,7 +232,7 @@ function bp_activity_admin_load() {
235
  'title' => __( 'Item, Link, Type', 'buddypress' ),
236
  'content' =>
237
  '<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>' .
238
- '<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>' .
239
  '<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>' .
240
  '<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>'
241
  ) );
@@ -299,12 +296,11 @@ function bp_activity_admin_load() {
299
  );
300
 
301
  // Add accessible hidden heading and text for Activity screen pagination.
302
- if ( bp_get_major_wp_version() >= 4.4 ) {
303
- get_current_screen()->set_screen_reader_content( array(
304
- /* translators: accessibility text */
305
- 'heading_pagination' => __( 'Activity list navigation', 'buddypress' ),
306
- ) );
307
- }
308
  }
309
 
310
  // Enqueue CSS and JavaScript.
@@ -393,8 +389,8 @@ function bp_activity_admin_load() {
393
  * Remove moderation and blacklist checks in case we want to ham an activity
394
  * which contains one of these listed keys.
395
  */
396
- remove_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2, 1 );
397
- remove_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2, 1 );
398
 
399
  bp_activity_mark_as_ham( $activity );
400
  $result = $activity->save();
@@ -803,7 +799,7 @@ function bp_activity_admin_edit_metabox_link( $item ) {
803
  _e( 'Link', 'buddypress' );
804
  ?></label>
805
  <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" />
806
- <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>
807
 
808
  <?php
809
  }
@@ -1043,9 +1039,9 @@ function bp_activity_admin_index() {
1043
 
1044
  <h3 id="bp-replyhead"><?php _e( 'Reply to Activity', 'buddypress' ); ?></h3>
1045
  <label for="bp-activities" class="screen-reader-text"><?php
1046
- /* translators: accessibility text */
1047
- _e( 'Reply', 'buddypress' );
1048
- ?></label>
1049
  <?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, ) ); ?>
1050
 
1051
  <p id="bp-replysubmit" class="submit">
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 );
94
 
95
  // @todo: Check if user is allowed to create new activity items
96
  // if ( ! current_user_can( 'bp_new_activity' ) )
97
+ if ( ! bp_current_user_can( 'bp_moderate' ) )
98
  die( '-1' );
99
 
100
  // Add new activity comment.
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|int Option value. False to abandon update.
145
  */
146
  function bp_activity_admin_screen_options( $value, $option, $new_value ) {
147
  if ( 'toplevel_page_bp_activity_per_page' != $option && 'toplevel_page_bp_activity_network_per_page' != $option )
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', ) );
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 (blog posts and comments) 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
  ) );
296
  );
297
 
298
  // Add accessible hidden heading and text for Activity screen pagination.
299
+ get_current_screen()->set_screen_reader_content( array(
300
+ /* translators: accessibility text */
301
+ 'heading_pagination' => __( 'Activity list navigation', 'buddypress' ),
302
+ ) );
303
+
 
304
  }
305
 
306
  // Enqueue CSS and JavaScript.
389
  * Remove moderation and blacklist checks in case we want to ham an activity
390
  * which contains one of these listed keys.
391
  */
392
+ remove_action( 'bp_activity_before_save', 'bp_activity_check_moderation_keys', 2 );
393
+ remove_action( 'bp_activity_before_save', 'bp_activity_check_blacklist_keys', 2 );
394
 
395
  bp_activity_mark_as_ham( $activity );
396
  $result = $activity->save();
799
  _e( 'Link', 'buddypress' );
800
  ?></label>
801
  <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" />
802
+ <p id="bp-activities-link-description"><?php _e( 'Activity generated by posts and comments uses the link field for a permalink back to the content item.', 'buddypress' ); ?></p>
803
 
804
  <?php
805
  }
1039
 
1040
  <h3 id="bp-replyhead"><?php _e( 'Reply to Activity', 'buddypress' ); ?></h3>
1041
  <label for="bp-activities" class="screen-reader-text"><?php
1042
+ /* translators: accessibility text */
1043
+ _e( 'Reply', 'buddypress' );
1044
+ ?></label>
1045
  <?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, ) ); ?>
1046
 
1047
  <p id="bp-replysubmit" class="submit">
bp-activity/bp-activity-akismet.php CHANGED
@@ -10,9 +10,28 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-akismet.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
 
16
 
17
  /**
18
  * Delete old spam activity meta data.
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.
bp-activity/bp-activity-cache.php CHANGED
@@ -63,3 +63,24 @@ 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' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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' );
bp-activity/bp-activity-classes.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Classes.
4
- *
5
- * @package BuddyPress
6
- * @subpackage ActivityClasses
7
- * @since 1.0.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- require dirname( __FILE__ ) . '/classes/class-bp-activity-activity.php';
14
- require dirname( __FILE__ ) . '/classes/class-bp-activity-feed.php';
15
- require dirname( __FILE__ ) . '/classes/class-bp-activity-query.php';
16
-
17
- // Embeds - only applicable for WP 4.5+
18
- if ( version_compare( $GLOBALS['wp_version'], '4.5', '>=' ) && bp_is_active( 'activity', 'embeds' ) ) {
19
- require dirname( __FILE__ ) . '/classes/class-bp-activity-oembed-extension.php';
20
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-embeds.php CHANGED
@@ -19,9 +19,7 @@ defined( 'ABSPATH' ) || exit;
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
 
@@ -64,9 +62,9 @@ function bp_activity_embed_add_inline_styles() {
64
  $min = bp_core_get_minified_asset_suffix();
65
 
66
  if ( is_rtl() ) {
67
- $css = bp_locate_template_asset( "assets/embeds/activity-rtl{$min}.css" );
68
  } else {
69
- $css = bp_locate_template_asset( "assets/embeds/activity{$min}.css" );
70
  }
71
 
72
  // Bail if file wasn't found.
@@ -123,7 +121,7 @@ function bp_activity_embed_has_activity( $activity_id = 0 ) {
123
  * @since 2.6.0
124
  */
125
  function bp_activity_embed_excerpt( $content = '' ) {
126
- echo bp_activity_get_embed_excerpt( $content = '' );
127
  }
128
 
129
  /**
19
  * @since 2.6.0
20
  */
21
  function bp_activity_setup_oembed() {
22
+ buddypress()->activity->oembed = new BP_Activity_oEmbed_Extension;
 
 
23
  }
24
  add_action( 'bp_loaded', 'bp_activity_setup_oembed' );
25
 
62
  $min = bp_core_get_minified_asset_suffix();
63
 
64
  if ( is_rtl() ) {
65
+ $css = bp_locate_template_asset( "css/embeds-activity-rtl{$min}.css" );
66
  } else {
67
+ $css = bp_locate_template_asset( "css/embeds-activity{$min}.css" );
68
  }
69
 
70
  // Bail if file wasn't found.
121
  * @since 2.6.0
122
  */
123
  function bp_activity_embed_excerpt( $content = '' ) {
124
+ echo bp_activity_get_embed_excerpt( $content );
125
  }
126
 
127
  /**
bp-activity/bp-activity-filters.php CHANGED
@@ -96,8 +96,6 @@ add_filter( 'bp_get_activity_latest_update_excerpt', 'bp_activity_make_nofollow_
96
  add_filter( 'bp_get_activity_feed_item_description', 'bp_activity_make_nofollow_filter' );
97
 
98
  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
 
@@ -207,13 +205,17 @@ 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
- $activity_allowedtags['b'] = array();
215
- $activity_allowedtags['code'] = array();
216
- $activity_allowedtags['i'] = array();
 
 
 
 
217
  $activity_allowedtags['img'] = array();
218
  $activity_allowedtags['img']['src'] = array();
219
  $activity_allowedtags['img']['alt'] = array();
@@ -221,10 +223,14 @@ function bp_activity_filter_kses( $content ) {
221
  $activity_allowedtags['img']['height'] = array();
222
  $activity_allowedtags['img']['class'] = array();
223
  $activity_allowedtags['img']['id'] = array();
224
- $activity_allowedtags['img']['title'] = array();
225
- $activity_allowedtags['span'] = array();
226
- $activity_allowedtags['span']['class'] = array();
227
 
 
 
 
 
 
 
 
228
 
229
  /**
230
  * Filters the allowed HTML tags for BuddyPress Activity content.
@@ -278,7 +284,7 @@ function bp_activity_at_name_filter( $content, $activity_id = 0 ) {
278
 
279
  // Linkify the mentions with the username.
280
  foreach ( (array) $usernames as $user_id => $username ) {
281
- $content = preg_replace( '/(@' . $username . '\b)/', "<a href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $content );
282
  }
283
 
284
  // Put everything back.
@@ -319,7 +325,7 @@ function bp_activity_at_name_filter_updates( $activity ) {
319
  if ( ! empty( $usernames ) ) {
320
  // Replace @mention text with userlinks.
321
  foreach( (array) $usernames as $user_id => $username ) {
322
- $activity->content = preg_replace( '/(@' . $username . '\b)/', "<a href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $activity->content );
323
  }
324
 
325
  // Add our hook to send @mention emails after the activity item is saved.
@@ -446,14 +452,7 @@ function bp_activity_truncate_entry( $text, $args = array() ) {
446
  */
447
  $append_text = apply_filters( 'bp_activity_excerpt_append_text', __( '[Read more]', 'buddypress' ) );
448
 
449
- /**
450
- * Filters the excerpt length for the activity excerpt.
451
- *
452
- * @since 1.5.0
453
- *
454
- * @param int $value Number indicating how many words to trim the excerpt down to.
455
- */
456
- $excerpt_length = apply_filters( 'bp_activity_excerpt_length', 358 );
457
 
458
  $args = wp_parse_args( $args, array( 'ending' => __( '&hellip;', 'buddypress' ) ) );
459
 
@@ -599,7 +598,7 @@ function bp_activity_heartbeat_last_recorded( $response = array(), $data = array
599
  ob_end_clean();
600
 
601
  // Remove the temporary filter.
602
- remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 );
603
 
604
  if ( ! empty( $newest_activities['last_recorded'] ) ) {
605
  $response['bp_activity_newest_activities'] = $newest_activities;
96
  add_filter( 'bp_get_activity_feed_item_description', 'bp_activity_make_nofollow_filter' );
97
 
98
  add_filter( 'pre_comment_content', 'bp_activity_at_name_filter' );
 
 
99
  add_filter( 'the_content', 'bp_activity_at_name_filter' );
100
  add_filter( 'bp_activity_get_embed_excerpt', 'bp_activity_at_name_filter' );
101
 
205
  global $allowedtags;
206
 
207
  $activity_allowedtags = $allowedtags;
208
+ $activity_allowedtags['a']['aria-label'] = array();
209
+ $activity_allowedtags['a']['class'] = array();
210
+ $activity_allowedtags['a']['data-bp-tooltip'] = 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();
223
  $activity_allowedtags['img']['height'] = array();
224
  $activity_allowedtags['img']['class'] = array();
225
  $activity_allowedtags['img']['id'] = array();
 
 
 
226
 
227
+ $activity_allowedtags['span'] = array();
228
+ $activity_allowedtags['span']['class'] = array();
229
+ $activity_allowedtags['span']['data-livestamp'] = array();
230
+
231
+ $activity_allowedtags['ul'] = array();
232
+ $activity_allowedtags['ol'] = array();
233
+ $activity_allowedtags['li'] = array();
234
 
235
  /**
236
  * Filters the allowed HTML tags for BuddyPress Activity content.
284
 
285
  // Linkify the mentions with the username.
286
  foreach ( (array) $usernames as $user_id => $username ) {
287
+ $content = preg_replace( '/(@' . $username . '\b)/', "<a class='bp-suggestions-mention' href='" . bp_core_get_user_domain( $user_id ) . "' rel='nofollow'>@$username</a>", $content );
288
  }
289
 
290
  // Put everything back.
325
  if ( ! empty( $usernames ) ) {
326
  // Replace @mention text with userlinks.
327
  foreach( (array) $usernames as $user_id => $username ) {
328
+ $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 );
329
  }
330
 
331
  // Add our hook to send @mention emails after the activity item is saved.
452
  */
453
  $append_text = apply_filters( 'bp_activity_excerpt_append_text', __( '[Read more]', 'buddypress' ) );
454
 
455
+ $excerpt_length = bp_activity_get_excerpt_length();
 
 
 
 
 
 
 
456
 
457
  $args = wp_parse_args( $args, array( 'ending' => __( '&hellip;', 'buddypress' ) ) );
458
 
598
  ob_end_clean();
599
 
600
  // Remove the temporary filter.
601
+ remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10 );
602
 
603
  if ( ! empty( $newest_activities['last_recorded'] ) ) {
604
  $response['bp_activity_newest_activities'] = $newest_activities;
bp-activity/bp-activity-functions.php CHANGED
@@ -406,7 +406,7 @@ function bp_activity_set_action( $component_id, $type, $description, $format_cal
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 frontend 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.
@@ -748,11 +748,14 @@ function bp_activity_post_type_get_tracking_arg( $activity_type, $arg = '' ) {
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
  }
@@ -839,6 +842,63 @@ function bp_activity_get_types() {
839
  return apply_filters( 'bp_activity_get_types', $actions );
840
  }
841
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842
  /** Favorites ****************************************************************/
843
 
844
  /**
@@ -880,11 +940,6 @@ function bp_activity_get_user_favorites( $user_id = 0 ) {
880
  */
881
  function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
882
 
883
- // Favorite activity stream items are for logged in users only.
884
- if ( ! is_user_logged_in() ) {
885
- return false;
886
- }
887
-
888
  // Fallback to logged in user if no user_id is passed.
889
  if ( empty( $user_id ) ) {
890
  $user_id = bp_loggedin_user_id();
@@ -954,11 +1009,6 @@ function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
954
  */
955
  function bp_activity_remove_user_favorite( $activity_id, $user_id = 0 ) {
956
 
957
- // Favorite activity stream items are for logged in users only.
958
- if ( ! is_user_logged_in() ) {
959
- return false;
960
- }
961
-
962
  // Fallback to logged in user if no user_id is passed.
963
  if ( empty( $user_id ) ) {
964
  $user_id = bp_loggedin_user_id();
@@ -1203,9 +1253,7 @@ function bp_activity_add_meta( $activity_id, $meta_key, $meta_value, $unique = f
1203
  * @return bool
1204
  */
1205
  function bp_activity_remove_all_user_data( $user_id = 0 ) {
1206
-
1207
- // Do not delete user data unless a logged in user says so.
1208
- if ( empty( $user_id ) || ! is_user_logged_in() ) {
1209
  return false;
1210
  }
1211
 
@@ -1370,6 +1418,21 @@ function bp_activity_ham_all_user_data( $user_id = 0 ) {
1370
  }
1371
  add_action( 'bp_make_ham_user', 'bp_activity_ham_all_user_data' );
1372
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1373
  /**
1374
  * Register the activity stream actions for updates.
1375
  *
@@ -1445,7 +1508,7 @@ function bp_activity_generate_action_string( $activity ) {
1445
  $action = apply_filters( 'bp_activity_generate_action_string', $activity->action, $activity );
1446
 
1447
  // Remove the filter for future activity items.
1448
- remove_filter( 'bp_activity_generate_action_string', $actions->{$activity->component}->{$activity->type}['format_callback'], 10, 2 );
1449
 
1450
  return $action;
1451
  }
@@ -1658,61 +1721,33 @@ function bp_activity_get( $args = '' ) {
1658
  * 'user_id' => false, // User ID to filter on.
1659
  * 'object' => false, // Object to filter on e.g. groups, profile, status, friends.
1660
  * 'action' => false, // Action to filter on e.g. activity_update, profile_updated.
1661
- * 'primary_id' => false, // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
1662
  * 'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
1663
  * );
1664
  */
1665
  'filter' => array()
1666
- ) );
1667
-
1668
- // Attempt to return a cached copy of the first page of sitewide activity.
1669
- if ( ( 1 === (int) $r['page'] ) && empty( $r['max'] ) && ( 'all' === $r['fields'] ) && empty( $r['search_terms'] ) && empty( $r['meta_query'] ) && empty( $r['date_query'] ) && empty( $r['filter_query'] ) && empty( $r['filter'] ) && empty( $r['scope'] )&& empty( $r['exclude'] ) && empty( $r['in'] ) && ( 'DESC' === $r['sort'] ) && empty( $r['exclude'] ) && ( 'ham_only' === $r['spam'] ) ) {
1670
-
1671
- $activity = wp_cache_get( 'bp_activity_sitewide_front', 'bp' );
1672
- if ( false === $activity ) {
1673
-
1674
- $activity = BP_Activity_Activity::get( array(
1675
- 'page' => $r['page'],
1676
- 'per_page' => $r['per_page'],
1677
- 'max' => $r['max'],
1678
- 'fields' => $r['fields'],
1679
- 'sort' => $r['sort'],
1680
- 'search_terms' => $r['search_terms'],
1681
- 'meta_query' => $r['meta_query'],
1682
- 'date_query' => $r['date_query'],
1683
- 'filter_query' => $r['filter_query'],
1684
- 'filter' => $r['filter'],
1685
- 'scope' => $r['scope'],
1686
- 'display_comments' => $r['display_comments'],
1687
- 'show_hidden' => $r['show_hidden'],
1688
- 'spam' => $r['spam'],
1689
- 'update_meta_cache' => $r['update_meta_cache'],
1690
- 'count_total' => $r['count_total'],
1691
- ) );
1692
-
1693
- wp_cache_set( 'bp_activity_sitewide_front', $activity, 'bp' );
1694
- }
1695
 
1696
- } else {
1697
- $activity = BP_Activity_Activity::get( array(
1698
- 'page' => $r['page'],
1699
- 'per_page' => $r['per_page'],
1700
- 'max' => $r['max'],
1701
- 'sort' => $r['sort'],
1702
- 'search_terms' => $r['search_terms'],
1703
- 'meta_query' => $r['meta_query'],
1704
- 'date_query' => $r['date_query'],
1705
- 'filter_query' => $r['filter_query'],
1706
- 'filter' => $r['filter'],
1707
- 'scope' => $r['scope'],
1708
- 'display_comments' => $r['display_comments'],
1709
- 'show_hidden' => $r['show_hidden'],
1710
- 'exclude' => $r['exclude'],
1711
- 'in' => $r['in'],
1712
- 'spam' => $r['spam'],
1713
- 'count_total' => $r['count_total'],
1714
- ) );
1715
- }
1716
 
1717
  /**
1718
  * Filters the requested activity item(s).
@@ -1752,7 +1787,7 @@ function bp_activity_get_specific( $args = '' ) {
1752
  'sort' => 'DESC', // Sort ASC or DESC
1753
  'spam' => 'ham_only', // Retrieve items marked as spam.
1754
  'update_meta_cache' => true,
1755
- ) );
1756
 
1757
  $get_args = array(
1758
  'display_comments' => $r['display_comments'],
@@ -1816,7 +1851,7 @@ function bp_activity_get_specific( $args = '' ) {
1816
  * @type bool $is_spam Should the item be marked as spam? Default: false.
1817
  * @type string $error_type Optional. Error type. Either 'bool' or 'wp_error'. Default: 'bool'.
1818
  * }
1819
- * @return int|bool The ID of the activity on success. False on error.
1820
  */
1821
  function bp_activity_add( $args = '' ) {
1822
 
@@ -1898,10 +1933,13 @@ function bp_activity_add( $args = '' ) {
1898
  * @since 1.2.0
1899
  *
1900
  * @param array|string $args {
1901
- * @type string $content The content of the activity update.
1902
- * @type int $user_id Optional. Defaults to the logged-in user.
 
 
1903
  * }
1904
- * @return int $activity_id The activity id.
 
1905
  */
1906
  function bp_activity_post_update( $args = '' ) {
1907
 
@@ -1994,7 +2032,7 @@ function bp_activity_post_update( $args = '' ) {
1994
  * @param int $post_id ID of the new post.
1995
  * @param WP_Post|null $post Post object.
1996
  * @param int $user_id ID of the post author.
1997
- * @return int|bool The ID of the activity on success. False on error.
1998
  */
1999
  function bp_activity_post_type_publish( $post_id = 0, $post = null, $user_id = 0 ) {
2000
 
@@ -2129,7 +2167,7 @@ function bp_activity_post_type_publish( $post_id = 0, $post = null, $user_id = 0
2129
  * @since 2.2.0
2130
  *
2131
  * @param WP_Post|null $post Post item.
2132
- * @return bool True on success, false on failure.
2133
  */
2134
  function bp_activity_post_type_update( $post = null ) {
2135
 
@@ -2251,7 +2289,7 @@ function bp_activity_post_type_unpublish( $post_id = 0, $post = null ) {
2251
  * @param int $comment_id ID of the comment.
2252
  * @param bool $is_approved Whether the comment is approved or not.
2253
  * @param object|null $activity_post_object The post type tracking args object.
2254
- * @return int|bool The ID of the activity on success. False on error.
2255
  */
2256
  function bp_activity_post_type_comment( $comment_id = 0, $is_approved = true, $activity_post_object = null ) {
2257
  // Get the users comment
@@ -2525,7 +2563,7 @@ add_action( 'delete_comment', 'bp_activity_post_type_remove_comment', 10, 1 );
2525
  * Defaults to false.
2526
  * @type string $error_type Optional. Error type. Either 'bool' or 'wp_error'. Default: 'bool'.
2527
  * }
2528
- * @return int|bool The ID of the comment on success, otherwise false.
2529
  */
2530
  function bp_activity_new_comment( $args = '' ) {
2531
  $bp = buddypress();
@@ -2597,10 +2635,12 @@ function bp_activity_new_comment( $args = '' ) {
2597
  * Filters the content of a new comment.
2598
  *
2599
  * @since 1.2.0
 
2600
  *
2601
- * @param string $r Content for the newly posted comment.
 
2602
  */
2603
- $comment_content = apply_filters( 'bp_activity_comment_content', $r['content'] );
2604
 
2605
  // Insert the activity comment.
2606
  $comment_id = bp_activity_add( array(
@@ -2640,9 +2680,9 @@ function bp_activity_new_comment( $args = '' ) {
2640
  *
2641
  * @since 1.2.0
2642
  *
2643
- * @param int $comment_id ID of the newly posted activity comment.
2644
- * @param array $r Array of parsed comment arguments.
2645
- * @param int $activity ID of the activity item being commented on.
2646
  */
2647
  do_action( 'bp_activity_comment_posted', $comment_id, $r, $activity );
2648
  } else {
@@ -2652,9 +2692,9 @@ function bp_activity_new_comment( $args = '' ) {
2652
  *
2653
  * @since 2.5.0
2654
  *
2655
- * @param int $comment_id ID of the newly posted activity comment.
2656
- * @param array $r Array of parsed comment arguments.
2657
- * @param int $activity ID of the activity item being commented on.
2658
  */
2659
  do_action( 'bp_activity_comment_posted_notification_skipped', $comment_id, $r, $activity );
2660
  }
@@ -2931,6 +2971,12 @@ function bp_activity_delete_comment( $activity_id, $comment_id ) {
2931
  return $deleted;
2932
  }
2933
 
 
 
 
 
 
 
2934
  // Delete any children of this comment.
2935
  bp_activity_delete_children( $activity_id, $comment_id );
2936
 
@@ -2971,6 +3017,11 @@ function bp_activity_delete_comment( $activity_id, $comment_id ) {
2971
  * @param int $comment_id The ID of the comment to be deleted.
2972
  */
2973
  function bp_activity_delete_children( $activity_id, $comment_id ) {
 
 
 
 
 
2974
 
2975
  // Get activity children to delete.
2976
  $children = BP_Activity_Activity::get_child_comments( $comment_id );
@@ -3030,7 +3081,7 @@ function bp_activity_get_permalink( $activity_id, $activity_obj = false ) {
3030
  $link = $activity_obj->primary_link;
3031
  } else {
3032
  if ( 'activity_comment' == $activity_obj->type ) {
3033
- $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->item_id . '/';
3034
  } else {
3035
  $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->id . '/';
3036
  }
@@ -3046,6 +3097,55 @@ function bp_activity_get_permalink( $activity_id, $activity_obj = false ) {
3046
  return apply_filters_ref_array( 'bp_activity_get_permalink', array( $link, &$activity_obj ) );
3047
  }
3048
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3049
  /**
3050
  * Hide a user's activity.
3051
  *
@@ -3137,6 +3237,24 @@ function bp_activity_thumbnail_content_images( $content, $link = false, $args =
3137
  return apply_filters( 'bp_activity_thumbnail_content_images', $content, $matches, $args );
3138
  }
3139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3140
  /**
3141
  * Create a rich summary of an activity item for the activity stream.
3142
  *
@@ -3207,7 +3325,7 @@ function bp_activity_create_summary( $content, $activity ) {
3207
  // Embeds must be subtracted from the paragraph count.
3208
  if ( ! empty( $media['has']['embeds'] ) ) {
3209
  $has_embeds = $media['has']['embeds'] > 0;
3210
- $para_count -= count( $media['has']['embeds'] );
3211
  }
3212
 
3213
  $extracted_media = array();
@@ -3346,7 +3464,7 @@ function bp_activity_mark_as_spam( &$activity, $source = 'by_a_person' ) {
3346
 
3347
  // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity.
3348
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
3349
- remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4, 1 );
3350
 
3351
  // Build data package for Akismet.
3352
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
@@ -3393,7 +3511,7 @@ function bp_activity_mark_as_ham( &$activity, $source = 'by_a_person' ) {
3393
 
3394
  // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity.
3395
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
3396
- remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4, 1 );
3397
 
3398
  // Build data package for Akismet.
3399
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
@@ -3417,6 +3535,211 @@ function bp_activity_mark_as_ham( &$activity, $source = 'by_a_person' ) {
3417
  do_action( 'bp_activity_mark_as_ham', $activity, $source );
3418
  }
3419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3420
 
3421
  /** Embeds *******************************************************************/
3422
 
@@ -3495,7 +3818,7 @@ add_action( 'bp_before_activity_comment', 'bp_activity_comment_embed' );
3495
  function bp_dtheme_embed_read_more( $activity ) {
3496
  buddypress()->activity->read_more_id = $activity->id;
3497
 
3498
- add_filter( 'embed_post_id', create_function( '', 'return buddypress()->activity->read_more_id;' ) );
3499
  add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 );
3500
  add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
3501
  }
@@ -3565,21 +3888,270 @@ function bp_embed_activity_save_cache( $cache, $cachekey, $id ) {
3565
  *
3566
  * @since 2.0.0
3567
  *
3568
- * directory.
3569
- * is the group activities.
3570
- *
3571
  * @return bool True if activity heartbeat is enabled, otherwise false.
3572
  */
3573
  function bp_activity_do_heartbeat() {
3574
  $retval = false;
3575
 
3576
- if ( ! bp_is_activity_heartbeat_active() ) {
3577
- return $retval;
3578
  }
3579
 
3580
- if ( bp_is_activity_directory() || bp_is_group_activity() ) {
3581
- $retval = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3582
  }
3583
 
3584
- return $retval;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3585
  }
 
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.
748
  function bp_activity_get_actions() {
749
  $bp = buddypress();
750
 
751
+ // Set the activity track global if not set yet.
752
+ if ( empty( $bp->activity->track ) ) {
753
+ $bp->activity->track = bp_activity_get_post_types_tracking_args();
754
+ }
755
 
756
  // Create the actions for the post types, if they haven't already been created.
757
+ if ( ! empty( $bp->activity->track ) ) {
758
+ foreach ( $bp->activity->track as $post_type ) {
759
  if ( isset( $bp->activity->actions->{$post_type->component_id}->{$post_type->action_id} ) ) {
760
  continue;
761
  }
842
  return apply_filters( 'bp_activity_get_types', $actions );
843
  }
844
 
845
+ /**
846
+ * Gets the current activity context.
847
+ *
848
+ * The "context" is the current view type, corresponding roughly to the
849
+ * current component. Use this context to determine which activity actions
850
+ * should be whitelisted for the filter dropdown.
851
+ *
852
+ * @since 2.8.0
853
+ *
854
+ * @return string Activity context. 'member', 'member_groups', 'group', 'activity'.
855
+ */
856
+ function bp_activity_get_current_context() {
857
+ // On member pages, default to 'member', unless this is a user's Groups activity.
858
+ if ( bp_is_user() ) {
859
+ if ( bp_is_active( 'groups' ) && bp_is_current_action( bp_get_groups_slug() ) ) {
860
+ $context = 'member_groups';
861
+ } else {
862
+ $context = 'member';
863
+ }
864
+
865
+ // On individual group pages, default to 'group'.
866
+ } elseif ( bp_is_active( 'groups' ) && bp_is_group() ) {
867
+ $context = 'group';
868
+
869
+ // 'activity' everywhere else.
870
+ } else {
871
+ $context = 'activity';
872
+ }
873
+
874
+ return $context;
875
+ }
876
+
877
+ /**
878
+ * Gets a flat list of activity actions compatible with a given context.
879
+ *
880
+ * @since 2.8.0
881
+ *
882
+ * @param string $context Optional. Name of the context. Defaults to the current context.
883
+ * @return array
884
+ */
885
+ function bp_activity_get_actions_for_context( $context = '' ) {
886
+ if ( ! $context ) {
887
+ $context = bp_activity_get_current_context();
888
+ }
889
+
890
+ $actions = array();
891
+ foreach ( bp_activity_get_actions() as $component_actions ) {
892
+ foreach ( $component_actions as $component_action ) {
893
+ if ( in_array( $context, (array) $component_action['context'], true ) ) {
894
+ $actions[] = $component_action;
895
+ }
896
+ }
897
+ }
898
+
899
+ return $actions;
900
+ }
901
+
902
  /** Favorites ****************************************************************/
903
 
904
  /**
940
  */
941
  function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
942
 
 
 
 
 
 
943
  // Fallback to logged in user if no user_id is passed.
944
  if ( empty( $user_id ) ) {
945
  $user_id = bp_loggedin_user_id();
1009
  */
1010
  function bp_activity_remove_user_favorite( $activity_id, $user_id = 0 ) {
1011
 
 
 
 
 
 
1012
  // Fallback to logged in user if no user_id is passed.
1013
  if ( empty( $user_id ) ) {
1014
  $user_id = bp_loggedin_user_id();
1253
  * @return bool
1254
  */
1255
  function bp_activity_remove_all_user_data( $user_id = 0 ) {
1256
+ if ( empty( $user_id ) ) {
 
 
1257
  return false;
1258
  }
1259
 
1418
  }
1419
  add_action( 'bp_make_ham_user', 'bp_activity_ham_all_user_data' );
1420
 
1421
+ /**
1422
+ * Allow core components and dependent plugins to register activity actions.
1423
+ *
1424
+ * @since 1.2.0
1425
+ */
1426
+ function bp_register_activity_actions() {
1427
+ /**
1428
+ * Fires on bp_init to allow core components and dependent plugins to register activity actions.
1429
+ *
1430
+ * @since 1.2.0
1431
+ */
1432
+ do_action( 'bp_register_activity_actions' );
1433
+ }
1434
+ add_action( 'bp_init', 'bp_register_activity_actions', 8 );
1435
+
1436
  /**
1437
  * Register the activity stream actions for updates.
1438
  *
1508
  $action = apply_filters( 'bp_activity_generate_action_string', $activity->action, $activity );
1509
 
1510
  // Remove the filter for future activity items.
1511
+ remove_filter( 'bp_activity_generate_action_string', $actions->{$activity->component}->{$activity->type}['format_callback'], 10 );
1512
 
1513
  return $action;
1514
  }
1721
  * 'user_id' => false, // User ID to filter on.
1722
  * 'object' => false, // Object to filter on e.g. groups, profile, status, friends.
1723
  * 'action' => false, // Action to filter on e.g. activity_update, profile_updated.
1724
+ * 'primary_id' => false, // Object ID to filter on e.g. a group_id or blog_id etc.
1725
  * 'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
1726
  * );
1727
  */
1728
  'filter' => array()
1729
+ ), 'activity_get' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1730
 
1731
+ $activity = BP_Activity_Activity::get( array(
1732
+ 'page' => $r['page'],
1733
+ 'per_page' => $r['per_page'],
1734
+ 'max' => $r['max'],
1735
+ 'sort' => $r['sort'],
1736
+ 'search_terms' => $r['search_terms'],
1737
+ 'meta_query' => $r['meta_query'],
1738
+ 'date_query' => $r['date_query'],
1739
+ 'filter_query' => $r['filter_query'],
1740
+ 'filter' => $r['filter'],
1741
+ 'scope' => $r['scope'],
1742
+ 'display_comments' => $r['display_comments'],
1743
+ 'show_hidden' => $r['show_hidden'],
1744
+ 'exclude' => $r['exclude'],
1745
+ 'in' => $r['in'],
1746
+ 'spam' => $r['spam'],
1747
+ 'update_meta_cache' => $r['update_meta_cache'],
1748
+ 'count_total' => $r['count_total'],
1749
+ 'fields' => $r['fields'],
1750
+ ) );
1751
 
1752
  /**
1753
  * Filters the requested activity item(s).
1787
  'sort' => 'DESC', // Sort ASC or DESC
1788
  'spam' => 'ham_only', // Retrieve items marked as spam.
1789
  'update_meta_cache' => true,
1790
+ ), 'activity_get_specific' );
1791
 
1792
  $get_args = array(
1793
  'display_comments' => $r['display_comments'],
1851
  * @type bool $is_spam Should the item be marked as spam? Default: false.
1852
  * @type string $error_type Optional. Error type. Either 'bool' or 'wp_error'. Default: 'bool'.
1853
  * }
1854
+ * @return WP_Error|bool|int The ID of the activity on success. False on error.
1855
  */
1856
  function bp_activity_add( $args = '' ) {
1857
 
1933
  * @since 1.2.0
1934
  *
1935
  * @param array|string $args {
1936
+ * @type string $content The content of the activity update.
1937
+ * @type int $user_id Optional. Defaults to the logged-in user.
1938
+ * @type string $error_type Optional. Error type to return. Either 'bool' or 'wp_error'. Defaults to
1939
+ * 'bool' for boolean. 'wp_error' will return a WP_Error object.
1940
  * }
1941
+ * @return int|bool|WP_Error $activity_id The activity id on success. On failure, either boolean false or WP_Error
1942
+ * object depending on the 'error_type' $args parameter.
1943
  */
1944
  function bp_activity_post_update( $args = '' ) {
1945
 
2032
  * @param int $post_id ID of the new post.
2033
  * @param WP_Post|null $post Post object.
2034
  * @param int $user_id ID of the post author.
2035
+ * @return null|WP_Error|bool|int The ID of the activity on success. False on error.
2036
  */
2037
  function bp_activity_post_type_publish( $post_id = 0, $post = null, $user_id = 0 ) {
2038
 
2167
  * @since 2.2.0
2168
  *
2169
  * @param WP_Post|null $post Post item.
2170
+ * @return null|WP_Error|bool True on success, false on failure.
2171
  */
2172
  function bp_activity_post_type_update( $post = null ) {
2173
 
2289
  * @param int $comment_id ID of the comment.
2290
  * @param bool $is_approved Whether the comment is approved or not.
2291
  * @param object|null $activity_post_object The post type tracking args object.
2292
+ * @return null|WP_Error|bool|int The ID of the activity on success. False on error.
2293
  */
2294
  function bp_activity_post_type_comment( $comment_id = 0, $is_approved = true, $activity_post_object = null ) {
2295
  // Get the users comment
2563
  * Defaults to false.
2564
  * @type string $error_type Optional. Error type. Either 'bool' or 'wp_error'. Default: 'bool'.
2565
  * }
2566
+ * @return WP_Error|bool|int The ID of the comment on success, otherwise false.
2567
  */
2568
  function bp_activity_new_comment( $args = '' ) {
2569
  $bp = buddypress();
2635
  * Filters the content of a new comment.
2636
  *
2637
  * @since 1.2.0
2638
+ * @since 3.0.0 Added $context parameter to disambiguate from bp_get_activity_comment_content().
2639
  *
2640
+ * @param string $r Content for the newly posted comment.
2641
+ * @param string $context This filter's context ("new").
2642
  */
2643
+ $comment_content = apply_filters( 'bp_activity_comment_content', $r['content'], 'new' );
2644
 
2645
  // Insert the activity comment.
2646
  $comment_id = bp_activity_add( array(
2680
  *
2681
  * @since 1.2.0
2682
  *
2683
+ * @param int $comment_id ID of the newly posted activity comment.
2684
+ * @param array $r Array of parsed comment arguments.
2685
+ * @param BP_Activity_Activity $activity Activity item being commented on.
2686
  */
2687
  do_action( 'bp_activity_comment_posted', $comment_id, $r, $activity );
2688
  } else {
2692
  *
2693
  * @since 2.5.0
2694
  *
2695
+ * @param int $comment_id ID of the newly posted activity comment.
2696
+ * @param array $r Array of parsed comment arguments.
2697
+ * @param BP_Activity_Activity $activity Activity item being commented on.
2698
  */
2699
  do_action( 'bp_activity_comment_posted_notification_skipped', $comment_id, $r, $activity );
2700
  }
2971
  return $deleted;
2972
  }
2973
 
2974
+ // Check if comment still exists.
2975
+ $comment = new BP_Activity_Activity( $comment_id );
2976
+ if ( empty( $comment->id ) ) {
2977
+ return false;
2978
+ }
2979
+
2980
  // Delete any children of this comment.
2981
  bp_activity_delete_children( $activity_id, $comment_id );
2982
 
3017
  * @param int $comment_id The ID of the comment to be deleted.
3018
  */
3019
  function bp_activity_delete_children( $activity_id, $comment_id ) {
3020
+ // Check if comment still exists.
3021
+ $comment = new BP_Activity_Activity( $comment_id );
3022
+ if ( empty( $comment->id ) ) {
3023
+ return;
3024
+ }
3025
 
3026
  // Get activity children to delete.
3027
  $children = BP_Activity_Activity::get_child_comments( $comment_id );
3081
  $link = $activity_obj->primary_link;
3082
  } else {
3083
  if ( 'activity_comment' == $activity_obj->type ) {
3084
+ $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->item_id . '/#acomment-' . $activity_obj->id;
3085
  } else {
3086
  $link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/p/' . $activity_obj->id . '/';
3087
  }
3097
  return apply_filters_ref_array( 'bp_activity_get_permalink', array( $link, &$activity_obj ) );
3098
  }
3099
 
3100
+ /**
3101
+ * Can a user see a particular activity item?
3102
+ *
3103
+ * @since 3.0.0
3104
+ *
3105
+ * @param BP_Activity_Activity $activity Activity object.
3106
+ * @param integer $user_id User ID.
3107
+ * @return boolean True on success, false on failure.
3108
+ */
3109
+ function bp_activity_user_can_read( $activity, $user_id = 0 ) {
3110
+ $retval = false;
3111
+
3112
+ // Fallback.
3113
+ if ( empty( $user_id ) ) {
3114
+ $user_id = bp_loggedin_user_id();
3115
+ }
3116
+
3117
+ // Admins and moderators can see everything.
3118
+ if ( bp_current_user_can( 'bp_moderate' ) ) {
3119
+ $retval = true;
3120
+ }
3121
+
3122
+ // If activity author match user, allow access as well.
3123
+ if ( $user_id === $activity->user_id ) {
3124
+ $retval = true;
3125
+ }
3126
+
3127
+ // If activity is from a group, do an extra cap check.
3128
+ if ( ! $retval && bp_is_active( 'groups' ) && $activity->component === buddypress()->groups->id ) {
3129
+
3130
+ // Check to see if the user has access to the activity's parent group.
3131
+ $group = groups_get_group( $activity->item_id );
3132
+ if ( $group ) {
3133
+ $retval = $group->user_has_access;
3134
+ }
3135
+ }
3136
+
3137
+ /**
3138
+ * Filters whether the current user has access to an activity item.
3139
+ *
3140
+ * @since 3.0.0
3141
+ *
3142
+ * @param bool $retval Return value.
3143
+ * @param int $user_id Current user ID.
3144
+ * @param BP_Activity_Activity $activity Activity object.
3145
+ */
3146
+ return apply_filters( 'bp_activity_user_can_read', $retval, $user_id, $activity );
3147
+ }
3148
+
3149
  /**
3150
  * Hide a user's activity.
3151
  *
3237
  return apply_filters( 'bp_activity_thumbnail_content_images', $content, $matches, $args );
3238
  }
3239
 
3240
+ /**
3241
+ * Gets the excerpt length for activity items.
3242
+ *
3243
+ * @since 2.8.0
3244
+ *
3245
+ * @return int Character length for activity excerpts.
3246
+ */
3247
+ function bp_activity_get_excerpt_length() {
3248
+ /**
3249
+ * Filters the excerpt length for the activity excerpt.
3250
+ *
3251
+ * @since 1.5.0
3252
+ *
3253
+ * @param int Character length for activity excerpts.
3254
+ */
3255
+ return (int) apply_filters( 'bp_activity_excerpt_length', 358 );
3256
+ }
3257
+
3258
  /**
3259
  * Create a rich summary of an activity item for the activity stream.
3260
  *
3325
  // Embeds must be subtracted from the paragraph count.
3326
  if ( ! empty( $media['has']['embeds'] ) ) {
3327
  $has_embeds = $media['has']['embeds'] > 0;
3328
+ $para_count -= $media['has']['embeds'];
3329
  }
3330
 
3331
  $extracted_media = array();
3464
 
3465
  // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity.
3466
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
3467
+ remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4 );
3468
 
3469
  // Build data package for Akismet.
3470
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
3511
 
3512
  // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity.
3513
  if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) {
3514
+ remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4 );
3515
 
3516
  // Build data package for Akismet.
3517
  $activity_data = BP_Akismet::build_akismet_data_package( $activity );
3535
  do_action( 'bp_activity_mark_as_ham', $activity, $source );
3536
  }
3537
 
3538
+ /* Emails *********************************************************************/
3539
+
3540
+ /**
3541
+ * Send email and BP notifications when a user is mentioned in an update.
3542
+ *
3543
+ * @since 1.2.0
3544
+ *
3545
+ * @param int $activity_id The ID of the activity update.
3546
+ * @param int $receiver_user_id The ID of the user who is receiving the update.
3547
+ */
3548
+ function bp_activity_at_message_notification( $activity_id, $receiver_user_id ) {
3549
+ $notifications = BP_Core_Notification::get_all_for_user( $receiver_user_id, 'all' );
3550
+
3551
+ // Don't leave multiple notifications for the same activity item.
3552
+ foreach( $notifications as $notification ) {
3553
+ if ( $activity_id == $notification->item_id ) {
3554
+ return;
3555
+ }
3556
+ }
3557
+
3558
+ $activity = new BP_Activity_Activity( $activity_id );
3559
+ $email_type = 'activity-at-message';
3560
+ $group_name = '';
3561
+ $message_link = bp_activity_get_permalink( $activity_id );
3562
+ $poster_name = bp_core_get_user_displayname( $activity->user_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( $activity->content, &$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
+ // Now email the user with the contents of the message (if they have enabled email notifications).
3576
+ if ( 'no' != bp_get_user_meta( $receiver_user_id, 'notification_activity_new_mention', true ) ) {
3577
+ if ( bp_is_active( 'groups' ) && bp_is_group() ) {
3578
+ $email_type = 'groups-at-message';
3579
+ $group_name = bp_get_current_group_name();
3580
+ }
3581
+
3582
+ $unsubscribe_args = array(
3583
+ 'user_id' => $receiver_user_id,
3584
+ 'notification_type' => $email_type,
3585
+ );
3586
+
3587
+ $args = array(
3588
+ 'tokens' => array(
3589
+ 'activity' => $activity,
3590
+ 'usermessage' => wp_strip_all_tags( $content ),
3591
+ 'group.name' => $group_name,
3592
+ 'mentioned.url' => $message_link,
3593
+ 'poster.name' => $poster_name,
3594
+ 'receiver-user.id' => $receiver_user_id,
3595
+ 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
3596
+ ),
3597
+ );
3598
+
3599
+ bp_send_email( $email_type, $receiver_user_id, $args );
3600
+ }
3601
+
3602
+ /**
3603
+ * Fires after the sending of an @mention email notification.
3604
+ *
3605
+ * @since 1.5.0
3606
+ * @since 2.5.0 $subject, $message, $content arguments unset and deprecated.
3607
+ *
3608
+ * @param BP_Activity_Activity $activity Activity Item object.
3609
+ * @param string $deprecated Removed in 2.5; now an empty string.
3610
+ * @param string $deprecated Removed in 2.5; now an empty string.
3611
+ * @param string $deprecated Removed in 2.5; now an empty string.
3612
+ * @param int $receiver_user_id The ID of the user who is receiving the update.
3613
+ */
3614
+ do_action( 'bp_activity_sent_mention_email', $activity, '', '', '', $receiver_user_id );
3615
+ }
3616
+
3617
+ /**
3618
+ * Send email and BP notifications when an activity item receives a comment.
3619
+ *
3620
+ * @since 1.2.0
3621
+ * @since 2.5.0 Updated to use new email APIs.
3622
+ *
3623
+ * @param int $comment_id The comment id.
3624
+ * @param int $commenter_id The ID of the user who posted the comment.
3625
+ * @param array $params {@link bp_activity_new_comment()}.
3626
+ */
3627
+ function bp_activity_new_comment_notification( $comment_id = 0, $commenter_id = 0, $params = array() ) {
3628
+ $original_activity = new BP_Activity_Activity( $params['activity_id'] );
3629
+ $poster_name = bp_core_get_user_displayname( $commenter_id );
3630
+ $thread_link = bp_activity_get_permalink( $params['activity_id'] );
3631
+
3632
+ remove_filter( 'bp_get_activity_content_body', 'convert_smilies' );
3633
+ remove_filter( 'bp_get_activity_content_body', 'wpautop' );
3634
+ remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
3635
+
3636
+ /** This filter is documented in bp-activity/bp-activity-template.php */
3637
+ $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $params['content'], &$original_activity ) );
3638
+
3639
+ add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
3640
+ add_filter( 'bp_get_activity_content_body', 'wpautop' );
3641
+ add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
3642
+
3643
+ if ( $original_activity->user_id != $commenter_id ) {
3644
+
3645
+ // Send an email if the user hasn't opted-out.
3646
+ if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
3647
+
3648
+ $unsubscribe_args = array(
3649
+ 'user_id' => $original_activity->user_id,
3650
+ 'notification_type' => 'activity-comment',
3651
+ );
3652
+
3653
+ $args = array(
3654
+ 'tokens' => array(
3655
+ 'comment.id' => $comment_id,
3656
+ 'commenter.id' => $commenter_id,
3657
+ 'usermessage' => wp_strip_all_tags( $content ),
3658
+ 'original_activity.user_id' => $original_activity->user_id,
3659
+ 'poster.name' => $poster_name,
3660
+ 'thread.url' => esc_url( $thread_link ),
3661
+ 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
3662
+ ),
3663
+ );
3664
+
3665
+ bp_send_email( 'activity-comment', $original_activity->user_id, $args );
3666
+ }
3667
+
3668
+ /**
3669
+ * Fires at the point that notifications should be sent for activity comments.
3670
+ *
3671
+ * @since 2.6.0
3672
+ *
3673
+ * @param BP_Activity_Activity $original_activity The original activity.
3674
+ * @param int $comment_id ID for the newly received comment.
3675
+ * @param int $commenter_id ID of the user who made the comment.
3676
+ * @param array $params Arguments used with the original activity comment.
3677
+ */
3678
+ do_action( 'bp_activity_sent_reply_to_update_notification', $original_activity, $comment_id, $commenter_id, $params );
3679
+ }
3680
+
3681
+
3682
+ /*
3683
+ * If this is a reply to another comment, send an email notification to the
3684
+ * author of the immediate parent comment.
3685
+ */
3686
+ if ( empty( $params['parent_id'] ) || ( $params['activity_id'] == $params['parent_id'] ) ) {
3687
+ return;
3688
+ }
3689
+
3690
+ $parent_comment = new BP_Activity_Activity( $params['parent_id'] );
3691
+
3692
+ if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id ) {
3693
+
3694
+ // Send an email if the user hasn't opted-out.
3695
+ if ( 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
3696
+
3697
+ $unsubscribe_args = array(
3698
+ 'user_id' => $parent_comment->user_id,
3699
+ 'notification_type' => 'activity-comment-author',
3700
+ );
3701
+
3702
+ $args = array(
3703
+ 'tokens' => array(
3704
+ 'comment.id' => $comment_id,
3705
+ 'commenter.id' => $commenter_id,
3706
+ 'usermessage' => wp_strip_all_tags( $content ),
3707
+ 'parent-comment-user.id' => $parent_comment->user_id,
3708
+ 'poster.name' => $poster_name,
3709
+ 'thread.url' => esc_url( $thread_link ),
3710
+ 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
3711
+ ),
3712
+ );
3713
+
3714
+ bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
3715
+ }
3716
+
3717
+ /**
3718
+ * Fires at the point that notifications should be sent for comments on activity replies.
3719
+ *
3720
+ * @since 2.6.0
3721
+ *
3722
+ * @param BP_Activity_Activity $parent_comment The parent activity.
3723
+ * @param int $comment_id ID for the newly received comment.
3724
+ * @param int $commenter_id ID of the user who made the comment.
3725
+ * @param array $params Arguments used with the original activity comment.
3726
+ */
3727
+ do_action( 'bp_activity_sent_reply_to_reply_notification', $parent_comment, $comment_id, $commenter_id, $params );
3728
+ }
3729
+ }
3730
+
3731
+ /**
3732
+ * Helper method to map action arguments to function parameters.
3733
+ *
3734
+ * @since 1.9.0
3735
+ *
3736
+ * @param int $comment_id ID of the comment being notified about.
3737
+ * @param array $params Parameters to use with notification.
3738
+ */
3739
+ function bp_activity_new_comment_notification_helper( $comment_id, $params ) {
3740
+ bp_activity_new_comment_notification( $comment_id, $params['user_id'], $params );
3741
+ }
3742
+ add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_helper', 10, 2 );
3743
 
3744
  /** Embeds *******************************************************************/
3745
 
3818
  function bp_dtheme_embed_read_more( $activity ) {
3819
  buddypress()->activity->read_more_id = $activity->id;
3820
 
3821
+ add_filter( 'embed_post_id', function() { return buddypress()->activity->read_more_id; } );
3822
  add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 );
3823
  add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
3824
  }
3888
  *
3889
  * @since 2.0.0
3890
  *
 
 
 
3891
  * @return bool True if activity heartbeat is enabled, otherwise false.
3892
  */
3893
  function bp_activity_do_heartbeat() {
3894
  $retval = false;
3895
 
3896
+ if ( bp_is_activity_heartbeat_active() && ( bp_is_activity_directory() || bp_is_group_activity() ) ) {
3897
+ $retval = true;
3898
  }
3899
 
3900
+ /**
3901
+ * Filters whether the heartbeat feature in the activity stream should be active.
3902
+ *
3903
+ * @since 2.8.0
3904
+ *
3905
+ * @param bool $retval Whether or not activity heartbeat is active.
3906
+ */
3907
+ return (bool) apply_filters( 'bp_activity_do_heartbeat', $retval );
3908
+ }
3909
+
3910
+ /**
3911
+ * AJAX endpoint for Suggestions API lookups.
3912
+ *
3913
+ * @since 2.1.0
3914
+ */
3915
+ function bp_ajax_get_suggestions() {
3916
+ if ( ! bp_is_user_active() || empty( $_GET['term'] ) || empty( $_GET['type'] ) ) {
3917
+ wp_send_json_error( 'missing_parameter' );
3918
+ exit;
3919
  }
3920
 
3921
+ $args = array(
3922
+ 'term' => sanitize_text_field( $_GET['term'] ),
3923
+ 'type' => sanitize_text_field( $_GET['type'] ),
3924
+ );
3925
+
3926
+ // Support per-Group suggestions.
3927
+ if ( ! empty( $_GET['group-id'] ) ) {
3928
+ $args['group_id'] = absint( $_GET['group-id'] );
3929
+ }
3930
+
3931
+ $results = bp_core_get_suggestions( $args );
3932
+
3933
+ if ( is_wp_error( $results ) ) {
3934
+ wp_send_json_error( $results->get_error_message() );
3935
+ exit;
3936
+ }
3937
+
3938
+ wp_send_json_success( $results );
3939
+ }
3940
+ add_action( 'wp_ajax_bp_get_suggestions', 'bp_ajax_get_suggestions' );
3941
+
3942
+ /**
3943
+ * Detect a change in post type status, and initiate an activity update if necessary.
3944
+ *
3945
+ * @since 2.2.0
3946
+ *
3947
+ * @todo Support untrashing better.
3948
+ *
3949
+ * @param string $new_status New status for the post.
3950
+ * @param string $old_status Old status for the post.
3951
+ * @param object $post Post data.
3952
+ */
3953
+ function bp_activity_catch_transition_post_type_status( $new_status, $old_status, $post ) {
3954
+ if ( ! post_type_supports( $post->post_type, 'buddypress-activity' ) ) {
3955
+ return;
3956
+ }
3957
+
3958
+ // This is an edit.
3959
+ if ( $new_status === $old_status ) {
3960
+ // An edit of an existing post should update the existing activity item.
3961
+ if ( $new_status == 'publish' ) {
3962
+ $edit = bp_activity_post_type_update( $post );
3963
+
3964
+ // Post was never recorded into activity stream, so record it now!
3965
+ if ( null === $edit ) {
3966
+ bp_activity_post_type_publish( $post->ID, $post );
3967
+ }
3968
+
3969
+ // Allow plugins to eventually deal with other post statuses.
3970
+ } else {
3971
+ /**
3972
+ * Fires when editing the post and the new status is not 'publish'.
3973
+ *
3974
+ * This is a variable filter that is dependent on the post type
3975
+ * being untrashed.
3976
+ *
3977
+ * @since 2.5.0
3978
+ *
3979
+ * @param WP_Post $post Post data.
3980
+ * @param string $new_status New status for the post.
3981
+ * @param string $old_status Old status for the post.
3982
+ */
3983
+ do_action( 'bp_activity_post_type_edit_' . $post->post_type, $post, $new_status, $old_status );
3984
+ }
3985
+
3986
+ return;
3987
+ }
3988
+
3989
+ // Publishing a previously unpublished post.
3990
+ if ( 'publish' === $new_status ) {
3991
+ // Untrashing the post type - nothing here yet.
3992
+ if ( 'trash' == $old_status ) {
3993
+
3994
+ /**
3995
+ * Fires if untrashing post in a post type.
3996
+ *
3997
+ * This is a variable filter that is dependent on the post type
3998
+ * being untrashed.
3999
+ *
4000
+ * @since 2.2.0
4001
+ *
4002
+ * @param WP_Post $post Post data.
4003
+ */
4004
+ do_action( 'bp_activity_post_type_untrash_' . $post->post_type, $post );
4005
+ } else {
4006
+ // Record the post.
4007
+ bp_activity_post_type_publish( $post->ID, $post );
4008
+ }
4009
+
4010
+ // Unpublishing a previously published post.
4011
+ } elseif ( 'publish' === $old_status ) {
4012
+ // Some form of pending status - only remove the activity entry.
4013
+ bp_activity_post_type_unpublish( $post->ID, $post );
4014
+
4015
+ // For any other cases, allow plugins to eventually deal with it.
4016
+ } else {
4017
+ /**
4018
+ * Fires when the old and the new post status are not 'publish'.
4019
+ *
4020
+ * This is a variable filter that is dependent on the post type
4021
+ * being untrashed.
4022
+ *
4023
+ * @since 2.5.0
4024
+ *
4025
+ * @param WP_Post $post Post data.
4026
+ * @param string $new_status New status for the post.
4027
+ * @param string $old_status Old status for the post.
4028
+ */
4029
+ do_action( 'bp_activity_post_type_transition_status_' . $post->post_type, $post, $new_status, $old_status );
4030
+ }
4031
+ }
4032
+ add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 );
4033
+
4034
+ /**
4035
+ * When a post type comment status transition occurs, update the relevant activity's status.
4036
+ *
4037
+ * @since 2.5.0
4038
+ *
4039
+ * @param string $new_status New comment status.
4040
+ * @param string $old_status Previous comment status.
4041
+ * @param WP_Comment $comment Comment data.
4042
+ */
4043
+ function bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment ) {
4044
+ $post_type = get_post_type( $comment->comment_post_ID );
4045
+ if ( ! $post_type ) {
4046
+ return;
4047
+ }
4048
+
4049
+ // Get the post type tracking args.
4050
+ $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
4051
+
4052
+ // Bail if the activity type does not exist
4053
+ if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
4054
+ return false;
4055
+
4056
+ // Set the $activity_comment_object
4057
+ } else {
4058
+ $activity_comment_object = $activity_post_object->comments_tracking;
4059
+ }
4060
+
4061
+ // Init an empty activity ID
4062
+ $activity_id = 0;
4063
+
4064
+ /**
4065
+ * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
4066
+ *
4067
+ * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
4068
+ * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
4069
+ * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
4070
+ * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
4071
+ * Otherwise, record the comment into the activity stream.
4072
+ */
4073
+
4074
+ // This clause handles delete/hold.
4075
+ if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
4076
+ return bp_activity_post_type_remove_comment( $comment->comment_ID, $activity_post_object );
4077
+
4078
+ // These clauses handle trash, spam, and un-spams.
4079
+ } elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
4080
+ $action = 'spam_activity';
4081
+ } elseif ( 'approved' == $new_status ) {
4082
+ $action = 'ham_activity';
4083
+ }
4084
+
4085
+ // Get the activity
4086
+ if ( bp_disable_blogforum_comments() ) {
4087
+ $activity_id = bp_activity_get_activity_id( array(
4088
+ 'component' => $activity_comment_object->component_id,
4089
+ 'item_id' => get_current_blog_id(),
4090
+ 'secondary_item_id' => $comment->comment_ID,
4091
+ 'type' => $activity_comment_object->action_id,
4092
+ ) );
4093
+ } else {
4094
+ $activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
4095
+ }
4096
+
4097
+ /**
4098
+ * Leave a chance to plugins to manage activity comments differently.
4099
+ *
4100
+ * @since 2.5.0
4101
+ *
4102
+ * @param bool $value True to override BuddyPress management.
4103
+ * @param string $post_type The post type name.
4104
+ * @param int $activity_id The post type activity (0 if not found).
4105
+ * @param string $new_status The new status of the post type comment.
4106
+ * @param string $old_status The old status of the post type comment.
4107
+ * @param WP_Comment $comment Comment data.
4108
+ */
4109
+ if ( true === apply_filters( 'bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment ) ) {
4110
+ return false;
4111
+ }
4112
+
4113
+ // Check activity item exists
4114
+ if ( empty( $activity_id ) ) {
4115
+ // If no activity exists, but the comment has been approved, record it into the activity table.
4116
+ if ( 'approved' == $new_status ) {
4117
+ return bp_activity_post_type_comment( $comment->comment_ID, true, $activity_post_object );
4118
+ }
4119
+
4120
+ return;
4121
+ }
4122
+
4123
+ // Create an activity object
4124
+ $activity = new BP_Activity_Activity( $activity_id );
4125
+ if ( empty( $activity->component ) ) {
4126
+ return;
4127
+ }
4128
+
4129
+ // Spam/ham the activity if it's not already in that state
4130
+ if ( 'spam_activity' === $action && ! $activity->is_spam ) {
4131
+ bp_activity_mark_as_spam( $activity );
4132
+ } elseif ( 'ham_activity' == $action) {
4133
+ bp_activity_mark_as_ham( $activity );
4134
+ }
4135
+
4136
+ // Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
4137
+ $post_type_comment_action = $activity_comment_object->action_id;
4138
+ $comment_akismet_history = function ( $activity_types ) use ( $post_type_comment_action ) {
4139
+ $activity_types[] = $post_type_comment_action;
4140
+
4141
+ return $activity_types;
4142
+ };
4143
+ add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
4144
+
4145
+ // Make sure the activity change won't edit the comment if sync is on
4146
+ remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
4147
+
4148
+ // Save the updated activity
4149
+ $activity->save();
4150
+
4151
+ // Restore the action
4152
+ add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
4153
+
4154
+ // Remove the "new_blog_comment" activity type whitelist so we don't break anything
4155
+ remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
4156
  }
4157
+ add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
bp-activity/bp-activity-loader.php CHANGED
@@ -12,12 +12,8 @@
12
  // Exit if accessed directly.
13
  defined( 'ABSPATH' ) || exit;
14
 
15
- if ( ! buddypress()->do_autoload ) {
16
- require dirname( __FILE__ ) . '/classes/class-bp-activity-component.php';
17
- }
18
-
19
  /**
20
- * Bootstrap the Activity component.
21
  *
22
  * @since 1.6.0
23
  */
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
  */
bp-activity/bp-activity-notifications.php CHANGED
@@ -10,194 +10,6 @@
10
  // Exit if accessed directly.
11
  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 1.2.0
19
- *
20
- * @param int $activity_id The ID of the activity update.
21
- * @param int $receiver_user_id The ID of the user who is receiving the update.
22
- */
23
- function bp_activity_at_message_notification( $activity_id, $receiver_user_id ) {
24
- $notifications = BP_Core_Notification::get_all_for_user( $receiver_user_id, 'all' );
25
-
26
- // Don't leave multiple notifications for the same activity item.
27
- foreach( $notifications as $notification ) {
28
- if ( $activity_id == $notification->item_id ) {
29
- return;
30
- }
31
- }
32
-
33
- $activity = new BP_Activity_Activity( $activity_id );
34
- $email_type = 'activity-at-message';
35
- $group_name = '';
36
- $message_link = bp_activity_get_permalink( $activity_id );
37
- $poster_name = bp_core_get_user_displayname( $activity->user_id );
38
-
39
- remove_filter( 'bp_get_activity_content_body', 'convert_smilies' );
40
- remove_filter( 'bp_get_activity_content_body', 'wpautop' );
41
- remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
42
-
43
- /** This filter is documented in bp-activity/bp-activity-template.php */
44
- $content = apply_filters( 'bp_get_activity_content_body', $activity->content );
45
-
46
- add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
47
- add_filter( 'bp_get_activity_content_body', 'wpautop' );
48
- add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
49
-
50
- // Now email the user with the contents of the message (if they have enabled email notifications).
51
- if ( 'no' != bp_get_user_meta( $receiver_user_id, 'notification_activity_new_mention', true ) ) {
52
- if ( bp_is_active( 'groups' ) && bp_is_group() ) {
53
- $email_type = 'groups-at-message';
54
- $group_name = bp_get_current_group_name();
55
- }
56
-
57
- $args = array(
58
- 'tokens' => array(
59
- 'activity' => $activity,
60
- 'usermessage' => wp_strip_all_tags( $content ),
61
- 'group.name' => $group_name,
62
- 'mentioned.url' => $message_link,
63
- 'poster.name' => $poster_name,
64
- 'receiver-user.id' => $receiver_user_id,
65
- ),
66
- );
67
-
68
- bp_send_email( $email_type, $receiver_user_id, $args );
69
- }
70
-
71
- /**
72
- * Fires after the sending of an @mention email notification.
73
- *
74
- * @since 1.5.0
75
- * @since 2.5.0 $subject, $message, $content arguments unset and deprecated.
76
- *
77
- * @param BP_Activity_Activity $activity Activity Item object.
78
- * @param string $deprecated Removed in 2.5; now an empty string.
79
- * @param string $deprecated Removed in 2.5; now an empty string.
80
- * @param string $deprecated Removed in 2.5; now an empty string.
81
- * @param int $receiver_user_id The ID of the user who is receiving the update.
82
- */
83
- do_action( 'bp_activity_sent_mention_email', $activity, '', '', '', $receiver_user_id );
84
- }
85
-
86
- /**
87
- * Send email and BP notifications when an activity item receives a comment.
88
- *
89
- * @since 1.2.0
90
- * @since 2.5.0 Updated to use new email APIs.
91
- *
92
- * @param int $comment_id The comment id.
93
- * @param int $commenter_id The ID of the user who posted the comment.
94
- * @param array $params {@link bp_activity_new_comment()}.
95
- */
96
- function bp_activity_new_comment_notification( $comment_id = 0, $commenter_id = 0, $params = array() ) {
97
- $original_activity = new BP_Activity_Activity( $params['activity_id'] );
98
- $poster_name = bp_core_get_user_displayname( $commenter_id );
99
- $thread_link = bp_activity_get_permalink( $params['activity_id'] );
100
-
101
- remove_filter( 'bp_get_activity_content_body', 'convert_smilies' );
102
- remove_filter( 'bp_get_activity_content_body', 'wpautop' );
103
- remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
104
-
105
- /** This filter is documented in bp-activity/bp-activity-template.php */
106
- $content = apply_filters( 'bp_get_activity_content_body', $params['content'] );
107
-
108
- add_filter( 'bp_get_activity_content_body', 'convert_smilies' );
109
- add_filter( 'bp_get_activity_content_body', 'wpautop' );
110
- add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
111
-
112
- if ( $original_activity->user_id != $commenter_id ) {
113
-
114
- // Send an email if the user hasn't opted-out.
115
- if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
116
- $args = array(
117
- 'tokens' => array(
118
- 'comment.id' => $comment_id,
119
- 'commenter.id' => $commenter_id,
120
- 'usermessage' => wp_strip_all_tags( $content ),
121
- 'original_activity.user_id' => $original_activity->user_id,
122
- 'poster.name' => $poster_name,
123
- 'thread.url' => esc_url( $thread_link ),
124
- ),
125
- );
126
-
127
- bp_send_email( 'activity-comment', $original_activity->user_id, $args );
128
- }
129
-
130
- /**
131
- * Fires at the point that notifications should be sent for activity comments.
132
- *
133
- * @since 2.6.0
134
- *
135
- * @param BP_Activity_Activity $original_activity The original activity.
136
- * @param int $comment_id ID for the newly received comment.
137
- * @param int $commenter_id ID of the user who made the comment.
138
- * @param array $params Arguments used with the original activity comment.
139
- */
140
- do_action( 'bp_activity_sent_reply_to_update_notification', $original_activity, $comment_id, $commenter_id, $params );
141
- }
142
-
143
-
144
- /*
145
- * If this is a reply to another comment, send an email notification to the
146
- * author of the immediate parent comment.
147
- */
148
- if ( empty( $params['parent_id'] ) || ( $params['activity_id'] == $params['parent_id'] ) ) {
149
- return;
150
- }
151
-
152
- $parent_comment = new BP_Activity_Activity( $params['parent_id'] );
153
-
154
- if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id ) {
155
-
156
- // Send an email if the user hasn't opted-out.
157
- if ( 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
158
- $args = array(
159
- 'tokens' => array(
160
- 'comment.id' => $comment_id,
161
- 'commenter.id' => $commenter_id,
162
- 'usermessage' => wp_strip_all_tags( $content ),
163
- 'parent-comment-user.id' => $parent_comment->user_id,
164
- 'poster.name' => $poster_name,
165
- 'thread.url' => esc_url( $thread_link ),
166
- ),
167
- );
168
-
169
- bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
170
- }
171
-
172
- /**
173
- * Fires at the point that notifications should be sent for comments on activity replies.
174
- *
175
- * @since 2.6.0
176
- *
177
- * @param BP_Activity_Activity $parent_comment The parent activity.
178
- * @param int $comment_id ID for the newly received comment.
179
- * @param int $commenter_id ID of the user who made the comment.
180
- * @param array $params Arguments used with the original activity comment.
181
- */
182
- do_action( 'bp_activity_sent_reply_to_reply_notification', $parent_comment, $comment_id, $commenter_id, $params );
183
- }
184
- }
185
-
186
- /**
187
- * Helper method to map action arguments to function parameters.
188
- *
189
- * @since 1.9.0
190
- *
191
- * @param int $comment_id ID of the comment being notified about.
192
- * @param array $params Parameters to use with notification.
193
- */
194
- function bp_activity_new_comment_notification_helper( $comment_id, $params ) {
195
- bp_activity_new_comment_notification( $comment_id, $params['user_id'], $params );
196
- }
197
- add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_helper', 10, 2 );
198
-
199
- /** Notifications *************************************************************/
200
-
201
  /**
202
  * Format notifications related to activity.
203
  *
@@ -208,9 +20,10 @@ add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_
208
  * @param int $secondary_item_id In the case of at-mentions, this is the mentioner's ID.
209
  * @param int $total_items The total number of notifications to format.
210
  * @param string $format 'string' to get a BuddyBar-compatible notification, 'array' otherwise.
 
211
  * @return string $return Formatted @mention notification.
212
  */
213
- function bp_activity_format_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
214
  $action_filter = $action;
215
  $return = false;
216
  $activity_id = $item_id;
@@ -225,10 +38,10 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
225
  $amount = 'single';
226
 
227
  if ( (int) $total_items > 1 ) {
228
- $text = sprintf( __( 'You have %1$d new mentions', 'buddypress' ), (int) $total_items );
229
  $amount = 'multiple';
230
  } else {
231
- $text = sprintf( __( '%1$s mentioned you', 'buddypress' ), $user_fullname );
232
  }
233
  break;
234
 
@@ -242,8 +55,8 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
242
  $text = sprintf( __( 'You have %1$d new replies', 'buddypress' ), (int) $total_items );
243
  $amount = 'multiple';
244
  } else {
245
- $link = bp_activity_get_permalink( $activity_id );
246
- $text = sprintf( __( '%1$s commented on one of your updates', 'buddypress' ), $user_fullname );
247
  }
248
  break;
249
 
@@ -257,8 +70,8 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
257
  $text = sprintf( __( 'You have %1$d new comment replies', 'buddypress' ), (int) $total_items );
258
  $amount = 'multiple';
259
  } else {
260
- $link = bp_activity_get_permalink( $activity_id );
261
- $text = sprintf( __( '%1$s replied to one your activity comments', 'buddypress' ), $user_fullname );
262
  }
263
  break;
264
  }
@@ -281,7 +94,7 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
281
  * @param int $activity_id ID of the activity item being formatted.
282
  * @param int $user_id ID of the user who inited the interaction.
283
  */
284
- $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 );
285
  } else {
286
 
287
  /**
@@ -338,8 +151,7 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
338
  * @param int $receiver_user_id ID of user receiving notification.
339
  */
340
  function bp_activity_at_mention_add_notification( $activity, $subject, $message, $content, $receiver_user_id ) {
341
- if ( bp_is_active( 'notifications' ) ) {
342
- bp_notifications_add_notification( array(
343
  'user_id' => $receiver_user_id,
344
  'item_id' => $activity->id,
345
  'secondary_item_id' => $activity->user_id,
@@ -347,8 +159,7 @@ function bp_activity_at_mention_add_notification( $activity, $subject, $message,
347
  'component_action' => 'new_at_mention',
348
  'date_notified' => bp_core_current_time(),
349
  'is_new' => 1,
350
- ) );
351
- }
352
  }
353
  add_action( 'bp_activity_sent_mention_email', 'bp_activity_at_mention_add_notification', 10, 5 );
354
 
@@ -362,17 +173,15 @@ add_action( 'bp_activity_sent_mention_email', 'bp_activity_at_mention_add_notifi
362
  * @param int $commenter_id ID of the user who made the comment.
363
  */
364
  function bp_activity_update_reply_add_notification( $activity, $comment_id, $commenter_id ) {
365
- if ( bp_is_active( 'notifications' ) ) {
366
- bp_notifications_add_notification( array(
367
- 'user_id' => $activity->user_id,
368
- 'item_id' => $activity->id,
369
- 'secondary_item_id' => $commenter_id,
370
- 'component_name' => buddypress()->activity->id,
371
- 'component_action' => 'update_reply',
372
- 'date_notified' => bp_core_current_time(),
373
- 'is_new' => 1,
374
- ) );
375
- }
376
  }
377
  add_action( 'bp_activity_sent_reply_to_update_notification', 'bp_activity_update_reply_add_notification', 10, 3 );
378
 
@@ -386,17 +195,15 @@ add_action( 'bp_activity_sent_reply_to_update_notification', 'bp_activity_update
386
  * @param int $commenter_id ID of the user who made the comment.
387
  */
388
  function bp_activity_comment_reply_add_notification( $activity_comment, $comment_id, $commenter_id ) {
389
- if ( bp_is_active( 'notifications' ) ) {
390
- bp_notifications_add_notification( array(
391
- 'user_id' => $activity_comment->user_id,
392
- 'item_id' => $activity_comment->item_id,
393
- 'secondary_item_id' => $commenter_id,
394
- 'component_name' => buddypress()->activity->id,
395
- 'component_action' => 'comment_reply',
396
- 'date_notified' => bp_core_current_time(),
397
- 'is_new' => 1,
398
- ) );
399
- }
400
  }
401
  add_action( 'bp_activity_sent_reply_to_reply_notification', 'bp_activity_comment_reply_add_notification', 10, 3 );
402
 
@@ -409,10 +216,6 @@ add_action( 'bp_activity_sent_reply_to_reply_notification', 'bp_activity_comment
409
  * @param int $user_id The id of the user whose notifications are marked as read.
410
  */
411
  function bp_activity_remove_screen_notifications( $user_id = 0 ) {
412
- if ( ! bp_is_active( 'notifications' ) ) {
413
- return;
414
- }
415
-
416
  // Only mark read if the current user is looking at his own mentions.
417
  if ( empty( $user_id ) || (int) $user_id !== (int) bp_loggedin_user_id() ) {
418
  return;
@@ -426,42 +229,44 @@ add_action( 'bp_activity_clear_new_mentions', 'bp_activity_remove_screen_notific
426
  * Mark at-mention notification as read when user visits the activity with the mention.
427
  *
428
  * @since 2.0.0
429
- * @since 2.6.0 Mark notifications for 'update_reply' and 'comment_reply' actions
430
  *
431
  * @param BP_Activity_Activity $activity Activity object.
432
  */
433
  function bp_activity_remove_screen_notifications_single_activity_permalink( $activity ) {
434
- if ( ! bp_is_active( 'notifications' ) ) {
435
- return;
436
- }
437
-
438
  if ( ! is_user_logged_in() ) {
439
  return;
440
  }
441
 
442
- /**
443
- * Filter here to add the notification actions to mark as read
444
- * when the single activity is displayed.
445
- *
446
- * @since 2.6.0
447
- *
448
- * @param array $value List of notification actions to mark as read.
449
- */
450
- $notification_actions = apply_filters( 'bp_activity_notification_actions_single_activity', array(
451
- 'new_at_mention',
452
- 'update_reply',
453
- 'comment_reply',
454
- ) );
455
-
456
- $user_id = bp_loggedin_user_id();
457
- $component = buddypress()->activity->id;
458
 
459
- foreach ( $notification_actions as $action ) {
460
- // Mark as read any notifications for the current user related to this activity item.
461
- bp_notifications_mark_notifications_by_item_id( $user_id, $activity->id, $component, $action );
 
 
 
 
 
 
 
 
462
  }
 
 
 
 
 
 
 
 
 
 
 
463
  }
464
- add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_screen_notifications_single_activity_permalink' );
465
 
466
  /**
467
  * Delete at-mention notifications when the corresponding activity item is deleted.
@@ -473,10 +278,64 @@ add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_
473
  function bp_activity_at_mention_delete_notification( $activity_ids_deleted = array() ) {
474
  // Let's delete all without checking if content contains any mentions
475
  // to avoid a query to get the activity.
476
- if ( bp_is_active( 'notifications' ) && ! empty( $activity_ids_deleted ) ) {
477
  foreach ( $activity_ids_deleted as $activity_id ) {
478
  bp_notifications_delete_all_notifications_by_type( $activity_id, buddypress()->activity->id );
479
  }
480
  }
481
  }
482
  add_action( 'bp_activity_deleted_activities', 'bp_activity_at_mention_delete_notification', 10 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  /**
14
  * Format notifications related to activity.
15
  *
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;
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
 
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
 
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
  }
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 ) . '">' . esc_html( $text ) . '</a>', $link, (int) $total_items, $activity_id, $user_id );
98
  } else {
99
 
100
  /**
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
  '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
 
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
 
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
 
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;
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.
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 posts and comments" 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 );
bp-activity/bp-activity-screens.php DELETED
@@ -1,378 +0,0 @@
1
- <?php
2
- /**
3
- * BuddyPress Activity Screens.
4
- *
5
- * The functions in this file detect, with each page load, whether an Activity
6
- * component page is being requested. If so, it parses any necessary data from
7
- * the URL, and tells BuddyPress to load the appropriate template.
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
- if ( ! buddypress()->do_autoload ) {
18
- require dirname( __FILE__ ) . '/classes/class-bp-activity-theme-compat.php';
19
- }
20
-
21
- /**
22
- * Load the Activity directory.
23
- *
24
- * @since 1.5.0
25
- *
26
- */
27
- function bp_activity_screen_index() {
28
- if ( bp_is_activity_directory() ) {
29
- bp_update_is_directory( true, 'activity' );
30
-
31
- /**
32
- * Fires right before the loading of the Activity directory screen template file.
33
- *
34
- * @since 1.5.0
35
- */
36
- do_action( 'bp_activity_screen_index' );
37
-
38
- /**
39
- * Filters the template to load for the Activity directory screen.
40
- *
41
- * @since 1.5.0
42
- *
43
- * @param string $template Path to the activity template to load.
44
- */
45
- bp_core_load_template( apply_filters( 'bp_activity_screen_index', 'activity/index' ) );
46
- }
47
- }
48
- add_action( 'bp_screens', 'bp_activity_screen_index' );
49
-
50
- /**
51
- * Load the 'My Activity' page.
52
- *
53
- * @since 1.0.0
54
- *
55
- */
56
- function bp_activity_screen_my_activity() {
57
-
58
- /**
59
- * Fires right before the loading of the "My Activity" screen template file.
60
- *
61
- * @since 1.0.0
62
- */
63
- do_action( 'bp_activity_screen_my_activity' );
64
-
65
- /**
66
- * Filters the template to load for the "My Activity" screen.
67
- *
68
- * @since 1.0.0
69
- *
70
- * @param string $template Path to the activity template to load.
71
- */
72
- bp_core_load_template( apply_filters( 'bp_activity_template_my_activity', 'members/single/home' ) );
73
- }
74
-
75
- /**
76
- * Load the 'My Friends' activity page.
77
- *
78
- * @since 1.0.0
79
- *
80
- */
81
- function bp_activity_screen_friends() {
82
- if ( !bp_is_active( 'friends' ) )
83
- return false;
84
-
85
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
86
-
87
- /**
88
- * Fires right before the loading of the "My Friends" screen template file.
89
- *
90
- * @since 1.2.0
91
- */
92
- do_action( 'bp_activity_screen_friends' );
93
-
94
- /**
95
- * Filters the template to load for the "My Friends" screen.
96
- *
97
- * @since 1.0.0
98
- *
99
- * @param string $template Path to the activity template to load.
100
- */
101
- bp_core_load_template( apply_filters( 'bp_activity_template_friends_activity', 'members/single/home' ) );
102
- }
103
-
104
- /**
105
- * Load the 'My Groups' activity page.
106
- *
107
- * @since 1.2.0
108
- *
109
- */
110
- function bp_activity_screen_groups() {
111
- if ( !bp_is_active( 'groups' ) )
112
- return false;
113
-
114
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
115
-
116
- /**
117
- * Fires right before the loading of the "My Groups" screen template file.
118
- *
119
- * @since 1.2.0
120
- */
121
- do_action( 'bp_activity_screen_groups' );
122
-
123
- /**
124
- * Filters the template to load for the "My Groups" screen.
125
- *
126
- * @since 1.2.0
127
- *
128
- * @param string $template Path to the activity template to load.
129
- */
130
- bp_core_load_template( apply_filters( 'bp_activity_template_groups_activity', 'members/single/home' ) );
131
- }
132
-
133
- /**
134
- * Load the 'Favorites' activity page.
135
- *
136
- * @since 1.2.0
137
- *
138
- */
139
- function bp_activity_screen_favorites() {
140
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
141
-
142
- /**
143
- * Fires right before the loading of the "Favorites" screen template file.
144
- *
145
- * @since 1.2.0
146
- */
147
- do_action( 'bp_activity_screen_favorites' );
148
-
149
- /**
150
- * Filters the template to load for the "Favorites" screen.
151
- *
152
- * @since 1.2.0
153
- *
154
- * @param string $template Path to the activity template to load.
155
- */
156
- bp_core_load_template( apply_filters( 'bp_activity_template_favorite_activity', 'members/single/home' ) );
157
- }
158
-
159
- /**
160
- * Load the 'Mentions' activity page.
161
- *
162
- * @since 1.2.0
163
- *
164
- */
165
- function bp_activity_screen_mentions() {
166
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
167
-
168
- /**
169
- * Fires right before the loading of the "Mentions" screen template file.
170
- *
171
- * @since 1.2.0
172
- */
173
- do_action( 'bp_activity_screen_mentions' );
174
-
175
- /**
176
- * Filters the template to load for the "Mentions" screen.
177
- *
178
- * @since 1.2.0
179
- *
180
- * @param string $template Path to the activity template to load.
181
- */
182
- bp_core_load_template( apply_filters( 'bp_activity_template_mention_activity', 'members/single/home' ) );
183
- }
184
-
185
- /**
186
- * Reset the logged-in user's new mentions data when he visits his mentions screen.
187
- *
188
- * @since 1.5.0
189
- *
190
- */
191
- function bp_activity_reset_my_new_mentions() {
192
- if ( bp_is_my_profile() )
193
- bp_activity_clear_new_mentions( bp_loggedin_user_id() );
194
- }
195
- add_action( 'bp_activity_screen_mentions', 'bp_activity_reset_my_new_mentions' );
196
-
197
- /**
198
- * Load the page for a single activity item.
199
- *
200
- * @since 1.2.0
201
- *
202
- */
203
- function bp_activity_screen_single_activity_permalink() {
204
- $bp = buddypress();
205
-
206
- // No displayed user or not viewing activity component.
207
- if ( !bp_is_activity_component() )
208
- return false;
209
-
210
- if ( ! bp_current_action() || !is_numeric( bp_current_action() ) )
211
- return false;
212
-
213
- // Get the activity details.
214
- $activity = bp_activity_get_specific( array( 'activity_ids' => bp_current_action(), 'show_hidden' => true, 'spam' => 'ham_only', ) );
215
-
216
- // 404 if activity does not exist
217
- if ( empty( $activity['activities'][0] ) || bp_action_variables() ) {
218
- bp_do_404();
219
- return;
220
-
221
- } else {
222
- $activity = $activity['activities'][0];
223
- }
224
-
225
- // Default access is true.
226
- $has_access = true;
227
-
228
- // If activity is from a group, do an extra cap check.
229
- if ( isset( $bp->groups->id ) && $activity->component == $bp->groups->id ) {
230
-
231
- // Activity is from a group, but groups is currently disabled.
232
- if ( !bp_is_active( 'groups') ) {
233
- bp_do_404();
234
- return;
235
- }
236
-
237
- // Check to see if the group is not public, if so, check the
238
- // user has access to see this activity.
239
- if ( $group = groups_get_group( array( 'group_id' => $activity->item_id ) ) ) {
240
-
241
- // Group is not public.
242
- if ( 'public' != $group->status ) {
243
-
244
- // User is not a member of group.
245
- if ( !groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
246
- $has_access = false;
247
- }
248
- }
249
- }
250
- }
251
-
252
- /**
253
- * Filters the access permission for a single activity view.
254
- *
255
- * @since 1.2.0
256
- *
257
- * @param array $access Array holding the current $has_access value and current activity item instance.
258
- */
259
- $has_access = apply_filters_ref_array( 'bp_activity_permalink_access', array( $has_access, &$activity ) );
260
-
261
- /**
262
- * Fires before the loading of a single activity template file.
263
- *
264
- * @since 1.2.0
265
- *
266
- * @param BP_Activity_Activity $activity Object representing the current activity item being displayed.
267
- * @param bool $has_access Whether or not the current user has access to view activity.
268
- */
269
- do_action( 'bp_activity_screen_single_activity_permalink', $activity, $has_access );
270
-
271
- // Access is specifically disallowed.
272
- if ( false === $has_access ) {
273
-
274
- // User feedback.
275
- bp_core_add_message( __( 'You do not have access to this activity.', 'buddypress' ), 'error' );
276
-
277
- // Redirect based on logged in status.
278
- if ( is_user_logged_in() ) {
279
- $url = bp_loggedin_user_domain();
280
-
281
- } else {
282
- $url = sprintf(
283
- site_url( 'wp-login.php?redirect_to=%s' ),
284
- urlencode( esc_url_raw( bp_activity_get_permalink( bp_current_action() ) ) )
285
- );
286
- }
287
-
288
- bp_core_redirect( $url );
289
- }
290
-
291
- /**
292
- * Filters the template to load for a single activity screen.
293
- *
294
- * @since 1.0.0
295
- *
296
- * @param string $template Path to the activity template to load.
297
- */
298
- bp_core_load_template( apply_filters( 'bp_activity_template_profile_activity_permalink', 'members/single/activity/permalink' ) );
299
- }
300
- add_action( 'bp_screens', 'bp_activity_screen_single_activity_permalink' );
301
-
302
- /**
303
- * Add activity notifications settings to the notifications settings page.
304
- *
305
- * @since 1.2.0
306
- *
307
- */
308
- function bp_activity_screen_notification_settings() {
309
-
310
- if ( bp_activity_do_mentions() ) {
311
- if ( ! $mention = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_mention', true ) ) {
312
- $mention = 'yes';
313
- }
314
- }
315
-
316
- if ( ! $reply = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_reply', true ) ) {
317
- $reply = 'yes';
318
- }
319
-
320
- ?>
321
-
322
- <table class="notification-settings" id="activity-notification-settings">
323
- <thead>
324
- <tr>
325
- <th class="icon">&nbsp;</th>
326
- <th class="title"><?php _e( 'Activity', 'buddypress' ) ?></th>
327
- <th class="yes"><?php _e( 'Yes', 'buddypress' ) ?></th>
328
- <th class="no"><?php _e( 'No', 'buddypress' )?></th>
329
- </tr>
330
- </thead>
331
-
332
- <tbody>
333
- <?php if ( bp_activity_do_mentions() ) : ?>
334
- <tr id="activity-notification-settings-mentions">
335
- <td>&nbsp;</td>
336
- <td><?php printf( __( 'A member mentions you in an update using "@%s"', 'buddypress' ), bp_core_get_username( bp_displayed_user_id() ) ) ?></td>
337
- <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
338
- /* translators: accessibility text */
339
- _e( 'Yes, send email', 'buddypress' );
340
- ?></label></td>
341
- <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
342
- /* translators: accessibility text */
343
- _e( 'No, do not send email', 'buddypress' );
344
- ?></label></td>
345
- </tr>
346
- <?php endif; ?>
347
-
348
- <tr id="activity-notification-settings-replies">
349
- <td>&nbsp;</td>
350
- <td><?php _e( "A member replies to an update or comment you've posted", 'buddypress' ) ?></td>
351
- <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
352
- /* translators: accessibility text */
353
- _e( 'Yes, send email', 'buddypress' );
354
- ?></label></td>
355
- <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
356
- /* translators: accessibility text */
357
- _e( 'No, do not send email', 'buddypress' );
358
- ?></label></td>
359
- </tr>
360
-
361
- <?php
362
-
363
- /**
364
- * Fires inside the closing </tbody> tag for activity screen notification settings.
365
- *
366
- * @since 1.2.0
367
- */
368
- do_action( 'bp_activity_screen_notification_settings' ) ?>
369
- </tbody>
370
- </table>
371
-
372
- <?php
373
- }
374
- add_action( 'bp_notification_settings', 'bp_activity_screen_notification_settings', 1 );
375
-
376
- /** Theme Compatibility *******************************************************/
377
-
378
- new BP_Activity_Theme_Compat();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-template.php CHANGED
@@ -10,10 +10,6 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-activity-template.php';
15
- }
16
-
17
  /**
18
  * Output the activity component slug.
19
  *
@@ -270,8 +266,8 @@ function bp_has_activities( $args = '' ) {
270
  // Filtering
271
  'user_id' => $user_id, // user_id to filter on.
272
  'object' => $object, // Object to filter on e.g. groups, profile, status, friends.
273
- 'action' => false, // Action to filter on e.g. activity_update, new_forum_post, profile_updated.
274
- 'primary_id' => $primary_id, // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
275
  'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
276
  'offset' => false, // Return only items >= this ID.
277
  'since' => false, // Return only items recorded since this Y-m-d H:i:s date.
@@ -1177,11 +1173,7 @@ function bp_activity_secondary_avatar( $args = '' ) {
1177
 
1178
  // Only if groups is active.
1179
  if ( bp_is_active( 'groups' ) ) {
1180
- $group = groups_get_group( array(
1181
- 'group_id' => $item_id,
1182
- 'populate_extras' => false,
1183
- 'update_meta_cache' => false,
1184
- ) );
1185
  $link = bp_get_group_permalink( $group );
1186
  $name = $group->name;
1187
  }
@@ -1394,7 +1386,8 @@ function bp_activity_content_body() {
1394
  *
1395
  * @since 1.2.0
1396
  *
1397
- * @param array $value Array containing the current activity content body and the current activity.
 
1398
  */
1399
  return apply_filters_ref_array( 'bp_get_activity_content_body', array( $activities_template->activity->content, &$activities_template->activity ) );
1400
  }
@@ -1476,6 +1469,13 @@ function bp_insert_activity_meta( $content = '' ) {
1476
  // Get the time since this activity was recorded.
1477
  $date_recorded = bp_core_time_since( $activities_template->activity->date_recorded );
1478
 
 
 
 
 
 
 
 
1479
  /**
1480
  * Filters the activity item time since markup.
1481
  *
@@ -1484,7 +1484,7 @@ function bp_insert_activity_meta( $content = '' ) {
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
- '<span class="time-since">' . $date_recorded . '</span>',
1488
  &$activities_template->activity
1489
  ) );
1490
 
@@ -1493,7 +1493,7 @@ function bp_insert_activity_meta( $content = '' ) {
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' ),
@@ -1533,7 +1533,7 @@ function bp_insert_activity_meta( $content = '' ) {
1533
  *
1534
  * @global object $activities_template {@link BP_Activity_Template}
1535
  *
1536
- * @param object|bool $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 ) {
@@ -2090,7 +2090,7 @@ function bp_activity_comment_delete_link() {
2090
  * activity comment.
2091
  */
2092
  function bp_get_activity_comment_delete_link() {
2093
- $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' );
2094
 
2095
  /**
2096
  * Filters the link used for deleting the activity comment currently being displayed.
@@ -2136,10 +2136,12 @@ function bp_activity_comment_content() {
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
  /**
@@ -2227,19 +2229,61 @@ function bp_activity_comment_count() {
2227
  * Output the depth of the current activity comment.
2228
  *
2229
  * @since 2.0.0
 
 
 
 
2230
  */
2231
- function bp_activity_comment_depth() {
2232
- echo bp_activity_get_comment_depth();
2233
  }
 
2234
  /**
2235
  * Return the current activity comment depth.
2236
  *
2237
  * @since 2.0.0
 
2238
  *
2239
- * @return int $depth Depth for the current activity comment.
 
 
2240
  */
2241
- function bp_activity_get_comment_depth() {
2242
- global $activities_template;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2243
 
2244
  /**
2245
  * Filters the comment depth of the current activity comment.
@@ -2248,7 +2292,7 @@ function bp_activity_comment_depth() {
2248
  *
2249
  * @param int $depth Depth for the current activity comment.
2250
  */
2251
- return apply_filters( 'bp_activity_get_comment_depth', $activities_template->activity->current_comment->depth );
2252
  }
2253
 
2254
  /**
@@ -2300,8 +2344,8 @@ function bp_activity_comment_form_nojs_display() {
2300
  *
2301
  * @global object $activities_template {@link BP_Activity_Template}
2302
  *
2303
- * @return string|bool The activity comment form no JavaScript
2304
- * display CSS. False on failure.
2305
  */
2306
  function bp_get_activity_comment_form_nojs_display() {
2307
  global $activities_template;
@@ -2420,25 +2464,18 @@ function bp_activity_comment_permalink() {
2420
  *
2421
  * @since 1.8.0
2422
  *
2423
- *
2424
  * @return string $link The activity comment permalink.
2425
  */
2426
  function bp_get_activity_comment_permalink() {
2427
  global $activities_template;
2428
 
2429
- // Check that comment exists.
 
 
2430
  $comment_id = isset( $activities_template->activity->current_comment->id )
2431
  ? $activities_template->activity->current_comment->id
2432
  : 0;
2433
 
2434
- // Setup the comment link.
2435
- $comment_link = ! empty( $comment_id )
2436
- ? '#acomment-' .$comment_id
2437
- : false;
2438
-
2439
- // Append comment ID to end of activity permalink.
2440
- $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity ) . $comment_link;
2441
-
2442
  /**
2443
  * Filters the activity comment permalink.
2444
  *
@@ -2701,7 +2738,7 @@ function bp_activity_latest_update( $user_id = 0 ) {
2701
  * @param string $value The excerpt for the latest update.
2702
  * @param int $user_id ID of the queried user.
2703
  */
2704
- $latest_update = apply_filters( 'bp_get_activity_latest_update_excerpt', trim( strip_tags( bp_create_excerpt( $update['content'], 358 ) ) ), $user_id );
2705
 
2706
  $latest_update = sprintf(
2707
  '%s <a href="%s">%s</a>',
@@ -2891,7 +2928,7 @@ function bp_activity_can_comment_reply( $comment = false ) {
2891
  // Fall back on current comment in activity loop.
2892
  $comment_depth = isset( $comment->depth )
2893
  ? intval( $comment->depth )
2894
- : bp_activity_get_comment_depth();
2895
 
2896
  // Threading is turned on, so check the depth.
2897
  if ( get_option( 'thread_comments' ) ) {
@@ -2909,7 +2946,7 @@ function bp_activity_can_comment_reply( $comment = false ) {
2909
  * @since 1.5.0
2910
  *
2911
  * @param bool $can_comment Status on if activity reply can be commented on.
2912
- * @param string $comment Current comment being checked on.
2913
  */
2914
  return (bool) apply_filters( 'bp_activity_can_comment_reply', $can_comment, $comment );
2915
  }
@@ -3169,8 +3206,6 @@ function bp_send_public_message_button( $args = '' ) {
3169
  * @type string $wrapper_id Default: 'post-mention'.
3170
  * @type string $link_href Default: the public message link for
3171
  * the current member in the loop.
3172
- * @type string $link_title Default: 'Send a public message on your
3173
- * activity stream.'.
3174
  * @type string $link_text Default: 'Public Message'.
3175
  * @type string $link_class Default: 'activity-button mention'.
3176
  * }
@@ -3185,7 +3220,6 @@ function bp_send_public_message_button( $args = '' ) {
3185
  'block_self' => true,
3186
  'wrapper_id' => 'post-mention',
3187
  'link_href' => bp_get_send_public_message_link(),
3188
- 'link_title' => __( 'Send a public message on your activity stream.', 'buddypress' ),
3189
  'link_text' => __( 'Public Message', 'buddypress' ),
3190
  'link_class' => 'activity-button mention'
3191
  ) );
@@ -3806,45 +3840,15 @@ function bp_activity_show_filters( $context = '' ) {
3806
  * @return string HTML for <option> values.
3807
  */
3808
  function bp_get_activity_show_filters( $context = '' ) {
3809
- // Set default context based on current page.
3810
- if ( empty( $context ) ) {
3811
-
3812
- // On member pages, default to 'member', unless this
3813
- // is a user's Groups activity.
3814
- if ( bp_is_user() ) {
3815
- if ( bp_is_active( 'groups' ) && bp_is_current_action( bp_get_groups_slug() ) ) {
3816
- $context = 'member_groups';
3817
- } else {
3818
- $context = 'member';
3819
- }
3820
-
3821
- // On individual group pages, default to 'group'.
3822
- } elseif ( bp_is_active( 'groups' ) && bp_is_group() ) {
3823
- $context = 'group';
3824
-
3825
- // 'activity' everywhere else.
3826
- } else {
3827
- $context = 'activity';
3828
- }
3829
- }
3830
-
3831
  $filters = array();
3832
-
3833
- // Walk through the registered actions, and prepare an the
3834
- // select box options.
3835
- foreach ( bp_activity_get_actions() as $actions ) {
3836
- foreach ( $actions as $action ) {
3837
- if ( ! in_array( $context, (array) $action['context'] ) ) {
3838
- continue;
3839
- }
3840
-
3841
- // Friends activity collapses two filters into one.
3842
- if ( in_array( $action['key'], array( 'friendship_accepted', 'friendship_created' ) ) ) {
3843
- $action['key'] = 'friendship_accepted,friendship_created';
3844
- }
3845
-
3846
- $filters[ $action['key'] ] = $action['label'];
3847
  }
 
 
3848
  }
3849
 
3850
  /**
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
13
  /**
14
  * Output the activity component slug.
15
  *
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, profile_updated.
270
+ 'primary_id' => $primary_id, // Object ID to filter on e.g. a group_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.
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
  }
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
  }
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
  *
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
 
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 bp-tooltip" data-bp-tooltip="%3$s">%4$s</a>',
1497
  $new_content,
1498
  $activity_permalink,
1499
  esc_attr__( 'View Discussion', 'buddypress' ),
1533
  *
1534
  * @global object $activities_template {@link BP_Activity_Template}
1535
  *
1536
+ * @param false|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 ) {
2090
  * activity comment.
2091
  */
2092
  function bp_get_activity_comment_delete_link() {
2093
+ $link = wp_nonce_url( trailingslashit( 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.
2136
  * Filters the content of the current activity comment.
2137
  *
2138
  * @since 1.2.0
2139
+ * @since 3.0.0 Added $context parameter to disambiguate from bp_get_activity_comment_content().
2140
  *
2141
  * @param string $content The content of the current activity comment.
2142
+ * @param string $context This filter's context ("get").
2143
  */
2144
+ return apply_filters( 'bp_activity_comment_content', $content, 'get' );
2145
  }
2146
 
2147
  /**
2229
  * Output the depth of the current activity comment.
2230
  *
2231
  * @since 2.0.0
2232
+ * @since 2.8.0 Added $comment as a parameter.
2233
+ *
2234
+ * @param object|int $comment Object of the activity comment or activity comment ID. Usually unnecessary
2235
+ * when used in activity comment loop.
2236
  */
2237
+ function bp_activity_comment_depth( $comment = 0 ) {
2238
+ echo bp_activity_get_comment_depth( $comment );
2239
  }
2240
+
2241
  /**
2242
  * Return the current activity comment depth.
2243
  *
2244
  * @since 2.0.0
2245
+ * @since 2.8.0 Added $comment as a parameter.
2246
  *
2247
+ * @param object|int $comment Object of the activity comment or activity comment ID. Usually unnecessary
2248
+ * when used in activity comment loop.
2249
+ * @return int
2250
  */
2251
+ function bp_activity_get_comment_depth( $comment = 0 ) {
2252
+ $depth = 0;
2253
+
2254
+ // Activity comment loop takes precedence.
2255
+ if ( isset( $GLOBALS['activities_template']->activity->current_comment->depth ) ) {
2256
+ $depth = $GLOBALS['activities_template']->activity->current_comment->depth;
2257
+
2258
+ // Get depth for activity comment manually.
2259
+ } elseif ( ! empty( $comment ) ) {
2260
+ // We passed an activity ID, so fetch the activity object.
2261
+ if ( is_int( $comment ) ) {
2262
+ $comment = new BP_Activity_Activity( $comment );
2263
+ }
2264
+
2265
+ // Recurse through activity tree to find the depth.
2266
+ if ( is_object( $comment ) && isset( $comment->type ) && 'activity_comment' === $comment->type ) {
2267
+ // Fetch the entire root comment tree... ugh.
2268
+ $comments = BP_Activity_Activity::get_activity_comments( $comment->item_id, 1, constant( 'PHP_INT_MAX' ) );
2269
+
2270
+ // Recursively find our comment object from the comment tree.
2271
+ $iterator = new RecursiveArrayIterator( $comments );
2272
+ $recursive = new RecursiveIteratorIterator( $iterator, RecursiveIteratorIterator::SELF_FIRST );
2273
+ foreach ( $recursive as $cid => $cobj ) {
2274
+ // Skip items that are not a comment object.
2275
+ if ( ! is_numeric( $cid ) || ! is_object( $cobj ) ) {
2276
+ continue;
2277
+ }
2278
+
2279
+ // We found the activity comment! Set the depth.
2280
+ if ( $cid === $comment->id && isset( $cobj->depth ) ) {
2281
+ $depth = $cobj->depth;
2282
+ break;
2283
+ }
2284
+ }
2285
+ }
2286
+ }
2287
 
2288
  /**
2289
  * Filters the comment depth of the current activity comment.
2292
  *
2293
  * @param int $depth Depth for the current activity comment.
2294
  */
2295
+ return apply_filters( 'bp_activity_get_comment_depth', $depth );
2296
  }
2297
 
2298
  /**
2344
  *
2345
  * @global object $activities_template {@link BP_Activity_Template}
2346
  *
2347
+ * @return string|false The activity comment form no JavaScript
2348
+ * display CSS. False on failure.
2349
  */
2350
  function bp_get_activity_comment_form_nojs_display() {
2351
  global $activities_template;
2464
  *
2465
  * @since 1.8.0
2466
  *
 
2467
  * @return string $link The activity comment permalink.
2468
  */
2469
  function bp_get_activity_comment_permalink() {
2470
  global $activities_template;
2471
 
2472
+ $link = bp_activity_get_permalink( $activities_template->activity->id, $activities_template->activity );
2473
+
2474
+ // Used for filter below.
2475
  $comment_id = isset( $activities_template->activity->current_comment->id )
2476
  ? $activities_template->activity->current_comment->id
2477
  : 0;
2478
 
 
 
 
 
 
 
 
 
2479
  /**
2480
  * Filters the activity comment permalink.
2481
  *
2738
  * @param string $value The excerpt for the latest update.
2739
  * @param int $user_id ID of the queried user.
2740
  */
2741
+ $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 );
2742
 
2743
  $latest_update = sprintf(
2744
  '%s <a href="%s">%s</a>',
2928
  // Fall back on current comment in activity loop.
2929
  $comment_depth = isset( $comment->depth )
2930
  ? intval( $comment->depth )
2931
+ : bp_activity_get_comment_depth( $comment );
2932
 
2933
  // Threading is turned on, so check the depth.
2934
  if ( get_option( 'thread_comments' ) ) {
2946
  * @since 1.5.0
2947
  *
2948
  * @param bool $can_comment Status on if activity reply can be commented on.
2949
+ * @param object $comment Current comment object being checked on.
2950
  */
2951
  return (bool) apply_filters( 'bp_activity_can_comment_reply', $can_comment, $comment );
2952
  }
3206
  * @type string $wrapper_id Default: 'post-mention'.
3207
  * @type string $link_href Default: the public message link for
3208
  * the current member in the loop.
 
 
3209
  * @type string $link_text Default: 'Public Message'.
3210
  * @type string $link_class Default: 'activity-button mention'.
3211
  * }
3220
  'block_self' => true,
3221
  'wrapper_id' => 'post-mention',
3222
  'link_href' => bp_get_send_public_message_link(),
 
3223
  'link_text' => __( 'Public Message', 'buddypress' ),
3224
  'link_class' => 'activity-button mention'
3225
  ) );
3840
  * @return string HTML for <option> values.
3841
  */
3842
  function bp_get_activity_show_filters( $context = '' ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3843
  $filters = array();
3844
+ $actions = bp_activity_get_actions_for_context( $context );
3845
+ foreach ( $actions as $action ) {
3846
+ // Friends activity collapses two filters into one.
3847
+ if ( in_array( $action['key'], array( 'friendship_accepted', 'friendship_created' ) ) ) {
3848
+ $action['key'] = 'friendship_accepted,friendship_created';
 
 
 
 
 
 
 
 
 
 
3849
  }
3850
+
3851
+ $filters[ $action['key'] ] = $action['label'];
3852
  }
3853
 
3854
  /**
bp-activity/classes/class-bp-activity-activity.php CHANGED
@@ -185,22 +185,25 @@ class BP_Activity_Activity {
185
  wp_cache_set( $this->id, $row, 'bp_activity' );
186
  }
187
 
188
- if ( ! empty( $row ) ) {
189
- $this->id = (int) $row->id;
190
- $this->item_id = (int) $row->item_id;
191
- $this->secondary_item_id = (int) $row->secondary_item_id;
192
- $this->user_id = (int) $row->user_id;
193
- $this->primary_link = $row->primary_link;
194
- $this->component = $row->component;
195
- $this->type = $row->type;
196
- $this->action = $row->action;
197
- $this->content = $row->content;
198
- $this->date_recorded = $row->date_recorded;
199
- $this->hide_sitewide = (int) $row->hide_sitewide;
200
- $this->mptt_left = (int) $row->mptt_left;
201
- $this->mptt_right = (int) $row->mptt_right;
202
- $this->is_spam = (int) $row->is_spam;
203
- }
 
 
 
204
 
205
  // Generate dynamic 'action' when possible.
206
  $action = bp_activity_generate_action_string( $this );
@@ -223,7 +226,7 @@ class BP_Activity_Activity {
223
  *
224
  * @since 1.0.0
225
  *
226
- * @return bool True on success.
227
  */
228
  public function save() {
229
  global $wpdb;
@@ -317,6 +320,7 @@ class BP_Activity_Activity {
317
  *
318
  * @since 1.2.0
319
  * @since 2.4.0 Introduced the `$fields` parameter.
 
320
  *
321
  * @see BP_Activity_Activity::get_filter_sql() for a description of the
322
  * 'filter' parameter.
@@ -332,6 +336,7 @@ class BP_Activity_Activity {
332
  * @type string $fields Activity fields to return. Pass 'ids' to get only the activity IDs.
333
  * 'all' returns full activity objects.
334
  * @type string $sort ASC or DESC. Default: 'DESC'.
 
335
  * @type array $exclude Array of activity IDs to exclude. Default: false.
336
  * @type array $in Array of ids to limit query by (IN). Default: false.
337
  * @type array $meta_query Array of meta_query conditions. See WP_Meta_Query::queries.
@@ -373,30 +378,30 @@ class BP_Activity_Activity {
373
  10 => 'spam'
374
  );
375
 
376
- $func_args = func_get_args();
377
- $args = bp_core_parse_args_array( $old_args_keys, $func_args );
378
  }
379
 
380
  $bp = buddypress();
381
  $r = wp_parse_args( $args, array(
382
- 'page' => 1, // The current page.
383
- 'per_page' => 25, // Activity items per page.
384
- 'max' => false, // Max number of items to return.
385
- 'fields' => 'all', // Fields to include.
386
- 'sort' => 'DESC', // ASC or DESC.
387
- 'exclude' => false, // Array of ids to exclude.
388
- 'in' => false, // Array of ids to limit query by (IN).
389
- 'meta_query' => false, // Filter by activitymeta.
390
- 'date_query' => false, // Filter by date.
391
- 'filter_query' => false, // Advanced filtering - see BP_Activity_Query.
392
- 'filter' => false, // See self::get_filter_sql().
393
- 'scope' => false, // Preset activity arguments.
394
- 'search_terms' => false, // Terms to search by.
395
- 'display_comments' => false, // Whether to include activity comments.
396
- 'show_hidden' => false, // Show items marked hide_sitewide.
397
- 'spam' => 'ham_only', // Spam status.
398
- 'update_meta_cache' => true, // Whether or not to update meta cache.
399
- 'count_total' => false, // Whether or not to use count_total.
 
400
  ) );
401
 
402
  // Select conditions.
@@ -423,7 +428,7 @@ class BP_Activity_Activity {
423
 
424
  // Override some arguments if needed.
425
  if ( ! empty( $scope_query['override'] ) ) {
426
- $r = self::array_replace_recursive( $r, $scope_query['override'] );
427
  }
428
 
429
  // Advanced filtering.
@@ -451,6 +456,21 @@ class BP_Activity_Activity {
451
  if ( $r['search_terms'] ) {
452
  $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%';
453
  $where_conditions['search_sql'] = $wpdb->prepare( 'a.content LIKE %s', $search_terms_like );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
  }
455
 
456
  // Sorting.
@@ -459,6 +479,29 @@ class BP_Activity_Activity {
459
  $sort = 'DESC';
460
  }
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  // Hide Hidden Items?
463
  if ( ! $r['show_hidden'] ) {
464
  $where_conditions['hidden_sql'] = "a.hide_sitewide = 0";
@@ -542,28 +585,6 @@ class BP_Activity_Activity {
542
  */
543
  $join_sql = apply_filters( 'bp_activity_get_join_sql', $join_sql, $r, $select_sql, $from_sql, $where_sql );
544
 
545
- /**
546
- * Filters the preferred order of indexes for activity item.
547
- *
548
- * @since 1.6.0
549
- *
550
- * @param array $value Array of indexes in preferred order.
551
- */
552
- $indexes = apply_filters( 'bp_activity_preferred_index_order', array( 'user_id', 'item_id', 'secondary_item_id', 'date_recorded', 'component', 'type', 'hide_sitewide', 'is_spam' ) );
553
-
554
- foreach( $indexes as $key => $index ) {
555
- if ( false !== strpos( $where_sql, $index ) ) {
556
- $the_index = $index;
557
- break; // Take the first one we find.
558
- }
559
- }
560
-
561
- if ( !empty( $the_index ) ) {
562
- $index_hint_sql = "USE INDEX ({$the_index})";
563
- } else {
564
- $index_hint_sql = '';
565
- }
566
-
567
  // Sanitize page and per_page parameters.
568
  $page = absint( $r['page'] );
569
  $per_page = absint( $r['per_page'] );
@@ -613,9 +634,21 @@ class BP_Activity_Activity {
613
  $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 ) );
614
  }
615
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  } else {
617
  // Query first for activity IDs.
618
- $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}, a.id {$sort}";
619
 
620
  if ( ! empty( $per_page ) && ! empty( $page ) ) {
621
  // We query for $per_page + 1 items in order to
@@ -633,7 +666,23 @@ class BP_Activity_Activity {
633
  */
634
  $activity_ids_sql = apply_filters( 'bp_activity_paged_activities_sql', $activity_ids_sql, $r );
635
 
636
- $activity_ids = $wpdb->get_col( $activity_ids_sql );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
 
638
  $retval['has_more_items'] = ! empty( $per_page ) && count( $activity_ids ) > $per_page;
639
 
@@ -690,7 +739,13 @@ class BP_Activity_Activity {
690
  * @param string $sort Sort direction for query.
691
  */
692
  $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 );
693
- $total_activities = $wpdb->get_var( $total_activities_sql );
 
 
 
 
 
 
694
 
695
  if ( !empty( $r['max'] ) ) {
696
  if ( (int) $total_activities > (int) $r['max'] ) {
@@ -947,7 +1002,7 @@ class BP_Activity_Activity {
947
  * @param mixed $scope The activity scope. Accepts string or array of scopes.
948
  * @param array $r Current activity arguments. Same as those of BP_Activity_Activity::get(),
949
  * but merged with defaults.
950
- * @return array 'sql' WHERE SQL string and 'override' activity args.
951
  */
952
  public static function get_scope_query_sql( $scope = false, $r = array() ) {
953
 
@@ -1076,7 +1131,7 @@ class BP_Activity_Activity {
1076
  * @param string $action Action to filter by.
1077
  * @param string $content Content to filter by.
1078
  * @param string $date_recorded Date to filter by.
1079
- * @return int|bool Activity ID on success, false if none is found.
1080
  */
1081
  public static function get_id( $user_id, $component, $type, $item_id, $secondary_item_id, $action, $content, $date_recorded ) {
1082
  global $wpdb;
@@ -1437,7 +1492,6 @@ class BP_Activity_Activity {
1437
  }
1438
 
1439
  // Legacy query - not recommended.
1440
- $func_args = func_get_args();
1441
 
1442
  /**
1443
  * Filters if BuddyPress should use the legacy activity query.
@@ -1448,7 +1502,7 @@ class BP_Activity_Activity {
1448
  * @param BP_Activity_Activity $value Magic method referring to currently called method.
1449
  * @param array $func_args Array of the method's argument list.
1450
  */
1451
- if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, $func_args ) ) {
1452
 
1453
  /**
1454
  * Filters the MySQL prepared statement for the legacy activity query.
@@ -1658,7 +1712,7 @@ class BP_Activity_Activity {
1658
  *
1659
  * @param string $field The database field.
1660
  * @param array|bool $items The values for the IN clause, or false when none are found.
1661
- * @return string|bool
1662
  */
1663
  public static function get_in_operator_sql( $field, $items ) {
1664
  global $wpdb;
@@ -1793,7 +1847,7 @@ class BP_Activity_Activity {
1793
  // Get activities from user meta.
1794
  $favorite_activity_entries = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
1795
  if ( ! empty( $favorite_activity_entries ) ) {
1796
- return count( maybe_unserialize( $favorite_activity_entries ) );
1797
  }
1798
 
1799
  // No favorites.
@@ -1806,7 +1860,7 @@ class BP_Activity_Activity {
1806
  * @since 1.1.0
1807
  *
1808
  * @param string $content The content to filter by.
1809
- * @return int|bool The ID of the first matching item if found, otherwise false.
1810
  */
1811
  public static function check_exists_by_content( $content ) {
1812
  global $wpdb;
@@ -1833,57 +1887,4 @@ class BP_Activity_Activity {
1833
 
1834
  return $wpdb->get_var( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET hide_sitewide = 1 WHERE user_id = %d", $user_id ) );
1835
  }
1836
-
1837
- /**
1838
- * PHP-agnostic version of {@link array_replace_recursive()}.
1839
- *
1840
- * The array_replace_recursive() function is a PHP 5.3 function. BuddyPress (and
1841
- * WordPress) currently supports down to PHP 5.2, so this method is a workaround
1842
- * for PHP 5.2.
1843
- *
1844
- * Note: array_replace_recursive() supports infinite arguments, but for our use-
1845
- * case, we only need to support two arguments.
1846
- *
1847
- * Subject to removal once WordPress makes PHP 5.3.0 the minimum requirement.
1848
- *
1849
- * @since 2.2.0
1850
- *
1851
- * @see http://php.net/manual/en/function.array-replace-recursive.php#109390
1852
- *
1853
- * @param array $base Array with keys needing to be replaced.
1854
- * @param array $replacements Array with the replaced keys.
1855
- * @return array
1856
- */
1857
- protected static function array_replace_recursive( $base = array(), $replacements = array() ) {
1858
- if ( function_exists( 'array_replace_recursive' ) ) {
1859
- return array_replace_recursive( $base, $replacements );
1860
- }
1861
-
1862
- // PHP 5.2-compatible version
1863
- // http://php.net/manual/en/function.array-replace-recursive.php#109390.
1864
- foreach ( array_slice( func_get_args(), 1 ) as $replacements ) {
1865
- $bref_stack = array( &$base );
1866
- $head_stack = array( $replacements );
1867
-
1868
- do {
1869
- end( $bref_stack );
1870
-
1871
- $bref = &$bref_stack[ key( $bref_stack ) ];
1872
- $head = array_pop( $head_stack );
1873
-
1874
- unset( $bref_stack[ key($bref_stack) ] );
1875
-
1876
- foreach ( array_keys( $head ) as $key ) {
1877
- if ( isset( $key, $bref ) && is_array( $bref[$key] ) && is_array( $head[$key] ) ) {
1878
- $bref_stack[] = &$bref[ $key ];
1879
- $head_stack[] = $head[ $key ];
1880
- } else {
1881
- $bref[ $key ] = $head[ $key ];
1882
- }
1883
- }
1884
- } while( count( $head_stack ) );
1885
- }
1886
-
1887
- return $base;
1888
- }
1889
  }
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 );
226
  *
227
  * @since 1.0.0
228
  *
229
+ * @return WP_Error|bool True on success.
230
  */
231
  public function save() {
232
  global $wpdb;
320
  *
321
  * @since 1.2.0
322
  * @since 2.4.0 Introduced the `$fields` parameter.
323
+ * @since 2.9.0 Introduced the `$order_by` parameter.
324
  *
325
  * @see BP_Activity_Activity::get_filter_sql() for a description of the
326
  * 'filter' parameter.
336
  * @type string $fields Activity fields to return. Pass 'ids' to get only the activity IDs.
337
  * 'all' returns full activity objects.
338
  * @type string $sort ASC or DESC. Default: 'DESC'.
339
+ * @type string $order_by Column to order results by.
340
  * @type array $exclude Array of activity IDs to exclude. Default: false.
341
  * @type array $in Array of ids to limit query by (IN). Default: false.
342
  * @type array $meta_query Array of meta_query conditions. See WP_Meta_Query::queries.
378
  10 => 'spam'
379
  );
380
 
381
+ $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
 
382
  }
383
 
384
  $bp = buddypress();
385
  $r = wp_parse_args( $args, array(
386
+ 'page' => 1, // The current page.
387
+ 'per_page' => 25, // Activity items per page.
388
+ 'max' => false, // Max number of items to return.
389
+ 'fields' => 'all', // Fields to include.
390
+ 'sort' => 'DESC', // ASC or DESC.
391
+ 'order_by' => 'date_recorded', // Column to order by.
392
+ 'exclude' => false, // Array of ids to exclude.
393
+ 'in' => false, // Array of ids to limit query by (IN).
394
+ 'meta_query' => false, // Filter by activitymeta.
395
+ 'date_query' => false, // Filter by date.
396
+ 'filter_query' => false, // Advanced filtering - see BP_Activity_Query.
397
+ 'filter' => false, // See self::get_filter_sql().
398
+ 'scope' => false, // Preset activity arguments.
399
+ 'search_terms' => false, // Terms to search by.
400
+ 'display_comments' => false, // Whether to include activity comments.
401
+ 'show_hidden' => false, // Show items marked hide_sitewide.
402
+ 'spam' => 'ham_only', // Spam status.
403
+ 'update_meta_cache' => true, // Whether or not to update meta cache.
404
+ 'count_total' => false, // Whether or not to use count_total.
405
  ) );
406
 
407
  // Select conditions.
428
 
429
  // Override some arguments if needed.
430
  if ( ! empty( $scope_query['override'] ) ) {
431
+ $r = array_replace_recursive( $r, $scope_query['override'] );
432
  }
433
 
434
  // Advanced filtering.
456
  if ( $r['search_terms'] ) {
457
  $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%';
458
  $where_conditions['search_sql'] = $wpdb->prepare( 'a.content LIKE %s', $search_terms_like );
459
+
460
+ /**
461
+ * Filters whether or not to include users for search parameters.
462
+ *
463
+ * @since 3.0.0
464
+ *
465
+ * @param bool $value Whether or not to include user search. Default false.
466
+ */
467
+ if ( apply_filters( 'bp_activity_get_include_user_search', false ) ) {
468
+ $user_search = get_user_by( 'slug', $r['search_terms'] );
469
+ if ( false !== $user_search ) {
470
+ $user_id = $user_search->ID;
471
+ $where_conditions['search_sql'] .= $wpdb->prepare( ' OR a.user_id = %d', $user_id );
472
+ }
473
+ }
474
  }
475
 
476
  // Sorting.
479
  $sort = 'DESC';
480
  }
481
 
482
+ switch( $r['order_by'] ) {
483
+ case 'id' :
484
+ case 'user_id' :
485
+ case 'component' :
486
+ case 'type' :
487
+ case 'action' :
488
+ case 'content' :
489
+ case 'primary_link' :
490
+ case 'item_id' :
491
+ case 'secondary_item_id' :
492
+ case 'date_recorded' :
493
+ case 'hide_sitewide' :
494
+ case 'mptt_left' :
495
+ case 'mptt_right' :
496
+ case 'is_spam' :
497
+ break;
498
+
499
+ default :
500
+ $r['order_by'] = 'date_recorded';
501
+ break;
502
+ }
503
+ $order_by = 'a.' . $r['order_by'];
504
+
505
  // Hide Hidden Items?
506
  if ( ! $r['show_hidden'] ) {
507
  $where_conditions['hidden_sql'] = "a.hide_sitewide = 0";
585
  */
586
  $join_sql = apply_filters( 'bp_activity_get_join_sql', $join_sql, $r, $select_sql, $from_sql, $where_sql );
587
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
588
  // Sanitize page and per_page parameters.
589
  $page = absint( $r['page'] );
590
  $per_page = absint( $r['per_page'] );
634
  $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 ) );
635
  }
636
 
637
+ // Integer casting for legacy activity query.
638
+ foreach ( (array) $activities as $i => $ac ) {
639
+ $activities[ $i ]->id = (int) $ac->id;
640
+ $activities[ $i ]->item_id = (int) $ac->item_id;
641
+ $activities[ $i ]->secondary_item_id = (int) $ac->secondary_item_id;
642
+ $activities[ $i ]->user_id = (int) $ac->user_id;
643
+ $activities[ $i ]->hide_sitewide = (int) $ac->hide_sitewide;
644
+ $activities[ $i ]->mptt_left = (int) $ac->mptt_left;
645
+ $activities[ $i ]->mptt_right = (int) $ac->mptt_right;
646
+ $activities[ $i ]->is_spam = (int) $ac->is_spam;
647
+ }
648
+
649
  } else {
650
  // Query first for activity IDs.
651
+ $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY {$order_by} {$sort}, a.id {$sort}";
652
 
653
  if ( ! empty( $per_page ) && ! empty( $page ) ) {
654
  // We query for $per_page + 1 items in order to
666
  */
667
  $activity_ids_sql = apply_filters( 'bp_activity_paged_activities_sql', $activity_ids_sql, $r );
668
 
669
+ /*
670
+ * Queries that include 'last_activity' are cached separately,
671
+ * since they are generally much less long-lived.
672
+ */
673
+ if ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $activity_ids_sql ) ) {
674
+ $cache_group = 'bp_activity';
675
+ } else {
676
+ $cache_group = 'bp_activity_with_last_activity';
677
+ }
678
+
679
+ $cached = bp_core_get_incremented_cache( $activity_ids_sql, $cache_group );
680
+ if ( false === $cached ) {
681
+ $activity_ids = $wpdb->get_col( $activity_ids_sql );
682
+ bp_core_set_incremented_cache( $activity_ids_sql, $cache_group, $activity_ids );
683
+ } else {
684
+ $activity_ids = $cached;
685
+ }
686
 
687
  $retval['has_more_items'] = ! empty( $per_page ) && count( $activity_ids ) > $per_page;
688
 
739
  * @param string $sort Sort direction for query.
740
  */
741
  $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 );
742
+ $cached = bp_core_get_incremented_cache( $total_activities_sql, $cache_group );
743
+ if ( false === $cached ) {
744
+ $total_activities = $wpdb->get_var( $total_activities_sql );
745
+ bp_core_set_incremented_cache( $total_activities_sql, $cache_group, $total_activities );
746
+ } else {
747
+ $total_activities = $cached;
748
+ }
749
 
750
  if ( !empty( $r['max'] ) ) {
751
  if ( (int) $total_activities > (int) $r['max'] ) {
1002
  * @param mixed $scope The activity scope. Accepts string or array of scopes.
1003
  * @param array $r Current activity arguments. Same as those of BP_Activity_Activity::get(),
1004
  * but merged with defaults.
1005
+ * @return false|array 'sql' WHERE SQL string and 'override' activity args.
1006
  */
1007
  public static function get_scope_query_sql( $scope = false, $r = array() ) {
1008
 
1131
  * @param string $action Action to filter by.
1132
  * @param string $content Content to filter by.
1133
  * @param string $date_recorded Date to filter by.
1134
+ * @return int|false Activity ID on success, false if none is found.
1135
  */
1136
  public static function get_id( $user_id, $component, $type, $item_id, $secondary_item_id, $action, $content, $date_recorded ) {
1137
  global $wpdb;
1492
  }
1493
 
1494
  // Legacy query - not recommended.
 
1495
 
1496
  /**
1497
  * Filters if BuddyPress should use the legacy activity query.
1502
  * @param BP_Activity_Activity $value Magic method referring to currently called method.
1503
  * @param array $func_args Array of the method's argument list.
1504
  */
1505
+ if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, func_get_args() ) ) {
1506
 
1507
  /**
1508
  * Filters the MySQL prepared statement for the legacy activity query.
1712
  *
1713
  * @param string $field The database field.
1714
  * @param array|bool $items The values for the IN clause, or false when none are found.
1715
+ * @return string|false
1716
  */
1717
  public static function get_in_operator_sql( $field, $items ) {
1718
  global $wpdb;
1847
  // Get activities from user meta.
1848
  $favorite_activity_entries = bp_get_user_meta( $user_id, 'bp_favorite_activities', true );
1849
  if ( ! empty( $favorite_activity_entries ) ) {
1850
+ return count( $favorite_activity_entries );
1851
  }
1852
 
1853
  // No favorites.
1860
  * @since 1.1.0
1861
  *
1862
  * @param string $content The content to filter by.
1863
+ * @return int|false The ID of the first matching item if found, otherwise false.
1864
  */
1865
  public static function check_exists_by_content( $content ) {
1866
  global $wpdb;
1887
 
1888
  return $wpdb->get_var( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET hide_sitewide = 1 WHERE user_id = %d", $user_id ) );
1889
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1890
  }
bp-activity/classes/class-bp-activity-component.php CHANGED
@@ -51,30 +51,28 @@ class BP_Activity_Component extends BP_Component {
51
  // Files to include.
52
  $includes = array(
53
  'cssjs',
54
- 'actions',
55
- 'screens',
56
  'filters',
57
  'adminbar',
58
  'template',
59
  'functions',
60
- 'notifications',
61
  'cache'
62
  );
63
 
64
- if ( ! buddypress()->do_autoload ) {
65
- $includes[] = 'classes';
 
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-actions.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
 
@@ -85,6 +83,67 @@ class BP_Activity_Component extends BP_Component {
85
  parent::includes( $includes );
86
  }
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  /**
89
  * Set up component global variables.
90
  *
@@ -116,13 +175,17 @@ class BP_Activity_Component extends BP_Component {
116
  'activity' => $bp->table_prefix . 'bp_activity_meta',
117
  );
118
 
 
 
 
 
119
  // All globals for activity component.
120
  // Note that global_tables is included in this array.
121
  $args = array(
122
  'slug' => BP_ACTIVITY_SLUG,
123
  'root_slug' => isset( $bp->pages->activity->slug ) ? $bp->pages->activity->slug : BP_ACTIVITY_SLUG,
124
  'has_directory' => true,
125
- 'directory_title' => _x( 'Site-Wide Activity', 'component directory title', 'buddypress' ),
126
  'notification_callback' => 'bp_activity_format_notifications',
127
  'search_string' => __( 'Search Activity...', 'buddypress' ),
128
  'global_tables' => $global_tables,
@@ -361,19 +424,6 @@ class BP_Activity_Component extends BP_Component {
361
  parent::setup_title();
362
  }
363
 
364
- /**
365
- * Set up actions necessary for the component.
366
- *
367
- * @since 1.6.0
368
- */
369
- public function setup_actions() {
370
-
371
- // Spam prevention.
372
- add_action( 'bp_include', 'bp_activity_setup_akismet' );
373
-
374
- parent::setup_actions();
375
- }
376
-
377
  /**
378
  * Setup cache groups.
379
  *
51
  // Files to include.
52
  $includes = array(
53
  'cssjs',
 
 
54
  'filters',
55
  'adminbar',
56
  'template',
57
  'functions',
 
58
  'cache'
59
  );
60
 
61
+ // Notifications support.
62
+ if ( bp_is_active( 'notifications' ) ) {
63
+ $includes[] = 'notifications';
64
  }
65
 
66
  // Load Akismet support if Akismet is configured.
67
  $akismet_key = bp_get_option( 'wordpress_api_key' );
68
 
69
+ /** This filter is documented in bp-activity/bp-activity-akismet.php */
70
  if ( defined( 'AKISMET_VERSION' ) && class_exists( 'Akismet' ) && ( ! empty( $akismet_key ) || defined( 'WPCOM_API_KEY' ) ) && apply_filters( 'bp_activity_use_akismet', bp_is_akismet_active() ) ) {
71
  $includes[] = 'akismet';
72
  }
73
 
74
+ // Embeds
75
+ if ( bp_is_active( $this->id, 'embeds' ) ) {
76
  $includes[] = 'embeds';
77
  }
78
 
83
  parent::includes( $includes );
84
  }
85
 
86
+ /**
87
+ * Late includes method.
88
+ *
89
+ * Only load up certain code when on specific pages.
90
+ *
91
+ * @since 3.0.0
92
+ */
93
+ public function late_includes() {
94
+ // Bail if PHPUnit is running.
95
+ if ( defined( 'BP_TESTS_DIR' ) ) {
96
+ return;
97
+ }
98
+
99
+ /*
100
+ * Load activity action and screen code if PHPUnit isn't running.
101
+ *
102
+ * For PHPUnit, we load these files in tests/phpunit/includes/install.php.
103
+ */
104
+ if ( bp_is_current_component( 'activity' ) ) {
105
+ // Authenticated actions - Only fires when JS is disabled.
106
+ if ( is_user_logged_in() &&
107
+ in_array( bp_current_action(), array( 'delete', 'spam', 'post', 'reply', 'favorite', 'unfavorite' ), true )
108
+ ) {
109
+ require $this->path . 'bp-activity/actions/' . bp_current_action() . '.php';
110
+ }
111
+
112
+ // RSS feeds.
113
+ if ( bp_is_current_action( 'feed' ) || bp_is_action_variable( 'feed', 0 ) ) {
114
+ require $this->path . 'bp-activity/actions/feeds.php';
115
+ }
116
+
117
+ // Screens - Directory.
118
+ if ( bp_is_activity_directory() ) {
119
+ require $this->path . 'bp-activity/screens/directory.php';
120
+ }
121
+
122
+ // Screens - User main nav.
123
+ if ( bp_is_user() ) {
124
+ require $this->path . 'bp-activity/screens/just-me.php';
125
+ }
126
+
127
+ // Screens - User secondary nav.
128
+ if ( bp_is_user() && in_array( bp_current_action(), array( 'friends', 'groups', 'favorites', 'mentions' ), true ) ) {
129
+ require $this->path . 'bp-activity/screens/' . bp_current_action() . '.php';
130
+ }
131
+
132
+ // Screens - Single permalink.
133
+ if ( bp_is_current_action( 'p' ) || is_numeric( bp_current_action() ) ) {
134
+ require $this->path . 'bp-activity/screens/permalink.php';
135
+ }
136
+
137
+ // Theme compatibility.
138
+ new BP_Activity_Theme_Compat();
139
+ }
140
+
141
+ // Activity notifications HTML table.
142
+ if ( bp_is_user_settings_notifications() ) {
143
+ require $this->path . 'bp-activity/screens/settings-email.php';
144
+ }
145
+ }
146
+
147
  /**
148
  * Set up component global variables.
149
  *
175
  'activity' => $bp->table_prefix . 'bp_activity_meta',
176
  );
177
 
178
+ // Fetch the default directory title.
179
+ $default_directory_titles = bp_core_get_directory_page_default_titles();
180
+ $default_directory_title = $default_directory_titles[$this->id];
181
+
182
  // All globals for activity component.
183
  // Note that global_tables is included in this array.
184
  $args = array(
185
  'slug' => BP_ACTIVITY_SLUG,
186
  'root_slug' => isset( $bp->pages->activity->slug ) ? $bp->pages->activity->slug : BP_ACTIVITY_SLUG,
187
  'has_directory' => true,
188
+ 'directory_title' => isset( $bp->pages->activity->title ) ? $bp->pages->activity->title : $default_directory_title,
189
  'notification_callback' => 'bp_activity_format_notifications',
190
  'search_string' => __( 'Search Activity...', 'buddypress' ),
191
  'global_tables' => $global_tables,
424
  parent::setup_title();
425
  }
426
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  /**
428
  * Setup cache groups.
429
  *
bp-activity/classes/class-bp-activity-list-table.php CHANGED
@@ -47,7 +47,7 @@ class BP_Activity_List_Table extends WP_List_Table {
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
  *
@@ -63,7 +63,7 @@ class BP_Activity_List_Table extends WP_List_Table {
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.
@@ -171,7 +171,7 @@ class BP_Activity_List_Table extends WP_List_Table {
171
  $activities['total'] = count( $activities['activities'] );
172
 
173
  // Sort the array by the activity object's date_recorded value.
174
- usort( $activities['activities'], create_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.
@@ -428,8 +428,26 @@ class BP_Activity_List_Table extends WP_List_Table {
428
  <option value="" <?php selected( ! $selected ); ?>><?php _e( 'View all actions', 'buddypress' ); ?></option>
429
 
430
  <?php foreach ( $activity_actions as $component => $actions ) : ?>
431
-
432
- <optgroup label="<?php echo ucfirst( $component ); ?>">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
 
434
  <?php foreach ( $actions as $action_key => $action_values ) : ?>
435
 
@@ -497,6 +515,7 @@ class BP_Activity_List_Table extends WP_List_Table {
497
  * @param array $item A singular item (one full row).
498
  */
499
  function column_cb( $item ) {
 
500
  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'] );
501
  }
502
 
@@ -573,7 +592,7 @@ class BP_Activity_List_Table extends WP_List_Table {
573
  if ( $this->can_comment( $item ) ) {
574
  $actions['reply'] = sprintf( '<a href="#" class="reply hide-if-no-js">%s</a>', __( 'Reply', 'buddypress' ) );
575
  } else {
576
- $actions['reply'] = sprintf( '<span class="form-input-tip" title="%s">%s</span>', __( 'Replies are disabled for this activity item', 'buddypress' ), __( 'Replies disabled', 'buddypress' ) );
577
  }
578
 
579
  // Edit.
@@ -622,15 +641,10 @@ class BP_Activity_List_Table extends WP_List_Table {
622
 
623
  // Get activity content - if not set, use the action.
624
  if ( ! empty( $item['content'] ) ) {
 
625
 
626
- /**
627
- * Filters current activity item content.
628
- *
629
- * @since 1.2.0
630
- *
631
- * @param array $item Array index holding current activity item content.
632
- */
633
- $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $item['content'] ) );
634
  } else {
635
  /**
636
  * Filters current activity item action.
@@ -692,8 +706,7 @@ class BP_Activity_List_Table extends WP_List_Table {
692
 
693
  // If the activity has comments, display a link to the activity's permalink, with its comment count in a speech bubble.
694
  if ( $comment_count ) {
695
- $title_attr = sprintf( _n( '%s related activity', '%s related activities', $comment_count, 'buddypress' ), number_format_i18n( $comment_count ) );
696
- 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 ) );
697
  }
698
 
699
  // For non-root activities, display a link to the replied-to activity's author's profile.
@@ -793,6 +806,7 @@ class BP_Activity_List_Table extends WP_List_Table {
793
  $parent_activity = (object) $item;
794
  } elseif ( 'activity_comment' === $item['type'] ) {
795
  $parent_activity = new BP_Activity_Activity( $item['item_id'] );
 
796
  }
797
 
798
  if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
47
  protected $activity_user_id = array();
48
 
49
  /**
50
+ * If users can comment on post and comment activity items.
51
  *
52
  * @link https://buddypress.trac.wordpress.org/ticket/6277
53
  *
63
  */
64
  public function __construct() {
65
 
66
+ // See if activity commenting is enabled for post/comment 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.
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.
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
 
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
 
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">%s</span>', __( 'Replies disabled', 'buddypress' ) );
596
  }
597
 
598
  // Edit.
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.
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
+ printf( '<a href="%1$s" class="post-com-count post-com-count-approved"><span class="comment-count comment-count-approved">%2$s</span></a>', esc_url( $root_activity_url ), number_format_i18n( $comment_count ) );
 
710
  }
711
 
712
  // For non-root activities, display a link to the replied-to activity's author's profile.
806
  $parent_activity = (object) $item;
807
  } elseif ( 'activity_comment' === $item['type'] ) {
808
  $parent_activity = new BP_Activity_Activity( $item['item_id'] );
809
+ $can_comment = bp_activity_can_comment_reply( (object) $item );
810
  }
811
 
812
  if ( isset( $parent_activity->type ) && bp_activity_post_type_get_tracking_arg( $parent_activity->type, 'post_type' ) ) {
bp-activity/classes/class-bp-activity-oembed-extension.php CHANGED
@@ -311,7 +311,9 @@ class BP_Activity_oEmbed_Extension extends BP_Core_oEmbed_Extension {
311
  <?php
312
  printf(
313
  _n(
 
314
  '%s <span class="screen-reader-text">Comment</span>',
 
315
  '%s <span class="screen-reader-text">Comments</span>',
316
  $count,
317
  'buddypress'
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'
bp-activity/classes/class-bp-activity-query.php CHANGED
@@ -46,7 +46,7 @@ class BP_Activity_Query extends BP_Recursive_Query {
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
 
46
  * @var array
47
  */
48
  public $db_columns = array(
49
+ 'id', 'user_id', 'component', 'type', 'action', 'content', 'primary_link',
50
  'item_id', 'secondary_item_id', 'hide_sitewide', 'is_spam',
51
  );
52
 
bp-activity/classes/class-bp-activity-template.php CHANGED
@@ -159,8 +159,7 @@ class BP_Activity_Template {
159
  12 => 'page_arg'
160
  );
161
 
162
- $func_args = func_get_args();
163
- $args = bp_core_parse_args_array( $old_args_keys, $func_args );
164
  }
165
 
166
  $defaults = array(
@@ -192,11 +191,11 @@ class BP_Activity_Template {
192
  $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page'] );
193
  $this->pag_num = bp_sanitize_pagination_arg( 'num', $r['per_page'] );
194
 
195
- // Check if blog/forum replies are disabled.
196
  $this->disable_blogforum_replies = (bool) bp_core_get_root_option( 'bp-disable-blogforum-comments' );
197
 
198
  // Get an array of the logged in user's favorite activities.
199
- $this->my_favs = maybe_unserialize( bp_get_user_meta( bp_loggedin_user_id(), 'bp_favorite_activities', true ) );
200
 
201
  // Fetch specific activity items based on ID's.
202
  if ( !empty( $include ) ) {
159
  12 => 'page_arg'
160
  );
161
 
162
+ $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
 
163
  }
164
 
165
  $defaults = array(
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 post/comment 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 = 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 ) ) {
bp-activity/classes/class-bp-akismet.php CHANGED
@@ -411,6 +411,19 @@ class BP_Akismet {
411
 
412
  // Mark as spam.
413
  bp_activity_mark_as_spam( $activity, 'by_akismet' );
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  }
415
 
416
  // Update activity meta after a spam check.
@@ -546,11 +559,11 @@ class BP_Akismet {
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' ) )
411
 
412
  // Mark as spam.
413
  bp_activity_mark_as_spam( $activity, 'by_akismet' );
414
+
415
+ if (
416
+ Akismet::allow_discard() &&
417
+ ! empty( $activity_data['akismet_pro_tip'] ) &&
418
+ 'discard' === $activity_data['akismet_pro_tip']
419
+ ) {
420
+ // If this is so spammy it's not worth your time, let's just delete it.
421
+ if ( $activity->type === 'activity_comment' ) {
422
+ bp_activity_delete_comment( $activity->item_id, $activity->id );
423
+ } else {
424
+ bp_activity_delete( array( 'id' => $activity->id ) );
425
+ }
426
+ }
427
  }
428
 
429
  // Update activity meta after a spam check.
559
  $response = Akismet::http_post( $query_string, $path );
560
  remove_filter( 'akismet_ua', array( $this, 'buddypress_ua' ) );
561
 
562
+ // Save response data.
563
+ $activity_data['bp_as_result'] = $response[1];
564
+ if ( isset( $response[0]['x-akismet-pro-tip'] ) ) {
565
+ $activity_data['akismet_pro_tip'] = $response[0]['x-akismet-pro-tip'];
566
+ }
567
 
568
  // Perform a daily tidy up.
569
  if ( ! wp_next_scheduled( 'bp_activity_akismet_delete_old_metadata' ) )
bp-activity/css/mentions-rtl.css CHANGED
@@ -2,8 +2,8 @@
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;
@@ -14,14 +14,16 @@
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;
@@ -32,59 +34,71 @@
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;
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;
14
  .atwho-view {
15
  left: 0;
16
  }
17
+
18
  .atwho-view ul {
19
+ background: #fff;
20
  list-style: none;
21
  margin: auto;
22
  padding: 0;
23
  }
24
+
25
  .atwho-view ul li {
26
+ border-bottom: 1px solid #efefef;
27
  box-sizing: content-box;
28
  cursor: pointer;
29
  display: block;
34
  overflow: hidden;
35
  padding: 5px 10px;
36
  }
37
+
38
  .atwho-view img {
39
  border-radius: 2px;
40
  float: left;
41
  height: 20px;
42
+ margin-top: 0;
43
  width: 20px;
44
  }
45
+
46
  .atwho-view strong {
47
+ background: #efefef;
48
+ font-weight: 700;
49
  }
50
+
51
  .atwho-view .username strong {
52
+ color: #d54e21;
53
  }
54
+
55
  .atwho-view small {
56
+ color: #aaa;
57
  float: left;
58
  font-size: smaller;
59
+ font-weight: 400;
60
  margin: 0 40px 0 10px;
61
  }
62
+
63
  .atwho-view .cur {
64
  background: rgba(239, 239, 239, 0.5);
65
  }
66
 
67
  @media (max-width: 900px) {
68
+
69
  .atwho-view img {
70
  float: right;
71
  margin: 0 0 0 10px;
72
  }
73
  }
74
+
75
  @media (max-width: 400px) {
76
+
77
  .atwho-view ul li {
78
  font-size: 16px;
79
  line-height: 23px;
80
  padding: 13px;
81
  }
82
+
83
  .atwho-view ul li img {
84
  height: 30px;
85
  margin-top: -5px;
86
  width: 30px;
87
  }
88
+
89
  .atwho-view {
90
  border-radius: 0;
91
  height: 100%;
92
  right: 0 !important;
93
  width: 100%;
94
  }
95
+
96
  .atwho-view ul li .username {
97
  display: inline-block;
98
  margin: -10px 0 0 0;
99
  padding: 10px 0;
100
  }
101
+
102
  .atwho-view ul li small {
103
  display: inline-block;
104
  margin-right: 20px;
bp-activity/css/mentions-rtl.min.css CHANGED
@@ -1 +1 @@
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}}
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}.atwho-view{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 0;padding:10px 0}.atwho-view ul li small{display:inline-block;margin-right:20px}}
bp-activity/css/mentions.css CHANGED
@@ -2,8 +2,8 @@
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;
@@ -11,18 +11,21 @@
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;
@@ -33,59 +36,71 @@
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;
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;
11
  top: 0;
12
  z-index: 1000; /* >999 for wp-admin */
13
  }
14
+
15
  /* rtl:ignore */
16
  .atwho-view {
17
  left: 0;
18
  }
19
+
20
  .atwho-view ul {
21
+ background: #fff;
22
  list-style: none;
23
  margin: auto;
24
  padding: 0;
25
  }
26
+
27
  .atwho-view ul li {
28
+ border-bottom: 1px solid #efefef;
29
  box-sizing: content-box;
30
  cursor: pointer;
31
  display: block;
36
  overflow: hidden;
37
  padding: 5px 10px;
38
  }
39
+
40
  .atwho-view img {
41
  border-radius: 2px;
42
  float: right;
43
  height: 20px;
44
+ margin-top: 0;
45
  width: 20px;
46
  }
47
+
48
  .atwho-view strong {
49
+ background: #efefef;
50
+ font-weight: 700;
51
  }
52
+
53
  .atwho-view .username strong {
54
+ color: #d54e21;
55
  }
56
+
57
  .atwho-view small {
58
+ color: #aaa;
59
  float: right;
60
  font-size: smaller;
61
+ font-weight: 400;
62
  margin: 0 10px 0 40px;
63
  }
64
+
65
  .atwho-view .cur {
66
  background: rgba(239, 239, 239, 0.5);
67
  }
68
 
69
  @media (max-width: 900px) {
70
+
71
  .atwho-view img {
72
  float: left;
73
  margin: 0 10px 0 0;
74
  }
75
  }
76
+
77
  @media (max-width: 400px) {
78
+
79
  .atwho-view ul li {
80
  font-size: 16px;
81
  line-height: 23px;
82
  padding: 13px;
83
  }
84
+
85
  .atwho-view ul li img {
86
  height: 30px;
87
  margin-top: -5px;
88
  width: 30px;
89
  }
90
+
91
  .atwho-view {
92
  border-radius: 0;
93
  height: 100%;
94
  left: 0 !important;
95
  width: 100%;
96
  }
97
+
98
  .atwho-view ul li .username {
99
  display: inline-block;
100
  margin: -10px 0 0 0;
101
  padding: 10px 0;
102
  }
103
+
104
  .atwho-view ul li small {
105
  display: inline-block;
106
  margin-left: 20px;
bp-activity/css/mentions.min.css CHANGED
@@ -1 +1 @@
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}}
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}.atwho-view{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 0;padding:10px 0}.atwho-view ul li small{display:inline-block;margin-left:20px}}
bp-activity/js/mentions.js CHANGED
@@ -28,12 +28,12 @@ window.bp = window.bp || {};
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
  /**
@@ -160,8 +160,9 @@ window.bp = window.bp || {};
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
 
@@ -230,8 +231,8 @@ window.bp = window.bp || {};
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 );
28
  * Default options for at.js; see https://github.com/ichord/At.js/.
29
  */
30
  var suggestionsDefaults = {
31
+ delay: 200,
32
+ hideWithoutSuffix: true,
33
+ insertTpl: '@${ID}',
34
+ limit: 10,
35
+ startWithSpace: false,
36
+ suffix: '',
37
 
38
  callbacks: {
39
  /**
160
  * @param {string} query Partial @mention to search for.
161
  * @param {function} render_view Render page callback function.
162
  * @since 2.1.0
163
+ * @since 3.0.0. Renamed from "remote_filter" for at.js v1.5.4 support.
164
  */
165
+ remoteFilter: function( query, render_view ) {
166
  var self = $( this ),
167
  params = {};
168
 
231
  ),
232
 
233
  at: '@',
234
+ searchKey: 'search',
235
+ displayTpl: '<li data-value="@${ID}"><img src="${image}" /><span class="username">@${ID}</span><small>${name}</small></li>'
236
  },
237
 
238
  opts = $.extend( true, {}, suggestionsDefaults, mentionsDefaults, options );
bp-activity/js/mentions.min.js CHANGED
@@ -1 +1 @@
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;f>e;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||5>d)&&(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);
1
+ window.bp=window.bp||{},function(t,e,i){var n,s=[];t.mentions=t.mentions||{},t.mentions.users=window.bp.mentions.users||[],"object"==typeof window.BP_Suggestions&&(t.mentions.users=window.BP_Suggestions.friends||t.mentions.users),e.fn.bp_mentions=function(t){e.isArray(t)&&(t={data:t});var i={delay:200,hideWithoutSuffix:!0,insertTpl:"@${ID}",limit:10,startWithSpace:!1,suffix:"",callbacks:{filter:function(t,e,i){var n,s,r,o=[],a=new RegExp("^"+t+"| "+t,"ig");for(s=0,r=e.length;s<r;s++)(n=e[s])[i].toLowerCase().match(a)&&o.push(n);return o},highlighter:function(t,e){if(!e)return t;var i=new RegExp(">(\\s*|[\\w\\s]*)("+this.at.replace("+","\\+")+"?"+e.replace("+","\\+")+")([\\w ]*)\\s*<","ig");return t.replace(i,function(t,e,i,n){return">"+e+"<strong>"+i+"</strong>"+n+"<"})},before_reposition:function(t){var i,n,s,r,o=e("#atwho-ground-"+this.id+" .atwho-view"),a=e("body"),u=this.$inputor.data("atwho");"undefined"!==u&&"undefined"!==u.iframe&&null!==u.iframe?(i=this.$inputor.caret("offset",{iframe:u.iframe}),"undefined"!==(s=e(u.iframe).offset())&&(i.left+=s.left,i.top+=s.top)):i=this.$inputor.caret("offset"),i.left>a.width()/2?(o.addClass("right"),r=i.left-t.left-this.view.$el.width()):(o.removeClass("right"),r=i.left-t.left+1),a.width()<=400&&e(document).scrollTop(i.top-6),(!(n=parseInt(this.$inputor.css("line-height").substr(0,this.$inputor.css("line-height").length-2),10))||n<5)&&(n=19),t.top=i.top+n,t.left+=r},inserting_wrapper:function(t,e,i){return""+e+i}}},r={callbacks:{remoteFilter:function(t,i){var r=e(this),o={};"object"!=typeof(n=s[t])?(r.xhr&&r.xhr.abort(),o={action:"bp_get_suggestions",term:t,type:"members"},e.isNumeric(this.$inputor.data("suggestions-group-id"))&&(o["group-id"]=parseInt(this.$inputor.data("suggestions-group-id"),10)),r.xhr=e.getJSON(ajaxurl,o).done(function(n){if(n.success){var r=e.map(n.data,function(t){return t.search=t.search||t.ID+" "+t.name,t});s[t]=r,i(r)}})):i(n)}},data:e.map(t.data,function(t){return t.search=t.search||t.ID+" "+t.name,t}),at:"@",searchKey:"search",displayTpl:'<li data-value="@${ID}"><img src="${image}" /><span class="username">@${ID}</span><small>${name}</small></li>'},o=e.extend(!0,{},i,r,t);return e.fn.atwho.call(this,o)},e(document).ready(function(){e(".bp-suggestions, #comments form textarea, .wp-editor-area").bp_mentions(t.mentions.users)}),t.mentions.tinyMCEinit=function(){void 0!==window.tinyMCE&&null!==window.tinyMCE.activeEditor&&void 0!==window.tinyMCE.activeEditor&&e(window.tinyMCE.activeEditor.contentDocument.activeElement).atwho("setIframe",e(".wp-editor-wrap iframe")[0]).bp_mentions(t.mentions.users)}}(bp,jQuery);
bp-activity/screens/directory.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Directory screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the Activity directory.
12
+ *
13
+ * @since 1.5.0
14
+ *
15
+ */
16
+ function bp_activity_screen_index() {
17
+ if ( bp_is_activity_directory() ) {
18
+ bp_update_is_directory( true, 'activity' );
19
+
20
+ /**
21
+ * Fires right before the loading of the Activity directory screen template file.
22
+ *
23
+ * @since 1.5.0
24
+ */
25
+ do_action( 'bp_activity_screen_index' );
26
+
27
+ /**
28
+ * Filters the template to load for the Activity directory screen.
29
+ *
30
+ * @since 1.5.0
31
+ *
32
+ * @param string $template Path to the activity template to load.
33
+ */
34
+ bp_core_load_template( apply_filters( 'bp_activity_screen_index', 'activity/index' ) );
35
+ }
36
+ }
37
+ add_action( 'bp_screens', 'bp_activity_screen_index' );
bp-activity/screens/favorites.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: User's "Activity > Favorites" screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the 'Favorites' activity page.
12
+ *
13
+ * @since 1.2.0
14
+ */
15
+ function bp_activity_screen_favorites() {
16
+ bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
17
+
18
+ /**
19
+ * Fires right before the loading of the "Favorites" screen template file.
20
+ *
21
+ * @since 1.2.0
22
+ */
23
+ do_action( 'bp_activity_screen_favorites' );
24
+
25
+ /**
26
+ * Filters the template to load for the "Favorites" screen.
27
+ *
28
+ * @since 1.2.0
29
+ *
30
+ * @param string $template Path to the activity template to load.
31
+ */
32
+ bp_core_load_template( apply_filters( 'bp_activity_template_favorite_activity', 'members/single/home' ) );
33
+ }
bp-activity/screens/friends.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: User's "Activity > Friends" screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the 'My Friends' activity page.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ function bp_activity_screen_friends() {
16
+ if ( !bp_is_active( 'friends' ) )
17
+ return false;
18
+
19
+ bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
20
+
21
+ /**
22
+ * Fires right before the loading of the "My Friends" screen template file.
23
+ *
24
+ * @since 1.2.0
25
+ */
26
+ do_action( 'bp_activity_screen_friends' );
27
+
28
+ /**
29
+ * Filters the template to load for the "My Friends" screen.
30
+ *
31
+ * @since 1.0.0
32
+ *
33
+ * @param string $template Path to the activity template to load.
34
+ */
35
+ bp_core_load_template( apply_filters( 'bp_activity_template_friends_activity', 'members/single/home' ) );
36
+ }
bp-activity/screens/groups.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: User's "Activity > Groups" screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the 'My Groups' activity page.
12
+ *
13
+ * @since 1.2.0
14
+ */
15
+ function bp_activity_screen_groups() {
16
+ if ( !bp_is_active( 'groups' ) )
17
+ return false;
18
+
19
+ bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
20
+
21
+ /**
22
+ * Fires right before the loading of the "My Groups" screen template file.
23
+ *
24
+ * @since 1.2.0
25
+ */
26
+ do_action( 'bp_activity_screen_groups' );
27
+
28
+ /**
29
+ * Filters the template to load for the "My Groups" screen.
30
+ *
31
+ * @since 1.2.0
32
+ *
33
+ * @param string $template Path to the activity template to load.
34
+ */
35
+ bp_core_load_template( apply_filters( 'bp_activity_template_groups_activity', 'members/single/home' ) );
36
+ }
bp-activity/screens/just-me.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: User's "Activity" screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the 'My Activity' page.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ function bp_activity_screen_my_activity() {
16
+
17
+ /**
18
+ * Fires right before the loading of the "My Activity" screen template file.
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ do_action( 'bp_activity_screen_my_activity' );
23
+
24
+ /**
25
+ * Filters the template to load for the "My Activity" screen.
26
+ *
27
+ * @since 1.0.0
28
+ *
29
+ * @param string $template Path to the activity template to load.
30
+ */
31
+ bp_core_load_template( apply_filters( 'bp_activity_template_my_activity', 'members/single/home' ) );
32
+ }
bp-activity/screens/mentions.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: User's "Activity > Mentions" screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the 'Mentions' activity page.
12
+ *
13
+ * @since 1.2.0
14
+ */
15
+ function bp_activity_screen_mentions() {
16
+ bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
17
+
18
+ /**
19
+ * Fires right before the loading of the "Mentions" screen template file.
20
+ *
21
+ * @since 1.2.0
22
+ */
23
+ do_action( 'bp_activity_screen_mentions' );
24
+
25
+ /**
26
+ * Filters the template to load for the "Mentions" screen.
27
+ *
28
+ * @since 1.2.0
29
+ *
30
+ * @param string $template Path to the activity template to load.
31
+ */
32
+ bp_core_load_template( apply_filters( 'bp_activity_template_mention_activity', 'members/single/home' ) );
33
+ }
34
+
35
+ /**
36
+ * Reset the logged-in user's new mentions data when he visits his mentions screen.
37
+ *
38
+ * @since 1.5.0
39
+ *
40
+ */
41
+ function bp_activity_reset_my_new_mentions() {
42
+ if ( bp_is_my_profile() )
43
+ bp_activity_clear_new_mentions( bp_loggedin_user_id() );
44
+ }
45
+ add_action( 'bp_activity_screen_mentions', 'bp_activity_reset_my_new_mentions' );
bp-activity/screens/permalink.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Single permalink screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Catch and route requests for single activity item permalinks.
12
+ *
13
+ * @since 1.2.0
14
+ *
15
+ * @return bool False on failure.
16
+ */
17
+ function bp_activity_action_permalink_router() {
18
+ // Not viewing activity.
19
+ if ( ! bp_is_activity_component() || ! bp_is_current_action( 'p' ) )
20
+ return false;
21
+
22
+ // No activity to display.
23
+ if ( ! bp_action_variable( 0 ) || ! is_numeric( bp_action_variable( 0 ) ) )
24
+ return false;
25
+
26
+ // Get the activity details.
27
+ $activity = bp_activity_get_specific( array( 'activity_ids' => bp_action_variable( 0 ), 'show_hidden' => true ) );
28
+
29
+ // 404 if activity does not exist
30
+ if ( empty( $activity['activities'][0] ) ) {
31
+ bp_do_404();
32
+ return;
33
+ } else {
34
+ $activity = $activity['activities'][0];
35
+ }
36
+
37
+ // Do not redirect at default.
38
+ $redirect = false;
39
+
40
+ // Redirect based on the type of activity.
41
+ if ( bp_is_active( 'groups' ) && $activity->component == buddypress()->groups->id ) {
42
+
43
+ // Activity is a user update.
44
+ if ( ! empty( $activity->user_id ) ) {
45
+ $redirect = bp_core_get_user_domain( $activity->user_id, $activity->user_nicename, $activity->user_login ) . bp_get_activity_slug() . '/' . $activity->id . '/';
46
+
47
+ // Activity is something else.
48
+ } else {
49
+
50
+ // Set redirect to group activity stream.
51
+ if ( $group = groups_get_group( $activity->item_id ) ) {
52
+ $redirect = bp_get_group_permalink( $group ) . bp_get_activity_slug() . '/' . $activity->id . '/';
53
+ }
54
+ }
55
+
56
+ // Set redirect to users' activity stream.
57
+ } elseif ( ! empty( $activity->user_id ) ) {
58
+ $redirect = bp_core_get_user_domain( $activity->user_id, $activity->user_nicename, $activity->user_login ) . bp_get_activity_slug() . '/' . $activity->id . '/';
59
+ }
60
+
61
+ // If set, add the original query string back onto the redirect URL.
62
+ if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
63
+ $query_frags = array();
64
+ wp_parse_str( $_SERVER['QUERY_STRING'], $query_frags );
65
+ $redirect = add_query_arg( urlencode_deep( $query_frags ), $redirect );
66
+ }
67
+
68
+ /**
69
+ * Filter the intended redirect url before the redirect occurs for the single activity item.
70
+ *
71
+ * @since 1.2.2
72
+ *
73
+ * @param array $value Array with url to redirect to and activity related to the redirect.
74
+ */
75
+ if ( ! $redirect = apply_filters_ref_array( 'bp_activity_permalink_redirect_url', array( $redirect, &$activity ) ) ) {
76
+ bp_core_redirect( bp_get_root_domain() );
77
+ }
78
+
79
+ // Redirect to the actual activity permalink page.
80
+ bp_core_redirect( $redirect );
81
+ }
82
+ add_action( 'bp_actions', 'bp_activity_action_permalink_router' );
83
+
84
+ /**
85
+ * Load the page for a single activity item.
86
+ *
87
+ * @since 1.2.0
88
+ *
89
+ * @return bool|string Boolean on false or the template for a single activity item on success.
90
+ */
91
+ function bp_activity_screen_single_activity_permalink() {
92
+ // No displayed user or not viewing activity component.
93
+ if ( ! bp_is_activity_component() ) {
94
+ return false;
95
+ }
96
+
97
+ $action = bp_current_action();
98
+ if ( ! $action || ! is_numeric( $action ) ) {
99
+ return false;
100
+ }
101
+
102
+ // Get the activity details.
103
+ $activity = bp_activity_get_specific( array(
104
+ 'activity_ids' => $action,
105
+ 'show_hidden' => true,
106
+ 'spam' => 'ham_only',
107
+ ) );
108
+
109
+ // 404 if activity does not exist
110
+ if ( empty( $activity['activities'][0] ) || bp_action_variables() ) {
111
+ bp_do_404();
112
+ return;
113
+
114
+ } else {
115
+ $activity = $activity['activities'][0];
116
+ }
117
+
118
+ /**
119
+ * Check user access to the activity item.
120
+ *
121
+ * @since 3.0.0
122
+ */
123
+ $has_access = bp_activity_user_can_read( $activity );
124
+
125
+ // If activity author does not match displayed user, block access.
126
+ // More info:https://buddypress.trac.wordpress.org/ticket/7048#comment:28
127
+ if ( true === $has_access && bp_displayed_user_id() !== $activity->user_id ) {
128
+ $has_access = false;
129
+ }
130
+
131
+ /**
132
+ * Fires before the loading of a single activity template file.
133
+ *
134
+ * @since 1.2.0
135
+ *
136
+ * @param BP_Activity_Activity $activity Object representing the current activity item being displayed.
137
+ * @param bool $has_access Whether or not the current user has access to view activity.
138
+ */
139
+ do_action( 'bp_activity_screen_single_activity_permalink', $activity, $has_access );
140
+
141
+ // Access is specifically disallowed.
142
+ if ( false === $has_access ) {
143
+ // If not logged in, prompt for login.
144
+ if ( ! is_user_logged_in() ) {
145
+ bp_core_no_access();
146
+
147
+ // Redirect away.
148
+ } else {
149
+ bp_core_add_message( __( 'You do not have access to this activity.', 'buddypress' ), 'error' );
150
+ bp_core_redirect( bp_loggedin_user_domain() );
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Filters the template to load for a single activity screen.
156
+ *
157
+ * @since 1.0.0
158
+ *
159
+ * @param string $template Path to the activity template to load.
160
+ */
161
+ $template = apply_filters( 'bp_activity_template_profile_activity_permalink', 'members/single/activity/permalink' );
162
+
163
+ // Load the template.
164
+ bp_core_load_template( $template );
165
+ }
166
+ add_action( 'bp_screens', 'bp_activity_screen_single_activity_permalink' );
bp-activity/screens/settings-email.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Activity: Integration into user's "Settings > Email" screen
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage ActivityScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ // Exit if accessed directly.
11
+ defined( 'ABSPATH' ) || exit;
12
+
13
+ /**
14
+ * Add activity notifications settings to the notifications settings page.
15
+ *
16
+ * @since 1.2.0
17
+ */
18
+ function bp_activity_screen_notification_settings() {
19
+ if ( bp_activity_do_mentions() ) {
20
+ if ( ! $mention = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_mention', true ) ) {
21
+ $mention = 'yes';
22
+ }
23
+ }
24
+
25
+ if ( ! $reply = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_reply', true ) ) {
26
+ $reply = 'yes';
27
+ }
28
+
29
+ ?>
30
+
31
+ <table class="notification-settings" id="activity-notification-settings">
32
+ <thead>
33
+ <tr>
34
+ <th class="icon">&nbsp;</th>
35
+ <th class="title"><?php _e( 'Activity', 'buddypress' ) ?></th>
36
+ <th class="yes"><?php _e( 'Yes', 'buddypress' ) ?></th>
37
+ <th class="no"><?php _e( 'No', 'buddypress' )?></th>
38
+ </tr>
39
+ </thead>
40
+
41
+ <tbody>
42
+ <?php if ( bp_activity_do_mentions() ) : ?>
43
+ <tr id="activity-notification-settings-mentions">
44
+ <td>&nbsp;</td>
45
+ <td><?php printf( __( 'A member mentions you in an update using "@%s"', 'buddypress' ), bp_core_get_username( bp_displayed_user_id() ) ) ?></td>
46
+ <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
47
+ /* translators: accessibility text */
48
+ _e( 'Yes, send email', 'buddypress' );
49
+ ?></label></td>
50
+ <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
51
+ /* translators: accessibility text */
52
+ _e( 'No, do not send email', 'buddypress' );
53
+ ?></label></td>
54
+ </tr>
55
+ <?php endif; ?>
56
+
57
+ <tr id="activity-notification-settings-replies">
58
+ <td>&nbsp;</td>
59
+ <td><?php _e( "A member replies to an update or comment you've posted", 'buddypress' ) ?></td>
60
+ <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
61
+ /* translators: accessibility text */
62
+ _e( 'Yes, send email', 'buddypress' );
63
+ ?></label></td>
64
+ <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
65
+ /* translators: accessibility text */
66
+ _e( 'No, do not send email', 'buddypress' );
67
+ ?></label></td>
68
+ </tr>
69
+
70
+ <?php
71
+
72
+ /**
73
+ * Fires inside the closing </tbody> tag for activity screen notification settings.
74
+ *
75
+ * @since 1.2.0
76
+ */
77
+ do_action( 'bp_activity_screen_notification_settings' ) ?>
78
+ </tbody>
79
+ </table>
80
+
81
+ <?php
82
+ }
83
+ add_action( 'bp_notification_settings', 'bp_activity_screen_notification_settings', 1 );
bp-blogs/{bp-blogs-actions.php → actions/random.php} RENAMED
@@ -1,15 +1,12 @@
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
  *
@@ -31,4 +28,4 @@ function bp_blogs_redirect_to_random_blog() {
31
  bp_core_redirect( bp_core_get_root_domain() );
32
  }
33
  }
34
- add_action( 'bp_actions', 'bp_blogs_redirect_to_random_blog' );
1
  <?php
2
  /**
3
+ * Blogs: Random blog action handler
4
  *
5
  * @package BuddyPress
6
  * @subpackage BlogsActions
7
+ * @since 3.0.0
8
  */
9
 
 
 
 
10
  /**
11
  * Redirect to a random blog in the multisite network.
12
  *
28
  bp_core_redirect( bp_core_get_root_domain() );
29
  }
30
  }
31
+ add_action( 'bp_actions', 'bp_blogs_redirect_to_random_blog' );
bp-blogs/bp-blogs-activity.php CHANGED
@@ -48,7 +48,7 @@ add_action( 'bp_register_activity_actions', 'bp_blogs_register_activity_actions'
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
 
@@ -435,7 +435,7 @@ add_filter( 'bp_activity_prefetch_object_data', 'bp_blogs_prefetch_activity_obje
435
  * bp_activity_add().
436
  * @type string $component Default: 'blogs'.
437
  * }
438
- * @return int|bool On success, returns the activity ID. False on failure.
439
  */
440
  function bp_blogs_record_activity( $args = '' ) {
441
  $defaults = array(
@@ -547,7 +547,7 @@ function bp_blogs_comments_open( $activity ) {
547
  switch_to_blog( $blog_id );
548
 
549
  // Use comments_open().
550
- remove_filter( 'comments_open', 'bp_comments_open', 10, 2 );
551
  $open = comments_open( $activity->secondary_item_id );
552
  add_filter( 'comments_open', 'bp_comments_open', 10, 2 );
553
 
@@ -624,6 +624,15 @@ function bp_blogs_record_activity_on_site_creation( $recorded_blog, $is_private,
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
  'primary_link' => apply_filters( 'bp_blogs_activity_created_blog_primary_link', bp_blogs_get_blogmeta( $recorded_blog->blog_id, 'url' ), $recorded_blog->blog_id ),
628
  'type' => 'new_blog',
629
  'item_id' => $recorded_blog->blog_id
@@ -639,15 +648,25 @@ add_action( 'bp_blogs_new_blog', 'bp_blogs_record_activity_on_site_creation', 10
639
  *
640
  * @param int $blog_id Site ID.
641
  */
642
- function bp_blogs_delete_new_blog_activity_for_site( $blog_id ) {
643
- bp_blogs_delete_activity( array(
644
  'item_id' => $blog_id,
645
  'component' => buddypress()->blogs->id,
646
  'type' => 'new_blog'
647
- ) );
 
 
 
 
 
 
 
 
 
 
648
  }
649
- add_action( 'bp_blogs_remove_blog', 'bp_blogs_delete_new_blog_activity_for_site' );
650
- add_action( 'bp_blogs_remove_blog_for_user', 'bp_blogs_delete_new_blog_activity_for_site' );
651
 
652
  /**
653
  * Delete all 'blogs' activity items for a site when the site is deleted.
@@ -787,7 +806,7 @@ function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_
787
  );
788
 
789
  // Prevent separate activity entry being made.
790
- remove_action( 'comment_post', 'bp_activity_post_type_comment', 10, 2 );
791
 
792
  // Handle multisite.
793
  switch_to_blog( $parent_activity->item_id );
@@ -813,7 +832,7 @@ function bp_blogs_sync_add_from_activity_comment( $comment_id, $params, $parent_
813
  // permalinks to use the post comment link
814
  //
815
  // @todo since this is done after AJAX posting, the activity comment permalink
816
- // doesn't change on the frontend until the next page refresh.
817
  $resave_activity = new BP_Activity_Activity( $comment_id );
818
  $resave_activity->primary_link = get_comment_link( $post_comment_id );
819
 
@@ -951,8 +970,8 @@ function bp_blogs_sync_activity_edit_to_post_comment( BP_Activity_Activity $acti
951
  $old_comment_status = $post_comment_status;
952
 
953
  // No need to edit the activity, as it's the activity who's updating the comment
954
- remove_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
955
- remove_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_comment', 10, 4 );
956
 
957
  if ( 1 === $activity->is_spam && 'spam' !== $post_comment_status ) {
958
  wp_spam_comment( $post_comment_id );
@@ -1129,6 +1148,7 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1129
 
1130
  $allow_comments = bp_blogs_comments_open( $activity );
1131
  $thread_depth = bp_blogs_get_blogmeta( $activity->item_id, 'thread_comments_depth' );
 
1132
 
1133
  // Initialize a local object so we won't have to query this again in the
1134
  // comment loop.
@@ -1138,16 +1158,23 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1138
  if ( empty( buddypress()->blogs->thread_depth ) ) {
1139
  buddypress()->blogs->thread_depth = array();
1140
  }
 
 
 
1141
 
1142
- // Cache comment settings in the buddypress() singleton to reference later in
1143
- // the activity comment loop
1144
- // @see bp_blogs_disable_activity_replies()
1145
- //
1146
- // thread_depth is keyed by activity ID instead of blog ID because when we're
1147
- // in a comment loop, we don't have access to the blog ID...
1148
- // should probably object cache these values instead...
1149
- buddypress()->blogs->allow_comments[ $activity->id ] = $allow_comments;
1150
- buddypress()->blogs->thread_depth[ $activity->id ] = $thread_depth;
 
 
 
 
1151
  }
1152
 
1153
  /**
@@ -1212,6 +1239,11 @@ function bp_blogs_disable_activity_commenting( $retval ) {
1212
  if ( empty( buddypress()->blogs->allow_comments[ bp_get_activity_id() ] ) ) {
1213
  $retval = false;
1214
  }
 
 
 
 
 
1215
  // The activity type does not support comments or replies
1216
  } else {
1217
  $retval = false;
@@ -1281,7 +1313,7 @@ function bp_blogs_can_comment_reply( $retval, $comment ) {
1281
 
1282
  // Check comment depth and disable if depth is too large.
1283
  if ( isset( buddypress()->blogs->thread_depth[$comment->item_id] ) ){
1284
- if ( $comment->mptt_left > buddypress()->blogs->thread_depth[$comment->item_id] ) {
1285
  $retval = false;
1286
  }
1287
  }
@@ -1295,6 +1327,11 @@ function bp_blogs_can_comment_reply( $retval, $comment ) {
1295
  }
1296
  }
1297
 
 
 
 
 
 
1298
  return $retval;
1299
  }
1300
  add_filter( 'bp_activity_can_comment_reply', 'bp_blogs_can_comment_reply', 10, 2 );
48
  *
49
  * @param object|null $params Tracking arguments.
50
  * @param string|int $post_type Post type to track.
51
+ * @return object|null
52
  */
53
  function bp_blogs_register_post_tracking_args( $params = null, $post_type = 0 ) {
54
 
435
  * bp_activity_add().
436
  * @type string $component Default: 'blogs'.
437
  * }
438
+ * @return WP_Error|bool|int On success, returns the activity ID. False on failure.
439
  */
440
  function bp_blogs_record_activity( $args = '' ) {
441
  $defaults = array(
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
 
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
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.
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 );
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
 
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 );
1148
 
1149
  $allow_comments = bp_blogs_comments_open( $activity );
1150
  $thread_depth = bp_blogs_get_blogmeta( $activity->item_id, 'thread_comments_depth' );
1151
+ $moderation = bp_blogs_get_blogmeta( $activity->item_id, 'comment_moderation' );
1152
 
1153
  // Initialize a local object so we won't have to query this again in the
1154
  // comment loop.
1158
  if ( empty( buddypress()->blogs->thread_depth ) ) {
1159
  buddypress()->blogs->thread_depth = array();
1160
  }
1161
+ if ( empty( buddypress()->blogs->comment_moderation ) ) {
1162
+ buddypress()->blogs->comment_moderation = array();
1163
+ }
1164
 
1165
+ /*
1166
+ * Cache comment settings in the buddypress() singleton for later reference.
1167
+ *
1168
+ * See bp_blogs_disable_activity_commenting() / bp_blogs_can_comment_reply().
1169
+ *
1170
+ * thread_depth is keyed by activity ID instead of blog ID because when we're
1171
+ * in an actvity comment loop, we don't have access to the blog ID...
1172
+ *
1173
+ * Should probably object cache these values instead...
1174
+ */
1175
+ buddypress()->blogs->allow_comments[ $activity->id ] = $allow_comments;
1176
+ buddypress()->blogs->thread_depth[ $activity->id ] = $thread_depth;
1177
+ buddypress()->blogs->comment_moderation[ $activity->id ] = $moderation;
1178
  }
1179
 
1180
  /**
1239
  if ( empty( buddypress()->blogs->allow_comments[ bp_get_activity_id() ] ) ) {
1240
  $retval = false;
1241
  }
1242
+
1243
+ // If comments need moderation, disable activity commenting.
1244
+ if ( ! empty( buddypress()->blogs->comment_moderation[ bp_get_activity_id() ] ) ) {
1245
+ $retval = false;
1246
+ }
1247
  // The activity type does not support comments or replies
1248
  } else {
1249
  $retval = false;
1313
 
1314
  // Check comment depth and disable if depth is too large.
1315
  if ( isset( buddypress()->blogs->thread_depth[$comment->item_id] ) ){
1316
+ if ( bp_activity_get_comment_depth( $comment ) >= buddypress()->blogs->thread_depth[$comment->item_id] ) {
1317
  $retval = false;
1318
  }
1319
  }
1327
  }
1328
  }
1329
 
1330
+ // If comments need moderation, disable activity commenting.
1331
+ if ( ! empty( buddypress()->blogs->comment_moderation[$comment->item_id] ) ) {
1332
+ $retval = false;
1333
+ }
1334
+
1335
  return $retval;
1336
  }
1337
  add_filter( 'bp_activity_can_comment_reply', 'bp_blogs_can_comment_reply', 10, 2 );
bp-blogs/bp-blogs-classes.php DELETED
@@ -1,13 +0,0 @@
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
- require dirname( __FILE__ ) . '/classes/class-bp-blogs-blog.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-blogs/bp-blogs-filters.php CHANGED
@@ -121,3 +121,17 @@ function bp_blogs_post_pre_publish( $return = true, $blog_id = 0, $post_id = 0,
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 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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' );
bp-blogs/bp-blogs-functions.php CHANGED
@@ -65,7 +65,14 @@ function bp_blogs_get_blogs( $args = '' ) {
65
  $r['include_blog_ids']
66
  );
67
 
68
- // Filter and return.
 
 
 
 
 
 
 
69
  return apply_filters( 'bp_blogs_get_blogs', $blogs, $r );
70
  }
71
 
@@ -93,7 +100,7 @@ function bp_blogs_record_existing_blogs( $args = array() ) {
93
 
94
  // Query for all sites in network.
95
  $r = bp_parse_args( $args, array(
96
- 'offset' => false === bp_get_option( '_bp_record_blogs_offset' ) ? 0 : bp_get_option( '_bp_record_blogs_offset' ),
97
  'limit' => 50,
98
  'blog_ids' => array(),
99
  'site_id' => $wpdb->siteid
@@ -246,9 +253,26 @@ function bp_blogs_record_existing_blogs( $args = array() ) {
246
  */
247
  function bp_blogs_is_blog_recordable( $blog_id, $user_id = 0 ) {
248
 
 
 
 
 
 
 
 
 
249
  $recordable_globally = apply_filters( 'bp_blogs_is_blog_recordable', true, $blog_id );
250
 
251
  if ( !empty( $user_id ) ) {
 
 
 
 
 
 
 
 
 
252
  $recordable_for_user = apply_filters( 'bp_blogs_is_blog_recordable_for_user', $recordable_globally, $blog_id, $user_id );
253
  } else {
254
  $recordable_for_user = $recordable_globally;
@@ -275,9 +299,27 @@ function bp_blogs_is_blog_recordable( $blog_id, $user_id = 0 ) {
275
  */
276
  function bp_blogs_is_blog_trackable( $blog_id, $user_id = 0 ) {
277
 
 
 
 
 
 
 
 
 
278
  $trackable_globally = apply_filters( 'bp_blogs_is_blog_trackable', bp_blogs_is_blog_recordable( $blog_id, $user_id ), $blog_id );
279
 
280
  if ( !empty( $user_id ) ) {
 
 
 
 
 
 
 
 
 
 
281
  $trackable_for_user = apply_filters( 'bp_blogs_is_blog_trackable_for_user', $trackable_globally, $blog_id, $user_id );
282
  } else {
283
  $trackable_for_user = $trackable_globally;
@@ -299,7 +341,7 @@ function bp_blogs_is_blog_trackable( $blog_id, $user_id = 0 ) {
299
  * @param int $user_id ID of the user for whom the blog is being recorded.
300
  * @param bool $no_activity Optional. Whether to skip recording an activity
301
  * item about this blog creation. Default: false.
302
- * @return bool|null Returns false on failure.
303
  */
304
  function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
305
 
@@ -320,6 +362,7 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
320
  $description = get_blog_option( $blog_id, 'blogdescription' );
321
  $close_old_posts = get_blog_option( $blog_id, 'close_comments_for_old_posts' );
322
  $close_days_old = get_blog_option( $blog_id, 'close_comments_days_old' );
 
323
 
324
  $thread_depth = get_blog_option( $blog_id, 'thread_comments' );
325
  if ( ! empty( $thread_depth ) ) {
@@ -342,8 +385,17 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
342
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_for_old_posts', $close_old_posts );
343
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_days_old', $close_days_old );
344
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'thread_comments_depth', $thread_depth );
 
345
 
346
  $is_private = !empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ? false : true;
 
 
 
 
 
 
 
 
347
  $is_private = !apply_filters( 'bp_is_new_blog_public', !$is_private );
348
 
349
  /**
@@ -475,11 +527,45 @@ function bp_blogs_update_option_thread_comments_depth( $oldvalue, $newvalue ) {
475
  }
476
  add_action( 'update_option_thread_comments_depth', 'bp_blogs_update_option_thread_comments_depth', 10, 2 );
477
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  /**
479
  * Deletes the 'url' blogmeta for a site.
480
  *
481
- * Hooked to 'refresh_blog_details', which is notably used when editing a site
482
- * under "Network Admin > Sites".
 
483
  *
484
  * @since 2.3.0
485
  *
@@ -488,7 +574,12 @@ add_action( 'update_option_thread_comments_depth', 'bp_blogs_update_option_threa
488
  function bp_blogs_delete_url_blogmeta( $site_id = 0 ) {
489
  bp_blogs_delete_blogmeta( (int) $site_id, 'url' );
490
  }
491
- add_action( 'refresh_blog_details', 'bp_blogs_delete_url_blogmeta' );
 
 
 
 
 
492
 
493
  /**
494
  * Record activity metadata about a published blog post.
@@ -624,7 +715,7 @@ add_action( 'bp_activity_post_type_updated', 'bp_blogs_update_post_activity_meta
624
  * @param WP_Comment|null $comment The comment object.
625
  * @param array $activity_args Array of activity arguments.
626
  * @param object|null $activity_post_object The post type tracking args object.
627
- * @return int|bool Returns false if no activity, the activity id otherwise.
628
  */
629
  function bp_blogs_comment_sync_activity_comment( &$activity_id, $comment = null, $activity_args = array(), $activity_post_object = null ) {
630
  if ( empty( $activity_args ) || empty( $comment->post->ID ) || empty( $activity_post_object->comment_action_id ) ) {
@@ -715,6 +806,18 @@ function bp_blogs_comment_sync_activity_comment( &$activity_id, $comment = null,
715
  bp_activity_update_meta( $activity_id, 'post_url', esc_url_raw( add_query_arg( 'p', $comment->post->ID, home_url( '/' ) ) ) );
716
  }
717
  }
 
 
 
 
 
 
 
 
 
 
 
 
718
  }
719
  }
720
 
@@ -752,7 +855,7 @@ add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_com
752
  * @param int $user_id The ID of the user.
753
  * @param string|bool $role User's WordPress role for this blog ID.
754
  * @param int $blog_id Blog ID user is being added to.
755
- * @return bool|null False on failure.
756
  */
757
  function bp_blogs_add_user_to_blog( $user_id, $role = false, $blog_id = 0 ) {
758
  global $wpdb;
@@ -812,6 +915,14 @@ add_action( 'user_register', 'bp_blogs_add_user_to_blog' );
812
  * @return string
813
  */
814
  function bp_blogs_get_allowed_roles() {
 
 
 
 
 
 
 
 
815
  return apply_filters( 'bp_blogs_get_allowed_roles', array( 'contributor', 'author', 'editor', 'administrator' ) );
816
  }
817
 
@@ -907,19 +1018,6 @@ function bp_blogs_remove_blog_for_user( $user_id, $blog_id ) {
907
 
908
  BP_Blogs_Blog::delete_blog_for_user( $blog_id, $user_id );
909
 
910
- /**
911
- * Delete activity stream item only if the Activity component is active
912
- *
913
- * @see https://buddypress.trac.wordpress.org/ticket/6937
914
- */
915
- if ( bp_is_active( 'activity' ) ) {
916
- bp_blogs_delete_activity( array(
917
- 'item_id' => $blog_id,
918
- 'component' => buddypress()->blogs->id,
919
- 'type' => 'new_blog'
920
- ) );
921
- }
922
-
923
  /**
924
  * Fires after a blog has been removed from the tracker for a specific user.
925
  *
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
 
100
 
101
  // Query for all sites in network.
102
  $r = bp_parse_args( $args, array(
103
+ 'offset' => (int) bp_get_option( '_bp_record_blogs_offset' ),
104
  'limit' => 50,
105
  'blog_ids' => array(),
106
  'site_id' => $wpdb->siteid
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;
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;
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 false|null Returns false on failure.
345
  */
346
  function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
347
 
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' );
365
+ $moderation = get_blog_option( $blog_id, 'comment_moderation' );
366
 
367
  $thread_depth = get_blog_option( $blog_id, 'thread_comments' );
368
  if ( ! empty( $thread_depth ) ) {
385
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_for_old_posts', $close_old_posts );
386
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_days_old', $close_days_old );
387
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'thread_comments_depth', $thread_depth );
388
+ bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'comment_moderation', $moderation );
389
 
390
  $is_private = !empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ? false : true;
391
+
392
+ /**
393
+ * Filters whether or not a new blog is public.
394
+ *
395
+ * @since 1.5.0
396
+ *
397
+ * @param bool $is_private Whether or not blog is public.
398
+ */
399
  $is_private = !apply_filters( 'bp_is_new_blog_public', !$is_private );
400
 
401
  /**
527
  }
528
  add_action( 'update_option_thread_comments_depth', 'bp_blogs_update_option_thread_comments_depth', 10, 2 );
529
 
530
+ /**
531
+ * When updating comment moderation, mirror value in blogmeta table.
532
+ *
533
+ * @since 3.0.0
534
+ *
535
+ * @param string $oldvalue Value before save. Passed by do_action() but unused here.
536
+ * @param string $newvalue Value to change meta to.
537
+ */
538
+ function bp_blogs_update_option_comment_moderation( $oldvalue, $newvalue ) {
539
+ bp_blogs_update_blogmeta( $GLOBALS['wpdb']->blogid, 'comment_moderation', $newvalue );
540
+ }
541
+ add_action( 'update_option_comment_moderation', 'bp_blogs_update_option_comment_moderation', 10, 2 );
542
+
543
+ /**
544
+ * Syncs site icon URLs to blogmeta.
545
+ *
546
+ * @since 2.7.0
547
+ *
548
+ * @param int|string $old_value Old value
549
+ * @param int|string $new_value New value
550
+ */
551
+ function bp_blogs_update_option_site_icon( $old_value, $new_value ) {
552
+ if ( 0 === $new_value ) {
553
+ bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_thumb', 0 );
554
+ bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_full', 0 );
555
+ } else {
556
+ // Save site icon URL as blogmeta.
557
+ bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_thumb', get_site_icon_url( bp_core_avatar_thumb_width() ) );
558
+ bp_blogs_update_blogmeta( get_current_blog_id(), 'site_icon_url_full', get_site_icon_url( bp_core_avatar_full_width() ) );
559
+ }
560
+ }
561
+ add_action( 'update_option_site_icon', 'bp_blogs_update_option_site_icon', 10, 2 );
562
+
563
  /**
564
  * Deletes the 'url' blogmeta for a site.
565
  *
566
+ * Fires when a site's details are updated, which generally happens when
567
+ * editing a site under "Network Admin > Sites". Prior to WP 4.9, the
568
+ * correct hook was 'refresh_blog_details'; afterward, 'clean_site_cache'.
569
  *
570
  * @since 2.3.0
571
  *
574
  function bp_blogs_delete_url_blogmeta( $site_id = 0 ) {
575
  bp_blogs_delete_blogmeta( (int) $site_id, 'url' );
576
  }
577
+
578
+ if ( function_exists( 'wp_switch_roles_and_user' ) ) {
579
+ add_action( 'clean_site_cache', 'bp_blogs_delete_url_blogmeta' );
580
+ } else {
581
+ add_action( 'refresh_blog_details', 'bp_blogs_delete_url_blogmeta' );
582
+ }
583
 
584
  /**
585
  * Record activity metadata about a published blog post.
715
  * @param WP_Comment|null $comment The comment object.
716
  * @param array $activity_args Array of activity arguments.
717
  * @param object|null $activity_post_object The post type tracking args object.
718
+ * @return WP_Error|bool|int Returns false if no activity, the activity id otherwise.
719
  */
720
  function bp_blogs_comment_sync_activity_comment( &$activity_id, $comment = null, $activity_args = array(), $activity_post_object = null ) {
721
  if ( empty( $activity_args ) || empty( $comment->post->ID ) || empty( $activity_post_object->comment_action_id ) ) {
806
  bp_activity_update_meta( $activity_id, 'post_url', esc_url_raw( add_query_arg( 'p', $comment->post->ID, home_url( '/' ) ) ) );
807
  }
808
  }
809
+
810
+ /**
811
+ * Fires after an activity comment is added from a WP post comment.
812
+ *
813
+ * @since 2.6.0
814
+ *
815
+ * @param int $activity_id The activity comment ID.
816
+ * @param WP_Comment $post_type_comment WP Comment object.
817
+ * @param array $activity_args Activity comment arguments.
818
+ * @param object $activity_post_object The post type tracking args object.
819
+ */
820
+ do_action( 'bp_blogs_comment_sync_activity_comment', $activity_id, $comment, $activity_args, $activity_post_object );
821
  }
822
  }
823
 
855
  * @param int $user_id The ID of the user.
856
  * @param string|bool $role User's WordPress role for this blog ID.
857
  * @param int $blog_id Blog ID user is being added to.
858
+ * @return false|null False on failure.
859
  */
860
  function bp_blogs_add_user_to_blog( $user_id, $role = false, $blog_id = 0 ) {
861
  global $wpdb;
915
  * @return string
916
  */
917
  function bp_blogs_get_allowed_roles() {
918
+
919
+ /**
920
+ * Filters the allowed roles a member must have to be recorded into bp_user_blogs pointer table.
921
+ *
922
+ * @since 2.1.0
923
+ *
924
+ * @param array $value Array of potential roles user needs.
925
+ */
926
  return apply_filters( 'bp_blogs_get_allowed_roles', array( 'contributor', 'author', 'editor', 'administrator' ) );
927
  }
928
 
1018
 
1019
  BP_Blogs_Blog::delete_blog_for_user( $blog_id, $user_id );
1020
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1021
  /**
1022
  * Fires after a blog has been removed from the tracker for a specific user.
1023
  *
bp-blogs/bp-blogs-loader.php CHANGED
@@ -14,12 +14,10 @@
14
  // Exit if accessed directly.
15
  defined( 'ABSPATH' ) || exit;
16
 
17
- if ( ! buddypress()->do_autoload ) {
18
- require dirname( __FILE__ ) . '/classes/class-bp-blogs-component.php';
19
- }
20
-
21
  /**
22
  * Set up the bp-blogs component.
 
 
23
  */
24
  function bp_setup_blogs() {
25
  buddypress()->blogs = new BP_Blogs_Component();
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();
bp-blogs/bp-blogs-screens.php DELETED
@@ -1,77 +0,0 @@
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
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-blogs-theme-compat.php';
15
- }
16
-
17
- /**
18
- * Load the "My Blogs" screen.
19
- */
20
- function bp_blogs_screen_my_blogs() {
21
- if ( !is_multisite() )
22
- return false;
23
-
24
- /**
25
- * Fires right before the loading of the My Blogs screen template file.
26
- *
27
- * @since 1.0.0
28
- */
29
- do_action( 'bp_blogs_screen_my_blogs' );
30
-
31
- bp_core_load_template( apply_filters( 'bp_blogs_template_my_blogs', 'members/single/home' ) );
32
- }
33
-
34
- /**
35
- * Load the "Create a Blog" screen.
36
- */
37
- function bp_blogs_screen_create_a_blog() {
38
-
39
- if ( !is_multisite() || !bp_is_blogs_component() || !bp_is_current_action( 'create' ) )
40
- return false;
41
-
42
- if ( !is_user_logged_in() || !bp_blog_signup_enabled() )
43
- return false;
44
-
45
- /**
46
- * Fires right before the loading of the Create A Blog screen template file.
47
- *
48
- * @since 1.0.0
49
- */
50
- do_action( 'bp_blogs_screen_create_a_blog' );
51
-
52
- bp_core_load_template( apply_filters( 'bp_blogs_template_create_a_blog', 'blogs/create' ) );
53
- }
54
- add_action( 'bp_screens', 'bp_blogs_screen_create_a_blog', 3 );
55
-
56
- /**
57
- * Load the top-level Blogs directory.
58
- */
59
- function bp_blogs_screen_index() {
60
- if ( bp_is_blogs_directory() ) {
61
- bp_update_is_directory( true, 'blogs' );
62
-
63
- /**
64
- * Fires right before the loading of the top-level Blogs screen template file.
65
- *
66
- * @since 1.0.0
67
- */
68
- do_action( 'bp_blogs_screen_index' );
69
-
70
- bp_core_load_template( apply_filters( 'bp_blogs_screen_index', 'blogs/index' ) );
71
- }
72
- }
73
- add_action( 'bp_screens', 'bp_blogs_screen_index', 2 );
74
-
75
- /** Theme Compatibility *******************************************************/
76
-
77
- new BP_Blogs_Theme_Compat();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-blogs/bp-blogs-template.php CHANGED
@@ -10,10 +10,6 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-blogs-template.php';
15
- }
16
-
17
  /**
18
  * Output the blogs component slug.
19
  *
@@ -220,9 +216,22 @@ function bp_the_blog() {
220
  /**
221
  * Output the blogs pagination count.
222
  *
223
- * @global object $blogs_template {@link BP_Blogs_Template}
224
  */
225
  function bp_blogs_pagination_count() {
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  global $blogs_template;
227
 
228
  $start_num = intval( ( $blogs_template->pag_page - 1 ) * $blogs_template->pag_num ) + 1;
@@ -236,7 +245,17 @@ function bp_blogs_pagination_count() {
236
  $message = sprintf( _n( 'Viewing %1$s - %2$s of %3$s site', 'Viewing %1$s - %2$s of %3$s sites', $blogs_template->total_blog_count, 'buddypress' ), $from_num, $to_num, $total );
237
  }
238
 
239
- echo $message;
 
 
 
 
 
 
 
 
 
 
240
  }
241
 
242
  /**
@@ -292,7 +311,6 @@ function bp_blog_avatar( $args = '' ) {
292
  * {@link bp_core_fetch_avatar()}.
293
  * @type string $alt Default: 'Profile picture of site author [user name]'.
294
  * @type string $class Default: 'avatar'.
295
- * @type string $title Default: 'Profile picture of site author [user name]'.
296
  * @type string $type Default: 'full'.
297
  * @type int|bool $width Default: false.
298
  * @type int|bool $height Default: false.
@@ -318,25 +336,81 @@ function bp_blog_avatar( $args = '' ) {
318
  'width' => false,
319
  'height' => false,
320
  'class' => 'avatar',
321
- 'title' => sprintf( __( 'Profile picture of site author %s', 'buddypress' ), esc_attr( $author_displayname ) ),
322
  'id' => false,
323
  'alt' => sprintf( __( 'Profile picture of site author %s', 'buddypress' ), esc_attr( $author_displayname ) ),
324
  'no_grav' => true,
325
  ) );
326
 
327
- // Fetch the avatar.
328
- $avatar = bp_core_fetch_avatar( array(
329
- 'item_id' => $blogs_template->blog->admin_user_id,
330
- 'title' => $r['title'],
331
- // 'avatar_dir' => 'blog-avatars',
332
- // 'object' => 'blog',
333
- 'type' => $r['type'],
334
- 'alt' => $r['alt'],
335
- 'css_id' => $r['id'],
336
- 'class' => $r['class'],
337
- 'width' => $r['width'],
338
- 'height' => $r['height']
339
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  /**
342
  * In future BuddyPress versions you will be able to set the avatar for a blog.
@@ -566,7 +640,7 @@ function bp_blog_last_active( $args = array() ) {
566
  /**
567
  * Filters the last active date of the current blog in the loop.
568
  *
569
- * @since
570
  *
571
  * @param string $last_activity Last active date.
572
  * @param array $r Array of parsed args used to determine formatting.
@@ -1005,7 +1079,7 @@ function bp_blogs_signup_blog( $blogname = '', $blog_title = '', $errors = '' )
1005
  if ( !is_subdomain_install() )
1006
  echo '<span class="prefix_address">' . $current_site->domain . $current_site->path . '</span> <input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" /><br />';
1007
  else
1008
- echo '<input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" ' . bp_get_form_field_attributes( 'blogname' ) . '/> <span class="suffix_address">.' . bp_blogs_get_subdomain_base() . '</span><br />';
1009
 
1010
  if ( !is_user_logged_in() ) {
1011
  print '(<strong>' . __( 'Your address will be ' , 'buddypress');
@@ -1032,9 +1106,8 @@ function bp_blogs_signup_blog( $blogname = '', $blog_title = '', $errors = '' )
1032
  echo '<input name="blog_title" type="text" id="blog_title" value="'.esc_html($blog_title, 1).'" /></p>';
1033
  ?>
1034
 
1035
- <p>
1036
- <label for="blog_public_on"><?php _e('Privacy:', 'buddypress') ?></label>
1037
- <?php _e( 'I would like my site to appear in search engines, and in public listings around this network.', 'buddypress' ); ?>
1038
 
1039
  <label class="checkbox" for="blog_public_on">
1040
  <input type="radio" id="blog_public_on" name="blog_public" value="1" <?php if( !isset( $_POST['blog_public'] ) || '1' == $_POST['blog_public'] ) { ?>checked="checked"<?php } ?> />
@@ -1044,7 +1117,7 @@ function bp_blogs_signup_blog( $blogname = '', $blog_title = '', $errors = '' )
1044
  <input type="radio" id="blog_public_off" name="blog_public" value="0" <?php if( isset( $_POST['blog_public'] ) && '0' == $_POST['blog_public'] ) { ?>checked="checked"<?php } ?> />
1045
  <strong><?php _e( 'No' , 'buddypress'); ?></strong>
1046
  </label>
1047
- </p>
1048
 
1049
  <?php
1050
 
@@ -1265,7 +1338,7 @@ function bp_blog_create_button() {
1265
  *
1266
  * @since 2.0.0
1267
  *
1268
- * @return string
1269
  */
1270
  function bp_get_blog_create_button() {
1271
  if ( ! is_user_logged_in() ) {
@@ -1280,7 +1353,6 @@ function bp_blog_create_button() {
1280
  'id' => 'create_blog',
1281
  'component' => 'blogs',
1282
  'link_text' => __( 'Create a Site', 'buddypress' ),
1283
- 'link_title' => __( 'Create a Site', 'buddypress' ),
1284
  'link_class' => 'blog-create no-ajax',
1285
  'link_href' => trailingslashit( bp_get_blogs_directory_permalink() . 'create' ),
1286
  'wrapper' => false,
@@ -1324,6 +1396,13 @@ function bp_blog_create_nav_item() {
1324
 
1325
  $output = '<li id="blog-create-nav">' . $create_blog_button . '</li>';
1326
 
 
 
 
 
 
 
 
1327
  return apply_filters( 'bp_get_blog_create_nav_item', $output );
1328
  }
1329
 
@@ -1333,7 +1412,7 @@ function bp_blog_create_nav_item() {
1333
  *
1334
  * @since 2.2.0
1335
  *
1336
- * @return string HTML Output
1337
  */
1338
  function bp_blog_backcompat_create_nav_item() {
1339
  // Bail if Blogs nav item is already used by bp-legacy.
@@ -1377,7 +1456,6 @@ function bp_blogs_visit_blog_button( $args = '' ) {
1377
  * @type string $link_href Permalink of the current blog in the loop.
1378
  * @type string $link_class Default: 'blog-button visit'.
1379
  * @type string $link_text Default: 'Visit Site'.
1380
- * @type string $link_title Default: 'Visit Site'.
1381
  * }
1382
  * @return string The HTML for the Visit button.
1383
  */
@@ -1391,7 +1469,6 @@ function bp_blogs_visit_blog_button( $args = '' ) {
1391
  'link_href' => bp_get_blog_permalink(),
1392
  'link_class' => 'blog-button visit',
1393
  'link_text' => __( 'Visit Site', 'buddypress' ),
1394
- 'link_title' => __( 'Visit Site', 'buddypress' ),
1395
  );
1396
 
1397
  $button = wp_parse_args( $args, $defaults );
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
13
  /**
14
  * Output the blogs component slug.
15
  *
216
  /**
217
  * Output the blogs pagination count.
218
  *
219
+ * @since 1.0.0
220
  */
221
  function bp_blogs_pagination_count() {
222
+ echo bp_get_blogs_pagination_count();
223
+ }
224
+
225
+ /**
226
+ * Get the blogs pagination count.
227
+ *
228
+ * @since 2.7.0
229
+ *
230
+ * @global object $blogs_template {@link BP_Blogs_Template}
231
+ *
232
+ * @return string
233
+ */
234
+ function bp_get_blogs_pagination_count() {
235
  global $blogs_template;
236
 
237
  $start_num = intval( ( $blogs_template->pag_page - 1 ) * $blogs_template->pag_num ) + 1;
245
  $message = sprintf( _n( 'Viewing %1$s - %2$s of %3$s site', 'Viewing %1$s - %2$s of %3$s sites', $blogs_template->total_blog_count, 'buddypress' ), $from_num, $to_num, $total );
246
  }
247
 
248
+ /**
249
+ * Filters the "Viewing x-y of z blogs" pagination message.
250
+ *
251
+ * @since 2.7.0
252
+ *
253
+ * @param string $message "Viewing x-y of z blogs" text.
254
+ * @param string $from_num Total amount for the low value in the range.
255
+ * @param string $to_num Total amount for the high value in the range.
256
+ * @param string $total Total amount of blogs found.
257
+ */
258
+ return apply_filters( 'bp_get_blogs_pagination_count', $message, $from_num, $to_num, $total );
259
  }
260
 
261
  /**
311
  * {@link bp_core_fetch_avatar()}.
312
  * @type string $alt Default: 'Profile picture of site author [user name]'.
313
  * @type string $class Default: 'avatar'.
 
314
  * @type string $type Default: 'full'.
315
  * @type int|bool $width Default: false.
316
  * @type int|bool $height Default: false.
336
  'width' => false,
337
  'height' => false,
338
  'class' => 'avatar',
 
339
  'id' => false,
340
  'alt' => sprintf( __( 'Profile picture of site author %s', 'buddypress' ), esc_attr( $author_displayname ) ),
341
  'no_grav' => true,
342
  ) );
343
 
344
+ // Use site icon if available.
345
+ $avatar = '';
346
+ if ( bp_is_active( 'blogs', 'site-icon' ) && function_exists( 'has_site_icon' ) ) {
347
+ $site_icon = bp_blogs_get_blogmeta( bp_get_blog_id(), "site_icon_url_{$r['type']}" );
348
+
349
+ // Never attempted to fetch site icon before; do it now!
350
+ if ( '' === $site_icon ) {
351
+ switch_to_blog( bp_get_blog_id() );
352
+
353
+ // Fetch the other size first.
354
+ if ( 'full' === $r['type'] ) {
355
+ $size = bp_core_avatar_thumb_width();
356
+ $save_size = 'thumb';
357
+ } else {
358
+ $size = bp_core_avatar_full_width();
359
+ $save_size = 'full';
360
+ }
361
+
362
+ $site_icon = get_site_icon_url( $size );
363
+ // Empty site icons get saved as integer 0.
364
+ if ( empty( $site_icon ) ) {
365
+ $site_icon = 0;
366
+ }
367
+
368
+ // Sync site icon for other size to blogmeta.
369
+ bp_blogs_update_blogmeta( bp_get_blog_id(), "site_icon_url_{$save_size}", $site_icon );
370
+
371
+ // Now, fetch the size we want.
372
+ if ( 0 !== $site_icon ) {
373
+ $size = 'full' === $r['type'] ? bp_core_avatar_full_width() : bp_core_avatar_thumb_width();
374
+ $site_icon = get_site_icon_url( $size );
375
+ }
376
+
377
+ // Sync site icon to blogmeta.
378
+ bp_blogs_update_blogmeta( bp_get_blog_id(), "site_icon_url_{$r['type']}", $site_icon );
379
+
380
+ restore_current_blog();
381
+ }
382
+
383
+ // We have a site icon.
384
+ if ( ! is_numeric( $site_icon ) ) {
385
+ if ( empty( $r['width'] ) && ! isset( $size ) ) {
386
+ $size = 'full' === $r['type'] ? bp_core_avatar_full_width() : bp_core_avatar_thumb_width();
387
+ } else {
388
+ $size = (int) $r['width'];
389
+ }
390
+
391
+ $avatar = sprintf( '<img src="%1$s" class="%2$s" width="%3$s" height="%3$s" alt="%4$s" />',
392
+ esc_url( $site_icon ),
393
+ esc_attr( "{$r['class']} avatar-{$size}" ),
394
+ esc_attr( $size ),
395
+ sprintf( esc_attr__( 'Site icon for %s', 'buddypress' ), bp_get_blog_name() )
396
+ );
397
+ }
398
+ }
399
+
400
+ // Fallback to user ID avatar.
401
+ if ( '' === $avatar ) {
402
+ $avatar = bp_core_fetch_avatar( array(
403
+ 'item_id' => $blogs_template->blog->admin_user_id,
404
+ // 'avatar_dir' => 'blog-avatars',
405
+ // 'object' => 'blog',
406
+ 'type' => $r['type'],
407
+ 'alt' => $r['alt'],
408
+ 'css_id' => $r['id'],
409
+ 'class' => $r['class'],
410
+ 'width' => $r['width'],
411
+ 'height' => $r['height']
412
+ ) );
413
+ }
414
 
415
  /**
416
  * In future BuddyPress versions you will be able to set the avatar for a blog.
640
  /**
641
  * Filters the last active date of the current blog in the loop.
642
  *
643
+ * @since 1.2.0
644
  *
645
  * @param string $last_activity Last active date.
646
  * @param array $r Array of parsed args used to determine formatting.
1079
  if ( !is_subdomain_install() )
1080
  echo '<span class="prefix_address">' . $current_site->domain . $current_site->path . '</span> <input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" /><br />';
1081
  else
1082
+ echo '<input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" ' . bp_get_form_field_attributes( 'blogname' ) . '/> <span class="suffix_address">.' . bp_signup_get_subdomain_base() . '</span><br />';
1083
 
1084
  if ( !is_user_logged_in() ) {
1085
  print '(<strong>' . __( 'Your address will be ' , 'buddypress');
1106
  echo '<input name="blog_title" type="text" id="blog_title" value="'.esc_html($blog_title, 1).'" /></p>';
1107
  ?>
1108
 
1109
+ <fieldset class="create-site">
1110
+ <legend class="label"><?php _e('Privacy: I would like my site to appear in search engines, and in public listings around this network', 'buddypress') ?></legend>
 
1111
 
1112
  <label class="checkbox" for="blog_public_on">
1113
  <input type="radio" id="blog_public_on" name="blog_public" value="1" <?php if( !isset( $_POST['blog_public'] ) || '1' == $_POST['blog_public'] ) { ?>checked="checked"<?php } ?> />
1117
  <input type="radio" id="blog_public_off" name="blog_public" value="0" <?php if( isset( $_POST['blog_public'] ) && '0' == $_POST['blog_public'] ) { ?>checked="checked"<?php } ?> />
1118
  <strong><?php _e( 'No' , 'buddypress'); ?></strong>
1119
  </label>
1120
+ </fieldset>
1121
 
1122
  <?php
1123
 
1338
  *
1339
  * @since 2.0.0
1340
  *
1341
+ * @return false|string
1342
  */
1343
  function bp_get_blog_create_button() {
1344
  if ( ! is_user_logged_in() ) {
1353
  'id' => 'create_blog',
1354
  'component' => 'blogs',
1355
  'link_text' => __( 'Create a Site', 'buddypress' ),
 
1356
  'link_class' => 'blog-create no-ajax',
1357
  'link_href' => trailingslashit( bp_get_blogs_directory_permalink() . 'create' ),
1358
  'wrapper' => false,
1396
 
1397
  $output = '<li id="blog-create-nav">' . $create_blog_button . '</li>';
1398
 
1399
+ /**
1400
+ * Filters the Create A Site nav item output.
1401
+ *
1402
+ * @since 2.2.0
1403
+ *
1404
+ * @param string $output Nav item output.
1405
+ */
1406
  return apply_filters( 'bp_get_blog_create_nav_item', $output );
1407
  }
1408
 
1412
  *
1413
  * @since 2.2.0
1414
  *
1415
+ * @return string|null HTML Output
1416
  */
1417
  function bp_blog_backcompat_create_nav_item() {
1418
  // Bail if Blogs nav item is already used by bp-legacy.
1456
  * @type string $link_href Permalink of the current blog in the loop.
1457
  * @type string $link_class Default: 'blog-button visit'.
1458
  * @type string $link_text Default: 'Visit Site'.
 
1459
  * }
1460
  * @return string The HTML for the Visit button.
1461
  */
1469
  'link_href' => bp_get_blog_permalink(),
1470
  'link_class' => 'blog-button visit',
1471
  'link_text' => __( 'Visit Site', 'buddypress' ),
 
1472
  );
1473
 
1474
  $button = wp_parse_args( $args, $defaults );
bp-blogs/bp-blogs-widgets.php CHANGED
@@ -10,10 +10,6 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-blogs-recent-posts-widget.php';
15
- }
16
-
17
  /**
18
  * Register the widgets for the Blogs component.
19
  */
@@ -21,7 +17,7 @@ function bp_blogs_register_widgets() {
21
  global $wpdb;
22
 
23
  if ( bp_is_active( 'activity' ) && bp_is_root_blog( $wpdb->blogid ) ) {
24
- add_action( 'widgets_init', create_function( '', 'return register_widget("BP_Blogs_Recent_Posts_Widget");' ) );
25
  }
26
  }
27
  add_action( 'bp_register_widgets', 'bp_blogs_register_widgets' );
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
13
  /**
14
  * Register the widgets for the Blogs component.
15
  */
17
  global $wpdb;
18
 
19
  if ( bp_is_active( 'activity' ) && bp_is_root_blog( $wpdb->blogid ) ) {
20
+ add_action( 'widgets_init', function() { register_widget( 'BP_Blogs_Recent_Posts_Widget' ); } );
21
  }
22
  }
23
  add_action( 'bp_register_widgets', 'bp_blogs_register_widgets' );
bp-blogs/classes/class-bp-blogs-blog.php CHANGED
@@ -48,7 +48,7 @@ class BP_Blogs_Blog {
48
  */
49
  public function __construct( $id = null ) {
50
  if ( !empty( $id ) ) {
51
- $this->id = $id;
52
  $this->populate();
53
  }
54
  }
@@ -63,8 +63,8 @@ class BP_Blogs_Blog {
63
 
64
  $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->blogs->table_name} WHERE id = %d", $this->id ) );
65
 
66
- $this->user_id = $blog->user_id;
67
- $this->blog_id = $blog->blog_id;
68
  }
69
 
70
  /**
@@ -75,7 +75,24 @@ class BP_Blogs_Blog {
75
  public function save() {
76
  global $wpdb;
77
 
 
 
 
 
 
 
 
 
78
  $this->user_id = apply_filters( 'bp_blogs_blog_user_id_before_save', $this->user_id, $this->id );
 
 
 
 
 
 
 
 
 
79
  $this->blog_id = apply_filters( 'bp_blogs_blog_id_before_save', $this->blog_id, $this->id );
80
 
81
  /**
@@ -243,6 +260,12 @@ class BP_Blogs_Blog {
243
 
244
  $paged_blogs = BP_Blogs_Blog::get_blog_extras( $paged_blogs, $blog_ids, $type );
245
 
 
 
 
 
 
 
246
  if ( $update_meta_cache ) {
247
  bp_blogs_update_meta_cache( $blog_ids );
248
  }
@@ -338,8 +361,8 @@ class BP_Blogs_Blog {
338
  $user_blogs = array();
339
  foreach ( (array) $blogs as $blog ) {
340
  $user_blogs[$blog->blog_id] = new stdClass;
341
- $user_blogs[$blog->blog_id]->id = $blog->id;
342
- $user_blogs[$blog->blog_id]->blog_id = $blog->blog_id;
343
  $user_blogs[$blog->blog_id]->siteurl = ( is_ssl() ) ? 'https://' . $blog->domain . $blog->path : 'http://' . $blog->domain . $blog->path;
344
  $user_blogs[$blog->blog_id]->name = $blog->name;
345
  }
@@ -364,7 +387,7 @@ class BP_Blogs_Blog {
364
  if ( !$user_id )
365
  $user_id = bp_displayed_user_id();
366
 
367
- return $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM {$bp->blogs->table_name} WHERE user_id = %d", $user_id ) );
368
  }
369
 
370
  /**
@@ -379,7 +402,9 @@ class BP_Blogs_Blog {
379
 
380
  $bp = buddypress();
381
 
382
- return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->blogs->table_name} WHERE blog_id = %d", $blog_id ) );
 
 
383
  }
384
 
385
  /**
@@ -444,7 +469,12 @@ class BP_Blogs_Blog {
444
  $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}" );
445
  $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" );
446
 
447
- return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
 
 
 
 
 
448
  }
449
 
450
  /**
@@ -472,7 +502,12 @@ class BP_Blogs_Blog {
472
  $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}" );
473
  $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}" );
474
 
475
- return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
 
 
 
 
 
476
  }
477
 
478
  /**
@@ -509,7 +544,12 @@ class BP_Blogs_Blog {
509
  $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}" );
510
  $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" );
511
 
512
- return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
 
 
 
 
 
513
  }
514
 
515
  /**
48
  */
49
  public function __construct( $id = null ) {
50
  if ( !empty( $id ) ) {
51
+ $this->id = (int) $id;
52
  $this->populate();
53
  }
54
  }
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
  /**
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
  /**
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
  }
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
  }
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
  /**
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
  /**
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
  /**
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
  /**
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
  /**
bp-blogs/classes/class-bp-blogs-component.php CHANGED
@@ -32,6 +32,7 @@ class BP_Blogs_Component extends BP_Component {
32
  array(
33
  'adminbar_myaccount_order' => 30,
34
  'search_query_arg' => 'sites_search',
 
35
  )
36
  );
37
  }
@@ -65,12 +66,16 @@ class BP_Blogs_Component extends BP_Component {
65
  'blog' => $bp->table_prefix . 'bp_user_blogs_blogmeta',
66
  );
67
 
 
 
 
 
68
  // All globals for blogs component.
69
  $args = array(
70
  'slug' => BP_BLOGS_SLUG,
71
  'root_slug' => isset( $bp->pages->blogs->slug ) ? $bp->pages->blogs->slug : BP_BLOGS_SLUG,
72
  'has_directory' => is_multisite(), // Non-multisite installs don't need a top-level Sites directory, since there's only one site.
73
- 'directory_title' => _x( 'Sites', 'component directory title', 'buddypress' ),
74
  'notification_callback' => 'bp_blogs_format_notifications',
75
  'search_string' => __( 'Search sites...', 'buddypress' ),
76
  'autocomplete_all' => defined( 'BP_MESSAGES_AUTOCOMPLETE_ALL' ),
@@ -120,17 +125,11 @@ class BP_Blogs_Component extends BP_Component {
120
  // Files to include.
121
  $includes = array(
122
  'cache',
123
- 'actions',
124
- 'screens',
125
  'template',
126
  'filters',
127
  'functions',
128
  );
129
 
130
- if ( ! buddypress()->do_autoload ) {
131
- $includes[] = 'classes';
132
- }
133
-
134
  if ( bp_is_active( 'activity' ) ) {
135
  $includes[] = 'activity';
136
  }
@@ -143,6 +142,46 @@ class BP_Blogs_Component extends BP_Component {
143
  parent::includes( $includes );
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  /**
147
  * Set up component navigation for bp-blogs.
148
  *
32
  array(
33
  'adminbar_myaccount_order' => 30,
34
  'search_query_arg' => 'sites_search',
35
+ 'features' => array( 'site-icon' )
36
  )
37
  );
38
  }
66
  'blog' => $bp->table_prefix . 'bp_user_blogs_blogmeta',
67
  );
68
 
69
+ // Fetch the default directory title.
70
+ $default_directory_titles = bp_core_get_directory_page_default_titles();
71
+ $default_directory_title = $default_directory_titles[$this->id];
72
+
73
  // All globals for blogs component.
74
  $args = array(
75
  'slug' => BP_BLOGS_SLUG,
76
  'root_slug' => isset( $bp->pages->blogs->slug ) ? $bp->pages->blogs->slug : BP_BLOGS_SLUG,
77
  'has_directory' => is_multisite(), // Non-multisite installs don't need a top-level Sites directory, since there's only one site.
78
+ 'directory_title' => isset( $bp->pages->blogs->title ) ? $bp->pages->blogs->title : $default_directory_title,
79
  'notification_callback' => 'bp_blogs_format_notifications',
80
  'search_string' => __( 'Search sites...', 'buddypress' ),
81
  'autocomplete_all' => defined( 'BP_MESSAGES_AUTOCOMPLETE_ALL' ),
125
  // Files to include.
126
  $includes = array(
127
  'cache',
 
 
128
  'template',
129
  'filters',
130
  'functions',
131
  );
132
 
 
 
 
 
133
  if ( bp_is_active( 'activity' ) ) {
134
  $includes[] = 'activity';
135
  }
142
  parent::includes( $includes );
143
  }
144
 
145
+ /**
146
+ * Late includes method.
147
+ *
148
+ * Only load up certain code when on specific pages.
149
+ *
150
+ * @since 3.0.0
151
+ */
152
+ public function late_includes() {
153
+ // Bail if PHPUnit is running.
154
+ if ( defined( 'BP_TESTS_DIR' ) ) {
155
+ return;
156
+ }
157
+
158
+ // Bail if not on a blogs page or not multisite.
159
+ if ( ! bp_is_blogs_component() || ! is_multisite() ) {
160
+ return;
161
+ }
162
+
163
+ // Actions.
164
+ if ( isset( $_GET['random-blog'] ) ) {
165
+ require $this->path . 'bp-blogs/actions/random.php';
166
+ }
167
+
168
+ // Screens.
169
+ if ( bp_is_user() ) {
170
+ require $this->path . 'bp-blogs/screens/my-blogs.php';
171
+ } else {
172
+ if ( bp_is_blogs_directory() ) {
173
+ require $this->path . 'bp-blogs/screens/directory.php';
174
+ }
175
+
176
+ if ( is_user_logged_in() && bp_is_current_action( 'create' ) ) {
177
+ require $this->path . 'bp-blogs/screens/create.php';
178
+ }
179
+
180
+ // Theme compatibility.
181
+ new BP_Blogs_Theme_Compat();
182
+ }
183
+ }
184
+
185
  /**
186
  * Set up component navigation for bp-blogs.
187
  *
bp-blogs/screens/create.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Blogs: Create screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage BlogsScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the "Create a Blog" screen.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ function bp_blogs_screen_create_a_blog() {
16
+
17
+ if ( !is_multisite() || !bp_is_blogs_component() || !bp_is_current_action( 'create' ) )
18
+ return false;
19
+
20
+ if ( !is_user_logged_in() || !bp_blog_signup_enabled() )
21
+ return false;
22
+
23
+ /**
24
+ * Fires right before the loading of the Create A Blog screen template file.
25
+ *
26
+ * @since 1.0.0
27
+ */
28
+ do_action( 'bp_blogs_screen_create_a_blog' );
29
+
30
+ bp_core_load_template( apply_filters( 'bp_blogs_template_create_a_blog', 'blogs/create' ) );
31
+ }
32
+ add_action( 'bp_screens', 'bp_blogs_screen_create_a_blog', 3 );
bp-blogs/screens/directory.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Blogs: Directory screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage BlogsScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the top-level Blogs directory.
12
+ *
13
+ * @since 1.5-beta-1
14
+ */
15
+ function bp_blogs_screen_index() {
16
+ if ( bp_is_blogs_directory() ) {
17
+ bp_update_is_directory( true, 'blogs' );
18
+
19
+ /**
20
+ * Fires right before the loading of the top-level Blogs screen template file.
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ do_action( 'bp_blogs_screen_index' );
25
+
26
+ bp_core_load_template( apply_filters( 'bp_blogs_screen_index', 'blogs/index' ) );
27
+ }
28
+ }
29
+ add_action( 'bp_screens', 'bp_blogs_screen_index', 2 );
bp-blogs/screens/my-blogs.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Blogs: User's "Sites" screen handler
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage BlogsScreens
7
+ * @since 3.0.0
8
+ */
9
+
10
+ /**
11
+ * Load the "My Blogs" screen.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ function bp_blogs_screen_my_blogs() {
16
+ if ( !is_multisite() )
17
+ return false;
18
+
19
+ /**
20
+ * Fires right before the loading of the My Blogs screen template file.
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ do_action( 'bp_blogs_screen_my_blogs' );
25
+
26
+ bp_core_load_template( apply_filters( 'bp_blogs_template_my_blogs', 'members/single/home' ) );
27
+ }
bp-core/admin/bp-core-admin-classes.php DELETED
@@ -1,13 +0,0 @@
1
- <?php
2
- /**
3
- * Core component classes for wp-admin screens.
4
- *
5
- * @package BuddyPress
6
- * @subpackage Core
7
- * @since 2.5.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- require dirname( dirname( __FILE__ ) ) . '/classes/class-bp-walker-category-checklist.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-core/admin/bp-core-admin-components.php CHANGED
@@ -81,11 +81,6 @@ function bp_core_admin_components_options() {
81
  $required_components = bp_core_admin_get_components( 'required' );
82
  $retired_components = bp_core_admin_get_components( 'retired' );
83
 
84
- // Don't show Forums component in optional components if it's disabled.
85
- if ( ! bp_is_active( 'forums' ) ) {
86
- unset( $optional_components['forums'] );
87
- }
88
-
89
  // Merge optional and required together.
90
  $all_components = $optional_components + $required_components;
91
 
@@ -170,9 +165,10 @@ function bp_core_admin_components_options() {
170
  <table class="wp-list-table widefat plugins">
171
  <thead>
172
  <tr>
173
- <td id="cb" class="manage-column column-cb check-column"><input id="cb-select-all-1" type="checkbox" disabled><label class="screen-reader-text" for="cb-select-all-1"><?php
 
174
  /* translators: accessibility text */
175
- _e( 'Bulk selection is disabled', 'buddypress' );
176
  ?></label></td>
177
  <th scope="col" id="name" class="manage-column column-title column-primary"><?php _e( 'Component', 'buddypress' ); ?></th>
178
  <th scope="col" id="description" class="manage-column column-description"><?php _e( 'Description', 'buddypress' ); ?></th>
@@ -196,18 +192,18 @@ function bp_core_admin_components_options() {
196
 
197
  <?php if ( !in_array( $name, array( 'core', 'members' ) ) ) : ?>
198
 
199
- <input type="checkbox" id="<?php echo esc_attr( "bp_components[$name]" ); ?>" name="<?php echo esc_attr( "bp_components[$name]" ); ?>" value="1"<?php checked( isset( $active_components[esc_attr( $name )] ) ); ?> /><label for="<?php echo esc_attr( "bp_components[$name]" ); ?>" class="screen-reader-text"><?php printf( __( 'Select %s', 'buddypress' ), esc_html( $labels['title'] ) ); ?></label>
200
-
201
- <?php else : ?>
202
-
203
- <input type="checkbox" id="<?php echo esc_attr( "bp_components[$name]" ); ?>" name="<?php echo esc_attr( "bp_components[$name]" ); ?>" value="1" checked="checked" disabled><label for="<?php echo esc_attr( "bp_components[$name]" ); ?>" class="screen-reader-text"><?php printf( __( '%s is a required component', 'buddypress' ), esc_html( $labels['title'] ) ); ?></label>
204
 
205
  <?php endif; ?>
206
 
207
  </th>
208
  <td class="plugin-title column-primary">
209
- <span aria-hidden="true"></span>
210
- <strong><?php echo esc_html( $labels['title'] ); ?></strong>
 
 
211
  </td>
212
 
213
  <td class="column-description desc">
@@ -232,9 +228,10 @@ function bp_core_admin_components_options() {
232
 
233
  <tfoot>
234
  <tr>
235
- <td class="manage-column column-cb check-column"><input id="cb-select-all-2" type="checkbox" disabled><label class="screen-reader-text" for="cb-select-all-2"><?php
 
236
  /* translators: accessibility text */
237
- _e( 'Bulk selection is disabled', 'buddypress' );
238
  ?></label></td>
239
  <th class="manage-column column-title column-primary"><?php _e( 'Component', 'buddypress' ); ?></th>
240
  <th class="manage-column column-description"><?php _e( 'Description', 'buddypress' ); ?></th>
@@ -272,6 +269,7 @@ function bp_core_admin_components_settings_handler() {
272
  $bp = buddypress();
273
 
274
  // Save settings and upgrade schema.
 
275
  require_once( $bp->plugin_dir . '/bp-core/admin/bp-core-admin-schema.php' );
276
 
277
  $submitted = stripslashes_deep( $_POST['bp_components'] );
81
  $required_components = bp_core_admin_get_components( 'required' );
82
  $retired_components = bp_core_admin_get_components( 'retired' );
83
 
 
 
 
 
 
84
  // Merge optional and required together.
85
  $all_components = $optional_components + $required_components;
86
 
165
  <table class="wp-list-table widefat plugins">
166
  <thead>
167
  <tr>
168
+ <td id="cb" class="manage-column column-cb check-column"><input id="cb-select-all-1" type="checkbox" <?php checked( empty( $inactive_components ) ); ?>>
169
+ <label class="screen-reader-text" for="cb-select-all-1"><?php
170
  /* translators: accessibility text */
171
+ _e( 'Enable or disable all optional components in bulk', 'buddypress' );
172
  ?></label></td>
173
  <th scope="col" id="name" class="manage-column column-title column-primary"><?php _e( 'Component', 'buddypress' ); ?></th>
174
  <th scope="col" id="description" class="manage-column column-description"><?php _e( 'Description', 'buddypress' ); ?></th>
192
 
193
  <?php if ( !in_array( $name, array( 'core', 'members' ) ) ) : ?>
194
 
195
+ <input type="checkbox" id="<?php echo esc_attr( "bp_components[$name]" ); ?>" name="<?php echo esc_attr( "bp_components[$name]" ); ?>" value="1"<?php checked( isset( $active_components[esc_attr( $name )] ) ); ?> /><label for="<?php echo esc_attr( "bp_components[$name]" ); ?>" class="screen-reader-text"><?php
196
+ /* translators: accessibility text */
197
+ printf( __( 'Select %s', 'buddypress' ), esc_html( $labels['title'] ) ); ?></label>
 
 
198
 
199
  <?php endif; ?>
200
 
201
  </th>
202
  <td class="plugin-title column-primary">
203
+ <label for="<?php echo esc_attr( "bp_components[$name]" ); ?>">
204
+ <span aria-hidden="true"></span>
205
+ <strong><?php echo esc_html( $labels['title'] ); ?></strong>
206
+ </label>
207
  </td>
208
 
209
  <td class="column-description desc">
228
 
229
  <tfoot>
230
  <tr>
231
+ <td class="manage-column column-cb check-column"><input id="cb-select-all-2" type="checkbox" <?php checked( empty( $inactive_components ) ); ?>>
232
+ <label class="screen-reader-text" for="cb-select-all-2"><?php
233
  /* translators: accessibility text */
234
+ _e( 'Enable or disable all optional components in bulk', 'buddypress' );
235
  ?></label></td>
236
  <th class="manage-column column-title column-primary"><?php _e( 'Component', 'buddypress' ); ?></th>
237
  <th class="manage-column column-description"><?php _e( 'Description', 'buddypress' ); ?></th>
269
  $bp = buddypress();
270
 
271
  // Save settings and upgrade schema.
272
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
273
  require_once( $bp->plugin_dir . '/bp-core/admin/bp-core-admin-schema.php' );
274
 
275
  $submitted = stripslashes_deep( $_POST['bp_components'] );
bp-core/admin/bp-core-admin-functions.php CHANGED
@@ -288,15 +288,6 @@ function bp_core_activation_notice() {
288
  }
289
  }
290
 
291
- // Special case: If the Forums component is orphaned, but the bbPress 1.x installation is
292
- // not correctly set up, don't show a nag. (In these cases, it's probably the case that the
293
- // user is using bbPress 2.x; see https://buddypress.trac.wordpress.org/ticket/4292.
294
- if ( isset( $bp->forums->name ) && in_array( $bp->forums->name, $orphaned_components ) && !bp_forums_is_installed_correctly() ) {
295
- $forum_key = array_search( $bp->forums->name, $orphaned_components );
296
- unset( $orphaned_components[$forum_key] );
297
- $orphaned_components = array_values( $orphaned_components );
298
- }
299
-
300
  if ( !empty( $orphaned_components ) ) {
301
  $admin_url = bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) );
302
  $notice = sprintf(
@@ -314,7 +305,7 @@ function bp_core_activation_notice() {
314
 
315
  // BP components cannot share a single WP page. Check for duplicate assignments, and post a message if found.
316
  $dupe_names = array();
317
- $page_ids = (array)bp_core_get_directory_page_ids();
318
  $dupes = array_diff_assoc( $page_ids, array_unique( $page_ids ) );
319
 
320
  if ( !empty( $dupes ) ) {
@@ -440,19 +431,6 @@ function bp_core_get_admin_tabs( $active_tab = '' ) {
440
  ),
441
  );
442
 
443
- // If forums component is active, add additional tab.
444
- if ( bp_is_active( 'forums' ) && class_exists( 'BP_Forums_Component' ) ) {
445
-
446
- // Enqueue thickbox.
447
- wp_enqueue_script( 'thickbox' );
448
- wp_enqueue_style( 'thickbox' );
449
-
450
- $tabs['3'] = array(
451
- 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bb-forums-setup' ), 'admin.php' ) ),
452
- 'name' => __( 'Forums', 'buddypress' )
453
- );
454
- }
455
-
456
  /**
457
  * Filters the tab data used in our wp-admin screens.
458
  *
@@ -804,7 +782,29 @@ function bp_admin_do_wp_nav_menu_meta_box() {
804
  </ul>
805
  </div>
806
 
 
 
 
 
 
 
 
 
 
 
 
807
  <p class="button-controls">
 
 
 
 
 
 
 
 
 
 
 
808
  <span class="add-to-menu">
809
  <input type="submit"<?php if ( function_exists( 'wp_nav_menu_disabled_check' ) ) : wp_nav_menu_disabled_check( $nav_menu_selected_id ); endif; ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu', 'buddypress' ); ?>" name="add-custom-menu-item" id="submit-buddypress-menu" />
810
  <span class="spinner"></span>
@@ -841,7 +841,7 @@ function bp_admin_email_maybe_add_translation_notice() {
841
 
842
  bp_core_add_admin_notice(
843
  sprintf(
844
- __( 'Are your emails in the wrong language? Go to <a href="%s">BuddyPress Tools and run the "reinstall emails"</a> tool.', 'buddypress' ),
845
  esc_url( add_query_arg( 'page', 'bp-tools', bp_get_admin_url( $admin_page ) ) )
846
  ),
847
  'updated'
@@ -1091,3 +1091,43 @@ function bp_core_admin_user_spammed_js() {
1091
  </script>
1092
  <?php
1093
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  }
289
  }
290
 
 
 
 
 
 
 
 
 
 
291
  if ( !empty( $orphaned_components ) ) {
292
  $admin_url = bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) );
293
  $notice = sprintf(
305
 
306
  // BP components cannot share a single WP page. Check for duplicate assignments, and post a message if found.
307
  $dupe_names = array();
308
+ $page_ids = bp_core_get_directory_page_ids();
309
  $dupes = array_diff_assoc( $page_ids, array_unique( $page_ids ) );
310
 
311
  if ( !empty( $dupes ) ) {
431
  ),
432
  );
433
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  /**
435
  * Filters the tab data used in our wp-admin screens.
436
  *
782
  </ul>
783
  </div>
784
 
785
+ <?php
786
+ $removed_args = array(
787
+ 'action',
788
+ 'customlink-tab',
789
+ 'edit-menu-item',
790
+ 'menu-item',
791
+ 'page-tab',
792
+ '_wpnonce',
793
+ );
794
+ ?>
795
+
796
  <p class="button-controls">
797
+ <span class="list-controls">
798
+ <a href="<?php
799
+ echo esc_url( add_query_arg(
800
+ array(
801
+ $post_type_name . '-tab' => 'all',
802
+ 'selectall' => 1,
803
+ ),
804
+ remove_query_arg( $removed_args )
805
+ ) );
806
+ ?>#buddypress-menu" class="select-all"><?php _e( 'Select All', 'buddypress' ); ?></a>
807
+ </span>
808
  <span class="add-to-menu">
809
  <input type="submit"<?php if ( function_exists( 'wp_nav_menu_disabled_check' ) ) : wp_nav_menu_disabled_check( $nav_menu_selected_id ); endif; ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu', 'buddypress' ); ?>" name="add-custom-menu-item" id="submit-buddypress-menu" />
810
  <span class="spinner"></span>
841
 
842
  bp_core_add_admin_notice(
843
  sprintf(
844
+ __( 'Are these emails not written in your site\'s language? Go to <a href="%s">BuddyPress Tools and try the "reinstall emails"</a> tool.', 'buddypress' ),
845
  esc_url( add_query_arg( 'page', 'bp-tools', bp_get_admin_url( $admin_page ) ) )
846
  ),
847
  'updated'
1091
  </script>
1092
  <?php
1093
  }
1094
+
1095
+ /**
1096
+ * Catch and process an admin notice dismissal.
1097
+ *
1098
+ * @since 2.7.0
1099
+ */
1100
+ function bp_core_admin_notice_dismiss_callback() {
1101
+ if ( ! current_user_can( 'install_plugins' ) ) {
1102
+ wp_send_json_error();
1103
+ }
1104
+
1105
+ if ( empty( $_POST['nonce'] ) || empty( $_POST['notice_id'] ) ) {
1106
+ wp_send_json_error();
1107
+ }
1108
+
1109
+ $notice_id = wp_unslash( $_POST['notice_id'] );
1110
+
1111
+ if ( ! wp_verify_nonce( $_POST['nonce'], 'bp-dismissible-notice-' . $notice_id ) ) {
1112
+ wp_send_json_error();
1113
+ }
1114
+
1115
+ bp_update_option( "bp-dismissed-notice-$notice_id", 1 );
1116
+
1117
+ wp_send_json_success();
1118
+ }
1119
+ add_action( 'wp_ajax_bp_dismiss_notice', 'bp_core_admin_notice_dismiss_callback' );
1120
+
1121
+ /**
1122
+ * Add a "buddypress" class to body element of wp-admin.
1123
+ *
1124
+ * @since 2.8.0
1125
+ *
1126
+ * @param string $classes CSS classes for the body tag in the admin, a comma separated string.
1127
+ *
1128
+ * @return string
1129
+ */
1130
+ function bp_core_admin_body_classes( $classes ) {
1131
+ return $classes . ' buddypress';
1132
+ }
1133
+ add_filter( 'admin_body_class', 'bp_core_admin_body_classes' );
bp-core/admin/bp-core-admin-schema.php CHANGED
@@ -10,23 +10,6 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- /**
14
- * Get the DB schema to use for BuddyPress components.
15
- *
16
- * @since 1.1.0
17
- *
18
- * @global $wpdb $wpdb
19
- *
20
- * @return string The default database character-set, if set.
21
- */
22
- function bp_core_set_charset() {
23
- global $wpdb;
24
-
25
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
26
-
27
- return !empty( $wpdb->charset ) ? "DEFAULT CHARACTER SET {$wpdb->charset}" : '';
28
- }
29
-
30
  /**
31
  * Main installer.
32
  *
@@ -93,7 +76,7 @@ function bp_core_install( $active_components = false ) {
93
  */
94
  function bp_core_install_notifications() {
95
  $sql = array();
96
- $charset_collate = bp_core_set_charset();
97
  $bp_prefix = bp_core_get_table_prefix();
98
 
99
  $sql[] = "CREATE TABLE {$bp_prefix}bp_notifications (
@@ -134,7 +117,7 @@ function bp_core_install_notifications() {
134
  */
135
  function bp_core_install_activity_streams() {
136
  $sql = array();
137
- $charset_collate = bp_core_set_charset();
138
  $bp_prefix = bp_core_get_table_prefix();
139
 
140
  $sql[] = "CREATE TABLE {$bp_prefix}bp_activity (
@@ -184,7 +167,7 @@ function bp_core_install_activity_streams() {
184
  */
185
  function bp_core_install_friends() {
186
  $sql = array();
187
- $charset_collate = bp_core_set_charset();
188
  $bp_prefix = bp_core_get_table_prefix();
189
 
190
  $sql[] = "CREATE TABLE {$bp_prefix}bp_friends (
@@ -209,7 +192,7 @@ function bp_core_install_friends() {
209
  */
210
  function bp_core_install_groups() {
211
  $sql = array();
212
- $charset_collate = bp_core_set_charset();
213
  $bp_prefix = bp_core_get_table_prefix();
214
 
215
  $sql[] = "CREATE TABLE {$bp_prefix}bp_groups (
@@ -219,10 +202,12 @@ function bp_core_install_groups() {
219
  slug varchar(200) NOT NULL,
220
  description longtext NOT NULL,
221
  status varchar(10) NOT NULL DEFAULT 'public',
 
222
  enable_forum tinyint(1) NOT NULL DEFAULT '1',
223
  date_created datetime NOT NULL,
224
  KEY creator_id (creator_id),
225
- KEY status (status)
 
226
  ) {$charset_collate};";
227
 
228
  $sql[] = "CREATE TABLE {$bp_prefix}bp_groups_members (
@@ -266,7 +251,7 @@ function bp_core_install_groups() {
266
  */
267
  function bp_core_install_private_messaging() {
268
  $sql = array();
269
- $charset_collate = bp_core_set_charset();
270
  $bp_prefix = bp_core_get_table_prefix();
271
 
272
  $sql[] = "CREATE TABLE {$bp_prefix}bp_messages_messages (
@@ -325,7 +310,7 @@ function bp_core_install_extended_profiles() {
325
  global $wpdb;
326
 
327
  $sql = array();
328
- $charset_collate = bp_core_set_charset();
329
  $bp_prefix = bp_core_get_table_prefix();
330
 
331
  // These values should only be updated if they are not already present.
@@ -410,7 +395,7 @@ function bp_core_install_extended_profiles() {
410
  */
411
  function bp_core_install_blog_tracking() {
412
  $sql = array();
413
- $charset_collate = bp_core_set_charset();
414
  $bp_prefix = bp_core_get_table_prefix();
415
 
416
  $sql[] = "CREATE TABLE {$bp_prefix}bp_user_blogs (
@@ -517,10 +502,16 @@ function bp_core_install_emails() {
517
  );
518
 
519
  $emails = bp_email_get_schema();
520
- $descriptions = bp_email_get_type_schema();
521
 
522
  // Add these emails to the database.
523
  foreach ( $emails as $id => $email ) {
 
 
 
 
 
 
524
  $post_id = wp_insert_post( bp_parse_args( $email, $defaults, 'install_email_' . $id ) );
525
  if ( ! $post_id ) {
526
  continue;
@@ -535,6 +526,8 @@ function bp_core_install_emails() {
535
  }
536
  }
537
 
 
 
538
  /**
539
  * Fires after BuddyPress adds the posts for its emails.
540
  *
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  /**
14
  * Main installer.
15
  *
76
  */
77
  function bp_core_install_notifications() {
78
  $sql = array();
79
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
80
  $bp_prefix = bp_core_get_table_prefix();
81
 
82
  $sql[] = "CREATE TABLE {$bp_prefix}bp_notifications (
117
  */
118
  function bp_core_install_activity_streams() {
119
  $sql = array();
120
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
121
  $bp_prefix = bp_core_get_table_prefix();
122
 
123
  $sql[] = "CREATE TABLE {$bp_prefix}bp_activity (
167
  */
168
  function bp_core_install_friends() {
169
  $sql = array();
170
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
171
  $bp_prefix = bp_core_get_table_prefix();
172
 
173
  $sql[] = "CREATE TABLE {$bp_prefix}bp_friends (
192
  */
193
  function bp_core_install_groups() {
194
  $sql = array();
195
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
196
  $bp_prefix = bp_core_get_table_prefix();
197
 
198
  $sql[] = "CREATE TABLE {$bp_prefix}bp_groups (
202
  slug varchar(200) NOT NULL,
203
  description longtext NOT NULL,
204
  status varchar(10) NOT NULL DEFAULT 'public',
205
+ parent_id bigint(20) NOT NULL DEFAULT 0,
206
  enable_forum tinyint(1) NOT NULL DEFAULT '1',
207
  date_created datetime NOT NULL,
208
  KEY creator_id (creator_id),
209
+ KEY status (status),
210
+ KEY parent_id (parent_id)
211
  ) {$charset_collate};";
212
 
213
  $sql[] = "CREATE TABLE {$bp_prefix}bp_groups_members (
251
  */
252
  function bp_core_install_private_messaging() {
253
  $sql = array();
254
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
255
  $bp_prefix = bp_core_get_table_prefix();
256
 
257
  $sql[] = "CREATE TABLE {$bp_prefix}bp_messages_messages (
310
  global $wpdb;
311
 
312
  $sql = array();
313
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
314
  $bp_prefix = bp_core_get_table_prefix();
315
 
316
  // These values should only be updated if they are not already present.
395
  */
396
  function bp_core_install_blog_tracking() {
397
  $sql = array();
398
+ $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
399
  $bp_prefix = bp_core_get_table_prefix();
400
 
401
  $sql[] = "CREATE TABLE {$bp_prefix}bp_user_blogs (
502
  );
503
 
504
  $emails = bp_email_get_schema();
505
+ $descriptions = bp_email_get_type_schema( 'description' );
506
 
507
  // Add these emails to the database.
508
  foreach ( $emails as $id => $email ) {
509
+
510
+ // Some emails are multisite-only.
511
+ if ( ! is_multisite() && isset( $email['args'] ) && ! empty( $email['args']['multisite'] ) ) {
512
+ continue;
513
+ }
514
+
515
  $post_id = wp_insert_post( bp_parse_args( $email, $defaults, 'install_email_' . $id ) );
516
  if ( ! $post_id ) {
517
  continue;
526
  }
527
  }
528
 
529
+ bp_update_option( 'bp-emails-unsubscribe-salt', base64_encode( wp_generate_password( 64, true, true ) ) );
530
+
531
  /**
532
  * Fires after BuddyPress adds the posts for its emails.
533
  *
bp-core/admin/bp-core-admin-settings.php CHANGED
@@ -47,6 +47,38 @@ function bp_admin_setting_callback_account_deletion() {
47
  <?php
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  /** Activity *******************************************************************/
51
 
52
  /**
@@ -72,7 +104,7 @@ function bp_admin_setting_callback_activity_akismet() {
72
  }
73
 
74
  /**
75
- * Allow activity comments on blog posts and forum posts.
76
  *
77
  * @since 1.6.0
78
  */
@@ -80,7 +112,7 @@ function bp_admin_setting_callback_blogforum_comments() {
80
  ?>
81
 
82
  <input id="bp-disable-blogforum-comments" name="bp-disable-blogforum-comments" type="checkbox" value="1" <?php checked( !bp_disable_blogforum_comments( false ) ); ?> />
83
- <label for="bp-disable-blogforum-comments"><?php _e( 'Allow activity stream commenting on blog and forum posts', 'buddypress' ); ?></label>
84
 
85
  <?php
86
  }
@@ -102,7 +134,7 @@ function bp_admin_setting_callback_heartbeat() {
102
  /**
103
  * Sanitization for bp-disable-blogforum-comments setting.
104
  *
105
- * In the UI, a checkbox asks whether you'd like to *enable* blog/forum activity comments. For
106
  * legacy reasons, the option that we store is 1 if these comments are *disabled*. So we use this
107
  * function to flip the boolean before saving the intval.
108
  *
@@ -215,40 +247,6 @@ function bp_admin_setting_callback_group_cover_image_uploads() {
215
  <?php
216
  }
217
 
218
- /** Forums Section ************************************************************/
219
-
220
- /**
221
- * Forums settings section description for the settings page.
222
- *
223
- * @since 1.6.0
224
- */
225
- function bp_admin_setting_callback_bbpress_section() { }
226
-
227
- /**
228
- * The bb-config.php location field.
229
- *
230
- * @since 1.6.0
231
- *
232
- */
233
- function bp_admin_setting_callback_bbpress_configuration() {
234
-
235
- $config_location = bp_get_option( 'bb-config-location' );
236
- $file_exists = (bool) ( file_exists( $config_location ) || is_file( $config_location ) ); ?>
237
-
238
- <input name="bb-config-location" type="text" id="bb-config-location" value="<?php bp_form_option( 'bb-config-location', '' ); ?>" class="medium-text" style="width: 300px;" />
239
-
240
- <?php if ( false === $file_exists ) : ?>
241
-
242
- <a class="button" href="<?php bp_admin_url( 'admin.php?page=bb-forums-setup&repair=1' ); ?>" title="<?php esc_attr_e( 'Attempt to save a new config file.', 'buddypress' ); ?>"><?php _e( 'Repair', 'buddypress' ) ?></a>
243
- <span class="attention"><?php _e( 'File does not exist', 'buddypress' ); ?></span>
244
-
245
- <?php endif; ?>
246
-
247
- <p class="description"><?php _e( 'Absolute path to your bbPress configuration file.', 'buddypress' ); ?></p>
248
-
249
- <?php
250
- }
251
-
252
  /** Settings Page *************************************************************/
253
 
254
  /**
47
  <?php
48
  }
49
 
50
+ /**
51
+ * Form element to change the active template pack.
52
+ */
53
+ function bp_admin_setting_callback_theme_package_id() {
54
+ $options = '';
55
+
56
+ /*
57
+ * Note: This should never be empty. /bp-templates/ is the
58
+ * canonical backup if no other packages exist. If there's an error here,
59
+ * something else is wrong.
60
+ *
61
+ * See BuddyPress::register_theme_packages()
62
+ */
63
+ foreach ( (array) buddypress()->theme_compat->packages as $id => $theme ) {
64
+ $options .= sprintf(
65
+ '<option value="%1$s" %2$s>%3$s</option>',
66
+ esc_attr( $id ),
67
+ selected( $theme->id, bp_get_theme_package_id(), false ),
68
+ esc_html( $theme->name )
69
+ );
70
+ }
71
+
72
+ if ( $options ) : ?>
73
+ <select name="_bp_theme_package_id" id="_bp_theme_package_id"><?php echo $options; ?></select>
74
+ <p class="description"><label for="_bp_theme_package_id"><?php esc_html_e( 'The selected Template Pack will serve all BuddyPress templates.', 'buddypress' ); ?></label></p>
75
+
76
+ <?php else : ?>
77
+ <p><?php esc_html_e( 'No template packages available.', 'buddypress' ); ?></p>
78
+
79
+ <?php endif;
80
+ }
81
+
82
  /** Activity *******************************************************************/
83
 
84
  /**
104
  }
105
 
106
  /**
107
+ * Allow activity comments on posts and comments.
108
  *
109
  * @since 1.6.0
110
  */
112
  ?>
113
 
114
  <input id="bp-disable-blogforum-comments" name="bp-disable-blogforum-comments" type="checkbox" value="1" <?php checked( !bp_disable_blogforum_comments( false ) ); ?> />
115
+ <label for="bp-disable-blogforum-comments"><?php _e( 'Allow activity stream commenting on posts and comments', 'buddypress' ); ?></label>
116
 
117
  <?php
118
  }
134
  /**
135
  * Sanitization for bp-disable-blogforum-comments setting.
136
  *
137
+ * In the UI, a checkbox asks whether you'd like to *enable* post/comment activity comments. For
138
  * legacy reasons, the option that we store is 1 if these comments are *disabled*. So we use this
139
  * function to flip the boolean before saving the intval.
140
  *
247
  <?php
248
  }
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  /** Settings Page *************************************************************/
251
 
252
  /**
bp-core/admin/bp-core-admin-slugs.php CHANGED
@@ -109,7 +109,6 @@ function bp_core_admin_get_static_pages() {
109
  * @todo Use settings API
110
  */
111
  function bp_core_admin_slugs_options() {
112
- $bp = buddypress();
113
 
114
  // Get the existing WP pages
115
  $existing_pages = bp_core_get_directory_page_ids();
@@ -184,12 +183,20 @@ function bp_core_admin_slugs_options() {
184
 
185
  <h3><?php _e( 'Registration', 'buddypress' ); ?></h3>
186
 
187
- <p><?php _e( 'Associate WordPress Pages with the following BuddyPress Registration pages.', 'buddypress' ); ?></p>
 
 
 
 
 
 
 
 
188
 
189
  <table class="form-table">
190
  <tbody>
191
 
192
- <?php foreach ( $static_pages as $name => $label ) : ?>
193
 
194
  <tr valign="top">
195
  <th scope="row">
@@ -218,7 +225,7 @@ function bp_core_admin_slugs_options() {
218
  </td>
219
  </tr>
220
 
221
- <?php endforeach ?>
222
 
223
  <?php
224
 
109
  * @todo Use settings API
110
  */
111
  function bp_core_admin_slugs_options() {
 
112
 
113
  // Get the existing WP pages
114
  $existing_pages = bp_core_get_directory_page_ids();
183
 
184
  <h3><?php _e( 'Registration', 'buddypress' ); ?></h3>
185
 
186
+ <?php if ( bp_get_signup_allowed() ) : ?>
187
+ <p><?php _e( 'Associate WordPress Pages with the following BuddyPress Registration pages.', 'buddypress' ); ?></p>
188
+ <?php else : ?>
189
+ <?php if ( is_multisite() ) : ?>
190
+ <p><?php printf( __( 'Registration is currently disabled. Before associating a page is allowed, please enable registration by selecting either the "User accounts may be registered" or "Both sites and user accounts can be registered" option on <a href="%s">this page</a>.', 'buddypress' ), network_admin_url( 'settings.php' ) ); ?></p>
191
+ <?php else : ?>
192
+ <p><?php printf( __( 'Registration is currently disabled. Before associating a page is allowed, please enable registration by clicking on the "Anyone can register" checkbox on <a href="%s">this page</a>.', 'buddypress' ), admin_url( 'options-general.php' ) ); ?></p>
193
+ <?php endif; ?>
194
+ <?php endif; ?>
195
 
196
  <table class="form-table">
197
  <tbody>
198
 
199
+ <?php if ( bp_get_signup_allowed() ) : foreach ( $static_pages as $name => $label ) : ?>
200
 
201
  <tr valign="top">
202
  <th scope="row">
225
  </td>
226
  </tr>
227
 
228
+ <?php endforeach; endif; ?>
229
 
230
  <?php
231
 
bp-core/admin/bp-core-admin-tools.php CHANGED
@@ -21,42 +21,33 @@ function bp_core_admin_tools() {
21
 
22
  <h1><?php esc_html_e( 'BuddyPress Tools', 'buddypress' ) ?></h1>
23
 
24
- <p>
25
- <?php esc_html_e( 'BuddyPress keeps track of various relationships between members, groups, and activity items. Occasionally these relationships become out of sync, most often after an import, update, or migration.', 'buddypress' ); ?>
26
- <?php esc_html_e( 'Use the tools below to manually recalculate these relationships.', 'buddypress' ); ?>
27
  </p>
28
  <p class="description"><?php esc_html_e( 'Some of these tools create substantial database overhead. Avoid running more than one repair job at a time.', 'buddypress' ); ?></p>
29
 
30
  <form class="settings" method="post" action="">
31
- <table class="form-table">
32
- <tbody>
33
- <tr valign="top">
34
- <th scope="row"><?php esc_html_e( 'Repair tools', 'buddypress' ) ?></th>
35
- <td>
36
- <fieldset>
37
- <legend class="screen-reader-text"><span><?php
38
- /* translators: accessibility text */
39
- esc_html_e( 'Repair', 'buddypress' );
40
- ?></span></legend>
41
-
42
- <?php foreach ( bp_admin_repair_list() as $item ) : ?>
43
-
44
- <label for="<?php echo esc_attr( str_replace( '_', '-', $item[0] ) ); ?>"><input type="checkbox" class="checkbox" name="<?php echo esc_attr( $item[0] ) . '" id="' . esc_attr( str_replace( '_', '-', $item[0] ) ); ?>" value="1" /> <?php echo esc_html( $item[1] ); ?></label><br />
45
-
46
- <?php endforeach; ?>
47
-
48
- </fieldset>
49
- </td>
50
- </tr>
51
- </tbody>
52
- </table>
53
-
54
- <fieldset class="submit">
55
- <input class="button-primary" type="submit" name="bp-tools-submit" value="<?php esc_attr_e( 'Repair Items', 'buddypress' ); ?>" />
56
- <?php wp_nonce_field( 'bp-do-counts' ); ?>
57
  </fieldset>
 
58
  </form>
 
59
  </div>
 
60
  <?php
61
  }
62
 
@@ -337,7 +328,7 @@ function bp_admin_repair_last_activity() {
337
  *
338
  * @param string $message Feedback message.
339
  * @param string|bool $class Unused.
340
- * @return bool
341
  */
342
  function bp_admin_tools_feedback( $message, $class = false ) {
343
  if ( is_string( $message ) ) {
@@ -366,7 +357,7 @@ function bp_admin_tools_feedback( $message, $class = false ) {
366
 
367
  $message = '<div id="message" class="' . esc_attr( $class ) . '">' . $message . '</div>';
368
  $message = str_replace( "'", "\'", $message );
369
- $lambda = create_function( '', "echo '$message';" );
370
 
371
  add_action( bp_core_do_network_admin() ? 'network_admin_notices' : 'admin_notices', $lambda );
372
 
21
 
22
  <h1><?php esc_html_e( 'BuddyPress Tools', 'buddypress' ) ?></h1>
23
 
24
+ <p><?php esc_html_e( 'BuddyPress keeps track of various relationships between members, groups, and activity items. Occasionally these relationships become out of sync, most often after an import, update, or migration.', 'buddypress' ); ?></p>
25
+ <p><?php esc_html_e( 'Use the tools below to manually recalculate these relationships.', 'buddypress' ); ?>
 
26
  </p>
27
  <p class="description"><?php esc_html_e( 'Some of these tools create substantial database overhead. Avoid running more than one repair job at a time.', 'buddypress' ); ?></p>
28
 
29
  <form class="settings" method="post" action="">
30
+
31
+ <fieldset>
32
+ <legend><?php esc_html_e( 'Repair tools', 'buddypress' ) ?></legend>
33
+
34
+ <div class="checkbox">
35
+ <?php foreach ( bp_admin_repair_list() as $item ) : ?>
36
+ <label for="<?php echo esc_attr( str_replace( '_', '-', $item[0] ) ); ?>"><input type="checkbox" class="checkbox" name="<?php echo esc_attr( $item[0] ) . '" id="' . esc_attr( str_replace( '_', '-', $item[0] ) ); ?>" value="1" /> <?php echo esc_html( $item[1] ); ?></label>
37
+ <?php endforeach; ?>
38
+ </div>
39
+
40
+ <p class="submit">
41
+ <input class="button-primary" type="submit" name="bp-tools-submit" value="<?php esc_attr_e( 'Repair Items', 'buddypress' ); ?>" />
42
+ <?php wp_nonce_field( 'bp-do-counts' ); ?>
43
+ </p>
44
+
 
 
 
 
 
 
 
 
 
 
 
45
  </fieldset>
46
+
47
  </form>
48
+
49
  </div>
50
+
51
  <?php
52
  }
53
 
328
  *
329
  * @param string $message Feedback message.
330
  * @param string|bool $class Unused.
331
+ * @return false|Closure
332
  */
333
  function bp_admin_tools_feedback( $message, $class = false ) {
334
  if ( is_string( $message ) ) {
357
 
358
  $message = '<div id="message" class="' . esc_attr( $class ) . '">' . $message . '</div>';
359
  $message = str_replace( "'", "\'", $message );
360
+ $lambda = function() use ( $message ) { echo $message; };
361
 
362
  add_action( bp_core_do_network_admin() ? 'network_admin_notices' : 'admin_notices', $lambda );
363
 
bp-core/admin/css/common-rtl.css CHANGED
@@ -12,15 +12,18 @@ TABLE OF CONTENTS:
12
  1.1 Version Badge
13
  1.2 About Panel
14
  1.2.1 Headline Feature
15
- 1.2.2 Columns
16
- 1.2.3 Features Section
17
- 1.2.4 Changelog Section
18
  2.0 Dashicons
19
  2.1 Top level menus
20
  2.2 Settings - Components
21
  2.3 Tools
22
- 3.0 User's Lists
 
 
23
  4.0 Emails - Edit page
 
 
24
  ------------------------------------------------------------------------------*/
25
 
26
  /*------------------------------------------------------------------------------
@@ -33,7 +36,7 @@ TABLE OF CONTENTS:
33
  .bp-badge {
34
  color: #d84800;
35
  display: inline-block;
36
- font: normal 150px/1 'dashicons' !important;
37
  }
38
 
39
  .bp-badge:before {
@@ -46,7 +49,15 @@ TABLE OF CONTENTS:
46
  left: 0;
47
  }
48
 
 
 
 
 
 
 
 
49
  @media only screen and (max-width: 500px) {
 
50
  .about-wrap .bp-badge {
51
  position: relative;
52
  margin: 10px auto;
@@ -62,139 +73,370 @@ TABLE OF CONTENTS:
62
  /*
63
  * 1.2.1 Headline Feature
64
  */
65
- .index_page_bp-about .about-wrap .headline-feature,
66
- .dashboard_page_bp-about .about-wrap .headline-feature {
67
  margin-bottom: 2em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  text-align: center;
 
69
  }
70
 
71
- .index_page_bp-about .about-wrap .headline-feature h3,
72
- .index_page_bp-about .headline-feature .headline-title,
73
- .dashboard_page_bp-about .about-wrap .headline-feature h3,
74
- .dashboard_page_bp-about .headline-feature .headline-title {
75
  font-size: 2.2em;
76
- font-weight: normal;
77
- line-height: 1.3;
78
- margin: 1.25em 0 0.6em;
79
  text-align: center;
80
  }
81
 
82
- .index_page_bp-about .about-wrap .headline-feature p,
83
- .dashboard_page_bp-about .about-wrap .headline-feature p {
84
  font-size: 1.15em;
85
- margin: 1.15em auto 0.6em;
86
- }
87
-
88
- .index_page_bp-about .about-wrap .headline-feature .introduction,
89
- .dashboard_page_bp-about .about-wrap .headline-feature .introduction {
90
- font-weight: 600;
91
  }
92
 
93
  /*
94
- * 1.2.2 Columns
95
  */
96
- .index_page_bp-about .about-wrap .two-col > div,
97
- .dashboard_page_bp-about .about-wrap .two-col > div {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  float: right;
 
99
  margin-left: 4.799999999%;
100
- position: relative;
101
  width: 47.6%;
102
  }
103
 
104
- .index_page_bp-about .about-wrap .two-col .last-feature,
105
- .dashboard_page_bp-about .about-wrap .two-col .last-feature {
106
  margin-left: 0;
107
  }
108
 
109
- /*
110
- * 1.2.3 Features Section
111
- */
112
- .index_page_bp-about .bp-features-section,
113
- .dashboard_page_bp-about .bp-features-section {
114
- margin-bottom: 2em;
115
  }
116
 
117
- .index_page_bp-about .about-wrap .feature-section,
118
- .dashboard_page_bp-about .about-wrap .feature-section {
119
  clear: both;
120
- margin-top: 2em;
121
- overflow: hidden;
122
- padding-bottom: 0;
123
  }
124
 
125
- .index_page_bp-about .about-wrap .changelog .feature-section,
126
- .dashboard_page_bp-about .about-wrap .changelog .feature-section {
 
 
127
  margin-top: 0;
128
  }
129
 
130
- .index_page_bp-about .about-wrap .feature-section h3,
131
- .dashboard_page_bp-about .about-wrap .feature-section h3 {
132
- font-size: 1.25em;
133
- line-height: 1.5em;
134
- margin: 0 0 0.6em;
135
  }
136
 
137
- .index_page_bp-about .about-wrap .changelog h4,
138
- .dashboard_page_bp-about .about-wrap .changelog h4 {
139
- color: #23282d;
 
 
140
  font-size: 1em;
141
- margin: 1.4em 0 0.6em;
 
 
 
 
 
 
 
 
142
  }
143
 
144
  /*
145
- * 1.2.4 Changelog Section
146
  */
147
- .index_page_bp-about .about-wrap .changelog,
148
- .dashboard_page_bp-about .about-wrap .changelog {
149
- border-top: 1px solid #eee;
150
  margin-bottom: 3em;
 
 
151
  }
152
 
153
- .index_page_bp-about .about-wrap .changelog .changelog-title,
154
- .dashboard_page_bp-about .about-wrap .changelog .changelog-title {
 
 
 
 
 
 
155
  font-size: 1.25em;
156
- line-height: 1.5em;
157
- margin: 1.25em 0 .6em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  text-align: center;
159
  }
160
 
 
 
 
 
 
161
  @media screen and ( max-width: 782px ) {
162
- .index_page_bp-about .about-wrap .headline-feature,
163
- .dashboard_page_bp-about .about-wrap .headline-feature {
164
- max-width: 100%;
165
- }
166
- .index_page_bp-about .about-wrap .headline-feature h3,
167
- .dahsboard_page_bp-about .about-wrap .headline-feature h3,
168
- .index_page_bp-about .about-wrap .headline-feature .headline-title,
169
- .dashboard_page_bp-about .about-wrap .headline-feature .headline-title {
170
- font-size: 2em;
171
- }
172
- .index_page_bp-about .bp-features-section,
173
- .dashboard_page_bp-about .bp-features-section {
 
 
 
 
 
 
 
 
174
  margin-bottom: 0;
 
 
175
  }
176
- .index_page_bp-about .about-wrap .feature-section,
177
- .dashboard_page_bp-about .about-wrap .feature-section {
178
- margin-top: 0;
 
 
 
 
179
  }
180
- .index_page_bp-about .about-wrap .two-col > div,
181
- .dashboard_page_bp-about .about-wrap .two-col > div {
182
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
183
- margin-top: 1.25em;
184
- padding-bottom: 1em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  width: 100%;
186
  }
187
- .index_page_bp-about .changelog .two-col > div,
188
- .dashboard_page_bp-about .changelog .two-col > div {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  margin-top: 0;
190
- padding-bottom: 0;
 
191
  }
192
- .index_page_bp-about .about-wrap .changelog .changelog-title,
193
- .dashboard_page_bp-about .about-wrap .changelog .changelog-title {
194
- text-align: right;
195
  }
196
  }
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  /*------------------------------------------------------------------------------
200
  * 2.0 Dashicons
@@ -229,7 +471,7 @@ TABLE OF CONTENTS:
229
 
230
  #adminmenu #toplevel_page_bp-friends .wp-menu-image:before,
231
  #adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before,
232
- #adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before{
233
  content: "\f454";
234
  }
235
 
@@ -255,7 +497,7 @@ TABLE OF CONTENTS:
255
  }
256
 
257
  .settings_page_bp-components td.plugin-title span:before {
258
- font-family: 'dashicons';
259
  font-size: 18px;
260
  }
261
 
@@ -283,10 +525,6 @@ TABLE OF CONTENTS:
283
  content: "\f457";
284
  }
285
 
286
- .settings_page_bp-components tr.forums td.plugin-title span:before {
287
- content: "\f452";
288
- }
289
-
290
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
291
  content: "\f120";
292
  }
@@ -308,13 +546,16 @@ TABLE OF CONTENTS:
308
  }
309
 
310
  @media screen and ( max-width: 782px ) {
 
311
  .settings_page_bp-components td.plugin-title span {
312
  margin-top: 5px;
313
  }
 
314
  #bp-admin-component-form .wp-list-table.plugins .plugin-title {
315
  display: block;
316
  width: auto;
317
  }
 
318
  #bp-admin-component-form .subsubsub {
319
  margin-bottom: 0;
320
  padding-bottom: 35px;
@@ -330,8 +571,12 @@ TABLE OF CONTENTS:
330
 
331
 
332
  /*------------------------------------------------------------------------------
333
- * 3.0 User's Lists
334
  *----------------------------------------------------------------------------*/
 
 
 
 
335
  body.site-users-php th#role,
336
  body.users-php th#role,
337
  body.users_page_bp-signups th#count_sent {
@@ -360,6 +605,100 @@ body.users_page_bp-signups td.count_sent {
360
  text-align: center;
361
  }
362
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
 
364
  /*------------------------------------------------------------------------------
365
  * 4.0 Emails - Edit Page
@@ -382,3 +721,63 @@ body.post-type-bp-email .categorydiv label {
382
  padding-right: 25px;
383
  text-indent: -25px;
384
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  1.1 Version Badge
13
  1.2 About Panel
14
  1.2.1 Headline Feature
15
+ 1.2.2 Features Section
16
+ 1.2.3 Changelog Section
 
17
  2.0 Dashicons
18
  2.1 Top level menus
19
  2.2 Settings - Components
20
  2.3 Tools
21
+ 3.0 Users
22
+ 3.1 Users List
23
+ 3.2 Site Notices
24
  4.0 Emails - Edit page
25
+ 5.0 Tools - BuddyPress
26
+ 6.0 Plugins page
27
  ------------------------------------------------------------------------------*/
28
 
29
  /*------------------------------------------------------------------------------
36
  .bp-badge {
37
  color: #d84800;
38
  display: inline-block;
39
+ font: 400 150px/1 dashicons !important;
40
  }
41
 
42
  .bp-badge:before {
49
  left: 0;
50
  }
51
 
52
+ .index_page_bp-credits code,
53
+ .index_page_bp-about code {
54
+ background-color: #e0e0e0;
55
+ color: #636363;
56
+ font-size: 1em;
57
+ }
58
+
59
  @media only screen and (max-width: 500px) {
60
+
61
  .about-wrap .bp-badge {
62
  position: relative;
63
  margin: 10px auto;
73
  /*
74
  * 1.2.1 Headline Feature
75
  */
76
+ .buddypress .bp-headline-feature {
 
77
  margin-bottom: 2em;
78
+ margin-top: 3em;
79
+ padding: 2em 3em;
80
+ }
81
+
82
+ .buddypress .bp-headline {
83
+ margin: 0 auto;
84
+ width: 45em;
85
+ }
86
+
87
+ .buddypress .bp-headline span.dashicons {
88
+ background-color: #f1f1f1;
89
+ color: #d84800;
90
+ clear: right;
91
+ font-size: 100px;
92
+ float: right;
93
+ height: 100px;
94
+ line-height: 100px;
95
+ margin: 0 0 15px 15px;
96
  text-align: center;
97
+ width: 100px;
98
  }
99
 
100
+ .buddypress .bp-headline-feature .headline-title {
 
 
 
101
  font-size: 2.2em;
102
+ font-weight: 300;
103
+ line-height: 2;
104
+ margin: 0 0 1em;
105
  text-align: center;
106
  }
107
 
108
+ .buddypress .bp-headline-feature p {
 
109
  font-size: 1.15em;
110
+ margin: 1.15em 0 0.6em auto;
 
 
 
 
 
111
  }
112
 
113
  /*
114
+ * 1.2.2 Features Section
115
  */
116
+ .buddypress .bp-features-section {
117
+ border-bottom: 1px solid #ccc;
118
+ clear: both;
119
+ margin-bottom: 3em;
120
+ margin-top: 2em;
121
+ overflow: hidden;
122
+ padding-bottom: 2em;
123
+ }
124
+
125
+ .buddypress .bp-features-section p {
126
+ font-size: 14px;
127
+ line-height: 1.5;
128
+ }
129
+
130
+ .buddypress .bp-features-section img {
131
+ margin-bottom: 20px;
132
+ }
133
+
134
+ .buddypress .bp-features-section span.dashicons {
135
+ background-color: #fff;
136
+ border-radius: 50%;
137
+ clear: right;
138
+ color: #d84800;
139
+ font-size: 50px;
140
+ float: right;
141
+ height: 80px;
142
+ line-height: 80px;
143
+ margin: 0 0 15px 15px;
144
+ text-align: center;
145
+ width: 80px;
146
+ }
147
+
148
+ .buddypress .bp-features-section .headline-title {
149
+ font-size: 2em;
150
+ font-weight: 300;
151
+ line-height: 1.5;
152
+ margin: 1em auto 2em;
153
+ text-align: center;
154
+ }
155
+
156
+ .buddypress .bp-features-section .bp-feature-with-images {
157
+ border-bottom: 1px solid #ccc;
158
+ margin-bottom: 5em;
159
+ padding-bottom: 2em;
160
+ }
161
+
162
+ .buddypress .bp-features-section .bp-feature,
163
+ .buddypress .bp-features-section .bp-feature-imaged {
164
  float: right;
165
+ margin-bottom: 3em;
166
  margin-left: 4.799999999%;
 
167
  width: 47.6%;
168
  }
169
 
170
+ .buddypress .bp-features-section .bp-feature.opposite,
171
+ .buddypress .bp-features-section .bp-feature-imaged.anon {
172
  margin-left: 0;
173
  }
174
 
175
+ .buddypress .bp-features-section .bp-feature code {
176
+ font-size: 0.95em;
177
+ line-height: 1.5;
 
 
 
178
  }
179
 
180
+ .buddypress .bp-feature:after {
 
181
  clear: both;
182
+ content: "";
183
+ margin-bottom: 2em;
 
184
  }
185
 
186
+ .buddypress .bp-feature-imaged .feature-title {
187
+ color: #23282d;
188
+ font-size: 1.25em;
189
+ margin-bottom: 0.6em;
190
  margin-top: 0;
191
  }
192
 
193
+ .buddypress .bp-feature-imaged p {
194
+ clear: right;
195
+ font-size: 1.1em;
 
 
196
  }
197
 
198
+ .buddypress .bp-feature-imaged img {
199
+ clear: right;
200
+ }
201
+
202
+ .buddypress .bp-feature .feature-title {
203
  font-size: 1em;
204
+ line-height: 1.5;
205
+ margin-bottom: 0;
206
+ margin-right: 110px;
207
+ margin-top: 0;
208
+ text-align: right;
209
+ }
210
+
211
+ .buddypress .bp-feature p {
212
+ margin-right: 110px;
213
  }
214
 
215
  /*
216
+ * 1.2.3 Changelog Section
217
  */
218
+ .buddypress .bp-changelog-section {
219
+ clear: both;
 
220
  margin-bottom: 3em;
221
+ margin-top: 4em;
222
+ padding-bottom: 0;
223
  }
224
 
225
+ .buddypress .bp-changelog-section:after {
226
+ clear: both;
227
+ content: "";
228
+ display: table;
229
+ }
230
+
231
+ .buddypress .bp-changelog-section .changelog-title {
232
+ color: #23282d;
233
  font-size: 1.25em;
234
+ line-height: 1.5;
235
+ margin: 0 auto 1.5em;
236
+ }
237
+
238
+ .buddypress .bp-two-column div {
239
+ float: right;
240
+ margin-left: 4.799999999%;
241
+ position: relative;
242
+ width: 47.6%;
243
+ }
244
+
245
+ .buddypress .bp-three-column .bp-column {
246
+ float: right;
247
+ margin-left: 5%;
248
+ position: relative;
249
+ width: 29.95%;
250
+ }
251
+
252
+ .buddypress .bp-two-column .bp-column:nth-of-type(2n),
253
+ .buddypress .bp-three-column .bp-column:nth-of-type(3n) {
254
+ margin-left: 0;
255
+ }
256
+
257
+ .buddypress .bp-changelog {
258
+ margin-bottom: 3em;
259
+ }
260
+
261
+ .buddypress .bp-changelog:after {
262
+ clear: both;
263
+ content: "";
264
+ display: table;
265
+ }
266
+
267
+ .buddypress .bp-changelog .title {
268
+ font-size: 14px;
269
+ margin-bottom: 0.75em;
270
+ margin-top: 0;
271
+ }
272
+
273
+ .buddypress .bp-changelog p {
274
+ margin-bottom: 0;
275
+ }
276
+
277
+ .bp-changelog-url {
278
  text-align: center;
279
  }
280
 
281
+ .bp-assets {
282
+ clear: both;
283
+ margin-bottom: 3em;
284
+ }
285
+
286
  @media screen and ( max-width: 782px ) {
287
+
288
+ .bp-headline-feature,
289
+ .bp-features-section,
290
+ .bp-changelog-section,
291
+ .bp-assets {
292
+ margin-right: 20px;
293
+ margin-left: 20px;
294
+ }
295
+
296
+ .buddypress .bp-headline-feature {
297
+ padding: 0;
298
+ }
299
+
300
+ .buddypress .bp-headline {
301
+ margin: 0;
302
+ width: 97%;
303
+ }
304
+
305
+ .buddypress .bp-features-section {
306
+ clear: both;
307
  margin-bottom: 0;
308
+ margin-top: 2em;
309
+ padding-bottom: 2em;
310
  }
311
+
312
+ .buddypress .bp-features-section .bp-feature-with-images {
313
+ margin-bottom: 2em;
314
+ }
315
+
316
+ .buddypress .bp-features-section .headline-title {
317
+ margin-bottom: 1em;
318
  }
319
+
320
+ .buddypress .bp-changelog-section .changelog-title {
321
+ font-size: 1.25em;
322
+ line-height: 1.5;
323
+ margin-bottom: 0.5em;
324
+ margin-top: 0.5em;
325
+ }
326
+
327
+ .buddypress .bp-features-section .feature-title,
328
+ .buddypress .bp-changelog-section .title {
329
+ font-size: 1.25em;
330
+ line-height: 1.25;
331
+ margin-top: 0.6em;
332
+ text-align: right;
333
+ }
334
+
335
+ .buddypress .bp-features-section .bp-feature,
336
+ .buddypress .bp-features-section .bp-feature-imaged {
337
+ clear: both;
338
+ float: right;
339
+ margin-bottom: 1em;
340
+ margin-top: 1em;
341
+ margin-left: 0;
342
+ padding-left: 1em;
343
  width: 100%;
344
  }
345
+
346
+ .buddypress .bp-features-section .bp-feature-imaged p {
347
+ font-size: 1em;
348
+ }
349
+
350
+ .buddypress .bp-features-section .bp-feature span {
351
+ margin-top: 0.33em;
352
+ }
353
+
354
+ .buddypress .bp-feature.opposite .feature-title,
355
+ .buddypress .bp-feature.opposite p {
356
+ float: none;
357
+ }
358
+
359
+ .buddypress .bp-changelog-section {
360
+ clear: both;
361
+ margin-bottom: 2em;
362
+ margin-top: 2em;
363
+ }
364
+
365
+ .buddypress .bp-changelog {
366
+ margin-bottom: 0;
367
+ }
368
+
369
+ .buddypress .bp-changelog-section .changelog-title {
370
+ margin-bottom: 0.5em;
371
+ }
372
+
373
+ .buddypress .bp-changelog .title {
374
+ font-size: 1em;
375
+ }
376
+
377
+ .buddypress .bp-changelog p {
378
+ margin-bottom: 1em;
379
+ }
380
+
381
+ .buddypress .bp-changelog-section .two-col > div,
382
+ .buddypress .bp-changelog-section .three-col .col {
383
  margin-top: 0;
384
+ padding-bottom: 0.5em;
385
+ width: 100%;
386
  }
387
+
388
+ .buddypress .bp-three-column .bp-column {
389
+ width: 100%;
390
  }
391
  }
392
 
393
+ @media screen and ( max-width: 360px ) {
394
+
395
+ .buddypress .bp-headline {
396
+ text-align: center;
397
+ }
398
+
399
+ .buddypress .bp-headline span.dashicons {
400
+ clear: none;
401
+ font-size: 80px;
402
+ float: none;
403
+ height: 80px;
404
+ line-height: 80px;
405
+ margin: 0 auto;
406
+ width: 80px;
407
+ }
408
+
409
+ .buddypress .bp-headline-feature .headline-title,
410
+ .buddypress .bp-features-section .headline-title {
411
+ font-size: 1.5em;
412
+ line-height: 1.5;
413
+ text-align: right;
414
+ }
415
+
416
+ .buddypress .bp-headline-feature .headline-title {
417
+ margin: 1em 0 0;
418
+ }
419
+
420
+ .buddypress .bp-headline-feature p {
421
+ margin: 1.15em 0 0.6em auto;
422
+ text-align: right;
423
+ width: auto;
424
+ }
425
+
426
+ .buddypress .bp-features-section .bp-feature {
427
+ text-align: center;
428
+ }
429
+
430
+ .buddypress .bp-features-section span.dashicons {
431
+ float: none;
432
+ }
433
+
434
+ .buddypress .bp-features-section .feature-title,
435
+ .buddypress .bp-features-section p {
436
+ margin-right: 0;
437
+ text-align: right;
438
+ }
439
+ }
440
 
441
  /*------------------------------------------------------------------------------
442
  * 2.0 Dashicons
471
 
472
  #adminmenu #toplevel_page_bp-friends .wp-menu-image:before,
473
  #adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before,
474
+ #adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before {
475
  content: "\f454";
476
  }
477
 
497
  }
498
 
499
  .settings_page_bp-components td.plugin-title span:before {
500
+ font-family: dashicons;
501
  font-size: 18px;
502
  }
503
 
525
  content: "\f457";
526
  }
527
 
 
 
 
 
528
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
529
  content: "\f120";
530
  }
546
  }
547
 
548
  @media screen and ( max-width: 782px ) {
549
+
550
  .settings_page_bp-components td.plugin-title span {
551
  margin-top: 5px;
552
  }
553
+
554
  #bp-admin-component-form .wp-list-table.plugins .plugin-title {
555
  display: block;
556
  width: auto;
557
  }
558
+
559
  #bp-admin-component-form .subsubsub {
560
  margin-bottom: 0;
561
  padding-bottom: 35px;
571
 
572
 
573
  /*------------------------------------------------------------------------------
574
+ * 3.0 Users
575
  *----------------------------------------------------------------------------*/
576
+
577
+ /*
578
+ * 3.1 Users List
579
+ */
580
  body.site-users-php th#role,
581
  body.users-php th#role,
582
  body.users_page_bp-signups th#count_sent {
605
  text-align: center;
606
  }
607
 
608
+ .bp-signups-list table {
609
+ margin: 1em 0;
610
+ }
611
+
612
+ .bp-signups-list .column-fields {
613
+ font-weight: 700;
614
+ }
615
+
616
+ /*
617
+ * 3.2 Site Notices
618
+ */
619
+ .bp-new-notice-panel {
620
+ background: #fff;
621
+ border: 1px solid #e5e5e5;
622
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
623
+ font-size: 13px;
624
+ line-height: 2.1;
625
+ margin: 1.5em 0 3em;
626
+ overflow: auto;
627
+ padding: 10px 25px 25px;
628
+ position: relative;
629
+ }
630
+
631
+ .bp-new-notice-panel label {
632
+ clear: both;
633
+ float: right;
634
+ margin-left: 3%;
635
+ width: 20%;
636
+ }
637
+
638
+ .bp-new-notice-panel input,
639
+ .bp-new-notice-panel textarea {
640
+ clear: none;
641
+ margin-bottom: 1em;
642
+ width: 75%;
643
+ }
644
+
645
+ .bp-new-notice-panel input[type="text"]:after,
646
+ .bp-new-notice-panel textarea:after {
647
+ clear: both;
648
+ content: " ";
649
+ display: table;
650
+ }
651
+
652
+ .bp-new-notice-panel .button-primary {
653
+ margin-right: 23%;
654
+ width: auto;
655
+ }
656
+
657
+ .bp-notice-about {
658
+ font-size: 1em;
659
+ margin-bottom: 1em;
660
+ }
661
+
662
+ .bp-new-notice {
663
+ margin-bottom: 1em;
664
+ margin-top: 0;
665
+ }
666
+
667
+ .bp-notices-list {
668
+ margin-bottom: 0;
669
+ }
670
+
671
+ @media screen and (max-width: 782px) {
672
+
673
+ .bp-new-notice-panel {
674
+ margin-bottom: 1.5em;
675
+ }
676
+
677
+ .bp-new-notice-panel input,
678
+ .bp-new-notice-panel textarea {
679
+ margin-right: 0;
680
+ width: 100%;
681
+ }
682
+
683
+ .bp-new-notice-panel .button-primary {
684
+ margin-right: 0;
685
+ width: auto;
686
+ }
687
+
688
+ .bp-new-notice-panel .button {
689
+ max-width: 45%;
690
+ word-wrap: break-word;
691
+ }
692
+
693
+ .bp-notice-about {
694
+ margin-top: 0;
695
+ margin-bottom: 1em;
696
+ }
697
+
698
+ .bp-new-notice {
699
+ margin-bottom: 0.5em;
700
+ }
701
+ }
702
 
703
  /*------------------------------------------------------------------------------
704
  * 4.0 Emails - Edit Page
721
  padding-right: 25px;
722
  text-indent: -25px;
723
  }
724
+
725
+ /*------------------------------------------------------------------------------
726
+ * 5.0 Tools - BuddyPress
727
+ *----------------------------------------------------------------------------*/
728
+ .tools_page_bp-tools .wrap {
729
+ max-width: 950px;
730
+ }
731
+
732
+ .tools_page_bp-tools p {
733
+ line-height: 2;
734
+ }
735
+
736
+ .tools_page_bp-tools fieldset {
737
+ margin: 2em 0 0;
738
+ }
739
+
740
+ .tools_page_bp-tools legend {
741
+ color: #23282d;
742
+ font-size: 1.3em;
743
+ font-weight: 600;
744
+ margin: 1em 0;
745
+ }
746
+
747
+ .tools_page_bp-tools label {
748
+ clear: right;
749
+ display: block;
750
+ line-height: 1.5;
751
+ margin: 0 0 1em;
752
+ vertical-align: middle;
753
+ }
754
+
755
+ @media screen and (max-width: 782px) {
756
+
757
+ .tools_page_bp-tools p {
758
+ line-height: 1.5;
759
+ }
760
+
761
+ .tools_page_bp-tools label {
762
+ margin-bottom: 1em;
763
+ padding-left: 25px;
764
+ text-indent: -33px;
765
+ }
766
+
767
+ .tools_page_bp-tools .checkbox {
768
+ padding: 0 30px 0 0;
769
+ }
770
+ }
771
+
772
+
773
+ /*------------------------------------------------------------------------------
774
+ * 6.0 Plugins page
775
+ *----------------------------------------------------------------------------*/
776
+ #buddypress-update.not-shiny .update-message {
777
+ border-right: 0;
778
+ padding-right: 36px;
779
+ }
780
+
781
+ #buddypress-update.not-shiny .update-message:before {
782
+ content: "\f534";
783
+ }
bp-core/admin/css/common-rtl.min.css CHANGED
@@ -1 +1 @@
1
- .bp-badge{color:#d84800;display:inline-block;font:400 150px/1 dashicons!important}.bp-badge:before{content:"\f448"}.about-wrap .bp-badge{position:absolute;top:0;left:0}@media only screen and (max-width:500px){.about-wrap .bp-badge{position:relative;margin:10px auto;top:auto;left:auto}}.dashboard_page_bp-about .about-wrap .headline-feature,.index_page_bp-about .about-wrap .headline-feature{margin-bottom:2em;text-align:center}.dashboard_page_bp-about .about-wrap .headline-feature h3,.dashboard_page_bp-about .headline-feature .headline-title,.index_page_bp-about .about-wrap .headline-feature h3,.index_page_bp-about .headline-feature .headline-title{font-size:2.2em;font-weight:400;line-height:1.3;margin:1.25em 0 .6em;text-align:center}.dashboard_page_bp-about .about-wrap .headline-feature p,.index_page_bp-about .about-wrap .headline-feature p{font-size:1.15em;margin:1.15em auto .6em}.dashboard_page_bp-about .about-wrap .headline-feature .introduction,.index_page_bp-about .about-wrap .headline-feature .introduction{font-weight:600}.dashboard_page_bp-about .about-wrap .two-col>div,.index_page_bp-about .about-wrap .two-col>div{float:right;margin-left:4.799999999%;position:relative;width:47.6%}.dashboard_page_bp-about .about-wrap .two-col .last-feature,.index_page_bp-about .about-wrap .two-col .last-feature{margin-left:0}.dashboard_page_bp-about .bp-features-section,.index_page_bp-about .bp-features-section{margin-bottom:2em}.dashboard_page_bp-about .about-wrap .feature-section,.index_page_bp-about .about-wrap .feature-section{clear:both;margin-top:2em;overflow:hidden;padding-bottom:0}.dashboard_page_bp-about .about-wrap .changelog .feature-section,.index_page_bp-about .about-wrap .changelog .feature-section{margin-top:0}.dashboard_page_bp-about .about-wrap .feature-section h3,.index_page_bp-about .about-wrap .feature-section h3{font-size:1.25em;line-height:1.5em;margin:0 0 .6em}.dashboard_page_bp-about .about-wrap .changelog h4,.index_page_bp-about .about-wrap .changelog h4{color:#23282d;font-size:1em;margin:1.4em 0 .6em}.dashboard_page_bp-about .about-wrap .changelog,.index_page_bp-about .about-wrap .changelog{border-top:1px solid #eee;margin-bottom:3em}.dashboard_page_bp-about .about-wrap .changelog .changelog-title,.index_page_bp-about .about-wrap .changelog .changelog-title{font-size:1.25em;line-height:1.5em;margin:1.25em 0 .6em;text-align:center}@media screen and (max-width:782px){.dashboard_page_bp-about .about-wrap .headline-feature,.index_page_bp-about .about-wrap .headline-feature{max-width:100%}.dahsboard_page_bp-about .about-wrap .headline-feature h3,.dashboard_page_bp-about .about-wrap .headline-feature .headline-title,.index_page_bp-about .about-wrap .headline-feature .headline-title,.index_page_bp-about .about-wrap .headline-feature h3{font-size:2em}.dashboard_page_bp-about .bp-features-section,.index_page_bp-about .bp-features-section{margin-bottom:0}.dashboard_page_bp-about .about-wrap .feature-section,.index_page_bp-about .about-wrap .feature-section{margin-top:0}.dashboard_page_bp-about .about-wrap .two-col>div,.index_page_bp-about .about-wrap .two-col>div{border-bottom:1px solid rgba(0,0,0,.1);margin-top:1.25em;padding-bottom:1em;width:100%}.dashboard_page_bp-about .changelog .two-col>div,.index_page_bp-about .changelog .two-col>div{margin-top:0;padding-bottom:0}.dashboard_page_bp-about .about-wrap .changelog .changelog-title,.index_page_bp-about .about-wrap .changelog .changelog-title{text-align:right}}#adminmenu #toplevel_page_bp-activity .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_user .wp-menu-image:before{content:"\f452"}#adminmenu #toplevel_page_bp-groups .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_user .wp-menu-image:before{content:"\f456"}#adminmenu #toplevel_page_bp-notifications .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_user .wp-menu-image:before{content:"\f439"}#adminmenu #toplevel_page_bp-messages .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_user .wp-menu-image:before{content:"\f457"}#adminmenu #toplevel_page_bp-friends .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before{content:"\f454"}#adminmenu #toplevel_page_bp-settings .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_user .wp-menu-image:before{content:"\f108"}#adminmenu li.toplevel_page_bp-components .wp-menu-image,#adminmenu li.toplevel_page_bp-general-settings .wp-menu-image{content:"\f448"}.settings_page_bp-components td.plugin-title span{float:right;width:18px;height:18px;margin-left:5px}.settings_page_bp-components td.plugin-title span:before{font-family:dashicons;font-size:18px}.settings_page_bp-components tr.activity td.plugin-title span:before{content:"\f452"}.settings_page_bp-components tr.notifications td.plugin-title span:before{content:"\f339"}.settings_page_bp-components tr.xprofile td.plugin-title span:before{content:"\f336"}.settings_page_bp-components tr.settings td.plugin-title span:before{content:"\f108"}.settings_page_bp-components tr.groups td.plugin-title span:before{content:"\f456"}.settings_page_bp-components tr.messages td.plugin-title span:before{content:"\f457"}.settings_page_bp-components tr.forums td.plugin-title span:before{content:"\f452"}.settings_page_bp-components tr.blogs td.plugin-title span:before{content:"\f120"}.settings_page_bp-components tr.friends td.plugin-title span:before{content:"\f454"}.settings_page_bp-components tr.core td.plugin-title span:before{content:"\f448"}.settings_page_bp-components tr.members td.plugin-title span:before{content:"\f307"}#bp-admin-component-form .wp-list-table.plugins .plugin-title{width:25%}@media screen and (max-width:782px){.settings_page_bp-components td.plugin-title span{margin-top:5px}#bp-admin-component-form .wp-list-table.plugins .plugin-title{display:block;width:auto}#bp-admin-component-form .subsubsub{margin-bottom:0;padding-bottom:35px}}#adminmenu .toplevel_page_network-tools div.wp-menu-image:before{content:""}body.site-users-php th#role,body.users-php th#role,body.users_page_bp-signups th#count_sent{width:10%}body.site-users-php th#email,body.site-users-php th#name,body.users-php th#email,body.users-php th#name,body.users-php th#registered,body.users_page_bp-signups th#date_sent,body.users_page_bp-signups th#email,body.users_page_bp-signups th#name,body.users_page_bp-signups th#registered{width:15%}body.post-type-bp-email th#situation,body.users-php th#blogs,body.users_page_bp-signups th#blogs{width:20%}body.users_page_bp-signups td.count_sent,body.users_page_bp-signups th.column-count_sent{text-align:center}body.post-type-bp-email #excerpt{height:auto}body.post-type-bp-email td.column-situation ul{margin:0}body.post-type-bp-email .categorydiv label{display:block;float:right;padding-right:25px;text-indent:-25px}
1
+ .bp-badge{color:#d84800;display:inline-block;font:400 150px/1 dashicons!important}.bp-badge:before{content:"\f448"}.about-wrap .bp-badge{position:absolute;top:0;left:0}.index_page_bp-about code,.index_page_bp-credits code{background-color:#e0e0e0;color:#636363;font-size:1em}@media only screen and (max-width:500px){.about-wrap .bp-badge{position:relative;margin:10px auto;top:auto;left:auto}}.buddypress .bp-headline-feature{margin-bottom:2em;margin-top:3em;padding:2em 3em}.buddypress .bp-headline{margin:0 auto;width:45em}.buddypress .bp-headline span.dashicons{background-color:#f1f1f1;color:#d84800;clear:right;font-size:100px;float:right;height:100px;line-height:100px;margin:0 0 15px 15px;text-align:center;width:100px}.buddypress .bp-headline-feature .headline-title{font-size:2.2em;font-weight:300;line-height:2;margin:0 0 1em;text-align:center}.buddypress .bp-headline-feature p{font-size:1.15em;margin:1.15em 0 .6em auto}.buddypress .bp-features-section{border-bottom:1px solid #ccc;clear:both;margin-bottom:3em;margin-top:2em;overflow:hidden;padding-bottom:2em}.buddypress .bp-features-section p{font-size:14px;line-height:1.5}.buddypress .bp-features-section img{margin-bottom:20px}.buddypress .bp-features-section span.dashicons{background-color:#fff;border-radius:50%;clear:right;color:#d84800;font-size:50px;float:right;height:80px;line-height:80px;margin:0 0 15px 15px;text-align:center;width:80px}.buddypress .bp-features-section .headline-title{font-size:2em;font-weight:300;line-height:1.5;margin:1em auto 2em;text-align:center}.buddypress .bp-features-section .bp-feature-with-images{border-bottom:1px solid #ccc;margin-bottom:5em;padding-bottom:2em}.buddypress .bp-features-section .bp-feature,.buddypress .bp-features-section .bp-feature-imaged{float:right;margin-bottom:3em;margin-left:4.799999999%;width:47.6%}.buddypress .bp-features-section .bp-feature-imaged.anon,.buddypress .bp-features-section .bp-feature.opposite{margin-left:0}.buddypress .bp-features-section .bp-feature code{font-size:.95em;line-height:1.5}.buddypress .bp-feature:after{clear:both;content:"";margin-bottom:2em}.buddypress .bp-feature-imaged .feature-title{color:#23282d;font-size:1.25em;margin-bottom:.6em;margin-top:0}.buddypress .bp-feature-imaged p{clear:right;font-size:1.1em}.buddypress .bp-feature-imaged img{clear:right}.buddypress .bp-feature .feature-title{font-size:1em;line-height:1.5;margin-bottom:0;margin-right:110px;margin-top:0;text-align:right}.buddypress .bp-feature p{margin-right:110px}.buddypress .bp-changelog-section{clear:both;margin-bottom:3em;margin-top:4em;padding-bottom:0}.buddypress .bp-changelog-section:after{clear:both;content:"";display:table}.buddypress .bp-changelog-section .changelog-title{color:#23282d;font-size:1.25em;line-height:1.5;margin:0 auto 1.5em}.buddypress .bp-two-column div{float:right;margin-left:4.799999999%;position:relative;width:47.6%}.buddypress .bp-three-column .bp-column{float:right;margin-left:5%;position:relative;width:29.95%}.buddypress .bp-three-column .bp-column:nth-of-type(3n),.buddypress .bp-two-column .bp-column:nth-of-type(2n){margin-left:0}.buddypress .bp-changelog{margin-bottom:3em}.buddypress .bp-changelog:after{clear:both;content:"";display:table}.buddypress .bp-changelog .title{font-size:14px;margin-bottom:.75em;margin-top:0}.buddypress .bp-changelog p{margin-bottom:0}.bp-changelog-url{text-align:center}.bp-assets{clear:both;margin-bottom:3em}@media screen and (max-width:782px){.bp-assets,.bp-changelog-section,.bp-features-section,.bp-headline-feature{margin-right:20px;margin-left:20px}.buddypress .bp-headline-feature{padding:0}.buddypress .bp-headline{margin:0;width:97%}.buddypress .bp-features-section{clear:both;margin-bottom:0;margin-top:2em;padding-bottom:2em}.buddypress .bp-features-section .bp-feature-with-images{margin-bottom:2em}.buddypress .bp-features-section .headline-title{margin-bottom:1em}.buddypress .bp-changelog-section .changelog-title{font-size:1.25em;line-height:1.5;margin-bottom:.5em;margin-top:.5em}.buddypress .bp-changelog-section .title,.buddypress .bp-features-section .feature-title{font-size:1.25em;line-height:1.25;margin-top:.6em;text-align:right}.buddypress .bp-features-section .bp-feature,.buddypress .bp-features-section .bp-feature-imaged{clear:both;float:right;margin-bottom:1em;margin-top:1em;margin-left:0;padding-left:1em;width:100%}.buddypress .bp-features-section .bp-feature-imaged p{font-size:1em}.buddypress .bp-features-section .bp-feature span{margin-top:.33em}.buddypress .bp-feature.opposite .feature-title,.buddypress .bp-feature.opposite p{float:none}.buddypress .bp-changelog-section{clear:both;margin-bottom:2em;margin-top:2em}.buddypress .bp-changelog{margin-bottom:0}.buddypress .bp-changelog-section .changelog-title{margin-bottom:.5em}.buddypress .bp-changelog .title{font-size:1em}.buddypress .bp-changelog p{margin-bottom:1em}.buddypress .bp-changelog-section .three-col .col,.buddypress .bp-changelog-section .two-col>div{margin-top:0;padding-bottom:.5em;width:100%}.buddypress .bp-three-column .bp-column{width:100%}}@media screen and (max-width:360px){.buddypress .bp-headline{text-align:center}.buddypress .bp-headline span.dashicons{clear:none;font-size:80px;float:none;height:80px;line-height:80px;margin:0 auto;width:80px}.buddypress .bp-features-section .headline-title,.buddypress .bp-headline-feature .headline-title{font-size:1.5em;line-height:1.5;text-align:right}.buddypress .bp-headline-feature .headline-title{margin:1em 0 0}.buddypress .bp-headline-feature p{margin:1.15em 0 .6em auto;text-align:right;width:auto}.buddypress .bp-features-section .bp-feature{text-align:center}.buddypress .bp-features-section span.dashicons{float:none}.buddypress .bp-features-section .feature-title,.buddypress .bp-features-section p{margin-right:0;text-align:right}}#adminmenu #toplevel_page_bp-activity .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_user .wp-menu-image:before{content:"\f452"}#adminmenu #toplevel_page_bp-groups .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_user .wp-menu-image:before{content:"\f456"}#adminmenu #toplevel_page_bp-notifications .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_user .wp-menu-image:before{content:"\f439"}#adminmenu #toplevel_page_bp-messages .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_user .wp-menu-image:before{content:"\f457"}#adminmenu #toplevel_page_bp-friends .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before{content:"\f454"}#adminmenu #toplevel_page_bp-settings .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_user .wp-menu-image:before{content:"\f108"}#adminmenu li.toplevel_page_bp-components .wp-menu-image,#adminmenu li.toplevel_page_bp-general-settings .wp-menu-image{content:"\f448"}.settings_page_bp-components td.plugin-title span{float:right;width:18px;height:18px;margin-left:5px}.settings_page_bp-components td.plugin-title span:before{font-family:dashicons;font-size:18px}.settings_page_bp-components tr.activity td.plugin-title span:before{content:"\f452"}.settings_page_bp-components tr.notifications td.plugin-title span:before{content:"\f339"}.settings_page_bp-components tr.xprofile td.plugin-title span:before{content:"\f336"}.settings_page_bp-components tr.settings td.plugin-title span:before{content:"\f108"}.settings_page_bp-components tr.groups td.plugin-title span:before{content:"\f456"}.settings_page_bp-components tr.messages td.plugin-title span:before{content:"\f457"}.settings_page_bp-components tr.blogs td.plugin-title span:before{content:"\f120"}.settings_page_bp-components tr.friends td.plugin-title span:before{content:"\f454"}.settings_page_bp-components tr.core td.plugin-title span:before{content:"\f448"}.settings_page_bp-components tr.members td.plugin-title span:before{content:"\f307"}#bp-admin-component-form .wp-list-table.plugins .plugin-title{width:25%}@media screen and (max-width:782px){.settings_page_bp-components td.plugin-title span{margin-top:5px}#bp-admin-component-form .wp-list-table.plugins .plugin-title{display:block;width:auto}#bp-admin-component-form .subsubsub{margin-bottom:0;padding-bottom:35px}}#adminmenu .toplevel_page_network-tools div.wp-menu-image:before{content:""}body.site-users-php th#role,body.users-php th#role,body.users_page_bp-signups th#count_sent{width:10%}body.site-users-php th#email,body.site-users-php th#name,body.users-php th#email,body.users-php th#name,body.users-php th#registered,body.users_page_bp-signups th#date_sent,body.users_page_bp-signups th#email,body.users_page_bp-signups th#name,body.users_page_bp-signups th#registered{width:15%}body.users-php th#blogs,body.users_page_bp-signups th#blogs{width:20%}body.users_page_bp-signups td.count_sent,body.users_page_bp-signups th.column-count_sent{text-align:center}.bp-signups-list table{margin:1em 0}.bp-signups-list .column-fields{font-weight:700}.bp-new-notice-panel{background:#fff;border:1px solid #e5e5e5;box-shadow:0 1px 1px rgba(0,0,0,.04);font-size:13px;line-height:2.1;margin:1.5em 0 3em;overflow:auto;padding:10px 25px 25px;position:relative}.bp-new-notice-panel label{clear:both;float:right;margin-left:3%;width:20%}.bp-new-notice-panel input,.bp-new-notice-panel textarea{clear:none;margin-bottom:1em;width:75%}.bp-new-notice-panel input[type=text]:after,.bp-new-notice-panel textarea:after{clear:both;content:" ";display:table}.bp-new-notice-panel .button-primary{margin-right:23%;width:auto}.bp-notice-about{font-size:1em;margin-bottom:1em}.bp-new-notice{margin-bottom:1em;margin-top:0}.bp-notices-list{margin-bottom:0}@media screen and (max-width:782px){.bp-new-notice-panel{margin-bottom:1.5em}.bp-new-notice-panel input,.bp-new-notice-panel textarea{margin-right:0;width:100%}.bp-new-notice-panel .button-primary{margin-right:0;width:auto}.bp-new-notice-panel .button{max-width:45%;word-wrap:break-word}.bp-notice-about{margin-top:0;margin-bottom:1em}.bp-new-notice{margin-bottom:.5em}}body.post-type-bp-email #excerpt{height:auto}body.post-type-bp-email th#situation{width:20%}body.post-type-bp-email td.column-situation ul{margin:0}body.post-type-bp-email .categorydiv label{display:block;float:right;padding-right:25px;text-indent:-25px}.tools_page_bp-tools .wrap{max-width:950px}.tools_page_bp-tools p{line-height:2}.tools_page_bp-tools fieldset{margin:2em 0 0}.tools_page_bp-tools legend{color:#23282d;font-size:1.3em;font-weight:600;margin:1em 0}.tools_page_bp-tools label{clear:right;display:block;line-height:1.5;margin:0 0 1em;vertical-align:middle}@media screen and (max-width:782px){.tools_page_bp-tools p{line-height:1.5}.tools_page_bp-tools label{margin-bottom:1em;padding-left:25px;text-indent:-33px}.tools_page_bp-tools .checkbox{padding:0 30px 0 0}}#buddypress-update.not-shiny .update-message{border-right:0;padding-right:36px}#buddypress-update.not-shiny .update-message:before{content:"\f534"}
bp-core/admin/css/common.css CHANGED
@@ -12,15 +12,18 @@ TABLE OF CONTENTS:
12
  1.1 Version Badge
13
  1.2 About Panel
14
  1.2.1 Headline Feature
15
- 1.2.2 Columns
16
- 1.2.3 Features Section
17
- 1.2.4 Changelog Section
18
  2.0 Dashicons
19
  2.1 Top level menus
20
  2.2 Settings - Components
21
  2.3 Tools
22
- 3.0 User's Lists
 
 
23
  4.0 Emails - Edit page
 
 
24
  ------------------------------------------------------------------------------*/
25
 
26
  /*------------------------------------------------------------------------------
@@ -33,7 +36,7 @@ TABLE OF CONTENTS:
33
  .bp-badge {
34
  color: #d84800;
35
  display: inline-block;
36
- font: normal 150px/1 'dashicons' !important;
37
  }
38
 
39
  .bp-badge:before {
@@ -46,7 +49,15 @@ TABLE OF CONTENTS:
46
  right: 0;
47
  }
48
 
 
 
 
 
 
 
 
49
  @media only screen and (max-width: 500px) {
 
50
  .about-wrap .bp-badge {
51
  position: relative;
52
  margin: 10px auto;
@@ -62,139 +73,370 @@ TABLE OF CONTENTS:
62
  /*
63
  * 1.2.1 Headline Feature
64
  */
65
- .index_page_bp-about .about-wrap .headline-feature,
66
- .dashboard_page_bp-about .about-wrap .headline-feature {
67
  margin-bottom: 2em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  text-align: center;
 
69
  }
70
 
71
- .index_page_bp-about .about-wrap .headline-feature h3,
72
- .index_page_bp-about .headline-feature .headline-title,
73
- .dashboard_page_bp-about .about-wrap .headline-feature h3,
74
- .dashboard_page_bp-about .headline-feature .headline-title {
75
  font-size: 2.2em;
76
- font-weight: normal;
77
- line-height: 1.3;
78
- margin: 1.25em 0 0.6em;
79
  text-align: center;
80
  }
81
 
82
- .index_page_bp-about .about-wrap .headline-feature p,
83
- .dashboard_page_bp-about .about-wrap .headline-feature p {
84
  font-size: 1.15em;
85
- margin: 1.15em auto 0.6em;
86
- }
87
-
88
- .index_page_bp-about .about-wrap .headline-feature .introduction,
89
- .dashboard_page_bp-about .about-wrap .headline-feature .introduction {
90
- font-weight: 600;
91
  }
92
 
93
  /*
94
- * 1.2.2 Columns
95
  */
96
- .index_page_bp-about .about-wrap .two-col > div,
97
- .dashboard_page_bp-about .about-wrap .two-col > div {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  float: left;
 
99
  margin-right: 4.799999999%;
100
- position: relative;
101
  width: 47.6%;
102
  }
103
 
104
- .index_page_bp-about .about-wrap .two-col .last-feature,
105
- .dashboard_page_bp-about .about-wrap .two-col .last-feature {
106
  margin-right: 0;
107
  }
108
 
109
- /*
110
- * 1.2.3 Features Section
111
- */
112
- .index_page_bp-about .bp-features-section,
113
- .dashboard_page_bp-about .bp-features-section {
114
- margin-bottom: 2em;
115
  }
116
 
117
- .index_page_bp-about .about-wrap .feature-section,
118
- .dashboard_page_bp-about .about-wrap .feature-section {
119
  clear: both;
120
- margin-top: 2em;
121
- overflow: hidden;
122
- padding-bottom: 0;
123
  }
124
 
125
- .index_page_bp-about .about-wrap .changelog .feature-section,
126
- .dashboard_page_bp-about .about-wrap .changelog .feature-section {
 
 
127
  margin-top: 0;
128
  }
129
 
130
- .index_page_bp-about .about-wrap .feature-section h3,
131
- .dashboard_page_bp-about .about-wrap .feature-section h3 {
132
- font-size: 1.25em;
133
- line-height: 1.5em;
134
- margin: 0 0 0.6em;
135
  }
136
 
137
- .index_page_bp-about .about-wrap .changelog h4,
138
- .dashboard_page_bp-about .about-wrap .changelog h4 {
139
- color: #23282d;
 
 
140
  font-size: 1em;
141
- margin: 1.4em 0 0.6em;
 
 
 
 
 
 
 
 
142
  }
143
 
144
  /*
145
- * 1.2.4 Changelog Section
146
  */
147
- .index_page_bp-about .about-wrap .changelog,
148
- .dashboard_page_bp-about .about-wrap .changelog {
149
- border-top: 1px solid #eee;
150
  margin-bottom: 3em;
 
 
151
  }
152
 
153
- .index_page_bp-about .about-wrap .changelog .changelog-title,
154
- .dashboard_page_bp-about .about-wrap .changelog .changelog-title {
 
 
 
 
 
 
155
  font-size: 1.25em;
156
- line-height: 1.5em;
157
- margin: 1.25em 0 .6em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  text-align: center;
159
  }
160
 
 
 
 
 
 
161
  @media screen and ( max-width: 782px ) {
162
- .index_page_bp-about .about-wrap .headline-feature,
163
- .dashboard_page_bp-about .about-wrap .headline-feature {
164
- max-width: 100%;
165
- }
166
- .index_page_bp-about .about-wrap .headline-feature h3,
167
- .dahsboard_page_bp-about .about-wrap .headline-feature h3,
168
- .index_page_bp-about .about-wrap .headline-feature .headline-title,
169
- .dashboard_page_bp-about .about-wrap .headline-feature .headline-title {
170
- font-size: 2em;
171
- }
172
- .index_page_bp-about .bp-features-section,
173
- .dashboard_page_bp-about .bp-features-section {
 
 
 
 
 
 
 
 
174
  margin-bottom: 0;
 
 
175
  }
176
- .index_page_bp-about .about-wrap .feature-section,
177
- .dashboard_page_bp-about .about-wrap .feature-section {
178
- margin-top: 0;
 
 
 
 
179
  }
180
- .index_page_bp-about .about-wrap .two-col > div,
181
- .dashboard_page_bp-about .about-wrap .two-col > div {
182
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
183
- margin-top: 1.25em;
184
- padding-bottom: 1em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  width: 100%;
186
  }
187
- .index_page_bp-about .changelog .two-col > div,
188
- .dashboard_page_bp-about .changelog .two-col > div {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  margin-top: 0;
190
- padding-bottom: 0;
 
191
  }
192
- .index_page_bp-about .about-wrap .changelog .changelog-title,
193
- .dashboard_page_bp-about .about-wrap .changelog .changelog-title {
194
- text-align: left;
195
  }
196
  }
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  /*------------------------------------------------------------------------------
200
  * 2.0 Dashicons
@@ -229,7 +471,7 @@ TABLE OF CONTENTS:
229
 
230
  #adminmenu #toplevel_page_bp-friends .wp-menu-image:before,
231
  #adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before,
232
- #adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before{
233
  content: "\f454";
234
  }
235
 
@@ -255,7 +497,7 @@ TABLE OF CONTENTS:
255
  }
256
 
257
  .settings_page_bp-components td.plugin-title span:before {
258
- font-family: 'dashicons';
259
  font-size: 18px;
260
  }
261
 
@@ -283,10 +525,6 @@ TABLE OF CONTENTS:
283
  content: "\f457";
284
  }
285
 
286
- .settings_page_bp-components tr.forums td.plugin-title span:before {
287
- content: "\f452";
288
- }
289
-
290
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
291
  content: "\f120";
292
  }
@@ -308,13 +546,16 @@ TABLE OF CONTENTS:
308
  }
309
 
310
  @media screen and ( max-width: 782px ) {
 
311
  .settings_page_bp-components td.plugin-title span {
312
  margin-top: 5px;
313
  }
 
314
  #bp-admin-component-form .wp-list-table.plugins .plugin-title {
315
  display: block;
316
  width: auto;
317
  }
 
318
  #bp-admin-component-form .subsubsub {
319
  margin-bottom: 0;
320
  padding-bottom: 35px;
@@ -330,8 +571,12 @@ TABLE OF CONTENTS:
330
 
331
 
332
  /*------------------------------------------------------------------------------
333
- * 3.0 User's Lists
334
  *----------------------------------------------------------------------------*/
 
 
 
 
335
  body.site-users-php th#role,
336
  body.users-php th#role,
337
  body.users_page_bp-signups th#count_sent {
@@ -360,6 +605,100 @@ body.users_page_bp-signups td.count_sent {
360
  text-align: center;
361
  }
362
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
 
364
  /*------------------------------------------------------------------------------
365
  * 4.0 Emails - Edit Page
@@ -382,3 +721,63 @@ body.post-type-bp-email .categorydiv label {
382
  padding-left: 25px;
383
  text-indent: -25px;
384
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  1.1 Version Badge
13
  1.2 About Panel
14
  1.2.1 Headline Feature
15
+ 1.2.2 Features Section
16
+ 1.2.3 Changelog Section
 
17
  2.0 Dashicons
18
  2.1 Top level menus
19
  2.2 Settings - Components
20
  2.3 Tools
21
+ 3.0 Users
22
+ 3.1 Users List
23
+ 3.2 Site Notices
24
  4.0 Emails - Edit page
25
+ 5.0 Tools - BuddyPress
26
+ 6.0 Plugins page
27
  ------------------------------------------------------------------------------*/
28
 
29
  /*------------------------------------------------------------------------------
36
  .bp-badge {
37
  color: #d84800;
38
  display: inline-block;
39
+ font: 400 150px/1 dashicons !important;
40
  }
41
 
42
  .bp-badge:before {
49
  right: 0;
50
  }
51
 
52
+ .index_page_bp-credits code,
53
+ .index_page_bp-about code {
54
+ background-color: #e0e0e0;
55
+ color: #636363;
56
+ font-size: 1em;
57
+ }
58
+
59
  @media only screen and (max-width: 500px) {
60
+
61
  .about-wrap .bp-badge {
62
  position: relative;
63
  margin: 10px auto;
73
  /*
74
  * 1.2.1 Headline Feature
75
  */
76
+ .buddypress .bp-headline-feature {
 
77
  margin-bottom: 2em;
78
+ margin-top: 3em;
79
+ padding: 2em 3em;
80
+ }
81
+
82
+ .buddypress .bp-headline {
83
+ margin: 0 auto;
84
+ width: 45em;
85
+ }
86
+
87
+ .buddypress .bp-headline span.dashicons {
88
+ background-color: #f1f1f1;
89
+ color: #d84800;
90
+ clear: left;
91
+ font-size: 100px;
92
+ float: left;
93
+ height: 100px;
94
+ line-height: 100px;
95
+ margin: 0 15px 15px 0;
96
  text-align: center;
97
+ width: 100px;
98
  }
99
 
100
+ .buddypress .bp-headline-feature .headline-title {
 
 
 
101
  font-size: 2.2em;
102
+ font-weight: 300;
103
+ line-height: 2;
104
+ margin: 0 0 1em;
105
  text-align: center;
106
  }
107
 
108
+ .buddypress .bp-headline-feature p {
 
109
  font-size: 1.15em;
110
+ margin: 1.15em auto 0.6em 0;
 
 
 
 
 
111
  }
112
 
113
  /*
114
+ * 1.2.2 Features Section
115
  */
116
+ .buddypress .bp-features-section {
117
+ border-bottom: 1px solid #ccc;
118
+ clear: both;
119
+ margin-bottom: 3em;
120
+ margin-top: 2em;
121
+ overflow: hidden;
122
+ padding-bottom: 2em;
123
+ }
124
+
125
+ .buddypress .bp-features-section p {
126
+ font-size: 14px;
127
+ line-height: 1.5;
128
+ }
129
+
130
+ .buddypress .bp-features-section img {
131
+ margin-bottom: 20px;
132
+ }
133
+
134
+ .buddypress .bp-features-section span.dashicons {
135
+ background-color: #fff;
136
+ border-radius: 50%;
137
+ clear: left;
138
+ color: #d84800;
139
+ font-size: 50px;
140
+ float: left;
141
+ height: 80px;
142
+ line-height: 80px;
143
+ margin: 0 15px 15px 0;
144
+ text-align: center;
145
+ width: 80px;
146
+ }
147
+
148
+ .buddypress .bp-features-section .headline-title {
149
+ font-size: 2em;
150
+ font-weight: 300;
151
+ line-height: 1.5;
152
+ margin: 1em auto 2em;
153
+ text-align: center;
154
+ }
155
+
156
+ .buddypress .bp-features-section .bp-feature-with-images {
157
+ border-bottom: 1px solid #ccc;
158
+ margin-bottom: 5em;
159
+ padding-bottom: 2em;
160
+ }
161
+
162
+ .buddypress .bp-features-section .bp-feature,
163
+ .buddypress .bp-features-section .bp-feature-imaged {
164
  float: left;
165
+ margin-bottom: 3em;
166
  margin-right: 4.799999999%;
 
167
  width: 47.6%;
168
  }
169
 
170
+ .buddypress .bp-features-section .bp-feature.opposite,
171
+ .buddypress .bp-features-section .bp-feature-imaged.anon {
172
  margin-right: 0;
173
  }
174
 
175
+ .buddypress .bp-features-section .bp-feature code {
176
+ font-size: 0.95em;
177
+ line-height: 1.5;
 
 
 
178
  }
179
 
180
+ .buddypress .bp-feature:after {
 
181
  clear: both;
182
+ content: "";
183
+ margin-bottom: 2em;
 
184
  }
185
 
186
+ .buddypress .bp-feature-imaged .feature-title {
187
+ color: #23282d;
188
+ font-size: 1.25em;
189
+ margin-bottom: 0.6em;
190
  margin-top: 0;
191
  }
192
 
193
+ .buddypress .bp-feature-imaged p {
194
+ clear: left;
195
+ font-size: 1.1em;
 
 
196
  }
197
 
198
+ .buddypress .bp-feature-imaged img {
199
+ clear: left;
200
+ }
201
+
202
+ .buddypress .bp-feature .feature-title {
203
  font-size: 1em;
204
+ line-height: 1.5;
205
+ margin-bottom: 0;
206
+ margin-left: 110px;
207
+ margin-top: 0;
208
+ text-align: left;
209
+ }
210
+
211
+ .buddypress .bp-feature p {
212
+ margin-left: 110px;
213
  }
214
 
215
  /*
216
+ * 1.2.3 Changelog Section
217
  */
218
+ .buddypress .bp-changelog-section {
219
+ clear: both;
 
220
  margin-bottom: 3em;
221
+ margin-top: 4em;
222
+ padding-bottom: 0;
223
  }
224
 
225
+ .buddypress .bp-changelog-section:after {
226
+ clear: both;
227
+ content: "";
228
+ display: table;
229
+ }
230
+
231
+ .buddypress .bp-changelog-section .changelog-title {
232
+ color: #23282d;
233
  font-size: 1.25em;
234
+ line-height: 1.5;
235
+ margin: 0 auto 1.5em;
236
+ }
237
+
238
+ .buddypress .bp-two-column div {
239
+ float: left;
240
+ margin-right: 4.799999999%;
241
+ position: relative;
242
+ width: 47.6%;
243
+ }
244
+
245
+ .buddypress .bp-three-column .bp-column {
246
+ float: left;
247
+ margin-right: 5%;
248
+ position: relative;
249
+ width: 29.95%;
250
+ }
251
+
252
+ .buddypress .bp-two-column .bp-column:nth-of-type(2n),
253
+ .buddypress .bp-three-column .bp-column:nth-of-type(3n) {
254
+ margin-right: 0;
255
+ }
256
+
257
+ .buddypress .bp-changelog {
258
+ margin-bottom: 3em;
259
+ }
260
+
261
+ .buddypress .bp-changelog:after {
262
+ clear: both;
263
+ content: "";
264
+ display: table;
265
+ }
266
+
267
+ .buddypress .bp-changelog .title {
268
+ font-size: 14px;
269
+ margin-bottom: 0.75em;
270
+ margin-top: 0;
271
+ }
272
+
273
+ .buddypress .bp-changelog p {
274
+ margin-bottom: 0;
275
+ }
276
+
277
+ .bp-changelog-url {
278
  text-align: center;
279
  }
280
 
281
+ .bp-assets {
282
+ clear: both;
283
+ margin-bottom: 3em;
284
+ }
285
+
286
  @media screen and ( max-width: 782px ) {
287
+
288
+ .bp-headline-feature,
289
+ .bp-features-section,
290
+ .bp-changelog-section,
291
+ .bp-assets {
292
+ margin-left: 20px;
293
+ margin-right: 20px;
294
+ }
295
+
296
+ .buddypress .bp-headline-feature {
297
+ padding: 0;
298
+ }
299
+
300
+ .buddypress .bp-headline {
301
+ margin: 0;
302
+ width: 97%;
303
+ }
304
+
305
+ .buddypress .bp-features-section {
306
+ clear: both;
307
  margin-bottom: 0;
308
+ margin-top: 2em;
309
+ padding-bottom: 2em;
310
  }
311
+
312
+ .buddypress .bp-features-section .bp-feature-with-images {
313
+ margin-bottom: 2em;
314
+ }
315
+
316
+ .buddypress .bp-features-section .headline-title {
317
+ margin-bottom: 1em;
318
  }
319
+
320
+ .buddypress .bp-changelog-section .changelog-title {
321
+ font-size: 1.25em;
322
+ line-height: 1.5;
323
+ margin-bottom: 0.5em;
324
+ margin-top: 0.5em;
325
+ }
326
+
327
+ .buddypress .bp-features-section .feature-title,
328
+ .buddypress .bp-changelog-section .title {
329
+ font-size: 1.25em;
330
+ line-height: 1.25;
331
+ margin-top: 0.6em;
332
+ text-align: left;
333
+ }
334
+
335
+ .buddypress .bp-features-section .bp-feature,
336
+ .buddypress .bp-features-section .bp-feature-imaged {
337
+ clear: both;
338
+ float: left;
339
+ margin-bottom: 1em;
340
+ margin-top: 1em;
341
+ margin-right: 0;
342
+ padding-right: 1em;
343
  width: 100%;
344
  }
345
+
346
+ .buddypress .bp-features-section .bp-feature-imaged p {
347
+ font-size: 1em;
348
+ }
349
+
350
+ .buddypress .bp-features-section .bp-feature span {
351
+ margin-top: 0.33em;
352
+ }
353
+
354
+ .buddypress .bp-feature.opposite .feature-title,
355
+ .buddypress .bp-feature.opposite p {
356
+ float: none;
357
+ }
358
+
359
+ .buddypress .bp-changelog-section {
360
+ clear: both;
361
+ margin-bottom: 2em;
362
+ margin-top: 2em;
363
+ }
364
+
365
+ .buddypress .bp-changelog {
366
+ margin-bottom: 0;
367
+ }
368
+
369
+ .buddypress .bp-changelog-section .changelog-title {
370
+ margin-bottom: 0.5em;
371
+ }
372
+
373
+ .buddypress .bp-changelog .title {
374
+ font-size: 1em;
375
+ }
376
+
377
+ .buddypress .bp-changelog p {
378
+ margin-bottom: 1em;
379
+ }
380
+
381
+ .buddypress .bp-changelog-section .two-col > div,
382
+ .buddypress .bp-changelog-section .three-col .col {
383
  margin-top: 0;
384
+ padding-bottom: 0.5em;
385
+ width: 100%;
386
  }
387
+
388
+ .buddypress .bp-three-column .bp-column {
389
+ width: 100%;
390
  }
391
  }
392
 
393
+ @media screen and ( max-width: 360px ) {
394
+
395
+ .buddypress .bp-headline {
396
+ text-align: center;
397
+ }
398
+
399
+ .buddypress .bp-headline span.dashicons {
400
+ clear: none;
401
+ font-size: 80px;
402
+ float: none;
403
+ height: 80px;
404
+ line-height: 80px;
405
+ margin: 0 auto;
406
+ width: 80px;
407
+ }
408
+
409
+ .buddypress .bp-headline-feature .headline-title,
410
+ .buddypress .bp-features-section .headline-title {
411
+ font-size: 1.5em;
412
+ line-height: 1.5;
413
+ text-align: left;
414
+ }
415
+
416
+ .buddypress .bp-headline-feature .headline-title {
417
+ margin: 1em 0 0;
418
+ }
419
+
420
+ .buddypress .bp-headline-feature p {
421
+ margin: 1.15em auto 0.6em 0;
422
+ text-align: left;
423
+ width: auto;
424
+ }
425
+
426
+ .buddypress .bp-features-section .bp-feature {
427
+ text-align: center;
428
+ }
429
+
430
+ .buddypress .bp-features-section span.dashicons {
431
+ float: none;
432
+ }
433
+
434
+ .buddypress .bp-features-section .feature-title,
435
+ .buddypress .bp-features-section p {
436
+ margin-left: 0;
437
+ text-align: left;
438
+ }
439
+ }
440
 
441
  /*------------------------------------------------------------------------------
442
  * 2.0 Dashicons
471
 
472
  #adminmenu #toplevel_page_bp-friends .wp-menu-image:before,
473
  #adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before,
474
+ #adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before {
475
  content: "\f454";
476
  }
477
 
497
  }
498
 
499
  .settings_page_bp-components td.plugin-title span:before {
500
+ font-family: dashicons;
501
  font-size: 18px;
502
  }
503
 
525
  content: "\f457";
526
  }
527
 
 
 
 
 
528
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
529
  content: "\f120";
530
  }
546
  }
547
 
548
  @media screen and ( max-width: 782px ) {
549
+
550
  .settings_page_bp-components td.plugin-title span {
551
  margin-top: 5px;
552
  }
553
+
554
  #bp-admin-component-form .wp-list-table.plugins .plugin-title {
555
  display: block;
556
  width: auto;
557
  }
558
+
559
  #bp-admin-component-form .subsubsub {
560
  margin-bottom: 0;
561
  padding-bottom: 35px;
571
 
572
 
573
  /*------------------------------------------------------------------------------
574
+ * 3.0 Users
575
  *----------------------------------------------------------------------------*/
576
+
577
+ /*
578
+ * 3.1 Users List
579
+ */
580
  body.site-users-php th#role,
581
  body.users-php th#role,
582
  body.users_page_bp-signups th#count_sent {
605
  text-align: center;
606
  }
607
 
608
+ .bp-signups-list table {
609
+ margin: 1em 0;
610
+ }
611
+
612
+ .bp-signups-list .column-fields {
613
+ font-weight: 700;
614
+ }
615
+
616
+ /*
617
+ * 3.2 Site Notices
618
+ */
619
+ .bp-new-notice-panel {
620
+ background: #fff;
621
+ border: 1px solid #e5e5e5;
622
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
623
+ font-size: 13px;
624
+ line-height: 2.1;
625
+ margin: 1.5em 0 3em;
626
+ overflow: auto;
627
+ padding: 10px 25px 25px;
628
+ position: relative;
629
+ }
630
+
631
+ .bp-new-notice-panel label {
632
+ clear: both;
633
+ float: left;
634
+ margin-right: 3%;
635
+ width: 20%;
636
+ }
637
+
638
+ .bp-new-notice-panel input,
639
+ .bp-new-notice-panel textarea {
640
+ clear: none;
641
+ margin-bottom: 1em;
642
+ width: 75%;
643
+ }
644
+
645
+ .bp-new-notice-panel input[type="text"]:after,
646
+ .bp-new-notice-panel textarea:after {
647
+ clear: both;
648
+ content: " ";
649
+ display: table;
650
+ }
651
+
652
+ .bp-new-notice-panel .button-primary {
653
+ margin-left: 23%;
654
+ width: auto;
655
+ }
656
+
657
+ .bp-notice-about {
658
+ font-size: 1em;
659
+ margin-bottom: 1em;
660
+ }
661
+
662
+ .bp-new-notice {
663
+ margin-bottom: 1em;
664
+ margin-top: 0;
665
+ }
666
+
667
+ .bp-notices-list {
668
+ margin-bottom: 0;
669
+ }
670
+
671
+ @media screen and (max-width: 782px) {
672
+
673
+ .bp-new-notice-panel {
674
+ margin-bottom: 1.5em;
675
+ }
676
+
677
+ .bp-new-notice-panel input,
678
+ .bp-new-notice-panel textarea {
679
+ margin-left: 0;
680
+ width: 100%;
681
+ }
682
+
683
+ .bp-new-notice-panel .button-primary {
684
+ margin-left: 0;
685
+ width: auto;
686
+ }
687
+
688
+ .bp-new-notice-panel .button {
689
+ max-width: 45%;
690
+ word-wrap: break-word;
691
+ }
692
+
693
+ .bp-notice-about {
694
+ margin-top: 0;
695
+ margin-bottom: 1em;
696
+ }
697
+
698
+ .bp-new-notice {
699
+ margin-bottom: 0.5em;
700
+ }
701
+ }
702
 
703
  /*------------------------------------------------------------------------------
704
  * 4.0 Emails - Edit Page
721
  padding-left: 25px;
722
  text-indent: -25px;
723
  }
724
+
725
+ /*------------------------------------------------------------------------------
726
+ * 5.0 Tools - BuddyPress
727
+ *----------------------------------------------------------------------------*/
728
+ .tools_page_bp-tools .wrap {
729
+ max-width: 950px;
730
+ }
731
+
732
+ .tools_page_bp-tools p {
733
+ line-height: 2;
734
+ }
735
+
736
+ .tools_page_bp-tools fieldset {
737
+ margin: 2em 0 0;
738
+ }
739
+
740
+ .tools_page_bp-tools legend {
741
+ color: #23282d;
742
+ font-size: 1.3em;
743
+ font-weight: 600;
744
+ margin: 1em 0;
745
+ }
746
+
747
+ .tools_page_bp-tools label {
748
+ clear: left;
749
+ display: block;
750
+ line-height: 1.5;
751
+ margin: 0 0 1em;
752
+ vertical-align: middle;
753
+ }
754
+
755
+ @media screen and (max-width: 782px) {
756
+
757
+ .tools_page_bp-tools p {
758
+ line-height: 1.5;
759
+ }
760
+
761
+ .tools_page_bp-tools label {
762
+ margin-bottom: 1em;
763
+ padding-right: 25px;
764
+ text-indent: -33px;
765
+ }
766
+
767
+ .tools_page_bp-tools .checkbox {
768
+ padding: 0 0 0 30px;
769
+ }
770
+ }
771
+
772
+
773
+ /*------------------------------------------------------------------------------
774
+ * 6.0 Plugins page
775
+ *----------------------------------------------------------------------------*/
776
+ #buddypress-update.not-shiny .update-message {
777
+ border-left: 0;
778
+ padding-left: 36px;
779
+ }
780
+
781
+ #buddypress-update.not-shiny .update-message:before {
782
+ content: "\f534";
783
+ }
bp-core/admin/css/common.min.css CHANGED
@@ -1 +1 @@
1
- .bp-badge{color:#d84800;display:inline-block;font:400 150px/1 dashicons!important}.bp-badge:before{content:"\f448"}.about-wrap .bp-badge{position:absolute;top:0;right:0}@media only screen and (max-width:500px){.about-wrap .bp-badge{position:relative;margin:10px auto;top:auto;right:auto}}.dashboard_page_bp-about .about-wrap .headline-feature,.index_page_bp-about .about-wrap .headline-feature{margin-bottom:2em;text-align:center}.dashboard_page_bp-about .about-wrap .headline-feature h3,.dashboard_page_bp-about .headline-feature .headline-title,.index_page_bp-about .about-wrap .headline-feature h3,.index_page_bp-about .headline-feature .headline-title{font-size:2.2em;font-weight:400;line-height:1.3;margin:1.25em 0 .6em;text-align:center}.dashboard_page_bp-about .about-wrap .headline-feature p,.index_page_bp-about .about-wrap .headline-feature p{font-size:1.15em;margin:1.15em auto .6em}.dashboard_page_bp-about .about-wrap .headline-feature .introduction,.index_page_bp-about .about-wrap .headline-feature .introduction{font-weight:600}.dashboard_page_bp-about .about-wrap .two-col>div,.index_page_bp-about .about-wrap .two-col>div{float:left;margin-right:4.799999999%;position:relative;width:47.6%}.dashboard_page_bp-about .about-wrap .two-col .last-feature,.index_page_bp-about .about-wrap .two-col .last-feature{margin-right:0}.dashboard_page_bp-about .bp-features-section,.index_page_bp-about .bp-features-section{margin-bottom:2em}.dashboard_page_bp-about .about-wrap .feature-section,.index_page_bp-about .about-wrap .feature-section{clear:both;margin-top:2em;overflow:hidden;padding-bottom:0}.dashboard_page_bp-about .about-wrap .changelog .feature-section,.index_page_bp-about .about-wrap .changelog .feature-section{margin-top:0}.dashboard_page_bp-about .about-wrap .feature-section h3,.index_page_bp-about .about-wrap .feature-section h3{font-size:1.25em;line-height:1.5em;margin:0 0 .6em}.dashboard_page_bp-about .about-wrap .changelog h4,.index_page_bp-about .about-wrap .changelog h4{color:#23282d;font-size:1em;margin:1.4em 0 .6em}.dashboard_page_bp-about .about-wrap .changelog,.index_page_bp-about .about-wrap .changelog{border-top:1px solid #eee;margin-bottom:3em}.dashboard_page_bp-about .about-wrap .changelog .changelog-title,.index_page_bp-about .about-wrap .changelog .changelog-title{font-size:1.25em;line-height:1.5em;margin:1.25em 0 .6em;text-align:center}@media screen and (max-width:782px){.dashboard_page_bp-about .about-wrap .headline-feature,.index_page_bp-about .about-wrap .headline-feature{max-width:100%}.dahsboard_page_bp-about .about-wrap .headline-feature h3,.dashboard_page_bp-about .about-wrap .headline-feature .headline-title,.index_page_bp-about .about-wrap .headline-feature .headline-title,.index_page_bp-about .about-wrap .headline-feature h3{font-size:2em}.dashboard_page_bp-about .bp-features-section,.index_page_bp-about .bp-features-section{margin-bottom:0}.dashboard_page_bp-about .about-wrap .feature-section,.index_page_bp-about .about-wrap .feature-section{margin-top:0}.dashboard_page_bp-about .about-wrap .two-col>div,.index_page_bp-about .about-wrap .two-col>div{border-bottom:1px solid rgba(0,0,0,.1);margin-top:1.25em;padding-bottom:1em;width:100%}.dashboard_page_bp-about .changelog .two-col>div,.index_page_bp-about .changelog .two-col>div{margin-top:0;padding-bottom:0}.dashboard_page_bp-about .about-wrap .changelog .changelog-title,.index_page_bp-about .about-wrap .changelog .changelog-title{text-align:left}}#adminmenu #toplevel_page_bp-activity .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_user .wp-menu-image:before{content:"\f452"}#adminmenu #toplevel_page_bp-groups .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_user .wp-menu-image:before{content:"\f456"}#adminmenu #toplevel_page_bp-notifications .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_user .wp-menu-image:before{content:"\f439"}#adminmenu #toplevel_page_bp-messages .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_user .wp-menu-image:before{content:"\f457"}#adminmenu #toplevel_page_bp-friends .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before{content:"\f454"}#adminmenu #toplevel_page_bp-settings .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_user .wp-menu-image:before{content:"\f108"}#adminmenu li.toplevel_page_bp-components .wp-menu-image,#adminmenu li.toplevel_page_bp-general-settings .wp-menu-image{content:"\f448"}.settings_page_bp-components td.plugin-title span{float:left;width:18px;height:18px;margin-right:5px}.settings_page_bp-components td.plugin-title span:before{font-family:dashicons;font-size:18px}.settings_page_bp-components tr.activity td.plugin-title span:before{content:"\f452"}.settings_page_bp-components tr.notifications td.plugin-title span:before{content:"\f339"}.settings_page_bp-components tr.xprofile td.plugin-title span:before{content:"\f336"}.settings_page_bp-components tr.settings td.plugin-title span:before{content:"\f108"}.settings_page_bp-components tr.groups td.plugin-title span:before{content:"\f456"}.settings_page_bp-components tr.messages td.plugin-title span:before{content:"\f457"}.settings_page_bp-components tr.forums td.plugin-title span:before{content:"\f452"}.settings_page_bp-components tr.blogs td.plugin-title span:before{content:"\f120"}.settings_page_bp-components tr.friends td.plugin-title span:before{content:"\f454"}.settings_page_bp-components tr.core td.plugin-title span:before{content:"\f448"}.settings_page_bp-components tr.members td.plugin-title span:before{content:"\f307"}#bp-admin-component-form .wp-list-table.plugins .plugin-title{width:25%}@media screen and (max-width:782px){.settings_page_bp-components td.plugin-title span{margin-top:5px}#bp-admin-component-form .wp-list-table.plugins .plugin-title{display:block;width:auto}#bp-admin-component-form .subsubsub{margin-bottom:0;padding-bottom:35px}}#adminmenu .toplevel_page_network-tools div.wp-menu-image:before{content:""}body.site-users-php th#role,body.users-php th#role,body.users_page_bp-signups th#count_sent{width:10%}body.site-users-php th#email,body.site-users-php th#name,body.users-php th#email,body.users-php th#name,body.users-php th#registered,body.users_page_bp-signups th#date_sent,body.users_page_bp-signups th#email,body.users_page_bp-signups th#name,body.users_page_bp-signups th#registered{width:15%}body.post-type-bp-email th#situation,body.users-php th#blogs,body.users_page_bp-signups th#blogs{width:20%}body.users_page_bp-signups td.count_sent,body.users_page_bp-signups th.column-count_sent{text-align:center}body.post-type-bp-email #excerpt{height:auto}body.post-type-bp-email td.column-situation ul{margin:0}body.post-type-bp-email .categorydiv label{display:block;float:left;padding-left:25px;text-indent:-25px}
1
+ .bp-badge{color:#d84800;display:inline-block;font:400 150px/1 dashicons!important}.bp-badge:before{content:"\f448"}.about-wrap .bp-badge{position:absolute;top:0;right:0}.index_page_bp-about code,.index_page_bp-credits code{background-color:#e0e0e0;color:#636363;font-size:1em}@media only screen and (max-width:500px){.about-wrap .bp-badge{position:relative;margin:10px auto;top:auto;right:auto}}.buddypress .bp-headline-feature{margin-bottom:2em;margin-top:3em;padding:2em 3em}.buddypress .bp-headline{margin:0 auto;width:45em}.buddypress .bp-headline span.dashicons{background-color:#f1f1f1;color:#d84800;clear:left;font-size:100px;float:left;height:100px;line-height:100px;margin:0 15px 15px 0;text-align:center;width:100px}.buddypress .bp-headline-feature .headline-title{font-size:2.2em;font-weight:300;line-height:2;margin:0 0 1em;text-align:center}.buddypress .bp-headline-feature p{font-size:1.15em;margin:1.15em auto .6em 0}.buddypress .bp-features-section{border-bottom:1px solid #ccc;clear:both;margin-bottom:3em;margin-top:2em;overflow:hidden;padding-bottom:2em}.buddypress .bp-features-section p{font-size:14px;line-height:1.5}.buddypress .bp-features-section img{margin-bottom:20px}.buddypress .bp-features-section span.dashicons{background-color:#fff;border-radius:50%;clear:left;color:#d84800;font-size:50px;float:left;height:80px;line-height:80px;margin:0 15px 15px 0;text-align:center;width:80px}.buddypress .bp-features-section .headline-title{font-size:2em;font-weight:300;line-height:1.5;margin:1em auto 2em;text-align:center}.buddypress .bp-features-section .bp-feature-with-images{border-bottom:1px solid #ccc;margin-bottom:5em;padding-bottom:2em}.buddypress .bp-features-section .bp-feature,.buddypress .bp-features-section .bp-feature-imaged{float:left;margin-bottom:3em;margin-right:4.799999999%;width:47.6%}.buddypress .bp-features-section .bp-feature-imaged.anon,.buddypress .bp-features-section .bp-feature.opposite{margin-right:0}.buddypress .bp-features-section .bp-feature code{font-size:.95em;line-height:1.5}.buddypress .bp-feature:after{clear:both;content:"";margin-bottom:2em}.buddypress .bp-feature-imaged .feature-title{color:#23282d;font-size:1.25em;margin-bottom:.6em;margin-top:0}.buddypress .bp-feature-imaged p{clear:left;font-size:1.1em}.buddypress .bp-feature-imaged img{clear:left}.buddypress .bp-feature .feature-title{font-size:1em;line-height:1.5;margin-bottom:0;margin-left:110px;margin-top:0;text-align:left}.buddypress .bp-feature p{margin-left:110px}.buddypress .bp-changelog-section{clear:both;margin-bottom:3em;margin-top:4em;padding-bottom:0}.buddypress .bp-changelog-section:after{clear:both;content:"";display:table}.buddypress .bp-changelog-section .changelog-title{color:#23282d;font-size:1.25em;line-height:1.5;margin:0 auto 1.5em}.buddypress .bp-two-column div{float:left;margin-right:4.799999999%;position:relative;width:47.6%}.buddypress .bp-three-column .bp-column{float:left;margin-right:5%;position:relative;width:29.95%}.buddypress .bp-three-column .bp-column:nth-of-type(3n),.buddypress .bp-two-column .bp-column:nth-of-type(2n){margin-right:0}.buddypress .bp-changelog{margin-bottom:3em}.buddypress .bp-changelog:after{clear:both;content:"";display:table}.buddypress .bp-changelog .title{font-size:14px;margin-bottom:.75em;margin-top:0}.buddypress .bp-changelog p{margin-bottom:0}.bp-changelog-url{text-align:center}.bp-assets{clear:both;margin-bottom:3em}@media screen and (max-width:782px){.bp-assets,.bp-changelog-section,.bp-features-section,.bp-headline-feature{margin-left:20px;margin-right:20px}.buddypress .bp-headline-feature{padding:0}.buddypress .bp-headline{margin:0;width:97%}.buddypress .bp-features-section{clear:both;margin-bottom:0;margin-top:2em;padding-bottom:2em}.buddypress .bp-features-section .bp-feature-with-images{margin-bottom:2em}.buddypress .bp-features-section .headline-title{margin-bottom:1em}.buddypress .bp-changelog-section .changelog-title{font-size:1.25em;line-height:1.5;margin-bottom:.5em;margin-top:.5em}.buddypress .bp-changelog-section .title,.buddypress .bp-features-section .feature-title{font-size:1.25em;line-height:1.25;margin-top:.6em;text-align:left}.buddypress .bp-features-section .bp-feature,.buddypress .bp-features-section .bp-feature-imaged{clear:both;float:left;margin-bottom:1em;margin-top:1em;margin-right:0;padding-right:1em;width:100%}.buddypress .bp-features-section .bp-feature-imaged p{font-size:1em}.buddypress .bp-features-section .bp-feature span{margin-top:.33em}.buddypress .bp-feature.opposite .feature-title,.buddypress .bp-feature.opposite p{float:none}.buddypress .bp-changelog-section{clear:both;margin-bottom:2em;margin-top:2em}.buddypress .bp-changelog{margin-bottom:0}.buddypress .bp-changelog-section .changelog-title{margin-bottom:.5em}.buddypress .bp-changelog .title{font-size:1em}.buddypress .bp-changelog p{margin-bottom:1em}.buddypress .bp-changelog-section .three-col .col,.buddypress .bp-changelog-section .two-col>div{margin-top:0;padding-bottom:.5em;width:100%}.buddypress .bp-three-column .bp-column{width:100%}}@media screen and (max-width:360px){.buddypress .bp-headline{text-align:center}.buddypress .bp-headline span.dashicons{clear:none;font-size:80px;float:none;height:80px;line-height:80px;margin:0 auto;width:80px}.buddypress .bp-features-section .headline-title,.buddypress .bp-headline-feature .headline-title{font-size:1.5em;line-height:1.5;text-align:left}.buddypress .bp-headline-feature .headline-title{margin:1em 0 0}.buddypress .bp-headline-feature p{margin:1.15em auto .6em 0;text-align:left;width:auto}.buddypress .bp-features-section .bp-feature{text-align:center}.buddypress .bp-features-section span.dashicons{float:none}.buddypress .bp-features-section .feature-title,.buddypress .bp-features-section p{margin-left:0;text-align:left}}#adminmenu #toplevel_page_bp-activity .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-activity_user .wp-menu-image:before{content:"\f452"}#adminmenu #toplevel_page_bp-groups .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-groups_user .wp-menu-image:before{content:"\f456"}#adminmenu #toplevel_page_bp-notifications .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-notifications_user .wp-menu-image:before{content:"\f439"}#adminmenu #toplevel_page_bp-messages .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-messages_user .wp-menu-image:before{content:"\f457"}#adminmenu #toplevel_page_bp-friends .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-friends_user .wp-menu-image:before{content:"\f454"}#adminmenu #toplevel_page_bp-settings .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_network .wp-menu-image:before,#adminmenu #toplevel_page_bp-settings_user .wp-menu-image:before{content:"\f108"}#adminmenu li.toplevel_page_bp-components .wp-menu-image,#adminmenu li.toplevel_page_bp-general-settings .wp-menu-image{content:"\f448"}.settings_page_bp-components td.plugin-title span{float:left;width:18px;height:18px;margin-right:5px}.settings_page_bp-components td.plugin-title span:before{font-family:dashicons;font-size:18px}.settings_page_bp-components tr.activity td.plugin-title span:before{content:"\f452"}.settings_page_bp-components tr.notifications td.plugin-title span:before{content:"\f339"}.settings_page_bp-components tr.xprofile td.plugin-title span:before{content:"\f336"}.settings_page_bp-components tr.settings td.plugin-title span:before{content:"\f108"}.settings_page_bp-components tr.groups td.plugin-title span:before{content:"\f456"}.settings_page_bp-components tr.messages td.plugin-title span:before{content:"\f457"}.settings_page_bp-components tr.blogs td.plugin-title span:before{content:"\f120"}.settings_page_bp-components tr.friends td.plugin-title span:before{content:"\f454"}.settings_page_bp-components tr.core td.plugin-title span:before{content:"\f448"}.settings_page_bp-components tr.members td.plugin-title span:before{content:"\f307"}#bp-admin-component-form .wp-list-table.plugins .plugin-title{width:25%}@media screen and (max-width:782px){.settings_page_bp-components td.plugin-title span{margin-top:5px}#bp-admin-component-form .wp-list-table.plugins .plugin-title{display:block;width:auto}#bp-admin-component-form .subsubsub{margin-bottom:0;padding-bottom:35px}}#adminmenu .toplevel_page_network-tools div.wp-menu-image:before{content:""}body.site-users-php th#role,body.users-php th#role,body.users_page_bp-signups th#count_sent{width:10%}body.site-users-php th#email,body.site-users-php th#name,body.users-php th#email,body.users-php th#name,body.users-php th#registered,body.users_page_bp-signups th#date_sent,body.users_page_bp-signups th#email,body.users_page_bp-signups th#name,body.users_page_bp-signups th#registered{width:15%}body.users-php th#blogs,body.users_page_bp-signups th#blogs{width:20%}body.users_page_bp-signups td.count_sent,body.users_page_bp-signups th.column-count_sent{text-align:center}.bp-signups-list table{margin:1em 0}.bp-signups-list .column-fields{font-weight:700}.bp-new-notice-panel{background:#fff;border:1px solid #e5e5e5;box-shadow:0 1px 1px rgba(0,0,0,.04);font-size:13px;line-height:2.1;margin:1.5em 0 3em;overflow:auto;padding:10px 25px 25px;position:relative}.bp-new-notice-panel label{clear:both;float:left;margin-right:3%;width:20%}.bp-new-notice-panel input,.bp-new-notice-panel textarea{clear:none;margin-bottom:1em;width:75%}.bp-new-notice-panel input[type=text]:after,.bp-new-notice-panel textarea:after{clear:both;content:" ";display:table}.bp-new-notice-panel .button-primary{margin-left:23%;width:auto}.bp-notice-about{font-size:1em;margin-bottom:1em}.bp-new-notice{margin-bottom:1em;margin-top:0}.bp-notices-list{margin-bottom:0}@media screen and (max-width:782px){.bp-new-notice-panel{margin-bottom:1.5em}.bp-new-notice-panel input,.bp-new-notice-panel textarea{margin-left:0;width:100%}.bp-new-notice-panel .button-primary{margin-left:0;width:auto}.bp-new-notice-panel .button{max-width:45%;word-wrap:break-word}.bp-notice-about{margin-top:0;margin-bottom:1em}.bp-new-notice{margin-bottom:.5em}}body.post-type-bp-email #excerpt{height:auto}body.post-type-bp-email th#situation{width:20%}body.post-type-bp-email td.column-situation ul{margin:0}body.post-type-bp-email .categorydiv label{display:block;float:left;padding-left:25px;text-indent:-25px}.tools_page_bp-tools .wrap{max-width:950px}.tools_page_bp-tools p{line-height:2}.tools_page_bp-tools fieldset{margin:2em 0 0}.tools_page_bp-tools legend{color:#23282d;font-size:1.3em;font-weight:600;margin:1em 0}.tools_page_bp-tools label{clear:left;display:block;line-height:1.5;margin:0 0 1em;vertical-align:middle}@media screen and (max-width:782px){.tools_page_bp-tools p{line-height:1.5}.tools_page_bp-tools label{margin-bottom:1em;padding-right:25px;text-indent:-33px}.tools_page_bp-tools .checkbox{padding:0 0 0 30px}}#buddypress-update.not-shiny .update-message{border-left:0;padding-left:36px}#buddypress-update.not-shiny .update-message:before{content:"\f534"}
bp-core/admin/css/customizer-controls-rtl.css CHANGED
@@ -1,7 +1,7 @@
1
  .customize-control-range output {
2
- background-color: #FFF;
3
- border: 1px solid #DDD;
4
- box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.07 );
5
  float: right;
6
  margin-left: 10px;
7
  margin-top: -4px;
1
  .customize-control-range output {
2
+ background-color: #fff;
3
+ border: 1px solid #ddd;
4
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.07);
5
  float: right;
6
  margin-left: 10px;
7
  margin-top: -4px;
bp-core/admin/css/customizer-controls-rtl.min.css CHANGED
@@ -1 +1 @@
1
- .customize-control-range output{background-color:#FFF;border:1px solid #DDD;box-shadow:inset 0 1px 2px rgba(0,0,0,.07);float:right;margin-left:10px;margin-top:-4px;min-width:16px;padding:5px}
1
+ .customize-control-range output{background-color:#fff;border:1px solid #ddd;box-shadow:inset 0 1px 2px rgba(0,0,0,.07);float:right;margin-left:10px;margin-top:-4px;min-width:16px;padding:5px}
bp-core/admin/css/customizer-controls.css CHANGED
@@ -1,7 +1,7 @@
1
  .customize-control-range output {
2
- background-color: #FFF;
3
- border: 1px solid #DDD;
4
- box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.07 );
5
  float: left;
6
  margin-right: 10px;
7
  margin-top: -4px;
1
  .customize-control-range output {
2
+ background-color: #fff;
3
+ border: 1px solid #ddd;
4
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.07);
5
  float: left;
6
  margin-right: 10px;
7
  margin-top: -4px;
bp-core/admin/css/customizer-controls.min.css CHANGED
@@ -1 +1 @@
1
- .customize-control-range output{background-color:#FFF;border:1px solid #DDD;box-shadow:inset 0 1px 2px rgba(0,0,0,.07);float:left;margin-right:10px;margin-top:-4px;min-width:16px;padding:5px}
1
+ .customize-control-range output{background-color:#fff;border:1px solid #ddd;box-shadow:inset 0 1px 2px rgba(0,0,0,.07);float:left;margin-right:10px;margin-top:-4px;min-width:16px;padding:5px}
bp-core/admin/images/autolink-feature.png DELETED
Binary file
bp-core/admin/images/bp-emails-feature.png DELETED
Binary file
bp-core/admin/images/emoji-feature.png DELETED
Binary file
bp-core/admin/images/post-type.png DELETED
Binary file
bp-core/admin/images/twentytwelve.png DELETED
Binary file
bp-core/admin/js/customizer-controls.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){a(window).on("load",function(){a(".customize-control-range input").on("input",function(){var b=a(this);b.siblings("output").text(b.val())})})}(jQuery);
1
+ !function(n){n(window).on("load",function(){n(".customize-control-range input").on("input",function(){var t=n(this);t.siblings("output").text(t.val())})})}(jQuery);
bp-core/admin/js/customizer-receiver-emails.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){wp.customize("bp_email_options[email_bg]",function(b){b.bind(function(b){b.length&&(a(".email_bg").attr("bgcolor",b),a("hr").attr("color",b))})}),wp.customize("bp_email_options[header_bg]",function(b){b.bind(function(b){b.length&&a(".header_bg").attr("bgcolor",b)})}),wp.customize("bp_email_options[header_text_size]",function(b){b.bind(function(b){b.length&&a(".header_text_size").css("font-size",b+"px")})}),wp.customize("bp_email_options[header_text_color]",function(b){b.bind(function(b){b.length&&a(".header_text_color").css("color",b)})}),wp.customize("bp_email_options[highlight_color]",function(b){b.bind(function(b){b.length&&(a(".header_bg").css("border-top-color",b),a("a").css("color",b),a("hr").attr("color",b))})}),wp.customize("bp_email_options[body_bg]",function(b){b.bind(function(b){b.length&&a(".body_bg").attr("bgcolor",b)})}),wp.customize("bp_email_options[body_text_size]",function(b){b.bind(function(b){b.length&&(a(".body_text_size").css("font-size",b+"px").css("line-height",Math.floor(1.618*b)+"px"),a(".welcome").css("font-size",Math.floor(1.35*b)+"px"))})}),wp.customize("bp_email_options[body_text_color]",function(b){b.bind(function(b){b.length&&a(".body_text_color").css("color",b)})}),wp.customize("bp_email_options[footer_bg]",function(b){b.bind(function(b){b.length&&a(".footer_bg").attr("bgcolor",b)})}),wp.customize("bp_email_options[footer_text_size]",function(b){b.bind(function(b){b.length&&a(".footer_text_size").css("font-size",b+"px").css("line-height",Math.floor(1.618*b)+"px")})}),wp.customize("bp_email_options[footer_text_color]",function(b){b.bind(function(b){b.length&&a(".footer_text_color").css("color",b)})}),wp.customize("bp_email_options[footer_text]",function(b){b.bind(function(b){a(".footer_text").text(b)})})}(jQuery);
1
+ !function(o){wp.customize("bp_email_options[email_bg]",function(t){t.bind(function(t){t.length&&(o(".email_bg").attr("bgcolor",t),o("hr").attr("color",t))})}),wp.customize("bp_email_options[header_bg]",function(t){t.bind(function(t){t.length&&o(".header_bg").attr("bgcolor",t)})}),wp.customize("bp_email_options[header_text_size]",function(t){t.bind(function(t){t.length&&o(".header_text_size").css("font-size",t+"px")})}),wp.customize("bp_email_options[header_text_color]",function(t){t.bind(function(t){t.length&&o(".header_text_color").css("color",t)})}),wp.customize("bp_email_options[highlight_color]",function(t){t.bind(function(t){t.length&&(o(".header_bg").css("border-top-color",t),o("a").css("color",t),o("hr").attr("color",t))})}),wp.customize("bp_email_options[body_bg]",function(t){t.bind(function(t){t.length&&o(".body_bg").attr("bgcolor",t)})}),wp.customize("bp_email_options[body_text_size]",function(t){t.bind(function(t){t.length&&(o(".body_text_size").css("font-size",t+"px").css("line-height",Math.floor(1.618*t)+"px"),o(".welcome").css("font-size",Math.floor(1.35*t)+"px"))})}),wp.customize("bp_email_options[body_text_color]",function(t){t.bind(function(t){t.length&&o(".body_text_color").css("color",t)})}),wp.customize("bp_email_options[footer_bg]",function(t){t.bind(function(t){t.length&&o(".footer_bg").attr("bgcolor",t)})}),wp.customize("bp_email_options[footer_text_size]",function(t){t.bind(function(t){t.length&&o(".footer_text_size").css("font-size",t+"px").css("line-height",Math.floor(1.618*t)+"px")})}),wp.customize("bp_email_options[footer_text_color]",function(t){t.bind(function(t){t.length&&o(".footer_text_color").css("color",t)})}),wp.customize("bp_email_options[footer_text]",function(t){t.bind(function(t){o(".footer_text").text(t)})})}(jQuery);
bp-core/admin/js/dismissible-admin-notices.js ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($){
2
+ $(document).ready(function() {
3
+ $( '.bp-is-dismissible .notice-dismiss' ).click( function() {
4
+ var $notice = $( this ).closest( '.notice' );
5
+ var notice_id = $notice.data( 'noticeid' );
6
+ $.post( {
7
+ url: ajaxurl,
8
+ data: {
9
+ action: 'bp_dismiss_notice',
10
+ nonce: $( '#bp-dismissible-nonce-' + notice_id ).val(),
11
+ notice_id: $notice.data( 'noticeid' )
12
+ }
13
+ } );
14
+ } );
15
+ });
16
+ }(jQuery));
bp-core/admin/js/dismissible-admin-notices.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(i){i(document).ready(function(){i(".bp-is-dismissible .notice-dismiss").click(function(){var n=i(this).closest(".notice"),s=n.data("noticeid");i.post({url:ajaxurl,data:{action:"bp_dismiss_notice",nonce:i("#bp-dismissible-nonce-"+s).val(),notice_id:n.data("noticeid")}})})})}(jQuery);
bp-core/bp-core-actions.php CHANGED
@@ -29,7 +29,7 @@ defined( 'ABSPATH' ) || exit;
29
  * near the bottom of this file.
30
  *
31
  * v--WordPress Actions v--BuddyPress Sub-actions
32
- */
33
  add_action( 'plugins_loaded', 'bp_loaded', 10 );
34
  add_action( 'init', 'bp_init', 10 );
35
  add_action( 'rest_api_init', 'bp_rest_api_init', 20 ); // After WP core.
@@ -55,9 +55,9 @@ add_action( 'generate_rewrite_rules', 'bp_generate_rewrite_rules', 10 );
55
  */
56
  add_action( 'bp_loaded', 'bp_setup_components', 2 );
57
  add_action( 'bp_loaded', 'bp_include', 4 );
 
58
  add_action( 'bp_loaded', 'bp_setup_cache_groups', 5 );
59
  add_action( 'bp_loaded', 'bp_setup_widgets', 6 );
60
- add_action( 'bp_loaded', 'bp_register_member_types', 8 );
61
  add_action( 'bp_loaded', 'bp_register_theme_packages', 12 );
62
  add_action( 'bp_loaded', 'bp_register_theme_directory', 14 );
63
 
@@ -68,9 +68,9 @@ add_action( 'bp_loaded', 'bp_register_theme_directory', 14 );
68
  * The load order helps to execute code at the correct time.
69
  * v---Load order
70
  */
 
 
71
  add_action( 'bp_init', 'bp_core_set_uri_globals', 2 );
72
- add_action( 'bp_init', 'bp_register_post_types', 3 );
73
- add_action( 'bp_init', 'bp_register_taxonomies', 3 );
74
  add_action( 'bp_init', 'bp_setup_globals', 4 );
75
  add_action( 'bp_init', 'bp_setup_canonical_stack', 5 );
76
  add_action( 'bp_init', 'bp_setup_nav', 6 );
@@ -80,6 +80,19 @@ add_action( 'bp_init', 'bp_add_rewrite_tags', 20 );
80
  add_action( 'bp_init', 'bp_add_rewrite_rules', 30 );
81
  add_action( 'bp_init', 'bp_add_permastructs', 40 );
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  /**
84
  * The bp_template_redirect hook - Attached to 'template_redirect' above.
85
  *
@@ -100,8 +113,9 @@ add_action( 'bp_template_redirect', 'bp_get_request', 10 );
100
  /**
101
  * Add the BuddyPress functions file and the Theme Compat Default features.
102
  */
103
- add_action( 'bp_after_setup_theme', 'bp_load_theme_functions', 1 );
104
- add_action( 'bp_after_setup_theme', 'bp_register_theme_compat_default_features', 10 );
 
105
 
106
  // Load the admin.
107
  if ( is_admin() ) {
@@ -110,3 +124,6 @@ if ( is_admin() ) {
110
 
111
  // Activation redirect.
112
  add_action( 'bp_activation', 'bp_add_activation_redirect' );
 
 
 
29
  * near the bottom of this file.
30
  *
31
  * v--WordPress Actions v--BuddyPress Sub-actions
32
+ */
33
  add_action( 'plugins_loaded', 'bp_loaded', 10 );
34
  add_action( 'init', 'bp_init', 10 );
35
  add_action( 'rest_api_init', 'bp_rest_api_init', 20 ); // After WP core.
55
  */
56
  add_action( 'bp_loaded', 'bp_setup_components', 2 );
57
  add_action( 'bp_loaded', 'bp_include', 4 );
58
+ add_action( 'bp_loaded', 'bp_setup_option_filters', 5 );
59
  add_action( 'bp_loaded', 'bp_setup_cache_groups', 5 );
60
  add_action( 'bp_loaded', 'bp_setup_widgets', 6 );
 
61
  add_action( 'bp_loaded', 'bp_register_theme_packages', 12 );
62
  add_action( 'bp_loaded', 'bp_register_theme_directory', 14 );
63
 
68
  * The load order helps to execute code at the correct time.
69
  * v---Load order
70
  */
71
+ add_action( 'bp_init', 'bp_register_post_types', 2 );
72
+ add_action( 'bp_init', 'bp_register_taxonomies', 2 );
73
  add_action( 'bp_init', 'bp_core_set_uri_globals', 2 );
 
 
74
  add_action( 'bp_init', 'bp_setup_globals', 4 );
75
  add_action( 'bp_init', 'bp_setup_canonical_stack', 5 );
76
  add_action( 'bp_init', 'bp_setup_nav', 6 );
80
  add_action( 'bp_init', 'bp_add_rewrite_rules', 30 );
81
  add_action( 'bp_init', 'bp_add_permastructs', 40 );
82
 
83
+ /**
84
+ * The bp_register_taxonomies hook - Attached to 'bp_init' @ priority 2 above.
85
+ */
86
+ add_action( 'bp_register_taxonomies', 'bp_register_member_types' );
87
+
88
+ /**
89
+ * Late includes.
90
+ *
91
+ * Run after the canonical stack is setup to allow for conditional includes
92
+ * on certain pages.
93
+ */
94
+ add_action( 'bp_setup_canonical_stack', 'bp_late_include', 20 );
95
+
96
  /**
97
  * The bp_template_redirect hook - Attached to 'template_redirect' above.
98
  *
113
  /**
114
  * Add the BuddyPress functions file and the Theme Compat Default features.
115
  */
116
+ add_action( 'bp_after_setup_theme', 'bp_check_theme_template_pack_dependency', -10 );
117
+ add_action( 'bp_after_setup_theme', 'bp_load_theme_functions', 1 );
118
+ add_action( 'bp_after_setup_theme', 'bp_register_theme_compat_default_features', 10 );
119
 
120
  // Load the admin.
121
  if ( is_admin() ) {
124
 
125
  // Activation redirect.
126
  add_action( 'bp_activation', 'bp_add_activation_redirect' );
127
+
128
+ // Email unsubscribe.
129
+ add_action( 'bp_get_request_unsubscribe', 'bp_email_unsubscribe_handler' );
bp-core/bp-core-admin.php CHANGED
@@ -10,10 +10,6 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-admin.php';
15
- }
16
-
17
  /**
18
  * Setup BuddyPress Admin.
19
  *
@@ -30,25 +26,33 @@ function bp_admin() {
30
  _n_noop( 'Security Release', 'Security Releases', 'buddypress' );
31
  _n_noop( 'Maintenance and Security Release', 'Maintenance and Security Releases', 'buddypress' );
32
 
33
- /* translators: 1: WordPress version number. */
34
- _n_noop( '<strong>Version %1$s</strong> addressed a security issue.',
35
- '<strong>Version %1$s</strong> addressed some security issues.',
36
- 'buddypress' );
37
-
38
- /* translators: 1: WordPress version number, 2: plural number of bugs. */
39
- _n_noop( '<strong>Version %1$s</strong> addressed %2$s bug.',
40
- '<strong>Version %1$s</strong> addressed %2$s bugs.',
41
- 'buddypress' );
42
-
43
- /* translators: 1: WordPress version number, 2: plural number of bugs. Singular security issue. */
44
- _n_noop( '<strong>Version %1$s</strong> addressed a security issue and fixed %2$s bug.',
45
- '<strong>Version %1$s</strong> addressed a security issue and fixed %2$s bugs.',
46
- 'buddypress' );
47
-
48
- /* translators: 1: WordPress version number, 2: plural number of bugs. More than one security issue. */
49
- _n_noop( '<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bug.',
50
- '<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bugs.',
51
- 'buddypress' );
 
 
 
 
 
 
 
 
52
 
53
  __( 'For more information, see <a href="%s">the release notes</a>.', 'buddypress' );
54
  }
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
13
  /**
14
  * Setup BuddyPress Admin.
15
  *
26
  _n_noop( 'Security Release', 'Security Releases', 'buddypress' );
27
  _n_noop( 'Maintenance and Security Release', 'Maintenance and Security Releases', 'buddypress' );
28
 
29
+ /* translators: 1: BuddyPress version number. */
30
+ _n_noop(
31
+ '<strong>Version %1$s</strong> addressed a security issue.',
32
+ '<strong>Version %1$s</strong> addressed some security issues.',
33
+ 'buddypress'
34
+ );
35
+
36
+ /* translators: 1: BuddyPress version number, 2: plural number of bugs. */
37
+ _n_noop(
38
+ '<strong>Version %1$s</strong> addressed %2$s bug.',
39
+ '<strong>Version %1$s</strong> addressed %2$s bugs.',
40
+ 'buddypress'
41
+ );
42
+
43
+ /* translators: 1: BuddyPress version number, 2: plural number of bugs. Singular security issue. */
44
+ _n_noop(
45
+ '<strong>Version %1$s</strong> addressed a security issue and fixed %2$s bug.',
46
+ '<strong>Version %1$s</strong> addressed a security issue and fixed %2$s bugs.',
47
+ 'buddypress'
48
+ );
49
+
50
+ /* translators: 1: BuddyPress version number, 2: plural number of bugs. More than one security issue. */
51
+ _n_noop(
52
+ '<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bug.',
53
+ '<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bugs.',
54
+ 'buddypress'
55
+ );
56
 
57
  __( 'For more information, see <a href="%s">the release notes</a>.', 'buddypress' );
58
  }
bp-core/bp-core-adminbar.php CHANGED
@@ -39,12 +39,6 @@ function bp_admin_bar_my_account_root() {
39
  'class' => 'ab-sub-secondary'
40
  )
41
  ) );
42
-
43
- // Remove 'Edit' post link as it's not applicable to BP.
44
- // Remove when https://core.trac.wordpress.org/ticket/29538 is addressed.
45
- if ( is_buddypress() ) {
46
- $wp_admin_bar->remove_node( 'edit' );
47
- }
48
  }
49
  }
50
  add_action( 'admin_bar_menu', 'bp_admin_bar_my_account_root', 100 );
@@ -53,8 +47,6 @@ add_action( 'admin_bar_menu', 'bp_admin_bar_my_account_root', 100 );
53
  * Handle the Toolbar/BuddyBar business.
54
  *
55
  * @since 1.2.0
56
- *
57
- * @global string $wp_version
58
  */
59
  function bp_core_load_admin_bar() {
60
 
@@ -67,6 +59,11 @@ function bp_core_load_admin_bar() {
67
  if ( ! bp_use_wp_admin_bar() ) {
68
  _doing_it_wrong( __FUNCTION__, __( 'The BuddyBar is no longer supported. Please migrate to the WordPress toolbar as soon as possible.', 'buddypress' ), '2.1.0' );
69
 
 
 
 
 
 
70
  // Keep the WP Toolbar from loading.
71
  show_admin_bar( false );
72
 
39
  'class' => 'ab-sub-secondary'
40
  )
41
  ) );
 
 
 
 
 
 
42
  }
43
  }
44
  add_action( 'admin_bar_menu', 'bp_admin_bar_my_account_root', 100 );
47
  * Handle the Toolbar/BuddyBar business.
48
  *
49
  * @since 1.2.0
 
 
50
  */
51
  function bp_core_load_admin_bar() {
52
 
59
  if ( ! bp_use_wp_admin_bar() ) {
60
  _doing_it_wrong( __FUNCTION__, __( 'The BuddyBar is no longer supported. Please migrate to the WordPress toolbar as soon as possible.', 'buddypress' ), '2.1.0' );
61
 
62
+ // Load deprecated code if not available.
63
+ if ( ! function_exists( 'bp_core_admin_bar' ) ) {
64
+ require buddypress()->plugin_dir . 'bp-core/deprecated/2.1.php';
65
+ }
66
+
67
  // Keep the WP Toolbar from loading.
68
  show_admin_bar( false );
69
 
bp-core/bp-core-attachments.php CHANGED
@@ -18,11 +18,12 @@ defined( 'ABSPATH' ) || exit;
18
  * match with our needs.
19
  *
20
  * @since 2.3.0
 
21
  *
22
- * @return bool True if WordPress is 3.9+, false otherwise.
23
  */
24
  function bp_attachments_is_wp_version_supported() {
25
- return (bool) version_compare( bp_get_major_wp_version(), '3.9', '>=' );
26
  }
27
 
28
  /**
@@ -52,6 +53,11 @@ function bp_attachments_uploads_dir_get( $data = '' ) {
52
  foreach ( $upload_data as $key => $value ) {
53
  if ( 'basedir' === $key || 'baseurl' === $key ) {
54
  $upload_data[ $key ] = trailingslashit( $value ) . $attachments_dir;
 
 
 
 
 
55
  } else {
56
  unset( $upload_data[ $key ] );
57
  }
@@ -78,6 +84,58 @@ function bp_attachments_uploads_dir_get( $data = '' ) {
78
  return apply_filters( 'bp_attachments_uploads_dir_get', $retval, $data );
79
  }
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  /**
82
  * Get the max upload file size for any attachment.
83
  *
@@ -260,7 +318,7 @@ function bp_attachments_create_item_type( $type = 'avatar', $args = array() ) {
260
  }
261
 
262
  // Make sure the file path is safe.
263
- if ( 0 !== validate_file( $r['image'] ) ) {
264
  return false;
265
  }
266
 
@@ -307,7 +365,7 @@ function bp_attachments_create_item_type( $type = 'avatar', $args = array() ) {
307
  $attachment_data = call_user_func_array( $r['component'] . '_avatar_upload_dir', $dir_args );
308
  }
309
  } elseif ( 'cover_image' === $type ) {
310
- $attachment_data = bp_attachments_uploads_dir_get();
311
 
312
  // The BP Attachments Uploads Dir is not set, stop.
313
  if ( ! $attachment_data ) {
@@ -442,7 +500,7 @@ function bp_attachments_get_attachment( $data = 'url', $args = array() ) {
442
  $type_subdir = $r['object_dir'] . '/' . $r['item_id'] . '/' . $r['type'];
443
  $type_dir = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $type_subdir;
444
 
445
- if ( ! is_dir( $type_dir ) ) {
446
  return $attachment_data;
447
  }
448
 
@@ -507,7 +565,7 @@ function bp_attachments_delete_file( $args = array() ) {
507
  * @since 2.5.1
508
  *
509
  * @param bool $value Whether or not to delete the BuddyPress attachment.
510
- * @param array Array of arguments for the attachment deletion.
511
  */
512
  if ( ! apply_filters( 'bp_attachments_pre_delete_file', true, $args ) ) {
513
  return true;
@@ -944,7 +1002,7 @@ function bp_attachments_get_template_part( $slug ) {
944
  * @since 2.4.0
945
  *
946
  * @param string $component The component to get the settings for ("xprofile" for user or "groups").
947
- * @return array The cover image settings.
948
  */
949
  function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) {
950
  // Default parameters.
@@ -963,7 +1021,7 @@ function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) {
963
  * Eg: for the user's profile cover image use:
964
  * add_filter( 'bp_before_xprofile_cover_image_settings_parse_args', 'your_filter', 10, 1 );
965
  *
966
- * @since 2.4.0
967
  *
968
  * @param array $settings The cover image settings
969
  */
@@ -990,12 +1048,12 @@ function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) {
990
  }
991
 
992
  /**
993
- * Get cover image Width and Height
994
  *
995
  * @since 2.4.0
996
  *
997
  * @param string $component The BuddyPress component concerned ("xprofile" for user or "groups").
998
- * @return array An associative array containing the advised width and height for the cover image.
999
  */
1000
  function bp_attachments_get_cover_image_dimensions( $component = 'xprofile' ) {
1001
  // Let's prevent notices when setting the warning strings.
@@ -1105,7 +1163,7 @@ function bp_attachments_get_group_has_cover_image( $group_id = 0 ) {
1105
  * @type string $cover_image_dir The Cover image dir to write the image into. Required.
1106
  * }
1107
  * @param BP_Attachment_Cover_Image|null $cover_image_class The class to use to fit the cover image.
1108
- * @return bool|array An array containing cover image data on success, false otherwise.
1109
  */
1110
  function bp_attachments_cover_image_generate_file( $args = array(), $cover_image_class = null ) {
1111
  // Bail if an argument is missing.
@@ -1125,8 +1183,10 @@ function bp_attachments_cover_image_generate_file( $args = array(), $cover_image
1125
  $cover_image_class = new BP_Attachment_Cover_Image();
1126
  }
1127
 
 
 
1128
  // Make sure the file is inside the Cover Image Upload path.
1129
- if ( false === strpos( $args['file'], $cover_image_class->upload_path ) ) {
1130
  return false;
1131
  }
1132
 
@@ -1180,40 +1240,31 @@ function bp_attachments_cover_image_generate_file( $args = array(), $cover_image
1180
  *
1181
  * @since 2.4.0
1182
  *
1183
- * @return string|null A json object containing success data if the upload succeeded
1184
  * error message otherwise.
1185
  */
1186
  function bp_attachments_cover_image_ajax_upload() {
1187
- // Bail if not a POST action.
1188
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1189
  wp_die();
1190
  }
1191
 
1192
- /**
1193
- * Sending the json response will be different if
1194
- * the current Plupload runtime is html4
1195
- */
1196
- $is_html4 = false;
1197
- if ( ! empty( $_POST['html4' ] ) ) {
1198
- $is_html4 = true;
1199
- }
1200
-
1201
- // Check the nonce.
1202
  check_admin_referer( 'bp-uploader' );
1203
 
1204
- // Init the BuddyPress parameters.
1205
- $bp_params = array();
1206
 
1207
- // We need it to carry on.
1208
- if ( ! empty( $_POST['bp_params'] ) ) {
1209
- $bp_params = bp_parse_args( $_POST['bp_params'], array(
1210
- 'object' => 'user',
1211
- 'item_id' => bp_loggedin_user_id(),
1212
- ), 'attachments_cover_image_ajax_upload' );
1213
- } else {
1214
  bp_attachments_json_response( false, $is_html4 );
1215
  }
1216
 
 
 
 
 
 
 
 
 
1217
  // We need the object to set the uploads dir filter.
1218
  if ( empty( $bp_params['object'] ) ) {
1219
  bp_attachments_json_response( false, $is_html4 );
@@ -1242,10 +1293,7 @@ function bp_attachments_cover_image_ajax_upload() {
1242
 
1243
  if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
1244
  $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
1245
- $bp->groups->current_group = groups_get_group( array(
1246
- 'group_id' => $bp_params['item_id'],
1247
- 'populate_extras' => false,
1248
- ) );
1249
  }
1250
 
1251
  // Other object's cover image.
@@ -1295,11 +1343,9 @@ function bp_attachments_cover_image_ajax_upload() {
1295
  ) );
1296
  }
1297
 
1298
- // Default error message.
1299
  $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
1300
 
1301
- // Get BuddyPress Attachments Uploads Dir datas.
1302
- $bp_attachments_uploads_dir = bp_attachments_uploads_dir_get();
1303
 
1304
  // The BP Attachments Uploads Dir is not set, stop.
1305
  if ( ! $bp_attachments_uploads_dir ) {
@@ -1312,7 +1358,7 @@ function bp_attachments_cover_image_ajax_upload() {
1312
  $cover_subdir = $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image';
1313
  $cover_dir = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $cover_subdir;
1314
 
1315
- if ( ! is_dir( $cover_dir ) ) {
1316
  // Upload error response.
1317
  bp_attachments_json_response( false, $is_html4, array(
1318
  'type' => 'upload_error',
@@ -1320,10 +1366,10 @@ function bp_attachments_cover_image_ajax_upload() {
1320
  ) );
1321
  }
1322
 
1323
- /**
1324
  * Generate the cover image so that it fit to feature's dimensions
1325
  *
1326
- * Unlike the Avatar, Uploading and generating the cover image is happening during
1327
  * the same Ajax request, as we already instantiated the BP_Attachment_Cover_Image
1328
  * class, let's use it.
1329
  */
@@ -1334,17 +1380,15 @@ function bp_attachments_cover_image_ajax_upload() {
1334
  ), $cover_image_attachment );
1335
 
1336
  if ( ! $cover ) {
1337
- // Upload error response.
1338
  bp_attachments_json_response( false, $is_html4, array(
1339
  'type' => 'upload_error',
1340
  'message' => $error_message,
1341
  ) );
1342
  }
1343
 
1344
- // Build the url to the file.
1345
  $cover_url = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $cover_subdir . '/' . $cover['cover_basename'];
1346
 
1347
- // Init Feedback code, 1 is success.
1348
  $feedback_code = 1;
1349
 
1350
  // 0 is the size warning.
@@ -1366,10 +1410,20 @@ function bp_attachments_cover_image_ajax_upload() {
1366
  * code once the user has set his cover image.
1367
  *
1368
  * @since 2.4.0
 
1369
  *
1370
- * @param int $item_id Inform about the item id the cover image was set for.
 
 
 
1371
  */
1372
- do_action( $object_data['component'] . '_cover_image_uploaded', (int) $bp_params['item_id'] );
 
 
 
 
 
 
1373
 
1374
  // Finally return the cover image url to the UI.
1375
  bp_attachments_json_response( true, $is_html4, array(
@@ -1389,43 +1443,55 @@ add_action( 'wp_ajax_bp_cover_image_upload', 'bp_attachments_cover_image_ajax_up
1389
  * error message otherwise.
1390
  */
1391
  function bp_attachments_cover_image_ajax_delete() {
1392
- // Bail if not a POST action.
1393
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1394
  wp_send_json_error();
1395
  }
1396
 
1397
- $cover_image_data = $_POST;
1398
-
1399
- if ( empty( $cover_image_data['object'] ) || empty( $cover_image_data['item_id'] ) ) {
1400
  wp_send_json_error();
1401
  }
1402
 
1403
- // Check the nonce.
1404
- check_admin_referer( 'bp_delete_cover_image', 'nonce' );
 
 
1405
 
1406
- // Capability check.
1407
- if ( ! bp_attachments_current_user_can( 'edit_cover_image', $cover_image_data ) ) {
 
1408
  wp_send_json_error();
1409
  }
1410
 
1411
  // Set object for the user's case.
1412
- if ( 'user' === $cover_image_data['object'] ) {
1413
  $component = 'xprofile';
1414
  $dir = 'members';
1415
 
1416
  // Set it for any other cases.
1417
  } else {
1418
- $component = $cover_image_data['object'] . 's';
1419
  $dir = $component;
1420
  }
1421
 
1422
  // Handle delete.
1423
- if ( bp_attachments_delete_file( array( 'item_id' => $cover_image_data['item_id'], 'object_dir' => $dir, 'type' => 'cover-image' ) ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
1424
 
1425
- // Defaults no cover image.
1426
  $response = array(
1427
  'reset_url' => '',
1428
- 'feedback_code' => 3 ,
1429
  );
1430
 
1431
  // Get cover image settings in case there's a default header.
@@ -1436,7 +1502,6 @@ function bp_attachments_cover_image_ajax_delete() {
1436
  $response['reset_url'] = $cover_params['default_cover'];
1437
  }
1438
 
1439
- // Finally send the reset url.
1440
  wp_send_json_success( $response );
1441
 
1442
  } else {
18
  * match with our needs.
19
  *
20
  * @since 2.3.0
21
+ * @since 3.0.0 We now require WP >= 4.5, so this is always true.
22
  *
23
+ * @return bool Always true.
24
  */
25
  function bp_attachments_is_wp_version_supported() {
26
+ return true;
27
  }
28
 
29
  /**
53
  foreach ( $upload_data as $key => $value ) {
54
  if ( 'basedir' === $key || 'baseurl' === $key ) {
55
  $upload_data[ $key ] = trailingslashit( $value ) . $attachments_dir;
56
+
57
+ // Fix for HTTPS.
58
+ if ( 'baseurl' === $key && is_ssl() ) {
59
+ $upload_data[ $key ] = str_replace( 'http://', 'https://', $upload_data[ $key ] );
60
+ }
61
  } else {
62
  unset( $upload_data[ $key ] );
63
  }
84
  return apply_filters( 'bp_attachments_uploads_dir_get', $retval, $data );
85
  }
86
 
87
+ /**
88
+ * Gets the upload dir array for cover images.
89
+ *
90
+ * @since 3.0.0
91
+ *
92
+ * @return array See wp_upload_dir().
93
+ */
94
+ function bp_attachments_cover_image_upload_dir( $args = array() ) {
95
+ // Default values are for profiles.
96
+ $object_id = bp_displayed_user_id();
97
+
98
+ if ( empty( $object_id ) ) {
99
+ $object_id = bp_loggedin_user_id();
100
+ }
101
+
102
+ $object_directory = 'members';
103
+
104
+ // We're in a group, edit default values.
105
+ if ( bp_is_group() || bp_is_group_create() ) {
106
+ $object_id = bp_get_current_group_id();
107
+ $object_directory = 'groups';
108
+ }
109
+
110
+ $r = bp_parse_args( $args, array(
111
+ 'object_id' => $object_id,
112
+ 'object_directory' => $object_directory,
113
+ ), 'cover_image_upload_dir' );
114
+
115
+
116
+ // Set the subdir.
117
+ $subdir = '/' . $r['object_directory'] . '/' . $r['object_id'] . '/cover-image';
118
+
119
+ $upload_dir = bp_attachments_uploads_dir_get();
120
+
121
+ /**
122
+ * Filters the cover image upload directory.
123
+ *
124
+ * @since 2.4.0
125
+ *
126
+ * @param array $value Array containing the path, URL, and other helpful settings.
127
+ * @param array $upload_dir The original Uploads dir.
128
+ */
129
+ return apply_filters( 'bp_attachments_cover_image_upload_dir', array(
130
+ 'path' => $upload_dir['basedir'] . $subdir,
131
+ 'url' => set_url_scheme( $upload_dir['baseurl'] ) . $subdir,
132
+ 'subdir' => $subdir,
133
+ 'basedir' => $upload_dir['basedir'],
134
+ 'baseurl' => set_url_scheme( $upload_dir['baseurl'] ),
135
+ 'error' => false,
136
+ ), $upload_dir );
137
+ }
138
+
139
  /**
140
  * Get the max upload file size for any attachment.
141
  *
318
  }
319
 
320
  // Make sure the file path is safe.
321
+ if ( 1 === validate_file( $r['image'] ) ) {
322
  return false;
323
  }
324
 
365
  $attachment_data = call_user_func_array( $r['component'] . '_avatar_upload_dir', $dir_args );
366
  }
367
  } elseif ( 'cover_image' === $type ) {
368
+ $attachment_data = bp_attachments_cover_image_upload_dir();
369
 
370
  // The BP Attachments Uploads Dir is not set, stop.
371
  if ( ! $attachment_data ) {
500
  $type_subdir = $r['object_dir'] . '/' . $r['item_id'] . '/' . $r['type'];
501
  $type_dir = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $type_subdir;
502
 
503
+ if ( 1 === validate_file( $type_dir ) || ! is_dir( $type_dir ) ) {
504
  return $attachment_data;
505
  }
506
 
565
  * @since 2.5.1
566
  *
567
  * @param bool $value Whether or not to delete the BuddyPress attachment.
568
+ ` * @param array $args Array of arguments for the attachment deletion.
569
  */
570
  if ( ! apply_filters( 'bp_attachments_pre_delete_file', true, $args ) ) {
571
  return true;
1002
  * @since 2.4.0
1003
  *
1004
  * @param string $component The component to get the settings for ("xprofile" for user or "groups").
1005
+ * @return false|array The cover image settings in array, false on failure.
1006
  */
1007
  function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) {
1008
  // Default parameters.
1021
  * Eg: for the user's profile cover image use:
1022
  * add_filter( 'bp_before_xprofile_cover_image_settings_parse_args', 'your_filter', 10, 1 );
1023
  *
1024
+ * @since 2.4.0
1025
  *
1026
  * @param array $settings The cover image settings
1027
  */
1048
  }
1049
 
1050
  /**
1051
+ * Get cover image Width and Height.
1052
  *
1053
  * @since 2.4.0
1054
  *
1055
  * @param string $component The BuddyPress component concerned ("xprofile" for user or "groups").
1056
+ * @return array|bool An associative array containing the advised width and height for the cover image. False if settings are empty.
1057
  */
1058
  function bp_attachments_get_cover_image_dimensions( $component = 'xprofile' ) {
1059
  // Let's prevent notices when setting the warning strings.
1163
  * @type string $cover_image_dir The Cover image dir to write the image into. Required.
1164
  * }
1165
  * @param BP_Attachment_Cover_Image|null $cover_image_class The class to use to fit the cover image.
1166
+ * @return false|array An array containing cover image data on success, false otherwise.
1167
  */
1168
  function bp_attachments_cover_image_generate_file( $args = array(), $cover_image_class = null ) {
1169
  // Bail if an argument is missing.
1183
  $cover_image_class = new BP_Attachment_Cover_Image();
1184
  }
1185
 
1186
+ $upload_dir = bp_attachments_cover_image_upload_dir();
1187
+
1188
  // Make sure the file is inside the Cover Image Upload path.
1189
+ if ( false === strpos( $args['file'], $upload_dir['basedir'] ) ) {
1190
  return false;
1191
  }
1192
 
1240
  *
1241
  * @since 2.4.0
1242
  *
1243
+ * @return string|null A json object containing success data if the upload succeeded,
1244
  * error message otherwise.
1245
  */
1246
  function bp_attachments_cover_image_ajax_upload() {
1247
+ if ( ! bp_is_post_request() ) {
 
1248
  wp_die();
1249
  }
1250
 
 
 
 
 
 
 
 
 
 
 
1251
  check_admin_referer( 'bp-uploader' );
1252
 
1253
+ // Sending the json response will be different if the current Plupload runtime is html4.
1254
+ $is_html4 = ! empty( $_POST['html4' ] );
1255
 
1256
+ if ( empty( $_POST['bp_params'] ) ) {
 
 
 
 
 
 
1257
  bp_attachments_json_response( false, $is_html4 );
1258
  }
1259
 
1260
+ $bp_params = bp_parse_args( $_POST['bp_params'], array(
1261
+ 'object' => 'user',
1262
+ 'item_id' => bp_loggedin_user_id(),
1263
+ ), 'attachments_cover_image_ajax_upload' );
1264
+
1265
+ $bp_params['item_id'] = (int) $bp_params['item_id'];
1266
+ $bp_params['object'] = sanitize_text_field( $bp_params['object'] );
1267
+
1268
  // We need the object to set the uploads dir filter.
1269
  if ( empty( $bp_params['object'] ) ) {
1270
  bp_attachments_json_response( false, $is_html4 );
1293
 
1294
  if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
1295
  $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
1296
+ $bp->groups->current_group = groups_get_group( $bp_params['item_id'] );
 
 
 
1297
  }
1298
 
1299
  // Other object's cover image.
1343
  ) );
1344
  }
1345
 
 
1346
  $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
1347
 
1348
+ $bp_attachments_uploads_dir = bp_attachments_cover_image_upload_dir();
 
1349
 
1350
  // The BP Attachments Uploads Dir is not set, stop.
1351
  if ( ! $bp_attachments_uploads_dir ) {
1358
  $cover_subdir = $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image';
1359
  $cover_dir = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $cover_subdir;
1360
 
1361
+ if ( 1 === validate_file( $cover_dir ) || ! is_dir( $cover_dir ) ) {
1362
  // Upload error response.
1363
  bp_attachments_json_response( false, $is_html4, array(
1364
  'type' => 'upload_error',
1366
  ) );
1367
  }
1368
 
1369
+ /*
1370
  * Generate the cover image so that it fit to feature's dimensions
1371
  *
1372
+ * Unlike the avatar, uploading and generating the cover image is happening during
1373
  * the same Ajax request, as we already instantiated the BP_Attachment_Cover_Image
1374
  * class, let's use it.
1375
  */
1380
  ), $cover_image_attachment );
1381
 
1382
  if ( ! $cover ) {
 
1383
  bp_attachments_json_response( false, $is_html4, array(
1384
  'type' => 'upload_error',
1385
  'message' => $error_message,
1386
  ) );
1387
  }
1388
 
 
1389
  $cover_url = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $cover_subdir . '/' . $cover['cover_basename'];
1390
 
1391
+ // 1 is success.
1392
  $feedback_code = 1;
1393
 
1394
  // 0 is the size warning.
1410
  * code once the user has set his cover image.
1411
  *
1412
  * @since 2.4.0
1413
+ * @since 3.0.0 Added $cover_url, $name, $feedback_code arguments.
1414
  *
1415
+ * @param int $item_id Inform about the item id the cover image was set for.
1416
+ * @param string $name Filename.
1417
+ * @param string $cover_url URL to the image.
1418
+ * @param int $feedback_code If value not 1, an error occured.
1419
  */
1420
+ do_action(
1421
+ $object_data['component'] . '_cover_image_uploaded',
1422
+ (int) $bp_params['item_id'],
1423
+ $name,
1424
+ $cover_url,
1425
+ $feedback_code
1426
+ );
1427
 
1428
  // Finally return the cover image url to the UI.
1429
  bp_attachments_json_response( true, $is_html4, array(
1443
  * error message otherwise.
1444
  */
1445
  function bp_attachments_cover_image_ajax_delete() {
1446
+ if ( ! bp_is_post_request() ) {
 
1447
  wp_send_json_error();
1448
  }
1449
 
1450
+ if ( empty( $_POST['object'] ) || empty( $_POST['item_id'] ) ) {
 
 
1451
  wp_send_json_error();
1452
  }
1453
 
1454
+ $args = array(
1455
+ 'object' => sanitize_text_field( $_POST['object'] ),
1456
+ 'item_id' => (int) $_POST['item_id'],
1457
+ );
1458
 
1459
+ // Check permissions.
1460
+ check_admin_referer( 'bp_delete_cover_image', 'nonce' );
1461
+ if ( ! bp_attachments_current_user_can( 'edit_cover_image', $args ) ) {
1462
  wp_send_json_error();
1463
  }
1464
 
1465
  // Set object for the user's case.
1466
+ if ( 'user' === $args['object'] ) {
1467
  $component = 'xprofile';
1468
  $dir = 'members';
1469
 
1470
  // Set it for any other cases.
1471
  } else {
1472
+ $component = $args['object'] . 's';
1473
  $dir = $component;
1474
  }
1475
 
1476
  // Handle delete.
1477
+ if ( bp_attachments_delete_file( array( 'item_id' => $args['item_id'], 'object_dir' => $dir, 'type' => 'cover-image' ) ) ) {
1478
+ /**
1479
+ * Fires if the cover image was successfully deleted.
1480
+ *
1481
+ * The dynamic portion of the hook will be xprofile in case of a user's
1482
+ * cover image, groups in case of a group's cover image. For instance:
1483
+ * Use add_action( 'xprofile_cover_image_deleted' ) to run your specific
1484
+ * code once the user has deleted his cover image.
1485
+ *
1486
+ * @since 2.8.0
1487
+ *
1488
+ * @param int $item_id Inform about the item id the cover image was deleted for.
1489
+ */
1490
+ do_action( "{$component}_cover_image_deleted", (int) $args['item_id'] );
1491
 
 
1492
  $response = array(
1493
  'reset_url' => '',
1494
+ 'feedback_code' => 3,
1495
  );
1496
 
1497
  // Get cover image settings in case there's a default header.
1502
  $response['reset_url'] = $cover_params['default_cover'];
1503
  }
1504
 
 
1505
  wp_send_json_success( $response );
1506
 
1507
  } else {
bp-core/bp-core-avatars.php CHANGED
@@ -313,7 +313,7 @@ function bp_core_fetch_avatar( $args = '' ) {
313
  break;
314
 
315
  case 'group' :
316
- $item_name = bp_get_group_name( groups_get_group( array( 'group_id' => $params['item_id'] ) ) );
317
  break;
318
 
319
  case 'user' :
@@ -542,9 +542,9 @@ function bp_core_fetch_avatar( $args = '' ) {
542
  * @param string $value Subdirectory where the requested avatar should be found.
543
  * @param string $html_css_id ID attribute for avatar.
544
  * @param string $html_width Width attribute for avatar.
545
- * @param string $html_height Height attribtue for avatar.
546
  * @param string $avatar_folder_url Avatar URL path.
547
- * @param string $avatar_folder_dir Avatar dir path.
548
  */
549
  return apply_filters( 'bp_core_fetch_avatar', '<img src="' . $avatar_url . '"' . $html_class . $html_css_id . $html_width . $html_height . $html_alt . $html_title . $extra_attr . ' />', $params, $params['item_id'], $params['avatar_dir'], $html_css_id, $html_width, $html_height, $avatar_folder_url, $avatar_folder_dir );
550
 
@@ -648,7 +648,7 @@ function bp_core_fetch_avatar( $args = '' ) {
648
  * @since 2.6.0
649
  *
650
  * @param string $default_grav The avatar default.
651
- * @param array $params The avatar's data.
652
  */
653
  $default_grav = apply_filters( 'bp_core_avatar_default', $default_grav, $params );
654
 
@@ -726,7 +726,7 @@ function bp_core_delete_existing_avatar( $args = '' ) {
726
  *
727
  * @since 2.5.1
728
  *
729
- * @param bool $value Whether or not to delete the avatar.
730
  * @param array $args {
731
  * Array of function parameters.
732
  *
@@ -805,12 +805,11 @@ function bp_core_delete_existing_avatar( $args = '' ) {
805
  *
806
  * @since 2.3.0
807
  *
808
- * @return string|null A json object containing success data if the avatar was deleted
809
  * error message otherwise.
810
  */
811
  function bp_avatar_ajax_delete() {
812
- // Bail if not a POST action.
813
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
814
  wp_send_json_error();
815
  }
816
 
@@ -948,18 +947,17 @@ function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) {
948
  *
949
  * @since 2.3.0
950
  *
951
- * @return string|null A json object containing success data if the upload succeeded
952
- * error message otherwise.
953
  */
954
  function bp_avatar_ajax_upload() {
955
- // Bail if not a POST action.
956
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
957
  wp_die();
958
  }
959
 
960
  /**
961
  * Sending the json response will be different if
962
- * the current Plupload runtime is html4
963
  */
964
  $is_html4 = false;
965
  if ( ! empty( $_POST['html4' ] ) ) {
@@ -1005,10 +1003,7 @@ function bp_avatar_ajax_upload() {
1005
 
1006
  if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
1007
  $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
1008
- $bp->groups->current_group = groups_get_group( array(
1009
- 'group_id' => $bp_params['item_id'],
1010
- 'populate_extras' => false,
1011
- ) );
1012
  }
1013
  } else {
1014
  /**
@@ -1097,15 +1092,15 @@ function bp_avatar_ajax_upload() {
1097
  }
1098
  add_action( 'wp_ajax_bp_avatar_upload', 'bp_avatar_ajax_upload' );
1099
 
1100
- /**
1101
- * Handle avatar webcam capture.
1102
- *
1103
- * @since 2.3.0
1104
- *
1105
- * @param string $data Base64 encoded image.
1106
- * @param int $item_id Item to associate.
1107
- * @return bool True on success, false on failure.
1108
- */
1109
  function bp_avatar_handle_capture( $data = '', $item_id = 0 ) {
1110
  if ( empty( $data ) || empty( $item_id ) ) {
1111
  return false;
@@ -1171,16 +1166,6 @@ function bp_avatar_handle_capture( $data = '', $item_id = 0 ) {
1171
  /**
1172
  * Crop an uploaded avatar.
1173
  *
1174
- * $args has the following parameters:
1175
- * object - What component the avatar is for, e.g. "user"
1176
- * avatar_dir The absolute path to the avatar
1177
- * item_id - Item ID
1178
- * original_file - The absolute path to the original avatar file
1179
- * crop_w - Crop width
1180
- * crop_h - Crop height
1181
- * crop_x - The horizontal starting point of the crop
1182
- * crop_y - The vertical starting point of the crop
1183
- *
1184
  * @since 1.1.0
1185
  *
1186
  * @param array|string $args {
@@ -1246,12 +1231,11 @@ function bp_core_avatar_handle_crop( $args = '' ) {
1246
  *
1247
  * @since 2.3.0
1248
  *
1249
- * @return string|null A json object containing success data if the crop/capture succeeded
1250
- * error message otherwise.
1251
  */
1252
  function bp_avatar_ajax_set() {
1253
- // Bail if not a POST action.
1254
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1255
  wp_send_json_error();
1256
  }
1257
 
@@ -1306,11 +1290,13 @@ function bp_avatar_ajax_set() {
1306
  * @since 2.3.4 Add two new parameters to inform about the user id and
1307
  * about the way the avatar was set (eg: 'crop' or 'camera')
1308
  * Move the action at the right place, once the avatar is set
 
1309
  *
1310
- * @param string $item_id Inform about the user id the avatar was set for
1311
- * @param string $type Inform about the way the avatar was set ('camera')
 
1312
  */
1313
- do_action( 'xprofile_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'] );
1314
 
1315
  wp_send_json_success( $return );
1316
  }
@@ -1355,18 +1341,11 @@ function bp_avatar_ajax_set() {
1355
  );
1356
 
1357
  if ( 'user' === $avatar_data['object'] ) {
1358
- /**
1359
- * Fires if the new avatar was successfully cropped.
1360
- *
1361
- * @since 1.1.0 Used to inform the avatar was successfully cropped
1362
- * @since 2.3.4 Add two new parameters to inform about the user id and
1363
- * about the way the avatar was set (eg: 'crop' or 'camera')
1364
- * Move the action at the right place, once the avatar is set
1365
- *
1366
- * @param string $item_id Inform about the user id the avatar was set for
1367
- * @param string $type Inform about the way the avatar was set ('crop')
1368
- */
1369
- do_action( 'xprofile_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'] );
1370
  }
1371
 
1372
  wp_send_json_success( $return );
@@ -1379,103 +1358,58 @@ function bp_avatar_ajax_set() {
1379
  add_action( 'wp_ajax_bp_avatar_set', 'bp_avatar_ajax_set' );
1380
 
1381
  /**
1382
- * Replace default WordPress avatars with BP avatars, if available.
1383
  *
1384
- * See 'get_avatar' filter description in wp-includes/pluggable.php.
1385
  *
1386
- * @since 1.1.0
1387
- * @since 2.4.0 Added $args parameter to coincide with WordPress 4.2.0.
1388
- *
1389
- * @param string $avatar The avatar path passed to 'get_avatar'.
1390
- * @param int|string|object $user A user ID, email address, or comment object.
1391
- * @param int $size Size of the avatar image ('thumb' or 'full').
1392
- * @param string $default URL to a default image to use if no avatar is available.
1393
- * @param string $alt Alternate text to use in image tag. Default: ''.
1394
- * @param array $args Arguments passed to get_avatar_data(), after processing.
1395
- * @return string BP avatar path, if found; else the original avatar path.
1396
  */
1397
- function bp_core_fetch_avatar_filter( $avatar, $user, $size, $default, $alt = '', $args = array() ) {
1398
- global $pagenow;
1399
-
1400
- // Do not filter if inside WordPress options page.
1401
- if ( 'options-discussion.php' == $pagenow )
1402
- return $avatar;
1403
-
1404
- // If passed an object, assume $user->user_id.
1405
- if ( is_object( $user ) ) {
1406
- if ( isset( $user->user_id ) ) {
1407
- $id = $user->user_id;
1408
- } else {
1409
- $id = $user->ID;
 
 
1410
  }
1411
-
1412
- // If passed a number, assume it was a $user_id.
1413
- } elseif ( is_numeric( $user ) ) {
1414
- $id = $user;
1415
-
1416
- // If passed a string and that string returns a user, get the $id.
1417
- } elseif ( is_string( $user ) && ( $user_by_email = get_user_by( 'email', $user ) ) ) {
1418
- $id = $user_by_email->ID;
1419
  }
1420
 
1421
- // If somehow $id hasn't been assigned, return the result of get_avatar.
1422
- if ( empty( $id ) ) {
1423
- return !empty( $avatar ) ? $avatar : $default;
1424
  }
1425
 
1426
- // Image alt tag.
1427
- if ( empty( $alt ) ) {
1428
- $alt = sprintf( __( 'Profile photo of %s', 'buddypress' ), bp_core_get_user_displayname( $id ) );
1429
- }
1430
 
1431
- // Use the 'thumb' type, unless the requested width is bigger than
1432
- // BP's thumb width.
1433
- $type = 'thumb';
1434
- if ( (int) $size > bp_core_avatar_thumb_width() ) {
1435
- $type = 'full';
1436
  }
1437
 
1438
- $avatar_args = array(
1439
- 'item_id' => $id,
1440
- 'type' => $type,
1441
- 'width' => $size,
1442
- 'height' => $size,
1443
- 'alt' => $alt,
1444
- );
1445
-
1446
- // Support new arguments as of WordPress 4.2.0.
1447
- if ( ! empty( $args['width'] ) ) {
1448
- $avatar_args['width'] = $args['width'];
1449
- }
1450
- if ( ! empty( $args['height'] ) ) {
1451
- $avatar_args['height'] = $args['height'];
1452
- }
1453
- if ( ! empty( $args['class'] ) ) {
1454
- $avatar_args['class'] = $args['class'];
1455
- }
1456
- if ( ! empty( $args['class'] ) ) {
1457
- $avatar_args['class'] = $args['class'];
1458
- }
1459
- if ( ! empty( $args['extra_attr'] ) ) {
1460
- $avatar_args['extra_attr'] = $args['extra_attr'];
1461
- }
1462
- if ( ! empty( $args['scheme'] ) ) {
1463
- $avatar_args['scheme'] = $args['scheme'];
1464
  }
1465
- if ( ! empty( $args['force_default'] ) ) {
1466
- $avatar_args['force_default'] = $args['force_default'];
1467
- }
1468
- if ( ! empty( $args['rating'] ) ) {
1469
- $avatar_args['rating'] = $args['rating'];
1470
- }
1471
-
1472
- // Let BuddyPress handle the fetching of the avatar.
1473
- $bp_avatar = bp_core_fetch_avatar( $avatar_args );
1474
 
1475
- // If BuddyPress found an avatar, use it. If not, use the result of get_avatar.
1476
- return ( !$bp_avatar ) ? $avatar : $bp_avatar;
1477
  }
1478
- add_filter( 'get_avatar', 'bp_core_fetch_avatar_filter', 10, 6 );
1479
 
1480
  /**
1481
  * Is the current avatar upload error-free?
@@ -1511,6 +1445,8 @@ function bp_core_check_avatar_size( $file ) {
1511
  * Get allowed avatar types.
1512
  *
1513
  * @since 2.3.0
 
 
1514
  */
1515
  function bp_core_get_allowed_avatar_types() {
1516
  $allowed_types = bp_attachments_get_allowed_types( 'avatar' );
@@ -1537,6 +1473,8 @@ function bp_core_get_allowed_avatar_types() {
1537
  * Get allowed avatar mime types.
1538
  *
1539
  * @since 2.3.0
 
 
1540
  */
1541
  function bp_core_get_allowed_avatar_mimes() {
1542
  $allowed_types = bp_core_get_allowed_avatar_types();
@@ -1943,7 +1881,7 @@ function bp_core_avatar_default_thumb( $type = 'gravatar', $params = array() ) {
1943
  * parameter of the WordPress main query to this posted var. To avoid
1944
  * notices, we need to make sure this 'week' query var is reset to 0.
1945
  *
1946
- * @since 2.2.0
1947
  *
1948
  * @param WP_Query|null $posts_query The main query object.
1949
  */
@@ -1977,7 +1915,7 @@ add_action( 'bp_parse_query', 'bp_core_avatar_reset_query', 10, 1 );
1977
  /**
1978
  * Checks whether Avatar UI should be loaded.
1979
  *
1980
- * @since 2.3.0
1981
  *
1982
  * @return bool True if Avatar UI should load, false otherwise.
1983
  */
@@ -2009,7 +1947,7 @@ function bp_avatar_is_front_edit() {
2009
  * - Load the avatar UI for a component that is !groups or !user (return true regarding your conditions)
2010
  * - Completely disable the avatar UI introduced in 2.3 (eg: __return_false())
2011
  *
2012
- * @since 2.3.0
2013
  *
2014
  * @param bool $retval Whether or not to load the Avatar UI.
2015
  */
@@ -2019,7 +1957,7 @@ function bp_avatar_is_front_edit() {
2019
  /**
2020
  * Checks whether the Webcam Avatar UI part should be loaded.
2021
  *
2022
- * @since 2.3.0
2023
  *
2024
  * @global $is_safari
2025
  * @global $is_IE
@@ -2040,7 +1978,7 @@ function bp_avatar_use_webcam() {
2040
  /**
2041
  * Bail when the browser does not support getUserMedia.
2042
  *
2043
- * @see http://caniuse.com/#feat=stream
2044
  */
2045
  if ( $is_safari || $is_IE || ( $is_chrome && ! is_ssl() ) ) {
2046
  return false;
@@ -2060,7 +1998,7 @@ function bp_avatar_use_webcam() {
2060
  /**
2061
  * Template function to load the Avatar UI javascript templates.
2062
  *
2063
- * @since 2.3.0
2064
  */
2065
  function bp_avatar_get_templates() {
2066
  if ( ! bp_avatar_is_front_edit() ) {
@@ -2076,7 +2014,7 @@ function bp_avatar_get_templates() {
2076
  * If the "avatar templates" are not including the new template tag, this will
2077
  * help users to get the avatar UI.
2078
  *
2079
- * @since 2.3.0
2080
  */
2081
  function bp_avatar_template_check() {
2082
  if ( ! bp_avatar_is_front_edit() ) {
313
  break;
314
 
315
  case 'group' :
316
+ $item_name = bp_get_group_name( groups_get_group( $params['item_id'] ) );
317
  break;
318
 
319
  case 'user' :
542
  * @param string $value Subdirectory where the requested avatar should be found.
543
  * @param string $html_css_id ID attribute for avatar.
544
  * @param string $html_width Width attribute for avatar.
545
+ * @param string $html_height Height attribute for avatar.
546
  * @param string $avatar_folder_url Avatar URL path.
547
+ * @param string $avatar_folder_dir Avatar DIR path.
548
  */
549
  return apply_filters( 'bp_core_fetch_avatar', '<img src="' . $avatar_url . '"' . $html_class . $html_css_id . $html_width . $html_height . $html_alt . $html_title . $extra_attr . ' />', $params, $params['item_id'], $params['avatar_dir'], $html_css_id, $html_width, $html_height, $avatar_folder_url, $avatar_folder_dir );
550
 
648
  * @since 2.6.0
649
  *
650
  * @param string $default_grav The avatar default.
651
+ * @param array $params The avatar's data.
652
  */
653
  $default_grav = apply_filters( 'bp_core_avatar_default', $default_grav, $params );
654
 
726
  *
727
  * @since 2.5.1
728
  *
729
+ * @param bool $value Whether or not to delete the avatar.
730
  * @param array $args {
731
  * Array of function parameters.
732
  *
805
  *
806
  * @since 2.3.0
807
  *
808
+ * @return string|null A JSON object containing success data if the avatar was deleted,
809
  * error message otherwise.
810
  */
811
  function bp_avatar_ajax_delete() {
812
+ if ( ! bp_is_post_request() ) {
 
813
  wp_send_json_error();
814
  }
815
 
947
  *
948
  * @since 2.3.0
949
  *
950
+ * @return string|null A JSON object containing success data if the upload succeeded
951
+ * error message otherwise.
952
  */
953
  function bp_avatar_ajax_upload() {
954
+ if ( ! bp_is_post_request() ) {
 
955
  wp_die();
956
  }
957
 
958
  /**
959
  * Sending the json response will be different if
960
+ * the current Plupload runtime is html4.
961
  */
962
  $is_html4 = false;
963
  if ( ! empty( $_POST['html4' ] ) ) {
1003
 
1004
  if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) {
1005
  $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group );
1006
+ $bp->groups->current_group = groups_get_group( $bp_params['item_id'] );
 
 
 
1007
  }
1008
  } else {
1009
  /**
1092
  }
1093
  add_action( 'wp_ajax_bp_avatar_upload', 'bp_avatar_ajax_upload' );
1094
 
1095
+ /**
1096
+ * Handle avatar webcam capture.
1097
+ *
1098
+ * @since 2.3.0
1099
+ *
1100
+ * @param string $data Base64 encoded image.
1101
+ * @param int $item_id Item to associate.
1102
+ * @return bool True on success, false on failure.
1103
+ */
1104
  function bp_avatar_handle_capture( $data = '', $item_id = 0 ) {
1105
  if ( empty( $data ) || empty( $item_id ) ) {
1106
  return false;
1166
  /**
1167
  * Crop an uploaded avatar.
1168
  *
 
 
 
 
 
 
 
 
 
 
1169
  * @since 1.1.0
1170
  *
1171
  * @param array|string $args {
1231
  *
1232
  * @since 2.3.0
1233
  *
1234
+ * @return string|null A JSON object containing success data if the crop/capture succeeded
1235
+ * error message otherwise.
1236
  */
1237
  function bp_avatar_ajax_set() {
1238
+ if ( ! bp_is_post_request() ) {
 
1239
  wp_send_json_error();
1240
  }
1241
 
1290
  * @since 2.3.4 Add two new parameters to inform about the user id and
1291
  * about the way the avatar was set (eg: 'crop' or 'camera')
1292
  * Move the action at the right place, once the avatar is set
1293
+ * @since 2.8.0 Added the `$avatar_data` parameter.
1294
  *
1295
+ * @param string $item_id Inform about the user id the avatar was set for.
1296
+ * @param string $type Inform about the way the avatar was set ('camera').
1297
+ * @param array $avatar_data Array of parameters passed to the avatar handler.
1298
  */
1299
+ do_action( 'xprofile_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $avatar_data );
1300
 
1301
  wp_send_json_success( $return );
1302
  }
1341
  );
1342
 
1343
  if ( 'user' === $avatar_data['object'] ) {
1344
+ /** This action is documented in bp-core/bp-core-avatars.php */
1345
+ do_action( 'xprofile_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r );
1346
+ } elseif ( 'group' === $avatar_data['object'] ) {
1347
+ /** This action is documented in bp-groups/bp-groups-screens.php */
1348
+ do_action( 'groups_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r );
 
 
 
 
 
 
 
1349
  }
1350
 
1351
  wp_send_json_success( $return );
1358
  add_action( 'wp_ajax_bp_avatar_set', 'bp_avatar_ajax_set' );
1359
 
1360
  /**
1361
+ * Filter {@link get_avatar_url()} to use the BuddyPress user avatar URL.
1362
  *
1363
+ * @since 2.9.0
1364
  *
1365
+ * @param string $retval The URL of the avatar.
1366
+ * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
1367
+ * user email, WP_User object, WP_Post object, or WP_Comment object.
1368
+ * @param array $args Arguments passed to get_avatar_data(), after processing.
1369
+ * @return string
 
 
 
 
 
1370
  */
1371
+ function bp_core_get_avatar_data_url_filter( $retval, $id_or_email, $args ) {
1372
+ $user = null;
1373
+
1374
+ // Ugh, hate duplicating code; process the user identifier.
1375
+ if ( is_numeric( $id_or_email ) ) {
1376
+ $user = get_user_by( 'id', absint( $id_or_email ) );
1377
+ } elseif ( $id_or_email instanceof WP_User ) {
1378
+ // User Object
1379
+ $user = $id_or_email;
1380
+ } elseif ( $id_or_email instanceof WP_Post ) {
1381
+ // Post Object
1382
+ $user = get_user_by( 'id', (int) $id_or_email->post_author );
1383
+ } elseif ( $id_or_email instanceof WP_Comment ) {
1384
+ if ( ! empty( $id_or_email->user_id ) ) {
1385
+ $user = get_user_by( 'id', (int) $id_or_email->user_id );
1386
  }
1387
+ } elseif ( is_email( $id_or_email ) ) {
1388
+ $user = get_user_by( 'email', $id_or_email );
 
 
 
 
 
 
1389
  }
1390
 
1391
+ // No user, so bail.
1392
+ if ( false === $user instanceof WP_User ) {
1393
+ return $retval;
1394
  }
1395
 
1396
+ // Set BuddyPress-specific avatar args.
1397
+ $args['item_id'] = $user->ID;
1398
+ $args['html'] = false;
 
1399
 
1400
+ // Use the 'full' type if size is larger than BP's thumb width.
1401
+ if ( (int) $args['size'] > bp_core_avatar_thumb_width() ) {
1402
+ $args['type'] = 'full';
 
 
1403
  }
1404
 
1405
+ // Get the BuddyPress avatar URL.
1406
+ if ( $bp_avatar = bp_core_fetch_avatar( $args ) ) {
1407
+ return $bp_avatar;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1408
  }
 
 
 
 
 
 
 
 
 
1409
 
1410
+ return $retval;
 
1411
  }
1412
+ add_filter( 'get_avatar_url', 'bp_core_get_avatar_data_url_filter', 10, 3 );
1413
 
1414
  /**
1415
  * Is the current avatar upload error-free?
1445
  * Get allowed avatar types.
1446
  *
1447
  * @since 2.3.0
1448
+ *
1449
+ * @return array
1450
  */
1451
  function bp_core_get_allowed_avatar_types() {
1452
  $allowed_types = bp_attachments_get_allowed_types( 'avatar' );
1473
  * Get allowed avatar mime types.
1474
  *
1475
  * @since 2.3.0
1476
+ *
1477
+ * @return array
1478
  */
1479
  function bp_core_get_allowed_avatar_mimes() {
1480
  $allowed_types = bp_core_get_allowed_avatar_types();
1881
  * parameter of the WordPress main query to this posted var. To avoid
1882
  * notices, we need to make sure this 'week' query var is reset to 0.
1883
  *
1884
+ * @since 2.2.0
1885
  *
1886
  * @param WP_Query|null $posts_query The main query object.
1887
  */
1915
  /**
1916
  * Checks whether Avatar UI should be loaded.
1917
  *
1918
+ * @since 2.3.0
1919
  *
1920
  * @return bool True if Avatar UI should load, false otherwise.
1921
  */
1947
  * - Load the avatar UI for a component that is !groups or !user (return true regarding your conditions)
1948
  * - Completely disable the avatar UI introduced in 2.3 (eg: __return_false())
1949
  *
1950
+ * @since 2.3.0
1951
  *
1952
  * @param bool $retval Whether or not to load the Avatar UI.
1953
  */
1957
  /**
1958
  * Checks whether the Webcam Avatar UI part should be loaded.
1959
  *
1960
+ * @since 2.3.0
1961
  *
1962
  * @global $is_safari
1963
  * @global $is_IE
1978
  /**
1979
  * Bail when the browser does not support getUserMedia.
1980
  *
1981
+ * @see http://caniuse.com/#feat=stream
1982
  */
1983
  if ( $is_safari || $is_IE || ( $is_chrome && ! is_ssl() ) ) {
1984
  return false;
1998
  /**
1999
  * Template function to load the Avatar UI javascript templates.
2000
  *
2001
+ * @since 2.3.0
2002
  */
2003
  function bp_avatar_get_templates() {
2004
  if ( ! bp_avatar_is_front_edit() ) {
2014
  * If the "avatar templates" are not including the new template tag, this will
2015
  * help users to get the avatar UI.
2016
  *
2017
+ * @since 2.3.0
2018
  */
2019
  function bp_avatar_template_check() {
2020
  if ( ! bp_avatar_is_front_edit() ) {
bp-core/bp-core-buddybar.php CHANGED
@@ -33,8 +33,8 @@ defined( 'ABSPATH' ) || exit;
33
  * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav
34
  * item is clicked.
35
  * }
36
- * @param string $component The component the navigation is attached to. Defaults to 'members'.
37
- * @return bool|null Returns false on failure.
38
  */
39
  function bp_core_new_nav_item( $args, $component = 'members' ) {
40
  if ( ! bp_is_active( $component ) ) {
@@ -90,7 +90,7 @@ function bp_core_new_nav_item( $args, $component = 'members' ) {
90
  * Add a link to the main BuddyPress navigation.
91
  *
92
  * @since 2.4.0
93
- * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Nav_Item object on success.
94
  *
95
  * @param array|string $args {
96
  * Array describing the new nav item.
@@ -107,8 +107,8 @@ function bp_core_new_nav_item( $args, $component = 'members' ) {
107
  * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav
108
  * item is clicked.
109
  * }
110
- * @param string $component Optional. Component that the nav belongs to.
111
- * @return bool|BP_Nav_Item Returns false on failure, new nav item on success.
112
  */
113
  function bp_core_create_nav_link( $args = '', $component = 'members' ) {
114
  $bp = buddypress();
@@ -152,7 +152,7 @@ function bp_core_create_nav_link( $args = '', $component = 'members' ) {
152
  );
153
 
154
  // Add the item to the nav.
155
- $retval = buddypress()->{$component}->nav->add_nav( $nav_item );
156
 
157
  /**
158
  * Fires after a link is added to the main BuddyPress nav.
@@ -167,7 +167,7 @@ function bp_core_create_nav_link( $args = '', $component = 'members' ) {
167
  */
168
  do_action( 'bp_core_create_nav_link', $r, $args, $defaults, $component );
169
 
170
- return $retval;
171
  }
172
 
173
  /**
@@ -190,7 +190,7 @@ function bp_core_create_nav_link( $args = '', $component = 'members' ) {
190
  * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav
191
  * item is clicked.
192
  * }
193
- * @return bool|null Returns false on failure.
194
  */
195
  function bp_core_register_nav_screen_function( $args = '' ) {
196
  $bp = buddypress();
@@ -214,9 +214,9 @@ function bp_core_register_nav_screen_function( $args = '' ) {
214
  }
215
 
216
  /**
217
- * If this is for site admins only and the user is not one,
218
- * don't register this screen function.
219
- */
220
  if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
221
  return false;
222
  }
@@ -321,7 +321,7 @@ function bp_core_new_nav_default( $args = '' ) {
321
  }
322
  }
323
 
324
- // Edit the screen function for the parent nav
325
  $bp->members->nav->edit_nav( array(
326
  'screen_function' => &$r['screen_function'],
327
  'default_subnav_slug' => $r['subnav_slug'],
@@ -394,8 +394,8 @@ function bp_core_new_nav_default( $args = '' ) {
394
  * @type bool $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
395
  * Admin Bar menu for group admins. Default: false.
396
  * }
397
- * @param string $component The component the navigation is attached to. Defaults to 'members'.
398
- * @return bool|null Returns false on failure.
399
  */
400
  function bp_core_new_subnav_item( $args, $component = null ) {
401
  // Backward compatibility for plugins using `bp_core_new_subnav_item()` without `$component`
@@ -405,7 +405,7 @@ function bp_core_new_subnav_item( $args, $component = null ) {
405
  * Assume that this item is intended to belong to the current group if:
406
  * a) the 'parent_slug' is the same as the slug of the current group, or
407
  * b) the 'parent_slug' starts with the slug of the current group, and the members nav doesn't have
408
- * a primary item with that slug
409
  */
410
  $group_slug = bp_get_current_group_slug();
411
  if (
@@ -446,7 +446,7 @@ function bp_core_new_subnav_item( $args, $component = null ) {
446
  * Add a subnav link to the BuddyPress navigation.
447
  *
448
  * @since 2.4.0
449
- * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Nav_Item object on success.
450
  *
451
  * @param array|string $args {
452
  * Array describing the new subnav item.
@@ -474,8 +474,8 @@ function bp_core_new_subnav_item( $args, $component = null ) {
474
  * the group's "Edit" Admin Bar menu for group admins.
475
  * Default: false.
476
  * }
477
- * @param string $component The component the navigation is attached to. Defaults to 'members'.
478
- * @return bool|BP_Nav_Item Returns false on failure, new nav item on success.
479
  */
480
  function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
481
  $bp = buddypress();
@@ -536,7 +536,9 @@ function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
536
  'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
537
  );
538
 
539
- return buddypress()->{$component}->nav->add_nav( $subnav_item );
 
 
540
  }
541
 
542
  /**
@@ -568,8 +570,8 @@ function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
568
  * the group's "Edit" Admin Bar menu for group admins.
569
  * Default: false.
570
  * }
571
- * @param string $component The component the navigation is attached to. Defaults to 'members'.
572
- * @return bool|null Returns false on failure.
573
  */
574
  function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) {
575
  $bp = buddypress();
@@ -606,6 +608,11 @@ function bp_core_register_subnav_screen_function( $args = '', $component = 'memb
606
  }
607
 
608
  $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
 
 
 
 
 
609
 
610
  // If we *do* meet condition (2), then the added subnav item is currently being requested.
611
  if ( ( bp_current_action() && bp_is_current_action( $r['slug'] ) ) || ( bp_is_user() && ! bp_current_action() && ! empty( $parent_nav->screen_function ) && $r['screen_function'] == $parent_nav->screen_function ) ) {
@@ -668,10 +675,9 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component
668
 
669
  $bp = buddypress();
670
 
671
- // If a redirect URL has been passed to the subnav
672
- // item, respect it.
673
  if ( ! empty( $subnav_item['no_access_url'] ) ) {
674
- $message = __( 'You do not have access to this page.', 'buddypress' );
675
  $redirect_to = trailingslashit( $subnav_item['no_access_url'] );
676
 
677
  // In the case of a user page, we try to assume a
@@ -687,7 +693,7 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component
687
  // component, as long as that component is
688
  // publicly accessible.
689
  if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
690
- $message = __( 'You do not have access to this page.', 'buddypress' );
691
  $redirect_to = bp_displayed_user_domain();
692
 
693
  // In some cases, the default tab is not accessible to
@@ -715,6 +721,7 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component
715
  'message' => $message,
716
  'root' => $redirect_to,
717
  'redirect' => false,
 
718
  );
719
 
720
  } else {
@@ -773,8 +780,8 @@ function bp_nav_item_has_subnav( $nav_item = '', $component = 'members' ) {
773
  * @since 1.0.0
774
  * @since 2.6.0 Introduced the `$component` parameter.
775
  *
776
- * @param string $slug The slug of the primary navigation item.
777
- * @param string $component The component the navigation is attached to. Defaults to 'members'.
778
  * @return bool Returns false on failure, True on success.
779
  */
780
  function bp_core_remove_nav_item( $slug, $component = null ) {
@@ -783,7 +790,7 @@ function bp_core_remove_nav_item( $slug, $component = null ) {
783
  // Backward compatibility for removing group nav items using the group slug as `$parent_slug`.
784
  if ( ! $component && bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
785
  if ( $bp->groups->nav->get_primary( array( 'slug' => $slug ) ) ) {
786
- return bp_core_remove_nav_item( $slug, 'groups' );
787
  }
788
  }
789
 
@@ -798,10 +805,8 @@ function bp_core_remove_nav_item( $slug, $component = null ) {
798
  $screen_functions = $bp->{$component}->nav->delete_nav( $slug );
799
 
800
  // Reset backcompat nav items so that subsequent references will be correct.
801
- if ( buddypress()->do_nav_backcompat ) {
802
- $bp->bp_nav->reset();
803
- $bp->bp_options_nav->reset();
804
- }
805
 
806
  if ( ! is_array( $screen_functions ) ) {
807
  return false;
@@ -823,9 +828,9 @@ function bp_core_remove_nav_item( $slug, $component = null ) {
823
  * @since 1.0.0
824
  * @since 2.6.0 Introduced the `$component` parameter.
825
  *
826
- * @param string $parent_slug The slug of the primary navigation item.
827
- * @param string $slug The slug of the secondary item to be removed.
828
- * @param string $component The component the navigation is attached to. Defaults to 'members'.
829
  * @return bool Returns false on failure, True on success.
830
  */
831
  function bp_core_remove_subnav_item( $parent_slug, $slug, $component = null ) {
@@ -834,7 +839,7 @@ function bp_core_remove_subnav_item( $parent_slug, $slug, $component = null ) {
834
  // Backward compatibility for removing group nav items using the group slug as `$parent_slug`.
835
  if ( ! $component && bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
836
  if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_slug ) ) ) {
837
- return bp_core_remove_subnav_item( $slug, $parent_slug, 'groups' );
838
  }
839
  }
840
 
@@ -849,10 +854,8 @@ function bp_core_remove_subnav_item( $parent_slug, $slug, $component = null ) {
849
  $screen_functions = $bp->{$component}->nav->delete_nav( $slug, $parent_slug );
850
 
851
  // Reset backcompat nav items so that subsequent references will be correct.
852
- if ( buddypress()->do_nav_backcompat ) {
853
- $bp->bp_nav->reset();
854
- $bp->bp_options_nav->reset();
855
- }
856
 
857
  if ( ! is_array( $screen_functions ) ) {
858
  return false;
33
  * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav
34
  * item is clicked.
35
  * }
36
+ * @param string $component The component the navigation is attached to. Defaults to 'members'.
37
+ * @return null|false Returns false on failure.
38
  */
39
  function bp_core_new_nav_item( $args, $component = 'members' ) {
40
  if ( ! bp_is_active( $component ) ) {
90
  * Add a link to the main BuddyPress navigation.
91
  *
92
  * @since 2.4.0
93
+ * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Core_Nav_Item object on success.
94
  *
95
  * @param array|string $args {
96
  * Array describing the new nav item.
107
  * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav
108
  * item is clicked.
109
  * }
110
+ * @param string $component Optional. Component that the nav belongs to.
111
+ * @return false|array Returns false on failure, new nav item on success.
112
  */
113
  function bp_core_create_nav_link( $args = '', $component = 'members' ) {
114
  $bp = buddypress();
152
  );
153
 
154
  // Add the item to the nav.
155
+ buddypress()->{$component}->nav->add_nav( $nav_item );
156
 
157
  /**
158
  * Fires after a link is added to the main BuddyPress nav.
167
  */
168
  do_action( 'bp_core_create_nav_link', $r, $args, $defaults, $component );
169
 
170
+ return $nav_item;
171
  }
172
 
173
  /**
190
  * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav
191
  * item is clicked.
192
  * }
193
+ * @return false|null Returns false on failure.
194
  */
195
  function bp_core_register_nav_screen_function( $args = '' ) {
196
  $bp = buddypress();
214
  }
215
 
216
  /**
217
+ * If this is for site admins only and the user is not one,
218
+ * don't register this screen function.
219
+ */
220
  if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
221
  return false;
222
  }
321
  }
322
  }
323
 
324
+ // Edit the screen function for the parent nav.
325
  $bp->members->nav->edit_nav( array(
326
  'screen_function' => &$r['screen_function'],
327
  'default_subnav_slug' => $r['subnav_slug'],
394
  * @type bool $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
395
  * Admin Bar menu for group admins. Default: false.
396
  * }
397
+ * @param string|null $component The component the navigation is attached to. Defaults to 'members'.
398
+ * @return null|false Returns false on failure.
399
  */
400
  function bp_core_new_subnav_item( $args, $component = null ) {
401
  // Backward compatibility for plugins using `bp_core_new_subnav_item()` without `$component`
405
  * Assume that this item is intended to belong to the current group if:
406
  * a) the 'parent_slug' is the same as the slug of the current group, or
407
  * b) the 'parent_slug' starts with the slug of the current group, and the members nav doesn't have
408
+ * a primary item with that slug.
409
  */
410
  $group_slug = bp_get_current_group_slug();
411
  if (
446
  * Add a subnav link to the BuddyPress navigation.
447
  *
448
  * @since 2.4.0
449
+ * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Core_Nav_Item object on success.
450
  *
451
  * @param array|string $args {
452
  * Array describing the new subnav item.
474
  * the group's "Edit" Admin Bar menu for group admins.
475
  * Default: false.
476
  * }
477
+ * @param string $component The component the navigation is attached to. Defaults to 'members'.
478
+ * @return false|array Returns false on failure, new BP_Core_Nav_Item instance on success.
479
  */
480
  function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
481
  $bp = buddypress();
536
  'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
537
  );
538
 
539
+ buddypress()->{$component}->nav->add_nav( $subnav_item );
540
+
541
+ return $subnav_item;
542
  }
543
 
544
  /**
570
  * the group's "Edit" Admin Bar menu for group admins.
571
  * Default: false.
572
  * }
573
+ * @param string $component The component the navigation is attached to. Defaults to 'members'.
574
+ * @return null|false Returns false on failure.
575
  */
576
  function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) {
577
  $bp = buddypress();
608
  }
609
 
610
  $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
611
+ if ( ! $parent_nav ) {
612
+ return ;
613
+ }
614
+
615
+ $parent_nav = reset( $parent_nav );
616
 
617
  // If we *do* meet condition (2), then the added subnav item is currently being requested.
618
  if ( ( bp_current_action() && bp_is_current_action( $r['slug'] ) ) || ( bp_is_user() && ! bp_current_action() && ! empty( $parent_nav->screen_function ) && $r['screen_function'] == $parent_nav->screen_function ) ) {
675
 
676
  $bp = buddypress();
677
 
678
+ // If a redirect URL has been passed to the subnav item, respect it.
 
679
  if ( ! empty( $subnav_item['no_access_url'] ) ) {
680
+ $message = __( 'You do not have access to that page.', 'buddypress' );
681
  $redirect_to = trailingslashit( $subnav_item['no_access_url'] );
682
 
683
  // In the case of a user page, we try to assume a
693
  // component, as long as that component is
694
  // publicly accessible.
695
  if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
696
+ $message = __( 'You do not have access to that page.', 'buddypress' );
697
  $redirect_to = bp_displayed_user_domain();
698
 
699
  // In some cases, the default tab is not accessible to
721
  'message' => $message,
722
  'root' => $redirect_to,
723
  'redirect' => false,
724
+ 'mode' => 1
725
  );
726
 
727
  } else {
780
  * @since 1.0.0
781
  * @since 2.6.0 Introduced the `$component` parameter.
782
  *
783
+ * @param string $slug The slug of the primary navigation item.
784
+ * @param string|null $component The component the navigation is attached to. Defaults to 'members'.
785
  * @return bool Returns false on failure, True on success.
786
  */
787
  function bp_core_remove_nav_item( $slug, $component = null ) {
790
  // Backward compatibility for removing group nav items using the group slug as `$parent_slug`.
791
  if ( ! $component && bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
792
  if ( $bp->groups->nav->get_primary( array( 'slug' => $slug ) ) ) {
793
+ $component = 'groups';
794
  }
795
  }
796
 
805
  $screen_functions = $bp->{$component}->nav->delete_nav( $slug );
806
 
807
  // Reset backcompat nav items so that subsequent references will be correct.
808
+ $bp->bp_nav->reset();
809
+ $bp->bp_options_nav->reset();
 
 
810
 
811
  if ( ! is_array( $screen_functions ) ) {
812
  return false;
828
  * @since 1.0.0
829
  * @since 2.6.0 Introduced the `$component` parameter.
830
  *
831
+ * @param string $parent_slug The slug of the primary navigation item.
832
+ * @param string $slug The slug of the secondary item to be removed.
833
+ * @param string|null $component The component the navigation is attached to. Defaults to 'members'.
834
  * @return bool Returns false on failure, True on success.
835
  */
836
  function bp_core_remove_subnav_item( $parent_slug, $slug, $component = null ) {
839
  // Backward compatibility for removing group nav items using the group slug as `$parent_slug`.
840
  if ( ! $component && bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
841
  if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_slug ) ) ) {
842
+ $component = 'groups';
843
  }
844
  }
845
 
854
  $screen_functions = $bp->{$component}->nav->delete_nav( $slug, $parent_slug );
855
 
856
  // Reset backcompat nav items so that subsequent references will be correct.
857
+ $bp->bp_nav->reset();
858
+ $bp->bp_options_nav->reset();
 
 
859
 
860
  if ( ! is_array( $screen_functions ) ) {
861
  return false;
bp-core/bp-core-cache.php CHANGED
@@ -73,19 +73,22 @@ add_action( 'deleted_user', 'bp_core_clear_member_count_caches
73
  *
74
  * @param int $post_id ID of the page that was saved.
75
  */
76
- function bp_core_clear_directory_pages_cache_page_edit( $post_id ) {
77
- if ( ! bp_is_root_blog() ) {
78
- return;
79
- }
80
 
81
  // Bail if BP is not defined here.
82
  if ( ! buddypress() ) {
83
  return;
84
  }
85
 
 
 
 
 
 
86
  $page_ids = bp_core_get_directory_page_ids( 'all' );
87
 
88
- if ( ! in_array( $post_id, (array) $page_ids ) ) {
 
89
  return;
90
  }
91
 
@@ -115,7 +118,17 @@ add_action( 'update_option', 'bp_core_clear_directory_pages_cache_settings_edit'
115
  * @param string $option Option name.
116
  */
117
  function bp_core_clear_root_options_cache( $option ) {
 
 
 
 
 
118
  $keys = array_keys( bp_get_default_options() );
 
 
 
 
 
119
  $keys = array_merge( $keys, array(
120
  'registration',
121
  'avatar_default',
@@ -181,7 +194,7 @@ function bp_get_non_cached_ids( $item_ids, $cache_group ) {
181
  * @type string $cache_key_prefix Optional. The prefix to use when creating
182
  * cache key names. Default: the value of $meta_table.
183
  * }
184
- * @return array|bool Metadata cache for the specified objects, or false on failure.
185
  */
186
  function bp_update_meta_cache( $args = array() ) {
187
  global $wpdb;
@@ -252,3 +265,117 @@ function bp_update_meta_cache( $args = array() ) {
252
 
253
  return $cache;
254
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  *
74
  * @param int $post_id ID of the page that was saved.
75
  */
76
+ function bp_core_clear_directory_pages_cache_page_edit( $post_id = 0 ) {
 
 
 
77
 
78
  // Bail if BP is not defined here.
79
  if ( ! buddypress() ) {
80
  return;
81
  }
82
 
83
+ // Bail if not on the root blog
84
+ if ( ! bp_is_root_blog() ) {
85
+ return;
86
+ }
87
+
88
  $page_ids = bp_core_get_directory_page_ids( 'all' );
89
 
90
+ // Bail if post ID is not a directory page
91
+ if ( ! in_array( $post_id, $page_ids ) ) {
92
  return;
93
  }
94
 
118
  * @param string $option Option name.
119
  */
120
  function bp_core_clear_root_options_cache( $option ) {
121
+ foreach ( array( 'add_option', 'add_site_option', 'update_option', 'update_site_option' ) as $action ) {
122
+ remove_action( $action, 'bp_core_clear_root_options_cache' );
123
+ }
124
+
125
+ // Surrounding code prevents infinite loops on WP < 4.4.
126
  $keys = array_keys( bp_get_default_options() );
127
+
128
+ foreach ( array( 'add_option', 'add_site_option', 'update_option', 'update_site_option' ) as $action ) {
129
+ add_action( $action, 'bp_core_clear_root_options_cache' );
130
+ }
131
+
132
  $keys = array_merge( $keys, array(
133
  'registration',
134
  'avatar_default',
194
  * @type string $cache_key_prefix Optional. The prefix to use when creating
195
  * cache key names. Default: the value of $meta_table.
196
  * }
197
+ * @return false|array Metadata cache for the specified objects, or false on failure.
198
  */
199
  function bp_update_meta_cache( $args = array() ) {
200
  global $wpdb;
265
 
266
  return $cache;
267
  }
268
+
269
+ /**
270
+ * Gets a value that has been cached using an incremented key.
271
+ *
272
+ * A utility function for use by query methods like BP_Activity_Activity::get().
273
+ *
274
+ * @since 2.7.0
275
+ * @see bp_core_set_incremented_cache()
276
+ *
277
+ * @param string $key Unique key for the query. Usually a SQL string.
278
+ * @param string $group Cache group. Eg 'bp_activity'.
279
+ * @return array|bool False if no cached values are found, otherwise an array of IDs.
280
+ */
281
+ function bp_core_get_incremented_cache( $key, $group ) {
282
+ $cache_key = bp_core_get_incremented_cache_key( $key, $group );
283
+ return wp_cache_get( $cache_key, $group );
284
+ }
285
+
286
+ /**
287
+ * Caches a value using an incremented key.
288
+ *
289
+ * An "incremented key" is a cache key that is hashed with a unique incrementor,
290
+ * allowing for bulk invalidation.
291
+ *
292
+ * Use this method when caching data that should be invalidated whenever any
293
+ * object of a given type is created, updated, or deleted. This usually means
294
+ * data related to object queries, which can only reliably cached until the
295
+ * underlying set of objects has been modified. See, eg, BP_Activity_Activity::get().
296
+ *
297
+ * @since 2.7.0
298
+ *
299
+ * @param string $key Unique key for the query. Usually a SQL string.
300
+ * @param string $group Cache group. Eg 'bp_activity'.
301
+ * @param array $ids Array of IDs.
302
+ * @return bool
303
+ */
304
+ function bp_core_set_incremented_cache( $key, $group, $ids ) {
305
+ $cache_key = bp_core_get_incremented_cache_key( $key, $group );
306
+ return wp_cache_set( $cache_key, $ids, $group );
307
+ }
308
+
309
+ /**
310
+ * Delete a value that has been cached using an incremented key.
311
+ *
312
+ * A utility function for use by query methods like BP_Activity_Activity::get().
313
+ *
314
+ * @since 3.0.0
315
+ * @see bp_core_set_incremented_cache()
316
+ *
317
+ * @param string $key Unique key for the query. Usually a SQL string.
318
+ * @param string $group Cache group. Eg 'bp_activity'.
319
+ * @return bool True on successful removal, false on failure.
320
+ */
321
+ function bp_core_delete_incremented_cache( $key, $group ) {
322
+ $cache_key = bp_core_get_incremented_cache_key( $key, $group );
323
+ return wp_cache_delete( $cache_key, $group );
324
+ }
325
+
326
+ /**
327
+ * Gets the key to be used when caching a value using an incremented cache key.
328
+ *
329
+ * The $key is hashed with a component-specific incrementor, which is used to
330
+ * invalidate multiple caches at once.
331
+
332
+ * @since 2.7.0
333
+ *
334
+ * @param string $key Unique key for the query. Usually a SQL string.
335
+ * @param string $group Cache group. Eg 'bp_activity'.
336
+ * @return string
337
+ */
338
+ function bp_core_get_incremented_cache_key( $key, $group ) {
339
+ $incrementor = bp_core_get_incrementor( $group );
340
+ $cache_key = md5( $key . $incrementor );
341
+ return $cache_key;
342
+ }
343
+
344
+ /**
345
+ * Gets a group-specific cache incrementor.
346
+ *
347
+ * The incrementor is paired with query identifiers (like SQL strings) to
348
+ * create cache keys that can be invalidated en masse.
349
+ *
350
+ * If an incrementor does not yet exist for the given `$group`, one will
351
+ * be created.
352
+ *
353
+ * @since 2.7.0
354
+ *
355
+ * @param string $group Cache group. Eg 'bp_activity'.
356
+ * @return string
357
+ */
358
+ function bp_core_get_incrementor( $group ) {
359
+ $incrementor = wp_cache_get( 'incrementor', $group );
360
+ if ( ! $incrementor ) {
361
+ $incrementor = microtime();
362
+ wp_cache_set( 'incrementor', $incrementor, $group );
363
+ }
364
+
365
+ return $incrementor;
366
+ }
367
+
368
+ /**
369
+ * Reset a group-specific cache incrementor.
370
+ *
371
+ * Call this function when all incrementor-based caches associated with a given
372
+ * cache group should be invalidated.
373
+ *
374
+ * @since 2.7.0
375
+ *
376
+ * @param string $group Cache group. Eg 'bp_activity'.
377
+ * @return bool True on success, false on failure.
378
+ */
379
+ function bp_core_reset_incrementor( $group ) {
380
+ return wp_cache_delete( 'incrementor', $group );
381
+ }
bp-core/bp-core-caps.php CHANGED
@@ -20,7 +20,7 @@ defined( 'ABSPATH' ) || exit;
20
  *
21
  * @since 2.1.0
22
  *
23
- * @return array
24
  */
25
  function bp_get_current_blog_roles() {
26
  global $wp_roles;
@@ -56,7 +56,6 @@ function bp_get_current_blog_roles() {
56
  * This is called on plugin activation.
57
  *
58
  * @since 1.6.0
59
- *
60
  */
61
  function bp_add_caps() {
62
  global $wp_roles;
@@ -89,7 +88,6 @@ function bp_add_caps() {
89
  * This is called on plugin deactivation.
90
  *
91
  * @since 1.6.0
92
- *
93
  */
94
  function bp_remove_caps() {
95
  global $wp_roles;
@@ -218,9 +216,6 @@ function bp_get_caps_for_role( $role = '' ) {
218
  * already have a role or capability on.
219
  *
220
  * @since 1.6.0
221
- *
222
- * @global BuddyPress $bp Global BuddyPress settings object.
223
- *
224
  */
225
  function bp_set_current_user_default_role() {
226
 
@@ -248,55 +243,105 @@ function bp_set_current_user_default_role() {
248
  *
249
  * @since 1.6.0
250
  * @since 2.4.0 Second argument modified to accept an array, rather than `$blog_id`.
 
251
  *
252
  * @param string $capability Capability or role name.
253
  * @param array|int $args {
254
  * Array of extra arguments applicable to the capability check.
255
- * @type int $blog_id Optional. Blog ID. Defaults to the BP root blog.
 
256
  * @type mixed $a,... Optional. Extra arguments applicable to the capability check.
257
  * }
258
  * @return bool True if the user has the cap for the given parameters.
259
  */
260
  function bp_current_user_can( $capability, $args = array() ) {
261
- $blog_id = 0;
262
-
263
  // Backward compatibility for older $blog_id parameter.
264
  if ( is_int( $args ) ) {
265
- $blog_id = $args;
266
  $args = array();
 
267
 
268
  // New format for second parameter.
269
  } elseif ( is_array( $args ) && isset( $args['blog_id'] ) ) {
270
  // Get the blog ID if set, but don't pass along to `current_user_can_for_blog()`.
271
- $blog_id = (int) $args['blog_id'];
272
  unset( $args['blog_id'] );
273
  }
274
 
275
- // Backward compatibility for older bp_current_user_can() checks
276
- if ( empty( $args ) ) {
277
- $args = null;
278
- }
279
 
280
  // Use root blog if no ID passed.
281
- if ( empty( $blog_id ) ) {
282
- $blog_id = bp_get_root_blog_id();
283
  }
284
 
285
- $args = array( $blog_id, $capability, $args );
286
- $retval = call_user_func_array( 'current_user_can_for_blog', $args );
 
 
 
287
 
288
  /**
289
  * Filters whether or not the current user has a given capability.
290
  *
291
  * @since 1.6.0
292
  * @since 2.4.0 Pass `$args` variable.
 
293
  *
294
  * @param bool $retval Whether or not the current user has the capability.
295
  * @param string $capability The capability being checked for.
296
  * @param int $blog_id Blog ID. Defaults to the BP root blog.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  * @param array $args Array of extra arguments passed.
298
  */
299
- return (bool) apply_filters( 'bp_current_user_can', $retval, $capability, $blog_id, $args );
 
 
 
 
 
 
300
  }
301
 
302
  /**
20
  *
21
  * @since 2.1.0
22
  *
23
+ * @return object
24
  */
25
  function bp_get_current_blog_roles() {
26
  global $wp_roles;
56
  * This is called on plugin activation.
57
  *
58
  * @since 1.6.0
 
59
  */
60
  function bp_add_caps() {
61
  global $wp_roles;
88
  * This is called on plugin deactivation.
89
  *
90
  * @since 1.6.0
 
91
  */
92
  function bp_remove_caps() {
93
  global $wp_roles;
216
  * already have a role or capability on.
217
  *
218
  * @since 1.6.0
 
 
 
219
  */
220
  function bp_set_current_user_default_role() {
221
 
243
  *
244
  * @since 1.6.0
245
  * @since 2.4.0 Second argument modified to accept an array, rather than `$blog_id`.
246
+ * @since 2.7.0 Deprecated $args['blog_id'] in favor of $args['site_id'].
247
  *
248
  * @param string $capability Capability or role name.
249
  * @param array|int $args {
250
  * Array of extra arguments applicable to the capability check.
251
+ * @type int $site_id Optional. Blog ID. Defaults to the BP root blog.
252
+ * @type int $blog_id Deprecated. Use $site_id instead.
253
  * @type mixed $a,... Optional. Extra arguments applicable to the capability check.
254
  * }
255
  * @return bool True if the user has the cap for the given parameters.
256
  */
257
  function bp_current_user_can( $capability, $args = array() ) {
 
 
258
  // Backward compatibility for older $blog_id parameter.
259
  if ( is_int( $args ) ) {
260
+ $site_id = $args;
261
  $args = array();
262
+ $args['site_id'] = $site_id;
263
 
264
  // New format for second parameter.
265
  } elseif ( is_array( $args ) && isset( $args['blog_id'] ) ) {
266
  // Get the blog ID if set, but don't pass along to `current_user_can_for_blog()`.
267
+ $args['site_id'] = (int) $args['blog_id'];
268
  unset( $args['blog_id'] );
269
  }
270
 
271
+ // Cast $args as an array.
272
+ $args = (array) $args;
 
 
273
 
274
  // Use root blog if no ID passed.
275
+ if ( empty( $args['site_id'] ) ) {
276
+ $args['site_id'] = bp_get_root_blog_id();
277
  }
278
 
279
+ /** This filter is documented in /bp-core/bp-core-template.php */
280
+ $current_user_id = apply_filters( 'bp_loggedin_user_id', get_current_user_id() );
281
+
282
+ // Call bp_user_can().
283
+ $retval = bp_user_can( $current_user_id, $capability, $args );
284
 
285
  /**
286
  * Filters whether or not the current user has a given capability.
287
  *
288
  * @since 1.6.0
289
  * @since 2.4.0 Pass `$args` variable.
290
+ * @since 2.7.0 Change format of $args variable array.
291
  *
292
  * @param bool $retval Whether or not the current user has the capability.
293
  * @param string $capability The capability being checked for.
294
  * @param int $blog_id Blog ID. Defaults to the BP root blog.
295
+ * @param array $args Array of extra arguments as originally passed.
296
+ */
297
+ return (bool) apply_filters( 'bp_current_user_can', $retval, $capability, $args['site_id'], $args );
298
+ }
299
+
300
+ /**
301
+ * Check whether the specified user has a given capability on a given site.
302
+ *
303
+ * @since 2.7.0
304
+ *
305
+ * @param int $user_id
306
+ * @param string $capability Capability or role name.
307
+ * @param array|int $args {
308
+ * Array of extra arguments applicable to the capability check.
309
+ *
310
+ * @type int $site_id Optional. Site ID. Defaults to the BP root blog.
311
+ * @type mixed $a,... Optional. Extra arguments applicable to the capability check.
312
+ * }
313
+ * @return bool True if the user has the cap for the given parameters.
314
+ */
315
+ function bp_user_can( $user_id, $capability, $args = array() ) {
316
+ $site_id = bp_get_root_blog_id();
317
+
318
+ // Get the site ID if set, but don't pass along to user_can().
319
+ if ( isset( $args['site_id'] ) ) {
320
+ $site_id = (int) $args['site_id'];
321
+ unset( $args['site_id'] );
322
+ }
323
+
324
+ $switched = is_multisite() ? switch_to_blog( $site_id ) : false;
325
+ $retval = call_user_func_array( 'user_can', array( $user_id, $capability, $args ) );
326
+
327
+ /**
328
+ * Filters whether or not the specified user has a given capability on a given site.
329
+ *
330
+ * @since 2.7.0
331
+ *
332
+ * @param bool $retval Whether or not the current user has the capability.
333
+ * @param int $user_id
334
+ * @param string $capability The capability being checked for.
335
+ * @param int $site_id Site ID. Defaults to the BP root blog.
336
  * @param array $args Array of extra arguments passed.
337
  */
338
+ $retval = (bool) apply_filters( 'bp_user_can', $retval, $user_id, $capability, $site_id, $args );
339
+
340
+ if ( $switched ) {
341
+ restore_current_blog();
342
+ }
343
+
344
+ return $retval;
345
  }
346
 
347
  /**
bp-core/bp-core-catchuri.php CHANGED
@@ -218,7 +218,7 @@ function bp_core_set_uri_globals() {
218
  /**
219
  * Filter the portion of the URI that is the displayed user's slug.
220
  *
221
- * eg. example.com/ADMIN (when root profiles is enabled)
222
  * example.com/members/ADMIN (when root profiles isn't enabled)
223
  *
224
  * ADMIN would be the displayed user's slug.
@@ -456,6 +456,17 @@ function bp_core_load_template( $templates ) {
456
  * @param array $filtered_templates Array of templates to attempt to load.
457
  */
458
  $located_template = apply_filters( 'bp_located_template', $template, $filtered_templates );
 
 
 
 
 
 
 
 
 
 
 
459
  if ( !empty( $located_template ) ) {
460
  // Template was located, lets set this as a valid page and not a 404.
461
  status_header( 200 );
@@ -542,16 +553,18 @@ function bp_core_catch_profile_uri() {
542
  * @since 2.6.0
543
  *
544
  * @param string $member_slug The current member slug.
 
545
  */
546
  function bp_core_members_shortlink_redirector( $member_slug ) {
 
547
  /**
548
  * Shortlink slug to redirect to logged-in user.
549
  *
550
- * x.com/members/me/* will redirect to x.com/members/{LOGGED_IN_USER_SLUG}/*
551
  *
552
  * @since 2.6.0
553
  *
554
- * @var string $slug Defaults to 'me'.
555
  */
556
  $me_slug = apply_filters( 'bp_core_members_shortlink_slug', 'me' );
557
 
@@ -624,9 +637,9 @@ function bp_core_no_access( $args = '' ) {
624
  $redirect_url .= $_SERVER['REQUEST_URI'];
625
 
626
  $defaults = array(
627
- 'mode' => 2, // 1 = $root, 2 = wp-login.php
628
- 'redirect' => $redirect_url, // the URL you get redirected to when a user successfully logs in
629
- 'root' => bp_get_root_domain(), // the landing page you get redirected to when a user doesn't have access
630
  'message' => __( 'You must log in to access the page you requested.', 'buddypress' )
631
  );
632
 
@@ -643,7 +656,7 @@ function bp_core_no_access( $args = '' ) {
643
  extract( $r, EXTR_SKIP );
644
 
645
  /*
646
- * @ignore Ignore these filters and use 'bp_core_no_access' above
647
  */
648
  $mode = apply_filters( 'bp_no_access_mode', $mode, $root, $redirect, $message );
649
  $redirect = apply_filters( 'bp_no_access_redirect', $redirect, $root, $message, $mode );
@@ -653,18 +666,21 @@ function bp_core_no_access( $args = '' ) {
653
 
654
  switch ( $mode ) {
655
 
656
- // Option to redirect to wp-login.php
657
  // Error message is displayed with bp_core_no_access_wp_login_error().
658
  case 2 :
659
  if ( !empty( $redirect ) ) {
660
- bp_core_redirect( add_query_arg( array( 'action' => 'bpnoaccess' ), wp_login_url( $redirect ) ) );
 
 
 
661
  } else {
662
  bp_core_redirect( $root );
663
  }
664
 
665
  break;
666
 
667
- // Redirect to root with "redirect_to" parameter
668
  // Error message is displayed with bp_core_add_message().
669
  case 1 :
670
  default :
@@ -685,16 +701,47 @@ function bp_core_no_access( $args = '' ) {
685
  }
686
 
687
  /**
688
- * Add an error message to wp-login.php.
 
 
 
 
 
 
 
689
  *
690
- * Hooks into the "bpnoaccess" action defined in bp_core_no_access().
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
691
  *
692
  * @since 1.5.0
 
693
  *
694
- * @global string $error Error message to pass to wp-login.php.
 
695
  */
696
- function bp_core_no_access_wp_login_error() {
697
- global $error;
 
 
698
 
699
  /**
700
  * Filters the error message for wp-login.php when needing to log in before accessing.
@@ -704,12 +751,27 @@ function bp_core_no_access_wp_login_error() {
704
  * @param string $value Error message to display.
705
  * @param string $value URL to redirect user to after successful login.
706
  */
707
- $error = apply_filters( 'bp_wp_login_error', __( 'You must log in to access the page you requested.', 'buddypress' ), $_REQUEST['redirect_to'] );
708
 
709
- // Shake shake shake!.
710
- add_action( 'login_head', 'wp_shake_js', 12 );
 
711
  }
712
- add_action( 'login_form_bpnoaccess', 'bp_core_no_access_wp_login_error' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
713
 
714
  /**
715
  * Canonicalize BuddyPress URLs.
@@ -822,11 +884,14 @@ function bp_get_canonical_url( $args = array() ) {
822
  if ( 'page' == get_option( 'show_on_front' ) && $page_on_front = (int) get_option( 'page_on_front' ) ) {
823
  $front_page_component = array_search( $page_on_front, bp_core_get_directory_page_ids() );
824
 
825
- // If requesting the front page component directory, canonical
826
- // URL is the front page. We detect whether we're detecting a
827
- // component *directory* by checking that bp_current_action()
828
- // is empty - ie, this not a single item or a feed.
829
- if ( false !== $front_page_component && bp_is_current_component( $front_page_component ) && ! bp_current_action() ) {
 
 
 
830
  $bp->canonical_stack['canonical_url'] = trailingslashit( bp_get_root_domain() );
831
 
832
  // Except when the front page is set to the registration page
@@ -928,7 +993,6 @@ function bp_get_requested_url() {
928
  * notice in future versions of BuddyPress.
929
  *
930
  * @since 1.6.0
931
- *
932
  */
933
  function _bp_maybe_remove_redirect_canonical() {
934
  if ( ! bp_is_blog_page() )
@@ -964,7 +1028,7 @@ add_action( 'bp_init', '_bp_maybe_remove_redirect_canonical' );
964
  * @link https://buddypress.trac.wordpress.org/ticket/4415
965
  */
966
  function _bp_rehook_maybe_redirect_404() {
967
- if ( defined( 'NOBLOGREDIRECT' ) ) {
968
  remove_action( 'template_redirect', 'maybe_redirect_404' );
969
  add_action( 'template_redirect', 'maybe_redirect_404', 100 );
970
  }
@@ -986,3 +1050,36 @@ function _bp_maybe_remove_rel_canonical() {
986
  }
987
  }
988
  add_action( 'wp_head', '_bp_maybe_remove_rel_canonical', 8 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  /**
219
  * Filter the portion of the URI that is the displayed user's slug.
220
  *
221
+ * Eg. example.com/ADMIN (when root profiles is enabled)
222
  * example.com/members/ADMIN (when root profiles isn't enabled)
223
  *
224
  * ADMIN would be the displayed user's slug.
456
  * @param array $filtered_templates Array of templates to attempt to load.
457
  */
458
  $located_template = apply_filters( 'bp_located_template', $template, $filtered_templates );
459
+
460
+ /*
461
+ * If current page is an embed, wipe out bp-default template.
462
+ *
463
+ * Wiping out the bp-default template allows WordPress to use their special
464
+ * embed template, which is what we want.
465
+ */
466
+ if ( function_exists( 'is_embed' ) && is_embed() ) {
467
+ $located_template = '';
468
+ }
469
+
470
  if ( !empty( $located_template ) ) {
471
  // Template was located, lets set this as a valid page and not a 404.
472
  status_header( 200 );
553
  * @since 2.6.0
554
  *
555
  * @param string $member_slug The current member slug.
556
+ * @return string $member_slug The current member slug.
557
  */
558
  function bp_core_members_shortlink_redirector( $member_slug ) {
559
+
560
  /**
561
  * Shortlink slug to redirect to logged-in user.
562
  *
563
+ * The x.com/members/me/* url will redirect to x.com/members/{LOGGED_IN_USER_SLUG}/*
564
  *
565
  * @since 2.6.0
566
  *
567
+ * @param string $slug Defaults to 'me'.
568
  */
569
  $me_slug = apply_filters( 'bp_core_members_shortlink_slug', 'me' );
570
 
637
  $redirect_url .= $_SERVER['REQUEST_URI'];
638
 
639
  $defaults = array(
640
+ 'mode' => 2, // 1 = $root, 2 = wp-login.php.
641
+ 'redirect' => $redirect_url, // the URL you get redirected to when a user successfully logs in.
642
+ 'root' => bp_get_root_domain(), // the landing page you get redirected to when a user doesn't have access.
643
  'message' => __( 'You must log in to access the page you requested.', 'buddypress' )
644
  );
645
 
656
  extract( $r, EXTR_SKIP );
657
 
658
  /*
659
+ * @ignore Ignore these filters and use 'bp_core_no_access' above.
660
  */
661
  $mode = apply_filters( 'bp_no_access_mode', $mode, $root, $redirect, $message );
662
  $redirect = apply_filters( 'bp_no_access_redirect', $redirect, $root, $message, $mode );
666
 
667
  switch ( $mode ) {
668
 
669
+ // Option to redirect to wp-login.php.
670
  // Error message is displayed with bp_core_no_access_wp_login_error().
671
  case 2 :
672
  if ( !empty( $redirect ) ) {
673
+ bp_core_redirect( add_query_arg( array(
674
+ 'bp-auth' => 1,
675
+ 'action' => 'bpnoaccess'
676
+ ), wp_login_url( $redirect ) ) );
677
  } else {
678
  bp_core_redirect( $root );
679
  }
680
 
681
  break;
682
 
683
+ // Redirect to root with "redirect_to" parameter.
684
  // Error message is displayed with bp_core_add_message().
685
  case 1 :
686
  default :
701
  }
702
 
703
  /**
704
+ * Login redirector.
705
+ *
706
+ * If a link is not publicly available, we can send members from external
707
+ * locations, like following links in an email, through the login screen.
708
+ *
709
+ * If a user clicks on this link and is already logged in, we should attempt
710
+ * to redirect the user to the authorized content instead of forcing the user
711
+ * to re-authenticate.
712
  *
713
+ * @since 2.9.0
714
+ */
715
+ function bp_login_redirector() {
716
+ // Redirect links must include the `redirect_to` and `bp-auth` parameters.
717
+ if ( empty( $_GET['redirect_to'] ) || empty( $_GET['bp-auth'] ) ) {
718
+ return;
719
+ }
720
+
721
+ /*
722
+ * If the user is already logged in,
723
+ * skip the login form and redirect them to the content.
724
+ */
725
+ if ( bp_loggedin_user_id() ) {
726
+ wp_safe_redirect( esc_url_raw( $_GET['redirect_to'] ) );
727
+ exit;
728
+ }
729
+ }
730
+ add_action( 'login_init', 'bp_login_redirector', 1 );
731
+
732
+ /**
733
+ * Add a custom BuddyPress no access error message to wp-login.php.
734
  *
735
  * @since 1.5.0
736
+ * @since 2.7.0 Hook moved to 'wp_login_errors' made available since WP 3.6.0.
737
  *
738
+ * @param WP_Error $errors Current error container.
739
+ * @return WP_Error
740
  */
741
+ function bp_core_no_access_wp_login_error( $errors ) {
742
+ if ( empty( $_GET['action'] ) || 'bpnoaccess' !== $_GET['action'] ) {
743
+ return $errors;
744
+ }
745
 
746
  /**
747
  * Filters the error message for wp-login.php when needing to log in before accessing.
751
  * @param string $value Error message to display.
752
  * @param string $value URL to redirect user to after successful login.
753
  */
754
+ $message = apply_filters( 'bp_wp_login_error', __( 'You must log in to access the page you requested.', 'buddypress' ), $_REQUEST['redirect_to'] );
755
 
756
+ $errors->add( 'bp_no_access', $message );
757
+
758
+ return $errors;
759
  }
760
+ add_filter( 'wp_login_errors', 'bp_core_no_access_wp_login_error' );
761
+
762
+ /**
763
+ * Add our custom error code to WP login's shake error codes.
764
+ *
765
+ * @since 2.7.0
766
+ *
767
+ * @param array $codes Array of WP error codes.
768
+ * @return array
769
+ */
770
+ function bp_core_login_filter_shake_codes( $codes ) {
771
+ $codes[] = 'bp_no_access';
772
+ return $codes;
773
+ }
774
+ add_filter( 'shake_error_codes', 'bp_core_login_filter_shake_codes' );
775
 
776
  /**
777
  * Canonicalize BuddyPress URLs.
884
  if ( 'page' == get_option( 'show_on_front' ) && $page_on_front = (int) get_option( 'page_on_front' ) ) {
885
  $front_page_component = array_search( $page_on_front, bp_core_get_directory_page_ids() );
886
 
887
+ /*
888
+ * If requesting the front page component directory, canonical
889
+ * URL is the front page. We detect whether we're detecting a
890
+ * component *directory* by checking that bp_current_action()
891
+ * is empty - ie, this not a single item, a feed, or an item
892
+ * type directory.
893
+ */
894
+ if ( false !== $front_page_component && bp_is_current_component( $front_page_component ) && ! bp_current_action() && ! bp_get_current_member_type() ) {
895
  $bp->canonical_stack['canonical_url'] = trailingslashit( bp_get_root_domain() );
896
 
897
  // Except when the front page is set to the registration page
993
  * notice in future versions of BuddyPress.
994
  *
995
  * @since 1.6.0
 
996
  */
997
  function _bp_maybe_remove_redirect_canonical() {
998
  if ( ! bp_is_blog_page() )
1028
  * @link https://buddypress.trac.wordpress.org/ticket/4415
1029
  */
1030
  function _bp_rehook_maybe_redirect_404() {
1031
+ if ( defined( 'NOBLOGREDIRECT' ) && is_multisite() ) {
1032
  remove_action( 'template_redirect', 'maybe_redirect_404' );
1033
  add_action( 'template_redirect', 'maybe_redirect_404', 100 );
1034
  }
1050
  }
1051
  }
1052
  add_action( 'wp_head', '_bp_maybe_remove_rel_canonical', 8 );
1053
+
1054
+ /**
1055
+ * Stop WordPress performing a DB query for its main loop.
1056
+ *
1057
+ * As of WordPress 4.6, it is possible to bypass the main WP_Query entirely.
1058
+ * This saves us one unnecessary database query! :)
1059
+ *
1060
+ * @since 2.7.0
1061
+ *
1062
+ * @param null $retval Current return value for filter.
1063
+ * @param WP_Query $query Current WordPress query object.
1064
+ * @return null|array
1065
+ */
1066
+ function bp_core_filter_wp_query( $retval, $query ) {
1067
+ if ( ! $query->is_main_query() ) {
1068
+ return $retval;
1069
+ }
1070
+
1071
+ /*
1072
+ * If not on a BP single page, bail.
1073
+ * Too early to use bp_is_single_item(), so use BP conditionals.
1074
+ */
1075
+ if ( false === ( bp_is_group() || bp_is_user() || bp_is_single_activity() ) ) {
1076
+ return $retval;
1077
+ }
1078
+
1079
+ // Set default properties as recommended in the 'posts_pre_query' DocBlock.
1080
+ $query->found_posts = 0;
1081
+ $query->max_num_pages = 0;
1082
+
1083
+ // Return something other than a null value to bypass WP_Query.
1084
+ return array();
1085
+ }
bp-core/bp-core-classes.php DELETED
@@ -1,40 +0,0 @@
1
- <?php
2
- /**
3
- * Core component classes.
4
- *
5
- * @package BuddyPress
6
- * @subpackage Core
7
- * @since 1.0.0
8
- */
9
-
10
- // Exit if accessed directly.
11
- defined( 'ABSPATH' ) || exit;
12
-
13
- require dirname( __FILE__ ) . '/classes/class-bp-user-query.php';
14
- require dirname( __FILE__ ) . '/classes/class-bp-core-user.php';
15
- require dirname( __FILE__ ) . '/classes/class-bp-date-query.php';
16
- require dirname( __FILE__ ) . '/classes/class-bp-core-notification.php';
17
- require dirname( __FILE__ ) . '/classes/class-bp-button.php';
18
- require dirname( __FILE__ ) . '/classes/class-bp-embed.php';
19
- require dirname( __FILE__ ) . '/classes/class-bp-walker-nav-menu.php';
20
- require dirname( __FILE__ ) . '/classes/class-bp-walker-nav-menu-checklist.php';
21
- require dirname( __FILE__ ) . '/classes/class-bp-suggestions.php';
22
- require dirname( __FILE__ ) . '/classes/class-bp-members-suggestions.php';
23
- require dirname( __FILE__ ) . '/classes/class-bp-recursive-query.php';
24
- require dirname( __FILE__ ) . '/classes/class-bp-core-sort-by-key-callback.php';
25
- require dirname( __FILE__ ) . '/classes/class-bp-media-extractor.php';
26
- require dirname( __FILE__ ) . '/classes/class-bp-attachment.php';
27
- require dirname( __FILE__ ) . '/classes/class-bp-attachment-avatar.php';
28
- require dirname( __FILE__ ) . '/classes/class-bp-attachment-cover-image.php';
29
- require dirname( __FILE__ ) . '/classes/class-bp-email-recipient.php';
30
- require dirname( __FILE__ ) . '/classes/class-bp-email.php';
31
- require dirname( __FILE__ ) . '/classes/class-bp-email-delivery.php';
32
- require dirname( __FILE__ ) . '/classes/class-bp-phpmailer.php';
33
- require dirname( __FILE__ ) . '/classes/class-bp-core-nav.php';
34
- require dirname( __FILE__ ) . '/classes/class-bp-core-nav-item.php';
35
- require dirname( __FILE__ ) . '/classes/class-bp-core-oembed-extension.php';
36
-
37
- if ( buddypress()->do_nav_backcompat ) {
38
- require dirname( __FILE__ ) . '/classes/class-bp-core-bp-nav-backcompat.php';
39
- require dirname( __FILE__ ) . '/classes/class-bp-core-bp-options-nav-backcompat.php';
40
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-core/bp-core-cssjs.php CHANGED
@@ -19,35 +19,79 @@ function bp_core_register_common_scripts() {
19
  $min = bp_core_get_minified_asset_suffix();
20
  $url = buddypress()->plugin_url . 'bp-core/js/';
21
 
22
- /**
23
- * Filters the BuddyPress Core javascript files to register.
24
  *
25
- * @since 2.1.0
26
  *
27
- * @param array $value Array of javascript file information to register.
 
28
  */
29
- $scripts = apply_filters( 'bp_core_register_common_scripts', array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
 
 
31
  // Legacy.
32
- 'bp-confirm' => array( 'file' => "{$url}confirm{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
33
  'bp-widget-members' => array( 'file' => "{$url}widget-members{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
34
- 'bp-jquery-query' => array( 'file' => "{$url}jquery-query{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
35
- 'bp-jquery-cookie' => array( 'file' => "{$url}jquery-cookie{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
36
- 'bp-jquery-scroll-to' => array( 'file' => "{$url}jquery-scroll-to{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
37
 
38
- // 2.1
39
- 'jquery-caret' => array( 'file' => "{$url}jquery.caret{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => true ),
40
- 'jquery-atwho' => array( 'file' => "{$url}jquery.atwho{$min}.js", 'dependencies' => array( 'jquery', 'jquery-caret' ), 'footer' => true ),
41
 
42
- // 2.3
43
  'bp-plupload' => array( 'file' => "{$url}bp-plupload{$min}.js", 'dependencies' => array( 'plupload', 'jquery', 'json2', 'wp-backbone' ), 'footer' => true ),
44
  'bp-avatar' => array( 'file' => "{$url}avatar{$min}.js", 'dependencies' => array( 'jcrop' ), 'footer' => true ),
45
  'bp-webcam' => array( 'file' => "{$url}webcam{$min}.js", 'dependencies' => array( 'bp-avatar' ), 'footer' => true ),
46
 
47
- // 2.4
48
  'bp-cover-image' => array( 'file' => "{$url}cover-image{$min}.js", 'dependencies' => array(), 'footer' => true ),
49
 
50
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  $version = bp_get_version();
53
  foreach ( $scripts as $id => $script ) {
@@ -106,7 +150,7 @@ add_action( 'bp_enqueue_scripts', 'bp_core_register_common_styles', 1 );
106
  add_action( 'bp_admin_enqueue_scripts', 'bp_core_register_common_styles', 1 );
107
 
108
  /**
109
- * Load the JS for "Are you sure?" .confirm links.
110
  *
111
  * @since 1.1.0
112
  */
@@ -128,7 +172,7 @@ add_action( 'bp_admin_enqueue_scripts', 'bp_core_confirmation_js' );
128
  /**
129
  * Enqueues the css and js required by the Avatar UI.
130
  *
131
- * @since 2.3.0
132
  */
133
  function bp_core_avatar_scripts() {
134
  if ( ! bp_avatar_is_front_edit() ) {
@@ -148,7 +192,7 @@ add_action( 'bp_enqueue_scripts', 'bp_core_avatar_scripts' );
148
  /**
149
  * Enqueues the css and js required by the Cover Image UI.
150
  *
151
- * @since 2.4.0
152
  */
153
  function bp_core_cover_image_scripts() {
154
  if ( ! bp_attachments_cover_image_is_edit() ) {
@@ -361,13 +405,13 @@ function bp_core_get_js_dependencies() {
361
  }
362
 
363
  /**
364
- * Add inline css to display the component's single item cover image
365
  *
366
  * @since 2.4.0
367
  *
368
- * @param bool $return True to get the inline css.
369
- * @return string|array the inline css or an associative array containing
370
- * the css rules and the style handle
371
  */
372
  function bp_add_cover_image_inline_css( $return = false ) {
373
  $bp = buddypress();
@@ -460,3 +504,84 @@ function bp_add_cover_image_inline_css( $return = false ) {
460
  }
461
  }
462
  add_action( 'bp_enqueue_scripts', 'bp_add_cover_image_inline_css', 11 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  $min = bp_core_get_minified_asset_suffix();
20
  $url = buddypress()->plugin_url . 'bp-core/js/';
21
 
22
+ /*
23
+ * Moment.js locale.
24
  *
25
+ * Try to map current WordPress locale to a moment.js locale file for loading.
26
  *
27
+ * eg. French (France) locale for WP is fr_FR. Here, we try to find fr-fr.js
28
+ * (this file doesn't exist).
29
  */
30
+ $locale = sanitize_file_name( strtolower( get_locale() ) );
31
+ $locale = str_replace( '_', '-', $locale );
32
+ if ( file_exists( buddypress()->core->path . "bp-core/js/vendor/moment-js/locale/{$locale}{$min}.js" ) ) {
33
+ $moment_locale_url = $url . "vendor/moment-js/locale/{$locale}{$min}.js";
34
+
35
+ /*
36
+ * Try to find the short-form locale.
37
+ *
38
+ * eg. French (France) locale for WP is fr_FR. Here, we try to find fr.js
39
+ * (this exists).
40
+ */
41
+ } else {
42
+ $locale = substr( $locale, 0, strpos( $locale, '-' ) );
43
+ if ( file_exists( buddypress()->core->path . "bp-core/js/vendor/moment-js/locale/{$locale}{$min}.js" ) ) {
44
+ $moment_locale_url = $url . "vendor/moment-js/locale/{$locale}{$min}.js";
45
+ }
46
+ }
47
 
48
+ // Set up default scripts to register.
49
+ $scripts = array(
50
  // Legacy.
51
+ 'bp-confirm' => array( 'file' => "{$url}confirm{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
52
  'bp-widget-members' => array( 'file' => "{$url}widget-members{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
53
+ 'bp-jquery-query' => array( 'file' => "{$url}jquery-query{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
54
+ 'bp-jquery-cookie' => array( 'file' => "{$url}vendor/jquery-cookie{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
55
+ 'bp-jquery-scroll-to' => array( 'file' => "{$url}vendor/jquery-scroll-to{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => false ),
56
 
57
+ // Version 2.1.
58
+ 'jquery-caret' => array( 'file' => "{$url}vendor/jquery.caret{$min}.js", 'dependencies' => array( 'jquery' ), 'footer' => true ),
59
+ 'jquery-atwho' => array( 'file' => "{$url}vendor/jquery.atwho{$min}.js", 'dependencies' => array( 'jquery', 'jquery-caret' ), 'footer' => true ),
60
 
61
+ // Version 2.3.
62
  'bp-plupload' => array( 'file' => "{$url}bp-plupload{$min}.js", 'dependencies' => array( 'plupload', 'jquery', 'json2', 'wp-backbone' ), 'footer' => true ),
63
  'bp-avatar' => array( 'file' => "{$url}avatar{$min}.js", 'dependencies' => array( 'jcrop' ), 'footer' => true ),
64
  'bp-webcam' => array( 'file' => "{$url}webcam{$min}.js", 'dependencies' => array( 'bp-avatar' ), 'footer' => true ),
65
 
66
+ // Version 2.4.
67
  'bp-cover-image' => array( 'file' => "{$url}cover-image{$min}.js", 'dependencies' => array(), 'footer' => true ),
68
 
69
+ // Version 2.7.
70
+ 'bp-moment' => array( 'file' => "{$url}vendor/moment-js/moment{$min}.js", 'dependencies' => array(), 'footer' => true ),
71
+ 'bp-livestamp' => array( 'file' => "{$url}vendor/livestamp{$min}.js", 'dependencies' => array( 'jquery', 'bp-moment' ), 'footer' => true ),
72
+ );
73
+
74
+ // Version 2.7 - Add Moment.js locale to our $scripts array if we found one.
75
+ if ( isset( $moment_locale_url ) ) {
76
+ $scripts['bp-moment-locale'] = array( 'file' => esc_url( $moment_locale_url ), 'dependencies' => array( 'bp-moment' ), 'footer' => true );
77
+ }
78
+
79
+ /**
80
+ * Filters the BuddyPress Core javascript files to register.
81
+ *
82
+ * Default handles include 'bp-confirm', 'bp-widget-members',
83
+ * 'bp-jquery-query', 'bp-jquery-cookie', and 'bp-jquery-scroll-to'.
84
+ *
85
+ * @since 2.1.0 'jquery-caret', 'jquery-atwho' added.
86
+ * @since 2.3.0 'bp-plupload', 'bp-avatar', 'bp-webcam' added.
87
+ * @since 2.4.0 'bp-cover-image' added.
88
+ * @since 2.7.0 'bp-moment', 'bp-livestamp' added.
89
+ * 'bp-moment-locale' is added conditionally if a moment.js locale file is found.
90
+ *
91
+ * @param array $value Array of javascript file information to register.
92
+ */
93
+ $scripts = apply_filters( 'bp_core_register_common_scripts', $scripts );
94
+
95
 
96
  $version = bp_get_version();
97
  foreach ( $scripts as $id => $script ) {
150
  add_action( 'bp_admin_enqueue_scripts', 'bp_core_register_common_styles', 1 );
151
 
152
  /**
153
+ * Load the JS for "Are you sure?" confirm links.
154
  *
155
  * @since 1.1.0
156
  */
172
  /**
173
  * Enqueues the css and js required by the Avatar UI.
174
  *
175
+ * @since 2.3.0
176
  */
177
  function bp_core_avatar_scripts() {
178
  if ( ! bp_avatar_is_front_edit() ) {
192
  /**
193
  * Enqueues the css and js required by the Cover Image UI.
194
  *
195
+ * @since 2.4.0
196
  */
197
  function bp_core_cover_image_scripts() {
198
  if ( ! bp_attachments_cover_image_is_edit() ) {
405
  }
406
 
407
  /**
408
+ * Add inline css to display the component's single item cover image.
409
  *
410
  * @since 2.4.0
411
  *
412
+ * @param bool $return True to get the inline css.
413
+ * @return null|array|false The inline css or an associative array containing
414
+ * the css rules and the style handle.
415
  */
416
  function bp_add_cover_image_inline_css( $return = false ) {
417
  $bp = buddypress();
504
  }
505
  }
506
  add_action( 'bp_enqueue_scripts', 'bp_add_cover_image_inline_css', 11 );
507
+
508
+ /**
509
+ * Enqueues livestamp.js on BuddyPress pages.
510
+ *
511
+ * @since 2.7.0
512
+ */
513
+ function bp_core_add_livestamp() {
514
+ if ( ! is_buddypress() ) {
515
+ return;
516
+ }
517
+
518
+ bp_core_enqueue_livestamp();
519
+ }
520
+ add_action( 'bp_enqueue_scripts', 'bp_core_add_livestamp' );
521
+
522
+ /**
523
+ * Enqueue and localize livestamp.js script.
524
+ *
525
+ * @since 2.7.0
526
+ */
527
+ function bp_core_enqueue_livestamp() {
528
+ // If bp-livestamp isn't enqueued, do it now.
529
+ if ( wp_script_is( 'bp-livestamp' ) ) {
530
+ return;
531
+ }
532
+
533
+ /*
534
+ * Only enqueue Moment.js locale if we registered it in
535
+ * bp_core_register_common_scripts().
536
+ */
537
+ if ( wp_script_is( 'bp-moment-locale', 'registered' ) ) {
538
+ wp_enqueue_script( 'bp-moment-locale' );
539
+
540
+ if ( function_exists( 'wp_add_inline_script' ) ) {
541
+ wp_add_inline_script ( 'bp-livestamp', bp_core_moment_js_config() );
542
+ } else {
543
+ add_action( 'wp_footer', '_bp_core_moment_js_config_footer', 20 );
544
+ }
545
+ }
546
+
547
+ wp_enqueue_script( 'bp-livestamp' );
548
+ }
549
+
550
+ /**
551
+ * Return moment.js config.
552
+ *
553
+ * @since 2.7.0
554
+ *
555
+ * @return string
556
+ */
557
+ function bp_core_moment_js_config() {
558
+ // Grab the locale from the enqueued JS.
559
+ $moment_locale = wp_scripts()->query( 'bp-moment-locale' );
560
+ $moment_locale = substr( $moment_locale->src, strpos( $moment_locale->src, '/moment-js/locale/' ) + 18 );
561
+ $moment_locale = str_replace( '.js', '', $moment_locale );
562
+
563
+ $inline_js = <<<EOD
564
+ jQuery(function() {
565
+ moment.locale( '{$moment_locale}' );
566
+ });
567
+ EOD;
568
+
569
+ return $inline_js;
570
+ }
571
+
572
+ /**
573
+ * Print moment.js config in page footer.
574
+ *
575
+ * Will be removed once we set our minimum version of WP 4.5.
576
+ *
577
+ * @since 2.7.0
578
+ *
579
+ * @access private
580
+ */
581
+ function _bp_core_moment_js_config_footer() {
582
+ if ( ! wp_script_is( 'bp-moment-locale' ) ) {
583
+ return;
584
+ }
585
+
586
+ printf( '<script>%s</script>', bp_core_moment_js_config() );
587
+ }
bp-core/bp-core-customizer-email.php CHANGED
@@ -2,10 +2,9 @@
2
  /**
3
  * BuddyPress Customizer implementation for email.
4
  *
5
- * @since 2.5.0
6
- *
7
  * @package BuddyPress
8
  * @subpackage Core
 
9
  */
10
 
11
  // Exit if accessed directly.
@@ -19,12 +18,6 @@ defined( 'ABSPATH' ) || exit;
19
  * @param WP_Customize_Manager $wp_customize The Customizer object.
20
  */
21
  function bp_email_init_customizer( WP_Customize_Manager $wp_customize ) {
22
-
23
- // Require WP 4.0+.
24
- if ( ! method_exists( $wp_customize, 'add_panel' ) ) {
25
- return;
26
- }
27
-
28
  if ( ! bp_is_email_customizer() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
29
  return;
30
  }
@@ -44,13 +37,6 @@ function bp_email_init_customizer( WP_Customize_Manager $wp_customize ) {
44
  $wp_customize->add_setting( $setting_id, $args );
45
  }
46
 
47
- /**
48
- * BP_Customizer_Control_Range class.
49
- */
50
- if ( ! buddypress()->do_autoload ) {
51
- require_once dirname( __FILE__ ) . '/classes/class-bp-customizer-control-range.php';
52
- }
53
-
54
  /**
55
  * Fires to let plugins register extra Customizer controls for emails.
56
  *
@@ -65,7 +51,6 @@ function bp_email_init_customizer( WP_Customize_Manager $wp_customize ) {
65
  $wp_customize->add_control( new $args['class']( $wp_customize, $control_id, $args ) );
66
  }
67
 
68
-
69
  /*
70
  * Hook actions/filters for further configuration.
71
  */
@@ -90,7 +75,7 @@ function bp_email_init_customizer( WP_Customize_Manager $wp_customize ) {
90
  true
91
  );
92
 
93
- // Include the preview loading style
94
  add_action( 'wp_footer', array( $wp_customize, 'customize_preview_loading_style' ) );
95
  }
96
  }
@@ -112,7 +97,7 @@ function bp_is_email_customizer() {
112
  *
113
  * @since 2.5.0
114
  *
115
- * @param $active Whether the Customizer section is active.
116
  * @param WP_Customize_Section $section {@see WP_Customize_Section} instance.
117
  * @return bool
118
  */
2
  /**
3
  * BuddyPress Customizer implementation for email.
4
  *
 
 
5
  * @package BuddyPress
6
  * @subpackage Core
7
+ * @since 2.5.0
8
  */
9
 
10
  // Exit if accessed directly.
18
  * @param WP_Customize_Manager $wp_customize The Customizer object.
19
  */
20
  function bp_email_init_customizer( WP_Customize_Manager $wp_customize ) {
 
 
 
 
 
 
21
  if ( ! bp_is_email_customizer() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
22
  return;
23
  }
37
  $wp_customize->add_setting( $setting_id, $args );
38
  }
39
 
 
 
 
 
 
 
 
40
  /**
41
  * Fires to let plugins register extra Customizer controls for emails.
42
  *
51
  $wp_customize->add_control( new $args['class']( $wp_customize, $control_id, $args ) );
52
  }
53
 
 
54
  /*
55
  * Hook actions/filters for further configuration.
56
  */
75
  true
76
  );
77
 
78
+ // Include the preview loading style.
79
  add_action( 'wp_footer', array( $wp_customize, 'customize_preview_loading_style' ) );
80
  }
81
  }
97
  *
98
  * @since 2.5.0
99
  *
100
+ * @param bool $active Whether the Customizer section is active.
101
  * @param WP_Customize_Section $section {@see WP_Customize_Section} instance.
102
  * @return bool
103
  */
bp-core/bp-core-dependency.php CHANGED
@@ -13,8 +13,6 @@
13
  * The following functions are wrappers for hooks, allowing them to be
14
  * manually called and/or piggy-backed on top of other hooks if needed.
15
  *
16
- * @todo use anonymous functions when PHP minimum requirement allows (5.3)
17
- *
18
  * @package BuddyPress
19
  * @subpackage Core
20
  * @since 1.7.0
@@ -35,6 +33,23 @@ function bp_include() {
35
  do_action( 'bp_include' );
36
  }
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  /**
39
  * Fire the 'bp_setup_components' action, where plugins should initialize components.
40
  *
@@ -140,7 +155,7 @@ function bp_setup_admin_bar() {
140
  *
141
  * @since 1.5.0
142
  */
143
- do_action( 'bp_setup_admin_bar' );
144
  }
145
  }
146
 
@@ -207,28 +222,12 @@ function bp_setup_cache_groups() {
207
  /**
208
  * Set up the currently logged-in user.
209
  *
210
- * We white-list the WordPress Customizer which purposely loads the user early.
211
- * If the current user is being setup before the "init" action has fired,
212
- * strange (and difficult to debug) role/capability issues will occur.
213
- *
214
  * @since 1.7.0
215
  *
216
  * @link https://buddypress.trac.wordpress.org/ticket/6046
217
  * @link https://core.trac.wordpress.org/ticket/24169
218
- *
219
  */
220
  function bp_setup_current_user() {
221
- $skip_warning = (
222
- ( isset( $_REQUEST['wp_customize'] ) && 'on' === $_REQUEST['wp_customize'] ) ||
223
- ( is_admin() && 'customize.php' === basename( $_SERVER['PHP_SELF'] ) )
224
- );
225
-
226
- if ( ! $skip_warning && ! did_action( 'after_setup_theme' ) ) {
227
- $e = new Exception;
228
- $trace = $e->getTraceAsString();
229
-
230
- _doing_it_wrong( __FUNCTION__, __( 'The current user is being initialized without using $wp->init().', 'buddypress' ) . "\n===\nTrace:\n" . substr( $trace, strpos( $trace, '#6' ) ) . "\n===\n", '1.7' );
231
- }
232
 
233
  /**
234
  * Fires to set up the current user setup process.
@@ -406,7 +405,6 @@ function bp_head() {
406
  * who do not have the proper permission to access certain content.
407
  *
408
  * @since 1.6.0
409
- *
410
  */
411
  function bp_template_redirect() {
412
 
@@ -426,7 +424,6 @@ function bp_template_redirect() {
426
  * The main action used registering theme directories.
427
  *
428
  * @since 1.5.0
429
- *
430
  */
431
  function bp_register_theme_directory() {
432
 
@@ -446,7 +443,6 @@ function bp_register_theme_directory() {
446
  * The main action used registering theme packages.
447
  *
448
  * @since 1.7.0
449
- *
450
  */
451
  function bp_register_theme_packages() {
452
 
@@ -462,7 +458,6 @@ function bp_register_theme_packages() {
462
  * Fire the 'bp_enqueue_scripts' action, where BP enqueues its CSS and JS.
463
  *
464
  * @since 1.6.0
465
- *
466
  */
467
  function bp_enqueue_scripts() {
468
 
@@ -496,7 +491,6 @@ function bp_enqueue_embed_scripts() {
496
  * Fire the 'bp_add_rewrite_tag' action, where BP adds its custom rewrite tags.
497
  *
498
  * @since 1.8.0
499
- *
500
  */
501
  function bp_add_rewrite_tags() {
502
 
@@ -512,7 +506,6 @@ function bp_add_rewrite_tags() {
512
  * Fire the 'bp_add_rewrite_rules' action, where BP adds its custom rewrite rules.
513
  *
514
  * @since 1.9.0
515
- *
516
  */
517
  function bp_add_rewrite_rules() {
518
 
@@ -528,7 +521,6 @@ function bp_add_rewrite_rules() {
528
  * Fire the 'bp_add_permastructs' action, where BP adds its BP-specific permalink structure.
529
  *
530
  * @since 1.9.0
531
- *
532
  */
533
  function bp_add_permastructs() {
534
 
@@ -547,7 +539,6 @@ function bp_add_permastructs() {
547
  * BuddyPress-specific functionality.
548
  *
549
  * @since 1.6.0
550
- *
551
  */
552
  function bp_setup_theme() {
553
 
@@ -570,7 +561,6 @@ function bp_setup_theme() {
570
  * before our theme compatibility layer kicks in.
571
  *
572
  * @since 1.6.0
573
- *
574
  */
575
  function bp_after_setup_theme() {
576
 
@@ -699,7 +689,6 @@ function bp_allowed_themes( $themes ) {
699
  * The main action used for handling theme-side POST requests.
700
  *
701
  * @since 1.9.0
702
- *
703
  */
704
  function bp_post_request() {
705
 
@@ -742,7 +731,6 @@ function bp_post_request() {
742
  * The main action used for handling theme-side GET requests.
743
  *
744
  * @since 1.9.0
745
- *
746
  */
747
  function bp_get_request() {
748
 
13
  * The following functions are wrappers for hooks, allowing them to be
14
  * manually called and/or piggy-backed on top of other hooks if needed.
15
  *
 
 
16
  * @package BuddyPress
17
  * @subpackage Core
18
  * @since 1.7.0
33
  do_action( 'bp_include' );
34
  }
35
 
36
+ /**
37
+ * Fire the 'bp_late_include' action for loading conditional files.
38
+ *
39
+ * @since 3.0.0
40
+ */
41
+ function bp_late_include() {
42
+
43
+ /**
44
+ * Fires the 'bp_late_include' action.
45
+ *
46
+ * Allow for conditional includes on certain pages.
47
+ *
48
+ * @since 3.0.0
49
+ */
50
+ do_action( 'bp_late_include' );
51
+ }
52
+
53
  /**
54
  * Fire the 'bp_setup_components' action, where plugins should initialize components.
55
  *
155
  *
156
  * @since 1.5.0
157
  */
158
+ do_action( 'bp_setup_admin_bar', array() );
159
  }
160
  }
161
 
222
  /**
223
  * Set up the currently logged-in user.
224
  *
 
 
 
 
225
  * @since 1.7.0
226
  *
227
  * @link https://buddypress.trac.wordpress.org/ticket/6046
228
  * @link https://core.trac.wordpress.org/ticket/24169
 
229
  */
230
  function bp_setup_current_user() {
 
 
 
 
 
 
 
 
 
 
 
231
 
232
  /**
233
  * Fires to set up the current user setup process.
405
  * who do not have the proper permission to access certain content.
406
  *
407
  * @since 1.6.0
 
408
  */
409
  function bp_template_redirect() {
410
 
424
  * The main action used registering theme directories.
425
  *
426
  * @since 1.5.0
 
427
  */
428
  function bp_register_theme_directory() {
429
 
443
  * The main action used registering theme packages.
444
  *
445
  * @since 1.7.0
 
446
  */
447
  function bp_register_theme_packages() {
448
 
458
  * Fire the 'bp_enqueue_scripts' action, where BP enqueues its CSS and JS.
459
  *
460
  * @since 1.6.0
 
461
  */
462
  function bp_enqueue_scripts() {
463
 
491
  * Fire the 'bp_add_rewrite_tag' action, where BP adds its custom rewrite tags.
492
  *
493
  * @since 1.8.0
 
494
  */
495
  function bp_add_rewrite_tags() {
496
 
506
  * Fire the 'bp_add_rewrite_rules' action, where BP adds its custom rewrite rules.
507
  *
508
  * @since 1.9.0
 
509
  */
510
  function bp_add_rewrite_rules() {
511
 
521
  * Fire the 'bp_add_permastructs' action, where BP adds its BP-specific permalink structure.
522
  *
523
  * @since 1.9.0
 
524
  */
525
  function bp_add_permastructs() {
526
 
539
  * BuddyPress-specific functionality.
540
  *
541
  * @since 1.6.0
 
542
  */
543
  function bp_setup_theme() {
544
 
561
  * before our theme compatibility layer kicks in.
562
  *
563
  * @since 1.6.0
 
564
  */
565
  function bp_after_setup_theme() {
566
 
689
  * The main action used for handling theme-side POST requests.
690
  *
691
  * @since 1.9.0
 
692
  */
693
  function bp_post_request() {
694
 
731
  * The main action used for handling theme-side GET requests.
732
  *
733
  * @since 1.9.0
 
734
  */
735
  function bp_get_request() {
736
 
bp-core/bp-core-filters.php CHANGED
@@ -75,6 +75,9 @@ add_filter( 'bp_get_template_stack', 'bp_add_template_stack_locations' );
75
  // Turn comments off for BuddyPress pages.
76
  add_filter( 'comments_open', 'bp_comments_open', 10, 2 );
77
 
 
 
 
78
  /**
79
  * Prevent specific pages (eg 'Activate') from showing on page listings.
80
  *
@@ -98,9 +101,6 @@ function bp_core_exclude_pages( $pages = array() ) {
98
  if ( !empty( $bp->pages->register ) )
99
  $pages[] = $bp->pages->register->id;
100
 
101
- if ( !empty( $bp->pages->forums ) && ( !bp_is_active( 'forums' ) || ( bp_is_active( 'forums' ) && bp_forums_has_directory() && !bp_forums_is_installed_correctly() ) ) )
102
- $pages[] = $bp->pages->forums->id;
103
-
104
  /**
105
  * Filters specific pages that shouldn't show up on page listings.
106
  *
@@ -175,7 +175,7 @@ function bp_core_menu_highlight_parent_page( $retval, $page ) {
175
  foreach ( (array) buddypress()->pages as $component => $bp_page ) {
176
  // Handles the majority of components.
177
  if ( bp_is_current_component( $component ) ) {
178
- $page_id = (int) $bp_page->id;
179
  }
180
 
181
  // Stop if not on a user page.
@@ -308,7 +308,7 @@ function bp_core_login_redirect( $redirect_to, $redirect_to_raw, $user ) {
308
  *
309
  * @since 1.6.0
310
  *
311
- * @param bool $value Whether or not to redirect.
312
  * @param string $redirect_to Sanitized URL to be redirected to.
313
  * @param string $redirect_to_raw Unsanitized URL to be redirected to.
314
  * @param WP_User $user The WP_User object corresponding to a
@@ -349,6 +349,7 @@ add_filter( 'bp_login_redirect', 'bp_core_login_redirect', 10, 3 );
349
  * @param string $retval Current email content.
350
  * @param string $prop Email property to check against.
351
  * @param string $transform Either 'raw' or 'replace-tokens'.
 
352
  */
353
  function bp_email_plaintext_entity_decode( $retval, $prop, $transform ) {
354
  switch ( $prop ) {
@@ -463,7 +464,7 @@ function bp_core_activation_signup_blog_notification( $domain, $path, $title, $u
463
  'domain' => $domain,
464
  'key_blog' => $key,
465
  'path' => $path,
466
- 'user-site.url' => esc_url( "http://{$domain}{$path}" ),
467
  'title' => $title,
468
  'user.email' => $user_email,
469
  ),
@@ -486,7 +487,7 @@ add_filter( 'wpmu_signup_blog_notification', 'bp_core_activation_signup_blog_not
486
  * @param string $user_email The user's email address.
487
  * @param string $key The activation key created in wpmu_signup_user().
488
  * @param array $meta By default, an empty array.
489
- * @return bool|string Returns false to stop original WPMU function from continuing.
490
  */
491
  function bp_core_activation_signup_user_notification( $user, $user_email, $key, $meta ) {
492
  if ( is_admin() ) {
@@ -545,9 +546,9 @@ add_filter( 'wpmu_signup_user_notification', 'bp_core_activation_signup_user_not
545
  * @see wp_title()
546
  * @global object $bp BuddyPress global settings.
547
  *
548
- * @param string $title Original page title.
549
- * @param string $sep How to separate the various items within the page title.
550
- * @param string $seplocation Direction to display title.
551
  * @return string New page title.
552
  */
553
  function bp_modify_page_title( $title = '', $sep = '&raquo;', $seplocation = 'right' ) {
@@ -570,7 +571,7 @@ function bp_modify_page_title( $title = '', $sep = '&raquo;', $seplocation = 'ri
570
  * @link https://buddypress.trac.wordpress.org/ticket/6107
571
  * @see wp_title()
572
  */
573
- $title_tag_compatibility = (bool) ( ! empty( $_wp_theme_features['title-tag'] ) || strstr( $title, $blogname ) );
574
 
575
  // Append the site title to title parts if theme supports title tag.
576
  if ( true === $title_tag_compatibility ) {
@@ -595,12 +596,12 @@ function bp_modify_page_title( $title = '', $sep = '&raquo;', $seplocation = 'ri
595
  /**
596
  * Filters the older 'wp_title' page title for BuddyPress pages.
597
  *
598
- * @since 1.5.0
599
  *
600
- * @param string $new_title The BuddyPress page title.
601
- * @param string $title The original WordPress page title.
602
- * @param string $sep The title parts separator.
603
- * @param string $seplocation Location of the separator (left or right).
604
  */
605
  return apply_filters( 'bp_modify_page_title', $new_title, $title, $sep, $seplocation );
606
  }
@@ -648,10 +649,10 @@ function bp_modify_document_title_parts( $title = array() ) {
648
  /**
649
  * Filters BuddyPress title parts that will be used into the document title.
650
  *
651
- * @since 2.4.3
652
  *
653
- * @param array $bp_title The BuddyPress page title parts.
654
- * @param array $title The original WordPress title parts.
655
  */
656
  return apply_filters( 'bp_modify_document_title_parts', $bp_title, $title );
657
  }
@@ -749,13 +750,13 @@ add_filter( 'wp_setup_nav_menu_item', 'bp_setup_nav_menu_item', 10, 1 );
749
  /**
750
  * Populate BuddyPress user nav items for the customizer.
751
  *
752
- * @since 2.3.3
753
  *
754
- * @param array $items The array of menu items.
755
- * @param string $type The requested type.
756
- * @param string $object The requested object name.
757
- * @param integer $page The page num being requested.
758
- * @return array The paginated BuddyPress user nav items.
759
  */
760
  function bp_customizer_nav_menus_get_items( $items = array(), $type = '', $object = '', $page = 0 ) {
761
  if ( 'bp_loggedin_nav' === $object ) {
@@ -786,9 +787,9 @@ add_filter( 'customize_nav_menu_available_items', 'bp_customizer_nav_menus_get_i
786
  /**
787
  * Set BuddyPress item navs for the customizer.
788
  *
789
- * @since 2.3.3
790
  *
791
- * @param array $item_types An associative array structured for the customizer.
792
  * @return array $item_types An associative array structured for the customizer.
793
  */
794
  function bp_customizer_nav_menus_set_item_types( $item_types = array() ) {
@@ -852,10 +853,10 @@ function bp_filter_metaid_column_name( $q ) {
852
  *
853
  * @since 2.1.0
854
  *
855
- * @param string $edit_link The edit link.
856
- * @param int $post_id Post ID.
857
- * @return bool|string Will be a boolean (false) if $post_id is 0. Will be a string (the unchanged edit link)
858
- * otherwise
859
  */
860
  function bp_core_filter_edit_post_link( $edit_link = '', $post_id = 0 ) {
861
  if ( 0 === $post_id ) {
@@ -899,7 +900,8 @@ add_filter( 'bp_activity_maybe_load_mentions_scripts', 'bp_maybe_load_mentions_s
899
  * @access private
900
  *
901
  * @global array $wp_registered_widgets Current registered widgets.
902
- * @param array $params Current sidebar params.
 
903
  * @return array
904
  */
905
  function _bp_core_inject_bp_widget_css_class( $params ) {
@@ -951,9 +953,9 @@ add_filter( 'dynamic_sidebar_params', '_bp_core_inject_bp_widget_css_class' );
951
  *
952
  * @since 2.5.0
953
  *
954
- * @param string $value Property value.
955
- * @param string $property_name
956
- * @param string $transform How the return value was transformed.
957
  * @return string Updated value.
958
  */
959
  function bp_email_add_link_color_to_template( $value, $property_name, $transform ) {
@@ -962,7 +964,7 @@ function bp_email_add_link_color_to_template( $value, $property_name, $transform
962
  }
963
 
964
  $settings = bp_email_get_appearance_settings();
965
- $replacement = 'style="color: ' . esc_attr( $settings['highlight_color'] ) . ';';
966
 
967
  // Find all links.
968
  preg_match_all( '#<a[^>]+>#i', $value, $links, PREG_SET_ORDER );
@@ -990,16 +992,32 @@ add_filter( 'bp_email_get_property', 'bp_email_add_link_color_to_template', 6, 3
990
  *
991
  * @since 2.5.0
992
  *
993
- * @param array $headers
994
- * @param string $property Name of property. Unused.
995
- * @param string $transform Return value transformation. Unused.
996
- * @param BP_Email $email Email object reference.
997
  * @return array
998
  */
999
  function bp_email_set_default_headers( $headers, $property, $transform, $email ) {
1000
  $headers['X-BuddyPress'] = bp_get_version();
1001
  $headers['X-BuddyPress-Type'] = $email->get( 'type' );
1002
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1003
  return $headers;
1004
  }
1005
  add_filter( 'bp_email_get_headers', 'bp_email_set_default_headers', 6, 4 );
@@ -1009,15 +1027,16 @@ add_filter( 'bp_email_get_headers', 'bp_email_set_default_headers', 6, 4 );
1009
  *
1010
  * @since 2.5.0
1011
  *
1012
- * @param array $tokens Email tokens.
1013
- * @param string $property_name Unused.
1014
- * @param string $transform Unused.
1015
- * @param BP_Email $email Email being sent.
1016
  * @return array
1017
  */
1018
  function bp_email_set_default_tokens( $tokens, $property_name, $transform, $email ) {
1019
  $tokens['site.admin-email'] = bp_get_option( 'admin_email' );
1020
  $tokens['site.url'] = home_url();
 
1021
 
1022
  // These options are escaped with esc_html on the way into the database in sanitize_option().
1023
  $tokens['site.description'] = wp_specialchars_decode( bp_get_option( 'blogdescription' ), ENT_QUOTES );
@@ -1028,8 +1047,6 @@ function bp_email_set_default_tokens( $tokens, $property_name, $transform, $emai
1028
  $tokens['recipient.email'] = '';
1029
  $tokens['recipient.name'] = '';
1030
  $tokens['recipient.username'] = '';
1031
- $tokens['unsubscribe'] = site_url( 'wp-login.php' );
1032
-
1033
 
1034
  // Who is the email going to?
1035
  $recipient = $email->get( 'to' );
@@ -1045,16 +1062,23 @@ function bp_email_set_default_tokens( $tokens, $property_name, $transform, $emai
1045
  }
1046
 
1047
  if ( $user_obj ) {
1048
- // Unsubscribe link.
1049
- $tokens['unsubscribe'] = esc_url( sprintf(
1050
- '%s%s/notifications/',
1051
- bp_core_get_user_domain( $user_obj->ID ),
1052
- function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings'
1053
- ) );
1054
  $tokens['recipient.username'] = $user_obj->user_login;
 
 
 
 
 
 
 
 
1055
  }
1056
  }
1057
 
 
 
 
 
 
1058
  // Email preheader.
1059
  $post = $email->get_post_object();
1060
  if ( $post ) {
@@ -1107,7 +1131,7 @@ function bp_core_render_email_template( $template ) {
1107
 
1108
  // Make sure we add a <title> tag so WP Customizer picks it up.
1109
  $template = str_replace( '<head>', '<head><title>' . esc_html_x( 'BuddyPress Emails', 'screen heading', 'buddypress' ) . '</title>', $template );
1110
- echo str_replace( '{{{content}}}', nl2br( get_post()->post_content ), $template );
1111
 
1112
  /*
1113
  * Link colours are applied directly in the email template before sending, so we
75
  // Turn comments off for BuddyPress pages.
76
  add_filter( 'comments_open', 'bp_comments_open', 10, 2 );
77
 
78
+ // Prevent DB query for WP's main loop.
79
+ add_filter( 'posts_pre_query', 'bp_core_filter_wp_query', 10, 2 );
80
+
81
  /**
82
  * Prevent specific pages (eg 'Activate') from showing on page listings.
83
  *
101
  if ( !empty( $bp->pages->register ) )
102
  $pages[] = $bp->pages->register->id;
103
 
 
 
 
104
  /**
105
  * Filters specific pages that shouldn't show up on page listings.
106
  *
175
  foreach ( (array) buddypress()->pages as $component => $bp_page ) {
176
  // Handles the majority of components.
177
  if ( bp_is_current_component( $component ) ) {
178
+ $page_id = (int) $bp_page->id;
179
  }
180
 
181
  // Stop if not on a user page.
308
  *
309
  * @since 1.6.0
310
  *
311
+ * @param bool $value Whether or not to redirect.
312
  * @param string $redirect_to Sanitized URL to be redirected to.
313
  * @param string $redirect_to_raw Unsanitized URL to be redirected to.
314
  * @param WP_User $user The WP_User object corresponding to a
349
  * @param string $retval Current email content.
350
  * @param string $prop Email property to check against.
351
  * @param string $transform Either 'raw' or 'replace-tokens'.
352
+ * @return string|null $retval Modified email content.
353
  */
354
  function bp_email_plaintext_entity_decode( $retval, $prop, $transform ) {
355
  switch ( $prop ) {
464
  'domain' => $domain,
465
  'key_blog' => $key,
466
  'path' => $path,
467
+ 'user-site.url' => esc_url( set_url_scheme( "http://{$domain}{$path}" ) ),
468
  'title' => $title,
469
  'user.email' => $user_email,
470
  ),
487
  * @param string $user_email The user's email address.
488
  * @param string $key The activation key created in wpmu_signup_user().
489
  * @param array $meta By default, an empty array.
490
+ * @return false|string Returns false to stop original WPMU function from continuing.
491
  */
492
  function bp_core_activation_signup_user_notification( $user, $user_email, $key, $meta ) {
493
  if ( is_admin() ) {
546
  * @see wp_title()
547
  * @global object $bp BuddyPress global settings.
548
  *
549
+ * @param string $title Original page title.
550
+ * @param string $sep How to separate the various items within the page title.
551
+ * @param string $seplocation Direction to display title.
552
  * @return string New page title.
553
  */
554
  function bp_modify_page_title( $title = '', $sep = '&raquo;', $seplocation = 'right' ) {
571
  * @link https://buddypress.trac.wordpress.org/ticket/6107
572
  * @see wp_title()
573
  */
574
+ $title_tag_compatibility = (bool) ( ! empty( $_wp_theme_features['title-tag'] ) || ( $blogname && strstr( $title, $blogname ) ) );
575
 
576
  // Append the site title to title parts if theme supports title tag.
577
  if ( true === $title_tag_compatibility ) {
596
  /**
597
  * Filters the older 'wp_title' page title for BuddyPress pages.
598
  *
599
+ * @since 1.5.0
600
  *
601
+ * @param string $new_title The BuddyPress page title.
602
+ * @param string $title The original WordPress page title.
603
+ * @param string $sep The title parts separator.
604
+ * @param string $seplocation Location of the separator (left or right).
605
  */
606
  return apply_filters( 'bp_modify_page_title', $new_title, $title, $sep, $seplocation );
607
  }
649
  /**
650
  * Filters BuddyPress title parts that will be used into the document title.
651
  *
652
+ * @since 2.4.3
653
  *
654
+ * @param array $bp_title The BuddyPress page title parts.
655
+ * @param array $title The original WordPress title parts.
656
  */
657
  return apply_filters( 'bp_modify_document_title_parts', $bp_title, $title );
658
  }
750
  /**
751
  * Populate BuddyPress user nav items for the customizer.
752
  *
753
+ * @since 2.3.3
754
  *
755
+ * @param array $items The array of menu items.
756
+ * @param string $type The requested type.
757
+ * @param string $object The requested object name.
758
+ * @param integer $page The page num being requested.
759
+ * @return array The paginated BuddyPress user nav items.
760
  */
761
  function bp_customizer_nav_menus_get_items( $items = array(), $type = '', $object = '', $page = 0 ) {
762
  if ( 'bp_loggedin_nav' === $object ) {
787
  /**
788
  * Set BuddyPress item navs for the customizer.
789
  *
790
+ * @since 2.3.3
791
  *
792
+ * @param array $item_types An associative array structured for the customizer.
793
  * @return array $item_types An associative array structured for the customizer.
794
  */
795
  function bp_customizer_nav_menus_set_item_types( $item_types = array() ) {
853
  *
854
  * @since 2.1.0
855
  *
856
+ * @param string $edit_link The edit link.
857
+ * @param int $post_id Post ID.
858
+ * @return false|string Will be a boolean (false) if $post_id is 0. Will be a string (the unchanged edit link)
859
+ * otherwise
860
  */
861
  function bp_core_filter_edit_post_link( $edit_link = '', $post_id = 0 ) {
862
  if ( 0 === $post_id ) {
900
  * @access private
901
  *
902
  * @global array $wp_registered_widgets Current registered widgets.
903
+ *
904
+ * @param array $params Current sidebar params.
905
  * @return array
906
  */
907
  function _bp_core_inject_bp_widget_css_class( $params ) {
953
  *
954
  * @since 2.5.0
955
  *
956
+ * @param string $value Property value.
957
+ * @param string $property_name Email template property name.
958
+ * @param string $transform How the return value was transformed.
959
  * @return string Updated value.
960
  */
961
  function bp_email_add_link_color_to_template( $value, $property_name, $transform ) {
964
  }
965
 
966
  $settings = bp_email_get_appearance_settings();
967
+ $replacement = 'style="color: ' . esc_attr( $settings['link_text_color'] ) . ';';
968
 
969
  // Find all links.
970
  preg_match_all( '#<a[^>]+>#i', $value, $links, PREG_SET_ORDER );
992
  *
993
  * @since 2.5.0
994
  *
995
+ * @param array $headers Array of email headers.
996
+ * @param string $property Name of property. Unused.
997
+ * @param string $transform Return value transformation. Unused.
998
+ * @param BP_Email $email Email object reference.
999
  * @return array
1000
  */
1001
  function bp_email_set_default_headers( $headers, $property, $transform, $email ) {
1002
  $headers['X-BuddyPress'] = bp_get_version();
1003
  $headers['X-BuddyPress-Type'] = $email->get( 'type' );
1004
 
1005
+ $tokens = $email->get_tokens();
1006
+
1007
+ // Add 'List-Unsubscribe' header if applicable.
1008
+ if ( ! empty( $tokens['unsubscribe'] ) && $tokens['unsubscribe'] !== wp_login_url() ) {
1009
+ $user = get_user_by( 'email', $tokens['recipient.email'] );
1010
+
1011
+ $link = bp_email_get_unsubscribe_link( array(
1012
+ 'user_id' => $user->ID,
1013
+ 'notification_type' => $email->get( 'type' ),
1014
+ ) );
1015
+
1016
+ if ( ! empty( $link ) ) {
1017
+ $headers['List-Unsubscribe'] = sprintf( '<%s>', esc_url_raw( $link ) );
1018
+ }
1019
+ }
1020
+
1021
  return $headers;
1022
  }
1023
  add_filter( 'bp_email_get_headers', 'bp_email_set_default_headers', 6, 4 );
1027
  *
1028
  * @since 2.5.0
1029
  *
1030
+ * @param array $tokens Email tokens.
1031
+ * @param string $property_name Unused.
1032
+ * @param string $transform Unused.
1033
+ * @param BP_Email $email Email being sent.
1034
  * @return array
1035
  */
1036
  function bp_email_set_default_tokens( $tokens, $property_name, $transform, $email ) {
1037
  $tokens['site.admin-email'] = bp_get_option( 'admin_email' );
1038
  $tokens['site.url'] = home_url();
1039
+ $tokens['email.subject'] = $email->get_subject();
1040
 
1041
  // These options are escaped with esc_html on the way into the database in sanitize_option().
1042
  $tokens['site.description'] = wp_specialchars_decode( bp_get_option( 'blogdescription' ), ENT_QUOTES );
1047
  $tokens['recipient.email'] = '';
1048
  $tokens['recipient.name'] = '';
1049
  $tokens['recipient.username'] = '';
 
 
1050
 
1051
  // Who is the email going to?
1052
  $recipient = $email->get( 'to' );
1062
  }
1063
 
1064
  if ( $user_obj ) {
 
 
 
 
 
 
1065
  $tokens['recipient.username'] = $user_obj->user_login;
1066
+
1067
+ if ( bp_is_active( 'settings' ) && empty( $tokens['unsubscribe'] ) ) {
1068
+ $tokens['unsubscribe'] = esc_url( sprintf(
1069
+ '%s%s/notifications/',
1070
+ bp_core_get_user_domain( $user_obj->ID ),
1071
+ bp_get_settings_slug()
1072
+ ) );
1073
+ }
1074
  }
1075
  }
1076
 
1077
+ // Set default unsubscribe link if not passed.
1078
+ if ( empty( $tokens['unsubscribe'] ) ) {
1079
+ $tokens['unsubscribe'] = wp_login_url();
1080
+ }
1081
+
1082
  // Email preheader.
1083
  $post = $email->get_post_object();
1084
  if ( $post ) {
1131
 
1132
  // Make sure we add a <title> tag so WP Customizer picks it up.
1133
  $template = str_replace( '<head>', '<head><title>' . esc_html_x( 'BuddyPress Emails', 'screen heading', 'buddypress' ) . '</title>', $template );
1134
+ echo str_replace( '{{{content}}}', wpautop( get_post()->post_content ), $template );
1135
 
1136
  /*
1137
  * Link colours are applied directly in the email template before sending, so we
bp-core/bp-core-functions.php CHANGED
@@ -108,14 +108,53 @@ function bp_core_get_table_prefix() {
108
  * your own awkward callback function for usort().
109
  *
110
  * @since 2.2.0
 
 
 
 
 
 
 
 
111
  *
112
- * @param array $items The items to be sorted. Its constituent items can be either associative arrays or objects.
113
- * @param string|int $key The array index or property name to sort by.
114
- * @param string $type Sort type. 'alpha' for alphabetical, 'num' for numeric. Default: 'alpha'.
115
  * @return array $items The sorted array.
116
  */
117
- function bp_sort_by_key( $items, $key, $type = 'alpha' ) {
118
- usort( $items, array( new BP_Core_Sort_By_Key_Callback( $key, $type ), 'sort_callback' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
  return $items;
121
  }
@@ -406,6 +445,27 @@ function bp_use_wp_admin_bar() {
406
  return (bool) apply_filters( 'bp_use_wp_admin_bar', $use_admin_bar );
407
  }
408
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  /** Directory *****************************************************************/
410
 
411
  /**
@@ -428,12 +488,6 @@ function bp_core_get_packaged_component_ids() {
428
  'notifications',
429
  );
430
 
431
- // Only add legacy forums if it is enabled
432
- // prevents conflicts with bbPress, which also uses the same 'forums' id.
433
- if ( class_exists( 'BP_Forums_Component' ) ) {
434
- $components[] = 'forums';
435
- }
436
-
437
  return $components;
438
  }
439
 
@@ -449,30 +503,29 @@ function bp_core_get_packaged_component_ids() {
449
  * empty string if the list is not found.
450
  */
451
  function bp_core_get_directory_page_ids( $status = 'active' ) {
452
- $page_ids = bp_get_option( 'bp-pages' );
453
 
454
- // Ensure that empty indexes are unset. Should only matter in edge cases.
455
- if ( !empty( $page_ids ) && is_array( $page_ids ) ) {
456
- foreach( (array) $page_ids as $component_name => $page_id ) {
457
- if ( empty( $component_name ) || empty( $page_id ) ) {
458
- unset( $page_ids[ $component_name ] );
459
- }
460
 
461
- // 'register' and 'activate' do not have components, but should be whitelisted.
462
- if ( 'register' === $component_name || 'activate' === $component_name ) {
463
- continue;
464
- }
465
 
466
- // Trashed pages should not appear in results.
467
- if ( 'trash' == get_post_status( $page_id ) ) {
468
- unset( $page_ids[ $component_name ] );
 
469
 
470
- }
 
 
 
471
 
472
- // Remove inactive component pages, if required.
473
- if ( 'active' === $status && ! bp_is_active( $component_name ) ) {
474
- unset( $page_ids[ $component_name ] );
475
- }
476
  }
477
  }
478
 
@@ -480,10 +533,12 @@ function bp_core_get_directory_page_ids( $status = 'active' ) {
480
  * Filters the list of BP directory pages from the appropriate meta table.
481
  *
482
  * @since 1.5.0
 
483
  *
484
- * @param array $page_ids Array of directory pages.
 
485
  */
486
- return apply_filters( 'bp_core_get_directory_page_ids', $page_ids );
487
  }
488
 
489
  /**
@@ -491,8 +546,8 @@ function bp_core_get_directory_page_ids( $status = 'active' ) {
491
  *
492
  * @since 2.6.0
493
  *
494
- * @param string $component The slug representing the component. Defaults to the current component.
495
- * @return int|bool The ID of the directory page associated with the component. False if none is found.
496
  */
497
  function bp_core_get_directory_page_id( $component = null ) {
498
  if ( ! $component ) {
@@ -623,21 +678,14 @@ function bp_core_add_page_mappings( $components, $existing = 'keep' ) {
623
 
624
  // Delete any existing pages.
625
  if ( 'delete' === $existing ) {
626
- foreach ( (array) $pages as $page_id ) {
627
  wp_delete_post( $page_id, true );
628
  }
629
 
630
  $pages = array();
631
  }
632
 
633
- $page_titles = array(
634
- 'activity' => _x( 'Activity', 'Page title for the Activity directory.', 'buddypress' ),
635
- 'groups' => _x( 'Groups', 'Page title for the Groups directory.', 'buddypress' ),
636
- 'sites' => _x( 'Sites', 'Page title for the Sites directory.', 'buddypress' ),
637
- 'members' => _x( 'Members', 'Page title for the Members directory.', 'buddypress' ),
638
- 'activate' => _x( 'Activate', 'Page title for the user activation screen.', 'buddypress' ),
639
- 'register' => _x( 'Register', 'Page title for the user registration screen.', 'buddypress' ),
640
- );
641
 
642
  $pages_to_create = array();
643
  foreach ( array_keys( $components ) as $component_name ) {
@@ -657,8 +705,8 @@ function bp_core_add_page_mappings( $components, $existing = 'keep' ) {
657
  }
658
 
659
  // No need for a Sites directory unless we're on multisite.
660
- if ( ! is_multisite() && isset( $pages_to_create['sites'] ) ) {
661
- unset( $pages_to_create['sites'] );
662
  }
663
 
664
  // Members must always have a page, no matter what.
@@ -693,6 +741,33 @@ function bp_core_add_page_mappings( $components, $existing = 'keep' ) {
693
  }
694
  }
695
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696
  /**
697
  * Remove the entry from bp_pages when the corresponding WP page is deleted.
698
  *
@@ -795,7 +870,7 @@ function bp_core_add_root_component( $slug ) {
795
 
796
  // If there was no match, add a page for this root component.
797
  if ( empty( $match ) ) {
798
- $add_root_items = $bp->add_root();
799
  $add_root_items[] = $slug;
800
  $bp->add_root = $add_root_items;
801
  }
@@ -829,7 +904,7 @@ function bp_core_create_root_component_page() {
829
  ) );
830
  }
831
 
832
- $page_ids = array_merge( (array) $new_page_ids, (array) bp_core_get_directory_page_ids( 'all' ) );
833
  bp_core_update_directory_page_ids( $page_ids );
834
  }
835
 
@@ -850,11 +925,17 @@ function bp_core_add_illegal_names() {
850
  * Get the 'search' query argument for a given component.
851
  *
852
  * @since 2.4.0
 
 
853
  *
854
- * @param string $component Component name.
855
  * @return string|bool Query argument on success. False on failure.
856
  */
857
- function bp_core_get_component_search_query_arg( $component ) {
 
 
 
 
858
  $query_arg = false;
859
  if ( isset( buddypress()->{$component}->search_query_arg ) ) {
860
  $query_arg = sanitize_title( buddypress()->{$component}->search_query_arg );
@@ -956,7 +1037,11 @@ function bp_core_redirect( $location = '', $status = 302 ) {
956
  buddypress()->no_status_set = true;
957
 
958
  wp_safe_redirect( $location, $status );
959
- die;
 
 
 
 
960
  }
961
 
962
  /**
@@ -1258,6 +1343,41 @@ function bp_core_time_since( $older_date, $newer_date = false ) {
1258
  return apply_filters( 'bp_core_time_since', $output, $older_date, $newer_date );
1259
  }
1260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1261
  /** Messages ******************************************************************/
1262
 
1263
  /**
@@ -1388,7 +1508,7 @@ function bp_core_render_message() {
1388
  *
1389
  * usermeta table.
1390
  *
1391
- * @return bool|null Returns false if there is nothing to do.
1392
  */
1393
  function bp_core_record_activity() {
1394
 
@@ -1414,7 +1534,7 @@ function bp_core_record_activity() {
1414
  }
1415
 
1416
  // Get current time.
1417
- $current_time = bp_core_current_time();
1418
 
1419
  // Use this action to detect the very first activity for a given member.
1420
  if ( empty( $activity ) ) {
@@ -1432,8 +1552,8 @@ function bp_core_record_activity() {
1432
  }
1433
 
1434
  // If it's been more than 5 minutes, record a newer last-activity time.
1435
- if ( empty( $activity ) || ( strtotime( $current_time ) >= strtotime( '+5 minutes', $activity ) ) ) {
1436
- bp_update_user_last_activity( $user_id, $current_time );
1437
  }
1438
  }
1439
  add_action( 'wp_head', 'bp_core_record_activity' );
@@ -1628,26 +1748,6 @@ function bp_use_embed_in_activity_replies() {
1628
  return apply_filters( 'bp_use_embed_in_activity_replies', !defined( 'BP_EMBED_DISABLE_ACTIVITY_REPLIES' ) || !BP_EMBED_DISABLE_ACTIVITY_REPLIES );
1629
  }
1630
 
1631
- /**
1632
- * Are oembeds allowed in forum posts?
1633
- *
1634
- * @since 1.5.0
1635
- *
1636
- * @return bool False when forum post embed support is disabled; true when
1637
- * enabled. Default: true.
1638
- */
1639
- function bp_use_embed_in_forum_posts() {
1640
-
1641
- /**
1642
- * Filters whether or not oEmbeds are allowed in forum posts.
1643
- *
1644
- * @since 1.5.0
1645
- *
1646
- * @param bool $value Whether or not oEmbeds are allowed.
1647
- */
1648
- return apply_filters( 'bp_use_embed_in_forum_posts', !defined( 'BP_EMBED_DISABLE_FORUM_POSTS' ) || !BP_EMBED_DISABLE_FORUM_POSTS );
1649
- }
1650
-
1651
  /**
1652
  * Are oembeds allowed in private messages?
1653
  *
@@ -1673,10 +1773,10 @@ function bp_use_embed_in_private_messages() {
1673
  *
1674
  * @since 2.6.0
1675
  *
1676
- * @param string $content The content to check.
1677
- * @param string|int $type The type to check. Can also use a bitmask. See the class constants in the
1678
  * BP_Media_Extractor class for more info.
1679
- * @return array|bool If media exists, will return array of media metadata. Else, boolean false.
1680
  */
1681
  function bp_core_extract_media_from_content( $content = '', $type = 'all' ) {
1682
  if ( is_string( $type ) ) {
@@ -2254,11 +2354,6 @@ function bp_core_action_search_site( $slug = '' ) {
2254
  $slug = bp_is_active( 'blogs' ) ? bp_get_blogs_root_slug() : '';
2255
  break;
2256
 
2257
- case 'forums':
2258
- $slug = bp_is_active( 'forums' ) ? bp_get_forums_root_slug() : '';
2259
- $query_string = '/?fs=';
2260
- break;
2261
-
2262
  case 'groups':
2263
  $slug = bp_is_active( 'groups' ) ? bp_get_groups_root_slug() : '';
2264
  break;
@@ -2302,7 +2397,7 @@ function bp_remove_adjacent_posts_rel_link() {
2302
  return;
2303
  }
2304
 
2305
- remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
2306
  }
2307
  add_action( 'bp_init', 'bp_remove_adjacent_posts_rel_link' );
2308
 
@@ -2362,10 +2457,6 @@ function bp_core_get_components( $type = 'all' ) {
2362
  );
2363
 
2364
  $retired_components = array(
2365
- 'forums' => array(
2366
- 'title' => __( 'Group Forums', 'buddypress' ),
2367
- 'description' => sprintf( __( 'BuddyPress Forums are retired. Use %s.', 'buddypress' ), '<a href="https://bbpress.org/">bbPress</a>' )
2368
- ),
2369
  );
2370
 
2371
  $optional_components = array(
@@ -2397,10 +2488,6 @@ function bp_core_get_components( $type = 'all' ) {
2397
  'title' => __( 'User Groups', 'buddypress' ),
2398
  'description' => __( 'Groups allow your users to organize themselves into specific public, private or hidden sections with separate activity streams and member listings.', 'buddypress' )
2399
  ),
2400
- 'forums' => array(
2401
- 'title' => __( 'Group Forums (Legacy)', 'buddypress' ),
2402
- 'description' => __( 'Group forums allow for focused, bulletin-board style conversations.', 'buddypress' )
2403
- ),
2404
  'blogs' => array(
2405
  'title' => __( 'Site Tracking', 'buddypress' ),
2406
  'description' => __( 'Record activity for new posts and comments from your site.', 'buddypress' )
@@ -2691,7 +2778,7 @@ function bp_core_get_suggestions( $args ) {
2691
  *
2692
  * @since 2.3.0
2693
  *
2694
- * @return string
2695
  */
2696
  function bp_upload_dir() {
2697
  $bp = buddypress();
@@ -2989,7 +3076,7 @@ function bp_get_email( $email_type ) {
2989
  * @param string|array|int|WP_User $to Either a email address, user ID, WP_User object,
2990
  * or an array containg the address and name.
2991
  * @param array $args {
2992
- * Optional. Array of extra. parameters.
2993
  *
2994
  * @type array $tokens Optional. Assocative arrays of string replacements for the email.
2995
  * }
@@ -3035,6 +3122,23 @@ function bp_send_email( $email_type, $to, $args = array() ) {
3035
  $email->set_to( $to );
3036
  $email->set_tokens( $args['tokens'] );
3037
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3038
  $status = $email->validate();
3039
  if ( is_wp_error( $status ) ) {
3040
  return $status;
@@ -3124,6 +3228,8 @@ function bp_send_email( $email_type, $to, $args = array() ) {
3124
  * Return email appearance settings.
3125
  *
3126
  * @since 2.5.0
 
 
3127
  *
3128
  * @return array
3129
  */
@@ -3140,6 +3246,7 @@ function bp_email_get_appearance_settings() {
3140
  'highlight_color' => '#D84800',
3141
  'header_text_color' => '#000000',
3142
  'header_text_size' => 30,
 
3143
 
3144
  'footer_text' => sprintf(
3145
  /* translators: email disclaimer, e.g. "© 2016 Site Name". */
@@ -3149,11 +3256,18 @@ function bp_email_get_appearance_settings() {
3149
  ),
3150
  );
3151
 
3152
- return bp_parse_args(
3153
  bp_get_option( 'bp_email_options', array() ),
3154
  $default_args,
3155
  'email_appearance_settings'
3156
  );
 
 
 
 
 
 
 
3157
  }
3158
 
3159
  /**
@@ -3176,6 +3290,7 @@ function bp_email_get_template( WP_Post $object ) {
3176
  * @param WP_Post $object WP_Post object.
3177
  */
3178
  return apply_filters( 'bp_email_get_template', array(
 
3179
  "{$single}-{$object->post_name}.php",
3180
  "{$single}.php",
3181
  "assets/emails/{$single}.php",
@@ -3189,8 +3304,8 @@ function bp_email_get_template( WP_Post $object ) {
3189
  *
3190
  * @since 2.5.0
3191
  *
3192
- * @param string $text
3193
- * @param array $tokens Token names and replacement values for the $text.
3194
  * @return string
3195
  */
3196
  function bp_core_replace_tokens_in_text( $text, $tokens ) {
@@ -3227,7 +3342,7 @@ function bp_core_replace_tokens_in_text( $text, $tokens ) {
3227
 
3228
  /**
3229
  * Get a list of emails for populating the email post type.
3230
- *t
3231
  * @since 2.5.1
3232
  *
3233
  * @return array
@@ -3273,6 +3388,9 @@ function bp_email_get_schema() {
3273
  'post_content' => __( "Thanks for registering!\n\nTo complete the activation of your account, go to the following link: <a href=\"{{{activate.url}}}\">{{{activate.url}}}</a>", 'buddypress' ),
3274
  /* translators: do not remove {} brackets or translate its contents. */
3275
  'post_excerpt' => __( "Thanks for registering!\n\nTo complete the activation of your account, go to the following link: {{{activate.url}}}", 'buddypress' ),
 
 
 
3276
  ),
3277
  'core-user-registration-with-blog' => array(
3278
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3281,6 +3399,9 @@ function bp_email_get_schema() {
3281
  'post_content' => __( "Thanks for registering!\n\nTo complete the activation of your account and site, go to the following link: <a href=\"{{{activate-site.url}}}\">{{{activate-site.url}}}</a>.\n\nAfter you activate, you can visit your site at <a href=\"{{{user-site.url}}}\">{{{user-site.url}}}</a>.", 'buddypress' ),
3282
  /* translators: do not remove {} brackets or translate its contents. */
3283
  'post_excerpt' => __( "Thanks for registering!\n\nTo complete the activation of your account and site, go to the following link: {{{activate-site.url}}}\n\nAfter you activate, you can visit your site at {{{user-site.url}}}.", 'buddypress' ),
 
 
 
3284
  ),
3285
  'friends-request' => array(
3286
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3304,7 +3425,7 @@ function bp_email_get_schema() {
3304
  /* translators: do not remove {} brackets or translate its contents. */
3305
  'post_content' => __( "Group details for the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot; were updated:\n<blockquote>{{changed_text}}</blockquote>", 'buddypress' ),
3306
  /* translators: do not remove {} brackets or translate its contents. */
3307
- 'post_excerpt' => __( "Group details for the group &quot;{{group.name}}&quot; were updated:\n\n{{changed_text}}\n\nTo view the group, visit: {{{group.url}}}", 'buddypress' ),
3308
  ),
3309
  'groups-invitation' => array(
3310
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3312,7 +3433,7 @@ function bp_email_get_schema() {
3312
  /* translators: do not remove {} brackets or translate its contents. */
3313
  'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the group: &quot;{{group.name}}&quot;.\n<a href=\"{{{invites.url}}}\">Go here to accept your invitation</a> or <a href=\"{{{group.url}}}\">visit the group</a> to learn more.", 'buddypress' ),
3314
  /* translators: do not remove {} brackets or translate its contents. */
3315
- 'post_excerpt' => __( "{{inviter.name}} has invited you to join the group: &quot;{{group.name}}&quot;.\n\nTo accept your invitation, visit: {{{invites.url}}}\n\nTo learn more about the group, visit {{{group.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ),
3316
  ),
3317
  'groups-member-promoted' => array(
3318
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3320,7 +3441,7 @@ function bp_email_get_schema() {
3320
  /* translators: do not remove {} brackets or translate its contents. */
3321
  'post_content' => __( "You have been promoted to <b>{{promoted_to}}</b> in the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot;.", 'buddypress' ),
3322
  /* translators: do not remove {} brackets or translate its contents. */
3323
- 'post_excerpt' => __( "You have been promoted to {{promoted_to}} in the group: &quot;{{group.name}}&quot;.\n\nTo visit the group, go to: {{{group.url}}}", 'buddypress' ),
3324
  ),
3325
  'groups-membership-request' => array(
3326
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3328,7 +3449,7 @@ function bp_email_get_schema() {
3328
  /* translators: do not remove {} brackets or translate its contents. */
3329
  'post_content' => __( "<a href=\"{{{profile.url}}}\">{{requesting-user.name}}</a> wants to join the group &quot;{{group.name}}&quot;. As you are an administrator of this group, you must either accept or reject the membership request.\n\n<a href=\"{{{group-requests.url}}}\">Go here to manage this</a> and all other pending requests.", 'buddypress' ),
3330
  /* translators: do not remove {} brackets or translate its contents. */
3331
- 'post_excerpt' => __( "{{requesting-user.name}} wants to join the group &quot;{{group.name}}&quot;. As you are the administrator of this group, you must either accept or reject the membership request.\n\nTo manage this and all other pending requests, visit: {{{group-requests.url}}}\n\nTo view {{requesting-user.name}}'s profile, visit: {{{profile.url}}}", 'buddypress' ),
3332
  ),
3333
  'messages-unread' => array(
3334
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3336,7 +3457,7 @@ function bp_email_get_schema() {
3336
  /* translators: do not remove {} brackets or translate its contents. */
3337
  'post_content' => __( "{{sender.name}} sent you a new message: &quot;{{usersubject}}&quot;\n\n<blockquote>&quot;{{usermessage}}&quot;</blockquote>\n\n<a href=\"{{{message.url}}}\">Go to the discussion</a> to reply or catch up on the conversation.", 'buddypress' ),
3338
  /* translators: do not remove {} brackets or translate its contents. */
3339
- 'post_excerpt' => __( "{{sender.name}} sent you a new message: &quot;{{usersubject}}&quot;\n\n&quot;{{usermessage}}&quot;\n\nGo to the discussion to reply or catch up on the conversation: {{{message.url}}}", 'buddypress' ),
3340
  ),
3341
  'settings-verify-email-change' => array(
3342
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3352,7 +3473,7 @@ function bp_email_get_schema() {
3352
  /* translators: do not remove {} brackets or translate its contents. */
3353
  'post_content' => __( "Your membership request for the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot; has been accepted.", 'buddypress' ),
3354
  /* translators: do not remove {} brackets or translate its contents. */
3355
- 'post_excerpt' => __( "Your membership request for the group &quot;{{group.name}}&quot; has been accepted.\n\nTo view the group, visit: {{{group.url}}}", 'buddypress' ),
3356
  ),
3357
  'groups-membership-request-rejected' => array(
3358
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3360,7 +3481,7 @@ function bp_email_get_schema() {
3360
  /* translators: do not remove {} brackets or translate its contents. */
3361
  'post_content' => __( "Your membership request for the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot; has been rejected.", 'buddypress' ),
3362
  /* translators: do not remove {} brackets or translate its contents. */
3363
- 'post_excerpt' => __( "Your membership request for the group &quot;{{group.name}}&quot; has been rejected.\n\nTo request membership again, visit: {{{group.url}}}", 'buddypress' ),
3364
  ),
3365
  );
3366
  }
@@ -3369,26 +3490,316 @@ function bp_email_get_schema() {
3369
  * Get a list of emails for populating email type taxonomy terms.
3370
  *
3371
  * @since 2.5.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3372
  *
3373
- * @return array
3374
  */
3375
- function bp_email_get_type_schema() {
3376
- return array(
3377
- 'activity-comment' => __( 'A member has replied to an activity update that the recipient posted.', 'buddypress' ),
3378
- 'activity-comment-author' => __( 'A member has replied to a comment on an activity update that the recipient posted.', 'buddypress' ),
3379
- 'activity-at-message' => __( 'Recipient was mentioned in an activity update.', 'buddypress' ),
3380
- 'groups-at-message' => __( 'Recipient was mentioned in a group activity update.', 'buddypress' ),
3381
- 'core-user-registration' => __( 'Recipient has registered for an account.', 'buddypress' ),
3382
- 'core-user-registration-with-blog' => __( 'Recipient has registered for an account and site.', 'buddypress' ),
3383
- 'friends-request' => __( 'A member has sent a friend request to the recipient.', 'buddypress' ),
3384
- 'friends-request-accepted' => __( 'Recipient has had a friend request accepted by a member.', 'buddypress' ),
3385
- 'groups-details-updated' => __( "A group's details were updated.", 'buddypress' ),
3386
- 'groups-invitation' => __( 'A member has sent a group invitation to the recipient.', 'buddypress' ),
3387
- 'groups-member-promoted' => __( "Recipient's status within a group has changed.", 'buddypress' ),
3388
- 'groups-membership-request' => __( 'A member has requested permission to join a group.', 'buddypress' ),
3389
- 'messages-unread' => __( 'Recipient has received a private message.', 'buddypress' ),
3390
- 'settings-verify-email-change' => __( 'Recipient has changed their email address.', 'buddypress' ),
3391
- 'groups-membership-request-accepted' => __( 'Recipient had requested to join a group, which was accepted.', 'buddypress' ),
3392
- 'groups-membership-request-rejected' => __( 'Recipient had requested to join a group, which was rejected.', 'buddypress' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3393
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3394
  }
108
  * your own awkward callback function for usort().
109
  *
110
  * @since 2.2.0
111
+ * @since 2.7.0 Added $preserve_keys parameter.
112
+ *
113
+ * @param array $items The items to be sorted. Its constituent items
114
+ * can be either associative arrays or objects.
115
+ * @param string|int $key The array index or property name to sort by.
116
+ * @param string $type Sort type. 'alpha' for alphabetical, 'num'
117
+ * for numeric. Default: 'alpha'.
118
+ * @param bool $preserve_keys Whether to keep the keys or not.
119
  *
 
 
 
120
  * @return array $items The sorted array.
121
  */
122
+ function bp_sort_by_key( $items, $key, $type = 'alpha', $preserve_keys = false ) {
123
+ $callback = function( $a, $b ) use ( $key, $type ) {
124
+ $values = array( 0 => false, 1 => false );
125
+ foreach ( func_get_args() as $indexi => $index ) {
126
+ if ( isset( $index->{$key} ) ) {
127
+ $values[ $indexi ] = $index->{$key};
128
+ } elseif ( isset( $index[ $key ] ) ) {
129
+ $values[ $indexi ] = $index[ $key ];
130
+ }
131
+ }
132
+
133
+ if ( isset( $values[0], $values[1] ) ) {
134
+ if ( 'num' === $type ) {
135
+ $cmp = $values[0] - $values[1];
136
+ } else {
137
+ $cmp = strcmp( $values[0], $values[1] );
138
+ }
139
+
140
+ if ( 0 > $cmp ) {
141
+ $retval = -1;
142
+ } elseif ( 0 < $cmp ) {
143
+ $retval = 1;
144
+ } else {
145
+ $retval = 0;
146
+ }
147
+ return $retval;
148
+ } else {
149
+ return 0;
150
+ }
151
+ };
152
+
153
+ if ( true === $preserve_keys ) {
154
+ uasort( $items, $callback );
155
+ } else {
156
+ usort( $items, $callback );
157
+ }
158
 
159
  return $items;
160
  }
445
  return (bool) apply_filters( 'bp_use_wp_admin_bar', $use_admin_bar );
446
  }
447
 
448
+
449
+ /**
450
+ * Return the parent forum ID for the Legacy Forums abstraction layer.
451
+ *
452
+ * @since 1.5.0
453
+ * @since 3.0.0 Supported for compatibility with bbPress 2.
454
+ *
455
+ * @return int Forum ID.
456
+ */
457
+ function bp_forums_parent_forum_id() {
458
+
459
+ /**
460
+ * Filters the parent forum ID for the bbPress abstraction layer.
461
+ *
462
+ * @since 1.5.0
463
+ *
464
+ * @param int BP_FORUMS_PARENT_FORUM_ID The Parent forum ID constant.
465
+ */
466
+ return apply_filters( 'bp_forums_parent_forum_id', BP_FORUMS_PARENT_FORUM_ID );
467
+ }
468
+
469
  /** Directory *****************************************************************/
470
 
471
  /**
488
  'notifications',
489
  );
490
 
 
 
 
 
 
 
491
  return $components;
492
  }
493
 
503
  * empty string if the list is not found.
504
  */
505
  function bp_core_get_directory_page_ids( $status = 'active' ) {
506
+ $page_ids = bp_get_option( 'bp-pages', array() );
507
 
508
+ // Loop through pages
509
+ foreach ( $page_ids as $component_name => $page_id ) {
 
 
 
 
510
 
511
+ // Ensure that empty indexes are unset. Should only matter in edge cases.
512
+ if ( empty( $component_name ) || empty( $page_id ) ) {
513
+ unset( $page_ids[ $component_name ] );
514
+ }
515
 
516
+ // Trashed pages should never appear in results.
517
+ if ( 'trash' == get_post_status( $page_id ) ) {
518
+ unset( $page_ids[ $component_name ] );
519
+ }
520
 
521
+ // 'register' and 'activate' do not have components, but should be whitelisted.
522
+ if ( in_array( $component_name, array( 'register', 'activate' ), true ) ) {
523
+ continue;
524
+ }
525
 
526
+ // Remove inactive component pages.
527
+ if ( ( 'active' === $status ) && ! bp_is_active( $component_name ) ) {
528
+ unset( $page_ids[ $component_name ] );
 
529
  }
530
  }
531
 
533
  * Filters the list of BP directory pages from the appropriate meta table.
534
  *
535
  * @since 1.5.0
536
+ * @since 2.9.0 Add $status parameter
537
  *
538
+ * @param array $page_ids Array of directory pages.
539
+ * @param string $status Page status to limit results to
540
  */
541
+ return (array) apply_filters( 'bp_core_get_directory_page_ids', $page_ids, $status );
542
  }
543
 
544
  /**
546
  *
547
  * @since 2.6.0
548
  *
549
+ * @param string|null $component The slug representing the component. Defaults to the current component.
550
+ * @return int|false The ID of the directory page associated with the component. False if none is found.
551
  */
552
  function bp_core_get_directory_page_id( $component = null ) {
553
  if ( ! $component ) {
678
 
679
  // Delete any existing pages.
680
  if ( 'delete' === $existing ) {
681
+ foreach ( $pages as $page_id ) {
682
  wp_delete_post( $page_id, true );
683
  }
684
 
685
  $pages = array();
686
  }
687
 
688
+ $page_titles = bp_core_get_directory_page_default_titles();
 
 
 
 
 
 
 
689
 
690
  $pages_to_create = array();
691
  foreach ( array_keys( $components ) as $component_name ) {
705
  }
706
 
707
  // No need for a Sites directory unless we're on multisite.
708
+ if ( ! is_multisite() && isset( $pages_to_create['blogs'] ) ) {
709
+ unset( $pages_to_create['blogs'] );
710
  }
711
 
712
  // Members must always have a page, no matter what.
741
  }
742
  }
743
 
744
+ /**
745
+ * Get the default page titles for BP directory pages.
746
+ *
747
+ * @since 2.7.0
748
+ *
749
+ * @return array
750
+ */
751
+ function bp_core_get_directory_page_default_titles() {
752
+ $page_default_titles = array(
753
+ 'activity' => _x( 'Activity', 'Page title for the Activity directory.', 'buddypress' ),
754
+ 'groups' => _x( 'Groups', 'Page title for the Groups directory.', 'buddypress' ),
755
+ 'blogs' => _x( 'Sites', 'Page title for the Sites directory.', 'buddypress' ),
756
+ 'members' => _x( 'Members', 'Page title for the Members directory.', 'buddypress' ),
757
+ 'activate' => _x( 'Activate', 'Page title for the user activation screen.', 'buddypress' ),
758
+ 'register' => _x( 'Register', 'Page title for the user registration screen.', 'buddypress' ),
759
+ );
760
+
761
+ /**
762
+ * Filters the default page titles array
763
+ *
764
+ * @since 2.7.0
765
+ *
766
+ * @param array $page_default_titles the array of default WP (post_title) titles.
767
+ */
768
+ return apply_filters( 'bp_core_get_directory_page_default_titles', $page_default_titles );
769
+ }
770
+
771
  /**
772
  * Remove the entry from bp_pages when the corresponding WP page is deleted.
773
  *
870
 
871
  // If there was no match, add a page for this root component.
872
  if ( empty( $match ) ) {
873
+ $add_root_items = $bp->add_root;
874
  $add_root_items[] = $slug;
875
  $bp->add_root = $add_root_items;
876
  }
904
  ) );
905
  }
906
 
907
+ $page_ids = array_merge( $new_page_ids, bp_core_get_directory_page_ids( 'all' ) );
908
  bp_core_update_directory_page_ids( $page_ids );
909
  }
910
 
925
  * Get the 'search' query argument for a given component.
926
  *
927
  * @since 2.4.0
928
+ * @since 2.7.0 The `$component` parameter was made optional, with the current component
929
+ * as the fallback value.
930
  *
931
+ * @param string|null $component Optional. Component name. Defaults to current component.
932
  * @return string|bool Query argument on success. False on failure.
933
  */
934
+ function bp_core_get_component_search_query_arg( $component = null ) {
935
+ if ( ! $component ) {
936
+ $component = bp_current_component();
937
+ }
938
+
939
  $query_arg = false;
940
  if ( isset( buddypress()->{$component}->search_query_arg ) ) {
941
  $query_arg = sanitize_title( buddypress()->{$component}->search_query_arg );
1037
  buddypress()->no_status_set = true;
1038
 
1039
  wp_safe_redirect( $location, $status );
1040
+
1041
+ // If PHPUnit is running, do not kill execution.
1042
+ if ( ! defined( 'BP_TESTS_DIR' ) ) {
1043
+ die;
1044
+ }
1045
  }
1046
 
1047
  /**
1343
  return apply_filters( 'bp_core_time_since', $output, $older_date, $newer_date );
1344
  }
1345
 
1346
+ /**
1347
+ * Output an ISO-8601 date from a date string.
1348
+ *
1349
+ * @since 2.7.0
1350
+ *
1351
+ * @param string String of date to convert. Timezone should be UTC before using this.
1352
+ * @return string|null
1353
+ */
1354
+ function bp_core_iso8601_date( $timestamp = '' ) {
1355
+ echo bp_core_get_iso8601_date( $timestamp );
1356
+ }
1357
+ /**
1358
+ * Return an ISO-8601 date from a date string.
1359
+ *
1360
+ * @since 2.7.0
1361
+ *
1362
+ * @param string String of date to convert. Timezone should be UTC before using this.
1363
+ * @return string
1364
+ */
1365
+ function bp_core_get_iso8601_date( $timestamp = '' ) {
1366
+ if ( ! $timestamp ) {
1367
+ return '';
1368
+ }
1369
+
1370
+ try {
1371
+ $date = new DateTime( $timestamp, new DateTimeZone( 'UTC' ) );
1372
+
1373
+ // Not a valid date, so return blank string.
1374
+ } catch( Exception $e ) {
1375
+ return '';
1376
+ }
1377
+
1378
+ return $date->format( DateTime::ISO8601 );
1379
+ }
1380
+
1381
  /** Messages ******************************************************************/
1382
 
1383
  /**
1508
  *
1509
  * usermeta table.
1510
  *
1511
+ * @return false|null Returns false if there is nothing to do.
1512
  */
1513
  function bp_core_record_activity() {
1514
 
1534
  }
1535
 
1536
  // Get current time.
1537
+ $current_time = bp_core_current_time( true, 'timestamp' );
1538
 
1539
  // Use this action to detect the very first activity for a given member.
1540
  if ( empty( $activity ) ) {
1552
  }
1553
 
1554
  // If it's been more than 5 minutes, record a newer last-activity time.
1555
+ if ( empty( $activity ) || ( $current_time >= strtotime( '+5 minutes', $activity ) ) ) {
1556
+ bp_update_user_last_activity( $user_id, date( 'Y-m-d H:i:s', $current_time ) );
1557
  }
1558
  }
1559
  add_action( 'wp_head', 'bp_core_record_activity' );
1748
  return apply_filters( 'bp_use_embed_in_activity_replies', !defined( 'BP_EMBED_DISABLE_ACTIVITY_REPLIES' ) || !BP_EMBED_DISABLE_ACTIVITY_REPLIES );
1749
  }
1750
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1751
  /**
1752
  * Are oembeds allowed in private messages?
1753
  *
1773
  *
1774
  * @since 2.6.0
1775
  *
1776
+ * @param string $content The content to check.
1777
+ * @param string|int $type The type to check. Can also use a bitmask. See the class constants in the
1778
  * BP_Media_Extractor class for more info.
1779
+ * @return false|array If media exists, will return array of media metadata. Else, boolean false.
1780
  */
1781
  function bp_core_extract_media_from_content( $content = '', $type = 'all' ) {
1782
  if ( is_string( $type ) ) {
2354
  $slug = bp_is_active( 'blogs' ) ? bp_get_blogs_root_slug() : '';
2355
  break;
2356
 
 
 
 
 
 
2357
  case 'groups':
2358
  $slug = bp_is_active( 'groups' ) ? bp_get_groups_root_slug() : '';
2359
  break;
2397
  return;
2398
  }
2399
 
2400
+ remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 );
2401
  }
2402
  add_action( 'bp_init', 'bp_remove_adjacent_posts_rel_link' );
2403
 
2457
  );
2458
 
2459
  $retired_components = array(
 
 
 
 
2460
  );
2461
 
2462
  $optional_components = array(
2488
  'title' => __( 'User Groups', 'buddypress' ),
2489
  'description' => __( 'Groups allow your users to organize themselves into specific public, private or hidden sections with separate activity streams and member listings.', 'buddypress' )
2490
  ),
 
 
 
 
2491
  'blogs' => array(
2492
  'title' => __( 'Site Tracking', 'buddypress' ),
2493
  'description' => __( 'Record activity for new posts and comments from your site.', 'buddypress' )
2778
  *
2779
  * @since 2.3.0
2780
  *
2781
+ * @return bool|array
2782
  */
2783
  function bp_upload_dir() {
2784
  $bp = buddypress();
3076
  * @param string|array|int|WP_User $to Either a email address, user ID, WP_User object,
3077
  * or an array containg the address and name.
3078
  * @param array $args {
3079
+ * Optional. Array of extra parameters.
3080
  *
3081
  * @type array $tokens Optional. Assocative arrays of string replacements for the email.
3082
  * }
3122
  $email->set_to( $to );
3123
  $email->set_tokens( $args['tokens'] );
3124
 
3125
+ /**
3126
+ * Gives access to an email before it is sent.
3127
+ *
3128
+ * @since 2.8.0
3129
+ *
3130
+ * @param BP_Email $email The email (object) about to be sent.
3131
+ * @param string $email_type Type of email being sent.
3132
+ * @param string|array|int|WP_User $to Either a email address, user ID, WP_User object,
3133
+ * or an array containg the address and name.
3134
+ * @param array $args {
3135
+ * Optional. Array of extra parameters.
3136
+ *
3137
+ * @type array $tokens Optional. Assocative arrays of string replacements for the email.
3138
+ * }
3139
+ */
3140
+ do_action_ref_array( 'bp_send_email', array( &$email, $email_type, $to, $args ) );
3141
+
3142
  $status = $email->validate();
3143
  if ( is_wp_error( $status ) ) {
3144
  return $status;
3228
  * Return email appearance settings.
3229
  *
3230
  * @since 2.5.0
3231
+ * @since 3.0.0 Added "direction" parameter for LTR/RTL email support, and
3232
+ * "link_text_color" to override that in the email body.
3233
  *
3234
  * @return array
3235
  */
3246
  'highlight_color' => '#D84800',
3247
  'header_text_color' => '#000000',
3248
  'header_text_size' => 30,
3249
+ 'direction' => is_rtl() ? 'right' : 'left',
3250
 
3251
  'footer_text' => sprintf(
3252
  /* translators: email disclaimer, e.g. "© 2016 Site Name". */
3256
  ),
3257
  );
3258
 
3259
+ $options = bp_parse_args(
3260
  bp_get_option( 'bp_email_options', array() ),
3261
  $default_args,
3262
  'email_appearance_settings'
3263
  );
3264
+
3265
+ // Link text colour defaults to the highlight colour.
3266
+ if ( ! isset( $options['link_text_color'] ) ) {
3267
+ $options['link_text_color'] = $options['highlight_color'];
3268
+ }
3269
+
3270
+ return $options;
3271
  }
3272
 
3273
  /**
3290
  * @param WP_Post $object WP_Post object.
3291
  */
3292
  return apply_filters( 'bp_email_get_template', array(
3293
+ "assets/emails/{$single}-{$object->post_name}.php",
3294
  "{$single}-{$object->post_name}.php",
3295
  "{$single}.php",
3296
  "assets/emails/{$single}.php",
3304
  *
3305
  * @since 2.5.0
3306
  *
3307
+ * @param string $text Text to replace tokens in.
3308
+ * @param array $tokens Token names and replacement values for the $text.
3309
  * @return string
3310
  */
3311
  function bp_core_replace_tokens_in_text( $text, $tokens ) {
3342
 
3343
  /**
3344
  * Get a list of emails for populating the email post type.
3345
+ *
3346
  * @since 2.5.1
3347
  *
3348
  * @return array
3388
  'post_content' => __( "Thanks for registering!\n\nTo complete the activation of your account, go to the following link: <a href=\"{{{activate.url}}}\">{{{activate.url}}}</a>", 'buddypress' ),
3389
  /* translators: do not remove {} brackets or translate its contents. */
3390
  'post_excerpt' => __( "Thanks for registering!\n\nTo complete the activation of your account, go to the following link: {{{activate.url}}}", 'buddypress' ),
3391
+ 'args' => array(
3392
+ 'multisite' => true,
3393
+ ),
3394
  ),
3395
  'core-user-registration-with-blog' => array(
3396
  /* translators: do not remove {} brackets or translate its contents. */
3399
  'post_content' => __( "Thanks for registering!\n\nTo complete the activation of your account and site, go to the following link: <a href=\"{{{activate-site.url}}}\">{{{activate-site.url}}}</a>.\n\nAfter you activate, you can visit your site at <a href=\"{{{user-site.url}}}\">{{{user-site.url}}}</a>.", 'buddypress' ),
3400
  /* translators: do not remove {} brackets or translate its contents. */
3401
  'post_excerpt' => __( "Thanks for registering!\n\nTo complete the activation of your account and site, go to the following link: {{{activate-site.url}}}\n\nAfter you activate, you can visit your site at {{{user-site.url}}}.", 'buddypress' ),
3402
+ 'args' => array(
3403
+ 'multisite' => true,
3404
+ ),
3405
  ),
3406
  'friends-request' => array(
3407
  /* translators: do not remove {} brackets or translate its contents. */
3425
  /* translators: do not remove {} brackets or translate its contents. */
3426
  'post_content' => __( "Group details for the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot; were updated:\n<blockquote>{{changed_text}}</blockquote>", 'buddypress' ),
3427
  /* translators: do not remove {} brackets or translate its contents. */
3428
+ 'post_excerpt' => __( "Group details for the group \"{{group.name}}\" were updated:\n\n{{changed_text}}\n\nTo view the group, visit: {{{group.url}}}", 'buddypress' ),
3429
  ),
3430
  'groups-invitation' => array(
3431
  /* translators: do not remove {} brackets or translate its contents. */
3433
  /* translators: do not remove {} brackets or translate its contents. */
3434
  'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the group: &quot;{{group.name}}&quot;.\n<a href=\"{{{invites.url}}}\">Go here to accept your invitation</a> or <a href=\"{{{group.url}}}\">visit the group</a> to learn more.", 'buddypress' ),
3435
  /* translators: do not remove {} brackets or translate its contents. */
3436
+ 'post_excerpt' => __( "{{inviter.name}} has invited you to join the group: \"{{group.name}}\".\n\nTo accept your invitation, visit: {{{invites.url}}}\n\nTo learn more about the group, visit: {{{group.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ),
3437
  ),
3438
  'groups-member-promoted' => array(
3439
  /* translators: do not remove {} brackets or translate its contents. */
3441
  /* translators: do not remove {} brackets or translate its contents. */
3442
  'post_content' => __( "You have been promoted to <b>{{promoted_to}}</b> in the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot;.", 'buddypress' ),
3443
  /* translators: do not remove {} brackets or translate its contents. */
3444
+ 'post_excerpt' => __( "You have been promoted to {{promoted_to}} in the group: \"{{group.name}}\".\n\nTo visit the group, go to: {{{group.url}}}", 'buddypress' ),
3445
  ),
3446
  'groups-membership-request' => array(
3447
  /* translators: do not remove {} brackets or translate its contents. */
3449
  /* translators: do not remove {} brackets or translate its contents. */
3450
  'post_content' => __( "<a href=\"{{{profile.url}}}\">{{requesting-user.name}}</a> wants to join the group &quot;{{group.name}}&quot;. As you are an administrator of this group, you must either accept or reject the membership request.\n\n<a href=\"{{{group-requests.url}}}\">Go here to manage this</a> and all other pending requests.", 'buddypress' ),
3451
  /* translators: do not remove {} brackets or translate its contents. */
3452
+ 'post_excerpt' => __( "{{requesting-user.name}} wants to join the group \"{{group.name}}\". As you are the administrator of this group, you must either accept or reject the membership request.\n\nTo manage this and all other pending requests, visit: {{{group-requests.url}}}\n\nTo view {{requesting-user.name}}'s profile, visit: {{{profile.url}}}", 'buddypress' ),
3453
  ),
3454
  'messages-unread' => array(
3455
  /* translators: do not remove {} brackets or translate its contents. */
3457
  /* translators: do not remove {} brackets or translate its contents. */
3458
  'post_content' => __( "{{sender.name}} sent you a new message: &quot;{{usersubject}}&quot;\n\n<blockquote>&quot;{{usermessage}}&quot;</blockquote>\n\n<a href=\"{{{message.url}}}\">Go to the discussion</a> to reply or catch up on the conversation.", 'buddypress' ),
3459
  /* translators: do not remove {} brackets or translate its contents. */
3460
+ 'post_excerpt' => __( "{{sender.name}} sent you a new message: \"{{usersubject}}\"\n\n\"{{usermessage}}\"\n\nGo to the discussion to reply or catch up on the conversation: {{{message.url}}}", 'buddypress' ),
3461
  ),
3462
  'settings-verify-email-change' => array(
3463
  /* translators: do not remove {} brackets or translate its contents. */
3473
  /* translators: do not remove {} brackets or translate its contents. */
3474
  'post_content' => __( "Your membership request for the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot; has been accepted.", 'buddypress' ),
3475
  /* translators: do not remove {} brackets or translate its contents. */
3476
+ 'post_excerpt' => __( "Your membership request for the group \"{{group.name}}\" has been accepted.\n\nTo view the group, visit: {{{group.url}}}", 'buddypress' ),
3477
  ),
3478
  'groups-membership-request-rejected' => array(
3479
  /* translators: do not remove {} brackets or translate its contents. */
3481
  /* translators: do not remove {} brackets or translate its contents. */
3482
  'post_content' => __( "Your membership request for the group &quot;<a href=\"{{{group.url}}}\">{{group.name}}</a>&quot; has been rejected.", 'buddypress' ),
3483
  /* translators: do not remove {} brackets or translate its contents. */
3484
+ 'post_excerpt' => __( "Your membership request for the group \"{{group.name}}\" has been rejected.\n\nTo request membership again, visit: {{{group.url}}}", 'buddypress' ),
3485
  ),
3486
  );
3487
  }
3490
  * Get a list of emails for populating email type taxonomy terms.
3491
  *
3492
  * @since 2.5.1
3493
+ * @since 2.7.0 $field argument added.
3494
+ *
3495
+ * @param string $field Optional; defaults to "description" for backwards compatibility. Other values: "all".
3496
+ * @return array {
3497
+ * The array of email types and their schema.
3498
+ *
3499
+ * @type string $description The description of the action which causes this to trigger.
3500
+ * @type array $unsubscribe {
3501
+ * Replacing this with false indicates that a user cannot unsubscribe from this type.
3502
+ *
3503
+ * @type string $meta_key The meta_key used to toggle the email setting for this notification.
3504
+ * @type string $message The message shown when the user has successfully unsubscribed.
3505
+ * }
3506
+ */
3507
+ function bp_email_get_type_schema( $field = 'description' ) {
3508
+ $activity_comment = array(
3509
+ 'description' => __( 'A member has replied to an activity update that the recipient posted.', 'buddypress' ),
3510
+ 'unsubscribe' => array(
3511
+ 'meta_key' => 'notification_activity_new_reply',
3512
+ 'message' => __( 'You will no longer receive emails when someone replies to an update or comment you posted.', 'buddypress' ),
3513
+ ),
3514
+ );
3515
+
3516
+ $activity_comment_author = array(
3517
+ 'description' => __( 'A member has replied to a comment on an activity update that the recipient posted.', 'buddypress' ),
3518
+ 'unsubscribe' => array(
3519
+ 'meta_key' => 'notification_activity_new_reply',
3520
+ 'message' => __( 'You will no longer receive emails when someone replies to an update or comment you posted.', 'buddypress' ),
3521
+ ),
3522
+ );
3523
+
3524
+ $activity_at_message = array(
3525
+ 'description' => __( 'Recipient was mentioned in an activity update.', 'buddypress' ),
3526
+ 'unsubscribe' => array(
3527
+ 'meta_key' => 'notification_activity_new_mention',
3528
+ 'message' => __( 'You will no longer receive emails when someone mentions you in an update.', 'buddypress' ),
3529
+ ),
3530
+ );
3531
+
3532
+ $groups_at_message = array(
3533
+ 'description' => __( 'Recipient was mentioned in a group activity update.', 'buddypress' ),
3534
+ 'unsubscribe' => array(
3535
+ 'meta_key' => 'notification_activity_new_mention',
3536
+ 'message' => __( 'You will no longer receive emails when someone mentions you in an update.', 'buddypress' ),
3537
+ ),
3538
+ );
3539
+
3540
+ $core_user_registration = array(
3541
+ 'description' => __( 'Recipient has registered for an account.', 'buddypress' ),
3542
+ 'unsubscribe' => false,
3543
+ );
3544
+
3545
+ $core_user_registration_with_blog = array(
3546
+ 'description' => __( 'Recipient has registered for an account and site.', 'buddypress' ),
3547
+ 'unsubscribe' => false,
3548
+ );
3549
+
3550
+ $friends_request = array(
3551
+ 'description' => __( 'A member has sent a friend request to the recipient.', 'buddypress' ),
3552
+ 'unsubscribe' => array(
3553
+ 'meta_key' => 'notification_friends_friendship_request',
3554
+ 'message' => __( 'You will no longer receive emails when someone sends you a friend request.', 'buddypress' ),
3555
+ ),
3556
+ );
3557
+
3558
+ $friends_request_accepted = array(
3559
+ 'description' => __( 'Recipient has had a friend request accepted by a member.', 'buddypress' ),
3560
+ 'unsubscribe' => array(
3561
+ 'meta_key' => 'notification_friends_friendship_accepted',
3562
+ 'message' => __( 'You will no longer receive emails when someone accepts your friendship request.', 'buddypress' ),
3563
+ ),
3564
+ );
3565
+
3566
+ $groups_details_updated = array(
3567
+ 'description' => __( "A group's details were updated.", 'buddypress' ),
3568
+ 'unsubscribe' => array(
3569
+ 'meta_key' => 'notification_groups_group_updated',
3570
+ 'message' => __( 'You will no longer receive emails when one of your groups is updated.', 'buddypress' ),
3571
+ ),
3572
+ );
3573
+
3574
+ $groups_invitation = array(
3575
+ 'description' => __( 'A member has sent a group invitation to the recipient.', 'buddypress' ),
3576
+ 'unsubscribe' => array(
3577
+ 'meta_key' => 'notification_groups_invite',
3578
+ 'message' => __( 'You will no longer receive emails when you are invited to join a group.', 'buddypress' ),
3579
+ ),
3580
+ );
3581
+
3582
+ $groups_member_promoted = array(
3583
+ 'description' => __( "Recipient's status within a group has changed.", 'buddypress' ),
3584
+ 'unsubscribe' => array(
3585
+ 'meta_key' => 'notification_groups_admin_promotion',
3586
+ 'message' => __( 'You will no longer receive emails when you have been promoted in a group.', 'buddypress' ),
3587
+ ),
3588
+ );
3589
+
3590
+ $groups_membership_request = array(
3591
+ 'description' => __( 'A member has requested permission to join a group.', 'buddypress' ),
3592
+ 'unsubscribe' => array(
3593
+ 'meta_key' => 'notification_groups_membership_request',
3594
+ 'message' => __( 'You will no longer receive emails when someone requests to be a member of your group.', 'buddypress' ),
3595
+ ),
3596
+ );
3597
+
3598
+ $messages_unread = array(
3599
+ 'description' => __( 'Recipient has received a private message.', 'buddypress' ),
3600
+ 'unsubscribe' => array(
3601
+ 'meta_key' => 'notification_messages_new_message',
3602
+ 'message' => __( 'You will no longer receive emails when someone sends you a message.', 'buddypress' ),
3603
+ ),
3604
+ );
3605
+
3606
+ $settings_verify_email_change = array(
3607
+ 'description' => __( 'Recipient has changed their email address.', 'buddypress' ),
3608
+ 'unsubscribe' => false,
3609
+ );
3610
+
3611
+ $groups_membership_request_accepted = array(
3612
+ 'description' => __( 'Recipient had requested to join a group, which was accepted.', 'buddypress' ),
3613
+ 'unsubscribe' => array(
3614
+ 'meta_key' => 'notification_membership_request_completed',
3615
+ 'message' => __( 'You will no longer receive emails when your request to join a group has been accepted or denied.', 'buddypress' ),
3616
+ ),
3617
+ );
3618
+
3619
+ $groups_membership_request_rejected = array(
3620
+ 'description' => __( 'Recipient had requested to join a group, which was rejected.', 'buddypress' ),
3621
+ 'unsubscribe' => array(
3622
+ 'meta_key' => 'notification_membership_request_completed',
3623
+ 'message' => __( 'You will no longer receive emails when your request to join a group has been accepted or denied.', 'buddypress' ),
3624
+ ),
3625
+ );
3626
+
3627
+ $types = array(
3628
+ 'activity-comment' => $activity_comment,
3629
+ 'activity-comment-author' => $activity_comment_author,
3630
+ 'activity-at-message' => $activity_at_message,
3631
+ 'groups-at-message' => $groups_at_message,
3632
+ 'core-user-registration' => $core_user_registration,
3633
+ 'core-user-registration-with-blog' => $core_user_registration_with_blog,
3634
+ 'friends-request' => $friends_request,
3635
+ 'friends-request-accepted' => $friends_request_accepted,
3636
+ 'groups-details-updated' => $groups_details_updated,
3637
+ 'groups-invitation' => $groups_invitation,
3638
+ 'groups-member-promoted' => $groups_member_promoted,
3639
+ 'groups-membership-request' => $groups_membership_request,
3640
+ 'messages-unread' => $messages_unread,
3641
+ 'settings-verify-email-change' => $settings_verify_email_change,
3642
+ 'groups-membership-request-accepted' => $groups_membership_request_accepted,
3643
+ 'groups-membership-request-rejected' => $groups_membership_request_rejected,
3644
+ );
3645
+
3646
+ if ( $field !== 'all' ) {
3647
+ return wp_list_pluck( $types, $field );
3648
+ } else {
3649
+ return $types;
3650
+ }
3651
+ }
3652
+
3653
+ /**
3654
+ * Handles unsubscribing user from notification emails.
3655
  *
3656
+ * @since 2.7.0
3657
  */
3658
+ function bp_email_unsubscribe_handler() {
3659
+ $emails = bp_email_get_unsubscribe_type_schema();
3660
+ $raw_email_type = ! empty( $_GET['nt'] ) ? $_GET['nt'] : '';
3661
+ $raw_hash = ! empty( $_GET['nh'] ) ? $_GET['nh'] : '';
3662
+ $raw_user_id = ! empty( $_GET['uid'] ) ? absint( $_GET['uid'] ) : 0;
3663
+ $new_hash = hash_hmac( 'sha1', "{$raw_email_type}:{$raw_user_id}", bp_email_get_salt() );
3664
+
3665
+ // Check required values.
3666
+ if ( ! $raw_user_id || ! $raw_email_type || ! $raw_hash || ! array_key_exists( $raw_email_type, $emails ) ) {
3667
+ $redirect_to = wp_login_url();
3668
+ $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3669
+ $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' );
3670
+
3671
+ // Check valid hash.
3672
+ } elseif ( ! hash_equals( $new_hash, $raw_hash ) ) {
3673
+ $redirect_to = wp_login_url();
3674
+ $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3675
+ $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' );
3676
+
3677
+ // Don't let authenticated users unsubscribe other users' email notifications.
3678
+ } elseif ( is_user_logged_in() && get_current_user_id() !== $raw_user_id ) {
3679
+ $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3680
+ $unsub_msg = __( 'Please go to your notifications settings to unsubscribe from emails.', 'buddypress' );
3681
+
3682
+ if ( bp_is_active( 'settings' ) ) {
3683
+ $redirect_to = sprintf(
3684
+ '%s%s/notifications/',
3685
+ bp_core_get_user_domain( get_current_user_id() ),
3686
+ bp_get_settings_slug()
3687
+ );
3688
+ } else {
3689
+ $redirect_to = bp_core_get_user_domain( get_current_user_id() );
3690
+ }
3691
+
3692
+ } else {
3693
+ if ( bp_is_active( 'settings' ) ) {
3694
+ $redirect_to = sprintf(
3695
+ '%s%s/notifications/',
3696
+ bp_core_get_user_domain( $raw_user_id ),
3697
+ bp_get_settings_slug()
3698
+ );
3699
+ } else {
3700
+ $redirect_to = bp_core_get_user_domain( $raw_user_id );
3701
+ }
3702
+
3703
+ // Unsubscribe.
3704
+ $meta_key = $emails[ $raw_email_type ]['unsubscribe']['meta_key'];
3705
+ bp_update_user_meta( $raw_user_id, $meta_key, 'no' );
3706
+
3707
+ $result_msg = $emails[ $raw_email_type ]['unsubscribe']['message'];
3708
+ $unsub_msg = __( 'You can change this or any other email notification preferences in your email settings.', 'buddypress' );
3709
+ }
3710
+
3711
+ $message = sprintf(
3712
+ '%1$s <a href="%2$s">%3$s</a>',
3713
+ $result_msg,
3714
+ esc_url( $redirect_to ),
3715
+ esc_html( $unsub_msg )
3716
+ );
3717
+
3718
+ bp_core_add_message( $message );
3719
+ bp_core_redirect( bp_core_get_user_domain( $raw_user_id ) );
3720
+
3721
+ exit;
3722
+ }
3723
+
3724
+ /**
3725
+ * Creates unsubscribe link for notification emails.
3726
+ *
3727
+ * @since 2.7.0
3728
+ *
3729
+ * @param string $redirect_to The URL to which the unsubscribe query string is appended.
3730
+ * @param array $args {
3731
+ * Used to build unsubscribe query string.
3732
+ *
3733
+ * @type string $notification_type Which notification type is being sent.
3734
+ * @type string $user_id The ID of the user to whom the notification is sent.
3735
+ * @type string $redirect_to Optional. The url to which the user will be redirected. Default is the activity directory.
3736
+ * }
3737
+ * @return string The unsubscribe link.
3738
+ */
3739
+ function bp_email_get_unsubscribe_link( $args ) {
3740
+ $emails = bp_email_get_unsubscribe_type_schema();
3741
+
3742
+ if ( empty( $args['notification_type'] ) || ! array_key_exists( $args['notification_type'], $emails ) ) {
3743
+ return wp_login_url();
3744
+ }
3745
+
3746
+ $email_type = $args['notification_type'];
3747
+ $redirect_to = ! empty( $args['redirect_to'] ) ? $args['redirect_to'] : site_url();
3748
+ $user_id = (int) $args['user_id'];
3749
+
3750
+ // Bail out if the activity type is not un-unsubscribable.
3751
+ if ( empty( $emails[ $email_type ]['unsubscribe'] ) ) {
3752
+ return '';
3753
+ }
3754
+
3755
+ $link = add_query_arg(
3756
+ array(
3757
+ 'action' => 'unsubscribe',
3758
+ 'nh' => hash_hmac( 'sha1', "{$email_type}:{$user_id}", bp_email_get_salt() ),
3759
+ 'nt' => $args['notification_type'],
3760
+ 'uid' => $user_id,
3761
+ ),
3762
+ $redirect_to
3763
  );
3764
+
3765
+ /**
3766
+ * Filters the unsubscribe link.
3767
+ *
3768
+ * @since 2.7.0
3769
+ */
3770
+ return apply_filters( 'bp_email_get_link', $link, $redirect_to, $args );
3771
+ }
3772
+
3773
+ /**
3774
+ * Get a persistent salt for email unsubscribe links.
3775
+ *
3776
+ * @since 2.7.0
3777
+ *
3778
+ * @return string|null Returns null if value isn't set, otherwise string.
3779
+ */
3780
+ function bp_email_get_salt() {
3781
+ return bp_get_option( 'bp-emails-unsubscribe-salt', null );
3782
+ }
3783
+
3784
+ /**
3785
+ * Get a list of emails for use in our unsubscribe functions.
3786
+ *
3787
+ * @since 2.8.0
3788
+ *
3789
+ * @see https://buddypress.trac.wordpress.org/ticket/7431
3790
+ *
3791
+ * @return array The array of email types and their schema.
3792
+ */
3793
+ function bp_email_get_unsubscribe_type_schema() {
3794
+ $emails = bp_email_get_type_schema( 'all' );
3795
+
3796
+ /**
3797
+ * Filters the return of `bp_email_get_type_schema( 'all' )` for use with
3798
+ * our unsubscribe functionality.
3799
+ *
3800
+ * @since 2.8.0
3801
+ *
3802
+ * @param array $emails The array of email types and their schema.
3803
+ */
3804
+ return (array) apply_filters( 'bp_email_get_unsubscribe_type_schema', $emails );
3805
  }
bp-core/bp-core-loader.php CHANGED
@@ -12,17 +12,10 @@
12
  // Exit if accessed directly.
13
  defined( 'ABSPATH' ) || exit;
14
 
15
- if ( ! buddypress()->do_autoload ) {
16
- require dirname( __FILE__ ) . '/classes/class-bp-component.php';
17
- require dirname( __FILE__ ) . '/classes/class-bp-core.php';
18
- }
19
-
20
  /**
21
- * Set up the BuddyPress Core component.
22
  *
23
  * @since 1.6.0
24
- *
25
- * @global BuddyPress $bp BuddyPress global settings object.
26
  */
27
  function bp_setup_core() {
28
  buddypress()->core = new BP_Core();
12
  // Exit if accessed directly.
13
  defined( 'ABSPATH' ) || exit;
14
 
 
 
 
 
 
15
  /**
16
+ * Set up the bp-core component.
17
  *
18
  * @since 1.6.0
 
 
19
  */
20
  function bp_setup_core() {
21
  buddypress()->core = new BP_Core();
bp-core/bp-core-moderation.php CHANGED
@@ -53,7 +53,7 @@ function bp_core_check_for_flood( $user_id = 0 ) {
53
  * @param string $title The title of the content.
54
  * @param string $content The content being posted.
55
  * @param string $error_type The error type to return. Either 'bool' or 'wp_error'.
56
- * @return bool True if test is passed, false if fail.
57
  */
58
  function bp_core_check_for_moderation( $user_id = 0, $title = '', $content = '', $error_type = 'bool' ) {
59
 
@@ -132,7 +132,7 @@ function bp_core_check_for_moderation( $user_id = 0, $title = '', $content = '',
132
  if ( 'bool' === $error_type ) {
133
  return false;
134
  } else {
135
- return new WP_Error( 'bp_moderation_too_many_links', __( 'You have inputted too many links', 'buddypress' ) );
136
  }
137
  }
138
  }
@@ -173,7 +173,7 @@ function bp_core_check_for_moderation( $user_id = 0, $title = '', $content = '',
173
  if ( 'bool' === $error_type ) {
174
  return false;
175
  } else {
176
- return new WP_Error( 'bp_moderation_word_match', _x( 'You have inputted an inappropriate word.', 'Comment moderation', 'buddypress' ) );
177
  }
178
  }
179
  }
@@ -196,7 +196,7 @@ function bp_core_check_for_moderation( $user_id = 0, $title = '', $content = '',
196
  * @param string $title The title of the content.
197
  * @param string $content The content being posted.
198
  * @param string $error_type The error type to return. Either 'bool' or 'wp_error'.
199
- * @return bool True if test is passed, false if fail.
200
  */
201
  function bp_core_check_for_blacklist( $user_id = 0, $title = '', $content = '', $error_type = 'bool' ) {
202
 
@@ -286,7 +286,7 @@ function bp_core_check_for_blacklist( $user_id = 0, $title = '', $content = '',
286
  if ( 'bool' === $error_type ) {
287
  return false;
288
  } else {
289
- return new WP_Error( 'bp_moderation_blacklist_match', _x( 'You have inputted an inappropriate word.', 'Comment blacklist', 'buddypress' ) );
290
  }
291
  }
292
  }
53
  * @param string $title The title of the content.
54
  * @param string $content The content being posted.
55
  * @param string $error_type The error type to return. Either 'bool' or 'wp_error'.
56
+ * @return bool|WP_Error True if test is passed, false if fail.
57
  */
58
  function bp_core_check_for_moderation( $user_id = 0, $title = '', $content = '', $error_type = 'bool' ) {
59
 
132
  if ( 'bool' === $error_type ) {
133
  return false;
134
  } else {
135
+ return new WP_Error( 'bp_moderation_too_many_links', __( 'You have posted too many links', 'buddypress' ) );
136
  }
137
  }
138
  }
173
  if ( 'bool' === $error_type ) {
174
  return false;
175
  } else {
176
+ return new WP_Error( 'bp_moderation_word_match', _x( 'You have posted an inappropriate word.', 'Comment moderation', 'buddypress' ) );
177
  }
178
  }
179
  }
196
  * @param string $title The title of the content.
197
  * @param string $content The content being posted.
198
  * @param string $error_type The error type to return. Either 'bool' or 'wp_error'.
199
+ * @return bool|WP_Error True if test is passed, false if fail.
200
  */
201
  function bp_core_check_for_blacklist( $user_id = 0, $title = '', $content = '', $error_type = 'bool' ) {
202
 
286
  if ( 'bool' === $error_type ) {
287
  return false;
288
  } else {
289
+ return new WP_Error( 'bp_moderation_blacklist_match', _x( 'You have posted an inappropriate word.', 'Comment blacklist', 'buddypress' ) );
290
  }
291
  }
292
  }
bp-core/bp-core-options.php CHANGED
@@ -13,6 +13,9 @@ defined( 'ABSPATH' ) || exit;
13
  /**
14
  * Get the default site options and their values.
15
  *
 
 
 
16
  * @since 1.6.0
17
  *
18
  * @return array Filtered option names and values.
@@ -26,11 +29,6 @@ function bp_get_default_options() {
26
 
27
  'bp-deactivated-components' => array(),
28
 
29
- /* bbPress ***********************************************************/
30
-
31
- // Legacy bbPress config location.
32
- 'bb-config-location' => ABSPATH . 'bb-config.php',
33
-
34
  /* XProfile **********************************************************/
35
 
36
  // Base profile groups name.
@@ -67,11 +65,14 @@ function bp_get_default_options() {
67
  // Allow users to delete their own accounts.
68
  'bp-disable-account-deletion' => false,
69
 
70
- // Allow comments on blog and forum activity items.
71
  'bp-disable-blogforum-comments' => true,
72
 
73
  // The ID for the current theme package.
74
- '_bp_theme_package_id' => 'legacy',
 
 
 
75
 
76
  /* Groups ************************************************************/
77
 
@@ -94,11 +95,14 @@ function bp_get_default_options() {
94
  // Force the BuddyBar.
95
  '_bp_force_buddybar' => false,
96
 
97
- /* Legacy theme *********************************************/
98
 
99
- // Whether to register the bp-default themes directory.
100
  '_bp_retain_bp_default' => false,
101
 
 
 
 
102
  /* Widgets **************************************************/
103
  'widget_bp_core_login_widget' => false,
104
  'widget_bp_core_members_widget' => false,
@@ -125,7 +129,6 @@ function bp_get_default_options() {
125
  * Non-destructive, so existing settings will not be overridden.
126
  *
127
  * @since 1.6.0
128
- *
129
  */
130
  function bp_add_options() {
131
 
@@ -156,7 +159,6 @@ function bp_add_options() {
156
  * Currently unused.
157
  *
158
  * @since 1.6.0
159
- *
160
  */
161
  function bp_delete_options() {
162
 
@@ -181,10 +183,7 @@ function bp_delete_options() {
181
  /**
182
  * Add filters to each BP option, allowing them to be overloaded from inside the $bp->options array.
183
  *
184
- * Currently unused.
185
- *
186
  * @since 1.6.0
187
- *
188
  */
189
  function bp_setup_option_filters() {
190
 
@@ -209,8 +208,6 @@ function bp_setup_option_filters() {
209
  /**
210
  * Filter default options and allow them to be overloaded from inside the $bp->options array.
211
  *
212
- * Currently unused.
213
- *
214
  * @since 1.6.0
215
  *
216
  * @param bool $value Optional. Default value false.
@@ -219,11 +216,8 @@ function bp_setup_option_filters() {
219
  function bp_pre_get_option( $value = false ) {
220
  $bp = buddypress();
221
 
222
- // Get the name of the current filter so we can manipulate it.
223
- $filter = current_filter();
224
-
225
  // Remove the filter prefix.
226
- $option = str_replace( 'pre_option_', '', $filter );
227
 
228
  // Check the options global for preset value.
229
  if ( ! empty( $bp->options[ $option ] ) ) {
@@ -242,7 +236,7 @@ function bp_pre_get_option( $value = false ) {
242
  *
243
  * The 'bp_get_option' filter is primarily for backward-compatibility.
244
  *
245
- * @since 1.2.0
246
  *
247
  * @param string $option_name The option to be retrieved.
248
  * @param string $default Optional. Default value to be returned if the option
@@ -255,7 +249,7 @@ function bp_get_option( $option_name, $default = '' ) {
255
  /**
256
  * Filters the option value for the requested option.
257
  *
258
- * @since 1.2.0
259
  *
260
  * @param mixed $value The value for the option.
261
  */
@@ -288,7 +282,7 @@ function bp_add_option( $option_name, $value ) {
288
  * @since 1.5.0
289
  *
290
  * @param string $option_name The option key to be set.
291
- * @param string $value The value to be set.
292
  * @return bool True on success, false on failure.
293
  */
294
  function bp_update_option( $option_name, $value ) {
@@ -411,61 +405,16 @@ function bp_core_get_root_options() {
411
  $root_blog_options_meta = array_merge( $root_blog_options_meta, $network_options_meta );
412
  }
413
 
414
- // Missing some options, so do some one-time fixing.
415
- if ( empty( $root_blog_options_meta ) || ( count( $root_blog_options_meta ) < count( $root_blog_option_keys ) ) ) {
416
-
417
- // Get a list of the keys that are already populated.
418
- $existing_options = array();
419
- foreach( $root_blog_options_meta as $already_option ) {
420
- $existing_options[$already_option->name] = $already_option->value;
421
- }
422
-
423
- // Unset the query - We'll be resetting it soon.
424
- unset( $root_blog_options_meta );
425
-
426
- // Loop through options.
427
- foreach ( $root_blog_options as $old_meta_key => $old_meta_default ) {
428
-
429
- if ( isset( $existing_options[$old_meta_key] ) ) {
430
- continue;
431
- }
432
-
433
- // Get old site option.
434
- if ( is_multisite() ) {
435
- $old_meta_value = get_site_option( $old_meta_key );
436
- }
437
-
438
- // No site option so look in root blog.
439
- if ( empty( $old_meta_value ) ) {
440
- $old_meta_value = bp_get_option( $old_meta_key, $old_meta_default );
441
- }
442
-
443
- // Update the root blog option.
444
- bp_update_option( $old_meta_key, $old_meta_value );
445
-
446
- // Update the global array.
447
- $root_blog_options_meta[$old_meta_key] = $old_meta_value;
448
-
449
- // Clear out the value for the next time around.
450
- unset( $old_meta_value );
451
- }
452
-
453
- $root_blog_options_meta = array_merge( $root_blog_options_meta, $existing_options );
454
- unset( $existing_options );
455
-
456
- // We're all matched up.
457
- } else {
458
- // Loop through our results and make them usable.
459
- foreach ( $root_blog_options_meta as $root_blog_option ) {
460
- $root_blog_options[$root_blog_option->name] = $root_blog_option->value;
461
- }
462
 
463
- // Copy the options no the return val.
464
- $root_blog_options_meta = $root_blog_options;
465
 
466
- // Clean up our temporary copy.
467
- unset( $root_blog_options );
468
- }
469
 
470
  wp_cache_set( 'root_blog_options', $root_blog_options_meta, 'bp' );
471
  }
@@ -489,7 +438,7 @@ function bp_core_get_root_options() {
489
  *
490
  * @since 2.3.0
491
  *
492
- * @param string $option Name of the option key.
493
  * @return mixed Value, if found.
494
  */
495
  function bp_core_get_root_option( $option ) {
@@ -672,7 +621,7 @@ function bp_disable_account_deletion( $default = false ) {
672
  }
673
 
674
  /**
675
- * Are blog and forum activity stream comments disabled?
676
  *
677
  * @since 1.6.0
678
  *
@@ -739,58 +688,6 @@ function bp_force_buddybar( $default = true ) {
739
  return (bool) apply_filters( 'bp_force_buddybar', (bool) bp_get_option( '_bp_force_buddybar', $default ) );
740
  }
741
 
742
- /**
743
- * Output the group forums root parent forum id.
744
- *
745
- * @since 1.6.0
746
- *
747
- * @param bool|string $default Optional. Default: '0'.
748
- */
749
- function bp_group_forums_root_id( $default = '0' ) {
750
- echo bp_get_group_forums_root_id( $default );
751
- }
752
- /**
753
- * Return the group forums root parent forum id.
754
- *
755
- * @since 1.6.0
756
- *
757
- *
758
- * @param bool|string $default Optional. Default: '0'.
759
- * @return int The ID of the group forums root forum.
760
- */
761
- function bp_get_group_forums_root_id( $default = '0' ) {
762
-
763
- /**
764
- * Filters the group forums root parent forum id.
765
- *
766
- * @since 1.6.0
767
- *
768
- * @param int $value The group forums root parent forum id.
769
- */
770
- return (int) apply_filters( 'bp_get_group_forums_root_id', (int) bp_get_option( '_bp_group_forums_root_id', $default ) );
771
- }
772
-
773
- /**
774
- * Check whether BuddyPress Group Forums are enabled.
775
- *
776
- * @since 1.6.0
777
- *
778
- * @param bool $default Optional. Fallback value if not found in the database.
779
- * Default: true.
780
- * @return bool True if group forums are active, otherwise false.
781
- */
782
- function bp_is_group_forums_active( $default = true ) {
783
-
784
- /**
785
- * Filters whether or not BuddyPress Group Forums are enabled.
786
- *
787
- * @since 1.6.0
788
- *
789
- * @param bool $value Whether or not BuddyPress Group Forums are enabled.
790
- */
791
- return (bool) apply_filters( 'bp_is_group_forums_active', (bool) bp_get_option( '_bp_enable_group_forums', $default ) );
792
- }
793
-
794
  /**
795
  * Check whether Akismet is enabled.
796
  *
13
  /**
14
  * Get the default site options and their values.
15
  *
16
+ * Default values should not be set by calls to `get_option()` or `get_site_option()` due to
17
+ * these causing load order problems with `bp_core_clear_root_options_cache()`; see #BP7227.
18
+ *
19
  * @since 1.6.0
20
  *
21
  * @return array Filtered option names and values.
29
 
30
  'bp-deactivated-components' => array(),
31
 
 
 
 
 
 
32
  /* XProfile **********************************************************/
33
 
34
  // Base profile groups name.
65
  // Allow users to delete their own accounts.
66
  'bp-disable-account-deletion' => false,
67
 
68
+ // Allow comments on post and comment activity items.
69
  'bp-disable-blogforum-comments' => true,
70
 
71
  // The ID for the current theme package.
72
+ '_bp_theme_package_id' => 'nouveau',
73
+
74
+ // Email unsubscribe salt.
75
+ 'bp-emails-unsubscribe-salt' => '',
76
 
77
  /* Groups ************************************************************/
78
 
95
  // Force the BuddyBar.
96
  '_bp_force_buddybar' => false,
97
 
98
+ /* Legacy *********************************************/
99
 
100
+ // Do not register the bp-default themes directory.
101
  '_bp_retain_bp_default' => false,
102
 
103
+ // Ignore deprecated code.
104
+ '_bp_ignore_deprecated_code' => true,
105
+
106
  /* Widgets **************************************************/
107
  'widget_bp_core_login_widget' => false,
108
  'widget_bp_core_members_widget' => false,
129
  * Non-destructive, so existing settings will not be overridden.
130
  *
131
  * @since 1.6.0
 
132
  */
133
  function bp_add_options() {
134
 
159
  * Currently unused.
160
  *
161
  * @since 1.6.0
 
162
  */
163
  function bp_delete_options() {
164
 
183
  /**
184
  * Add filters to each BP option, allowing them to be overloaded from inside the $bp->options array.
185
  *
 
 
186
  * @since 1.6.0
 
187
  */
188
  function bp_setup_option_filters() {
189
 
208
  /**
209
  * Filter default options and allow them to be overloaded from inside the $bp->options array.
210
  *
 
 
211
  * @since 1.6.0
212
  *
213
  * @param bool $value Optional. Default value false.
216
  function bp_pre_get_option( $value = false ) {
217
  $bp = buddypress();
218
 
 
 
 
219
  // Remove the filter prefix.
220
+ $option = str_replace( 'pre_option_', '', current_filter() );
221
 
222
  // Check the options global for preset value.
223
  if ( ! empty( $bp->options[ $option ] ) ) {
236
  *
237
  * The 'bp_get_option' filter is primarily for backward-compatibility.
238
  *
239
+ * @since 1.5.0
240
  *
241
  * @param string $option_name The option to be retrieved.
242
  * @param string $default Optional. Default value to be returned if the option
249
  /**
250
  * Filters the option value for the requested option.
251
  *
252
+ * @since 1.5.0
253
  *
254
  * @param mixed $value The value for the option.
255
  */
282
  * @since 1.5.0
283
  *
284
  * @param string $option_name The option key to be set.
285
+ * @param mixed $value The value to be set.
286
  * @return bool True on success, false on failure.
287
  */
288
  function bp_update_option( $option_name, $value ) {
405
  $root_blog_options_meta = array_merge( $root_blog_options_meta, $network_options_meta );
406
  }
407
 
408
+ // Loop through our results and make them usable.
409
+ foreach ( $root_blog_options_meta as $root_blog_option ) {
410
+ $root_blog_options[$root_blog_option->name] = $root_blog_option->value;
411
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
 
413
+ // Copy the options no the return val.
414
+ $root_blog_options_meta = $root_blog_options;
415
 
416
+ // Clean up our temporary copy.
417
+ unset( $root_blog_options );
 
418
 
419
  wp_cache_set( 'root_blog_options', $root_blog_options_meta, 'bp' );
420
  }
438
  *
439
  * @since 2.3.0
440
  *
441
+ * @param string $option Name of the option key.
442
  * @return mixed Value, if found.
443
  */
444
  function bp_core_get_root_option( $option ) {
621
  }
622
 
623
  /**
624
+ * Are post/comment activity stream comments disabled?
625
  *
626
  * @since 1.6.0
627
  *
688
  return (bool) apply_filters( 'bp_force_buddybar', (bool) bp_get_option( '_bp_force_buddybar', $default ) );
689
  }
690
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
691
  /**
692
  * Check whether Akismet is enabled.
693
  *
bp-core/bp-core-taxonomy.php CHANGED
@@ -21,7 +21,7 @@ defined( 'ABSPATH' ) || exit;
21
  */
22
  function bp_register_default_taxonomies() {
23
  // Member Type.
24
- register_taxonomy( 'bp_member_type', 'user', array(
25
  'public' => false,
26
  ) );
27
 
@@ -51,6 +51,7 @@ add_action( 'bp_register_taxonomies', 'bp_register_default_taxonomies' );
51
  *
52
  * @since 2.6.0
53
  *
 
54
  * @return int
55
  */
56
  function bp_get_taxonomy_term_site_id( $taxonomy = '' ) {
@@ -61,8 +62,8 @@ function bp_get_taxonomy_term_site_id( $taxonomy = '' ) {
61
  *
62
  * @since 2.6.0
63
  *
64
- * @param int $site_id
65
- * @param string $taxonomy
66
  */
67
  return (int) apply_filters( 'bp_get_taxonomy_term_site_id', $site_id, $taxonomy );
68
  }
@@ -90,13 +91,25 @@ function bp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
90
  $switched = true;
91
  }
92
 
93
- $retval = wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
94
 
95
- if ( ! $switched ) {
96
  restore_current_blog();
97
  }
98
 
99
- return $retval;
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
 
102
  /**
@@ -131,7 +144,7 @@ function bp_get_object_terms( $object_ids, $taxonomies, $args = array() ) {
131
  $site_terms = wp_get_object_terms( $object_ids, $site_taxonomies, $args );
132
  $retval = array_merge( $retval, $site_terms );
133
 
134
- if ( ! $switched ) {
135
  restore_current_blog();
136
  }
137
  }
@@ -163,9 +176,104 @@ function bp_remove_object_terms( $object_id, $terms, $taxonomy ) {
163
 
164
  $retval = wp_remove_object_terms( $object_id, $terms, $taxonomy );
165
 
166
- if ( ! $switched ) {
167
  restore_current_blog();
168
  }
169
 
 
 
 
 
 
 
 
 
 
 
 
170
  return $retval;
171
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  */
22
  function bp_register_default_taxonomies() {
23
  // Member Type.
24
+ register_taxonomy( bp_get_member_type_tax_name(), 'user', array(
25
  'public' => false,
26
  ) );
27
 
51
  *
52
  * @since 2.6.0
53
  *
54
+ * @param string $taxonomy Taxonomy slug to check for.
55
  * @return int
56
  */
57
  function bp_get_taxonomy_term_site_id( $taxonomy = '' ) {
62
  *
63
  * @since 2.6.0
64
  *
65
+ * @param int $site_id Site ID to cehck for.
66
+ * @param string $taxonomy Taxonomy slug to check for.
67
  */
68
  return (int) apply_filters( 'bp_get_taxonomy_term_site_id', $site_id, $taxonomy );
69
  }
91
  $switched = true;
92
  }
93
 
94
+ $tt_ids = wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
95
 
96
+ if ( $switched ) {
97
  restore_current_blog();
98
  }
99
 
100
+ /**
101
+ * Fires when taxonomy terms have been set on BuddyPress objects.
102
+ *
103
+ * @since 2.7.0
104
+ *
105
+ * @param int $object_id Object ID.
106
+ * @param array $terms Term or terms to remove.
107
+ * @param array $tt_ids Array of term taxonomy IDs.
108
+ * @param string $taxonomy Taxonomy name.
109
+ */
110
+ do_action( 'bp_set_object_terms', $object_id, $terms, $tt_ids, $taxonomy );
111
+
112
+ return $tt_ids;
113
  }
114
 
115
  /**
144
  $site_terms = wp_get_object_terms( $object_ids, $site_taxonomies, $args );
145
  $retval = array_merge( $retval, $site_terms );
146
 
147
+ if ( $switched ) {
148
  restore_current_blog();
149
  }
150
  }
176
 
177
  $retval = wp_remove_object_terms( $object_id, $terms, $taxonomy );
178
 
179
+ if ( $switched ) {
180
  restore_current_blog();
181
  }
182
 
183
+ /**
184
+ * Fires when taxonomy terms have been removed from BuddyPress objects.
185
+ *
186
+ * @since 2.7.0
187
+ *
188
+ * @param int $object_id Object ID.
189
+ * @param array $terms Term or terms to remove.
190
+ * @param string $taxonomy Taxonomy name.
191
+ */
192
+ do_action( 'bp_remove_object_terms', $object_id, $terms, $taxonomy );
193
+
194
  return $retval;
195
  }
196
+
197
+ /**
198
+ * Retrieve IDs of objects in valid taxonomies and terms for BuddyPress-related taxonomies.
199
+ *
200
+ * Note that object IDs are from the `bp_get_taxonomy_term_site_id()`, which on some
201
+ * multisite configurations may not be the same as the current site.
202
+ *
203
+ * @since 2.7.0
204
+ *
205
+ * @see get_objects_in_term() for a full description of function and parameters.
206
+ *
207
+ * @param int|array $term_ids Term id or array of term ids of terms that will be used.
208
+ * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names.
209
+ * @param array|string $args Change the order of the object_ids, either ASC or DESC.
210
+ *
211
+ * @return WP_Error|array If the taxonomy does not exist, then WP_Error will be returned. On success,
212
+ * the array can be empty, meaning that there are no $object_ids found. When
213
+ * object IDs are found, an array of those IDs will be returned.
214
+ */
215
+ function bp_get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
216
+ // Different taxonomies may be stored on different sites.
217
+ $taxonomy_site_map = array();
218
+ foreach ( (array) $taxonomies as $taxonomy ) {
219
+ $taxonomy_site_id = bp_get_taxonomy_term_site_id( $taxonomy );
220
+ $taxonomy_site_map[ $taxonomy_site_id ][] = $taxonomy;
221
+ }
222
+
223
+ $retval = array();
224
+ foreach ( $taxonomy_site_map as $taxonomy_site_id => $site_taxonomies ) {
225
+ $switched = false;
226
+ if ( $taxonomy_site_id !== get_current_blog_id() ) {
227
+ switch_to_blog( $taxonomy_site_id );
228
+ bp_register_taxonomies();
229
+ $switched = true;
230
+ }
231
+
232
+ $site_objects = get_objects_in_term( $term_ids, $site_taxonomies, $args );
233
+ $retval = array_merge( $retval, $site_objects );
234
+
235
+ if ( $switched ) {
236
+ restore_current_blog();
237
+ }
238
+ }
239
+
240
+ return $retval;
241
+ }
242
+
243
+ /**
244
+ * Get term data for terms in BuddyPress taxonomies.
245
+ *
246
+ * Note that term data is from the `bp_get_taxonomy_term_site_id()`, which on some
247
+ * multisite configurations may not be the same as the current site.
248
+ *
249
+ * @since 2.7.0
250
+ *
251
+ * @see get_term_by() for a full description of function and parameters.
252
+ *
253
+ * @param string $field Either 'slug', 'name', 'id' (term_id), or 'term_taxonomy_id'
254
+ * @param string|int $value Search for this term value
255
+ * @param string $taxonomy Taxonomy name. Optional, if `$field` is 'term_taxonomy_id'.
256
+ * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
257
+ * @param string $filter Optional, default is raw or no WordPress defined filter will applied.
258
+ *
259
+ * @return WP_Term|bool WP_Term instance on success. Will return false if `$taxonomy` does not exist
260
+ * or `$term` was not found.
261
+ */
262
+ function bp_get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
263
+ $site_id = bp_get_taxonomy_term_site_id( $taxonomy );
264
+
265
+ $switched = false;
266
+ if ( $site_id !== get_current_blog_id() ) {
267
+ switch_to_blog( $site_id );
268
+ bp_register_taxonomies();
269
+ $switched = true;
270
+ }
271
+
272
+ $term = get_term_by( $field, $value, $taxonomy, $output, $filter );
273
+
274
+ if ( $switched ) {
275
+ restore_current_blog();
276
+ }
277
+
278
+ return $term;
279
+ }
bp-core/bp-core-template-loader.php CHANGED
@@ -23,7 +23,7 @@ defined( 'ABSPATH' ) || exit;
23
  * eg 'friends' for 'friends.php'.
24
  * @param string|null $name Optional. Template part name. Used to generate
25
  * secondary filenames, eg 'personal' for 'activity-personal.php'.
26
- * @return string Path to located template. See {@link bp_locate_template()}.
27
  */
28
  function bp_get_template_part( $slug, $name = null ) {
29
 
@@ -70,6 +70,10 @@ function bp_get_template_part( $slug, $name = null ) {
70
  * @since 2.6.0
71
  *
72
  * @see bp_get_template_part() for full documentation.
 
 
 
 
73
  */
74
  function bp_get_asset_template_part( $slug, $name = null ) {
75
  return bp_get_template_part( "assets/{$slug}", $name );
@@ -93,6 +97,11 @@ function bp_get_asset_template_part( $slug, $name = null ) {
93
  */
94
  function bp_locate_template( $template_names, $load = false, $require_once = true ) {
95
 
 
 
 
 
 
96
  // No file found yet.
97
  $located = false;
98
  $template_locations = bp_get_template_stack();
@@ -156,9 +165,9 @@ function bp_locate_template( $template_names, $load = false, $require_once = tru
156
  *
157
  * @since 2.6.0
158
  *
159
- * @param string Relative filename to search for.
160
- * @return array|bool Array of asset data if one is located (includes absolute filepath and URI).
161
- * Boolean false on failure.
162
  */
163
  function bp_locate_template_asset( $filename ) {
164
  // Ensure assets can be located when running from /src/.
@@ -178,12 +187,12 @@ function bp_locate_template_asset( $filename ) {
178
 
179
  $find = array(
180
  get_theme_root(),
181
- buddypress()->plugin_dir
182
  );
183
 
184
  $replace = array(
185
  get_theme_root_uri(),
186
- buddypress()->plugin_url
187
  );
188
 
189
  // Make sure URI path is relative to site URL.
@@ -596,7 +605,7 @@ function bp_load_theme_functions() {
596
  * @since 1.7.0
597
  * @since 2.4.0 Added singular.php to stack
598
  *
599
- * @return array Array of possible root level wrapper template files.
600
  */
601
  function bp_get_theme_compat_templates() {
602
  return bp_get_query_template( 'buddypress', array(
23
  * eg 'friends' for 'friends.php'.
24
  * @param string|null $name Optional. Template part name. Used to generate
25
  * secondary filenames, eg 'personal' for 'activity-personal.php'.
26
+ * @return false|string Path to located template. See {@link bp_locate_template()}.
27
  */
28
  function bp_get_template_part( $slug, $name = null ) {
29
 
70
  * @since 2.6.0
71
  *
72
  * @see bp_get_template_part() for full documentation.
73
+ *
74
+ * @param string $slug Template slug.
75
+ * @param string|null $name Template name.
76
+ * @return false|string
77
  */
78
  function bp_get_asset_template_part( $slug, $name = null ) {
79
  return bp_get_template_part( "assets/{$slug}", $name );
97
  */
98
  function bp_locate_template( $template_names, $load = false, $require_once = true ) {
99
 
100
+ // Bail when there are no templates to locate
101
+ if ( empty( $template_names ) ) {
102
+ return false;
103
+ }
104
+
105
  // No file found yet.
106
  $located = false;
107
  $template_locations = bp_get_template_stack();
165
  *
166
  * @since 2.6.0
167
  *
168
+ * @param string $filename Relative filename to search for.
169
+ * @return false|array Array of asset data if one is located (includes absolute filepath and URI).
170
+ * Boolean false on failure.
171
  */
172
  function bp_locate_template_asset( $filename ) {
173
  // Ensure assets can be located when running from /src/.
187
 
188
  $find = array(
189
  get_theme_root(),
190
+ bp_get_theme_compat_dir()
191
  );
192
 
193
  $replace = array(
194
  get_theme_root_uri(),
195
+ bp_get_theme_compat_url()
196
  );
197
 
198
  // Make sure URI path is relative to site URL.
605
  * @since 1.7.0
606
  * @since 2.4.0 Added singular.php to stack
607
  *
608
+ * @return string Possible root level wrapper template files.
609
  */
610
  function bp_get_theme_compat_templates() {
611
  return bp_get_query_template( 'buddypress', array(
bp-core/bp-core-template.php CHANGED
@@ -550,10 +550,6 @@ function bp_search_form_type_select() {
550
  $options['blogs'] = _x( 'Blogs', 'search form', 'buddypress' );
551
  }
552
 
553
- if ( bp_is_active( 'forums' ) && bp_forums_is_installed_correctly() && bp_forums_has_directory() ) {
554
- $options['forums'] = _x( 'Forums', 'search form', 'buddypress' );
555
- }
556
-
557
  $options['posts'] = _x( 'Posts', 'search form', 'buddypress' );
558
 
559
  // Eventually this won't be needed and a page will be built to integrate all search results.
@@ -584,6 +580,71 @@ function bp_search_form_type_select() {
584
  return apply_filters( 'bp_search_form_type_select', $selection_box );
585
  }
586
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  /**
588
  * Output the default text for the search box for a given component.
589
  *
@@ -731,7 +792,14 @@ function bp_form_field_attributes( $name = '', $attributes = array() ) {
731
  $attributes = (array) apply_filters( 'bp_get_form_field_attributes', $attributes, $name );
732
 
733
  foreach( $attributes as $attr => $value ) {
734
- $retval .= sprintf( ' %s="%s"', sanitize_key( $attr ), esc_attr( $value ) );
 
 
 
 
 
 
 
735
  }
736
 
737
  return $retval;
@@ -1089,10 +1157,7 @@ function bp_blog_signup_allowed() {
1089
  * otherwise false.
1090
  */
1091
  function bp_account_was_activated() {
1092
- $bp = buddypress();
1093
- $activation_complete = !empty( $bp->activation_complete )
1094
- ? $bp->activation_complete
1095
- : false;
1096
 
1097
  return $activation_complete;
1098
  }
@@ -2134,6 +2199,7 @@ function bp_is_groups_component() {
2134
  * Check whether the current page is part of the Forums component.
2135
  *
2136
  * @since 1.5.0
 
2137
  *
2138
  * @return bool True if the current page is part of the Forums component.
2139
  */
@@ -2399,7 +2465,7 @@ function bp_is_user_change_avatar() {
2399
  *
2400
  * Eg http://example.com/members/joe/profile/change-cover-image/ (or a subpage thereof).
2401
  *
2402
- * @since 2.4.0
2403
  *
2404
  * @return bool True if the current page is a user's profile edit cover image page.
2405
  */
@@ -2407,54 +2473,6 @@ function bp_is_user_change_cover_image() {
2407
  return (bool) ( bp_is_profile_component() && bp_is_current_action( 'change-cover-image' ) );
2408
  }
2409
 
2410
- /**
2411
- * Is this a user's forums page?
2412
- *
2413
- * Eg http://example.com/members/joe/forums/ (or a subpage thereof).
2414
- *
2415
- * @since 1.5.0
2416
- *
2417
- * @return bool True if the current page is a user's forums page.
2418
- */
2419
- function bp_is_user_forums() {
2420
-
2421
- if ( ! bp_is_active( 'forums' ) ) {
2422
- return false;
2423
- }
2424
-
2425
- if ( bp_is_user() && bp_is_forums_component() ) {
2426
- return true;
2427
- }
2428
-
2429
- return false;
2430
- }
2431
-
2432
- /**
2433
- * Is this a user's "Topics Started" page?
2434
- *
2435
- * Eg http://example.com/members/joe/forums/topics/.
2436
- *
2437
- * @since 1.5.0
2438
- *
2439
- * @return bool True if the current page is a user's Topics Started page.
2440
- */
2441
- function bp_is_user_forums_started() {
2442
- return (bool) ( bp_is_user_forums() && bp_is_current_action( 'topics' ) );
2443
- }
2444
-
2445
- /**
2446
- * Is this a user's "Replied To" page?
2447
- *
2448
- * Eg http://example.com/members/joe/forums/replies/.
2449
- *
2450
- * @since 1.5.0
2451
- *
2452
- * @return bool True if the current page is a user's Replied To forums page.
2453
- */
2454
- function bp_is_user_forums_replied_to() {
2455
- return (bool) ( bp_is_user_forums() && bp_is_current_action( 'replies' ) );
2456
- }
2457
-
2458
  /**
2459
  * Is the current page part of a user's Groups page?
2460
  *
@@ -2618,10 +2636,10 @@ function bp_is_user_settings_profile() {
2618
  *
2619
  * @since 2.0.0
2620
  *
2621
- * @return True if the current page is the groups directory.
2622
  */
2623
  function bp_is_groups_directory() {
2624
- if ( bp_is_groups_component() && ! bp_current_action() && ! bp_current_item() ) {
2625
  return true;
2626
  }
2627
 
@@ -2689,38 +2707,12 @@ function bp_is_group_admin_page() {
2689
  return (bool) ( bp_is_single_item() && bp_is_groups_component() && bp_is_current_action( 'admin' ) );
2690
  }
2691
 
2692
- /**
2693
- * Is the current page a group's forum page?
2694
- *
2695
- * Only applies to legacy bbPress forums.
2696
- *
2697
- * @since 1.1.0
2698
- *
2699
- * @return bool True if the current page is a group forum page.
2700
- */
2701
- function bp_is_group_forum() {
2702
- $retval = false;
2703
-
2704
- // At a forum URL.
2705
- if ( bp_is_single_item() && bp_is_groups_component() && bp_is_current_action( 'forum' ) ) {
2706
- $retval = true;
2707
-
2708
- // If at a forum URL, set back to false if forums are inactive, or not
2709
- // installed correctly.
2710
- if ( ! bp_is_active( 'forums' ) || ! bp_forums_is_installed_correctly() ) {
2711
- $retval = false;
2712
- }
2713
- }
2714
-
2715
- return $retval;
2716
- }
2717
-
2718
  /**
2719
  * Is the current page a group's activity page?
2720
  *
2721
  * @since 1.2.1
2722
  *
2723
- * @return True if the current page is a group's activity page.
2724
  */
2725
  function bp_is_group_activity() {
2726
  $retval = false;
@@ -2739,9 +2731,8 @@ function bp_is_group_activity() {
2739
  /**
2740
  * Is the current page a group forum topic?
2741
  *
2742
- * Only applies to legacy bbPress (1.x) forums.
2743
- *
2744
  * @since 1.1.0
 
2745
  *
2746
  * @return bool True if the current page is part of a group forum topic.
2747
  */
@@ -2752,9 +2743,8 @@ function bp_is_group_forum_topic() {
2752
  /**
2753
  * Is the current page a group forum topic edit page?
2754
  *
2755
- * Only applies to legacy bbPress (1.x) forums.
2756
- *
2757
  * @since 1.2.0
 
2758
  *
2759
  * @return bool True if the current page is part of a group forum topic edit page.
2760
  */
@@ -2865,7 +2855,7 @@ function bp_is_create_blog() {
2865
  *
2866
  * @since 2.0.0
2867
  *
2868
- * @return True if the current page is the blogs directory.
2869
  */
2870
  function bp_is_blogs_directory() {
2871
  if ( is_multisite() && bp_is_blogs_component() && ! bp_current_action() ) {
@@ -3154,7 +3144,7 @@ function bp_get_title_parts( $seplocation = 'right' ) {
3154
  *
3155
  * @since 2.4.3
3156
  *
3157
- * @param array $bp_title_parts Current BuddyPress title parts
3158
  * @return array
3159
  */
3160
  return (array) apply_filters( 'bp_get_title_parts', $bp_title_parts );
@@ -3233,6 +3223,13 @@ function bp_the_body_class() {
3233
 
3234
  if ( bp_is_user() ) {
3235
  $bp_classes[] = 'bp-user';
 
 
 
 
 
 
 
3236
  }
3237
 
3238
  if ( ! bp_is_directory() ) {
@@ -3247,6 +3244,10 @@ function bp_the_body_class() {
3247
  if ( bp_is_user_activity() ) {
3248
  $bp_classes[] = 'my-activity';
3249
  }
 
 
 
 
3250
  }
3251
 
3252
  if ( bp_is_my_profile() ) {
@@ -3319,6 +3320,13 @@ function bp_the_body_class() {
3319
 
3320
  if ( bp_is_group() ) {
3321
  $bp_classes[] = 'group-' . groups_get_current_group()->slug;
 
 
 
 
 
 
 
3322
  }
3323
 
3324
  if ( bp_is_group_leave() ) {
@@ -3333,18 +3341,6 @@ function bp_the_body_class() {
3333
  $bp_classes[] = 'group-members';
3334
  }
3335
 
3336
- if ( bp_is_group_forum_topic() ) {
3337
- $bp_classes[] = 'group-forum-topic';
3338
- }
3339
-
3340
- if ( bp_is_group_forum_topic_edit() ) {
3341
- $bp_classes[] = 'group-forum-topic-edit';
3342
- }
3343
-
3344
- if ( bp_is_group_forum() ) {
3345
- $bp_classes[] = 'group-forum';
3346
- }
3347
-
3348
  if ( bp_is_group_admin_page() ) {
3349
  $bp_classes[] = 'group-admin';
3350
  $bp_classes[] = bp_get_group_current_admin_tab();
@@ -3387,6 +3383,9 @@ function bp_the_body_class() {
3387
  $bp_classes[] = 'buddypress';
3388
  }
3389
 
 
 
 
3390
  // Merge WP classes with BuddyPress classes and remove any duplicates.
3391
  $classes = array_unique( array_merge( (array) $bp_classes, (array) $wp_classes ) );
3392
 
@@ -3439,9 +3438,6 @@ function bp_get_the_post_class( $wp_classes = array() ) {
3439
 
3440
  } elseif ( bp_is_activation_page() ) {
3441
  $bp_classes[] = 'bp_activate';
3442
-
3443
- } elseif ( bp_is_forums_component() && bp_is_directory() ) {
3444
- $bp_classes[] = 'bp_forum';
3445
  }
3446
 
3447
  if ( empty( $bp_classes ) ) {
@@ -3509,7 +3505,7 @@ function bp_get_nav_menu_items( $component = 'members' ) {
3509
  $menu = new stdClass;
3510
  $menu->class = array( 'menu-parent' );
3511
  $menu->css_id = $nav_menu->css_id;
3512
- $menu->link = $nav_menu->link;
3513
  $menu->name = $nav_menu->name;
3514
  $menu->parent = 0;
3515
 
@@ -3525,7 +3521,7 @@ function bp_get_nav_menu_items( $component = 'members' ) {
3525
  $submenu->parent = $nav_menu->slug;
3526
 
3527
  // If we're viewing this item's screen, record that we need to mark its parent menu to be selected.
3528
- if ( $sub_menu->slug == bp_current_action() ) {
3529
  $menu->class[] = 'current-menu-parent';
3530
  $submenu->class[] = 'current-menu-item';
3531
  }
@@ -3724,9 +3720,9 @@ function bp_nav_menu( $args = array() ) {
3724
  /**
3725
  * Prints the Recipient Salutation.
3726
  *
3727
- * @since 2.5.0
3728
  *
3729
- * @param array $settings Email Settings.
3730
  */
3731
  function bp_email_the_salutation( $settings = array() ) {
3732
  echo bp_email_get_salutation( $settings );
@@ -3735,9 +3731,9 @@ function bp_email_the_salutation( $settings = array() ) {
3735
  /**
3736
  * Gets the Recipient Salutation.
3737
  *
3738
- * @since 2.5.0
3739
  *
3740
- * @param array $settings Email Settings.
3741
  * @return string The Recipient Salutation.
3742
  */
3743
  function bp_email_get_salutation( $settings = array() ) {
@@ -3746,7 +3742,7 @@ function bp_email_the_salutation( $settings = array() ) {
3746
  /**
3747
  * Filters The Recipient Salutation inside the Email Template.
3748
  *
3749
- * @since 2.5.0
3750
  *
3751
  * @param string $value The Recipient Salutation.
3752
  * @param array $settings Email Settings.
550
  $options['blogs'] = _x( 'Blogs', 'search form', 'buddypress' );
551
  }
552
 
 
 
 
 
553
  $options['posts'] = _x( 'Posts', 'search form', 'buddypress' );
554
 
555
  // Eventually this won't be needed and a page will be built to integrate all search results.
580
  return apply_filters( 'bp_search_form_type_select', $selection_box );
581
  }
582
 
583
+ /**
584
+ * Output the 'name' attribute for search form input element.
585
+ *
586
+ * @since 2.7.0
587
+ *
588
+ * @param string $component See bp_get_search_input_name().
589
+ */
590
+ function bp_search_input_name( $component = '' ) {
591
+ echo esc_attr( bp_get_search_input_name( $component ) );
592
+ }
593
+
594
+ /**
595
+ * Get the 'name' attribute for the search form input element.
596
+ *
597
+ * @since 2.7.0
598
+ *
599
+ * @param string $component Component name. Defaults to current component.
600
+ * @return string Text for the 'name' attribute.
601
+ */
602
+ function bp_get_search_input_name( $component = '' ) {
603
+ if ( ! $component ) {
604
+ $component = bp_current_component();
605
+ }
606
+
607
+ $bp = buddypress();
608
+
609
+ $name = '';
610
+ if ( isset( $bp->{$component}->id ) ) {
611
+ $name = $bp->{$component}->id . '_search';
612
+ }
613
+
614
+ return $name;
615
+ }
616
+
617
+ /**
618
+ * Output the placeholder text for the search box for a given component.
619
+ *
620
+ * @since 2.7.0
621
+ *
622
+ * @param string $component See bp_get_search_placeholder().
623
+ */
624
+ function bp_search_placeholder( $component = '' ) {
625
+ echo esc_attr( bp_get_search_placeholder( $component ) );
626
+ }
627
+
628
+ /**
629
+ * Get the placeholder text for the search box for a given component.
630
+ *
631
+ * @since 2.7.0
632
+ *
633
+ * @param string $component Component name. Defaults to current component.
634
+ * @return string Placeholder text for the search field.
635
+ */
636
+ function bp_get_search_placeholder( $component = '' ) {
637
+ $query_arg = bp_core_get_component_search_query_arg( $component );
638
+
639
+ if ( $query_arg && ! empty( $_REQUEST[ $query_arg ] ) ) {
640
+ $placeholder = wp_unslash( $_REQUEST[ $query_arg ] );
641
+ } else {
642
+ $placeholder = bp_get_search_default_text( $component );
643
+ }
644
+
645
+ return $placeholder;
646
+ }
647
+
648
  /**
649
  * Output the default text for the search box for a given component.
650
  *
792
  $attributes = (array) apply_filters( 'bp_get_form_field_attributes', $attributes, $name );
793
 
794
  foreach( $attributes as $attr => $value ) {
795
+ // Numeric keyed array.
796
+ if (is_numeric( $attr ) ) {
797
+ $retval .= sprintf( ' %s', esc_attr( $value ) );
798
+
799
+ // Associative keyed array.
800
+ } else {
801
+ $retval .= sprintf( ' %s="%s"', sanitize_key( $attr ), esc_attr( $value ) );
802
+ }
803
  }
804
 
805
  return $retval;
1157
  * otherwise false.
1158
  */
1159
  function bp_account_was_activated() {
1160
+ $activation_complete = ! empty( buddypress()->activation_complete ) || ( bp_is_current_component( 'activate' ) && ! empty( $_GET['activated'] ) );
 
 
 
1161
 
1162
  return $activation_complete;
1163
  }
2199
  * Check whether the current page is part of the Forums component.
2200
  *
2201
  * @since 1.5.0
2202
+ * @since 3.0.0 Required for bbPress 2 integration.
2203
  *
2204
  * @return bool True if the current page is part of the Forums component.
2205
  */
2465
  *
2466
  * Eg http://example.com/members/joe/profile/change-cover-image/ (or a subpage thereof).
2467
  *
2468
+ * @since 2.4.0
2469
  *
2470
  * @return bool True if the current page is a user's profile edit cover image page.
2471
  */
2473
  return (bool) ( bp_is_profile_component() && bp_is_current_action( 'change-cover-image' ) );
2474
  }
2475
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2476
  /**
2477
  * Is the current page part of a user's Groups page?
2478
  *
2636
  *
2637
  * @since 2.0.0
2638
  *
2639
+ * @return bool True if the current page is the groups directory.
2640
  */
2641
  function bp_is_groups_directory() {
2642
+ if ( bp_is_groups_component() && ! bp_is_group() && ( ! bp_current_action() || ( bp_action_variable() && bp_is_current_action( bp_get_groups_group_type_base() ) ) ) ) {
2643
  return true;
2644
  }
2645
 
2707
  return (bool) ( bp_is_single_item() && bp_is_groups_component() && bp_is_current_action( 'admin' ) );
2708
  }
2709
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2710
  /**
2711
  * Is the current page a group's activity page?
2712
  *
2713
  * @since 1.2.1
2714
  *
2715
+ * @return bool True if the current page is a group's activity page.
2716
  */
2717
  function bp_is_group_activity() {
2718
  $retval = false;
2731
  /**
2732
  * Is the current page a group forum topic?
2733
  *
 
 
2734
  * @since 1.1.0
2735
+ * @since 3.0.0 Required for bbPress 2 integration.
2736
  *
2737
  * @return bool True if the current page is part of a group forum topic.
2738
  */
2743
  /**
2744
  * Is the current page a group forum topic edit page?
2745
  *
 
 
2746
  * @since 1.2.0
2747
+ * @since 3.0.0 Required for bbPress 2 integration.
2748
  *
2749
  * @return bool True if the current page is part of a group forum topic edit page.
2750
  */
2855
  *
2856
  * @since 2.0.0
2857
  *
2858
+ * @return bool True if the current page is the blogs directory.
2859
  */
2860
  function bp_is_blogs_directory() {
2861
  if ( is_multisite() && bp_is_blogs_component() && ! bp_current_action() ) {
3144
  *
3145
  * @since 2.4.3
3146
  *
3147
+ * @param array $bp_title_parts Current BuddyPress title parts.
3148
  * @return array
3149
  */
3150
  return (array) apply_filters( 'bp_get_title_parts', $bp_title_parts );
3223
 
3224
  if ( bp_is_user() ) {
3225
  $bp_classes[] = 'bp-user';
3226
+
3227
+ // Add current user member types.
3228
+ if ( $member_types = bp_get_member_type( bp_displayed_user_id(), false ) ) {
3229
+ foreach( $member_types as $member_type ) {
3230
+ $bp_classes[] = sprintf( 'member-type-%s', esc_attr( $member_type ) );
3231
+ }
3232
+ }
3233
  }
3234
 
3235
  if ( ! bp_is_directory() ) {
3244
  if ( bp_is_user_activity() ) {
3245
  $bp_classes[] = 'my-activity';
3246
  }
3247
+ } else {
3248
+ if ( bp_get_current_member_type() ) {
3249
+ $bp_classes[] = 'type';
3250
+ }
3251
  }
3252
 
3253
  if ( bp_is_my_profile() ) {
3320
 
3321
  if ( bp_is_group() ) {
3322
  $bp_classes[] = 'group-' . groups_get_current_group()->slug;
3323
+
3324
+ // Add current group types.
3325
+ if ( $group_types = bp_groups_get_group_type( bp_get_current_group_id(), false ) ) {
3326
+ foreach ( $group_types as $group_type ) {
3327
+ $bp_classes[] = sprintf( 'group-type-%s', esc_attr( $group_type ) );
3328
+ }
3329
+ }
3330
  }
3331
 
3332
  if ( bp_is_group_leave() ) {
3341
  $bp_classes[] = 'group-members';
3342
  }
3343
 
 
 
 
 
 
 
 
 
 
 
 
 
3344
  if ( bp_is_group_admin_page() ) {
3345
  $bp_classes[] = 'group-admin';
3346
  $bp_classes[] = bp_get_group_current_admin_tab();
3383
  $bp_classes[] = 'buddypress';
3384
  }
3385
 
3386
+ // Add the theme name/id to the body classes
3387
+ $bp_classes[] = 'bp-' . bp_get_theme_compat_id();
3388
+
3389
  // Merge WP classes with BuddyPress classes and remove any duplicates.
3390
  $classes = array_unique( array_merge( (array) $bp_classes, (array) $wp_classes ) );
3391
 
3438
 
3439
  } elseif ( bp_is_activation_page() ) {
3440
  $bp_classes[] = 'bp_activate';
 
 
 
3441
  }
3442
 
3443
  if ( empty( $bp_classes ) ) {
3505
  $menu = new stdClass;
3506
  $menu->class = array( 'menu-parent' );
3507
  $menu->css_id = $nav_menu->css_id;
3508
+ $menu->link = $link;
3509
  $menu->name = $nav_menu->name;
3510
  $menu->parent = 0;
3511
 
3521
  $submenu->parent = $nav_menu->slug;
3522
 
3523
  // If we're viewing this item's screen, record that we need to mark its parent menu to be selected.
3524
+ if ( bp_is_current_action( $sub_menu->slug ) && bp_is_current_component( $nav_menu->slug ) ) {
3525
  $menu->class[] = 'current-menu-parent';
3526
  $submenu->class[] = 'current-menu-item';
3527
  }
3720
  /**
3721
  * Prints the Recipient Salutation.
3722
  *
3723
+ * @since 2.5.0
3724
  *
3725
+ * @param array $settings Email Settings.
3726
  */
3727
  function bp_email_the_salutation( $settings = array() ) {
3728
  echo bp_email_get_salutation( $settings );
3731
  /**
3732
  * Gets the Recipient Salutation.
3733
  *
3734
+ * @since 2.5.0
3735
  *
3736
+ * @param array $settings Email Settings.
3737
  * @return string The Recipient Salutation.
3738
  */
3739
  function bp_email_get_salutation( $settings = array() ) {
3742
  /**
3743
  * Filters The Recipient Salutation inside the Email Template.
3744
  *
3745
+ * @since 2.5.0
3746
  *
3747
  * @param string $value The Recipient Salutation.
3748
  * @param array $settings Email Settings.
bp-core/bp-core-theme-compatibility.php CHANGED
@@ -22,12 +22,6 @@ defined( 'ABSPATH' ) || exit;
22
  * Don't try anything you're about to witness here, at home. Ever.
23
  */
24
 
25
- /** Base Class ****************************************************************/
26
-
27
- if ( ! buddypress()->do_autoload ) {
28
- require dirname( __FILE__ ) . '/classes/class-bp-theme-compat.php';
29
- }
30
-
31
  /** Functions *****************************************************************/
32
 
33
  /**
@@ -319,8 +313,8 @@ function bp_set_theme_compat_original_template( $template = '' ) {
319
  *
320
  * @since 2.4.0
321
  *
322
- * @param string $theme_id The theme id (eg: legacy).
323
- * @param array $feature An associative array (eg: array( name => 'feature_name', 'settings' => array() )).
324
  */
325
  function bp_set_theme_compat_feature( $theme_id, $feature = array() ) {
326
  if ( empty( $theme_id ) || empty( $feature['name'] ) ) {
@@ -379,8 +373,8 @@ function bp_set_theme_compat_feature( $theme_id, $feature = array() ) {
379
  *
380
  * @since 2.4.0
381
  *
382
- * @param string $feature The feature (eg: cover_image).
383
- * @return object The feature settings.
384
  */
385
  function bp_get_theme_compat_feature( $feature = '' ) {
386
  // Get current theme compat theme.
@@ -397,7 +391,7 @@ function bp_get_theme_compat_feature( $feature = '' ) {
397
  }
398
 
399
  /**
400
- * Setup the theme's features
401
  *
402
  * Note: BP Legacy's buddypress-functions.php is not loaded in WP Administration
403
  * as it's loaded using bp_locate_template(). That's why this function is here.
@@ -646,7 +640,7 @@ function bp_theme_compat_reset_post( $args = array() ) {
646
  unset( $dummy );
647
 
648
  /**
649
- * Force the header back to 200 status if not a deliberate 404
650
  *
651
  * @see https://bbpress.trac.wordpress.org/ticket/1973
652
  */
@@ -957,10 +951,12 @@ function bp_comments_open( $open, $post_id = 0 ) {
957
  function bp_theme_compat_toggle_is_page( $retval = '' ) {
958
  global $wp_query;
959
 
960
- $wp_query->is_page = false;
 
961
 
962
- // Set a switch so we know that we've toggled these WP_Query properties.
963
- buddypress()->theme_compat->is_page_toggled = true;
 
964
 
965
  return $retval;
966
  }
@@ -991,3 +987,22 @@ function bp_theme_compat_loop_end( $query ) {
991
  unset( $bp->theme_compat->is_page_toggled );
992
  }
993
  add_action( 'loop_end', 'bp_theme_compat_loop_end' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  * Don't try anything you're about to witness here, at home. Ever.
23
  */
24
 
 
 
 
 
 
 
25
  /** Functions *****************************************************************/
26
 
27
  /**
313
  *
314
  * @since 2.4.0
315
  *
316
+ * @param string $theme_id The theme id (eg: legacy).
317
+ * @param array $feature An associative array (eg: array( name => 'feature_name', 'settings' => array() )).
318
  */
319
  function bp_set_theme_compat_feature( $theme_id, $feature = array() ) {
320
  if ( empty( $theme_id ) || empty( $feature['name'] ) ) {
373
  *
374
  * @since 2.4.0
375
  *
376
+ * @param string $feature The feature (eg: cover_image).
377
+ * @return object The feature settings.
378
  */
379
  function bp_get_theme_compat_feature( $feature = '' ) {
380
  // Get current theme compat theme.
391
  }
392
 
393
  /**
394
+ * Setup the theme's features.
395
  *
396
  * Note: BP Legacy's buddypress-functions.php is not loaded in WP Administration
397
  * as it's loaded using bp_locate_template(). That's why this function is here.
640
  unset( $dummy );
641
 
642
  /**
643
+ * Force the header back to 200 status if not a deliberate 404.
644
  *
645
  * @see https://bbpress.trac.wordpress.org/ticket/1973
646
  */
951
  function bp_theme_compat_toggle_is_page( $retval = '' ) {
952
  global $wp_query;
953
 
954
+ if ( $wp_query->is_page ) {
955
+ $wp_query->is_page = false;
956
 
957
+ // Set a switch so we know that we've toggled these WP_Query properties.
958
+ buddypress()->theme_compat->is_page_toggled = true;
959
+ }
960
 
961
  return $retval;
962
  }
987
  unset( $bp->theme_compat->is_page_toggled );
988
  }
989
  add_action( 'loop_end', 'bp_theme_compat_loop_end' );
990
+
991
+ /**
992
+ * Maybe override the preferred template pack if the theme declares a dependency.
993
+ *
994
+ * @since 3.0.0
995
+ */
996
+ function bp_check_theme_template_pack_dependency() {
997
+ $all_packages = array_keys( buddypress()->theme_compat->packages );
998
+
999
+ foreach ( $all_packages as $package ) {
1000
+ // e.g. "buddypress-use-nouveau", "buddypress-use-legacy".
1001
+ if ( ! current_theme_supports( "buddypress-use-{$package}" ) ) {
1002
+ continue;
1003
+ }
1004
+
1005
+ bp_setup_theme_compat( $package );
1006
+ return;
1007
+ }
1008
+ }
bp-core/bp-core-update.php CHANGED
@@ -139,7 +139,6 @@ function bp_is_deactivation( $basename = '' ) {
139
  * Update the BP version stored in the database to the current version.
140
  *
141
  * @since 1.6.0
142
- *
143
  */
144
  function bp_version_bump() {
145
  bp_update_option( '_bp_db_version', bp_get_db_version() );
@@ -192,10 +191,11 @@ function bp_version_updater() {
192
  'notifications' => 1,
193
  ) );
194
 
 
195
  require_once( buddypress()->plugin_dir . '/bp-core/admin/bp-core-admin-schema.php' );
196
  $switched_to_root_blog = false;
197
 
198
- // Make sure the current blog is set to the root blog
199
  if ( ! bp_is_root_blog() ) {
200
  switch_to_blog( bp_get_root_blog_id() );
201
  bp_register_taxonomies();
@@ -218,51 +218,56 @@ function bp_version_updater() {
218
  // Run the schema install to update tables.
219
  bp_core_install();
220
 
221
- // 1.5.0
222
  if ( $raw_db_version < 1801 ) {
223
  bp_update_to_1_5();
224
  bp_core_add_page_mappings( $default_components, 'delete' );
225
  }
226
 
227
- // 1.6.0
228
  if ( $raw_db_version < 6067 ) {
229
  bp_update_to_1_6();
230
  }
231
 
232
- // 1.9.0
233
  if ( $raw_db_version < 7553 ) {
234
  bp_update_to_1_9();
235
  }
236
 
237
- // 1.9.2
238
  if ( $raw_db_version < 7731 ) {
239
  bp_update_to_1_9_2();
240
  }
241
 
242
- // 2.0.0
243
  if ( $raw_db_version < 7892 ) {
244
  bp_update_to_2_0();
245
  }
246
 
247
- // 2.0.1
248
  if ( $raw_db_version < 8311 ) {
249
  bp_update_to_2_0_1();
250
  }
251
 
252
- // 2.2.0
253
  if ( $raw_db_version < 9181 ) {
254
  bp_update_to_2_2();
255
  }
256
 
257
- // 2.3.0
258
  if ( $raw_db_version < 9615 ) {
259
  bp_update_to_2_3();
260
  }
261
 
262
- // 2.5.0
263
  if ( $raw_db_version < 10440 ) {
264
  bp_update_to_2_5();
265
  }
 
 
 
 
 
266
  }
267
 
268
  /* All done! *************************************************************/
@@ -331,7 +336,7 @@ function bp_update_to_1_5() {
331
  }
332
 
333
  /**
334
- * Remove unused metadata from database when upgrading from < 1.6.
335
  *
336
  * Database update methods based on version numbers.
337
  *
@@ -380,7 +385,7 @@ function bp_update_to_1_9() {
380
  }
381
 
382
  /**
383
- * Perform database updates for BP 1.9.2
384
  *
385
  * In 1.9, BuddyPress stopped registering its theme directory when it detected
386
  * that bp-default (or a child theme) was not currently being used, in effect
@@ -389,6 +394,7 @@ function bp_update_to_1_9() {
389
  * bp-default would no longer be available, with no obvious way (outside of
390
  * a manual filter) to restore it. In 1.9.2, we add an option that flags
391
  * whether bp-default or a child theme is active at the time of upgrade; if so,
 
392
  * the theme directory will continue to be registered even if the theme is
393
  * deactivated temporarily. Thus, new installations will not see bp-default,
394
  * but legacy installations using the theme will continue to see it.
@@ -440,8 +446,6 @@ function bp_update_to_2_0() {
440
  * 2.0.1 database upgrade routine.
441
  *
442
  * @since 2.0.1
443
- *
444
- * @return void
445
  */
446
  function bp_update_to_2_0_1() {
447
 
@@ -501,6 +505,43 @@ function bp_update_to_2_5() {
501
  bp_core_install_emails();
502
  }
503
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  /**
505
  * Updates the component field for new_members type.
506
  *
@@ -539,7 +580,6 @@ function bp_migrate_new_member_activity_component() {
539
  * Remove all hidden friendship activities.
540
  *
541
  * @since 2.2.0
542
- *
543
  */
544
  function bp_cleanup_friendship_activities() {
545
  bp_activity_delete( array(
@@ -549,13 +589,61 @@ function bp_cleanup_friendship_activities() {
549
  ) );
550
  }
551
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
  /**
553
  * Redirect user to BP's What's New page on first page load after activation.
554
  *
555
  * @since 1.7.0
556
  *
557
  * @internal Used internally to redirect BuddyPress to the about page on activation.
558
- *
559
  */
560
  function bp_add_activation_redirect() {
561
 
@@ -624,7 +712,6 @@ function bp_core_maybe_install_signups() {
624
  * Runs on BuddyPress activation.
625
  *
626
  * @since 1.6.0
627
- *
628
  */
629
  function bp_activation() {
630
 
@@ -637,13 +724,13 @@ function bp_activation() {
637
  /**
638
  * Fires during the activation of BuddyPress.
639
  *
640
- * Use as of (1.6.0)
641
  *
642
  * @since 1.6.0
643
  */
644
  do_action( 'bp_activation' );
645
 
646
- // @deprecated as of (1.6)
647
  do_action( 'bp_loader_activate' );
648
  }
649
 
@@ -653,7 +740,6 @@ function bp_activation() {
653
  * Runs on BuddyPress deactivation.
654
  *
655
  * @since 1.6.0
656
- *
657
  */
658
  function bp_deactivation() {
659
 
@@ -671,13 +757,13 @@ function bp_deactivation() {
671
  /**
672
  * Fires during the deactivation of BuddyPress.
673
  *
674
- * Use as of (1.6.0)
675
  *
676
  * @since 1.6.0
677
  */
678
  do_action( 'bp_deactivation' );
679
 
680
- // @deprecated as of (1.6)
681
  do_action( 'bp_loader_deactivate' );
682
  }
683
 
@@ -687,7 +773,6 @@ function bp_deactivation() {
687
  * Runs when uninstalling BuddyPress.
688
  *
689
  * @since 1.6.0
690
- *
691
  */
692
  function bp_uninstall() {
693
 
139
  * Update the BP version stored in the database to the current version.
140
  *
141
  * @since 1.6.0
 
142
  */
143
  function bp_version_bump() {
144
  bp_update_option( '_bp_db_version', bp_get_db_version() );
191
  'notifications' => 1,
192
  ) );
193
 
194
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
195
  require_once( buddypress()->plugin_dir . '/bp-core/admin/bp-core-admin-schema.php' );
196
  $switched_to_root_blog = false;
197
 
198
+ // Make sure the current blog is set to the root blog.
199
  if ( ! bp_is_root_blog() ) {
200
  switch_to_blog( bp_get_root_blog_id() );
201
  bp_register_taxonomies();
218
  // Run the schema install to update tables.
219
  bp_core_install();
220
 
221
+ // Version 1.5.0.
222
  if ( $raw_db_version < 1801 ) {
223
  bp_update_to_1_5();
224
  bp_core_add_page_mappings( $default_components, 'delete' );
225
  }
226
 
227
+ // Version 1.6.0.
228
  if ( $raw_db_version < 6067 ) {
229
  bp_update_to_1_6();
230
  }
231
 
232
+ // Version 1.9.0.
233
  if ( $raw_db_version < 7553 ) {
234
  bp_update_to_1_9();
235
  }
236
 
237
+ // Version 1.9.2.
238
  if ( $raw_db_version < 7731 ) {
239
  bp_update_to_1_9_2();
240
  }
241
 
242
+ // Version 2.0.0.
243
  if ( $raw_db_version < 7892 ) {
244
  bp_update_to_2_0();
245
  }
246
 
247
+ // Version 2.0.1.
248
  if ( $raw_db_version < 8311 ) {
249
  bp_update_to_2_0_1();
250
  }
251
 
252
+ // Version 2.2.0.
253
  if ( $raw_db_version < 9181 ) {
254
  bp_update_to_2_2();
255
  }
256
 
257
+ // Version 2.3.0.
258
  if ( $raw_db_version < 9615 ) {
259
  bp_update_to_2_3();
260
  }
261
 
262
+ // Version 2.5.0.
263
  if ( $raw_db_version < 10440 ) {
264
  bp_update_to_2_5();
265
  }
266
+
267
+ // Version 2.7.0.
268
+ if ( $raw_db_version < 11105 ) {
269
+ bp_update_to_2_7();
270
+ }
271
  }
272
 
273
  /* All done! *************************************************************/
336
  }
337
 
338
  /**
339
+ * Remove unused metadata from database when upgrading from < 1.6.0.
340
  *
341
  * Database update methods based on version numbers.
342
  *
385
  }
386
 
387
  /**
388
+ * Perform database updates for BP 1.9.2.
389
  *
390
  * In 1.9, BuddyPress stopped registering its theme directory when it detected
391
  * that bp-default (or a child theme) was not currently being used, in effect
394
  * bp-default would no longer be available, with no obvious way (outside of
395
  * a manual filter) to restore it. In 1.9.2, we add an option that flags
396
  * whether bp-default or a child theme is active at the time of upgrade; if so,
397
+ *
398
  * the theme directory will continue to be registered even if the theme is
399
  * deactivated temporarily. Thus, new installations will not see bp-default,
400
  * but legacy installations using the theme will continue to see it.
446
  * 2.0.1 database upgrade routine.
447
  *
448
  * @since 2.0.1
 
 
449
  */
450
  function bp_update_to_2_0_1() {
451
 
505
  bp_core_install_emails();
506
  }
507
 
508
+ /**
509
+ * 2.7.0 update routine.
510
+ *
511
+ * - Add email unsubscribe salt.
512
+ * - Save legacy directory titles to the corresponding WP pages.
513
+ * - Add ignore deprecated code option (false for updates).
514
+ *
515
+ * @since 2.7.0
516
+ */
517
+ function bp_update_to_2_7() {
518
+ bp_add_option( 'bp-emails-unsubscribe-salt', base64_encode( wp_generate_password( 64, true, true ) ) );
519
+
520
+ // Update post_titles
521
+ bp_migrate_directory_page_titles();
522
+
523
+ /*
524
+ * Add `parent_id` column to groups table.
525
+ * Also handled by `bp_core_install()`.
526
+ */
527
+ if ( bp_is_active( 'groups' ) ) {
528
+ bp_core_install_groups();
529
+
530
+ // Invalidate all cached group objects.
531
+ global $wpdb;
532
+ $bp = buddypress();
533
+
534
+ $group_ids = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name}" );
535
+
536
+ foreach ( $group_ids as $group_id ) {
537
+ wp_cache_delete( $group_id, 'bp_groups' );
538
+ }
539
+ }
540
+
541
+ // Do not ignore deprecated code for existing installs.
542
+ bp_add_option( '_bp_ignore_deprecated_code', false );
543
+ }
544
+
545
  /**
546
  * Updates the component field for new_members type.
547
  *
580
  * Remove all hidden friendship activities.
581
  *
582
  * @since 2.2.0
 
583
  */
584
  function bp_cleanup_friendship_activities() {
585
  bp_activity_delete( array(
589
  ) );
590
  }
591
 
592
+ /**
593
+ * Update WP pages so that their post_title matches the legacy component directory title.
594
+ *
595
+ * As of 2.7.0, component directory titles come from the `post_title` attribute of the corresponding WP post object,
596
+ * instead of being hardcoded. To ensure that directory titles don't change for existing installations, we update these
597
+ * WP posts with the formerly hardcoded titles.
598
+ *
599
+ * @since 2.7.0
600
+ */
601
+ function bp_migrate_directory_page_titles() {
602
+ $bp_pages = bp_core_get_directory_page_ids( 'all' );
603
+
604
+ $default_titles = bp_core_get_directory_page_default_titles();
605
+
606
+ $legacy_titles = array(
607
+ 'activity' => _x( 'Site-Wide Activity', 'component directory title', 'buddypress' ),
608
+ 'blogs' => _x( 'Sites', 'component directory title', 'buddypress' ),
609
+ 'groups' => _x( 'Groups', 'component directory title', 'buddypress' ),
610
+ 'members' => _x( 'Members', 'component directory title', 'buddypress' ),
611
+ );
612
+
613
+ foreach ( $bp_pages as $component => $page_id ) {
614
+ if ( ! isset( $legacy_titles[ $component ] ) ) {
615
+ continue;
616
+ }
617
+
618
+ $page = get_post( $page_id );
619
+ if ( ! $page ) {
620
+ continue;
621
+ }
622
+
623
+ // If the admin has changed the default title, don't touch it.
624
+ if ( isset( $default_titles[ $component ] ) && $default_titles[ $component ] !== $page->post_title ) {
625
+ continue;
626
+ }
627
+
628
+ // If the saved page title is the same as the legacy title, there's nothing to do.
629
+ if ( $legacy_titles[ $component ] == $page->post_title ) {
630
+ continue;
631
+ }
632
+
633
+ // Update the page with the legacy title.
634
+ wp_update_post( array(
635
+ 'ID' => $page_id,
636
+ 'post_title' => $legacy_titles[ $component ],
637
+ ) );
638
+ }
639
+ }
640
+
641
  /**
642
  * Redirect user to BP's What's New page on first page load after activation.
643
  *
644
  * @since 1.7.0
645
  *
646
  * @internal Used internally to redirect BuddyPress to the about page on activation.
 
647
  */
648
  function bp_add_activation_redirect() {
649
 
712
  * Runs on BuddyPress activation.
713
  *
714
  * @since 1.6.0
 
715
  */
716
  function bp_activation() {
717
 
724
  /**
725
  * Fires during the activation of BuddyPress.
726
  *
727
+ * Use as of 1.6.0.
728
  *
729
  * @since 1.6.0
730
  */
731
  do_action( 'bp_activation' );
732
 
733
+ // @deprecated as of 1.6.0
734
  do_action( 'bp_loader_activate' );
735
  }
736
 
740
  * Runs on BuddyPress deactivation.
741
  *
742
  * @since 1.6.0
 
743
  */
744
  function bp_deactivation() {
745
 
757
  /**
758
  * Fires during the deactivation of BuddyPress.
759
  *
760
+ * Use as of 1.6.0.
761
  *
762
  * @since 1.6.0
763
  */
764
  do_action( 'bp_deactivation' );
765
 
766
+ // @deprecated as of 1.6.0
767
  do_action( 'bp_loader_deactivate' );
768
  }
769
 
773
  * Runs when uninstalling BuddyPress.
774
  *
775
  * @since 1.6.0
 
776
  */
777
  function bp_uninstall() {
778
 
bp-core/bp-core-widgets.php CHANGED
@@ -10,16 +10,12 @@
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
13
- if ( ! buddypress()->do_autoload ) {
14
- require dirname( __FILE__ ) . '/classes/class-bp-core-login-widget.php';
15
- }
16
-
17
  /**
18
  * Register bp-core widgets.
19
  *
20
  * @since 1.0.0
21
  */
22
  function bp_core_register_widgets() {
23
- add_action('widgets_init', create_function('', 'return register_widget("BP_Core_Login_Widget");') );
24
  }
25
  add_action( 'bp_register_widgets', 'bp_core_register_widgets' );
10
  // Exit if accessed directly.
11
  defined( 'ABSPATH' ) || exit;
12
 
 
 
 
 
13
  /**
14
  * Register bp-core widgets.
15
  *
16
  * @since 1.0.0
17
  */
18
  function bp_core_register_widgets() {
19
+ add_action( 'widgets_init', function() { register_widget( 'BP_Core_Login_Widget' ); } );
20
  }
21
  add_action( 'bp_register_widgets', 'bp_core_register_widgets' );
bp-core/bp-core-wpabstraction.php CHANGED
@@ -23,7 +23,7 @@ defined( 'ABSPATH' ) || exit;
23
  *
24
  * @global string $wp_version
25
  *
26
- * @return string $wp_version
27
  */
28
  function bp_get_major_wp_version() {
29
  global $wp_version;
@@ -52,7 +52,6 @@ if ( !is_multisite() ) {
52
  * @param int $blog_id Blog ID to fetch for. Not used.
53
  * @param string $option_name Option name to fetch.
54
  * @param bool $default Whether or not default.
55
- *
56
  * @return mixed
57
  */
58
  function get_blog_option( $blog_id, $option_name, $default = false ) {
@@ -72,7 +71,6 @@ if ( !is_multisite() ) {
72
  * @param int $blog_id Blog ID to add for. Not used.
73
  * @param string $option_name Option name to add.
74
  * @param mixed $option_value Option value to add.
75
- *
76
  * @return mixed
77
  */
78
  function add_blog_option( $blog_id, $option_name, $option_value ) {
@@ -92,7 +90,6 @@ if ( !is_multisite() ) {
92
  * @param int $blog_id Blog ID to update for. Not used.
93
  * @param string $option_name Option name to update.
94
  * @param mixed $value Option value to update.
95
- *
96
  * @return mixed
97
  */
98
  function update_blog_option( $blog_id, $option_name, $value ) {
@@ -111,7 +108,6 @@ if ( !is_multisite() ) {
111
  *
112
  * @param int $blog_id Blog ID to delete for. Not used.
113
  * @param string $option_name Option name to delete.
114
- *
115
  * @return mixed
116
  */
117
  function delete_blog_option( $blog_id, $option_name ) {
@@ -130,7 +126,6 @@ if ( !is_multisite() ) {
130
  *
131
  * @param mixed $new_blog New blog to switch to. Not used.
132
  * @param null $deprecated Whether or not deprecated. Not used.
133
- *
134
  * @return int
135
  */
136
  function switch_to_blog( $new_blog, $deprecated = null ) {
@@ -165,8 +160,7 @@ if ( !is_multisite() ) {
165
  *
166
  * @param int $user_id ID of the user. Not used.
167
  * @param bool $all Whether or not to return all. Not used.
168
- *
169
- * @return false
170
  */
171
  function get_blogs_of_user( $user_id, $all = false ) {
172
  return false;
@@ -186,8 +180,7 @@ if ( !is_multisite() ) {
186
  * @param mixed $pref Preference. Not used.
187
  * @param string $value Value. Not used.
188
  * @param null $deprecated Whether or not deprecated. Not used.
189
- *
190
- * @return true
191
  */
192
  function update_blog_status( $blog_id, $pref, $value, $deprecated = null ) {
193
  return true;
@@ -273,7 +266,7 @@ if ( !function_exists( 'mb_strpos' ) ) {
273
  * @param string $needle String to search for.
274
  * @param int $offset Optional. Start position for the search. Default: 0.
275
  * @param string $encoding Optional. Encoding type. Ignored.
276
- * @return int|bool Position of needle in haystack if found, else false.
277
  */
278
  function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
279
  $needle = preg_quote( $needle, '/' );
@@ -298,7 +291,7 @@ if ( !function_exists( 'mb_strrpos' ) ) {
298
  * @param string $needle String to search for.
299
  * @param int $offset Optional. Start position for the search. Default: 0.
300
  * @param string $encoding Optional. Encoding type. Ignored.
301
- * @return int Position of last needle in haystack if found, else false.
302
  */
303
  function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
304
  $needle = preg_quote( $needle, '/' );
23
  *
24
  * @global string $wp_version
25
  *
26
+ * @return double $wp_version
27
  */
28
  function bp_get_major_wp_version() {
29
  global $wp_version;
52
  * @param int $blog_id Blog ID to fetch for. Not used.
53
  * @param string $option_name Option name to fetch.
54
  * @param bool $default Whether or not default.
 
55
  * @return mixed
56
  */
57
  function get_blog_option( $blog_id, $option_name, $default = false ) {
71
  * @param int $blog_id Blog ID to add for. Not used.
72
  * @param string $option_name Option name to add.
73
  * @param mixed $option_value Option value to add.
 
74
  * @return mixed
75
  */
76
  function add_blog_option( $blog_id, $option_name, $option_value ) {
90
  * @param int $blog_id Blog ID to update for. Not used.
91
  * @param string $option_name Option name to update.
92
  * @param mixed $value Option value to update.
 
93
  * @return mixed
94
  */
95
  function update_blog_option( $blog_id, $option_name, $value ) {
108
  *
109
  * @param int $blog_id Blog ID to delete for. Not used.
110
  * @param string $option_name Option name to delete.
 
111
  * @return mixed
112
  */
113
  function delete_blog_option( $blog_id, $option_name ) {
126
  *
127
  * @param mixed $new_blog New blog to switch to. Not used.
128
  * @param null $deprecated Whether or not deprecated. Not used.
 
129
  * @return int
130
  */
131
  function switch_to_blog( $new_blog, $deprecated = null ) {
160
  *
161
  * @param int $user_id ID of the user. Not used.
162
  * @param bool $all Whether or not to return all. Not used.
163
+ * @return bool
 
164
  */
165
  function get_blogs_of_user( $user_id, $all = false ) {
166
  return false;
180
  * @param mixed $pref Preference. Not used.
181
  * @param string $value Value. Not used.
182
  * @param null $deprecated Whether or not deprecated. Not used.
183
+ * @return bool
 
184
  */
185
  function update_blog_status( $blog_id, $pref, $value, $deprecated = null ) {
186
  return true;
266
  * @param string $needle String to search for.
267
  * @param int $offset Optional. Start position for the search. Default: 0.
268
  * @param string $encoding Optional. Encoding type. Ignored.
269
+ * @return int|false Position of needle in haystack if found, else false.
270
  */
271
  function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
272
  $needle = preg_quote( $needle, '/' );
291
  * @param string $needle String to search for.
292
  * @param int $offset Optional. Start position for the search. Default: 0.
293
  * @param string $encoding Optional. Encoding type. Ignored.
294
+ * @return string|false Position of last needle in haystack if found, else false.
295
  */
296
  function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
297
  $needle = preg_quote( $needle, '/' );
bp-core/classes/class-bp-admin.php CHANGED
@@ -117,10 +117,6 @@ class BP_Admin {
117
  * @since 1.6.0
118
  */
119
  private function includes() {
120
- if ( ! buddypress()->do_autoload ) {
121
- require( $this->admin_dir . 'bp-core-admin-classes.php' );
122
- }
123
-
124
  require( $this->admin_dir . 'bp-core-admin-actions.php' );
125
  require( $this->admin_dir . 'bp-core-admin-settings.php' );
126
  require( $this->admin_dir . 'bp-core-admin-functions.php' );
@@ -193,8 +189,6 @@ class BP_Admin {
193
  * Contextually hooked to site or network-admin depending on current configuration.
194
  *
195
  * @since 1.6.0
196
- *
197
- * section.
198
  */
199
  public function admin_menus() {
200
 
@@ -342,27 +336,24 @@ class BP_Admin {
342
 
343
  $hooks = array();
344
 
345
- // Require WP 4.0+.
346
- if ( bp_is_root_blog() && version_compare( $GLOBALS['wp_version'], '4.0', '>=' ) ) {
347
- // Appearance > Emails.
348
- $hooks[] = add_theme_page(
349
- _x( 'Emails', 'screen heading', 'buddypress' ),
350
- _x( 'Emails', 'screen heading', 'buddypress' ),
351
- $this->capability,
352
- 'bp-emails-customizer-redirect',
353
- 'bp_email_redirect_to_customizer'
354
- );
355
 
356
- // Emails > Customize.
357
- $hooks[] = add_submenu_page(
358
- 'edit.php?post_type=' . bp_get_email_post_type(),
359
- _x( 'Customize', 'email menu label', 'buddypress' ),
360
- _x( 'Customize', 'email menu label', 'buddypress' ),
361
- $this->capability,
362
- 'bp-emails-customizer-redirect',
363
- 'bp_email_redirect_to_customizer'
364
- );
365
- }
366
 
367
  foreach( $hooks as $hook ) {
368
  add_action( "admin_head-$hook", 'bp_core_modify_admin_menu_highlight' );
@@ -388,6 +379,11 @@ class BP_Admin {
388
 
389
  // Only show 'switch to Toolbar' option if the user chose to retain the BuddyBar during the 1.6 upgrade.
390
  if ( (bool) bp_get_option( '_bp_force_buddybar', false ) ) {
 
 
 
 
 
391
  add_settings_field( '_bp_force_buddybar', __( 'Toolbar', 'buddypress' ), 'bp_admin_setting_callback_force_buddybar', 'buddypress', 'bp_main' );
392
  register_setting( 'buddypress', '_bp_force_buddybar', 'bp_admin_sanitize_callback_force_buddybar' );
393
  }
@@ -396,6 +392,10 @@ class BP_Admin {
396
  add_settings_field( 'bp-disable-account-deletion', __( 'Account Deletion', 'buddypress' ), 'bp_admin_setting_callback_account_deletion', 'buddypress', 'bp_main' );
397
  register_setting( 'buddypress', 'bp-disable-account-deletion', 'intval' );
398
 
 
 
 
 
399
  /* XProfile Section **************************************************/
400
 
401
  if ( bp_is_active( 'xprofile' ) ) {
@@ -440,18 +440,6 @@ class BP_Admin {
440
  }
441
  }
442
 
443
- /* Forums ************************************************************/
444
-
445
- if ( bp_is_active( 'forums' ) ) {
446
-
447
- // Add the main section.
448
- add_settings_section( 'bp_forums', __( 'Legacy Group Forums', 'buddypress' ), 'bp_admin_setting_callback_bbpress_section', 'buddypress' );
449
-
450
- // Allow subscriptions setting.
451
- add_settings_field( 'bb-config-location', __( 'bbPress Configuration', 'buddypress' ), 'bp_admin_setting_callback_bbpress_configuration', 'buddypress', 'bp_forums' );
452
- register_setting( 'buddypress', 'bb-config-location', '' );
453
- }
454
-
455
  /* Activity Section **************************************************/
456
 
457
  if ( bp_is_active( 'activity' ) ) {
@@ -459,8 +447,8 @@ class BP_Admin {
459
  // Add the main section.
460
  add_settings_section( 'bp_activity', __( 'Activity Settings', 'buddypress' ), 'bp_admin_setting_callback_activity_section', 'buddypress' );
461
 
462
- // Activity commenting on blog and forum posts.
463
- add_settings_field( 'bp-disable-blogforum-comments', __( 'Blog &amp; Forum Comments', 'buddypress' ), 'bp_admin_setting_callback_blogforum_comments', 'buddypress', 'bp_activity' );
464
  register_setting( 'buddypress', 'bp-disable-blogforum-comments', 'bp_admin_sanitize_callback_blogforum_comments' );
465
 
466
  // Activity Heartbeat refresh.
@@ -564,7 +552,7 @@ class BP_Admin {
564
 
565
  <div id="welcome-panel" class="welcome-panel">
566
  <div class="welcome-panel-content">
567
- <h3 style="margin:0"><?php _e( 'Getting Started with BuddyPress', 'buddypress' ); ?></h3>
568
  <div class="welcome-panel-column-container">
569
  <div class="welcome-panel-column">
570
  <h4><?php _e( 'Configure BuddyPress', 'buddypress' ); ?></h4>
@@ -585,16 +573,16 @@ class BP_Admin {
585
  <h4><?php _e( 'Administration Tools', 'buddypress' ); ?></h4>
586
  <ul>
587
  <?php if ( bp_is_active( 'members' ) ) : ?>
588
- <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Add User Profile Fields', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-profile-setup' ), 'users.php' ) ) ) ); ?></li>
589
  <?php endif; ?>
590
- <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Manage User Signups', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-signups' ), 'users.php' ) ) ) ); ?></li>
591
  <?php if ( bp_is_active( 'activity' ) ) : ?>
592
- <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Moderate Activity Streams', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-activity' ), 'admin.php' ) ) ) ); ?></li>
593
  <?php endif; ?>
594
  <?php if ( bp_is_active( 'groups' ) ) : ?>
595
- <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Manage Groups', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-groups' ), 'admin.php' ) ) ) ); ?></li>
596
  <?php endif; ?>
597
- <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Repair Data', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-tools' ), 'tools.php' ) ) ) ); ?>
598
  </li>
599
  </ul>
600
  </div>
@@ -609,76 +597,88 @@ class BP_Admin {
609
 
610
  <?php endif; ?>
611
 
612
- <div class="headline-feature">
613
- <h3 class="headline-title"><?php esc_html_e( 'Customizable BuddyPress Emails', 'buddypress' ); ?></h3>
 
614
 
615
- <div class="featured-image">
616
- <img src="<?php echo esc_url( buddypress()->plugin_url . 'bp-core/admin/images/bp-emails-feature.png' ); ?>" alt="<?php esc_html_e( 'Change colors of the email template using the Customizer.', 'buddypress' ); ?>">
 
 
617
  </div>
618
 
619
- <p class="introduction"><?php _e( 'Keep your users coming back with beautiful and flexible email notifications.', 'buddypress' ); ?> </p>
620
- <p><?php _e( 'Edit the content of your emails, create new email templates, or change the design of the template in the Customizer. These are just a few of the customizations you can make to engage your users and increase their participation in your community with the new email features.', 'buddypress' ); ?> <a href="https://codex.buddypress.org/emails/"><?php esc_html_e( 'Learn more &rarr;', 'buddypress' ); ?></a></p>
621
-
622
- <div class="clear"></div>
623
- </div>
624
 
625
- <hr />
 
 
 
 
626
 
627
- <div class="bp-features-section">
 
 
628
 
629
- <div class="feature-section two-col">
630
- <div>
631
- <h3 class="feature-title"><?php esc_html_e( 'Post Type Comments Tracking', 'buddypress' ); ?></h3>
632
- <img src="<?php echo esc_url( buddypress()->plugin_url . 'bp-core/admin/images/post-type.png' ); ?>" alt="<?php esc_attr_e( 'Registered post types', 'buddypress' ); ?>">
633
- <p><?php esc_html_e( 'New Activity functions help you track post type comments in sync with the Blogs component when activated.', 'buddypress' ); ?></p>
634
- </div>
635
- <div class="last-feature">
636
- <h3 class="feature-title"><?php esc_html_e( 'Twenty Twelve Companion Stylesheet', 'buddypress' ); ?></h3>
637
- <img src="<?php echo esc_url( buddypress()->plugin_url . 'bp-core/admin/images/twentytwelve.png' ); ?>" alt="<?php esc_attr_e( 'BuddyPress styles Twenty Twelve', 'buddypress' ); ?>">
638
- <p><?php esc_html_e( 'BuddyPress components never looked so fine as they do now in the Twenty Twelve theme.', 'buddypress' ); ?></p>
639
- </div>
640
  </div>
641
 
642
- <div class="feature-section two-col">
643
- <div>
644
- <h3 class="feature-title"><?php esc_html_e( 'Support for emoji', 'buddypress' ); ?></h3>
645
- <img src="<?php echo esc_url( buddypress()->plugin_url . 'bp-core/admin/images/emoji-feature.png' ); ?>" alt="<?php esc_attr_e( 'Fun with emoji', 'buddypress' ); ?>">
646
- <p><?php esc_html_e( 'Have fun and be merry! You can now use emoji in activity updates, messages, and group descriptions.', 'buddypress' ); ?></p>
647
 
 
 
 
 
 
648
  </div>
649
- <div class="last-feature">
650
- <h3 class="feature-title"><?php esc_html_e( 'Autolink Settings for Profile Fields', 'buddypress' ); ?></h3>
651
- <img src="<?php echo esc_url( buddypress()->plugin_url . 'bp-core/admin/images/autolink-feature.png' ); ?>" alt="<?php esc_attr_e( 'Autolink settings in the profile fields panel', 'buddypress' ); ?>">
652
- <p><?php _e( 'Administrators can enable or disable autolink settings for each new profile field type.', 'buddypress' ); ?></p>
653
  </div>
654
- </div>
655
-
656
- </div>
657
 
658
- <div class="changelog">
659
- <h3 class="changelog-title"><?php esc_html_e( 'Under The Hood', 'buddypress' ); ?></h3>
 
 
 
660
 
661
- <div class="feature-section col two-col">
662
- <div>
663
- <h4 class="title"><?php esc_html_e( 'Localization Improvements', 'buddypress' ); ?></h4>
664
- <p><?php esc_html_e( 'We continue to improve on localization for translation editors so that BuddyPress will be available for everyone in their own language.', 'buddypress' ); ?></p>
665
- <h4 class="title"><?php esc_html_e( 'Accessibility Upgrades', 'buddypress' ); ?></h4>
666
- <p><?php esc_html_e( 'Continued improvements in the frontend and backend to make BuddyPress usable for everyone.', 'buddypress' ); ?></p>
 
 
 
 
 
 
667
  </div>
668
 
669
- <div class="last-feature">
670
- <h4 class="title"><?php esc_html_e( 'Enhanced Multisite Support', 'buddypress' ); ?></h4>
671
- <p><?php esc_html_e( 'BuddyPress is already primed for all multisite configurations available. We just made it better.', 'buddypress' ); ?></p>
672
- <h4 class="title"><?php esc_html_e( 'Developer Reference', 'buddypress' ); ?></h4>
673
- <p><?php esc_html_e( 'Regular updates to inline code documentation make it easier for developers to understand how BuddyPress works.', 'buddypress' ); ?></p>
 
 
674
  </div>
675
  </div>
676
 
677
  </div>
678
 
679
- <p><?php _ex( 'Learn more:', 'About screen, website links', 'buddypress' ); ?> <a href="https://buddypress.org/blog/"><?php _ex( 'News', 'About screen, link to project blog', 'buddypress' ); ?></a> &bullet; <a href="https://buddypress.org/support/"><?php _ex( 'Support', 'About screen, link to support site', 'buddypress' ); ?></a> &bullet; <a href="https://codex.buddypress.org/"><?php _ex( 'Documentation', 'About screen, link to documentation', 'buddypress' ); ?></a> &bullet; <a href="https://bpdevel.wordpress.com/"><?php _ex( 'Development Blog', 'About screen, link to development blog', 'buddypress' ); ?></a></p>
 
680
 
681
- <p><?php _ex( 'Twitter:', 'official Twitter accounts:', 'buddypress' ); ?> <a href="https://twitter.com/buddypress/"><?php _ex( 'BuddyPress', '@buddypress twitter account name', 'buddypress' ); ?></a> &bullet; <a href="https://twitter.com/bptrac/"><?php _ex( 'Trac', '@bptrac twitter account name', 'buddypress' ); ?></a> &bullet; <a href="https://twitter.com/buddypressdev/"><?php _ex( 'Development', '@buddypressdev twitter account name', 'buddypress' ); ?></a></p>
 
682
 
683
  </div>
684
 
@@ -707,7 +707,7 @@ class BP_Admin {
707
  <h3 class="wp-people-group"><?php _e( 'Project Leaders', 'buddypress' ); ?></h3>
708
  <ul class="wp-people-group " id="wp-people-group-project-leaders">
709
  <li class="wp-person" id="wp-person-johnjamesjacoby">
710
- <a class="web" href="https://profiles.wordpress.org/johnjamesjacoby"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/81ec16063d89b162d55efe72165c105f?s=60">
711
  John James Jacoby</a>
712
  <span class="title"><?php _e( 'Project Lead', 'buddypress' ); ?></span>
713
  </li>
@@ -723,8 +723,13 @@ class BP_Admin {
723
  </li>
724
  </ul>
725
 
726
- <h3 class="wp-people-group"><?php _e( 'Core Team', 'buddypress' ); ?></h3>
727
  <ul class="wp-people-group " id="wp-people-group-core-team">
 
 
 
 
 
728
  <li class="wp-person" id="wp-person-r-a-y">
729
  <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3bfa556a62b5bfac1012b6ba5f42ebfa?s=60">
730
  Ray</a>
@@ -750,74 +755,106 @@ class BP_Admin {
750
  Michael Beckwith</a>
751
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
752
  </li>
753
- <li class="wp-person" id="wp-person-hnla">
754
- <a class="web" href="https://profiles.wordpress.org/hnla"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3860c955aa3f79f13b92826ae47d07fe?s=60">
755
- Hugo</a>
756
- <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
757
- </li>
758
- </ul>
759
-
760
- <h3 class="wp-people-group"><?php _e( '&#x1f31f;Recent Rockstars&#x1f31f;', 'buddypress' ); ?></h3>
761
- <ul class="wp-people-group " id="wp-people-group-rockstars">
762
  <li class="wp-person" id="wp-person-henry-wright">
763
  <a class="web" href="https://profiles.wordpress.org/henry.wright"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0da2f1a9340d6af196b870f6c107a248?s=60">
764
  Henry Wright</a>
 
765
  </li>
766
  <li class="wp-person" id="wp-person-danbp">
767
  <a class="web" href="https://profiles.wordpress.org/danbp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0deae2e7003027fbf153500cd3fa5501?s=60">
768
  danbp</a>
 
769
  </li>
770
  <li class="wp-person" id="wp-person-shanebp">
771
  <a class="web" href="https://profiles.wordpress.org/shanebp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ffd294ab5833ba14aaf175f9acc71cc4?s=60">
772
  shanebp</a>
 
 
 
 
 
 
 
 
 
 
 
773
  </li>
774
  <li class="wp-person" id="wp-person-netweb">
775
  <a class="web" href="https://profiles.wordpress.org/netweb"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/97e1620b501da675315ba7cfb740e80f?s=60">
776
  Stephen Edgar</a>
 
777
  </li>
 
 
 
 
778
  <li class="wp-person" id="wp-person-dimensionmedia">
779
  <a class="web" href="https://profiles.wordpress.org/dimensionmedia"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7735aada1ec39d0c1118bd92ed4551f1?s=60">
780
  David Bisset</a>
781
  </li>
782
-
 
 
 
 
 
 
 
 
 
 
 
783
  </ul>
784
 
785
  <h3 class="wp-people-group"><?php printf( esc_html__( 'Contributors to BuddyPress %s', 'buddypress' ), self::display_version() ); ?></h3>
786
  <p class="wp-credits-list">
 
 
 
 
 
787
  <a href="https://profiles.wordpress.org/boonebgorges/">Boone B Gorges (boonebgorges)</a>,
 
788
  <a href="https://profiles.wordpress.org/sbrajesh/">Brajesh Singh (sbrajesh)</a>,
789
- <a href="https://profiles.wordpress.org/thebrandonallen/">Brandon Allen (thebrandonallen)</a>,
790
  <a href="https://profiles.wordpress.org/needle/">Christian Wach (needle)</a>,
791
- <a href="https://profiles.wordpress.org/timersys/">Damian (timersys)</a>,
792
- <a href="https://profiles.wordpress.org/danbrellis/">danbrellis</a>,
793
  <a href="https://profiles.wordpress.org/dcavins/">David Cavins (dcavins)</a>,
794
- <a href="https://profiles.wordpress.org/wpdennis/">Dennis (wpdennis)</a>,
795
- <a href="https://profiles.wordpress.org/wdfee/">Fee (wdfee)</a>,
796
- <a href="https://profiles.wordpress.org/garrett-eclipse/">Garrett Hyder (garrett-eclipse)</a>,
797
- <a href="https://profiles.wordpress.org/Mamaduka/">George Mamadashvili (Mamaduka)</a>,
798
- <a href="https://profiles.wordpress.org/henrywright/">Henry Wright (henry.wright)</a>,
799
  <a href="https://profiles.wordpress.org/hnla/">Hugo (hnla)</a>,
800
- <a href="https://profiles.wordpress.org/jeffsayre/">Jeff Sayre (jeffsayre)</a>,
 
 
801
  <a href="https://profiles.wordpress.org/johnjamesjacoby/">John James Jacoby (johnjamesjacoby)</a>,
802
- <a href="https://profiles.wordpress.org/Jonnyauk/">Jonnyauk</a>,
803
- <a href="https://profiles.wordpress.org/joost-abrahams/">Joost Abrahams (joost-abrahams)</a>,
804
- <a href="https://profiles.wordpress.org/kennibc/">kennibc</a>,
805
- <a href="https://profiles.wordpress.org/sooskriszta/">OC2PS (sooskriszta)</a>,
806
  <a href="https://profiles.wordpress.org/Offereins">Laurens Offereins (Offereins)</a>,
807
- <a href="https://profiles.wordpress.org/LenLay/">LenLay</a>,
 
 
808
  <a href="https://profiles.wordpress.org/imath/">Mathieu Viet (imath)</a>,
809
  <a href="https://profiles.wordpress.org/mercime/">mercime</a>,
810
  <a href="https://profiles.wordpress.org/tw2113/">Michael Beckwith (tw2113)</a>,
 
 
811
  <a href="https://profiles.wordpress.org/modemlooper/">modemlooper</a>,
 
 
 
812
  <a href="https://profiles.wordpress.org/DJPaul/">Paul Gibbs (DJPaul)</a>,
813
- <a href="https://profiles.wordpress.org/ramiy/">Rami Yushuvaev (ramiy)</a>,
814
  <a href="https://profiles.wordpress.org/r-a-y/">r-a-y</a>,
815
- <a href="https://profiles.wordpress.org/shanebp/">shanebp</a>,
816
- <a href="https://profiles.wordpress.org/slaffik/">Slava UA (slaffik)</a>,
817
- <a href="https://profiles.wordpress.org/jozik/">Srdjan (jozik)</a>,
 
 
818
  <a href="https://profiles.wordpress.org/netweb/">Stephen Edgar (netweb)</a>,
819
- <a href="https://profiles.wordpress.org/timeuser/">timeuser</a>,
820
- <a href="https://profiles.wordpress.org/vnd/">vnd</a>.
821
  </p>
822
 
823
  <h3 class="wp-people-group"><?php _e( '&#x1f496;With our thanks to these Open Source projects&#x1f496;', 'buddypress' ); ?></h3>
@@ -825,10 +862,12 @@ class BP_Admin {
825
  <a href="https://github.com/ichord/At.js">At.js</a>,
826
  <a href="https://bbpress.org">bbPress</a>,
827
  <a href="https://github.com/ichord/Caret.js">Caret.js</a>,
828
- <a href="http://tedgoas.github.io/Cerberus/">Cerberus</a>,
829
- <a href="http://ionicons.com/">Ionicons</a>,
830
  <a href="https://github.com/carhartl/jquery-cookie">jquery.cookie</a>,
 
831
  <a href="https://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a>,
 
832
  <a href="https://wordpress.org">WordPress</a>.
833
  </p>
834
 
@@ -846,8 +885,8 @@ class BP_Admin {
846
 
847
  // Switch welcome text based on whether this is a new installation or not.
848
  $welcome_text = ( self::is_new_install() )
849
- ? __( 'Thank you for installing BuddyPress! BuddyPress helps you build any type of community website using WordPress, with member profiles, activity streams, user groups, messaging, and more.', 'buddypress' )
850
- : __( 'Thank you for updating! BuddyPress %s has many new features that you will enjoy.', 'buddypress' );
851
 
852
  ?>
853
 
@@ -896,7 +935,7 @@ class BP_Admin {
896
  *
897
  * @since 2.6.0
898
  *
899
- * @param array $columns Current column data.
900
  * @return array
901
  */
902
  public function emails_register_situation_column( $columns = array() ) {
117
  * @since 1.6.0
118
  */
119
  private function includes() {
 
 
 
 
120
  require( $this->admin_dir . 'bp-core-admin-actions.php' );
121
  require( $this->admin_dir . 'bp-core-admin-settings.php' );
122
  require( $this->admin_dir . 'bp-core-admin-functions.php' );
189
  * Contextually hooked to site or network-admin depending on current configuration.
190
  *
191
  * @since 1.6.0
 
 
192
  */
193
  public function admin_menus() {
194
 
336
 
337
  $hooks = array();
338
 
339
+ // Appearance > Emails.
340
+ $hooks[] = add_theme_page(
341
+ _x( 'Emails', 'screen heading', 'buddypress' ),
342
+ _x( 'Emails', 'screen heading', 'buddypress' ),
343
+ $this->capability,
344
+ 'bp-emails-customizer-redirect',
345
+ 'bp_email_redirect_to_customizer'
346
+ );
 
 
347
 
348
+ // Emails > Customize.
349
+ $hooks[] = add_submenu_page(
350
+ 'edit.php?post_type=' . bp_get_email_post_type(),
351
+ _x( 'Customize', 'email menu label', 'buddypress' ),
352
+ _x( 'Customize', 'email menu label', 'buddypress' ),
353
+ $this->capability,
354
+ 'bp-emails-customizer-redirect',
355
+ 'bp_email_redirect_to_customizer'
356
+ );
 
357
 
358
  foreach( $hooks as $hook ) {
359
  add_action( "admin_head-$hook", 'bp_core_modify_admin_menu_highlight' );
379
 
380
  // Only show 'switch to Toolbar' option if the user chose to retain the BuddyBar during the 1.6 upgrade.
381
  if ( (bool) bp_get_option( '_bp_force_buddybar', false ) ) {
382
+ // Load deprecated code if not available.
383
+ if ( ! function_exists( 'bp_admin_setting_callback_force_buddybar' ) ) {
384
+ require buddypress()->plugin_dir . 'bp-core/deprecated/2.1.php';
385
+ }
386
+
387
  add_settings_field( '_bp_force_buddybar', __( 'Toolbar', 'buddypress' ), 'bp_admin_setting_callback_force_buddybar', 'buddypress', 'bp_main' );
388
  register_setting( 'buddypress', '_bp_force_buddybar', 'bp_admin_sanitize_callback_force_buddybar' );
389
  }
392
  add_settings_field( 'bp-disable-account-deletion', __( 'Account Deletion', 'buddypress' ), 'bp_admin_setting_callback_account_deletion', 'buddypress', 'bp_main' );
393
  register_setting( 'buddypress', 'bp-disable-account-deletion', 'intval' );
394
 
395
+ // Template pack picker.
396
+ add_settings_field( '_bp_theme_package_id', __( 'Template Pack', 'buddypress' ), 'bp_admin_setting_callback_theme_package_id', 'buddypress', 'bp_main' );
397
+ register_setting( 'buddypress', '_bp_theme_package_id', 'sanitize_text_field' );
398
+
399
  /* XProfile Section **************************************************/
400
 
401
  if ( bp_is_active( 'xprofile' ) ) {
440
  }
441
  }
442
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  /* Activity Section **************************************************/
444
 
445
  if ( bp_is_active( 'activity' ) ) {
447
  // Add the main section.
448
  add_settings_section( 'bp_activity', __( 'Activity Settings', 'buddypress' ), 'bp_admin_setting_callback_activity_section', 'buddypress' );
449
 
450
+ // Activity commenting on post and comments.
451
+ add_settings_field( 'bp-disable-blogforum-comments', __( 'Post Comments', 'buddypress' ), 'bp_admin_setting_callback_blogforum_comments', 'buddypress', 'bp_activity' );
452
  register_setting( 'buddypress', 'bp-disable-blogforum-comments', 'bp_admin_sanitize_callback_blogforum_comments' );
453
 
454
  // Activity Heartbeat refresh.
552
 
553
  <div id="welcome-panel" class="welcome-panel">
554
  <div class="welcome-panel-content">
555
+ <h3 style="margin:0;"><?php _e( 'Getting Started with BuddyPress', 'buddypress' ); ?></h3>
556
  <div class="welcome-panel-column-container">
557
  <div class="welcome-panel-column">
558
  <h4><?php _e( 'Configure BuddyPress', 'buddypress' ); ?></h4>
573
  <h4><?php _e( 'Administration Tools', 'buddypress' ); ?></h4>
574
  <ul>
575
  <?php if ( bp_is_active( 'members' ) ) : ?>
576
+ <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Add User Profile Fields', 'buddypress' ) . '</a>', esc_url( add_query_arg( array( 'page' => 'bp-profile-setup' ), bp_get_admin_url( 'users.php' ) ) ) ); ?></li>
577
  <?php endif; ?>
578
+ <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Manage User Signups', 'buddypress' ) . '</a>', esc_url( add_query_arg( array( 'page' => 'bp-signups' ), bp_get_admin_url( 'users.php' ) ) ) ); ?></li>
579
  <?php if ( bp_is_active( 'activity' ) ) : ?>
580
+ <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Moderate Activity Streams', 'buddypress' ) . '</a>', esc_url( add_query_arg( array( 'page' => 'bp-activity' ), bp_get_admin_url( 'admin.php' ) ) ) ); ?></li>
581
  <?php endif; ?>
582
  <?php if ( bp_is_active( 'groups' ) ) : ?>
583
+ <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Manage Groups', 'buddypress' ) . '</a>', esc_url( add_query_arg( array( 'page' => 'bp-groups' ), bp_get_admin_url( 'admin.php' ) ) ) ); ?></li>
584
  <?php endif; ?>
585
+ <li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Repair Data', 'buddypress' ) . '</a>', esc_url( add_query_arg( array( 'page' => 'bp-tools' ), bp_get_admin_url( 'tools.php' ) ) ) ); ?>
586
  </li>
587
  </ul>
588
  </div>
597
 
598
  <?php endif; ?>
599
 
600
+ <div class="bp-features-section">
601
+
602
+ <h3 class="headline-title"><?php esc_html_e( 'For Developers &amp; Site Builders', 'buddypress' ); ?></h3>
603
 
604
+ <div class="bp-feature">
605
+ <span class="dashicons dashicons-groups" aria-hidden="true"></span>
606
+ <h4 class="feature-title"><?php esc_html_e( 'Edit Group Slug', 'buddypress' ); ?></h4>
607
+ <p><?php esc_html_e( 'Allow administrators to change group names and permalinks. Navigate to the Groups screen in the wp-admin dashboard, click on the Edit link under the Group name, and adjust as needed.', 'buddypress' ); ?></p>
608
  </div>
609
 
610
+ <div class="bp-feature opposite">
611
+ <span class="dashicons dashicons-admin-users" aria-hidden="true"></span>
612
+ <h4 class="feature-title"><?php esc_html_e( 'Improve accessibility of Extended Profile Fields', 'buddypress' ); ?></h4>
613
+ <p><?php esc_html_e( 'Related form fields are grouped together in fieldsets and all interactive form controls are associated with necessary ARIA states and properties.', 'buddypress' ); ?></p>
614
+ </div>
615
 
616
+ <div class="bp-feature">
617
+ <span class="dashicons dashicons-email" aria-hidden="true"></span>
618
+ <h4 class="feature-title"><?php esc_html_e( 'Send group invitation only once per user', 'buddypress' ); ?></h4>
619
+ <p><?php esc_html_e( 'Prevent duplicate group invitations from being sent to a user by double-checking if a group invitation has already been sent to that user.', 'buddypress' ); ?></p>
620
+ </div>
621
 
622
+ <div class="bp-feature opposite">
623
+ <span class="dashicons dashicons-testimonial" aria-hidden="true"></span>
624
+ <h4 class="feature-title"><?php esc_html_e( 'Tooltips Usable for All Devices', 'buddypress' ); ?></h4>
625
 
626
+ <p><?php esc_html_e( 'Replaced HTML title attributes with tooltips which provide additional information and visual cues where needed on mouse hover and keyboard focus events.', 'buddypress' );
627
+ ?></p>
 
 
 
 
 
 
 
 
 
628
  </div>
629
 
630
+ </div>
631
+
632
+ <div class="bp-changelog-section">
 
 
633
 
634
+ <h3 class="changelog-title"><?php esc_html_e( 'More under the hood &#8230;', 'buddypress' ); ?></h3>
635
+ <div class="bp-changelog bp-three-column">
636
+ <div class="bp-column">
637
+ <h4 class="title"><?php esc_html_e( 'Better support for private message thread links in emails', 'buddypress' ); ?></h4>
638
+ <p><?php esc_html_e( 'Redirect non-authenticated users to the login screen and authenticated users to the message linked.', 'buddypress' ); ?></p>
639
  </div>
640
+ <div class="bp-column">
641
+ <h4 class="title"><?php esc_html_e( 'Compatibility with Bootstrap themes', 'buddypress' ); ?></h4>
642
+ <p><?php esc_html_e( 'Removed issues with BuddyPress-generated content being hidden in the Groups loop and Activity comments in Bootstrap themes.', 'buddypress' ); ?></p>
 
643
  </div>
 
 
 
644
 
645
+ <div class="bp-column">
646
+ <h4 class="title"><?php esc_html_e( 'Improve profile image uploads', 'buddypress' ); ?></h4>
647
+ <p><?php esc_html_e( 'Fixed issues with uploading in iOS Safari and uploading files with non-ASCII filenames.', 'buddypress' ); ?></p>
648
+ </div>
649
+ </div>
650
 
651
+ <div class="bp-changelog bp-three-column">
652
+ <div class="bp-column">
653
+ <h4 class="title"><?php esc_html_e( 'URL compatibility for LightSpeed Servers', 'buddypress' ); ?></h4>
654
+ <p><?php
655
+ /* translators: %s: trailingslashit() */
656
+ printf( __( 'Audited and changed template link functions to use %s where necessary.', 'buddypress' ),
657
+ '<code>trailingslashit()</code>' );
658
+ ?></p>
659
+ </div>
660
+ <div class="bp-column">
661
+ <h4 class="title"><?php esc_html_e( 'Template Packs UI in BuddyPress > Settings.', 'buddypress' ); ?></h4>
662
+ <p><?php esc_html_e( 'Register your new BuddyPress theme package and allow the user to select which template pack to use.', 'buddypress' ); ?></p>
663
  </div>
664
 
665
+ <div class="bp-column">
666
+ <h4 class="title"><?php
667
+ /* translators: %s: bp_group_link() */
668
+ printf( __( 'New template function %s', 'buddypress' ),
669
+ '<code>bp_group_link()</code>' );
670
+ ?></h4>
671
+ <p><?php esc_html_e( 'Output a group name as a text hyperlink where appropriate.', 'buddypress' ); ?></p>
672
  </div>
673
  </div>
674
 
675
  </div>
676
 
677
+ <div class="bp-assets">
678
+ <p><?php _ex( 'Learn more:', 'About screen, website links', 'buddypress' ); ?> <a href="https://buddypress.org/blog/"><?php _ex( 'News', 'About screen, link to project blog', 'buddypress' ); ?></a> &bullet; <a href="https://buddypress.org/support/"><?php _ex( 'Support', 'About screen, link to support site', 'buddypress' ); ?></a> &bullet; <a href="https://codex.buddypress.org/"><?php _ex( 'Documentation', 'About screen, link to documentation', 'buddypress' ); ?></a> &bullet; <a href="https://bpdevel.wordpress.com/"><?php _ex( 'Development Blog', 'About screen, link to development blog', 'buddypress' ); ?></a></p>
679
 
680
+ <p><?php _ex( 'Twitter:', 'official Twitter accounts:', 'buddypress' ); ?> <a href="https://twitter.com/buddypress/"><?php _ex( 'BuddyPress', '@buddypress twitter account name', 'buddypress' ); ?></a> &bullet; <a href="https://twitter.com/bptrac/"><?php _ex( 'Trac', '@bptrac twitter account name', 'buddypress' ); ?></a> &bullet; <a href="https://twitter.com/buddypressdev/"><?php _ex( 'Development', '@buddypressdev twitter account name', 'buddypress' ); ?></a></p>
681
+ </div>
682
 
683
  </div>
684
 
707
  <h3 class="wp-people-group"><?php _e( 'Project Leaders', 'buddypress' ); ?></h3>
708
  <ul class="wp-people-group " id="wp-people-group-project-leaders">
709
  <li class="wp-person" id="wp-person-johnjamesjacoby">
710
+ <a class="web" href="https://profiles.wordpress.org/johnjamesjacoby"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7a2644fb53ae2f7bfd7143b504af396c?s=60">
711
  John James Jacoby</a>
712
  <span class="title"><?php _e( 'Project Lead', 'buddypress' ); ?></span>
713
  </li>
723
  </li>
724
  </ul>
725
 
726
+ <h3 class="wp-people-group"><?php _e( 'BuddyPress Team', 'buddypress' ); ?></h3>
727
  <ul class="wp-people-group " id="wp-people-group-core-team">
728
+ <li class="wp-person" id="wp-person-hnla">
729
+ <a class="web" href="https://profiles.wordpress.org/hnla"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3860c955aa3f79f13b92826ae47d07fe?s=60">
730
+ Hugo Ashmore</a>
731
+ <span class="title"><?php _e( '2.9 Release Lead', 'buddypress' ); ?></span>
732
+ </li>
733
  <li class="wp-person" id="wp-person-r-a-y">
734
  <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3bfa556a62b5bfac1012b6ba5f42ebfa?s=60">
735
  Ray</a>
755
  Michael Beckwith</a>
756
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
757
  </li>
 
 
 
 
 
 
 
 
 
758
  <li class="wp-person" id="wp-person-henry-wright">
759
  <a class="web" href="https://profiles.wordpress.org/henry.wright"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0da2f1a9340d6af196b870f6c107a248?s=60">
760
  Henry Wright</a>
761
+ <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
762
  </li>
763
  <li class="wp-person" id="wp-person-danbp">
764
  <a class="web" href="https://profiles.wordpress.org/danbp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0deae2e7003027fbf153500cd3fa5501?s=60">
765
  danbp</a>
766
+ <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
767
  </li>
768
  <li class="wp-person" id="wp-person-shanebp">
769
  <a class="web" href="https://profiles.wordpress.org/shanebp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ffd294ab5833ba14aaf175f9acc71cc4?s=60">
770
  shanebp</a>
771
+ <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
772
+ </li>
773
+ <li class="wp-person" id="wp-person-slaffik">
774
+ <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/61fb07ede3247b63f19015f200b3eb2c?s=60">
775
+ Slava Abakumov</a>
776
+ <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
777
+ </li>
778
+ <li class="wp-person" id="wp-person-offereins">
779
+ <a class="web" href="https://profiles.wordpress.org/Offereins"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/2404ed0a35bb41aedefd42b0a7be61c1?s=60">
780
+ Laurens Offereins</a>
781
+ <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
782
  </li>
783
  <li class="wp-person" id="wp-person-netweb">
784
  <a class="web" href="https://profiles.wordpress.org/netweb"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/97e1620b501da675315ba7cfb740e80f?s=60">
785
  Stephen Edgar</a>
786
+ <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
787
  </li>
788
+ </ul>
789
+
790
+ <h3 class="wp-people-group"><?php _e( '&#x1f31f;Recent Rockstars&#x1f31f;', 'buddypress' ); ?></h3>
791
+ <ul class="wp-people-group " id="wp-people-group-rockstars">
792
  <li class="wp-person" id="wp-person-dimensionmedia">
793
  <a class="web" href="https://profiles.wordpress.org/dimensionmedia"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7735aada1ec39d0c1118bd92ed4551f1?s=60">
794
  David Bisset</a>
795
  </li>
796
+ <li class="wp-person" id="wp-person-garrett-eclipse">
797
+ <a class="web" href="https://profiles.wordpress.org/garrett-eclipse"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7f68f24441c61514d5d0e1451bb5bc9d?s=60">
798
+ Garrett Hyder</a>
799
+ </li>
800
+ <li class="wp-person" id="wp-person-thebrandonallen">
801
+ <a class="web" href="https://profiles.wordpress.org/thebrandonallen"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/6d3f77bf3c9ca94c406dea401b566950?s=60">
802
+ Brandon Allen</a>
803
+ </li>
804
+ <li class="wp-person" id="wp-person-ramiy">
805
+ <a class="web" href="https://profiles.wordpress.org/ramiy"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ce2a269e424156d79cb0c4e1d4d82db1?s=60">
806
+ Rami Yushuvaev</a>
807
+ </li>
808
  </ul>
809
 
810
  <h3 class="wp-people-group"><?php printf( esc_html__( 'Contributors to BuddyPress %s', 'buddypress' ), self::display_version() ); ?></h3>
811
  <p class="wp-credits-list">
812
+ <a href="https://profiles.wordpress.org/55don/">55don</a>,
813
+ <a href="https://profiles.wordpress.org/aaronoftomorrow/">AaronOfTomorrow</a>,
814
+ <a href="https://profiles.wordpress.org/allianse/">allianse</a>,
815
+ <a href="https://profiles.wordpress.org/antonioeatgoat/">Antonio Mangiacapra (antonioeatgoat)</a>,
816
+ <a href="https://profiles.wordpress.org/benjlipchak/">Benj (benjlipchak)</a>,
817
  <a href="https://profiles.wordpress.org/boonebgorges/">Boone B Gorges (boonebgorges)</a>,
818
+ <a href="https://profiles.wordpress.org/bhargavbhandari90/">Bunty (bhargavbhandari90)</a>,
819
  <a href="https://profiles.wordpress.org/sbrajesh/">Brajesh Singh (sbrajesh)</a>,
 
820
  <a href="https://profiles.wordpress.org/needle/">Christian Wach (needle)</a>,
821
+ <a href="https://profiles.wordpress.org/brandonliles/">brandonliles</a>,
822
+ <a href="https://profiles.wordpress.org/danbp/">danbp</a>,
823
  <a href="https://profiles.wordpress.org/dcavins/">David Cavins (dcavins)</a>,
824
+ <a href="https://profiles.wordpress.org/dkelm/">dkelm</a>,
825
+ <a href="https://profiles.wordpress.org/dsar/">dsar</a>,
826
+ <a href="https://profiles.wordpress.org/dsided/">dsided</a>,
827
+ <a href="https://profiles.wordpress.org/henry.wright">Henry Wright (henry.wright)</a>,
 
828
  <a href="https://profiles.wordpress.org/hnla/">Hugo (hnla)</a>,
829
+ <a href="https://profiles.wordpress.org/idofri/">Ido Friedlander (idofri)</a>,
830
+ <a href="https://profiles.wordpress.org/uscore713/">Jay (uscore713)</a>,
831
+ <a href="https://profiles.wordpress.org/johnbillion/">John Blackbourn (johnbillion)</a>,
832
  <a href="https://profiles.wordpress.org/johnjamesjacoby/">John James Jacoby (johnjamesjacoby)</a>,
833
+ <a href="https://profiles.wordpress.org/juanho/">Juanho</a>,
834
+ <a href="https://profiles.wordpress.org/lakrisgubben/">lakrisgubben</a>,
 
 
835
  <a href="https://profiles.wordpress.org/Offereins">Laurens Offereins (Offereins)</a>,
836
+ <a href="https://profiles.wordpress.org/lne1030/">lne1030</a>,
837
+ <a href="https://profiles.wordpress.org/lenasterg/">lenasterg</a>,
838
+ <a href="https://profiles.wordpress.org/maniou/">Maniou</a>,
839
  <a href="https://profiles.wordpress.org/imath/">Mathieu Viet (imath)</a>,
840
  <a href="https://profiles.wordpress.org/mercime/">mercime</a>,
841
  <a href="https://profiles.wordpress.org/tw2113/">Michael Beckwith (tw2113)</a>,
842
+ <a href="https://profiles.wordpress.org/mikegillihan/">Mike Gillihan (MikeGillihan)</a>,
843
+ <a href="https://profiles.wordpress.org/milindmore22/">Milind More (milindmore22)</a>,
844
  <a href="https://profiles.wordpress.org/modemlooper/">modemlooper</a>,
845
+ <a href="https://profiles.wordpress.org/mrjarbenne/">mrjarbenne</a>,
846
+ <a href="https://profiles.wordpress.org/nicolaskulka/">Nicolas Kulka (NicolasKulka)</a>,
847
+ <a href="https://profiles.wordpress.org/oelita/">Oelita</a>,
848
  <a href="https://profiles.wordpress.org/DJPaul/">Paul Gibbs (DJPaul)</a>,
849
+ <a href="https://profiles.wordpress.org/pareshradadiya/">paresh.radadiya (pareshradadiya)</a>,
850
  <a href="https://profiles.wordpress.org/r-a-y/">r-a-y</a>,
851
+ <a href="https://profiles.wordpress.org/espellcaste/">Renato Alves (espellcaste)</a>,
852
+ <a href="https://profiles.wordpress.org/rianrietveld/">Rian Rietveld (rianrietvelde)</a>,
853
+ <a href="https://profiles.wordpress.org/elhardoum/">Samuel Elh (elhardoum)</a>,
854
+ <a href="https://profiles.wordpress.org/seventhqueen/">seventhqueen</a>,
855
+ <a href="https://profiles.wordpress.org/slaffik/">Slava Abakumov (slaffik)</a>,
856
  <a href="https://profiles.wordpress.org/netweb/">Stephen Edgar (netweb)</a>,
857
+ <a href="https://profiles.wordpress.org/vishalkakadiya/">Vishal Kakadiya (vishalkakadiya)</a>
 
858
  </p>
859
 
860
  <h3 class="wp-people-group"><?php _e( '&#x1f496;With our thanks to these Open Source projects&#x1f496;', 'buddypress' ); ?></h3>
862
  <a href="https://github.com/ichord/At.js">At.js</a>,
863
  <a href="https://bbpress.org">bbPress</a>,
864
  <a href="https://github.com/ichord/Caret.js">Caret.js</a>,
865
+ <a href="https://tedgoas.github.io/Cerberus/">Cerberus</a>,
866
+ <a href="https://ionicons.com/">Ionicons</a>,
867
  <a href="https://github.com/carhartl/jquery-cookie">jquery.cookie</a>,
868
+ <a href="https://mattbradley.github.io/livestampjs/">Livestamp.js</a>,
869
  <a href="https://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a>,
870
+ <a href="http://momentjs.com/">Moment.js</a>,
871
  <a href="https://wordpress.org">WordPress</a>.
872
  </p>
873
 
885
 
886
  // Switch welcome text based on whether this is a new installation or not.
887
  $welcome_text = ( self::is_new_install() )
888
+ ? __( 'Thank you for installing BuddyPress! BuddyPress adds community features to WordPress. Member Profiles, Activity Streams, Direct Messaging, Notifications, and more!', 'buddypress' )
889
+ : __( 'Thank you for updating! BuddyPress %s has many new improvements that you will enjoy.', 'buddypress' );
890
 
891
  ?>
892
 
935
  *
936
  * @since 2.6.0
937
  *
938
+ * @param array $columns Current column data.
939
  * @return array
940
  */
941
  public function emails_register_situation_column( $columns = array() ) {
bp-core/classes/class-bp-attachment-avatar.php CHANGED
@@ -61,7 +61,6 @@ class BP_Attachment_Avatar extends BP_Attachment {
61
  * Set Upload Dir data for avatars.
62
  *
63
  * @since 2.3.0
64
- *
65
  */
66
  public function set_upload_dir() {
67
  if ( bp_core_avatar_upload_path() && bp_core_avatar_url() ) {
@@ -81,8 +80,7 @@ class BP_Attachment_Avatar extends BP_Attachment {
81
  *
82
  * @since 2.3.0
83
  *
84
- *
85
- * @param array $file the temporary file attributes (before it has been moved).
86
  * @return array the file with extra errors if needed.
87
  */
88
  public function validate_upload( $file = array() ) {
@@ -110,10 +108,9 @@ class BP_Attachment_Avatar extends BP_Attachment {
110
  * @since 2.3.0
111
  * @since 2.4.0 Add the $ui_available_width parameter, to inform about the Avatar UI width.
112
  *
113
- *
114
  * @param string $file The absolute path to the file.
115
  * @param int $ui_available_width Available width for the UI.
116
- * @return mixed
117
  */
118
  public static function shrink( $file = '', $ui_available_width = 0 ) {
119
  // Get image size.
@@ -207,11 +204,23 @@ class BP_Attachment_Avatar extends BP_Attachment {
207
  return false;
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  /**
211
  * Original file is a relative path to the image
212
  * eg: /avatars/1/avatar.jpg
213
  */
214
- $relative_path = $args['original_file'];
215
  $absolute_path = $this->upload_path . $relative_path;
216
 
217
  // Bail if the avatar is not available.
61
  * Set Upload Dir data for avatars.
62
  *
63
  * @since 2.3.0
 
64
  */
65
  public function set_upload_dir() {
66
  if ( bp_core_avatar_upload_path() && bp_core_avatar_url() ) {
80
  *
81
  * @since 2.3.0
82
  *
83
+ * @param array $file the temporary file attributes (before it has been moved).
 
84
  * @return array the file with extra errors if needed.
85
  */
86
  public function validate_upload( $file = array() ) {
108
  * @since 2.3.0
109
  * @since 2.4.0 Add the $ui_available_width parameter, to inform about the Avatar UI width.
110
  *
 
111
  * @param string $file The absolute path to the file.
112
  * @param int $ui_available_width Available width for the UI.
113
+ * @return false|string|WP_Image_Editor|WP_Error
114
  */
115
  public static function shrink( $file = '', $ui_available_width = 0 ) {
116
  // Get image size.
204
  return false;
205
  }
206
 
207
+ if ( ! bp_attachments_current_user_can( 'edit_avatar', $args ) ) {
208
+ return false;
209
+ }
210
+
211
+ if ( 'user' === $args['object'] ) {
212
+ $avatar_dir = 'avatars';
213
+ } else {
214
+ $avatar_dir = sanitize_key( $args['object'] ) . '-avatars';
215
+ }
216
+
217
+ $args['item_id'] = (int) $args['item_id'];
218
+
219
  /**
220
  * Original file is a relative path to the image
221
  * eg: /avatars/1/avatar.jpg
222
  */
223
+ $relative_path = sprintf( '/%s/%s/%s', $avatar_dir, $args['item_id'], basename( $args['original_file'] ) );
224
  $absolute_path = $this->upload_path . $relative_path;
225
 
226
  // Bail if the avatar is not available.
bp-core/classes/class-bp-attachment-cover-image.php CHANGED
@@ -96,40 +96,7 @@ class BP_Attachment_Cover_Image extends BP_Attachment {
96
  * @return array $value Upload data (path, url, basedir...).
97
  */
98
  public function upload_dir_filter( $upload_dir = array() ) {
99
- // Default values are for profiles.
100
- $object_id = bp_displayed_user_id();
101
-
102
- if ( empty( $object_id ) ) {
103
- $object_id = bp_loggedin_user_id();
104
- }
105
-
106
- $object_directory = 'members';
107
-
108
- // We're in a group, edit default values.
109
- if ( bp_is_group() || bp_is_group_create() ) {
110
- $object_id = bp_get_current_group_id();
111
- $object_directory = 'groups';
112
- }
113
-
114
- // Set the subdir.
115
- $subdir = '/' . $object_directory . '/' . $object_id . '/cover-image';
116
-
117
- /**
118
- * Filters the cover image upload directory.
119
- *
120
- * @since 2.4.0
121
- *
122
- * @param array $value Array containing the path, URL, and other helpful settings.
123
- * @param array $upload_dir The original Uploads dir.
124
- */
125
- return apply_filters( 'bp_attachments_cover_image_upload_dir', array(
126
- 'path' => $this->upload_path . $subdir,
127
- 'url' => $this->url . $subdir,
128
- 'subdir' => $subdir,
129
- 'basedir' => $this->upload_path,
130
- 'baseurl' => $this->url,
131
- 'error' => false
132
- ), $upload_dir );
133
  }
134
 
135
  /**
@@ -201,7 +168,7 @@ class BP_Attachment_Cover_Image extends BP_Attachment {
201
  * @since 2.4.0
202
  *
203
  * @param string $file The absolute path to the file.
204
- * @return string $value The absolute path to the new file name.
205
  */
206
  public function generate_filename( $file = '' ) {
207
  if ( empty( $file ) || ! file_exists( $file ) ) {
96
  * @return array $value Upload data (path, url, basedir...).
97
  */
98
  public function upload_dir_filter( $upload_dir = array() ) {
99
+ return bp_attachments_cover_image_upload_dir();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
 
102
  /**
168
  * @since 2.4.0
169
  *
170
  * @param string $file The absolute path to the file.
171
+ * @return false|string $value The absolute path to the new file name.
172
  */
173
  public function generate_filename( $file = '' ) {
174
  if ( empty( $file ) || ! file_exists( $file ) ) {
bp-core/classes/class-bp-attachment.php CHANGED
@@ -197,17 +197,17 @@ abstract class BP_Attachment {
197
  *
198
  * @since 2.3.0
199
  *
200
- *
201
- * @param array $file The appropriate entry the from $_FILES superglobal.
202
- * @param string $upload_dir_filter A specific filter to be applied to 'upload_dir' (optional).
203
- * @param string|null $time Optional. Time formatted in 'yyyy/mm'. Default null.
204
  * @return array On success, returns an associative array of file attributes.
205
  * On failure, returns an array containing the error message
206
  * (eg: array( 'error' => $message ) )
207
  */
208
  public function upload( $file, $upload_dir_filter = '', $time = null ) {
209
  /**
210
- * Upload action and the file input name are required parameters
 
211
  * @see BP_Attachment:__construct()
212
  */
213
  if ( empty( $this->action ) || empty( $this->file_input ) ) {
@@ -219,13 +219,6 @@ abstract class BP_Attachment {
219
  */
220
  add_filter( "{$this->action}_prefilter", array( $this, 'validate_upload' ), 10, 1 );
221
 
222
- /**
223
- * The above dynamic filter was introduced in WordPress 4.0, as we support WordPress
224
- * back to 3.6, we need to also use the pre 4.0 static filter and remove it after
225
- * the upload was processed.
226
- */
227
- add_filter( 'wp_handle_upload_prefilter', array( $this, 'validate_upload' ), 10, 1 );
228
-
229
  // Set Default overrides.
230
  $overrides = array(
231
  'action' => $this->action,
@@ -268,21 +261,50 @@ abstract class BP_Attachment {
268
  add_filter( 'upload_dir', $upload_dir_filter, 10, $this->upload_dir_filter_args );
269
  }
270
 
 
 
 
271
  // Upload the attachment.
272
  $this->attachment = wp_handle_upload( $file[ $this->file_input ], $overrides, $time );
273
 
 
 
274
  // Restore WordPress Uploads data.
275
  if ( ! empty( $upload_dir_filter ) ) {
276
- remove_filter( 'upload_dir', $upload_dir_filter, 10, $this->upload_dir_filter_args );
277
  }
278
 
279
- // Remove the pre WordPress 4.0 static filter.
280
- remove_filter( 'wp_handle_upload_prefilter', array( $this, 'validate_upload' ), 10, 1 );
281
-
282
  // Finally return the uploaded file or the error.
283
  return $this->attachment;
284
  }
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  /**
287
  * Validate the allowed mime types using WordPress allowed mime types.
288
  *
@@ -320,7 +342,7 @@ abstract class BP_Attachment {
320
  *
321
  * @since 2.3.0
322
  *
323
- * @param array $file The temporary file attributes (before it has been moved).
324
  * @return array The file.
325
  */
326
  public function validate_upload( $file = array() ) {
@@ -345,7 +367,7 @@ abstract class BP_Attachment {
345
  *
346
  * regarding to context
347
  *
348
- * @param array $upload_dir The original Uploads dir.
349
  * @return array The upload directory data.
350
  */
351
  public function upload_dir_filter( $upload_dir = array() ) {
@@ -522,9 +544,9 @@ abstract class BP_Attachment {
522
  /**
523
  * Get full data for an image
524
  *
525
- * @since 2.4.0
526
  *
527
- * @param string $file Absolute path to the uploaded image.
528
  * @return bool|array An associate array containing the width, height and metadatas.
529
  * False in case an important image attribute is missing.
530
  */
@@ -553,30 +575,16 @@ abstract class BP_Attachment {
553
 
554
  // Now try to get image's meta data.
555
  $meta = wp_read_image_metadata( $file );
556
-
557
  if ( ! empty( $meta ) ) {
558
- // Before 4.0 the Orientation wasn't included.
559
- if ( ! isset( $meta['orientation'] ) &&
560
- is_callable( 'exif_read_data' ) &&
561
- in_array( $sourceImageType, apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) ) )
562
- ) {
563
- $exif = exif_read_data( $file );
564
-
565
- if ( ! empty( $exif['Orientation'] ) ) {
566
- $meta['orientation'] = $exif['Orientation'];
567
- }
568
- }
569
-
570
- // Now add the metas to image data.
571
  $image_data['meta'] = $meta;
572
  }
573
 
574
  /**
575
  * Filter here to add/remove/edit data to the image full data
576
  *
577
- * @since 2.4.0
578
  *
579
- * @param array $image_data An associate array containing the width, height and metadatas.
580
  */
581
  return apply_filters( 'bp_attachments_get_image_data', $image_data );
582
  }
@@ -584,7 +592,7 @@ abstract class BP_Attachment {
584
  /**
585
  * Edit an image file to resize it or rotate it
586
  *
587
- * @since 2.4.0
588
  *
589
  * @param string $attachment_type The attachment type (eg: avatar or cover_image). Required.
590
  * @param array $args {
197
  *
198
  * @since 2.3.0
199
  *
200
+ * @param array $file The appropriate entry the from $_FILES superglobal.
201
+ * @param string $upload_dir_filter A specific filter to be applied to 'upload_dir' (optional).
202
+ * @param string|null $time Optional. Time formatted in 'yyyy/mm'. Default null.
 
203
  * @return array On success, returns an associative array of file attributes.
204
  * On failure, returns an array containing the error message
205
  * (eg: array( 'error' => $message ) )
206
  */
207
  public function upload( $file, $upload_dir_filter = '', $time = null ) {
208
  /**
209
+ * Upload action and the file input name are required parameters.
210
+ *
211
  * @see BP_Attachment:__construct()
212
  */
213
  if ( empty( $this->action ) || empty( $this->file_input ) ) {
219
  */
220
  add_filter( "{$this->action}_prefilter", array( $this, 'validate_upload' ), 10, 1 );
221
 
 
 
 
 
 
 
 
222
  // Set Default overrides.
223
  $overrides = array(
224
  'action' => $this->action,
261
  add_filter( 'upload_dir', $upload_dir_filter, 10, $this->upload_dir_filter_args );
262
  }
263
 
264
+ // Helper for utf-8 filenames.
265
+ add_filter( 'sanitize_file_name', array( $this, 'sanitize_utf8_filename' ) );
266
+
267
  // Upload the attachment.
268
  $this->attachment = wp_handle_upload( $file[ $this->file_input ], $overrides, $time );
269
 
270
+ remove_filter( 'sanitize_file_name', array( $this, 'sanitize_utf8_filename' ) );
271
+
272
  // Restore WordPress Uploads data.
273
  if ( ! empty( $upload_dir_filter ) ) {
274
+ remove_filter( 'upload_dir', $upload_dir_filter, 10 );
275
  }
276
 
 
 
 
277
  // Finally return the uploaded file or the error.
278
  return $this->attachment;
279
  }
280
 
281
+ /**
282
+ * Helper to convert utf-8 characters in filenames to their ASCII equivalent.
283
+ *
284
+ * @since 2.9.0
285
+ *
286
+ * @param string $retval Filename.
287
+ * @return string
288
+ */
289
+ public function sanitize_utf8_filename( $retval ) {
290
+ // PHP 5.4+ or with PECL intl 2.0+
291
+ if ( function_exists( 'transliterator_transliterate' ) && seems_utf8( $retval ) ) {
292
+ $retval = transliterator_transliterate( 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove', $retval );
293
+
294
+ // Older.
295
+ } else {
296
+ // Use WP's built-in function to convert accents to their ASCII equivalent.
297
+ $retval = remove_accents( $retval );
298
+
299
+ // Still here? use iconv().
300
+ if ( function_exists( 'iconv' ) && seems_utf8( $retval ) ) {
301
+ $retval = iconv( 'UTF-8', 'ASCII//TRANSLIT//IGNORE', $retval );
302
+ }
303
+ }
304
+
305
+ return $retval;
306
+ }
307
+
308
  /**
309
  * Validate the allowed mime types using WordPress allowed mime types.
310
  *
342
  *
343
  * @since 2.3.0
344
  *
345
+ * @param array $file The temporary file attributes (before it has been moved).
346
  * @return array The file.
347
  */
348
  public function validate_upload( $file = array() ) {
367
  *
368
  * regarding to context
369
  *
370
+ * @param array $upload_dir The original Uploads dir.
371
  * @return array The upload directory data.
372
  */
373
  public function upload_dir_filter( $upload_dir = array() ) {
544
  /**
545
  * Get full data for an image
546
  *
547
+ * @since 2.4.0
548
  *
549
+ * @param string $file Absolute path to the uploaded image.
550
  * @return bool|array An associate array containing the width, height and metadatas.
551
  * False in case an important image attribute is missing.
552
  */
575
 
576
  // Now try to get image's meta data.
577
  $meta = wp_read_image_metadata( $file );
 
578
  if ( ! empty( $meta ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  $image_data['meta'] = $meta;
580
  }
581
 
582
  /**
583
  * Filter here to add/remove/edit data to the image full data
584
  *
585
+ * @since 2.4.0
586
  *
587
+ * @param array $image_data An associate array containing the width, height and metadatas.
588
  */
589
  return apply_filters( 'bp_attachments_get_image_data', $image_data );
590
  }
592
  /**
593
  * Edit an image file to resize it or rotate it
594
  *
595
+ * @since 2.4.0
596
  *
597
  * @param string $attachment_type The attachment type (eg: avatar or cover_image). Required.
598
  * @param array $args {
bp-core/classes/class-bp-button.php CHANGED
@@ -14,35 +14,35 @@ defined( 'ABSPATH' ) || exit;
14
  * API to create BuddyPress buttons.
15
  *
16
  * @since 1.2.6
 
 
 
 
17
  *
18
  * @param array $args {
19
  * Array of arguments.
20
  *
21
  * @type string $id String describing the button type.
22
- * @type string $component The name of the component the button belongs to.
23
- * Default: 'core'.
24
- * @type bool $must_be_logged_in Optional. Does the user need to be logged
25
- * in to see this button? Default: true.
26
- * @type bool $block_self Optional. True if the button should be hidden
27
- * when a user is viewing his own profile.
28
- * Default: true.
29
- * @type string|bool $wrapper Optional. HTML element type that should wrap
30
- * the button: 'div', 'span', 'p', or 'li'.
31
- * False for no wrapper at all. Default: 'div'.
32
- * @type string $wrapper_id Optional. DOM ID of the button wrapper element.
33
- * Default: ''.
34
- * @type string $wrapper_class Optional. DOM class of the button wrapper
35
- * element. Default: ''.
36
- * @type string $link_href Optional. Destination link of the button.
37
- * Default: ''.
38
- * @type string $link_class Optional. DOM class of the button. Default: ''.
39
- * @type string $link_id Optional. DOM ID of the button. Default: ''.
40
- * @type string $link_rel Optional. DOM 'rel' attribute of the button.
41
- * Default: ''.
42
- * @type string $link_title Optional. Title attribute of the button.
43
- * Default: ''.
44
- * @type string $link_text Optional. Text to appear on the button.
45
- * Default: ''.
46
  * }
47
  */
48
  class BP_Button {
@@ -52,6 +52,8 @@ class BP_Button {
52
  /**
53
  * The button ID.
54
  *
 
 
55
  * @var string
56
  */
57
  public $id = '';
@@ -59,6 +61,8 @@ class BP_Button {
59
  /**
60
  * The name of the component that the button belongs to.
61
  *
 
 
62
  * @var string
63
  */
64
  public $component = 'core';
@@ -66,6 +70,8 @@ class BP_Button {
66
  /**
67
  * Does the user need to be logged in to see this button?
68
  *
 
 
69
  * @var bool
70
  */
71
  public $must_be_logged_in = true;
@@ -73,22 +79,88 @@ class BP_Button {
73
  /**
74
  * Whether the button should be hidden when viewing your own profile.
75
  *
 
 
76
  * @var bool
77
  */
78
  public $block_self = true;
79
 
80
  /** Wrapper ***************************************************************/
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  /**
83
  * The type of DOM element to use for a wrapper.
84
  *
85
- * @var string|bool 'div', 'span', 'p', 'li', or false for no wrapper.
 
 
 
86
  */
87
  public $wrapper = 'div';
88
 
89
  /**
90
  * The DOM class of the button wrapper.
91
  *
 
 
 
92
  * @var string
93
  */
94
  public $wrapper_class = '';
@@ -96,15 +168,19 @@ class BP_Button {
96
  /**
97
  * The DOM ID of the button wrapper.
98
  *
 
 
 
99
  * @var string
100
  */
101
  public $wrapper_id = '';
102
 
103
- /** Button ****************************************************************/
104
-
105
  /**
106
  * The destination link of the button.
107
  *
 
 
 
108
  * @var string
109
  */
110
  public $link_href = '';
@@ -112,6 +188,9 @@ class BP_Button {
112
  /**
113
  * The DOM class of the button link.
114
  *
 
 
 
115
  * @var string
116
  */
117
  public $link_class = '';
@@ -119,6 +198,9 @@ class BP_Button {
119
  /**
120
  * The DOM ID of the button link.
121
  *
 
 
 
122
  * @var string
123
  */
124
  public $link_id = '';
@@ -126,6 +208,9 @@ class BP_Button {
126
  /**
127
  * The DOM rel value of the button link.
128
  *
 
 
 
129
  * @var string
130
  */
131
  public $link_rel = '';
@@ -133,22 +218,12 @@ class BP_Button {
133
  /**
134
  * Title of the button link.
135
  *
136
- * @var string
137
- */
138
- public $link_title = '';
139
-
140
- /**
141
- * The contents of the button link.
142
- *
143
- * @var string
144
- */
145
- public $link_text = '';
146
-
147
- /** HTML result
148
  *
149
  * @var string
150
  */
151
- public $contents = '';
152
 
153
  /** Methods ***************************************************************/
154
 
@@ -163,76 +238,102 @@ class BP_Button {
163
 
164
  $r = wp_parse_args( $args, get_class_vars( __CLASS__ ) );
165
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  // Required button properties.
167
  $this->id = $r['id'];
168
  $this->component = $r['component'];
169
  $this->must_be_logged_in = (bool) $r['must_be_logged_in'];
170
  $this->block_self = (bool) $r['block_self'];
171
- $this->wrapper = $r['wrapper'];
172
-
173
- // $id and $component are required
174
- if ( empty( $r['id'] ) || empty( $r['component'] ) )
175
- return false;
176
 
177
- // No button if component is not active.
178
- if ( ! bp_is_active( $this->component ) )
179
  return false;
 
180
 
181
  // No button for guests if must be logged in.
182
- if ( true == $this->must_be_logged_in && ! is_user_logged_in() )
183
  return false;
 
184
 
185
  // The block_self property.
186
  if ( true == $this->block_self ) {
187
- // No button if you are the current user in a members loop
188
- // This condition takes precedence, because members loops
189
- // can be found on user profiles.
 
 
 
190
  if ( bp_get_member_user_id() ) {
191
  if ( is_user_logged_in() && bp_loggedin_user_id() == bp_get_member_user_id() ) {
192
  return false;
193
  }
194
 
195
- // No button if viewing your own profile (and not in
196
- // a members loop).
197
  } elseif ( bp_is_my_profile() ) {
198
  return false;
199
  }
200
  }
201
 
202
- // Wrapper properties.
203
- if ( false !== $this->wrapper ) {
204
-
205
- // Wrapper ID.
206
- if ( !empty( $r['wrapper_id'] ) ) {
207
- $this->wrapper_id = ' id="' . $r['wrapper_id'] . '"';
208
  }
209
 
210
- // Wrapper class.
211
- if ( !empty( $r['wrapper_class'] ) ) {
212
- $this->wrapper_class = ' class="generic-button ' . $r['wrapper_class'] . '"';
213
- } else {
214
- $this->wrapper_class = ' class="generic-button"';
 
 
 
 
215
  }
216
 
 
 
 
 
 
 
 
 
 
 
217
  // Set before and after.
218
- $before = '<' . $r['wrapper'] . $this->wrapper_class . $this->wrapper_id . '>';
219
- $after = '</' . $r['wrapper'] . '>';
220
 
221
- // No wrapper.
222
  } else {
223
  $before = $after = '';
224
  }
225
 
226
- // Link properties.
227
- if ( !empty( $r['link_id'] ) ) $this->link_id = ' id="' . $r['link_id'] . '"';
228
- if ( !empty( $r['link_href'] ) ) $this->link_href = ' href="' . $r['link_href'] . '"';
229
- if ( !empty( $r['link_title'] ) ) $this->link_title = ' title="' . $r['link_title'] . '"';
230
- if ( !empty( $r['link_rel'] ) ) $this->link_rel = ' rel="' . $r['link_rel'] . '"';
231
- if ( !empty( $r['link_class'] ) ) $this->link_class = ' class="' . $r['link_class'] . '"';
232
- if ( !empty( $r['link_text'] ) ) $this->link_text = $r['link_text'];
 
 
 
233
 
234
  // Build the button.
235
- $this->contents = $before . '<a'. $this->link_href . $this->link_title . $this->link_id . $this->link_rel . $this->link_class . '>' . $this->link_text . '</a>' . $after;
236
 
237
  /**
238
  * Filters the button based on class parameters.
@@ -241,15 +342,76 @@ class BP_Button {
241
  * allows button to be manipulated externally.
242
  *
243
  * @since 1.2.6
 
244
  *
245
  * @param string $contents HTML being used for the button.
246
  * @param BP_Button $this Current BP_Button instance.
247
  * @param string $before HTML appended before the actual button.
248
  * @param string $after HTML appended after the actual button.
 
249
  */
250
- $this->contents = apply_filters( 'bp_button_' . $this->component . '_' . $this->id, $this->contents, $this, $before, $after );
251
  }
252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  /**
254
  * Return the markup for the generated button.
255
  *
14
  * API to create BuddyPress buttons.
15
  *
16
  * @since 1.2.6
17
+ * @since 2.7.0 Introduced $parent_element, $parent_attr, $button_element, $button_attr as
18
+ * $args parameters.
19
+ * Deprecated $wrapper, $wrapper_id, $wrapper_class, $link_href, $link_class,
20
+ * $link_id, $link_rel, $link_title as $args params.
21
  *
22
  * @param array $args {
23
  * Array of arguments.
24
  *
25
  * @type string $id String describing the button type.
26
+ * @type string $component The name of the component the button belongs to. Default: 'core'.
27
+ * @type bool $must_be_logged_in Optional. Does the user need to be logged in to see this button? Default:
28
+ * true.
29
+ * @type bool $block_self Optional. True if the button should be hidden when a user is viewing his
30
+ * own profile. Default: true.
31
+ * @type string $parent_element Optional. Parent element to wrap button around. Default: 'div'.
32
+ * @type array $parent_attr Optional. Element attributes for parent element. Set whatever attributes
33
+ * like 'id', 'class' as array keys.
34
+ * @type string $button_element Optional. Button element. Default: 'a'.
35
+ * @type array $button_attr Optional. Button attributes. Set whatever attributes like 'id', 'class' as
36
+ * array keys.
37
+ * @type string $link_text Optional. Text to appear on the button. Default: ''.
38
+ * @type string|bool $wrapper Deprecated. Use $parent_element instead.
39
+ * @type string $wrapper_id Deprecated. Use $parent_attr and set 'id' as array key.
40
+ * @type string $wrapper_class Deprecated. Use $parent_attr and set 'class' as array key.
41
+ * @type string $link_href Deprecated. Use $button_attr and set 'href' as array key.
42
+ * @type string $link_class Deprecated. Use $button_attr and set 'class' as array key.
43
+ * @type string $link_id Deprecated. Use $button_attr and set 'id' as array key.
44
+ * @type string $link_rel Deprecated. Use $button_attr and set 'rel' as array key.
45
+ * @type string $link_title Deprecated. Use $button_attr and set 'title' as array key.
 
 
 
 
46
  * }
47
  */
48
  class BP_Button {
52
  /**
53
  * The button ID.
54
  *
55
+ * @since 1.2.6
56
+ *
57
  * @var string
58
  */
59
  public $id = '';
61
  /**
62
  * The name of the component that the button belongs to.
63
  *
64
+ * @since 1.2.6
65
+ *
66
  * @var string
67
  */
68
  public $component = 'core';
70
  /**
71
  * Does the user need to be logged in to see this button?
72
  *
73
+ * @since 1.2.6
74
+ *
75
  * @var bool
76
  */
77
  public $must_be_logged_in = true;
79
  /**
80
  * Whether the button should be hidden when viewing your own profile.
81
  *
82
+ * @since 1.2.6
83
+ *
84
  * @var bool
85
  */
86
  public $block_self = true;
87
 
88
  /** Wrapper ***************************************************************/
89
 
90
+ /**
91
+ * Parent element to wrap button around.
92
+ *
93
+ * @since 2.7.0
94
+ *
95
+ * @var string Default: 'div'.
96
+ */
97
+ public $parent_element = '';
98
+
99
+ /**
100
+ * Element attributes for parent element.
101
+ *
102
+ * @since 2.7.0
103
+ *
104
+ * @var array Set whatever attributes like 'id', 'class' as array key.
105
+ */
106
+ public $parent_attr = array();
107
+
108
+ /** Button ****************************************************************/
109
+
110
+ /**
111
+ * Button element.
112
+ *
113
+ * @since 2.7.0
114
+ *
115
+ * @var string Default: 'a'.
116
+ */
117
+ public $button_element = 'a';
118
+
119
+ /**
120
+ * Button attributes.
121
+ *
122
+ * @since 2.7.0
123
+ *
124
+ * @var array Set whatever attributes like 'id', 'href' as array key.
125
+ */
126
+ public $button_attr = array();
127
+
128
+ /**
129
+ * The contents of the button link.
130
+ *
131
+ * @since 1.2.6
132
+ *
133
+ * @var string
134
+ */
135
+ public $link_text = '';
136
+
137
+ /**
138
+ * HTML result.
139
+ *
140
+ * @since 1.2.6
141
+ *
142
+ * @var string
143
+ */
144
+ public $contents = '';
145
+
146
+ /** Deprecated ***********************************************************/
147
+
148
  /**
149
  * The type of DOM element to use for a wrapper.
150
  *
151
+ * @since 1.2.6
152
+ * @deprecated 2.7.0 Use $parent_element instead.
153
+ *
154
+ * @var string|bool
155
  */
156
  public $wrapper = 'div';
157
 
158
  /**
159
  * The DOM class of the button wrapper.
160
  *
161
+ * @since 1.2.6
162
+ * @deprecated 2.7.0 Set 'class' key in $parent_attr instead.
163
+ *
164
  * @var string
165
  */
166
  public $wrapper_class = '';
168
  /**
169
  * The DOM ID of the button wrapper.
170
  *
171
+ * @since 1.2.6
172
+ * @deprecated 2.7.0 Set 'id' key in $parent_attr instead.
173
+ *
174
  * @var string
175
  */
176
  public $wrapper_id = '';
177
 
 
 
178
  /**
179
  * The destination link of the button.
180
  *
181
+ * @since 1.2.6
182
+ * @deprecated 2.7.0 Set 'href' key in $button_attr instead.
183
+ *
184
  * @var string
185
  */
186
  public $link_href = '';
188
  /**
189
  * The DOM class of the button link.
190
  *
191
+ * @since 1.2.6
192
+ * @deprecated 2.7.0 Set 'class' key in $button_attr instead.
193
+ *
194
  * @var string
195
  */
196
  public $link_class = '';
198
  /**
199
  * The DOM ID of the button link.
200
  *
201
+ * @since 1.2.6
202
+ * @deprecated 2.7.0 Set 'id' key in $button_attr instead.
203
+ *
204
  * @var string
205
  */
206
  public $link_id = '';
208
  /**
209
  * The DOM rel value of the button link.
210
  *
211
+ * @since 1.2.6
212
+ * @deprecated 2.7.0 Set 'rel' key in $button_attr instead.
213
+ *
214
  * @var string
215
  */
216
  public $link_rel = '';
218
  /**
219
  * Title of the button link.
220
  *
221
+ * @since 1.2.6
222
+ * @deprecated 2.7.0 Set 'title' key in $button_attr instead.
 
 
 
 
 
 
 
 
 
 
223
  *
224
  * @var string
225
  */
226
+ public $link_title = '';
227
 
228
  /** Methods ***************************************************************/
229
 
238
 
239
  $r = wp_parse_args( $args, get_class_vars( __CLASS__ ) );
240
 
241
+ // Backward compatibility with deprecated parameters.
242
+ $r = $this->backward_compatibility_args( $r );
243
+
244
+ // Deprecated. Subject to removal in a future release.
245
+ $this->wrapper = $r['wrapper'];
246
+ if ( !empty( $r['link_id'] ) ) $this->link_id = ' id="' . $r['link_id'] . '"';
247
+ if ( !empty( $r['link_href'] ) ) $this->link_href = ' href="' . $r['link_href'] . '"';
248
+ if ( !empty( $r['link_title'] ) ) $this->link_title = ' title="' . $r['link_title'] . '"';
249
+ if ( !empty( $r['link_rel'] ) ) $this->link_rel = ' rel="' . $r['link_rel'] . '"';
250
+ if ( !empty( $r['link_class'] ) ) $this->link_class = ' class="' . $r['link_class'] . '"';
251
+ if ( !empty( $r['link_text'] ) ) $this->link_text = $r['link_text'];
252
+
253
  // Required button properties.
254
  $this->id = $r['id'];
255
  $this->component = $r['component'];
256
  $this->must_be_logged_in = (bool) $r['must_be_logged_in'];
257
  $this->block_self = (bool) $r['block_self'];
 
 
 
 
 
258
 
259
+ // $id and $component are required and component must be active.
260
+ if ( empty( $r['id'] ) || empty( $r['component'] ) || ! bp_is_active( $this->component ) ) {
261
  return false;
262
+ }
263
 
264
  // No button for guests if must be logged in.
265
+ if ( true == $this->must_be_logged_in && ! is_user_logged_in() ) {
266
  return false;
267
+ }
268
 
269
  // The block_self property.
270
  if ( true == $this->block_self ) {
271
+ /*
272
+ * No button if you are the current user in a members loop.
273
+ *
274
+ * This condition takes precedence, because members loops can be found on user
275
+ * profiles.
276
+ */
277
  if ( bp_get_member_user_id() ) {
278
  if ( is_user_logged_in() && bp_loggedin_user_id() == bp_get_member_user_id() ) {
279
  return false;
280
  }
281
 
282
+ // No button if viewing your own profile (and not in a members loop).
 
283
  } elseif ( bp_is_my_profile() ) {
284
  return false;
285
  }
286
  }
287
 
288
+ // Should we use a parent element?
289
+ if ( ! empty( $r['parent_element'] ) ) {
290
+ if ( ! isset( $r['parent_attr']['class'] ) ) {
291
+ $r['parent_attr']['class'] = '';
 
 
292
  }
293
 
294
+ // Always add 'generic-button' class.
295
+ if ( false === strpos( $r['parent_attr']['class'], 'generic-button' ) ) {
296
+ if ( ! is_array( $r['parent_attr'] ) ) {
297
+ $r['parent_attr'] = array();
298
+ }
299
+ if ( ! empty( $r['parent_attr']['class'] ) ) {
300
+ $r['parent_attr']['class'] .= ' ';
301
+ }
302
+ $r['parent_attr']['class'] .= 'generic-button';
303
  }
304
 
305
+ // Set parent element props.
306
+ $this->parent_element = $r['parent_element'];
307
+ $this->parent_attr = $r['parent_attr'];
308
+
309
+ // Render parent element attributes.
310
+ $parent_elem = new BP_Core_HTML_Element( array(
311
+ 'element' => $r['parent_element'],
312
+ 'attr' => $r['parent_attr']
313
+ ) );
314
+
315
  // Set before and after.
316
+ $before = $parent_elem->get( 'open_tag' );
317
+ $after = $parent_elem->get( 'close_tag' );
318
 
319
+ // No parent element.
320
  } else {
321
  $before = $after = '';
322
  }
323
 
324
+ // Button properties.
325
+ $button = '';
326
+ if ( ! empty( $r['button_element'] ) ) {
327
+ $button = new BP_Core_HTML_Element( array(
328
+ 'element' => $r['button_element'],
329
+ 'attr' => $r['button_attr'],
330
+ 'inner_html' => ! empty( $r['link_text'] ) ? $r['link_text'] : ''
331
+ ) );
332
+ $button = $button->contents();
333
+ }
334
 
335
  // Build the button.
336
+ $this->contents = $before . $button . $after;
337
 
338
  /**
339
  * Filters the button based on class parameters.
342
  * allows button to be manipulated externally.
343
  *
344
  * @since 1.2.6
345
+ * @since 2.7.0 Added $r as a parameter.
346
  *
347
  * @param string $contents HTML being used for the button.
348
  * @param BP_Button $this Current BP_Button instance.
349
  * @param string $before HTML appended before the actual button.
350
  * @param string $after HTML appended after the actual button.
351
+ * @param array $r Parsed button arguments.
352
  */
353
+ $this->contents = apply_filters( 'bp_button_' . $this->component . '_' . $this->id, $this->contents, $this, $before, $after, $r );
354
  }
355
 
356
+
357
+ /**
358
+ * Provide backward compatibility for deprecated button arguments.
359
+ *
360
+ * @since 2.7.0.
361
+ *
362
+ * @param array $r See {@link BP_Button} class for full documentation.
363
+ * @return array
364
+ */
365
+ protected function backward_compatibility_args( $r = array() ) {
366
+ // Array of deprecated arguments.
367
+ $backpat_args = array(
368
+ 'wrapper', 'wrapper_class', 'wrapper_id',
369
+ 'link_href', 'link_class', 'link_id', 'link_rel', 'link_title'
370
+ );
371
+
372
+ foreach ( $backpat_args as $prop ) {
373
+ if ( empty( $r[ $prop ] ) ) {
374
+ continue;
375
+ }
376
+
377
+ $parent = $child = false;
378
+ $sep = strpos( $prop, '_' );
379
+
380
+ // Check if this is an attribute.
381
+ if ( false !== $sep ) {
382
+ $child = true;
383
+ $parent = substr( $prop, 0, $sep );
384
+ } else {
385
+ $parent = $prop;
386
+ }
387
+
388
+ if ( 'wrapper' === $parent ) {
389
+ $parent = 'parent';
390
+ } else {
391
+ $parent = 'button';
392
+ }
393
+
394
+ // Set element.
395
+ if ( false === $child && empty( $r[ "{$parent}_element" ] ) ) {
396
+ $r[ "{$parent}_element" ] = $r[ $prop ];
397
+
398
+ // Set attributes.
399
+ } elseif ( true === $child ) {
400
+ $new_prop = substr( $prop, strpos( $prop, '_' ) +1 );
401
+ if ( empty( $r[ "{$parent}_attr" ] ) ) {
402
+ $r[ "{$parent}_attr" ] = array();
403
+ }
404
+
405
+ if ( empty( $r[ "{$parent}_attr" ][ $new_prop ] ) ) {
406
+ $r[ "{$parent}_attr" ][ $new_prop ] = $r[ $prop ];
407
+ }
408
+ }
409
+ }
410
+
411
+ return $r;
412
+ }
413
+
414
+
415
  /**
416
  * Return the markup for the generated button.
417
  *
bp-core/classes/class-bp-component.php CHANGED
@@ -393,6 +393,17 @@ class BP_Component {
393
  do_action( 'bp_' . $this->id . '_includes' );
394
  }
395
 
 
 
 
 
 
 
 
 
 
 
 
396
  /**
397
  * Set up the actions.
398
  *
@@ -414,6 +425,9 @@ class BP_Component {
414
  // extending this base class.
415
  add_action( 'bp_include', array( $this, 'includes' ), 8 );
416
 
 
 
 
417
  // Setup navigation.
418
  add_action( 'bp_setup_nav', array( $this, 'setup_nav' ), 10 );
419
 
393
  do_action( 'bp_' . $this->id . '_includes' );
394
  }
395
 
396
+ /**
397
+ * Late includes method.
398
+ *
399
+ * Components should include files here only on specific pages using
400
+ * conditionals such as {@link bp_is_current_component()}. Intentionally left
401
+ * empty.
402
+ *
403
+ * @since 3.0.0
404
+ */
405
+ public function late_includes() {}
406
+
407
  /**
408
  * Set up the actions.
409
  *
425
  // extending this base class.
426
  add_action( 'bp_include', array( $this, 'includes' ), 8 );
427
 
428
+ // Load files conditionally, based on certain pages.
429
+ add_action( 'bp_late_include', array( $this, 'late_includes' ) );
430
+
431
  // Setup navigation.
432
  add_action( 'bp_setup_nav', array( $this, 'setup_nav' ), 10 );
433
 
bp-core/classes/class-bp-core-bp-nav-backcompat.php CHANGED
@@ -180,7 +180,7 @@ class BP_Core_BP_Nav_BackCompat implements ArrayAccess {
180
  * @since 2.6.0
181
  *
182
  * @param mixed $offset Array offset.
183
- * @return string
184
  */
185
  public function get_component( $offset = '' ) {
186
  if ( ! isset( $this->component ) ) {
180
  * @since 2.6.0
181
  *
182
  * @param mixed $offset Array offset.
183
+ * @return string|array
184
  */
185
  public function get_component( $offset = '' ) {
186
  if ( ! isset( $this->component ) ) {
bp-core/classes/class-bp-core-html-element.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Core component classes.
4
+ *
5
+ * @package BuddyPress
6
+ * @subpackage Core
7
+ * @since 2.7.0
8
+ */
9
+
10
+ /**
11
+ * Generate markup for an HTML element.
12
+ *
13
+ * @since 2.7.0
14
+ */
15
+ class BP_Core_HTML_Element {
16
+ /**
17
+ * Open tag for an element.
18
+ *
19
+ * This would include attributes if applicable. eg. '<a href="" class="">'
20
+ *
21
+ * @since 2.7.0
22
+ *
23
+ * @var string
24
+ */
25
+ public $open_tag = '';
26
+
27
+ /**
28
+ * Inner HTML for an element.
29
+ *
30
+ * For example, this could be anchor text within an <a> element.
31
+ *
32
+ * @since 2.7.0
33
+ *
34
+ * @var string
35
+ */
36
+ public $inner_html = '';
37
+
38
+ /**
39
+ * Closing tag for an element.
40
+ *
41
+ * For example, "</a>".
42
+ *
43
+ * @since 2.7.0
44
+ *
45
+ * @var string
46
+ */
47
+ public $close_tag = '';
48
+
49
+ /**
50
+ * Constructor.
51
+ *
52
+ * @since 2.7.0
53
+ *
54
+ * @param array $r {
55
+ * An array of arguments.
56
+ * @type string $element The element to render. eg. 'a' for the anchor element.
57
+ * @type array $attr Optional. The element's attributes set as key/value pairs. eg.
58
+ * array( 'href' => 'http://example.com', 'class' => 'my-class' )
59
+ * @type string $inner_html Optional. The inner HTML for the element if applicable. Please note that
60
+ * this isn't sanitized, so you should use your own sanitization routine
61
+ * before using this parameter.
62
+ * }
63
+ */
64
+ public function __construct( $r = array() ) {
65
+ $elem = sanitize_html_class( $r['element'] );
66
+ if ( empty( $elem ) ) {
67
+ return;
68
+ }
69
+
70
+ // Render attributes.
71
+ $attributes = '';
72
+ foreach( (array) $r['attr'] as $attr => $val ) {
73
+ // If attribute is empty, skip.
74
+ if ( empty( $val ) ) {
75
+ continue;
76
+ }
77
+
78
+ if ( 'href' === $attr || 'formaction' === $attr || 'src' === $attr ) {
79
+ $val = esc_url( $val );
80
+ } elseif ( 'id' === $attr ) {
81
+ $val = sanitize_html_class( $val );
82
+ } else {
83
+ $val = esc_attr( $val );
84
+ }
85
+
86
+ $attributes .= sprintf( '%s="%s" ', sanitize_html_class( $attr ), $val );
87
+ }
88
+
89
+ // <input> / <img> is self-closing.
90
+ if ( 'input' === $elem || 'img' === $elem ) {
91
+ $this->open_tag = sprintf( '<%1$s %2$s />', $elem, $attributes );
92
+
93
+ // All other elements.
94
+ } else {
95
+ $this->open_tag = sprintf( '<%1$s %2$s>', $elem, $attributes );
96
+ $this->inner_html = ! empty( $r['inner_html'] ) ? $r['inner_html'] : '';
97
+ $this->close_tag = sprintf( '</%1$s>', $elem );
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Returns a property from this class.
103
+ *
104
+ * @since 2.7.0
105
+ *
106
+ * @param string $prop Property name. Either 'open_tag', 'inner_html', 'close_tag'.
107
+ * @return string
108
+ */
109
+ public function get( $prop = '' ) {
110
+ if ( ! isset( $this->{$prop} ) ) {
111
+ return '';
112
+ }
113
+
114
+ return $this->{$prop};
115
+ }
116
+
117
+ /**
118
+ * Returns full contents of HTML element.
119
+ *
120
+ * @since 2.7.0
121
+ *
122
+ * @return string
123
+ */
124
+ public function contents() {
125
+ return $this->open_tag . $this->inner_html . $this->close_tag;
126
+ }
127
+ }
bp-core/classes/class-bp-core-login-widget.php CHANGED
@@ -104,7 +104,7 @@ class BP_Core_Login_Widget extends WP_Widget {
104
  */
105
  do_action( 'bp_before_login_widget_loggedout' ); ?>
106
 
107
- <form name="bp-login-form" id="bp-login-widget-form" class="standard-form" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post">
108
  <label for="bp-login-widget-user-login"><?php _e( 'Username', 'buddypress' ); ?></label>
109
  <input type="text" name="log" id="bp-login-widget-user-login" class="input" value="" />
110
 
@@ -117,7 +117,7 @@ class BP_Core_Login_Widget extends WP_Widget {
117
 
118
  <?php if ( bp_get_signup_allowed() ) : ?>
119
 
120
- <span class="bp-login-widget-register-link"><a href="<?php echo esc_url( bp_get_signup_page() ); ?>" title="<?php esc_attr_e( 'Register for a new account', 'buddypress' ); ?>"><?php _e( 'Register', 'buddypress' ); ?></a></span>
121
 
122
  <?php endif; ?>
123
 
104
  */
105
  do_action( 'bp_before_login_widget_loggedout' ); ?>
106
 
107
+ <form name="bp-login-form" id="bp-login-widget-form" class="standard-form" action="<?php echo esc_url( wp_login_url() ); ?>" method="post">
108
  <label for="bp-login-widget-user-login"><?php _e( 'Username', 'buddypress' ); ?></label>
109
  <input type="text" name="log" id="bp-login-widget-user-login" class="input" value="" />
110
 
117
 
118
  <?php if ( bp_get_signup_allowed() ) : ?>
119
 
120
+ <span class="bp-login-widget-register-link"><a href="<?php echo esc_url( bp_get_signup_page() ); ?>"><?php _e( 'Register', 'buddypress' ); ?></a></span>
121
 
122
  <?php endif; ?>
123
 
bp-core/classes/class-bp-core-nav-item.php CHANGED
@@ -3,8 +3,6 @@
3
  // Exit if accessed directly.
4
  defined( 'ABSPATH' ) || exit;
5
 
6
- if ( class_exists( 'ArrayObject' ) ) :
7
-
8
  /**
9
  * Navigation item.
10
  *
@@ -15,20 +13,3 @@ class BP_Core_Nav_Item extends ArrayObject {
15
  parent::__construct( $data, ArrayObject::ARRAY_AS_PROPS );
16
  }
17
  }
18
-
19
- else :
20
-
21
- /**
22
- * Navigation item.
23
- *
24
- * @since 2.6.0
25
- */
26
- class BP_Core_Nav_Item {
27
- public function __construct( $data ) {
28
- foreach ( $data as $key => $value ) {
29
- $this->key = $value;
30
- }
31
- }
32
- }
33
-
34
- endif;
3
  // Exit if accessed directly.
4
  defined( 'ABSPATH' ) || exit;
5
 
 
 
6
  /**
7
  * Navigation item.
8
  *
13
  parent::__construct( $data, ArrayObject::ARRAY_AS_PROPS );
14
  }
15
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-core/classes/class-bp-core-nav.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package BuddyPress
6
  * @subpackage Core
7
- * @since 2.6.0
8
  */
9
 
10
  // Exit if accessed directly.
@@ -56,7 +56,7 @@ class BP_Core_Nav {
56
  *
57
  * @since 2.6.0
58
  *
59
- * @param string $key The requested nav slug.
60
  * @return bool True if the nav item is set, false otherwise.
61
  */
62
  public function __isset( $key ) {
@@ -68,7 +68,7 @@ class BP_Core_Nav {
68
  *
69
  * @since 2.6.0
70
  *
71
- * @param string $key The requested nav slug.
72
  * @return mixed The value corresponding to the requested nav item.
73
  */
74
  public function __get( $key ) {
@@ -84,8 +84,8 @@ class BP_Core_Nav {
84
  *
85
  * @since 2.6.0
86
  *
87
- * @param string $key The requested nav slug.
88
- * @param mixed $value The value of the nav item.
89
  */
90
  public function __set( $key, $value ) {
91
  if ( is_array( $value ) ) {
@@ -100,7 +100,7 @@ class BP_Core_Nav {
100
  *
101
  * @since 2.6.0
102
  *
103
- * @param string $key The nav item slug to get. Optional.
104
  * @return mixed An array of nav item, a single nav item, or null if none found.
105
  */
106
  public function get( $key = '' ) {
@@ -210,11 +210,13 @@ class BP_Core_Nav {
210
  *
211
  * @since 2.6.0
212
  *
213
- * @param string $key The slug of the main item.
214
- * @param string $sub_key The slug of the sub item.
215
- * @return bool|callable|array False on failure, the screen function(s) on success.
216
  */
217
- public function delete_nav( $slug, $parent_slug = '' ) {
 
 
218
  if ( empty( $slug ) ) {
219
  return false;
220
  }
@@ -274,7 +276,7 @@ class BP_Core_Nav {
274
  unset( $this->nav[ $this->object_id ][ $nav_item->slug ] );
275
 
276
  // Return the deleted item's screen functions.
277
- return array_unique( $screen_functions );
278
  }
279
  }
280
 
@@ -318,14 +320,14 @@ class BP_Core_Nav {
318
  *
319
  * @since 2.6.0
320
  *
321
- * @param array $args Filters to select the specific primary items. See wp_list_filter().
322
- * @param bool $sort True to sort the nav items. False otherwise.
323
  * @return array The list of primary objects nav
324
  */
325
  public function get_primary( $args = array(), $sort = true ) {
326
  $params = wp_parse_args( $args, array( 'primary' => true ) );
327
 
328
- // This parameter is not overridable
329
  if ( empty( $params['primary'] ) ) {
330
  return false;
331
  }
@@ -348,14 +350,14 @@ class BP_Core_Nav {
348
  *
349
  * @since 2.6.0
350
  *
351
- * @param array $args Filters to select the specific secondary items. See wp_list_filter().
352
- * @param bool $sort True to sort the nav items. False otherwise.
353
- * @return array The list of secondary objects nav
354
  */
355
  public function get_secondary( $args = array(), $sort = true ) {
356
  $params = wp_parse_args( $args, array( 'parent_slug' => '' ) );
357
 
358
- // No need to search children if the parent is not set
359
  if ( empty( $params['parent_slug'] ) && empty( $params['secondary'] ) ) {
360
  return false;
361
  }
@@ -385,11 +387,11 @@ class BP_Core_Nav {
385
 
386
  if ( $primary_nav_items ) {
387
  foreach( $primary_nav_items as $key_nav => $primary_nav ) {
388
- // Try to get the children
389
  $children = $this->get_secondary( array( 'parent_slug' => $primary_nav->slug, 'user_has_access' => true ) );
390
 
391
  if ( $children ) {
392
- $primary_nav_items[ $key_nav ] = clone( $primary_nav );
393
  $primary_nav_items[ $key_nav ]->children = $children;
394
  }
395
  }
4
  *
5
  * @package BuddyPress
6
  * @subpackage Core
7
+ * @since 2.6.0
8
  */
9
 
10
  // Exit if accessed directly.
56
  *
57
  * @since 2.6.0
58
  *
59
+ * @param string $key The requested nav slug.
60
  * @return bool True if the nav item is set, false otherwise.
61
  */
62
  public function __isset( $key ) {
68
  *
69
  * @since 2.6.0
70
  *
71
+ * @param string $key The requested nav slug.
72
  * @return mixed The value corresponding to the requested nav item.
73
  */
74
  public function __get( $key ) {
84
  *
85
  * @since 2.6.0
86
  *
87
+ * @param string $key The requested nav slug.
88
+ * @param mixed $value The value of the nav item.
89
  */
90
  public function __set( $key, $value ) {
91
  if ( is_array( $value ) ) {
100
  *
101
  * @since 2.6.0
102
  *
103
+ * @param string $key The nav item slug to get. Optional.
104
  * @return mixed An array of nav item, a single nav item, or null if none found.
105
  */
106
  public function get( $key = '' ) {
210
  *
211
  * @since 2.6.0
212
  *
213
+ * @param string $slug The slug of the main item.
214
+ * @param string $parent_slug The slug of the sub item.
215
+ * @return false|callable|array False on failure, the screen function(s) on success.
216
  */
217
+ public function delete_nav( $slug = '', $parent_slug = '' ) {
218
+
219
+ // Bail if slug is empty
220
  if ( empty( $slug ) ) {
221
  return false;
222
  }
276
  unset( $this->nav[ $this->object_id ][ $nav_item->slug ] );
277
 
278
  // Return the deleted item's screen functions.
279
+ return $screen_functions;
280
  }
281
  }
282
 
320
  *
321
  * @since 2.6.0
322
  *
323
+ * @param array $args Filters to select the specific primary items. See wp_list_filter().
324
+ * @param bool $sort True to sort the nav items. False otherwise.
325
  * @return array The list of primary objects nav
326
  */
327
  public function get_primary( $args = array(), $sort = true ) {
328
  $params = wp_parse_args( $args, array( 'primary' => true ) );
329
 
330
+ // This parameter is not overridable.
331
  if ( empty( $params['primary'] ) ) {
332
  return false;
333
  }
350
  *
351
  * @since 2.6.0
352
  *
353
+ * @param array $args Filters to select the specific secondary items. See wp_list_filter().
354
+ * @param bool $sort True to sort the nav items. False otherwise.
355
+ * @return bool|array The list of secondary objects nav, or false if none set.
356
  */
357
  public function get_secondary( $args = array(), $sort = true ) {
358
  $params = wp_parse_args( $args, array( 'parent_slug' => '' ) );
359
 
360
+ // No need to search children if the parent is not set.
361
  if ( empty( $params['parent_slug'] ) && empty( $params['secondary'] ) ) {
362
  return false;
363
  }
387
 
388
  if ( $primary_nav_items ) {
389
  foreach( $primary_nav_items as $key_nav => $primary_nav ) {
390
+ // Try to get the children.
391
  $children = $this->get_secondary( array( 'parent_slug' => $primary_nav->slug, 'user_has_access' => true ) );
392
 
393
  if ( $children ) {
394
+ $primary_nav_items[ $key_nav ] = clone $primary_nav;
395
  $primary_nav_items[ $key_nav ]->children = $children;
396
  }
397
  }
bp-core/classes/class-bp-core-oembed-extension.php CHANGED
@@ -4,6 +4,7 @@
4
  *
5
  * @package BuddyPress
6
  * @subpackage Core
 
7
  */
8
 
9
  // Exit if accessed directly.
@@ -52,6 +53,8 @@ abstract class BP_Core_oEmbed_Extension {
52
  * Add content for your oEmbed response here.
53
  *
54
  * @since 2.6.0
 
 
55
  */
56
  abstract protected function content();
57
 
@@ -71,6 +74,7 @@ abstract class BP_Core_oEmbed_Extension {
71
  *
72
  * @since 2.6.0
73
  *
 
74
  * @return int Your item ID
75
  */
76
  abstract protected function validate_url_to_item_id( $url );
@@ -80,7 +84,7 @@ abstract class BP_Core_oEmbed_Extension {
80
  *
81
  * @since 2.6.0
82
  *
83
- * @param int $item_id Your item ID to do checks against.
84
  * @return array Should contain 'content', 'title', 'author_url', 'author_name' as array
85
  * keys. 'author_url' and 'author_name' is optional; the rest are required.
86
  */
@@ -94,7 +98,7 @@ abstract class BP_Core_oEmbed_Extension {
94
  *
95
  * @since 2.6.0
96
  *
97
- * @param int $item_id Your item ID to do checks against.
98
  * @return string Fallback HTML you want to output.
99
  */
100
  abstract protected function set_fallback_html( $item_id );
@@ -122,7 +126,6 @@ abstract class BP_Core_oEmbed_Extension {
122
  * @since 2.6.0
123
  *
124
  * @param int $item_id The item ID to do checks for.
125
- * @return string
126
  */
127
  protected function set_iframe_title( $item_id ) {}
128
 
@@ -145,7 +148,7 @@ abstract class BP_Core_oEmbed_Extension {
145
  protected function set_permalink() {
146
  $url = bp_get_requested_url();
147
 
148
- // Remove querystring from bp_get_requested_url()
149
  if ( false !== strpos( bp_get_requested_url(), '?' ) ) {
150
  $url = substr( bp_get_requested_url(), 0, strpos( bp_get_requested_url(), '?' ) );
151
  }
@@ -239,7 +242,7 @@ abstract class BP_Core_oEmbed_Extension {
239
  *
240
  * @since 2.6.0
241
  *
242
- * @param string $template File path to current embed template.
243
  * @return string
244
  */
245
  public function setup_template_parts( $template ) {
@@ -263,6 +266,9 @@ abstract class BP_Core_oEmbed_Extension {
263
  * and inject our own template for BuddyPress use.
264
  *
265
  * @since 2.6.0
 
 
 
266
  */
267
  public function content_buffer_start( $slug, $name ) {
268
  if ( 'embed' !== $slug || 'content' !== $name ) {
@@ -280,6 +286,8 @@ abstract class BP_Core_oEmbed_Extension {
280
  * and inject our own template for BuddyPress use.
281
  *
282
  * @since 2.6.0
 
 
283
  */
284
  public function content_buffer_end( $name ) {
285
  if ( 'embed' !== $name || is_404() ) {
@@ -318,7 +326,7 @@ abstract class BP_Core_oEmbed_Extension {
318
  *
319
  * @since 2.6.0
320
  *
321
- * @param string $retval Current discovery links.
322
  * @return string
323
  */
324
  public function add_oembed_discovery_links( $retval ) {
@@ -353,8 +361,8 @@ abstract class BP_Core_oEmbed_Extension {
353
  *
354
  * @link http://oembed.com/ View the 'Response parameters' section for more details.
355
  *
356
- * @param array $item Custom oEmbed response data.
357
- * @param int $width The requested width.
358
  * @return array
359
  */
360
  protected function get_oembed_response_data( $item, $width ) {
@@ -403,7 +411,7 @@ abstract class BP_Core_oEmbed_Extension {
403
  *
404
  * @since 2.6.0
405
  *
406
- * @param WP_REST_Request $request Full data about the request.
407
  * @return WP_Error|array oEmbed response data or WP_Error on failure.
408
  */
409
  public function get_item( $request ) {
@@ -508,7 +516,7 @@ abstract class BP_Core_oEmbed_Extension {
508
  *
509
  * @see bp_activity_embed_rest_route_callback()
510
  *
511
- * @param string $retval Current embed URL
512
  * @return string
513
  */
514
  public function filter_embed_url( $retval ) {
@@ -520,7 +528,7 @@ abstract class BP_Core_oEmbed_Extension {
520
  $url = trailingslashit( $url );
521
 
522
  // This is for the 'WordPress Embed' block
523
- // @see bp_activity_embed_comments_button()
524
  if ( 'the_permalink' !== current_filter() ) {
525
  $url = add_query_arg( 'embed', 'true', trailingslashit( $url ) );
526
 
@@ -540,7 +548,7 @@ abstract class BP_Core_oEmbed_Extension {
540
  *
541
  * @since 2.6.0
542
  *
543
- * @param string $retval Current embed HTML
544
  * @return string
545
  */
546
  public function filter_embed_html( $retval ) {
@@ -567,7 +575,7 @@ abstract class BP_Core_oEmbed_Extension {
567
  $retval = str_replace( '<iframe', '<iframe style="max-width:100%"', $retval );
568
  }
569
 
570
- // Remove default <blockquote>
571
  $retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 );
572
 
573
  // Set up new fallback HTML
@@ -594,7 +602,7 @@ abstract class BP_Core_oEmbed_Extension {
594
  *
595
  * @see add_oembed_discovery_links()
596
  *
597
- * @param string $retval Current oEmbed endpoint URL
598
  * @return string
599
  */
600
  public function filter_rest_url( $retval = '' ) {
@@ -613,4 +621,4 @@ abstract class BP_Core_oEmbed_Extension {
613
 
614
  $this->content();
615
  }
616
- }
4
  *
5
  * @package BuddyPress
6
  * @subpackage Core
7
+ * @since 2.6.0
8
  */
9
 
10
  // Exit if accessed directly.
53
  * Add content for your oEmbed response here.
54
  *
55
  * @since 2.6.0
56
+ *
57
+ * @return null
58
  */
59
  abstract protected function content();
60
 
74
  *
75
  * @since 2.6.0
76
  *
77
+ * @param string $url URL to validate.
78
  * @return int Your item ID
79
  */
80
  abstract protected function validate_url_to_item_id( $url );
84
  *
85
  * @since 2.6.0
86
  *
87
+ * @param int $item_id Your item ID to do checks against.
88
  * @return array Should contain 'content', 'title', 'author_url', 'author_name' as array
89
  * keys. 'author_url' and 'author_name' is optional; the rest are required.
90
  */
98
  *
99
  * @since 2.6.0
100
  *
101
+ * @param int $item_id Your item ID to do checks against.
102
  * @return string Fallback HTML you want to output.
103
  */
104
  abstract protected function set_fallback_html( $item_id );
126
  * @since 2.6.0
127
  *
128
  * @param int $item_id The item ID to do checks for.
 
129
  */
130
  protected function set_iframe_title( $item_id ) {}
131
 
148
  protected function set_permalink() {
149
  $url = bp_get_requested_url();
150
 
151
+ // Remove querystring from bp_get_requested_url().
152
  if ( false !== strpos( bp_get_requested_url(), '?' ) ) {
153
  $url = substr( bp_get_requested_url(), 0, strpos( bp_get_requested_url(), '?' ) );
154
  }
242
  *
243
  * @since 2.6.0
244
  *
245
+ * @param string $template File path to current embed template.
246
  * @return string
247
  */
248
  public function setup_template_parts( $template ) {
266
  * and inject our own template for BuddyPress use.
267
  *
268
  * @since 2.6.0
269
+ *
270
+ * @param string $slug Template slug.
271
+ * @param string $name Template name.
272
  */
273
  public function content_buffer_start( $slug, $name ) {
274
  if ( 'embed' !== $slug || 'content' !== $name ) {
286
  * and inject our own template for BuddyPress use.
287
  *
288
  * @since 2.6.0
289
+ *
290
+ * @param string $name Template name.
291
  */
292
  public function content_buffer_end( $name ) {
293
  if ( 'embed' !== $name || is_404() ) {
326
  *
327
  * @since 2.6.0
328
  *
329
+ * @param string $retval Current discovery links.
330
  * @return string
331
  */
332
  public function add_oembed_discovery_links( $retval ) {
361
  *
362
  * @link http://oembed.com/ View the 'Response parameters' section for more details.
363
  *
364
+ * @param array $item Custom oEmbed response data.
365
+ * @param int $width The requested width.
366
  * @return array
367
  */
368
  protected function get_oembed_response_data( $item, $width ) {
411
  *
412
  * @since 2.6.0
413
  *
414
+ * @param WP_REST_Request $request Full data about the request.
415
  * @return WP_Error|array oEmbed response data or WP_Error on failure.
416
  */
417
  public function get_item( $request ) {
516
  *
517
  * @see bp_activity_embed_rest_route_callback()
518
  *
519
+ * @param string $retval Current embed URL.
520
  * @return string
521
  */
522
  public function filter_embed_url( $retval ) {
528
  $url = trailingslashit( $url );
529
 
530
  // This is for the 'WordPress Embed' block
531
+ // @see bp_activity_embed_comments_button().
532
  if ( 'the_permalink' !== current_filter() ) {
533
  $url = add_query_arg( 'embed', 'true', trailingslashit( $url ) );
534
 
548
  *
549
  * @since 2.6.0
550
  *
551
+ * @param string $retval Current embed HTML.
552
  * @return string
553
  */
554
  public function filter_embed_html( $retval ) {
575
  $retval = str_replace( '<iframe', '<iframe style="max-width:100%"', $retval );
576
  }
577
 
578
+ // Remove default <blockquote>.
579
  $retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 );
580
 
581
  // Set up new fallback HTML
602
  *
603
  * @see add_oembed_discovery_links()
604
  *
605
+ * @param string $retval Current oEmbed endpoint URL.
606
  * @return string
607
  */
608
  public function filter_rest_url( $retval = '' ) {
621
 
622
  $this->content();
623
  }
624
+ }
bp-core/classes/class-bp-core-sort-by-key-callback.php DELETED
@@ -1,83 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Callback class for bp_sort_by_key().
5
- *
6
- * Used in place of an anonymous closure.
7
- *
8
- * Developers should not use this class directly, as it may be removed once support for PHP 5.2 is dropped.
9
- *
10
- * @ignore
11
- *
12
- * @since 2.5.0
13
- */
14
- class BP_Core_Sort_By_Key_Callback {
15
- /**
16
- * Object/array index to use for sorting.
17
- *
18
- * @since 2.5.0
19
- * @var mixed
20
- */
21
- protected $key;
22
-
23
- /**
24
- * Sort type.
25
- *
26
- * @since 2.5.0
27
- * @var string
28
- */
29
- protected $type;
30
-
31
- /**
32
- * Constructor.
33
- *
34
- * @since 2.5.0
35
- *
36
- * @param mixed $key Object or array index to use for sorting.
37
- * @param string $type Sort type.
38
- */
39
- public function __construct( $key, $type ) {
40
- $this->key = $key;
41
- $this->type = $type;
42
- }
43
-
44
- /**
45
- * Sort callback.
46
- *
47
- * @since 2.5.0
48
- *
49
- * @param $a object|array
50
- * @param $b object|array
51
- * @return int
52
- */
53
- public function sort_callback( $a, $b ) {
54
- $values = array( 0 => false, 1 => false, );
55
- $func_args = func_get_args();
56
- foreach ( $func_args as $indexi => $index ) {
57
- if ( isset( $index->{$this->key} ) ) {
58
- $values[ $indexi ] = $index->{$this->key};
59
- } elseif ( isset( $index[ $this->key ] ) ) {
60
- $values[ $indexi ] = $index[ $this->key ];
61
- }
62
- }
63
-
64
- if ( isset( $values[0], $values[1] ) ) {
65
- if ( 'num' === $this->type ) {
66
- $cmp = $values[0] - $values[1];
67
- } else {
68
- $cmp = strcmp( $values[0], $values[1] );
69
- }
70
-
71
- if ( 0 > $cmp ) {
72
- $retval = -1;
73
- } elseif ( 0 < $cmp ) {
74
- $retval = 1;
75
- } else {
76
- $retval = 0;
77
- }
78
- return $retval;
79
- } else {
80
- return 0;
81
- }
82
- }
83
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-core/classes/class-bp-core-user.php CHANGED
@@ -157,7 +157,7 @@ class BP_Core_User {
157
 
158
  $this->user_url = bp_core_get_user_domain( $this->id, $this->profile_data['user_nicename'], $this->profile_data['user_login'] );
159
  $this->fullname = esc_attr( $this->profile_data[$full_name_field_name]['field_data'] );
160
- $this->user_link = "<a href='{$this->user_url}' title='{$this->fullname}'>{$this->fullname}</a>";
161
  $this->email = esc_attr( $this->profile_data['user_email'] );
162
  } else {
163
  $this->user_url = bp_core_get_user_domain( $this->id );
@@ -166,11 +166,6 @@ class BP_Core_User {
166
  $this->email = esc_attr( bp_core_get_user_email( $this->id ) );
167
  }
168
 
169
- // Cache a few things that are fetched often.
170
- wp_cache_set( 'bp_user_fullname_' . $this->id, $this->fullname, 'bp' );
171
- wp_cache_set( 'bp_user_email_' . $this->id, $this->email, 'bp' );
172
- wp_cache_set( 'bp_user_url_' . $this->id, $this->user_url, 'bp' );
173
-
174
  $this->avatar = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'full', 'alt' => sprintf( __( 'Profile photo of %s', 'buddypress' ), $this->fullname ) ) );
175
  $this->avatar_thumb = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'thumb', 'alt' => sprintf( __( 'Profile photo of %s', 'buddypress' ), $this->fullname ) ) );
176
  $this->avatar_mini = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'thumb', 'alt' => sprintf( __( 'Profile photo of %s', 'buddypress' ), $this->fullname ), 'width' => 30, 'height' => 30 ) );
@@ -230,7 +225,7 @@ class BP_Core_User {
230
  * Default: false.
231
  * @param string|bool $meta_value See {@link BP_User_Query}.
232
  * Default: false.
233
- * @return array {
234
  * @type int $total_users Total number of users matched by query
235
  * params.
236
  * @type array $paged_users The current page of users matched by
@@ -439,7 +434,7 @@ class BP_Core_User {
439
  * @param bool $populate_extras If we should populate extra user fields.
440
  * @param string $exclude Comma-separated IDs of users whose results
441
  * aren't to be fetched.
442
- * @return mixed False on error, otherwise associative array of results.
443
  */
444
  public static function get_users_by_letter( $letter, $limit = null, $page = 1, $populate_extras = true, $exclude = '' ) {
445
  global $wpdb;
@@ -723,16 +718,6 @@ class BP_Core_User {
723
  }
724
  }
725
 
726
- if ( 'active' != $type ) {
727
- $user_activity = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as last_activity FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'last_activity' ) ) );
728
- for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) {
729
- foreach ( (array) $user_activity as $activity ) {
730
- if ( $activity->id == $paged_users[$i]->id )
731
- $paged_users[$i]->last_activity = $activity->last_activity;
732
- }
733
- }
734
- }
735
-
736
  // Fetch the user's last_activity.
737
  if ( 'active' != $type ) {
738
  $user_activity = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as last_activity FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'last_activity' ) ) );
@@ -759,25 +744,20 @@ class BP_Core_User {
759
  /**
760
  * Get WordPress user details for a specified user.
761
  *
762
- * @global wpdb $wpdb WordPress database object.
763
  *
764
  * @param int $user_id User ID.
765
- * @return array Associative array.
766
  */
767
  public static function get_core_userdata( $user_id ) {
768
- global $wpdb;
769
-
770
- if ( !$user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->users} WHERE ID = %d LIMIT 1", $user_id ) ) )
771
- return false;
772
-
773
- return $user;
774
  }
775
 
776
  /**
777
  * Get last activity data for a user or set of users.
778
  *
779
  * @param int|array $user_id User IDs or multiple user IDs.
780
- * @return array
781
  */
782
  public static function get_last_activity( $user_id ) {
783
  global $wpdb;
@@ -811,6 +791,13 @@ class BP_Core_User {
811
  $retval = array();
812
  foreach ( $user_ids as $user_id ) {
813
  $retval[ $user_id ] = wp_cache_get( $user_id, 'bp_last_activity' );
 
 
 
 
 
 
 
814
  }
815
 
816
  return $retval;
@@ -905,6 +892,16 @@ class BP_Core_User {
905
  // Set cache.
906
  wp_cache_set( $user_id, $activity[ $user_id ], 'bp_last_activity' );
907
 
 
 
 
 
 
 
 
 
 
 
908
  return $updated;
909
  }
910
 
157
 
158
  $this->user_url = bp_core_get_user_domain( $this->id, $this->profile_data['user_nicename'], $this->profile_data['user_login'] );
159
  $this->fullname = esc_attr( $this->profile_data[$full_name_field_name]['field_data'] );
160
+ $this->user_link = "<a href='{$this->user_url}'>{$this->fullname}</a>";
161
  $this->email = esc_attr( $this->profile_data['user_email'] );
162
  } else {
163
  $this->user_url = bp_core_get_user_domain( $this->id );
166
  $this->email = esc_attr( bp_core_get_user_email( $this->id ) );
167
  }
168
 
 
 
 
 
 
169
  $this->avatar = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'full', 'alt' => sprintf( __( 'Profile photo of %s', 'buddypress' ), $this->fullname ) ) );
170
  $this->avatar_thumb = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'thumb', 'alt' => sprintf( __( 'Profile photo of %s', 'buddypress' ), $this->fullname ) ) );
171
  $this->avatar_mini = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'thumb', 'alt' => sprintf( __( 'Profile photo of %s', 'buddypress' ), $this->fullname ), 'width' => 30, 'height' => 30 ) );
225
  * Default: false.
226
  * @param string|bool $meta_value See {@link BP_User_Query}.
227
  * Default: false.
228
+ * @return false|array {
229
  * @type int $total_users Total number of users matched by query
230
  * params.
231
  * @type array $paged_users The current page of users matched by
434
  * @param bool $populate_extras If we should populate extra user fields.
435
  * @param string $exclude Comma-separated IDs of users whose results
436
  * aren't to be fetched.
437
+ * @return false|array False on error, otherwise associative array of results.
438
  */
439
  public static function get_users_by_letter( $letter, $limit = null, $page = 1, $populate_extras = true, $exclude = '' ) {
440
  global $wpdb;
718
  }
719
  }
720
 
 
 
 
 
 
 
 
 
 
 
721
  // Fetch the user's last_activity.
722
  if ( 'active' != $type ) {
723
  $user_activity = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as last_activity FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'last_activity' ) ) );
744
  /**
745
  * Get WordPress user details for a specified user.
746
  *
747
+ * @since 3.0.0 Results might be from cache
748
  *
749
  * @param int $user_id User ID.
750
+ * @return false|object WP_User if successful, false on failure.
751
  */
752
  public static function get_core_userdata( $user_id ) {
753
+ return WP_User::get_data_by( 'id', $user_id );
 
 
 
 
 
754
  }
755
 
756
  /**
757
  * Get last activity data for a user or set of users.
758
  *
759
  * @param int|array $user_id User IDs or multiple user IDs.
760
+ * @return false|array
761
  */
762
  public static function get_last_activity( $user_id ) {
763
  global $wpdb;
791
  $retval = array();
792
  foreach ( $user_ids as $user_id ) {
793
  $retval[ $user_id ] = wp_cache_get( $user_id, 'bp_last_activity' );
794
+
795
+ if ( isset( $retval['user_id'] ) ) {
796
+ $retval[ $user_id ]['user_id'] = (int) $retval[ $user_id ]['user_id'];
797
+ }
798
+ if ( isset( $retval['activity_id'] ) ) {
799
+ $retval[ $user_id ]['activity_id'] = (int) $retval[ $user_id ]['activity_id'];
800
+ }
801
  }
802
 
803
  return $retval;
892
  // Set cache.
893
  wp_cache_set( $user_id, $activity[ $user_id ], 'bp_last_activity' );
894
 
895
+ /**
896
+ * Fires when a user's last_activity value has been updated.
897
+ *
898
+ * @since 2.7.0
899
+ *
900
+ * @param int $user_id ID of the user.
901
+ * @param string $time Last activity timestamp, in 'Y-m-d H:i:s' format.
902
+ */
903
+ do_action( 'bp_core_user_updated_last_activity', $user_id, $time );
904
+
905
  return $updated;
906
  }
907
 
bp-core/classes/class-bp-core.php CHANGED
@@ -65,7 +65,7 @@ class BP_Core extends BP_Component {
65
  *
66
  * @param array $value Array of included and optional components.
67
  */
68
- $bp->optional_components = apply_filters( 'bp_optional_components', array( 'activity', 'blogs', 'forums', 'friends', 'groups', 'messages', 'notifications', 'settings', 'xprofile' ) );
69
 
70
  /**
71
  * Filters the required components.
@@ -254,10 +254,8 @@ class BP_Core extends BP_Component {
254
  $bp->core->table_name_notifications = $bp->table_prefix . 'bp_notifications';
255
 
256
  // Backward compatibility for plugins modifying the legacy bp_nav and bp_options_nav global properties.
257
- if ( buddypress()->do_nav_backcompat ) {
258
- $bp->bp_nav = new BP_Core_BP_Nav_BackCompat();
259
- $bp->bp_options_nav = new BP_Core_BP_Options_Nav_BackCompat();
260
- }
261
 
262
  /**
263
  * Used to determine if user has admin rights on current content. If the
65
  *
66
  * @param array $value Array of included and optional components.
67
  */
68
+ $bp->optional_components = apply_filters( 'bp_optional_components', array( 'activity', 'blogs', 'friends', 'groups', 'messages', 'notifications', 'settings', 'xprofile' ) );
69
 
70
  /**
71
  * Filters the required components.
254
  $bp->core->table_name_notifications = $bp->table_prefix . 'bp_notifications';
255
 
256
  // Backward compatibility for plugins modifying the legacy bp_nav and bp_options_nav global properties.
257
+ $bp->bp_nav = new BP_Core_BP_Nav_BackCompat();
258
+ $bp->bp_options_nav = new BP_Core_BP_Options_Nav_BackCompat();
 
 
259
 
260
  /**
261
  * Used to determine if user has admin rights on current content. If the
bp-core/classes/class-bp-email.php CHANGED
@@ -246,7 +246,7 @@ class BP_Email {
246
  switch ( $transform ) {
247
  // Special-case to fill the $template with the email $content.
248
  case 'add-content':
249
- $retval = str_replace( '{{{content}}}', nl2br( $this->get_content( 'replace-tokens' ) ), $retval );
250
  // Fall through.
251
 
252
  case 'replace-tokens':
246
  switch ( $transform ) {
247
  // Special-case to fill the $template with the email $content.
248
  case 'add-content':
249
+ $retval = str_replace( '{{{content}}}', wpautop( $this->get_content( 'replace-tokens' ) ), $retval );
250
  // Fall through.
251
 
252
  case 'replace-tokens':
bp-core/classes/class-bp-embed.php CHANGED
@@ -45,11 +45,6 @@ class BP_Embed extends WP_Embed {
45
  add_filter( 'bp_get_activity_content', array( &$this, 'run_shortcode' ), 7 );
46
  }
47
 
48
- if ( bp_use_embed_in_forum_posts() ) {
49
- add_filter( 'bp_get_the_topic_post_content', array( &$this, 'autoembed' ), 8 );
50
- add_filter( 'bp_get_the_topic_post_content', array( &$this, 'run_shortcode' ), 7 );
51
- }
52
-
53
  if ( bp_use_embed_in_private_messages() ) {
54
  add_filter( 'bp_get_the_thread_message_content', array( &$this, 'autoembed' ), 8 );
55
  add_filter( 'bp_get_the_thread_message_content', array( &$this, 'run_shortcode' ), 7 );
45
  add_filter( 'bp_get_activity_content', array( &$this, 'run_shortcode' ), 7 );
46
  }
47
 
 
 
 
 
 
48
  if ( bp_use_embed_in_private_messages() ) {
49
  add_filter( 'bp_get_the_thread_message_content', array( &$this, 'autoembed' ), 8 );
50
  add_filter( 'bp_get_the_thread_message_content', array( &$this, 'run_shortcode' ), 7 );
bp-core/classes/class-bp-media-extractor.php CHANGED
@@ -469,7 +469,7 @@ class BP_Media_Extractor {
469
  if ( ! empty( $matches[2] ) ) {
470
  foreach ( $matches[2] as $i => $shortcode_name ) {
471
  $attrs = shortcode_parse_atts( $matches[3][ $i ] );
472
- $attrs = ( ! $attrs ) ? array() : $attrs;
473
 
474
  $shortcode = array();
475
  $shortcode['attributes'] = $attrs; // Attributes.
469
  if ( ! empty( $matches[2] ) ) {
470
  foreach ( $matches[2] as $i => $shortcode_name ) {
471
  $attrs = shortcode_parse_atts( $matches[3][ $i ] );
472
+ $attrs = ( ! $attrs ) ? array() : (array) $attrs;
473
 
474
  $shortcode = array();
475
  $shortcode['attributes'] = $attrs; // Attributes.
bp-core/classes/class-bp-members-suggestions.php CHANGED
@@ -117,10 +117,11 @@ class BP_Members_Suggestions extends BP_Suggestions {
117
  $results = array();
118
 
119
  foreach ( $user_query->results as $user ) {
120
- $result = new stdClass();
121
- $result->ID = $user->user_nicename;
122
- $result->image = bp_core_fetch_avatar( array( 'html' => false, 'item_id' => $user->ID ) );
123
- $result->name = bp_core_get_user_displayname( $user->ID );
 
124
 
125
  $results[] = $result;
126
  }
117
  $results = array();
118
 
119
  foreach ( $user_query->results as $user ) {
120
+ $result = new stdClass();
121
+ $result->ID = $user->user_nicename;
122
+ $result->image = bp_core_fetch_avatar( array( 'html' => false, 'item_id' => $user->ID ) );
123
+ $result->name = bp_core_get_user_displayname( $user->ID );
124
+ $result->user_id = $user->ID;
125
 
126
  $results[] = $result;
127
  }
bp-core/classes/class-bp-phpmailer.php CHANGED
@@ -27,7 +27,18 @@ class BP_PHPMailer implements BP_Email_Delivery {
27
  public function bp_email( BP_Email $email ) {
28
  static $phpmailer = null;
29
 
30
- if ( $phpmailer === null ) {
 
 
 
 
 
 
 
 
 
 
 
31
  if ( ! class_exists( 'PHPMailer' ) ) {
32
  require_once ABSPATH . WPINC . '/class-phpmailer.php';
33
  require_once ABSPATH . WPINC . '/class-smtp.php';
@@ -40,7 +51,7 @@ class BP_PHPMailer implements BP_Email_Delivery {
40
  /*
41
  * Resets.
42
  */
43
-
44
  $phpmailer->clearAllRecipients();
45
  $phpmailer->clearAttachments();
46
  $phpmailer->clearCustomHeaders();
27
  public function bp_email( BP_Email $email ) {
28
  static $phpmailer = null;
29
 
30
+ /**
31
+ * Filter PHPMailer object to use.
32
+ *
33
+ * Specify an alternative version of PHPMailer to use instead of WordPress' default.
34
+ *
35
+ * @since 2.8.0
36
+ *
37
+ * @param null|PHPMailer $phpmailer The phpmailer class.
38
+ */
39
+ $phpmailer = apply_filters( 'bp_phpmailer_object', $phpmailer );
40
+
41
+ if ( ! ( $phpmailer instanceof PHPMailer ) ) {
42
  if ( ! class_exists( 'PHPMailer' ) ) {
43
  require_once ABSPATH . WPINC . '/class-phpmailer.php';
44
  require_once ABSPATH . WPINC . '/class-smtp.php';
51
  /*
52
  * Resets.
53
  */
54
+ $phpmailer->MessageDate = date( 'D, j M Y H:i:s O' );
55
  $phpmailer->clearAllRecipients();
56
  $phpmailer->clearAttachments();
57
  $phpmailer->clearCustomHeaders();
bp-core/classes/class-bp-theme-compat.php CHANGED
@@ -50,7 +50,7 @@ class BP_Theme_Compat {
50
  *
51
  * @param array $properties Array of properties for BP_Theme_Compat.
52
  */
53
- public function __construct( Array $properties = array() ) {
54
  $this->_data = $properties;
55
  }
56
 
50
  *
51
  * @param array $properties Array of properties for BP_Theme_Compat.
52
  */
53
+ public function __construct( Array $properties = array() ) {
54
  $this->_data = $properties;
55
  }
56
 
bp-core/classes/class-bp-user-query.php CHANGED
@@ -247,7 +247,7 @@ class BP_User_Query {
247
  // Setup the main SQL query container.
248
  $sql = array(
249
  'select' => '',
250
- 'where' => array(),
251
  'orderby' => '',
252
  'order' => '',
253
  'limit' => ''
@@ -364,7 +364,11 @@ class BP_User_Query {
364
  // 'include' - User ids to include in the results.
365
  $include = false !== $include ? wp_parse_id_list( $include ) : array();
366
  $include_ids = $this->get_include_ids( $include );
367
- if ( ! empty( $include_ids ) ) {
 
 
 
 
368
  $include_ids = implode( ',', wp_parse_id_list( $include_ids ) );
369
  $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids})";
370
  }
@@ -409,13 +413,16 @@ class BP_User_Query {
409
  $search_terms_space = '%' . $search_terms . '%';
410
  }
411
 
412
- $sql['where']['search'] = $wpdb->prepare(
413
- "u.{$this->uid_name} IN ( SELECT ID FROM {$wpdb->users} WHERE ( user_login LIKE %s OR user_login LIKE %s OR user_nicename LIKE %s OR user_nicename LIKE %s ) )",
414
  $search_terms_nospace,
415
  $search_terms_space,
416
  $search_terms_nospace,
417
  $search_terms_space
418
- );
 
 
 
419
  }
420
 
421
  // Only use $member_type__in if $member_type is not set.
@@ -566,14 +573,6 @@ class BP_User_Query {
566
 
567
  ), $this ) );
568
 
569
- // WP_User_Query doesn't cache the data it pulls from wp_users,
570
- // and it does not give us a way to save queries by fetching
571
- // only uncached users. However, BP does cache this data, so
572
- // we set it here.
573
- foreach ( $wp_user_query->results as $u ) {
574
- wp_cache_set( 'bp_core_userdata_' . $u->ID, $u, 'bp' );
575
- }
576
-
577
  // We calculate total_users using a standalone query, except
578
  // when a whitelist of user_ids is passed to the constructor.
579
  // This clause covers the latter situation, and ensures that
@@ -591,11 +590,14 @@ class BP_User_Query {
591
  // Match up to the user ids from the main query.
592
  foreach ( $this->user_ids as $key => $uid ) {
593
  if ( isset( $r[ $uid ] ) ) {
 
 
 
594
  $this->results[ $uid ] = $r[ $uid ];
595
 
596
  // The BP template functions expect an 'id'
597
  // (as opposed to 'ID') property.
598
- $this->results[ $uid ]->id = $uid;
599
 
600
  // Remove user ID from original user_ids property.
601
  } else {
@@ -780,7 +782,7 @@ class BP_User_Query {
780
 
781
  $tax_query = new WP_Tax_Query( array(
782
  array(
783
- 'taxonomy' => 'bp_member_type',
784
  'field' => 'name',
785
  'operator' => $operator,
786
  'terms' => $types,
@@ -788,18 +790,15 @@ class BP_User_Query {
788
  ) );
789
 
790
  // Switch to the root blog, where member type taxonomies live.
 
791
  $switched = false;
792
- if ( ! bp_is_root_blog() ) {
793
- switch_to_blog( bp_get_root_blog_id() );
794
  $switched = true;
795
  }
796
 
797
  $sql_clauses = $tax_query->get_sql( 'u', $this->uid_name );
798
 
799
- if ( $switched ) {
800
- restore_current_blog();
801
- }
802
-
803
  $clause = '';
804
 
805
  // The no_results clauses are the same between IN and NOT IN.
@@ -815,6 +814,10 @@ class BP_User_Query {
815
  $clause = "u.{$this->uid_name} IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )";
816
  }
817
 
 
 
 
 
818
  return $clause;
819
  }
820
  }
247
  // Setup the main SQL query container.
248
  $sql = array(
249
  'select' => '',
250
+ 'where' => array('1=1'),
251
  'orderby' => '',
252
  'order' => '',
253
  'limit' => ''
364
  // 'include' - User ids to include in the results.
365
  $include = false !== $include ? wp_parse_id_list( $include ) : array();
366
  $include_ids = $this->get_include_ids( $include );
367
+
368
+ // An array containing nothing but 0 should always fail.
369
+ if ( 1 === count( $include_ids ) && 0 == reset( $include_ids ) ) {
370
+ $sql['where'][] = $this->no_results['where'];
371
+ } elseif ( ! empty( $include_ids ) ) {
372
  $include_ids = implode( ',', wp_parse_id_list( $include_ids ) );
373
  $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids})";
374
  }
413
  $search_terms_space = '%' . $search_terms . '%';
414
  }
415
 
416
+ $matched_user_ids = $wpdb->get_col( $wpdb->prepare(
417
+ "SELECT ID FROM {$wpdb->users} WHERE ( user_login LIKE %s OR user_login LIKE %s OR user_nicename LIKE %s OR user_nicename LIKE %s )",
418
  $search_terms_nospace,
419
  $search_terms_space,
420
  $search_terms_nospace,
421
  $search_terms_space
422
+ ) );
423
+
424
+ $match_in_clause = empty( $matched_user_ids) ? 'NULL' : implode( ',', $matched_user_ids );
425
+ $sql['where']['search'] = "u.{$this->uid_name} IN ({$match_in_clause})";
426
  }
427
 
428
  // Only use $member_type__in if $member_type is not set.
573
 
574
  ), $this ) );
575
 
 
 
 
 
 
 
 
 
576
  // We calculate total_users using a standalone query, except
577
  // when a whitelist of user_ids is passed to the constructor.
578
  // This clause covers the latter situation, and ensures that
590
  // Match up to the user ids from the main query.
591
  foreach ( $this->user_ids as $key => $uid ) {
592
  if ( isset( $r[ $uid ] ) ) {
593
+ $r[ $uid ]->ID = (int) $uid;
594
+ $r[ $uid ]->user_status = (int) $r[ $uid ]->user_status;
595
+
596
  $this->results[ $uid ] = $r[ $uid ];
597
 
598
  // The BP template functions expect an 'id'
599
  // (as opposed to 'ID') property.
600
+ $this->results[ $uid ]->id = (int) $uid;
601
 
602
  // Remove user ID from original user_ids property.
603
  } else {
782
 
783
  $tax_query = new WP_Tax_Query( array(
784
  array(
785
+ 'taxonomy' => bp_get_member_type_tax_name(),
786
  'field' => 'name',
787
  'operator' => $operator,
788
  'terms' => $types,
790
  ) );
791
 
792
  // Switch to the root blog, where member type taxonomies live.
793
+ $site_id = bp_get_taxonomy_term_site_id( bp_get_member_type_tax_name() );
794
  $switched = false;
795
+ if ( $site_id !== get_current_blog_id() ) {
796
+ switch_to_blog( $site_id );
797
  $switched = true;
798
  }
799
 
800
  $sql_clauses = $tax_query->get_sql( 'u', $this->uid_name );
801
 
 
 
 
 
802
  $clause = '';
803
 
804
  // The no_results clauses are the same between IN and NOT IN.
814
  $clause = "u.{$this->uid_name} IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )";
815
  }
816
 
817
+ if ( $switched ) {
818
+ restore_current_blog();
819
+ }
820
+
821
  return $clause;
822
  }
823
  }
bp-core/classes/class-bp-walker-nav-menu.php CHANGED
@@ -55,9 +55,7 @@ class BP_Walker_Nav_Menu extends Walker_Nav_Menu {
55
  * @return string See {@link Walker::walk()}.
56
  */
57
  public function walk( $elements, $max_depth ) {
58
- $func_args = func_get_args();
59
-
60
- $args = array_slice( $func_args, 2 );
61
  $output = '';
62
 
63
  if ( $max_depth < -1 ) // Invalid parameter.
55
  * @return string See {@link Walker::walk()}.
56
  */
57
  public function walk( $elements, $max_depth ) {
58
+ $args = array_slice( func_get_args(), 2 );
 
 
59
  $output = '';
60
 
61
  if ( $max_depth < -1 ) // Invalid parameter.
bp-core/css/admin-bar-rtl.css CHANGED
@@ -16,6 +16,7 @@
16
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul {
17
  right: 0;
18
  }
 
19
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul {
20
  right: 0;
21
  }
@@ -24,13 +25,13 @@
24
  #wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,
25
  #wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count,
26
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
27
- background: #21759B;
28
  color: #fff;
29
  text-shadow: none;
30
  display: inline;
31
  padding: 2px 5px;
32
  font-size: 10px;
33
- font-weight: bold;
34
  -moz-border-radius: 10px;
35
  -khtml-border-radius: 10px;
36
  -webkit-border-radius: 10px;
@@ -40,19 +41,33 @@
40
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
41
  background: #ddd;
42
  color: #333;
43
- margin: 0
44
  }
45
 
46
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert {
47
- background-color: #1fb3dd;
48
  color: #fff;
49
  }
50
 
51
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications > a {
52
- padding: 0 .5em;
53
  }
54
 
55
  #wp-admin-bar-user-info img.avatar {
56
  height: 64px;
57
  width: 64px;
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul {
17
  right: 0;
18
  }
19
+
20
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul {
21
  right: 0;
22
  }
25
  #wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,
26
  #wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count,
27
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
28
+ background: #21759b;
29
  color: #fff;
30
  text-shadow: none;
31
  display: inline;
32
  padding: 2px 5px;
33
  font-size: 10px;
34
+ font-weight: 700;
35
  -moz-border-radius: 10px;
36
  -khtml-border-radius: 10px;
37
  -webkit-border-radius: 10px;
41
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
42
  background: #ddd;
43
  color: #333;
44
+ margin: 0;
45
  }
46
 
47
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert {
48
+ background-color: #21759b;
49
  color: #fff;
50
  }
51
 
52
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications > a {
53
+ padding: 0 0.5em;
54
  }
55
 
56
  #wp-admin-bar-user-info img.avatar {
57
  height: 64px;
58
  width: 64px;
59
  }
60
+
61
+ /* Remove additional arrows from appearing on the BuddyPress' `my_account_menu`
62
+ * on large screens. Add back arrows for screen widths 600px and lower.
63
+ */
64
+ #wpadminbar .wp-admin-bar-arrow-right {
65
+ display: none;
66
+ }
67
+
68
+ @media screen and (max-width: 600px) {
69
+
70
+ #wpadminbar .wp-admin-bar-arrow-right {
71
+ display: block;
72
+ }
73
+ }
bp-core/css/admin-bar-rtl.min.css CHANGED
@@ -1 +1 @@
1
- #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar>a img,#wpadminbar .quicklinks li#wp-admin-bar-user-admin-with-avatar>a img{width:16px;height:16px;display:inline;border:1px solid #999;vertical-align:middle;margin:-2px -5px 0 10px;padding:0;background:#eee;float:none}#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul,#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul{right:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications,#wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,#wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count{background:#21759B;color:#fff;text-shadow:none;display:inline;padding:2px 5px;font-size:10px;font-weight:700;-moz-border-radius:10px;-khtml-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications{background:#ddd;color:#333;margin:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert{background-color:#1fb3dd;color:#fff}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications>a{padding:0 .5em}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}
1
+ #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar>a img,#wpadminbar .quicklinks li#wp-admin-bar-user-admin-with-avatar>a img{width:16px;height:16px;display:inline;border:1px solid #999;vertical-align:middle;margin:-2px -5px 0 10px;padding:0;background:#eee;float:none}#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul{right:0}#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul{right:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications,#wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,#wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count{background:#21759b;color:#fff;text-shadow:none;display:inline;padding:2px 5px;font-size:10px;font-weight:700;-moz-border-radius:10px;-khtml-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications{background:#ddd;color:#333;margin:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert{background-color:#21759b;color:#fff}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications>a{padding:0 .5em}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}#wpadminbar .wp-admin-bar-arrow-right{display:none}@media screen and (max-width:600px){#wpadminbar .wp-admin-bar-arrow-right{display:block}}
bp-core/css/admin-bar.css CHANGED
@@ -16,6 +16,7 @@
16
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul {
17
  left: 0;
18
  }
 
19
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul {
20
  left: 0;
21
  }
@@ -24,13 +25,13 @@
24
  #wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,
25
  #wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count,
26
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
27
- background: #21759B;
28
  color: #fff;
29
  text-shadow: none;
30
  display: inline;
31
  padding: 2px 5px;
32
  font-size: 10px;
33
- font-weight: bold;
34
  -moz-border-radius: 10px;
35
  -khtml-border-radius: 10px;
36
  -webkit-border-radius: 10px;
@@ -40,19 +41,33 @@
40
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
41
  background: #ddd;
42
  color: #333;
43
- margin: 0
44
  }
45
 
46
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert {
47
- background-color: #1fb3dd;
48
  color: #fff;
49
  }
50
 
51
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications > a {
52
- padding: 0 .5em;
53
  }
54
 
55
  #wp-admin-bar-user-info img.avatar {
56
  height: 64px;
57
  width: 64px;
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul {
17
  left: 0;
18
  }
19
+
20
  #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul {
21
  left: 0;
22
  }
25
  #wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,
26
  #wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count,
27
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
28
+ background: #21759b;
29
  color: #fff;
30
  text-shadow: none;
31
  display: inline;
32
  padding: 2px 5px;
33
  font-size: 10px;
34
+ font-weight: 700;
35
  -moz-border-radius: 10px;
36
  -khtml-border-radius: 10px;
37
  -webkit-border-radius: 10px;
41
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications {
42
  background: #ddd;
43
  color: #333;
44
+ margin: 0;
45
  }
46
 
47
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert {
48
+ background-color: #21759b;
49
  color: #fff;
50
  }
51
 
52
  #wpadminbar .quicklinks li#wp-admin-bar-bp-notifications > a {
53
+ padding: 0 0.5em;
54
  }
55
 
56
  #wp-admin-bar-user-info img.avatar {
57
  height: 64px;
58
  width: 64px;
59
  }
60
+
61
+ /* Remove additional arrows from appearing on the BuddyPress' `my_account_menu`
62
+ * on large screens. Add back arrows for screen widths 600px and lower.
63
+ */
64
+ #wpadminbar .wp-admin-bar-arrow-right {
65
+ display: none;
66
+ }
67
+
68
+ @media screen and (max-width: 600px) {
69
+
70
+ #wpadminbar .wp-admin-bar-arrow-right {
71
+ display: block;
72
+ }
73
+ }
bp-core/css/admin-bar.min.css CHANGED
@@ -1 +1 @@
1
- #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar>a img,#wpadminbar .quicklinks li#wp-admin-bar-user-admin-with-avatar>a img{width:16px;height:16px;display:inline;border:1px solid #999;vertical-align:middle;margin:-2px 10px 0 -5px;padding:0;background:#eee;float:none}#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul,#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul{left:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications,#wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,#wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count{background:#21759B;color:#fff;text-shadow:none;display:inline;padding:2px 5px;font-size:10px;font-weight:700;-moz-border-radius:10px;-khtml-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications{background:#ddd;color:#333;margin:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert{background-color:#1fb3dd;color:#fff}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications>a{padding:0 .5em}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}
1
+ #wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar>a img,#wpadminbar .quicklinks li#wp-admin-bar-user-admin-with-avatar>a img{width:16px;height:16px;display:inline;border:1px solid #999;vertical-align:middle;margin:-2px 10px 0 -5px;padding:0;background:#eee;float:none}#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul{left:0}#wpadminbar .quicklinks li#wp-admin-bar-group-admin-with-avatar ul ul{left:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications,#wpadminbar .quicklinks li#wp-admin-bar-my-account a span.count,#wpadminbar .quicklinks li#wp-admin-bar-my-account-with-avatar a span.count{background:#21759b;color:#fff;text-shadow:none;display:inline;padding:2px 5px;font-size:10px;font-weight:700;-moz-border-radius:10px;-khtml-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications{background:#ddd;color:#333;margin:0}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications #ab-pending-notifications.alert{background-color:#21759b;color:#fff}#wpadminbar .quicklinks li#wp-admin-bar-bp-notifications>a{padding:0 .5em}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}#wpadminbar .wp-admin-bar-arrow-right{display:none}@media screen and (max-width:600px){#wpadminbar .wp-admin-bar-arrow-right{display:block}}
bp-core/css/avatar-rtl.css CHANGED
@@ -30,7 +30,7 @@ div.bp-cover-image-status .bp-progress {
30
  border: 1px solid #d1d1d1;
31
  float: left;
32
  height: 22px;
33
- line-height: 2em;
34
  margin: 6px 0 0 10px;
35
  margin-bottom: 2px;
36
  padding: 0;
@@ -55,6 +55,7 @@ div.bp-cover-image-status .bp-bar {
55
  padding: 10px 15px;
56
  }
57
 
 
58
  #buddypress p.warning,
59
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,
60
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
@@ -66,11 +67,12 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
66
  margin: 1em 0;
67
  padding: 10px 15px;
68
  }
 
69
 
70
  div.bp-avatar-nav {
71
  background: transparent;
72
  clear: both;
73
- margin: 10px 0 10px;
74
  overflow: hidden;
75
  }
76
 
@@ -117,7 +119,7 @@ div.bp-avatar-nav {
117
  .bp-avatar-nav li.current a {
118
  background: none;
119
  color: inherit;
120
- font-weight: bold;
121
  opacity: 0.8;
122
  outline: 0;
123
  }
@@ -145,6 +147,10 @@ div.bp-avatar-nav {
145
  text-align: inherit;
146
  }
147
 
 
 
 
 
148
  .drag-drop #drag-drop-area {
149
  box-sizing: border-box;
150
  display: table;
@@ -165,7 +171,7 @@ div.bp-avatar-nav {
165
  }
166
 
167
  .drag-drop .drag-drop-inside p {
168
- color: #aaa;
169
  font-size: 110%;
170
  margin: 5px 0;
171
  text-align: center;
@@ -175,14 +181,8 @@ div.bp-avatar-nav {
175
  margin-top: 0;
176
  }
177
 
178
- @supports (-ms-accelerator:true) {
179
- .drag-drop-inside p.drag-drop-info {
180
- display: block;
181
- }
182
- }
183
-
184
  #avatar-to-crop {
185
- margin: 0 auto 20px ;
186
  text-align: right;
187
  }
188
 
@@ -222,6 +222,7 @@ div.bp-avatar-nav {
222
  }
223
 
224
  @media screen and (min-width: 801px) {
 
225
  #bp-webcam-avatar #avatar-to-crop {
226
  max-width: 64%;
227
  width: 64%;
@@ -234,7 +235,7 @@ div.bp-avatar-nav {
234
 
235
  #bp-webcam-avatar #avatar-crop-actions {
236
  float: right;
237
- margin: 0 0 20px 0;
238
  width: 50%;
239
  }
240
 
@@ -299,7 +300,7 @@ div.bp-avatar-nav {
299
  }
300
 
301
  .bp-avatar .item {
302
- overflow:hidden;
303
  }
304
 
305
  .bp-avatar .avatar-crop-management.adjust {
@@ -324,7 +325,7 @@ div.bp-avatar-nav {
324
  margin: 0 auto 10px;
325
  }
326
 
327
- #bp-webcam-avatar .avatar-crop-management #avatar-crop-actions {
328
  width: auto;
329
  }
330
 
@@ -349,7 +350,9 @@ div.bp-avatar-nav {
349
 
350
  }
351
 
 
352
  /** Admin Profile **/
 
353
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent,
354
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent {
355
  height: 95% !important;
@@ -368,9 +371,11 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
368
  float: right;
369
  margin: 0;
370
  }
 
371
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
372
  margin-bottom: 20px;
373
  }
 
374
  @media screen and (min-width: 783px) {
375
 
376
  .wp-admin #TB_window .bp-avatar .avatar-crop-management {
@@ -385,8 +390,8 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
385
  }
386
 
387
  .wp-admin #TB_window .bp-avatar #avatar-to-crop video {
388
- width: 100%;
389
- }
390
 
391
  .wp-admin #TB_window .bp-avatar .avatar-crop-management a.button {
392
  height: auto;
@@ -394,6 +399,7 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
394
  }
395
 
396
  @media screen and (min-width: 810px) {
 
397
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
398
  max-width: none;
399
  width: 76%;
@@ -404,3 +410,4 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
404
  width: auto;
405
  }
406
  }
 
30
  border: 1px solid #d1d1d1;
31
  float: left;
32
  height: 22px;
33
+ line-height: 2;
34
  margin: 6px 0 0 10px;
35
  margin-bottom: 2px;
36
  padding: 0;
55
  padding: 10px 15px;
56
  }
57
 
58
+ /* stylelint-disable selector-id-pattern */
59
  #buddypress p.warning,
60
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,
61
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
67
  margin: 1em 0;
68
  padding: 10px 15px;
69
  }
70
+ /* stylelint-enable */
71
 
72
  div.bp-avatar-nav {
73
  background: transparent;
74
  clear: both;
75
+ margin: 10px 0;
76
  overflow: hidden;
77
  }
78
 
119
  .bp-avatar-nav li.current a {
120
  background: none;
121
  color: inherit;
122
+ font-weight: 700;
123
  opacity: 0.8;
124
  outline: 0;
125
  }
147
  text-align: inherit;
148
  }
149
 
150
+ .moxie-shim.moxie-shim-html5 input {
151
+ cursor: pointer;
152
+ }
153
+
154
  .drag-drop #drag-drop-area {
155
  box-sizing: border-box;
156
  display: table;
171
  }
172
 
173
  .drag-drop .drag-drop-inside p {
174
+ color: #767676;
175
  font-size: 110%;
176
  margin: 5px 0;
177
  text-align: center;
181
  margin-top: 0;
182
  }
183
 
 
 
 
 
 
 
184
  #avatar-to-crop {
185
+ margin: 0 auto 20px;
186
  text-align: right;
187
  }
188
 
222
  }
223
 
224
  @media screen and (min-width: 801px) {
225
+
226
  #bp-webcam-avatar #avatar-to-crop {
227
  max-width: 64%;
228
  width: 64%;
235
 
236
  #bp-webcam-avatar #avatar-crop-actions {
237
  float: right;
238
+ margin: 0 0 20px;
239
  width: 50%;
240
  }
241
 
300
  }
301
 
302
  .bp-avatar .item {
303
+ overflow: hidden;
304
  }
305
 
306
  .bp-avatar .avatar-crop-management.adjust {
325
  margin: 0 auto 10px;
326
  }
327
 
328
+ #bp-webcam-avatar .avatar-crop-management #avatar-crop-actions {
329
  width: auto;
330
  }
331
 
350
 
351
  }
352
 
353
+
354
  /** Admin Profile **/
355
+ /* stylelint-disable selector-id-pattern */
356
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent,
357
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent {
358
  height: 95% !important;
371
  float: right;
372
  margin: 0;
373
  }
374
+
375
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
376
  margin-bottom: 20px;
377
  }
378
+
379
  @media screen and (min-width: 783px) {
380
 
381
  .wp-admin #TB_window .bp-avatar .avatar-crop-management {
390
  }
391
 
392
  .wp-admin #TB_window .bp-avatar #avatar-to-crop video {
393
+ width: 100%;
394
+ }
395
 
396
  .wp-admin #TB_window .bp-avatar .avatar-crop-management a.button {
397
  height: auto;
399
  }
400
 
401
  @media screen and (min-width: 810px) {
402
+
403
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
404
  max-width: none;
405
  width: 76%;
410
  width: auto;
411
  }
412
  }
413
+ /* stylelint-enable */
bp-core/css/avatar-rtl.min.css CHANGED
@@ -1 +1 @@
1
- div.bp-avatar-status,div.bp-cover-image-status{clear:both;margin:1em 0}div.bp-avatar-status p.updated,div.bp-cover-image-status p.updated{display:block;padding:10px 15px}div.bp-avatar-status p.success,div.bp-cover-image-status p.success{background-color:#efc;border:1px solid #591;color:#250}div.bp-avatar-status p.error,div.bp-cover-image-status p.error{background-color:#fdc;border:1px solid #a00;color:#800}div.bp-avatar-status .bp-progress,div.bp-cover-image-status .bp-progress{background:0 0;border:1px solid #d1d1d1;float:left;height:22px;line-height:2em;margin:6px 0 2px 10px;padding:0;overflow:hidden;width:200px}div.bp-avatar-status .bp-bar,div.bp-cover-image-status .bp-bar{background-color:#c3ff88;width:0;height:100%;z-index:9}.bp-uploader-progress div.error{background-color:#fdc;border:1px solid #a00;color:#800;display:block;font-size:90%;padding:10px 15px}#buddypress p.warning,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{background-color:#ffd;border:1px solid #cb2;color:#440;display:block;font-size:90%;margin:1em 0;padding:10px 15px}div.bp-avatar-nav{background:0 0;clear:both;margin:10px 0;overflow:hidden}.avatar-nav-items{margin:0;padding:0}.bp-avatar-nav .avatar-nav-items li.avatar-nav-item{float:right!important;margin:0;list-style:none}.avatar-nav-items li a{display:block;padding:5px 10px;text-decoration:none}.bp-avatar-nav ul:after,.bp-avatar-nav ul:before{content:" ";display:table}.bp-avatar-nav ul:after{clear:both}.bp-avatar-nav ul{border-bottom:1px solid #ccc;margin-bottom:10px}.bp-avatar-nav ul.avatar-nav-items li.current{border:1px solid #ccc;border-bottom-color:#fff;border-top-right-radius:4px;border-top-left-radius:4px;margin-bottom:-1px}.bp-avatar-nav li.current a{background:0 0;color:inherit;font-weight:700;opacity:.8;outline:0}#drag-drop-area{border:4px dashed #bbb;height:200px}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}.drag-drop-inside p{display:none}.drag-drop-inside p.drag-drop-buttons{margin-top:80px;text-align:center}.drag-drop .drag-drop-inside p.drag-drop-buttons{margin:auto;text-align:inherit}.drag-drop #drag-drop-area{box-sizing:border-box;display:table;height:100%;width:100%}.drag-drop .drag-drop-inside{display:table-cell;padding:40px 0;text-align:center;vertical-align:middle}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop .drag-drop-inside p{color:#aaa;font-size:110%;margin:5px 0;text-align:center}.drag-drop-inside p.drag-drop-info{margin-top:0}@supports (-ms-accelerator:true){.drag-drop-inside p.drag-drop-info{display:block}}#avatar-to-crop{margin:0 auto 20px;text-align:right}#bp-webcam-avatar #avatar-to-crop{float:right;margin:0 0 20px}#avatar-to-crop .jcrop-holder{margin:0 auto}.avatar-crop-management{clear:right;overflow:hidden;padding-top:20px;text-align:center}#bp-webcam-avatar .avatar-crop-management{clear:none;float:none;overflow:visible;padding-top:0;width:auto}#avatar-crop-pane{margin:0 auto;overflow:hidden}#bp-webcam-avatar #avatar-to-crop{border:1px solid #eee;max-width:100%;width:100%}@media screen and (min-width:801px){#bp-webcam-avatar #avatar-to-crop{max-width:64%;width:64%}}#avatar-crop-actions a{display:block}#bp-webcam-avatar #avatar-crop-actions{float:right;margin:0 0 20px;width:50%}#avatar-crop-actions a.button{margin-top:10px}#bp-webcam-avatar #avatar-crop-actions a.button{display:block;margin:0 0 5px;padding:4px 0;width:100%}#avatar-crop-pane canvas,#avatar-crop-pane img,#avatar-to-crop img,#avatar-upload-form img,#create-group-form img,#group-settings-form img{border:none!important;max-width:none!important}#bp-webcam-avatar video{float:right;margin-bottom:0;max-width:100%;width:100%;-webkit-transform:scaleX(-1);transform:scaleX(-1)}#bp-webcam-avatar #avatar-crop-pane{border:2px dashed #bbb;clear:right;float:left;margin:0 0 10px 40px;overflow:hidden}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{max-width:150px;max-height:150px}#avatar-crop-pane canvas{height:auto;width:100%;max-width:100%}.group-avatar .bp-avatar .avatar-crop-management{margin-right:0;padding-top:0;width:auto}.bp-avatar .item{overflow:hidden}.bp-avatar .avatar-crop-management.adjust{float:right;clear:none;padding-top:0}.bp-avatar #avatar-to-crop.adjust{float:right;margin-left:20px}@media screen and (max-width:480px){#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions,#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{width:auto}}@media screen and (min-width:801px){#bp-webcam-avatar .avatar-crop-management{clear:none;float:left}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none;margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{float:right;width:100%}}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent{height:95%!important;width:95%!important}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{display:block;padding:10px 15px}.wp-admin #TB_window .bp-avatar #avatar-to-crop{float:right;margin:0}.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{margin-bottom:20px}@media screen and (min-width:783px){.wp-admin #TB_window .bp-avatar .avatar-crop-management{clear:none;float:right;margin-right:20px;padding-top:0;text-align:center}}.wp-admin #TB_window .bp-avatar #avatar-to-crop video{width:100%}.wp-admin #TB_window .bp-avatar .avatar-crop-management a.button{height:auto;line-height:inherit}@media screen and (min-width:810px){.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{max-width:none;width:76%}.wp-admin #TB_window #bp-webcam-avatar .avatar-crop-management{max-width:none;width:auto}}
1
+ div.bp-avatar-status,div.bp-cover-image-status{clear:both;margin:1em 0}div.bp-avatar-status p.updated,div.bp-cover-image-status p.updated{display:block;padding:10px 15px}div.bp-avatar-status p.success,div.bp-cover-image-status p.success{background-color:#efc;border:1px solid #591;color:#250}div.bp-avatar-status p.error,div.bp-cover-image-status p.error{background-color:#fdc;border:1px solid #a00;color:#800}div.bp-avatar-status .bp-progress,div.bp-cover-image-status .bp-progress{background:0 0;border:1px solid #d1d1d1;float:left;height:22px;line-height:2;margin:6px 0 0 10px;margin-bottom:2px;padding:0;overflow:hidden;width:200px}div.bp-avatar-status .bp-bar,div.bp-cover-image-status .bp-bar{background-color:#c3ff88;width:0;height:100%;z-index:9}.bp-uploader-progress div.error{background-color:#fdc;border:1px solid #a00;color:#800;display:block;font-size:90%;padding:10px 15px}#buddypress p.warning,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{background-color:#ffd;border:1px solid #cb2;color:#440;display:block;font-size:90%;margin:1em 0;padding:10px 15px}div.bp-avatar-nav{background:0 0;clear:both;margin:10px 0;overflow:hidden}.avatar-nav-items{margin:0;padding:0}.bp-avatar-nav .avatar-nav-items li.avatar-nav-item{float:right!important;margin:0;list-style:none}.avatar-nav-items li a{display:block;padding:5px 10px;text-decoration:none}.bp-avatar-nav ul:after,.bp-avatar-nav ul:before{content:" ";display:table}.bp-avatar-nav ul:after{clear:both}.bp-avatar-nav ul{border-bottom:1px solid #ccc;margin-bottom:10px}.bp-avatar-nav ul.avatar-nav-items li.current{border:1px solid #ccc;border-bottom-color:#fff;border-top-right-radius:4px;border-top-left-radius:4px;margin-bottom:-1px}.bp-avatar-nav li.current a{background:0 0;color:inherit;font-weight:700;opacity:.8;outline:0}#drag-drop-area{border:4px dashed #bbb;height:200px}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}.drag-drop-inside p{display:none}.drag-drop-inside p.drag-drop-buttons{margin-top:80px;text-align:center}.drag-drop .drag-drop-inside p.drag-drop-buttons{margin:auto;text-align:inherit}.moxie-shim.moxie-shim-html5 input{cursor:pointer}.drag-drop #drag-drop-area{box-sizing:border-box;display:table;height:100%;width:100%}.drag-drop .drag-drop-inside{display:table-cell;padding:40px 0;text-align:center;vertical-align:middle}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop .drag-drop-inside p{color:#767676;font-size:110%;margin:5px 0;text-align:center}.drag-drop-inside p.drag-drop-info{margin-top:0}#avatar-to-crop{margin:0 auto 20px;text-align:right}#bp-webcam-avatar #avatar-to-crop{float:right;margin:0 0 20px}#avatar-to-crop .jcrop-holder{margin:0 auto}.avatar-crop-management{clear:right;overflow:hidden;padding-top:20px;text-align:center}#bp-webcam-avatar .avatar-crop-management{clear:none;float:none;overflow:visible;padding-top:0;width:auto}#avatar-crop-pane{margin:0 auto;overflow:hidden}#bp-webcam-avatar #avatar-to-crop{border:1px solid #eee;max-width:100%;width:100%}@media screen and (min-width:801px){#bp-webcam-avatar #avatar-to-crop{max-width:64%;width:64%}}#avatar-crop-actions a{display:block}#bp-webcam-avatar #avatar-crop-actions{float:right;margin:0 0 20px;width:50%}#avatar-crop-actions a.button{margin-top:10px}#bp-webcam-avatar #avatar-crop-actions a.button{display:block;margin:0 0 5px;padding:4px 0;width:100%}#avatar-crop-pane canvas,#avatar-crop-pane img,#avatar-to-crop img,#avatar-upload-form img,#create-group-form img,#group-settings-form img{border:none!important;max-width:none!important}#bp-webcam-avatar video{float:right;margin-bottom:0;max-width:100%;width:100%;-webkit-transform:scaleX(-1);transform:scaleX(-1)}#bp-webcam-avatar #avatar-crop-pane{border:2px dashed #bbb;clear:right;float:left;margin:0 0 10px 40px;overflow:hidden}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{max-width:150px;max-height:150px}#avatar-crop-pane canvas{height:auto;width:100%;max-width:100%}.group-avatar .bp-avatar .avatar-crop-management{margin-right:0;padding-top:0;width:auto}.bp-avatar .item{overflow:hidden}.bp-avatar .avatar-crop-management.adjust{float:right;clear:none;padding-top:0}.bp-avatar #avatar-to-crop.adjust{float:right;margin-left:20px}@media screen and (max-width:480px){#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions,#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{width:auto}}@media screen and (min-width:801px){#bp-webcam-avatar .avatar-crop-management{clear:none;float:left}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none;margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{float:right;width:100%}}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent{height:95%!important;width:95%!important}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{display:block;padding:10px 15px}.wp-admin #TB_window .bp-avatar #avatar-to-crop{float:right;margin:0}.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{margin-bottom:20px}@media screen and (min-width:783px){.wp-admin #TB_window .bp-avatar .avatar-crop-management{clear:none;float:right;margin-right:20px;padding-top:0;text-align:center}}.wp-admin #TB_window .bp-avatar #avatar-to-crop video{width:100%}.wp-admin #TB_window .bp-avatar .avatar-crop-management a.button{height:auto;line-height:inherit}@media screen and (min-width:810px){.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{max-width:none;width:76%}.wp-admin #TB_window #bp-webcam-avatar .avatar-crop-management{max-width:none;width:auto}}
bp-core/css/avatar.css CHANGED
@@ -30,7 +30,7 @@ div.bp-cover-image-status .bp-progress {
30
  border: 1px solid #d1d1d1;
31
  float: right;
32
  height: 22px;
33
- line-height: 2em;
34
  margin: 6px 10px 0 0;
35
  margin-bottom: 2px;
36
  padding: 0;
@@ -55,6 +55,7 @@ div.bp-cover-image-status .bp-bar {
55
  padding: 10px 15px;
56
  }
57
 
 
58
  #buddypress p.warning,
59
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,
60
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
@@ -66,11 +67,12 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
66
  margin: 1em 0;
67
  padding: 10px 15px;
68
  }
 
69
 
70
  div.bp-avatar-nav {
71
  background: transparent;
72
  clear: both;
73
- margin: 10px 0 10px;
74
  overflow: hidden;
75
  }
76
 
@@ -117,7 +119,7 @@ div.bp-avatar-nav {
117
  .bp-avatar-nav li.current a {
118
  background: none;
119
  color: inherit;
120
- font-weight: bold;
121
  opacity: 0.8;
122
  outline: 0;
123
  }
@@ -145,6 +147,10 @@ div.bp-avatar-nav {
145
  text-align: inherit;
146
  }
147
 
 
 
 
 
148
  .drag-drop #drag-drop-area {
149
  box-sizing: border-box;
150
  display: table;
@@ -165,7 +171,7 @@ div.bp-avatar-nav {
165
  }
166
 
167
  .drag-drop .drag-drop-inside p {
168
- color: #aaa;
169
  font-size: 110%;
170
  margin: 5px 0;
171
  text-align: center;
@@ -175,14 +181,8 @@ div.bp-avatar-nav {
175
  margin-top: 0;
176
  }
177
 
178
- @supports (-ms-accelerator:true) {
179
- .drag-drop-inside p.drag-drop-info {
180
- display: block;
181
- }
182
- }
183
-
184
  #avatar-to-crop {
185
- margin: 0 auto 20px ;
186
  text-align: left;
187
  }
188
 
@@ -222,6 +222,7 @@ div.bp-avatar-nav {
222
  }
223
 
224
  @media screen and (min-width: 801px) {
 
225
  #bp-webcam-avatar #avatar-to-crop {
226
  max-width: 64%;
227
  width: 64%;
@@ -234,7 +235,7 @@ div.bp-avatar-nav {
234
 
235
  #bp-webcam-avatar #avatar-crop-actions {
236
  float: left;
237
- margin: 0 0 20px 0;
238
  width: 50%;
239
  }
240
 
@@ -299,7 +300,7 @@ div.bp-avatar-nav {
299
  }
300
 
301
  .bp-avatar .item {
302
- overflow:hidden;
303
  }
304
 
305
  .bp-avatar .avatar-crop-management.adjust {
@@ -324,7 +325,7 @@ div.bp-avatar-nav {
324
  margin: 0 auto 10px;
325
  }
326
 
327
- #bp-webcam-avatar .avatar-crop-management #avatar-crop-actions {
328
  width: auto;
329
  }
330
 
@@ -349,7 +350,9 @@ div.bp-avatar-nav {
349
 
350
  }
351
 
 
352
  /** Admin Profile **/
 
353
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent,
354
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent {
355
  height: 95% !important;
@@ -368,9 +371,11 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
368
  float: left;
369
  margin: 0;
370
  }
 
371
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
372
  margin-bottom: 20px;
373
  }
 
374
  @media screen and (min-width: 783px) {
375
 
376
  .wp-admin #TB_window .bp-avatar .avatar-crop-management {
@@ -385,8 +390,8 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
385
  }
386
 
387
  .wp-admin #TB_window .bp-avatar #avatar-to-crop video {
388
- width: 100%;
389
- }
390
 
391
  .wp-admin #TB_window .bp-avatar .avatar-crop-management a.button {
392
  height: auto;
@@ -394,6 +399,7 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
394
  }
395
 
396
  @media screen and (min-width: 810px) {
 
397
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
398
  max-width: none;
399
  width: 76%;
@@ -404,3 +410,4 @@ body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
404
  width: auto;
405
  }
406
  }
 
30
  border: 1px solid #d1d1d1;
31
  float: right;
32
  height: 22px;
33
+ line-height: 2;
34
  margin: 6px 10px 0 0;
35
  margin-bottom: 2px;
36
  padding: 0;
55
  padding: 10px 15px;
56
  }
57
 
58
+ /* stylelint-disable selector-id-pattern */
59
  #buddypress p.warning,
60
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,
61
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning {
67
  margin: 1em 0;
68
  padding: 10px 15px;
69
  }
70
+ /* stylelint-enable */
71
 
72
  div.bp-avatar-nav {
73
  background: transparent;
74
  clear: both;
75
+ margin: 10px 0;
76
  overflow: hidden;
77
  }
78
 
119
  .bp-avatar-nav li.current a {
120
  background: none;
121
  color: inherit;
122
+ font-weight: 700;
123
  opacity: 0.8;
124
  outline: 0;
125
  }
147
  text-align: inherit;
148
  }
149
 
150
+ .moxie-shim.moxie-shim-html5 input {
151
+ cursor: pointer;
152
+ }
153
+
154
  .drag-drop #drag-drop-area {
155
  box-sizing: border-box;
156
  display: table;
171
  }
172
 
173
  .drag-drop .drag-drop-inside p {
174
+ color: #767676;
175
  font-size: 110%;
176
  margin: 5px 0;
177
  text-align: center;
181
  margin-top: 0;
182
  }
183
 
 
 
 
 
 
 
184
  #avatar-to-crop {
185
+ margin: 0 auto 20px;
186
  text-align: left;
187
  }
188
 
222
  }
223
 
224
  @media screen and (min-width: 801px) {
225
+
226
  #bp-webcam-avatar #avatar-to-crop {
227
  max-width: 64%;
228
  width: 64%;
235
 
236
  #bp-webcam-avatar #avatar-crop-actions {
237
  float: left;
238
+ margin: 0 0 20px;
239
  width: 50%;
240
  }
241
 
300
  }
301
 
302
  .bp-avatar .item {
303
+ overflow: hidden;
304
  }
305
 
306
  .bp-avatar .avatar-crop-management.adjust {
325
  margin: 0 auto 10px;
326
  }
327
 
328
+ #bp-webcam-avatar .avatar-crop-management #avatar-crop-actions {
329
  width: auto;
330
  }
331
 
350
 
351
  }
352
 
353
+
354
  /** Admin Profile **/
355
+ /* stylelint-disable selector-id-pattern */
356
  body.users_page_bp-profile-edit.modal-open #TB_ajaxContent,
357
  body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent {
358
  height: 95% !important;
371
  float: left;
372
  margin: 0;
373
  }
374
+
375
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
376
  margin-bottom: 20px;
377
  }
378
+
379
  @media screen and (min-width: 783px) {
380
 
381
  .wp-admin #TB_window .bp-avatar .avatar-crop-management {
390
  }
391
 
392
  .wp-admin #TB_window .bp-avatar #avatar-to-crop video {
393
+ width: 100%;
394
+ }
395
 
396
  .wp-admin #TB_window .bp-avatar .avatar-crop-management a.button {
397
  height: auto;
399
  }
400
 
401
  @media screen and (min-width: 810px) {
402
+
403
  .wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop {
404
  max-width: none;
405
  width: 76%;
410
  width: auto;
411
  }
412
  }
413
+ /* stylelint-enable */
bp-core/css/avatar.min.css CHANGED
@@ -1 +1 @@
1
- div.bp-avatar-status,div.bp-cover-image-status{clear:both;margin:1em 0}div.bp-avatar-status p.updated,div.bp-cover-image-status p.updated{display:block;padding:10px 15px}div.bp-avatar-status p.success,div.bp-cover-image-status p.success{background-color:#efc;border:1px solid #591;color:#250}div.bp-avatar-status p.error,div.bp-cover-image-status p.error{background-color:#fdc;border:1px solid #a00;color:#800}div.bp-avatar-status .bp-progress,div.bp-cover-image-status .bp-progress{background:0 0;border:1px solid #d1d1d1;float:right;height:22px;line-height:2em;margin:6px 10px 2px 0;padding:0;overflow:hidden;width:200px}div.bp-avatar-status .bp-bar,div.bp-cover-image-status .bp-bar{background-color:#c3ff88;width:0;height:100%;z-index:9}.bp-uploader-progress div.error{background-color:#fdc;border:1px solid #a00;color:#800;display:block;font-size:90%;padding:10px 15px}#buddypress p.warning,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{background-color:#ffd;border:1px solid #cb2;color:#440;display:block;font-size:90%;margin:1em 0;padding:10px 15px}div.bp-avatar-nav{background:0 0;clear:both;margin:10px 0;overflow:hidden}.avatar-nav-items{margin:0;padding:0}.bp-avatar-nav .avatar-nav-items li.avatar-nav-item{float:left!important;margin:0;list-style:none}.avatar-nav-items li a{display:block;padding:5px 10px;text-decoration:none}.bp-avatar-nav ul:after,.bp-avatar-nav ul:before{content:" ";display:table}.bp-avatar-nav ul:after{clear:both}.bp-avatar-nav ul{border-bottom:1px solid #ccc;margin-bottom:10px}.bp-avatar-nav ul.avatar-nav-items li.current{border:1px solid #ccc;border-bottom-color:#fff;border-top-left-radius:4px;border-top-right-radius:4px;margin-bottom:-1px}.bp-avatar-nav li.current a{background:0 0;color:inherit;font-weight:700;opacity:.8;outline:0}#drag-drop-area{border:4px dashed #bbb;height:200px}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}.drag-drop-inside p{display:none}.drag-drop-inside p.drag-drop-buttons{margin-top:80px;text-align:center}.drag-drop .drag-drop-inside p.drag-drop-buttons{margin:auto;text-align:inherit}.drag-drop #drag-drop-area{box-sizing:border-box;display:table;height:100%;width:100%}.drag-drop .drag-drop-inside{display:table-cell;padding:40px 0;text-align:center;vertical-align:middle}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop .drag-drop-inside p{color:#aaa;font-size:110%;margin:5px 0;text-align:center}.drag-drop-inside p.drag-drop-info{margin-top:0}@supports (-ms-accelerator:true){.drag-drop-inside p.drag-drop-info{display:block}}#avatar-to-crop{margin:0 auto 20px;text-align:left}#bp-webcam-avatar #avatar-to-crop{float:left;margin:0 0 20px}#avatar-to-crop .jcrop-holder{margin:0 auto}.avatar-crop-management{clear:left;overflow:hidden;padding-top:20px;text-align:center}#bp-webcam-avatar .avatar-crop-management{clear:none;float:none;overflow:visible;padding-top:0;width:auto}#avatar-crop-pane{margin:0 auto;overflow:hidden}#bp-webcam-avatar #avatar-to-crop{border:1px solid #eee;max-width:100%;width:100%}@media screen and (min-width:801px){#bp-webcam-avatar #avatar-to-crop{max-width:64%;width:64%}}#avatar-crop-actions a{display:block}#bp-webcam-avatar #avatar-crop-actions{float:left;margin:0 0 20px;width:50%}#avatar-crop-actions a.button{margin-top:10px}#bp-webcam-avatar #avatar-crop-actions a.button{display:block;margin:0 0 5px;padding:4px 0;width:100%}#avatar-crop-pane canvas,#avatar-crop-pane img,#avatar-to-crop img,#avatar-upload-form img,#create-group-form img,#group-settings-form img{border:none!important;max-width:none!important}#bp-webcam-avatar video{float:left;margin-bottom:0;max-width:100%;width:100%;-webkit-transform:scaleX(-1);transform:scaleX(-1)}#bp-webcam-avatar #avatar-crop-pane{border:2px dashed #bbb;clear:left;float:right;margin:0 40px 10px 0;overflow:hidden}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{max-width:150px;max-height:150px}#avatar-crop-pane canvas{height:auto;width:100%;max-width:100%}.group-avatar .bp-avatar .avatar-crop-management{margin-left:0;padding-top:0;width:auto}.bp-avatar .item{overflow:hidden}.bp-avatar .avatar-crop-management.adjust{float:left;clear:none;padding-top:0}.bp-avatar #avatar-to-crop.adjust{float:left;margin-right:20px}@media screen and (max-width:480px){#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions,#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{width:auto}}@media screen and (min-width:801px){#bp-webcam-avatar .avatar-crop-management{clear:none;float:right}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none;margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{float:left;width:100%}}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent{height:95%!important;width:95%!important}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{display:block;padding:10px 15px}.wp-admin #TB_window .bp-avatar #avatar-to-crop{float:left;margin:0}.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{margin-bottom:20px}@media screen and (min-width:783px){.wp-admin #TB_window .bp-avatar .avatar-crop-management{clear:none;float:left;margin-left:20px;padding-top:0;text-align:center}}.wp-admin #TB_window .bp-avatar #avatar-to-crop video{width:100%}.wp-admin #TB_window .bp-avatar .avatar-crop-management a.button{height:auto;line-height:inherit}@media screen and (min-width:810px){.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{max-width:none;width:76%}.wp-admin #TB_window #bp-webcam-avatar .avatar-crop-management{max-width:none;width:auto}}
1
+ div.bp-avatar-status,div.bp-cover-image-status{clear:both;margin:1em 0}div.bp-avatar-status p.updated,div.bp-cover-image-status p.updated{display:block;padding:10px 15px}div.bp-avatar-status p.success,div.bp-cover-image-status p.success{background-color:#efc;border:1px solid #591;color:#250}div.bp-avatar-status p.error,div.bp-cover-image-status p.error{background-color:#fdc;border:1px solid #a00;color:#800}div.bp-avatar-status .bp-progress,div.bp-cover-image-status .bp-progress{background:0 0;border:1px solid #d1d1d1;float:right;height:22px;line-height:2;margin:6px 10px 0 0;margin-bottom:2px;padding:0;overflow:hidden;width:200px}div.bp-avatar-status .bp-bar,div.bp-cover-image-status .bp-bar{background-color:#c3ff88;width:0;height:100%;z-index:9}.bp-uploader-progress div.error{background-color:#fdc;border:1px solid #a00;color:#800;display:block;font-size:90%;padding:10px 15px}#buddypress p.warning,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{background-color:#ffd;border:1px solid #cb2;color:#440;display:block;font-size:90%;margin:1em 0;padding:10px 15px}div.bp-avatar-nav{background:0 0;clear:both;margin:10px 0;overflow:hidden}.avatar-nav-items{margin:0;padding:0}.bp-avatar-nav .avatar-nav-items li.avatar-nav-item{float:left!important;margin:0;list-style:none}.avatar-nav-items li a{display:block;padding:5px 10px;text-decoration:none}.bp-avatar-nav ul:after,.bp-avatar-nav ul:before{content:" ";display:table}.bp-avatar-nav ul:after{clear:both}.bp-avatar-nav ul{border-bottom:1px solid #ccc;margin-bottom:10px}.bp-avatar-nav ul.avatar-nav-items li.current{border:1px solid #ccc;border-bottom-color:#fff;border-top-left-radius:4px;border-top-right-radius:4px;margin-bottom:-1px}.bp-avatar-nav li.current a{background:0 0;color:inherit;font-weight:700;opacity:.8;outline:0}#drag-drop-area{border:4px dashed #bbb;height:200px}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}.drag-drop-inside p{display:none}.drag-drop-inside p.drag-drop-buttons{margin-top:80px;text-align:center}.drag-drop .drag-drop-inside p.drag-drop-buttons{margin:auto;text-align:inherit}.moxie-shim.moxie-shim-html5 input{cursor:pointer}.drag-drop #drag-drop-area{box-sizing:border-box;display:table;height:100%;width:100%}.drag-drop .drag-drop-inside{display:table-cell;padding:40px 0;text-align:center;vertical-align:middle}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop .drag-drop-inside p{color:#767676;font-size:110%;margin:5px 0;text-align:center}.drag-drop-inside p.drag-drop-info{margin-top:0}#avatar-to-crop{margin:0 auto 20px;text-align:left}#bp-webcam-avatar #avatar-to-crop{float:left;margin:0 0 20px}#avatar-to-crop .jcrop-holder{margin:0 auto}.avatar-crop-management{clear:left;overflow:hidden;padding-top:20px;text-align:center}#bp-webcam-avatar .avatar-crop-management{clear:none;float:none;overflow:visible;padding-top:0;width:auto}#avatar-crop-pane{margin:0 auto;overflow:hidden}#bp-webcam-avatar #avatar-to-crop{border:1px solid #eee;max-width:100%;width:100%}@media screen and (min-width:801px){#bp-webcam-avatar #avatar-to-crop{max-width:64%;width:64%}}#avatar-crop-actions a{display:block}#bp-webcam-avatar #avatar-crop-actions{float:left;margin:0 0 20px;width:50%}#avatar-crop-actions a.button{margin-top:10px}#bp-webcam-avatar #avatar-crop-actions a.button{display:block;margin:0 0 5px;padding:4px 0;width:100%}#avatar-crop-pane canvas,#avatar-crop-pane img,#avatar-to-crop img,#avatar-upload-form img,#create-group-form img,#group-settings-form img{border:none!important;max-width:none!important}#bp-webcam-avatar video{float:left;margin-bottom:0;max-width:100%;width:100%;-webkit-transform:scaleX(-1);transform:scaleX(-1)}#bp-webcam-avatar #avatar-crop-pane{border:2px dashed #bbb;clear:left;float:right;margin:0 40px 10px 0;overflow:hidden}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{max-width:150px;max-height:150px}#avatar-crop-pane canvas{height:auto;width:100%;max-width:100%}.group-avatar .bp-avatar .avatar-crop-management{margin-left:0;padding-top:0;width:auto}.bp-avatar .item{overflow:hidden}.bp-avatar .avatar-crop-management.adjust{float:left;clear:none;padding-top:0}.bp-avatar #avatar-to-crop.adjust{float:left;margin-right:20px}@media screen and (max-width:480px){#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions,#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{width:auto}}@media screen and (min-width:801px){#bp-webcam-avatar .avatar-crop-management{clear:none;float:right}#bp-webcam-avatar .avatar-crop-management #avatar-crop-pane{float:none;margin:0 auto 10px}#bp-webcam-avatar .avatar-crop-management #avatar-crop-actions{float:left;width:100%}}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent{height:95%!important;width:95%!important}body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.profile_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.updated,body.users_page_bp-profile-edit.modal-open #TB_ajaxContent p.warning{display:block;padding:10px 15px}.wp-admin #TB_window .bp-avatar #avatar-to-crop{float:left;margin:0}.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{margin-bottom:20px}@media screen and (min-width:783px){.wp-admin #TB_window .bp-avatar .avatar-crop-management{clear:none;float:left;margin-left:20px;padding-top:0;text-align:center}}.wp-admin #TB_window .bp-avatar #avatar-to-crop video{width:100%}.wp-admin #TB_window .bp-avatar .avatar-crop-management a.button{height:auto;line-height:inherit}@media screen and (min-width:810px){.wp-admin #TB_window .bp-avatar #bp-webcam-avatar #avatar-to-crop{max-width:none;width:76%}.wp-admin #TB_window #bp-webcam-avatar .avatar-crop-management{max-width:none;width:auto}}
bp-core/css/buddybar-rtl.css CHANGED
@@ -1,6 +1,7 @@
1
  body:not(.wp-admin) {
2
  padding-top: 25px !important;
3
  }
 
4
  #wp-admin-bar {
5
  position: fixed;
6
  top: 0;
@@ -10,63 +11,76 @@ body:not(.wp-admin) {
10
  width: 100%;
11
  z-index: 9999;
12
  }
 
13
  #wp-admin-bar .padder {
14
  position: relative;
15
  padding: 0;
16
  width: 100%;
17
  margin: 0 auto;
18
- background: url('../images/60pc_black.png');
19
  height: 25px;
20
  }
 
21
  body#bp-default #wp-admin-bar .padder {
22
  max-width: 1250px;
23
  }
 
24
  #wp-admin-bar * {
25
  z-index: 999;
26
  }
 
27
  #wp-admin-bar div#admin-bar-logo {
28
  position: absolute;
29
  top: 5px;
30
  right: 10px;
31
  }
 
32
  #wp-admin-bar a img {
33
  border: none;
34
  }
 
35
  #wp-admin-bar li {
36
  list-style: none;
37
  margin: 0;
38
  padding: 0;
39
- line-height: 100%;
40
  text-align: right;
41
  }
 
42
  #wp-admin-bar li a {
43
- padding: 7px 15px 7px 15px;
44
  color: #eee;
45
  text-decoration: none;
46
  font-size: 11px;
47
  }
 
48
  #wp-admin-bar li.alt {
49
  border: none;
50
  }
 
51
  #wp-admin-bar li.no-arrow a {
52
  padding-left: 15px;
53
  }
 
54
  #wp-admin-bar ul li ul li a span {
55
  display: none;
56
  }
 
57
  #wp-admin-bar li:hover,
58
  #wp-admin-bar li.hover {
59
  position: static;
60
  }
 
61
  #admin-bar-logo {
62
  float: right;
63
- font-weight: bold;
64
  font-size: 11px;
65
  padding: 5px 8px;
66
  margin: 0;
67
  text-decoration: none;
68
  color: #fff;
69
  }
 
70
  body#bp-default #admin-bar-logo {
71
  padding: 2px 8px;
72
  }
@@ -86,23 +100,28 @@ body#bp-default #admin-bar-logo {
86
  padding: 0;
87
  float: right;
88
  position: relative;
89
- background: url('../images/admin-menu-arrow.gif') 88% 53% no-repeat;
90
  padding-left: 11px;
91
  }
 
92
  #wp-admin-bar ul li.no-arrow {
93
  background: none;
94
  padding-left: 0;
95
  }
 
96
  #wp-admin-bar ul li ul li {
97
  background-image: none;
98
  }
 
99
  #wp-admin-bar ul li.align-right {
100
  position: absolute;
101
  left: 0;
102
  }
 
103
  #wp-admin-bar ul li a {
104
  display: block;
105
  }
 
106
  #wp-admin-bar ul.main-nav li:hover,
107
  #wp-admin-bar ul.main-nav li.sfhover,
108
  #wp-admin-bar ul.main-nav li ul li.sfhover {
@@ -126,23 +145,29 @@ body#bp-default #admin-bar-logo {
126
  -moz-border-radius-topleft: 0;
127
  -webkit-border-top-left-radius: 0;
128
  }
 
129
  #wp-admin-bar ul li > ul {
130
  border-top: none;
131
  }
 
132
  #wp-admin-bar ul li ul a {
133
  color: #eee;
134
  }
 
135
  #wp-admin-bar ul li ul li {
136
  float: right;
137
  width: 174px;
138
  margin: 0;
139
  }
 
140
  #wp-admin-bar ul li ul li:hover a {
141
  color: #fff;
142
  }
 
143
  #wp-admin-bar ul li div.admin-bar-clear {
144
  clear: both;
145
  }
 
146
  #wp-admin-bar ul.main-nav li ul li:hover,
147
  #wp-admin-bar ul.main-nav li ul li.sfhover,
148
  #wp-admin-bar ul.main-nav li ul li.sfhover {
@@ -155,21 +180,26 @@ body#bp-default #admin-bar-logo {
155
  -moz-border-radius: 3px;
156
  -webkit-border-radius: 3px;
157
  }
 
158
  #wp-admin-bar ul li ul li:hover ul li a {
159
  color: #eee;
160
  }
 
161
  #wp-admin-bar ul li ul li ul li:hover a {
162
  color: #fff;
163
  }
 
164
  #wp-admin-bar ul li:hover ul,
165
  #wp-admin-bar ul li ul li:hover ul,
166
  #wp-admin-bar ul li.sfhover ul,
167
  #wp-admin-bar ul li ul li.sfhover ul {
168
  right: auto;
169
  }
 
170
  #wp-admin-bar ul li.align-right:hover ul {
171
  left: 0;
172
  }
 
173
  #wp-admin-bar ul li:hover ul ul,
174
  #wp-admin-bar li.sfhover ul li ul {
175
  right: -999em;
@@ -180,14 +210,17 @@ body#bp-default #admin-bar-logo {
180
  float: right;
181
  margin-left: 8px;
182
  }
 
183
  #wp-admin-bar span.activity {
184
  display: block;
185
  margin-right: 34px;
186
  padding: 0;
187
  }
 
188
  #wp-admin-bar ul.author-list li a {
189
  height: 17px;
190
  }
 
191
  #wp-admin-bar ul li#bp-adminbar-notifications-menu a span {
192
  padding: 0 6px;
193
  margin-right: 2px;
@@ -197,6 +230,7 @@ body#bp-default #admin-bar-logo {
197
  -webkit-border-radius: 3px;
198
  border-radius: 3px;
199
  }
 
200
  #wp-admin-bar-user-info img.avatar {
201
  height: 64px;
202
  width: 64px;
1
  body:not(.wp-admin) {
2
  padding-top: 25px !important;
3
  }
4
+
5
  #wp-admin-bar {
6
  position: fixed;
7
  top: 0;
11
  width: 100%;
12
  z-index: 9999;
13
  }
14
+
15
  #wp-admin-bar .padder {
16
  position: relative;
17
  padding: 0;
18
  width: 100%;
19
  margin: 0 auto;
20
+ background: url(../images/60pc_black.png);
21
  height: 25px;
22
  }
23
+
24
  body#bp-default #wp-admin-bar .padder {
25
  max-width: 1250px;
26
  }
27
+
28
  #wp-admin-bar * {
29
  z-index: 999;
30
  }
31
+
32
  #wp-admin-bar div#admin-bar-logo {
33
  position: absolute;
34
  top: 5px;
35
  right: 10px;
36
  }
37
+
38
  #wp-admin-bar a img {
39
  border: none;
40
  }
41
+
42
  #wp-admin-bar li {
43
  list-style: none;
44
  margin: 0;
45
  padding: 0;
46
+ line-height: 1;
47
  text-align: right;
48
  }
49
+
50
  #wp-admin-bar li a {
51
+ padding: 7px 15px;
52
  color: #eee;
53
  text-decoration: none;
54
  font-size: 11px;
55
  }
56
+
57
  #wp-admin-bar li.alt {
58
  border: none;
59
  }
60
+
61
  #wp-admin-bar li.no-arrow a {
62
  padding-left: 15px;
63
  }
64
+
65
  #wp-admin-bar ul li ul li a span {
66
  display: none;
67
  }
68
+
69
  #wp-admin-bar li:hover,
70
  #wp-admin-bar li.hover {
71
  position: static;
72
  }
73
+
74
  #admin-bar-logo {
75
  float: right;
76
+ font-weight: 700;
77
  font-size: 11px;
78
  padding: 5px 8px;
79
  margin: 0;
80
  text-decoration: none;
81
  color: #fff;
82
  }
83
+
84
  body#bp-default #admin-bar-logo {
85
  padding: 2px 8px;
86
  }
100
  padding: 0;
101
  float: right;
102
  position: relative;
103
+ background: url(../images/admin-menu-arrow.gif) 88% 53% no-repeat;
104
  padding-left: 11px;
105
  }
106
+
107
  #wp-admin-bar ul li.no-arrow {
108
  background: none;
109
  padding-left: 0;
110
  }
111
+
112
  #wp-admin-bar ul li ul li {
113
  background-image: none;
114
  }
115
+
116
  #wp-admin-bar ul li.align-right {
117
  position: absolute;
118
  left: 0;
119
  }
120
+
121
  #wp-admin-bar ul li a {
122
  display: block;
123
  }
124
+
125
  #wp-admin-bar ul.main-nav li:hover,
126
  #wp-admin-bar ul.main-nav li.sfhover,
127
  #wp-admin-bar ul.main-nav li ul li.sfhover {
145
  -moz-border-radius-topleft: 0;
146
  -webkit-border-top-left-radius: 0;
147
  }
148
+
149
  #wp-admin-bar ul li > ul {
150
  border-top: none;
151
  }
152
+
153
  #wp-admin-bar ul li ul a {
154
  color: #eee;
155
  }
156
+
157
  #wp-admin-bar ul li ul li {
158
  float: right;
159
  width: 174px;
160
  margin: 0;
161
  }
162
+
163
  #wp-admin-bar ul li ul li:hover a {
164
  color: #fff;
165
  }
166
+
167
  #wp-admin-bar ul li div.admin-bar-clear {
168
  clear: both;
169
  }
170
+
171
  #wp-admin-bar ul.main-nav li ul li:hover,
172
  #wp-admin-bar ul.main-nav li ul li.sfhover,
173
  #wp-admin-bar ul.main-nav li ul li.sfhover {
180
  -moz-border-radius: 3px;
181
  -webkit-border-radius: 3px;
182
  }
183
+
184
  #wp-admin-bar ul li ul li:hover ul li a {
185
  color: #eee;
186
  }
187
+
188
  #wp-admin-bar ul li ul li ul li:hover a {
189
  color: #fff;
190
  }
191
+
192
  #wp-admin-bar ul li:hover ul,
193
  #wp-admin-bar ul li ul li:hover ul,
194
  #wp-admin-bar ul li.sfhover ul,
195
  #wp-admin-bar ul li ul li.sfhover ul {
196
  right: auto;
197
  }
198
+
199
  #wp-admin-bar ul li.align-right:hover ul {
200
  left: 0;
201
  }
202
+
203
  #wp-admin-bar ul li:hover ul ul,
204
  #wp-admin-bar li.sfhover ul li ul {
205
  right: -999em;
210
  float: right;
211
  margin-left: 8px;
212
  }
213
+
214
  #wp-admin-bar span.activity {
215
  display: block;
216
  margin-right: 34px;
217
  padding: 0;
218
  }
219
+
220
  #wp-admin-bar ul.author-list li a {
221
  height: 17px;
222
  }
223
+
224
  #wp-admin-bar ul li#bp-adminbar-notifications-menu a span {
225
  padding: 0 6px;
226
  margin-right: 2px;
230
  -webkit-border-radius: 3px;
231
  border-radius: 3px;
232
  }
233
+
234
  #wp-admin-bar-user-info img.avatar {
235
  height: 64px;
236
  width: 64px;
bp-core/css/buddybar-rtl.min.css CHANGED
@@ -1 +1 @@
1
- #admin-bar-logo,#wp-admin-bar li a{font-size:11px;text-decoration:none}#wp-admin-bar ul li ul a,#wp-admin-bar ul li ul li:hover ul li a{color:#eee}#wp-admin-bar ul li ul li ul li:hover a,#wp-admin-bar ul li ul li:hover a{color:#fff}body:not(.wp-admin){padding-top:25px!important}#wp-admin-bar{position:fixed;top:0;right:0;height:25px;font-size:11px;width:100%;z-index:9999}#wp-admin-bar .padder{position:relative;padding:0;width:100%;margin:0 auto;background:url(../images/60pc_black.png);height:25px}body#bp-default #wp-admin-bar .padder{max-width:1250px}#wp-admin-bar *{z-index:999}#wp-admin-bar div#admin-bar-logo{position:absolute;top:5px;right:10px}#wp-admin-bar a img,#wp-admin-bar li.alt{border:none}#wp-admin-bar li{list-style:none;margin:0;padding:0;line-height:100%;text-align:right}#wp-admin-bar li a{padding:7px 15px;color:#eee}#wp-admin-bar li.no-arrow a{padding-left:15px}#wp-admin-bar ul li ul li a span{display:none}#wp-admin-bar li.hover,#wp-admin-bar li:hover{position:static}#admin-bar-logo{float:right;font-weight:700;padding:5px 8px;margin:0;color:#fff}body#bp-default #admin-bar-logo{padding:2px 8px}#wp-admin-bar ul{margin:0;list-style:none;line-height:1;cursor:pointer;height:auto;padding:0}#wp-admin-bar ul li{padding:0 0 0 11px;float:right;position:relative;background:url(../images/admin-menu-arrow.gif) 88% 53% no-repeat}#wp-admin-bar ul li.no-arrow{background:0 0;padding-left:0}#wp-admin-bar ul li ul li{background-image:none;float:right;width:174px;margin:0}#wp-admin-bar ul li.align-right{position:absolute;left:0}#wp-admin-bar ul li a{display:block}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li.sfhover,#wp-admin-bar ul.main-nav li:hover{background-color:#333}#wp-admin-bar ul li ul{position:absolute;width:185px;right:-999em;margin-right:0;background:#333;border:1px solid #222;-moz-box-shadow:0 4px 8px rgba(0,0,0,.1);-webkit-box-shadow:0 4px 8px rgba(0,0,0,.1);-moz-border-radius:3px;-webkit-border-radius:0 0 3px 3px;-moz-border-radius-topright:0;-moz-border-radius-topleft:0}#wp-admin-bar ul li>ul{border-top:none}#wp-admin-bar ul li div.admin-bar-clear{clear:both}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li ul li:hover{background-color:#222}#wp-admin-bar ul li ul ul{margin:-25px 184px 0 0;-moz-border-radius:3px;-webkit-border-radius:3px}#wp-admin-bar ul li ul li.sfhover ul,#wp-admin-bar ul li ul li:hover ul,#wp-admin-bar ul li.sfhover ul,#wp-admin-bar ul li:hover ul{right:auto}#wp-admin-bar ul li.align-right:hover ul{left:0}#wp-admin-bar li.sfhover ul li ul,#wp-admin-bar ul li:hover ul ul{right:-999em}#wp-admin-bar img.avatar{float:right;margin-left:8px}#wp-admin-bar span.activity{display:block;margin-right:34px;padding:0}#wp-admin-bar ul.author-list li a{height:17px}#wp-admin-bar ul li#bp-adminbar-notifications-menu a span{padding:0 6px;margin-right:2px;background:#fff;color:#000;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}
1
+ body:not(.wp-admin){padding-top:25px!important}#wp-admin-bar{position:fixed;top:0;right:0;height:25px;font-size:11px;width:100%;z-index:9999}#wp-admin-bar .padder{position:relative;padding:0;width:100%;margin:0 auto;background:url(../images/60pc_black.png);height:25px}body#bp-default #wp-admin-bar .padder{max-width:1250px}#wp-admin-bar *{z-index:999}#wp-admin-bar div#admin-bar-logo{position:absolute;top:5px;right:10px}#wp-admin-bar a img{border:none}#wp-admin-bar li{list-style:none;margin:0;padding:0;line-height:1;text-align:right}#wp-admin-bar li a{padding:7px 15px;color:#eee;text-decoration:none;font-size:11px}#wp-admin-bar li.alt{border:none}#wp-admin-bar li.no-arrow a{padding-left:15px}#wp-admin-bar ul li ul li a span{display:none}#wp-admin-bar li.hover,#wp-admin-bar li:hover{position:static}#admin-bar-logo{float:right;font-weight:700;font-size:11px;padding:5px 8px;margin:0;text-decoration:none;color:#fff}body#bp-default #admin-bar-logo{padding:2px 8px}#wp-admin-bar ul{margin:0;list-style:none;line-height:1;cursor:pointer;height:auto;padding:0}#wp-admin-bar ul li{padding:0;float:right;position:relative;background:url(../images/admin-menu-arrow.gif) 88% 53% no-repeat;padding-left:11px}#wp-admin-bar ul li.no-arrow{background:0 0;padding-left:0}#wp-admin-bar ul li ul li{background-image:none}#wp-admin-bar ul li.align-right{position:absolute;left:0}#wp-admin-bar ul li a{display:block}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li.sfhover,#wp-admin-bar ul.main-nav li:hover{background-color:#333}#wp-admin-bar ul li ul{position:absolute;width:185px;right:-999em;margin-right:0;background:#333;border:1px solid #222;-moz-box-shadow:0 4px 8px rgba(0,0,0,.1);-webkit-box-shadow:0 4px 8px rgba(0,0,0,.1);-moz-border-radius:3px;-webkit-border-radius:3px;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0}#wp-admin-bar ul li>ul{border-top:none}#wp-admin-bar ul li ul a{color:#eee}#wp-admin-bar ul li ul li{float:right;width:174px;margin:0}#wp-admin-bar ul li ul li:hover a{color:#fff}#wp-admin-bar ul li div.admin-bar-clear{clear:both}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li ul li:hover{background-color:#222}#wp-admin-bar ul li ul ul{margin:-25px 184px 0 0;-moz-border-radius:3px;-webkit-border-radius:3px}#wp-admin-bar ul li ul li:hover ul li a{color:#eee}#wp-admin-bar ul li ul li ul li:hover a{color:#fff}#wp-admin-bar ul li ul li.sfhover ul,#wp-admin-bar ul li ul li:hover ul,#wp-admin-bar ul li.sfhover ul,#wp-admin-bar ul li:hover ul{right:auto}#wp-admin-bar ul li.align-right:hover ul{left:0}#wp-admin-bar li.sfhover ul li ul,#wp-admin-bar ul li:hover ul ul{right:-999em}#wp-admin-bar img.avatar{float:right;margin-left:8px}#wp-admin-bar span.activity{display:block;margin-right:34px;padding:0}#wp-admin-bar ul.author-list li a{height:17px}#wp-admin-bar ul li#bp-adminbar-notifications-menu a span{padding:0 6px;margin-right:2px;background:#fff;color:#000;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}
bp-core/css/buddybar.css CHANGED
@@ -1,6 +1,7 @@
1
  body:not(.wp-admin) {
2
  padding-top: 25px !important;
3
  }
 
4
  #wp-admin-bar {
5
  position: fixed;
6
  top: 0;
@@ -10,63 +11,76 @@ body:not(.wp-admin) {
10
  width: 100%;
11
  z-index: 9999;
12
  }
 
13
  #wp-admin-bar .padder {
14
  position: relative;
15
  padding: 0;
16
  width: 100%;
17
  margin: 0 auto;
18
- background: url('../images/60pc_black.png');
19
  height: 25px;
20
  }
 
21
  body#bp-default #wp-admin-bar .padder {
22
  max-width: 1250px;
23
  }
 
24
  #wp-admin-bar * {
25
  z-index: 999;
26
  }
 
27
  #wp-admin-bar div#admin-bar-logo {
28
  position: absolute;
29
  top: 5px;
30
  left: 10px;
31
  }
 
32
  #wp-admin-bar a img {
33
  border: none;
34
  }
 
35
  #wp-admin-bar li {
36
  list-style: none;
37
  margin: 0;
38
  padding: 0;
39
- line-height: 100%;
40
  text-align: left;
41
  }
 
42
  #wp-admin-bar li a {
43
- padding: 7px 15px 7px 15px;
44
  color: #eee;
45
  text-decoration: none;
46
  font-size: 11px;
47
  }
 
48
  #wp-admin-bar li.alt {
49
  border: none;
50
  }
 
51
  #wp-admin-bar li.no-arrow a {
52
  padding-right: 15px;
53
  }
 
54
  #wp-admin-bar ul li ul li a span {
55
  display: none;
56
  }
 
57
  #wp-admin-bar li:hover,
58
  #wp-admin-bar li.hover {
59
  position: static;
60
  }
 
61
  #admin-bar-logo {
62
  float: left;
63
- font-weight: bold;
64
  font-size: 11px;
65
  padding: 5px 8px;
66
  margin: 0;
67
  text-decoration: none;
68
  color: #fff;
69
  }
 
70
  body#bp-default #admin-bar-logo {
71
  padding: 2px 8px;
72
  }
@@ -86,23 +100,28 @@ body#bp-default #admin-bar-logo {
86
  padding: 0;
87
  float: left;
88
  position: relative;
89
- background: url('../images/admin-menu-arrow.gif') 88% 53% no-repeat;
90
  padding-right: 11px;
91
  }
 
92
  #wp-admin-bar ul li.no-arrow {
93
  background: none;
94
  padding-right: 0;
95
  }
 
96
  #wp-admin-bar ul li ul li {
97
  background-image: none;
98
  }
 
99
  #wp-admin-bar ul li.align-right {
100
  position: absolute;
101
  right: 0;
102
  }
 
103
  #wp-admin-bar ul li a {
104
  display: block;
105
  }
 
106
  #wp-admin-bar ul.main-nav li:hover,
107
  #wp-admin-bar ul.main-nav li.sfhover,
108
  #wp-admin-bar ul.main-nav li ul li.sfhover {
@@ -126,23 +145,29 @@ body#bp-default #admin-bar-logo {
126
  -moz-border-radius-topright: 0;
127
  -webkit-border-top-right-radius: 0;
128
  }
 
129
  #wp-admin-bar ul li > ul {
130
  border-top: none;
131
  }
 
132
  #wp-admin-bar ul li ul a {
133
  color: #eee;
134
  }
 
135
  #wp-admin-bar ul li ul li {
136
  float: left;
137
  width: 174px;
138
  margin: 0;
139
  }
 
140
  #wp-admin-bar ul li ul li:hover a {
141
  color: #fff;
142
  }
 
143
  #wp-admin-bar ul li div.admin-bar-clear {
144
  clear: both;
145
  }
 
146
  #wp-admin-bar ul.main-nav li ul li:hover,
147
  #wp-admin-bar ul.main-nav li ul li.sfhover,
148
  #wp-admin-bar ul.main-nav li ul li.sfhover {
@@ -155,21 +180,26 @@ body#bp-default #admin-bar-logo {
155
  -moz-border-radius: 3px;
156
  -webkit-border-radius: 3px;
157
  }
 
158
  #wp-admin-bar ul li ul li:hover ul li a {
159
  color: #eee;
160
  }
 
161
  #wp-admin-bar ul li ul li ul li:hover a {
162
  color: #fff;
163
  }
 
164
  #wp-admin-bar ul li:hover ul,
165
  #wp-admin-bar ul li ul li:hover ul,
166
  #wp-admin-bar ul li.sfhover ul,
167
  #wp-admin-bar ul li ul li.sfhover ul {
168
  left: auto;
169
  }
 
170
  #wp-admin-bar ul li.align-right:hover ul {
171
  right: 0;
172
  }
 
173
  #wp-admin-bar ul li:hover ul ul,
174
  #wp-admin-bar li.sfhover ul li ul {
175
  left: -999em;
@@ -180,14 +210,17 @@ body#bp-default #admin-bar-logo {
180
  float: left;
181
  margin-right: 8px;
182
  }
 
183
  #wp-admin-bar span.activity {
184
  display: block;
185
  margin-left: 34px;
186
  padding: 0;
187
  }
 
188
  #wp-admin-bar ul.author-list li a {
189
  height: 17px;
190
  }
 
191
  #wp-admin-bar ul li#bp-adminbar-notifications-menu a span {
192
  padding: 0 6px;
193
  margin-left: 2px;
@@ -197,6 +230,7 @@ body#bp-default #admin-bar-logo {
197
  -webkit-border-radius: 3px;
198
  border-radius: 3px;
199
  }
 
200
  #wp-admin-bar-user-info img.avatar {
201
  height: 64px;
202
  width: 64px;
1
  body:not(.wp-admin) {
2
  padding-top: 25px !important;
3
  }
4
+
5
  #wp-admin-bar {
6
  position: fixed;
7
  top: 0;
11
  width: 100%;
12
  z-index: 9999;
13
  }
14
+
15
  #wp-admin-bar .padder {
16
  position: relative;
17
  padding: 0;
18
  width: 100%;
19
  margin: 0 auto;
20
+ background: url(../images/60pc_black.png);
21
  height: 25px;
22
  }
23
+
24
  body#bp-default #wp-admin-bar .padder {
25
  max-width: 1250px;
26
  }
27
+
28
  #wp-admin-bar * {
29
  z-index: 999;
30
  }
31
+
32
  #wp-admin-bar div#admin-bar-logo {
33
  position: absolute;
34
  top: 5px;
35
  left: 10px;
36
  }
37
+
38
  #wp-admin-bar a img {
39
  border: none;
40
  }
41
+
42
  #wp-admin-bar li {
43
  list-style: none;
44
  margin: 0;
45
  padding: 0;
46
+ line-height: 1;
47
  text-align: left;
48
  }
49
+
50
  #wp-admin-bar li a {
51
+ padding: 7px 15px;
52
  color: #eee;
53
  text-decoration: none;
54
  font-size: 11px;
55
  }
56
+
57
  #wp-admin-bar li.alt {
58
  border: none;
59
  }
60
+
61
  #wp-admin-bar li.no-arrow a {
62
  padding-right: 15px;
63
  }
64
+
65
  #wp-admin-bar ul li ul li a span {
66
  display: none;
67
  }
68
+
69
  #wp-admin-bar li:hover,
70
  #wp-admin-bar li.hover {
71
  position: static;
72
  }
73
+
74
  #admin-bar-logo {
75
  float: left;
76
+ font-weight: 700;
77
  font-size: 11px;
78
  padding: 5px 8px;
79
  margin: 0;
80
  text-decoration: none;
81
  color: #fff;
82
  }
83
+
84
  body#bp-default #admin-bar-logo {
85
  padding: 2px 8px;
86
  }
100
  padding: 0;
101
  float: left;
102
  position: relative;
103
+ background: url(../images/admin-menu-arrow.gif) 88% 53% no-repeat;
104
  padding-right: 11px;
105
  }
106
+
107
  #wp-admin-bar ul li.no-arrow {
108
  background: none;
109
  padding-right: 0;
110
  }
111
+
112
  #wp-admin-bar ul li ul li {
113
  background-image: none;
114
  }
115
+
116
  #wp-admin-bar ul li.align-right {
117
  position: absolute;
118
  right: 0;
119
  }
120
+
121
  #wp-admin-bar ul li a {
122
  display: block;
123
  }
124
+
125
  #wp-admin-bar ul.main-nav li:hover,
126
  #wp-admin-bar ul.main-nav li.sfhover,
127
  #wp-admin-bar ul.main-nav li ul li.sfhover {
145
  -moz-border-radius-topright: 0;
146
  -webkit-border-top-right-radius: 0;
147
  }
148
+
149
  #wp-admin-bar ul li > ul {
150
  border-top: none;
151
  }
152
+
153
  #wp-admin-bar ul li ul a {
154
  color: #eee;
155
  }
156
+
157
  #wp-admin-bar ul li ul li {
158
  float: left;
159
  width: 174px;
160
  margin: 0;
161
  }
162
+
163
  #wp-admin-bar ul li ul li:hover a {
164
  color: #fff;
165
  }
166
+
167
  #wp-admin-bar ul li div.admin-bar-clear {
168
  clear: both;
169
  }
170
+
171
  #wp-admin-bar ul.main-nav li ul li:hover,
172
  #wp-admin-bar ul.main-nav li ul li.sfhover,
173
  #wp-admin-bar ul.main-nav li ul li.sfhover {
180
  -moz-border-radius: 3px;
181
  -webkit-border-radius: 3px;
182
  }
183
+
184
  #wp-admin-bar ul li ul li:hover ul li a {
185
  color: #eee;
186
  }
187
+
188
  #wp-admin-bar ul li ul li ul li:hover a {
189
  color: #fff;
190
  }
191
+
192
  #wp-admin-bar ul li:hover ul,
193
  #wp-admin-bar ul li ul li:hover ul,
194
  #wp-admin-bar ul li.sfhover ul,
195
  #wp-admin-bar ul li ul li.sfhover ul {
196
  left: auto;
197
  }
198
+
199
  #wp-admin-bar ul li.align-right:hover ul {
200
  right: 0;
201
  }
202
+
203
  #wp-admin-bar ul li:hover ul ul,
204
  #wp-admin-bar li.sfhover ul li ul {
205
  left: -999em;
210
  float: left;
211
  margin-right: 8px;
212
  }
213
+
214
  #wp-admin-bar span.activity {
215
  display: block;
216
  margin-left: 34px;
217
  padding: 0;
218
  }
219
+
220
  #wp-admin-bar ul.author-list li a {
221
  height: 17px;
222
  }
223
+
224
  #wp-admin-bar ul li#bp-adminbar-notifications-menu a span {
225
  padding: 0 6px;
226
  margin-left: 2px;
230
  -webkit-border-radius: 3px;
231
  border-radius: 3px;
232
  }
233
+
234
  #wp-admin-bar-user-info img.avatar {
235
  height: 64px;
236
  width: 64px;
bp-core/css/buddybar.min.css CHANGED
@@ -1 +1 @@
1
- #admin-bar-logo,#wp-admin-bar li a{font-size:11px;text-decoration:none}#wp-admin-bar ul li ul a,#wp-admin-bar ul li ul li:hover ul li a{color:#eee}#wp-admin-bar ul li ul li ul li:hover a,#wp-admin-bar ul li ul li:hover a{color:#fff}body:not(.wp-admin){padding-top:25px!important}#wp-admin-bar{position:fixed;top:0;left:0;height:25px;font-size:11px;width:100%;z-index:9999}#wp-admin-bar .padder{position:relative;padding:0;width:100%;margin:0 auto;background:url(../images/60pc_black.png);height:25px}body#bp-default #wp-admin-bar .padder{max-width:1250px}#wp-admin-bar *{z-index:999}#wp-admin-bar div#admin-bar-logo{position:absolute;top:5px;left:10px}#wp-admin-bar a img,#wp-admin-bar li.alt{border:none}#wp-admin-bar li{list-style:none;margin:0;padding:0;line-height:100%;text-align:left}#wp-admin-bar li a{padding:7px 15px;color:#eee}#wp-admin-bar li.no-arrow a{padding-right:15px}#wp-admin-bar ul li ul li a span{display:none}#wp-admin-bar li.hover,#wp-admin-bar li:hover{position:static}#admin-bar-logo{float:left;font-weight:700;padding:5px 8px;margin:0;color:#fff}body#bp-default #admin-bar-logo{padding:2px 8px}#wp-admin-bar ul{margin:0;list-style:none;line-height:1;cursor:pointer;height:auto;padding:0}#wp-admin-bar ul li{padding:0 11px 0 0;float:left;position:relative;background:url(../images/admin-menu-arrow.gif) 88% 53% no-repeat}#wp-admin-bar ul li.no-arrow{background:0 0;padding-right:0}#wp-admin-bar ul li ul li{background-image:none;float:left;width:174px;margin:0}#wp-admin-bar ul li.align-right{position:absolute;right:0}#wp-admin-bar ul li a{display:block}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li.sfhover,#wp-admin-bar ul.main-nav li:hover{background-color:#333}#wp-admin-bar ul li ul{position:absolute;width:185px;left:-999em;margin-left:0;background:#333;border:1px solid #222;-moz-box-shadow:0 4px 8px rgba(0,0,0,.1);-webkit-box-shadow:0 4px 8px rgba(0,0,0,.1);-moz-border-radius:3px;-webkit-border-radius:0 0 3px 3px;-moz-border-radius-topleft:0;-moz-border-radius-topright:0}#wp-admin-bar ul li>ul{border-top:none}#wp-admin-bar ul li div.admin-bar-clear{clear:both}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li ul li:hover{background-color:#222}#wp-admin-bar ul li ul ul{margin:-25px 0 0 184px;-moz-border-radius:3px;-webkit-border-radius:3px}#wp-admin-bar ul li ul li.sfhover ul,#wp-admin-bar ul li ul li:hover ul,#wp-admin-bar ul li.sfhover ul,#wp-admin-bar ul li:hover ul{left:auto}#wp-admin-bar ul li.align-right:hover ul{right:0}#wp-admin-bar li.sfhover ul li ul,#wp-admin-bar ul li:hover ul ul{left:-999em}#wp-admin-bar img.avatar{float:left;margin-right:8px}#wp-admin-bar span.activity{display:block;margin-left:34px;padding:0}#wp-admin-bar ul.author-list li a{height:17px}#wp-admin-bar ul li#bp-adminbar-notifications-menu a span{padding:0 6px;margin-left:2px;background:#fff;color:#000;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}
1
+ body:not(.wp-admin){padding-top:25px!important}#wp-admin-bar{position:fixed;top:0;left:0;height:25px;font-size:11px;width:100%;z-index:9999}#wp-admin-bar .padder{position:relative;padding:0;width:100%;margin:0 auto;background:url(../images/60pc_black.png);height:25px}body#bp-default #wp-admin-bar .padder{max-width:1250px}#wp-admin-bar *{z-index:999}#wp-admin-bar div#admin-bar-logo{position:absolute;top:5px;left:10px}#wp-admin-bar a img{border:none}#wp-admin-bar li{list-style:none;margin:0;padding:0;line-height:1;text-align:left}#wp-admin-bar li a{padding:7px 15px;color:#eee;text-decoration:none;font-size:11px}#wp-admin-bar li.alt{border:none}#wp-admin-bar li.no-arrow a{padding-right:15px}#wp-admin-bar ul li ul li a span{display:none}#wp-admin-bar li.hover,#wp-admin-bar li:hover{position:static}#admin-bar-logo{float:left;font-weight:700;font-size:11px;padding:5px 8px;margin:0;text-decoration:none;color:#fff}body#bp-default #admin-bar-logo{padding:2px 8px}#wp-admin-bar ul{margin:0;list-style:none;line-height:1;cursor:pointer;height:auto;padding:0}#wp-admin-bar ul li{padding:0;float:left;position:relative;background:url(../images/admin-menu-arrow.gif) 88% 53% no-repeat;padding-right:11px}#wp-admin-bar ul li.no-arrow{background:0 0;padding-right:0}#wp-admin-bar ul li ul li{background-image:none}#wp-admin-bar ul li.align-right{position:absolute;right:0}#wp-admin-bar ul li a{display:block}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li.sfhover,#wp-admin-bar ul.main-nav li:hover{background-color:#333}#wp-admin-bar ul li ul{position:absolute;width:185px;left:-999em;margin-left:0;background:#333;border:1px solid #222;-moz-box-shadow:0 4px 8px rgba(0,0,0,.1);-webkit-box-shadow:0 4px 8px rgba(0,0,0,.1);-moz-border-radius:3px;-webkit-border-radius:3px;-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0}#wp-admin-bar ul li>ul{border-top:none}#wp-admin-bar ul li ul a{color:#eee}#wp-admin-bar ul li ul li{float:left;width:174px;margin:0}#wp-admin-bar ul li ul li:hover a{color:#fff}#wp-admin-bar ul li div.admin-bar-clear{clear:both}#wp-admin-bar ul.main-nav li ul li.sfhover,#wp-admin-bar ul.main-nav li ul li:hover{background-color:#222}#wp-admin-bar ul li ul ul{margin:-25px 0 0 184px;-moz-border-radius:3px;-webkit-border-radius:3px}#wp-admin-bar ul li ul li:hover ul li a{color:#eee}#wp-admin-bar ul li ul li ul li:hover a{color:#fff}#wp-admin-bar ul li ul li.sfhover ul,#wp-admin-bar ul li ul li:hover ul,#wp-admin-bar ul li.sfhover ul,#wp-admin-bar ul li:hover ul{left:auto}#wp-admin-bar ul li.align-right:hover ul{right:0}#wp-admin-bar li.sfhover ul li ul,#wp-admin-bar ul li:hover ul ul{left:-999em}#wp-admin-bar img.avatar{float:left;margin-right:8px}#wp-admin-bar span.activity{display:block;margin-left:34px;padding:0}#wp-admin-bar ul.author-list li a{height:17px}#wp-admin-bar ul li#bp-adminbar-notifications-menu a span{padding:0 6px;margin-left:2px;background:#fff;color:#000;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#wp-admin-bar-user-info img.avatar{height:64px;width:64px}
bp-core/deprecated/1.2.php CHANGED
@@ -14,7 +14,7 @@
14
  * @since 1.0.0
15
  * @deprecated 1.2.0
16
  *
17
- * @param array $args
18
  *
19
  * @return object $activity The activity/activities object
20
  */
14
  * @since 1.0.0
15
  * @deprecated 1.2.0
16
  *
17
+ * @param string|array $args
18
  *
19
  * @return object $activity The activity/activities object
20
  */
bp-core/deprecated/1.5.php CHANGED
@@ -398,19 +398,6 @@ function bp_core_delete_notifications_for_user_by_item_id( $user_id, $item_id, $
398
  return BP_Core_Notification::delete_for_user_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id );
399
  }
400
 
401
- /**
402
- * In BP 1.5, these functions were renamed for greater consistency
403
- * @deprecated 1.5.0
404
- */
405
- function bp_forum_directory_permalink() {
406
- _deprecated_function( __FUNCTION__, '1.5', 'bp_forums_directory_permalink()' );
407
- bp_forums_directory_permalink();
408
- }
409
- function bp_get_forum_directory_permalink() {
410
- _deprecated_function( __FUNCTION__, '1.5', 'bp_get_forums_directory_permalink()' );
411
- return bp_get_forums_directory_permalink();
412
- }
413
-
414
  /**
415
  * Last used by core in BP 1.1. The markup was merged into DTheme's header.php template.
416
  * @deprecated 1.5.0
@@ -508,7 +495,7 @@ function bp_dtheme_deprecated() {
508
  * @deprecated No longer required.
509
  * @param string $oldvalue Previous value of get_option( 'page_on_front' )
510
  * @param string $oldvalue New value of get_option( 'page_on_front' )
511
- * @return bool|string
512
  * @since 1.2.0
513
  */
514
  function bp_dtheme_page_on_front_update( $oldvalue, $newvalue ) {
398
  return BP_Core_Notification::delete_for_user_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id );
399
  }
400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  /**
402
  * Last used by core in BP 1.1. The markup was merged into DTheme's header.php template.
403
  * @deprecated 1.5.0
495
  * @deprecated No longer required.
496
  * @param string $oldvalue Previous value of get_option( 'page_on_front' )
497
  * @param string $oldvalue New value of get_option( 'page_on_front' )
498
+ * @return false|string
499
  * @since 1.2.0
500
  */
501
  function bp_dtheme_page_on_front_update( $oldvalue, $newvalue ) {
bp-core/deprecated/1.6.php CHANGED
@@ -265,8 +265,13 @@ if ( !function_exists( 'bp_dtheme_register_actions' ) ) :
265
 
266
  // For each of the problematic hooks, exit at the very end of execution
267
  foreach( $actions as $action ) {
268
- add_action( 'wp_ajax_' . $action, create_function( '', 'exit;' ), 9999 );
269
- add_action( 'wp_ajax_nopriv_' . $action, create_function( '', 'exit;' ), 9999 );
 
 
 
 
 
270
  }
271
  }
272
  add_action( 'after_setup_theme', 'bp_die_legacy_ajax_callbacks', 20 );
265
 
266
  // For each of the problematic hooks, exit at the very end of execution
267
  foreach( $actions as $action ) {
268
+ add_action( 'wp_ajax_' . $action, function() {
269
+ exit;
270
+ }, 9999 );
271
+
272
+ add_action( 'wp_ajax_nopriv_' . $action, function() {
273
+ exit;
274
+ }, 9999 );
275
  }
276
  }
277
  add_action( 'after_setup_theme', 'bp_die_legacy_ajax_callbacks', 20 );
bp-core/deprecated/1.7.php CHANGED
@@ -74,7 +74,7 @@ function bp_get_plugin_sidebar() {
74
  * step. It also means that the themes won't show for selection on other blogs.
75
  *
76
  * @deprecated 1.7.0
77
- * @package BuddyPress Core
78
  */
79
  function bp_core_allow_default_theme( $themes ) {
80
  _deprecated_function( __FUNCTION__, '1.7' );
74
  * step. It also means that the themes won't show for selection on other blogs.
75
  *
76
  * @deprecated 1.7.0
77
+ * @return array
78
  */
79
  function bp_core_allow_default_theme( $themes ) {
80
  _deprecated_function( __FUNCTION__, '1.7' );
bp-core/deprecated/1.9.php CHANGED
@@ -19,14 +19,14 @@ defined( 'ABSPATH' ) || exit;
19
  * bp_notifications_add_notification() instead.
20
  *
21
  * @since 1.0.0
22
- * @param string $item_id
23
- * @param int $user_id
24
- * @param string $component_name
25
- * @param string $component_action
26
- * @param string $secondary_item_id
27
- * @param string $date_notified
28
- * @param int $is_new
29
- * @return boolean True on success, false on failure.
30
  */
31
  function bp_core_add_notification( $item_id, $user_id, $component_name, $component_action, $secondary_item_id = 0, $date_notified = false, $is_new = 1 ) {
32
 
@@ -62,8 +62,9 @@ function bp_core_add_notification( $item_id, $user_id, $component_name, $compone
62
  * bp_notifications_delete_notification() instead.
63
  *
64
  * @since 1.0.0
 
65
  * @param int $id ID of notification.
66
- * @return boolean True on success, false on failure.
67
  */
68
  function bp_core_delete_notification( $id ) {
69
 
@@ -86,7 +87,7 @@ function bp_core_delete_notification( $id ) {
86
  *
87
  * @since 1.0.0
88
  * @param int $id ID of notification.
89
- * @return BP_Core_Notification
90
  */
91
  function bp_core_get_notification( $id ) {
92
 
@@ -140,7 +141,7 @@ function bp_core_get_notifications_for_user( $user_id, $format = 'string' ) {
140
  * @param int $user_id
141
  * @param string $component_name
142
  * @param string $component_action
143
- * @return boolean True on success, false on failure.
144
  */
145
  function bp_core_delete_notifications_by_type( $user_id, $component_name, $component_action ) {
146
 
@@ -165,10 +166,11 @@ function bp_core_delete_notifications_by_type( $user_id, $component_name, $compo
165
  * bp_notifications_delete_notifications_by_item_id() instead.
166
  *
167
  * @since 1.0.0
 
168
  * @param int $user_id
169
  * @param string $component_name
170
  * @param string $component_action
171
- * @return boolean True on success, false on failure.
172
  */
173
  function bp_core_delete_notifications_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id = false ) {
174
 
@@ -190,9 +192,10 @@ function bp_core_delete_notifications_by_item_id( $user_id, $item_id, $component
190
  * bp_notifications_delete_all_notifications_by_type() instead.
191
  *
192
  * @since 1.0.0
193
- * @param int $user_id
194
- * @param string $component_name
195
- * @param string $component_action
 
196
  * @return boolean True on success, false on failure.
197
  */
198
  function bp_core_delete_all_notifications_by_type( $item_id, $component_name, $component_action = false, $secondary_item_id = false ) {
@@ -220,7 +223,7 @@ function bp_core_delete_all_notifications_by_type( $item_id, $component_name, $c
220
  * @param int $user_id
221
  * @param string $component_name
222
  * @param string $component_action
223
- * @return boolean True on success, false on failure.
224
  */
225
  function bp_core_delete_notifications_from_user( $user_id, $component_name, $component_action ) {
226
 
19
  * bp_notifications_add_notification() instead.
20
  *
21
  * @since 1.0.0
22
+ * @param string $item_id
23
+ * @param int $user_id
24
+ * @param string $component_name
25
+ * @param string $component_action
26
+ * @param int $secondary_item_id
27
+ * @param false|string $date_notified
28
+ * @param int $is_new
29
+ * @return int|boolean True on success, false on failure.
30
  */
31
  function bp_core_add_notification( $item_id, $user_id, $component_name, $component_action, $secondary_item_id = 0, $date_notified = false, $is_new = 1 ) {
32
 
62
  * bp_notifications_delete_notification() instead.
63
  *
64
  * @since 1.0.0
65
+ *
66
  * @param int $id ID of notification.
67
+ * @return false|integer True on success, false on failure.
68
  */
69
  function bp_core_delete_notification( $id ) {
70
 
87
  *
88
  * @since 1.0.0
89
  * @param int $id ID of notification.
90
+ * @return false|BP_Core_Notification
91
  */
92
  function bp_core_get_notification( $id ) {
93
 
141
  * @param int $user_id
142
  * @param string $component_name
143
  * @param string $component_action
144
+ * @return false|int True on success, false on failure.
145
  */
146
  function bp_core_delete_notifications_by_type( $user_id, $component_name, $component_action ) {
147
 
166
  * bp_notifications_delete_notifications_by_item_id() instead.
167
  *
168
  * @since 1.0.0
169
+ *
170
  * @param int $user_id
171
  * @param string $component_name
172
  * @param string $component_action
173
+ * @return false|int True on success, false on failure.
174
  */
175
  function bp_core_delete_notifications_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id = false ) {
176
 
192
  * bp_notifications_delete_all_notifications_by_type() instead.
193
  *
194
  * @since 1.0.0
195
+ *
196
+ * @param int $user_id
197
+ * @param string $component_name
198
+ * @param false|string $component_action
199
  * @return boolean True on success, false on failure.
200
  */
201
  function bp_core_delete_all_notifications_by_type( $item_id, $component_name, $component_action = false, $secondary_item_id = false ) {
223
  * @param int $user_id
224
  * @param string $component_name
225
  * @param string $component_action
226
+ * @return false|int True on success, false on failure.
227
  */
228
  function bp_core_delete_notifications_from_user( $user_id, $component_name, $component_action ) {
229
 
bp-core/deprecated/2.1.php CHANGED
@@ -36,7 +36,7 @@ function bp_core_register_deprecated_styles() {
36
  * @since 1.0.0
37
  * @deprecated 2.1.0
38
  *
39
- * @return bool|null Returns false on failure. Otherwise echoes the menu item.
40
  */
41
  function bp_adminbar_blogs_menu() {
42
 
@@ -131,7 +131,7 @@ function bp_admin_sanitize_callback_force_buddybar( $value = false ) {
131
  /**
132
  * Wrapper function for rendering the BuddyBar.
133
  *
134
- * @return bool|null Returns false if the BuddyBar is disabled.
135
  * @deprecated 2.1.0
136
  */
137
  function bp_core_admin_bar() {
@@ -179,7 +179,7 @@ function bp_adminbar_logo() {
179
  *
180
  * @deprecated 2.1.0
181
  *
182
- * @return bool|null Returns false if the current user is logged in.
183
  */
184
  function bp_adminbar_login_menu() {
185
 
@@ -200,7 +200,7 @@ function bp_adminbar_login_menu() {
200
  *
201
  * @deprecated 2.1.0
202
  *
203
- * @return bool|null Returns false on failure.
204
  */
205
  function bp_adminbar_account_menu() {
206
  $bp = buddypress();
36
  * @since 1.0.0
37
  * @deprecated 2.1.0
38
  *
39
+ * @return false|null Returns false on failure. Otherwise echoes the menu item.
40
  */
41
  function bp_adminbar_blogs_menu() {
42
 
131
  /**
132
  * Wrapper function for rendering the BuddyBar.
133
  *
134
+ * @return false|null Returns false if the BuddyBar is disabled.
135
  * @deprecated 2.1.0
136
  */
137
  function bp_core_admin_bar() {
179
  *
180
  * @deprecated 2.1.0
181
  *
182
+ * @return false|null Returns false if the current user is logged in.
183
  */
184
  function bp_adminbar_login_menu() {
185
 
200
  *
201
  * @deprecated 2.1.0
202
  *
203
+ * @return false|null Returns false on failure.
204
  */
205
  function bp_adminbar_account_menu() {
206
  $bp = buddypress();
bp-core/deprecated/2.5.php CHANGED
@@ -62,7 +62,7 @@ function bp_core_deprecated_email_filters( $value, $property, $transform, $email
62
  'settings-verify-email-change',
63
  );
64
 
65
- remove_filter( 'bp_email_get_property', 'bp_core_deprecated_email_filters', 20, 4 );
66
  $email_type = $email->get( 'type' );
67
  $tokens = $email->get( 'tokens' );
68
  add_filter( 'bp_email_get_property', 'bp_core_deprecated_email_filters', 20, 4 );
@@ -701,7 +701,7 @@ function bp_core_deprecated_email_actions( $delivery_status, $email ) {
701
  'settings-verify-email-change',
702
  );
703
 
704
- remove_action( 'bp_send_email_success', 'bp_core_deprecated_email_actions', 20, 2 );
705
  $email_content = $email->get( 'content' );
706
  $email_subject = $email->get( 'subject' );
707
  $email_type = $email->get( 'type' );
@@ -914,7 +914,7 @@ function bp_blogs_transition_activity_status( $new_status, $old_status, $comment
914
  * @param int $comment_id ID of the comment being recorded.
915
  * @param bool|string $is_approved Optional. The $is_approved value passed to
916
  * the 'comment_post' action. Default: true.
917
- * @return bool|object Returns false on failure, the comment object on success.
918
  */
919
  function bp_blogs_record_comment( $comment_id, $is_approved = true ) {
920
  _deprecated_function( __FUNCTION__, '2.5.0', 'bp_activity_post_type_comment()' );
62
  'settings-verify-email-change',
63
  );
64
 
65
+ remove_filter( 'bp_email_get_property', 'bp_core_deprecated_email_filters', 20 );
66
  $email_type = $email->get( 'type' );
67
  $tokens = $email->get( 'tokens' );
68
  add_filter( 'bp_email_get_property', 'bp_core_deprecated_email_filters', 20, 4 );
701
  'settings-verify-email-change',
702
  );
703
 
704
+ remove_action( 'bp_send_email_success', 'bp_core_deprecated_email_actions', 20 );
705
  $email_content = $email->get( 'content' );
706
  $email_subject = $email->get( 'subject' );
707
  $email_type = $email->get( 'type' );
914
  * @param int $comment_id ID of the comment being recorded.
915
  * @param bool|string $is_approved Optional. The $is_approved value passed to
916
  * the 'comment_post' action. Default: true.
917
+ * @return bool|object|null Returns false on failure, the comment object on success.
918
  */
919
  function bp_blogs_record_comment( $comment_id, $is_approved = true ) {
920
  _deprecated_function( __FUNCTION__, '2.5.0', 'bp_activity_post_type_comment()' );
bp-core/deprecated/2.7.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated functions.
4
+ *
5
+ * @deprecated 2.7.0
6
+ */
7
+
8
+ // Exit if accessed directly.
9
+ defined( 'ABSPATH' ) || exit;
10
+
11
+ /**
12
+ * Get the DB schema to use for BuddyPress components.
13
+ *
14
+ * @since 1.1.0
15
+ * @deprecated 2.7.0
16
+ *
17
+ * @return string The default database character-set, if set.
18
+ */
19
+ function bp_core_set_charset() {
20
+ global $wpdb;
21
+
22
+ _deprecated_function( __FUNCTION__, '2.7', 'wpdb::get_charset_collate()' );
23
+
24
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
25
+ return !empty( $wpdb->charset ) ? "DEFAULT CHARACTER SET {$wpdb->charset}" : '';
26
+ }
bp-core/deprecated/2.8.php ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated functions.
4
+ *
5
+ * @deprecated 2.8.0
6
+ */
7
+
8
+ // Exit if accessed directly.
9
+ defined( 'ABSPATH' ) || exit;
10
+
11
+ /**
12
+ * Determines whether the current installation is running PHP 5.3 or greater.
13
+ *
14
+ * BuddyPress 2.8 introduces a minimum PHP requirement of PHP 5.3.
15
+ *
16
+ * @since 2.7.0
17
+ * @deprecated 2.8.0
18
+ *
19
+ * @return bool
20
+ */
21
+ function bp_core_admin_is_running_php53_or_greater() {
22
+ _deprecated_function( __FUNCTION__, '2.8' );
23
+ return version_compare( PHP_VERSION, '5.3', '>=' );
24
+ }
25
+
26
+ /**
27
+ * Replaces WP's default update notice on plugins.php with an error message, when site is not running PHP 5.3 or greater.
28
+ *
29
+ * Originally hooked to 'load-plugins.php' with priority 100.
30
+ *
31
+ * @since 2.7.0
32
+ * @deprecated 2.8.0
33
+ */
34
+ function bp_core_admin_maybe_disable_update_row_for_php53_requirement() {
35
+ if ( bp_core_admin_is_running_php53_or_greater() ) {
36
+ return;
37
+ }
38
+
39
+ $loader = basename( constant( 'BP_PLUGIN_DIR' ) ) . '/bp-loader.php';
40
+
41
+ remove_action( "after_plugin_row_{$loader}", 'wp_plugin_update_row', 10 );
42
+ add_action( "after_plugin_row_{$loader}", 'bp_core_admin_php52_plugin_row', 10, 2 );
43
+ }
44
+
45
+ /**
46
+ * On the "Dashboard > Updates" page, remove BuddyPress from plugins list if PHP < 5.3.
47
+ *
48
+ * Originally hooked to 'load-update-core.php'.
49
+ *
50
+ * @since 2.7.0
51
+ * @deprecated 2.8.0
52
+ */
53
+ function bp_core_admin_maybe_remove_from_update_core() {
54
+ if ( bp_core_admin_is_running_php53_or_greater() ) {
55
+ return;
56
+ }
57
+
58
+ // Add filter to remove BP from the update plugins list.
59
+ add_filter( 'site_transient_update_plugins', 'bp_core_admin_remove_buddypress_from_update_transient' );
60
+ }
61
+
62
+ /**
63
+ * Filter callback to remove BuddyPress from the update plugins list.
64
+ *
65
+ * Attached to the 'site_transient_update_plugins' filter.
66
+ *
67
+ * @since 2.7.0
68
+ * @deprecated 2.8.0
69
+ *
70
+ * @param object $retval Object of plugin update data.
71
+ * @return object
72
+ */
73
+ function bp_core_admin_remove_buddypress_from_update_transient( $retval ) {
74
+ _deprecated_function( __FUNCTION__, '2.8' );
75
+
76
+ $loader = basename( constant( 'BP_PLUGIN_DIR' ) ) . '/bp-loader.php';
77
+
78
+ // Remove BP from update plugins list.
79
+ if ( isset( $retval->response[ $loader ] ) ) {
80
+ unset( $retval->response[ $loader ] );
81
+ }
82
+
83
+ return $retval;
84
+ }
85
+
86
+ /**
87
+ * Outputs a replacement for WP's default update notice, when site is not running PHP 5.3 or greater.
88
+ *
89
+ * When we see that a site is not running PHP 5.3 and is trying to update to
90
+ * BP 2.8+, we replace WP's default notice with our own, which both provides a
91
+ * link to our documentation of the requirement, and removes the link that
92
+ * allows a single plugin to be updated.
93
+ *
94
+ * @since 2.7.0
95
+ * @deprecated 2.8.0
96
+ *
97
+ * @param string $file Plugin filename. buddypress/bp-loader.php.
98
+ * @param array $plugin_data Data about the BuddyPress plugin, as returned by the
99
+ * plugins API.
100
+ */
101
+ function bp_core_admin_php52_plugin_row( $file, $plugin_data ) {
102
+ _deprecated_function( __FUNCTION__, '2.8' );
103
+
104
+ if ( is_multisite() && ! is_network_admin() ) {
105
+ return;
106
+ }
107
+
108
+ $current = get_site_transient( 'update_plugins' );
109
+ if ( ! isset( $current->response[ $file ] ) ) {
110
+ return false;
111
+ }
112
+
113
+ $response = $current->response[ $file ];
114
+
115
+ // No need to do this if update is for < BP 2.8.
116
+ if ( version_compare( $response->new_version, '2.8', '<' ) ) {
117
+ return false;
118
+ }
119
+
120
+ $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
121
+
122
+ if ( is_network_admin() ) {
123
+ $active_class = is_plugin_active_for_network( $file ) ? ' active' : '';
124
+ } else {
125
+ $active_class = is_plugin_active( $file ) ? ' active' : '';
126
+ }
127
+
128
+ // WP 4.6 uses different markup for the plugin row notice.
129
+ if ( function_exists( 'wp_get_ext_types' ) ) {
130
+ $p = '<p>%s</p>';
131
+
132
+ // WP < 4.6.
133
+ } else {
134
+ $p = '%s';
135
+
136
+ // Ugh.
137
+ $active_class .= ' not-shiny';
138
+ }
139
+
140
+ echo '<tr class="plugin-update-tr' . $active_class . '" id="' . esc_attr( $response->slug . '-update' ) . '" data-slug="' . esc_attr( $response->slug ) . '" data-plugin="' . esc_attr( $file ) . '"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message inline notice notice-error notice-alt">';
141
+
142
+ printf( $p,
143
+ esc_html__( 'A BuddyPress update is available, but your system is not compatible.', 'buddypress' ) . ' ' .
144
+ sprintf( __( 'See <a href="%s">the Codex guide</a> for more information.', 'buddypress' ), 'https://codex.buddypress.org/getting-started/buddypress-2-8-will-require-php-5-3/' )
145
+ );
146
+
147
+ echo '</div></td></tr>';
148
+
149
+ /*
150
+ * JavaScript to disable the bulk upgrade checkbox.
151
+ * See WP_Plugins_List_Table::single_row().
152
+ */
153
+ $checkbox_id = 'checkbox_' . md5( $plugin_data['Name'] );
154
+ echo "<script type='text/javascript'>document.getElementById('$checkbox_id').disabled = true;</script>";
155
+ }
156
+
157
+ /**
158
+ * Add an admin notice to installations that are not running PHP 5.3+.
159
+ *
160
+ * @since 2.7.0
161
+ * @deprecated 2.8.0
162
+ */
163
+ function bp_core_admin_php53_admin_notice() {
164
+ _deprecated_function( __FUNCTION__, '2.8' );
165
+
166
+ // If not on the Plugins page, stop now.
167
+ if ( 'plugins' !== get_current_screen()->parent_base ) {
168
+ return;
169
+ }
170
+
171
+ if ( ! current_user_can( 'update_core' ) ) {
172
+ return;
173
+ }
174
+
175
+ if ( bp_core_admin_is_running_php53_or_greater() ) {
176
+ return;
177
+ }
178
+
179
+ $notice_id = 'bp28-php53';
180
+ if ( bp_get_option( "bp-dismissed-notice-$notice_id" ) ) {
181
+ return;
182
+ }
183
+
184
+ $bp = buddypress();
185
+ $min = bp_core_get_minified_asset_suffix();
186
+
187
+ wp_enqueue_script(
188
+ 'bp-dismissible-admin-notices',
189
+ "{$bp->plugin_url}bp-core/admin/js/dismissible-admin-notices{$min}.js",
190
+ array( 'jquery' ),
191
+ bp_get_version(),
192
+ true
193
+ );
194
+ ?>
195
+
196
+ <div id="message" class="error notice is-dismissible bp-is-dismissible" data-noticeid="<?php echo esc_attr( $notice_id ); ?>">
197
+ <p><strong><?php esc_html_e( 'Your site is not ready for BuddyPress 2.8.', 'buddypress' ); ?></strong></p>
198
+ <p><?php printf( esc_html__( 'Your site is currently running PHP version %s, while BuddyPress 2.8 will require version 5.3+.', 'buddypress' ), esc_html( phpversion() ) ); ?> <?php printf( __( 'See <a href="%s">the Codex guide</a> for more information.', 'buddypress' ), 'https://codex.buddypress.org/getting-started/buddypress-2-8-will-require-php-5-3/' ); ?></p>
199
+ <?php wp_nonce_field( "bp-dismissible-notice-$notice_id", "bp-dismissible-nonce-$notice_id" ); ?>
200
+ </div>
201
+ <?php
202
+ }
203
+
bp-core/deprecated/2.9.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated functions.
4
+ *
5
+ * @deprecated 2.9.0
6
+ */
7
+
8
+ // Exit if accessed directly.
9
+ defined( 'ABSPATH' ) || exit;
10
+
11
+ /**
12
+ * Replace default WordPress avatars with BP avatars, if available.
13
+ *
14
+ * See 'get_avatar' filter description in wp-includes/pluggable.php.
15
+ *
16
+ * @since 1.1.0
17
+ * @since 2.4.0 Added $args parameter to coincide with WordPress 4.2.0.
18
+ *
19
+ * @param string $avatar The avatar path passed to 'get_avatar'.
20
+ * @param int|string|object $user A user ID, email address, or comment object.
21
+ * @param int $size Size of the avatar image ('thumb' or 'full').
22
+ * @param string $default URL to a default image to use if no avatar is available.
23
+ * @param string $alt Alternate text to use in image tag. Default: ''.
24
+ * @param array $args Arguments passed to get_avatar_data(), after processing.
25
+ * @return string BP avatar path, if found; else the original avatar path.
26
+ */
27
+ function bp_core_fetch_avatar_filter( $avatar, $user, $size, $default, $alt = '', $args = array() ) {
28
+ _deprecated_function( __FUNCTION__, '2.9' );
29
+ return $avatar;
30
+ }
bp-core/deprecated/3.0.php ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated functions.
4
+ *
5
+ * @deprecated 2.9.0
6
+ */
7
+
8
+ // Exit if accessed directly.
9
+ defined( 'ABSPATH' ) || exit;
10
+
11
+ /**
12
+ * Check whether bbPress plugin-powered Group Forums are enabled.
13
+ *
14
+ * @since 1.6.0
15
+ * @since 3.0.0 $default argument's default value changed from true to false.
16
+ * @deprecated 3.0.0 No longer used in core, but supported for third-party code.
17
+ *
18
+ * @param bool $default Optional. Fallback value if not found in the database.
19
+ * Default: false.
20
+ * @return bool True if group forums are active, otherwise false.
21
+ */
22
+ function bp_is_group_forums_active( $default = false ) {
23
+ _deprecated_function( __FUNCTION__, '3.0', 'groups_get_group( $id )->enable_forum' );
24
+
25
+ $is_active = function_exists( 'bbp_is_group_forums_active' ) ? bbp_is_group_forums_active( $default ) : $default;
26
+
27
+ /**
28
+ * Filters whether or not bbPress plugin-powered Group Forums are enabled.
29
+ *
30
+ * @since 1.6.0
31
+ * @deprecated 3.0.0 No longer used in core, but supported for third-party code.
32
+ *
33
+ * @param bool $value Whether or not bbPress plugin-powered Group Forums are enabled.
34
+ */
35
+ return (bool) apply_filters( 'bp_is_group_forums_active', $is_active );
36
+ }
37
+
38
+ /**
39
+ * Is this a user's forums page?
40
+ *
41
+ * Eg http://example.com/members/joe/forums/ (or a subpage thereof).
42
+ *
43
+ * @since 1.5.0
44
+ * @deprecated 3.0.0 No longer used in core, but supported for third-party code.
45
+ *
46
+ * @return false
47
+ */
48
+ function bp_is_user_forums() {
49
+ _deprecated_function( __FUNCTION__, '3.0', 'legacy forum support removed' );
50
+ return false;
51
+ }
52
+
53
+ /**
54
+ * Is the current page a group's (legacy bbPress) forum page?
55
+ *
56
+ * @since 1.1.0
57
+ * @since 3.0.0 Always returns false.
58
+ * @deprecated 3.0.0 No longer used in core, but supported for custom theme templates.
59
+ *
60
+ * @return bool
61
+ */
62
+ function bp_is_group_forum() {
63
+ _deprecated_function( __FUNCTION__, '3.0', 'legacy forum support removed' );
64
+ return false;
65
+ }
66
+
67
+
68
+ /**
69
+ * Output a 'New Topic' button for a group.
70
+ *
71
+ * @since 1.2.7
72
+ * @deprecated 3.0.0 No longer used in core, but supported for third-party code.
73
+ *
74
+ * @param BP_Groups_Group|bool $group The BP Groups_Group object if passed, boolean false if not passed.
75
+ */
76
+ function bp_group_new_topic_button( $group = false ) {
77
+ _deprecated_function( __FUNCTION__, '3.0', 'legacy forum support removed' );
78
+ }
79
+
80
+ /**
81
+ * Return a 'New Topic' button for a group.
82
+ *
83
+ * @since 1.2.7
84
+ * @deprecated 3.0.0 No longer used in core, but supported for third-party code.
85
+ *
86
+ * @param BP_Groups_Group|bool $group The BP Groups_Group object if passed, boolean false if not passed.
87
+ *
88
+ * @return false
89
+ */
90
+ function bp_get_group_new_topic_button( $group = false ) {
91
+ _deprecated_function( __FUNCTION__, '3.0', 'legacy forum support removed' );
92
+ return false;
93
+ }
94
+
95
+ /**
96
+ * Catch a "Mark as Spammer/Not Spammer" click from the toolbar.
97
+ *
98
+ * When a site admin selects "Mark as Spammer/Not Spammer" from the admin menu
99
+ * this action will fire and mark or unmark the user and their blogs as spam.
100
+ * Must be a site admin for this function to run.
101
+ *
102
+ * Note: no longer used in the current state. See the Settings component.
103
+ *
104
+ * @since 1.1.0
105
+ * @since 1.6.0 No longer used, unhooked.
106
+ * @since 3.0.0 Formally marked as deprecated.
107
+ *
108
+ * @param int $user_id Optional. User ID to mark as spam. Defaults to displayed user.
109
+ */
110
+ function bp_core_action_set_spammer_status( $user_id = 0 ) {
111
+ _deprecated_function( __FUNCTION__, '3.0' );
112
+
113
+ // Only super admins can currently spam users (but they can't spam
114
+ // themselves).
115
+ if ( ! is_super_admin() || bp_is_my_profile() ) {
116
+ return;
117
+ }
118
+
119
+ // Use displayed user if it's not yourself.
120
+ if ( empty( $user_id ) )
121
+ $user_id = bp_displayed_user_id();
122
+
123
+ if ( bp_is_current_component( 'admin' ) && ( in_array( bp_current_action(), array( 'mark-spammer', 'unmark-spammer' ) ) ) ) {
124
+
125
+ // Check the nonce.
126
+ check_admin_referer( 'mark-unmark-spammer' );
127
+
128
+ // To spam or not to spam.
129
+ $status = bp_is_current_action( 'mark-spammer' ) ? 'spam' : 'ham';
130
+
131
+ // The heavy lifting.
132
+ bp_core_process_spammer_status( $user_id, $status );
133
+
134
+ // Add feedback message. @todo - Error reporting.
135
+ if ( 'spam' == $status ) {
136
+ bp_core_add_message( __( 'User marked as spammer. Spam users are visible only to site admins.', 'buddypress' ) );
137
+ } else {
138
+ bp_core_add_message( __( 'User removed as spammer.', 'buddypress' ) );
139
+ }
140
+
141
+ // Deprecated. Use bp_core_process_spammer_status.
142
+ $is_spam = 'spam' == $status;
143
+ do_action( 'bp_core_action_set_spammer_status', bp_displayed_user_id(), $is_spam );
144
+
145
+ // Redirect back to where we came from.
146
+ bp_core_redirect( wp_get_referer() );
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Process user deletion requests.
152
+ *
153
+ * Note: no longer used in the current state. See the Settings component.
154
+ *
155
+ * @since 1.1.0
156
+ * @since 1.6.0 No longer used, unhooked.
157
+ * @since 3.0.0 Formally marked as deprecated.
158
+ */
159
+ function bp_core_action_delete_user() {
160
+ _deprecated_function( __FUNCTION__, '3.0' );
161
+
162
+ if ( !bp_current_user_can( 'bp_moderate' ) || bp_is_my_profile() || !bp_displayed_user_id() )
163
+ return false;
164
+
165
+ if ( bp_is_current_component( 'admin' ) && bp_is_current_action( 'delete-user' ) ) {
166
+
167
+ // Check the nonce.
168
+ check_admin_referer( 'delete-user' );
169
+
170
+ $errors = false;
171
+ do_action( 'bp_core_before_action_delete_user', $errors );
172
+
173
+ if ( bp_core_delete_account( bp_displayed_user_id() ) ) {
174
+ bp_core_add_message( sprintf( __( '%s has been deleted from the system.', 'buddypress' ), bp_get_displayed_user_fullname() ) );
175
+ } else {
176
+ bp_core_add_message( sprintf( __( 'There was an error deleting %s from the system. Please try again.', 'buddypress' ), bp_get_displayed_user_fullname() ), 'error' );
177
+ $errors = true;
178
+ }
179
+
180
+ do_action( 'bp_core_action_delete_user', $errors );
181
+
182
+ if ( $errors )
183
+ bp_core_redirect( bp_displayed_user_domain() );
184
+ else
185
+ bp_core_redirect( bp_loggedin_user_domain() );
186
+ }
187
+ }
bp-core/js/avatar.min.js CHANGED
@@ -1 +1 @@
1
- window.bp=window.bp||{},function(a,b){"undefined"!=typeof BP_Uploader&&(bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.Avatar={start:function(){var a=this;this.removeLegacyUI(),this.views=new Backbone.Collection,this.jcropapi={},this.warning=null,this.setupNav(),this.avatars=bp.Uploader.filesUploaded,this.Attachment=new Backbone.Model,bp.Uploader.filesQueue.on("reset",this.cropView,this),b("body.wp-admin").on("tb_unload","#TB_window",function(){a.resetViews()}),b("body.wp-admin").on("click",".bp-xprofile-avatar-user-edit",function(){a.resetViews()})},removeLegacyUI:function(){b("#avatar-upload-form").length?(b("#avatar-upload").remove(),b("#avatar-upload-form p").remove()):b("#group-settings-form").length?(b("#group-settings-form p").each(function(a){0!==a&&b(this).remove()}),b("#delete-group-avatar-button").length&&b("#delete-group-avatar-button").remove()):b("#group-create-body").length?(b(".main-column p #file").remove(),b(".main-column p #upload").remove()):b("#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin").length&&b("#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin").remove()},setView:function(a){switch(_.isUndefined(this.views.models)||_.each(this.views.models,function(a){a.get("view").remove()},this),this.views.reset(),_.isUndefined(this.avatars)||this.avatars.reset(),_.isEmpty(this.jcropapi)||(this.jcropapi.destroy(),this.jcropapi={}),a){case"upload":this.uploaderView();break;case"delete":this.deleteView()}},resetViews:function(){this.nav.trigger("bp-avatar-view:changed","upload"),_.each(this.navItems.models,function(a){"upload"===a.id?a.set({active:1}):a.set({active:0})})},setupNav:function(){var a,b,c=this;this.navItems=new Backbone.Collection,_.each(BP_Uploader.settings.nav,function(d,e){_.isObject(d)&&(b=0,0===e&&(a=d.id,b=1),c.navItems.add({id:d.id,name:d.caption,href:"#",active:b,hide:_.isUndefined(d.hide)?0:d.hide}))}),this.nav=new bp.Views.Nav({collection:this.navItems}),this.nav.inject(".bp-avatar-nav"),this.setView(a),this.nav.on("bp-avatar-view:changed",_.bind(this.setView,this))},uploaderView:function(){bp.Uploader.filesQueue.on("add",this.uploadProgress,this);var a=new bp.Views.Uploader;this.views.add({id:"upload",view:a}),a.inject(".bp-avatar")},uploadProgress:function(){var a=new bp.Views.uploaderStatus({collection:bp.Uploader.filesQueue});_.isUndefined(this.views.get("status"))?this.views.add({id:"status",view:a}):this.views.set({id:"status",view:a}),a.inject(".bp-avatar-status")},cropView:function(){var a;if(!_.isEmpty(this.avatars.models)){_.isUndefined(this.views.get("status"))||(a=this.views.get("status"),a.get("view").remove(),this.views.remove({id:"status",view:a}));var b=new bp.Views.Avatars({collection:this.avatars});this.views.add({id:"crop",view:b}),b.inject(".bp-avatar")}},setAvatar:function(a){var c,d=this;_.isUndefined(this.views.get("crop"))||(_.isEmpty(this.jcropapi)||(this.jcropapi.destroy(),this.jcropapi={}),c=this.views.get("crop"),c.get("view").remove(),this.views.remove({id:"crop",view:c})),bp.ajax.post("bp_avatar_set",{json:!0,original_file:a.get("url"),crop_w:a.get("w"),crop_h:a.get("h"),crop_x:a.get("x"),crop_y:a.get("y"),item_id:a.get("item_id"),object:a.get("object"),type:_.isUndefined(a.get("type"))?"crop":a.get("type"),nonce:a.get("nonces").set}).done(function(c){var e=new bp.Views.AvatarStatus({value:BP_Uploader.strings.feedback_messages[c.feedback_code],type:"success"});d.views.add({id:"status",view:e}),e.inject(".bp-avatar-status"),b("."+a.get("object")+"-"+c.item_id+"-avatar").each(function(){b(this).prop("src",c.avatar)}),bp.Avatar.navItems.get("delete").set({hide:0}),d.Attachment.set(_.extend(_.pick(a.attributes,["object","item_id"]),{url:c.avatar,action:"uploaded"}))}).fail(function(a){var b=BP_Uploader.strings.default_error;_.isUndefined(a)||(b=BP_Uploader.strings.feedback_messages[a.feedback_code]);var c=new bp.Views.AvatarStatus({value:b,type:"error"});d.views.add({id:"status",view:c}),c.inject(".bp-avatar-status")})},deleteView:function(){var a=new Backbone.Model(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,"object","item_id","nonces")),b=new bp.Views.DeleteAvatar({model:a});this.views.add({id:"delete",view:b}),b.inject(".bp-avatar")},deleteAvatar:function(a){var c,d=this;_.isUndefined(this.views.get("delete"))||(c=this.views.get("delete"),c.get("view").remove(),this.views.remove({id:"delete",view:c})),bp.ajax.post("bp_avatar_delete",{json:!0,item_id:a.get("item_id"),object:a.get("object"),nonce:a.get("nonces").remove}).done(function(c){var e=new bp.Views.AvatarStatus({value:BP_Uploader.strings.feedback_messages[c.feedback_code],type:"success"});d.views.add({id:"status",view:e}),e.inject(".bp-avatar-status"),b("."+a.get("object")+"-"+c.item_id+"-avatar").each(function(){b(this).prop("src",c.avatar)}),bp.Avatar.navItems.get("delete").set({active:0,hide:1}),d.Attachment.set(_.extend(_.pick(a.attributes,["object","item_id"]),{url:c.avatar,action:"deleted"}))}).fail(function(a){var b=BP_Uploader.strings.default_error;_.isUndefined(a)||(b=BP_Uploader.strings.feedback_messages[a.feedback_code]);var c=new bp.Views.AvatarStatus({value:b,type:"error"});d.views.add({id:"status",view:c}),c.inject(".bp-avatar-status")})},removeWarning:function(){_.isNull(this.warning)||this.warning.remove()},displayWarning:function(a){this.removeWarning(),this.warning=new bp.Views.uploaderWarning({value:a}),this.warning.inject(".bp-avatar-status")}},bp.Views.Nav=bp.View.extend({tagName:"ul",className:"avatar-nav-items",events:{"click .bp-avatar-nav-item":"toggleView"},initialize:function(){var a=_.findWhere(this.collection.models,{id:"delete"});1!==a.get("hide")&&bp.Avatar.displayWarning(BP_Uploader.strings.has_avatar_warning),_.each(this.collection.models,this.addNavItem,this),this.collection.on("change:hide",this.showHideNavItem,this)},addNavItem:function(a){1!==a.get("hide")&&this.views.add(new bp.Views.NavItem({model:a}))},showHideNavItem:function(a){var b=null;_.each(this.views._views[""],function(c){1===c.model.get("hide")&&c.remove(),a.get("id")===c.model.get("id")&&(b=!0)}),_.isBoolean(b)||this.addNavItem(a)},toggleView:function(a){a.preventDefault(),bp.Avatar.removeWarning();var c=b(a.target).data("nav");_.each(this.collection.models,function(a){a.id===c?(a.set({active:1}),this.trigger("bp-avatar-view:changed",a.id)):a.set({active:0})},this)}}),bp.Views.NavItem=bp.View.extend({tagName:"li",className:"avatar-nav-item",template:bp.template("bp-avatar-nav"),initialize:function(){1===this.model.get("active")&&(this.el.className+=" current"),this.el.id+="bp-avatar-"+this.model.get("id"),this.model.on("change:active",this.setCurrentNav,this)},setCurrentNav:function(a){1===a.get("active")?this.$el.addClass("current"):this.$el.removeClass("current")}}),bp.Views.Avatars=bp.View.extend({className:"items",initialize:function(){_.each(this.collection.models,this.addItemView,this)},addItemView:function(a){var b={full_h:150,full_w:150};_.isUndefined(BP_Uploader.settings.crop.full_h)||_.isUndefined(BP_Uploader.settings.crop.full_w)||(b.full_h=BP_Uploader.settings.crop.full_h,b.full_w=BP_Uploader.settings.crop.full_w),a.set(_.extend(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,"object","item_id","nonces"),b)),this.views.add(new bp.Views.Avatar({model:a}))}}),bp.Views.Avatar=bp.View.extend({className:"item",template:bp.template("bp-avatar-item"),events:{"click .avatar-crop-submit":"cropAvatar"},initialize:function(){_.defaults(this.options,{full_h:BP_Uploader.settings.crop.full_h,full_w:BP_Uploader.settings.crop.full_w,aspectRatio:1}),!1!==this.model.get("feedback")&&bp.Avatar.displayWarning(this.model.get("feedback")),this.on("ready",this.initCropper)},initCropper:function(){var a,c,d,e,f,g,h=this,i=this.$el.find("#avatar-to-crop img"),j=this.$el.width(),k={};_.isUndefined(this.options.full_h)||_.isUndefined(this.options.full_w)||(this.options.aspectRatio=this.options.full_w/this.options.full_h),k.w=this.model.get("width"),k.h=this.model.get("height"),this.options.full_w+k.w+20<j&&(b("#avatar-to-crop").addClass("adjust"),this.$el.find(".avatar-crop-management").addClass("adjust")),k.h<=k.w?(a=Math.round(k.h/4),f=g=Math.round(k.h/2),c=f+a,d=(k.w-g)/2,e=g+d):(d=Math.round(k.w/4),f=g=Math.round(k.w/2),e=g+d,a=(k.h-f)/2,c=f+a),i.Jcrop({onChange:_.bind(h.showPreview,h),onSelect:_.bind(h.showPreview,h),aspectRatio:h.options.aspectRatio,setSelect:[d,a,e,c]},function(){bp.Avatar.jcropapi=this})},cropAvatar:function(a){a.preventDefault(),bp.Avatar.setAvatar(this.model)},showPreview:function(a){if(a.w&&a.h&&parseInt(a.w,10)>0){var c=this.options.full_w,d=this.options.full_h,e=c/a.w,f=d/a.h;this.model.set({x:a.x,y:a.y,w:a.w,h:a.h}),b("#avatar-crop-preview").css({maxWidth:"none",width:Math.round(e*this.model.get("width"))+"px",height:Math.round(f*this.model.get("height"))+"px",marginLeft:"-"+Math.round(e*this.model.get("x"))+"px",marginTop:"-"+Math.round(f*this.model.get("y"))+"px"})}}}),bp.Views.AvatarStatus=bp.View.extend({tagName:"p",className:"updated",id:"bp-avatar-feedback",initialize:function(){this.el.className+=" "+this.options.type,this.value=this.options.value},render:function(){return this.$el.html(this.value),this}}),bp.Views.DeleteAvatar=bp.View.extend({tagName:"div",id:"bp-delete-avatar-container",template:bp.template("bp-avatar-delete"),events:{"click #bp-delete-avatar":"deleteAvatar"},deleteAvatar:function(a){a.preventDefault(),bp.Avatar.deleteAvatar(this.model)}}),bp.Avatar.start())}(bp,jQuery);
1
+ window.bp=window.bp||{},function(e,t){"undefined"!=typeof BP_Uploader&&(bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.Avatar={start:function(){var e=this;this.removeLegacyUI(),this.views=new Backbone.Collection,this.jcropapi={},this.warning=null,this.setupNav(),this.avatars=bp.Uploader.filesUploaded,this.Attachment=new Backbone.Model,bp.Uploader.filesQueue.on("reset",this.cropView,this),t("body.wp-admin").on("tb_unload","#TB_window",function(){e.resetViews()}),t("body.wp-admin").on("click",".bp-xprofile-avatar-user-edit",function(){e.resetViews()})},removeLegacyUI:function(){t("#avatar-upload-form").length?(t("#avatar-upload").remove(),t("#avatar-upload-form p").remove()):t("#group-settings-form").length?(t("#group-settings-form p").each(function(e){0!==e&&t(this).remove()}),t("#delete-group-avatar-button").length&&t("#delete-group-avatar-button").remove()):t("#group-create-body").length?(t(".main-column p #file").remove(),t(".main-column p #upload").remove()):t("#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin").length&&t("#bp_xprofile_user_admin_avatar a.bp-xprofile-avatar-user-admin").remove()},setView:function(e){switch(_.isUndefined(this.views.models)||_.each(this.views.models,function(e){e.get("view").remove()},this),this.views.reset(),_.isUndefined(this.avatars)||this.avatars.reset(),_.isEmpty(this.jcropapi)||(this.jcropapi.destroy(),this.jcropapi={}),e){case"upload":this.uploaderView();break;case"delete":this.deleteView()}},resetViews:function(){this.nav.trigger("bp-avatar-view:changed","upload"),_.each(this.navItems.models,function(e){"upload"===e.id?e.set({active:1}):e.set({active:0})})},setupNav:function(){var e,t,a=this;this.navItems=new Backbone.Collection,_.each(BP_Uploader.settings.nav,function(i,s){_.isObject(i)&&(t=0,0===s&&(e=i.id,t=1),a.navItems.add({id:i.id,name:i.caption,href:"#",active:t,hide:_.isUndefined(i.hide)?0:i.hide}))}),this.nav=new bp.Views.Nav({collection:this.navItems}),this.nav.inject(".bp-avatar-nav"),this.setView(e),this.nav.on("bp-avatar-view:changed",_.bind(this.setView,this))},uploaderView:function(){bp.Uploader.filesQueue.on("add",this.uploadProgress,this);var e=new bp.Views.Uploader;this.views.add({id:"upload",view:e}),e.inject(".bp-avatar")},uploadProgress:function(){var e=new bp.Views.uploaderStatus({collection:bp.Uploader.filesQueue});_.isUndefined(this.views.get("status"))?this.views.add({id:"status",view:e}):this.views.set({id:"status",view:e}),e.inject(".bp-avatar-status")},cropView:function(){var e;if(!_.isEmpty(this.avatars.models)){_.isUndefined(this.views.get("status"))||((e=this.views.get("status")).get("view").remove(),this.views.remove({id:"status",view:e}));var t=new bp.Views.Avatars({collection:this.avatars});this.views.add({id:"crop",view:t}),t.inject(".bp-avatar")}},setAvatar:function(e){var a,i=this;_.isUndefined(this.views.get("crop"))||(_.isEmpty(this.jcropapi)||(this.jcropapi.destroy(),this.jcropapi={}),(a=this.views.get("crop")).get("view").remove(),this.views.remove({id:"crop",view:a})),bp.ajax.post("bp_avatar_set",{json:!0,original_file:e.get("url"),crop_w:e.get("w"),crop_h:e.get("h"),crop_x:e.get("x"),crop_y:e.get("y"),item_id:e.get("item_id"),object:e.get("object"),type:_.isUndefined(e.get("type"))?"crop":e.get("type"),nonce:e.get("nonces").set}).done(function(a){var s=new bp.Views.AvatarStatus({value:BP_Uploader.strings.feedback_messages[a.feedback_code],type:"success"});i.views.add({id:"status",view:s}),s.inject(".bp-avatar-status"),t("."+e.get("object")+"-"+a.item_id+"-avatar").each(function(){t(this).prop("src",a.avatar)}),bp.Avatar.navItems.get("delete").set({hide:0}),i.Attachment.set(_.extend(_.pick(e.attributes,["object","item_id"]),{url:a.avatar,action:"uploaded"}))}).fail(function(e){var t=BP_Uploader.strings.default_error;_.isUndefined(e)||(t=BP_Uploader.strings.feedback_messages[e.feedback_code]);var a=new bp.Views.AvatarStatus({value:t,type:"error"});i.views.add({id:"status",view:a}),a.inject(".bp-avatar-status")})},deleteView:function(){var e=new Backbone.Model(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,"object","item_id","nonces")),t=new bp.Views.DeleteAvatar({model:e});this.views.add({id:"delete",view:t}),t.inject(".bp-avatar")},deleteAvatar:function(e){var a,i=this;_.isUndefined(this.views.get("delete"))||((a=this.views.get("delete")).get("view").remove(),this.views.remove({id:"delete",view:a})),bp.ajax.post("bp_avatar_delete",{json:!0,item_id:e.get("item_id"),object:e.get("object"),nonce:e.get("nonces").remove}).done(function(a){var s=new bp.Views.AvatarStatus({value:BP_Uploader.strings.feedback_messages[a.feedback_code],type:"success"});i.views.add({id:"status",view:s}),s.inject(".bp-avatar-status"),t("."+e.get("object")+"-"+a.item_id+"-avatar").each(function(){t(this).prop("src",a.avatar)}),bp.Avatar.navItems.get("delete").set({active:0,hide:1}),i.Attachment.set(_.extend(_.pick(e.attributes,["object","item_id"]),{url:a.avatar,action:"deleted"}))}).fail(function(e){var t=BP_Uploader.strings.default_error;_.isUndefined(e)||(t=BP_Uploader.strings.feedback_messages[e.feedback_code]);var a=new bp.Views.AvatarStatus({value:t,type:"error"});i.views.add({id:"status",view:a}),a.inject(".bp-avatar-status")})},removeWarning:function(){_.isNull(this.warning)||this.warning.remove()},displayWarning:function(e){this.removeWarning(),this.warning=new bp.Views.uploaderWarning({value:e}),this.warning.inject(".bp-avatar-status")}},bp.Views.Nav=bp.View.extend({tagName:"ul",className:"avatar-nav-items",events:{"click .bp-avatar-nav-item":"toggleView"},initialize:function(){1!==_.findWhere(this.collection.models,{id:"delete"}).get("hide")&&bp.Avatar.displayWarning(BP_Uploader.strings.has_avatar_warning),_.each(this.collection.models,this.addNavItem,this),this.collection.on("change:hide",this.showHideNavItem,this)},addNavItem:function(e){1!==e.get("hide")&&this.views.add(new bp.Views.NavItem({model:e}))},showHideNavItem:function(e){var t=null;_.each(this.views._views[""],function(a){1===a.model.get("hide")&&a.remove(),e.get("id")===a.model.get("id")&&(t=!0)}),_.isBoolean(t)||this.addNavItem(e)},toggleView:function(e){e.preventDefault(),bp.Avatar.removeWarning();var a=t(e.target).data("nav");_.each(this.collection.models,function(e){e.id===a?(e.set({active:1}),this.trigger("bp-avatar-view:changed",e.id)):e.set({active:0})},this)}}),bp.Views.NavItem=bp.View.extend({tagName:"li",className:"avatar-nav-item",template:bp.template("bp-avatar-nav"),initialize:function(){1===this.model.get("active")&&(this.el.className+=" current"),this.el.id+="bp-avatar-"+this.model.get("id"),this.model.on("change:active",this.setCurrentNav,this)},setCurrentNav:function(e){1===e.get("active")?this.$el.addClass("current"):this.$el.removeClass("current")}}),bp.Views.Avatars=bp.View.extend({className:"items",initialize:function(){_.each(this.collection.models,this.addItemView,this)},addItemView:function(e){var t={full_h:150,full_w:150};_.isUndefined(BP_Uploader.settings.crop.full_h)||_.isUndefined(BP_Uploader.settings.crop.full_w)||(t.full_h=BP_Uploader.settings.crop.full_h,t.full_w=BP_Uploader.settings.crop.full_w),e.set(_.extend(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,"object","item_id","nonces"),t)),this.views.add(new bp.Views.Avatar({model:e}))}}),bp.Views.Avatar=bp.View.extend({className:"item",template:bp.template("bp-avatar-item"),events:{"click .avatar-crop-submit":"cropAvatar"},initialize:function(){_.defaults(this.options,{full_h:BP_Uploader.settings.crop.full_h,full_w:BP_Uploader.settings.crop.full_w,aspectRatio:1}),!1!==this.model.get("feedback")&&bp.Avatar.displayWarning(this.model.get("feedback")),this.on("ready",this.initCropper)},initCropper:function(){var e,a,i,s,n,o,r=this,d=this.$el.find("#avatar-to-crop img"),l=this.$el.width(),p={};_.isUndefined(this.options.full_h)||_.isUndefined(this.options.full_w)||(this.options.aspectRatio=this.options.full_w/this.options.full_h),p.w=this.model.get("width"),p.h=this.model.get("height"),this.options.full_w+p.w+20<l&&(t("#avatar-to-crop").addClass("adjust"),this.$el.find(".avatar-crop-management").addClass("adjust")),p.h<=p.w?(e=Math.round(p.h/4),a=(n=o=Math.round(p.h/2))+e,s=o+(i=(p.w-o)/2)):(i=Math.round(p.w/4),n=o=Math.round(p.w/2),s=o+i,a=n+(e=(p.h-n)/2)),d.Jcrop({onChange:_.bind(r.showPreview,r),onSelect:_.bind(r.showPreview,r),aspectRatio:r.options.aspectRatio,setSelect:[i,e,s,a]},function(){bp.Avatar.jcropapi=this})},cropAvatar:function(e){e.preventDefault(),bp.Avatar.setAvatar(this.model)},showPreview:function(e){if(e.w&&e.h&&parseInt(e.w,10)>0){var a=this.options.full_w,i=this.options.full_h,s=a/e.w,n=i/e.h;this.model.set({x:e.x,y:e.y,w:e.w,h:e.h}),t("#avatar-crop-preview").css({maxWidth:"none",width:Math.round(s*this.model.get("width"))+"px",height:Math.round(n*this.model.get("height"))+"px",marginLeft:"-"+Math.round(s*this.model.get("x"))+"px",marginTop:"-"+Math.round(n*this.model.get("y"))+"px"})}}}),bp.Views.AvatarStatus=bp.View.extend({tagName:"p",className:"updated",id:"bp-avatar-feedback",initialize:function(){this.el.className+=" "+this.options.type,this.value=this.options.value},render:function(){return this.$el.html(this.value),this}}),bp.Views.DeleteAvatar=bp.View.extend({tagName:"div",id:"bp-delete-avatar-container",template:bp.template("bp-avatar-delete"),events:{"click #bp-delete-avatar":"deleteAvatar"},deleteAvatar:function(e){e.preventDefault(),bp.Avatar.deleteAvatar(this.model)}}),bp.Avatar.start())}(bp,jQuery);
bp-core/js/bp-plupload.js CHANGED
@@ -97,6 +97,11 @@ window.bp = window.bp || {};
97
 
98
  } );
99
 
 
 
 
 
 
100
  // Init BuddyPress Uploader
101
  this.uploader.init();
102
 
@@ -270,7 +275,7 @@ window.bp = window.bp || {};
270
  'IO_ERROR': self.strings.io_error,
271
  'HTTP_ERROR': self.strings.http_error,
272
  'SECURITY_ERROR': self.strings.security_error,
273
- 'FILE_SIZE_ERROR': self.strings.file_exceeds_size_limit.replace( '%s' , pluploadError.file.name )
274
  };
275
 
276
  // Check for plupload errors.
97
 
98
  } );
99
 
100
+ // See https://core.trac.wordpress.org/ticket/37039
101
+ this.uploader.bind( 'postinit', function( up ) {
102
+ up.refresh();
103
+ });
104
+
105
  // Init BuddyPress Uploader
106
  this.uploader.init();
107
 
275
  'IO_ERROR': self.strings.io_error,
276
  'HTTP_ERROR': self.strings.http_error,
277
  'SECURITY_ERROR': self.strings.security_error,
278
+ 'FILE_SIZE_ERROR': self.strings.file_exceeds_size_limit.replace( '%s' , $( '<span />' ).text( pluploadError.file.name ).html() )
279
  };
280
 
281
  // Check for plupload errors.
bp-core/js/bp-plupload.min.js CHANGED
@@ -1 +1 @@
1
- window.wp=window.wp||{},window.bp=window.bp||{},function(a,b){"undefined"!=typeof BP_Uploader&&(_.extend(bp,_.pick(wp,"Backbone","ajax","template")),bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.Uploader={},bp.Uploader.uploader=function(){var a=this,c=-1!==navigator.userAgent.indexOf("Trident/")||-1!==navigator.userAgent.indexOf("MSIE ");return this.params=BP_Uploader.settings,this.strings=BP_Uploader.strings,this.supports={upload:this.params.browser.supported},this.supported=this.supports.upload,this.supported?(c||"flash"!==plupload.predictRuntime(this.params.defaults)||this.params.defaults.required_features&&this.params.defaults.required_features.hasOwnProperty("send_binary_string")||(this.params.defaults.required_features=this.params.defaults.required_features||{},this.params.defaults.required_features.send_binary_string=!0),this.uploader=new plupload.Uploader(this.params.defaults),this.uploader.bind("Init",function(c){var d=b("#"+a.params.defaults.container),e=b("#"+a.params.defaults.drop_element);"html4"===c.runtime&&(c.settings.multipart_params.html4=!0),"bp_avatar_upload"===c.settings.multipart_params.action&&(c.settings.multipart_params.bp_params.ui_available_width=d.width()),c.features.dragdrop&&!a.params.browser.mobile?(d.addClass("drag-drop"),e.bind("dragover.wp-uploader",function(){d.addClass("drag-over")}).bind("dragleave.wp-uploader, drop.wp-uploader",function(){d.removeClass("drag-over")})):(d.removeClass("drag-drop"),e.unbind(".wp-uploader"))}),this.uploader.init(),this.feedback=function(a,b,c){!_.isNull(c)&&c.item&&c.item.clear(),bp.Uploader.filesError.unshift({message:a,data:b,file:c})},this.uploader.bind("FilesAdded",function(c,d){var e=104857600,f=parseInt(c.settings.max_file_size,10),g=this;if(!c.settings.multi_selection&&d.length>1){for(var h in d)c.removeFile(d[h]);return void b(a).trigger("bp-uploader-warning",a.strings.unique_file_warning)}_.each(d,function(a){var b;plupload.FAILED!==a.status&&(f>e&&a.size>e&&"html5"!==c.runtime?g.uploadSizeError(c,a,!0):(b=_.extend({id:a.id,file:a,uploading:!0,date:new Date,filename:a.name},_.pick(a,"loaded","size","percent")),a.item=new bp.Models.File(b),bp.Uploader.filesQueue.add(a.item)))}),c.refresh(),c.start()}),this.uploader.bind("UploadProgress",function(a,b){b.item.set(_.pick(b,"loaded","percent"))}),this.uploader.bind("FileUploaded",function(b,c,d){var e=a.strings.default_error;try{d=JSON.parse(d.response)}catch(f){return a.feedback(e,f,c)}return!_.isObject(d)||_.isUndefined(d.success)?a.feedback(e,null,c):d.success?(_.each(["file","loaded","size","percent"],function(a){c.item.unset(a)}),c.item.set(_.extend(d.data,{uploading:!1})),void bp.Uploader.filesUploaded.add(c.item)):(d.data&&d.data.message&&(e=d.data.message),a.feedback(e,d.data,c))}),this.uploader.bind("BeforeUpload",function(c,d){b(a).trigger("bp-uploader-new-upload",c,d)}),this.uploader.bind("UploadComplete",function(c,d){b(a).trigger("bp-uploader-upload-complete",c,d),bp.Uploader.filesQueue.reset()}),void this.uploader.bind("Error",function(c,d){var e,f=a.strings.default_error,g={FAILED:a.strings.upload_failed,FILE_EXTENSION_ERROR:a.strings.invalid_filetype,IMAGE_FORMAT_ERROR:a.strings.not_an_image,IMAGE_MEMORY_ERROR:a.strings.image_memory_exceeded,IMAGE_DIMENSIONS_ERROR:a.strings.image_dimensions_exceeded,GENERIC_ERROR:a.strings.upload_failed,IO_ERROR:a.strings.io_error,HTTP_ERROR:a.strings.http_error,SECURITY_ERROR:a.strings.security_error,FILE_SIZE_ERROR:a.strings.file_exceeds_size_limit.replace("%s",d.file.name)};for(e in g)if(d.code===plupload[e]){f=g[e];break}b(a).trigger("bp-uploader-warning",f),c.refresh()})):void(BP_Uploader=void 0)},bp.Models.File=Backbone.Model.extend({file:{}}),b.extend(bp.Uploader,{filesQueue:new Backbone.Collection,filesUploaded:new Backbone.Collection,filesError:new Backbone.Collection}),bp.View=bp.Backbone.View.extend({inject:function(a){this.render(),b(a).html(this.el),this.views.ready()},prepare:function(){return!_.isUndefined(this.model)&&_.isFunction(this.model.toJSON)?this.model.toJSON():{}}}),bp.Views.Uploader=bp.View.extend({className:"bp-uploader-window",template:bp.template("upload-window"),defaults:_.pick(BP_Uploader.settings.defaults,"container","drop_element","browse_button"),initialize:function(){this.warnings=[],this.model=new Backbone.Model(this.defaults),this.on("ready",this.initUploader)},initUploader:function(){this.uploader=new bp.Uploader.uploader,b(this.uploader).on("bp-uploader-warning",_.bind(this.setWarning,this)),b(this.uploader).on("bp-uploader-new-upload",_.bind(this.resetWarning,this))},setWarning:function(a,b){if(!_.isUndefined(b)){var c=new bp.Views.uploaderWarning({value:b}).render();this.warnings.push(c),this.$el.after(c.el)}},resetWarning:function(){0!==this.warnings.length&&(_.each(this.warnings,function(a){a.remove()}),this.warnings=[])}}),bp.Views.uploaderWarning=bp.View.extend({tagName:"p",className:"warning",initialize:function(){this.value=this.options.value},render:function(){return this.$el.html(this.value),this}}),bp.Views.uploaderStatus=bp.View.extend({className:"files",initialize:function(){_.each(this.collection.models,this.addFile,this),this.collection.on("change:percent",this.progress,this),bp.Uploader.filesError.on("add",this.feedback,this)},addFile:function(a){this.views.add(new bp.Views.uploaderProgress({model:a}))},progress:function(a){_.isUndefined(a.get("percent"))||b("#"+a.get("id")+" .bp-progress .bp-bar").css("width",a.get("percent")+"%")},feedback:function(a){_.isUndefined(a.get("message"))||_.isUndefined(a.get("file"))||b("#"+a.get("file").id).html(a.get("message")).addClass("error")}}),bp.Views.uploaderProgress=bp.View.extend({className:"bp-uploader-progress",template:bp.template("progress-window")}))}(bp,jQuery);
1
+ window.wp=window.wp||{},window.bp=window.bp||{},function(e,i){"undefined"!=typeof BP_Uploader&&(_.extend(bp,_.pick(wp,"Backbone","ajax","template")),bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.Uploader={},bp.Uploader.uploader=function(){var e=this,t=-1!==navigator.userAgent.indexOf("Trident/")||-1!==navigator.userAgent.indexOf("MSIE ");this.params=BP_Uploader.settings,this.strings=BP_Uploader.strings,this.supports={upload:this.params.browser.supported},this.supported=this.supports.upload,this.supported?(t||"flash"!==plupload.predictRuntime(this.params.defaults)||this.params.defaults.required_features&&this.params.defaults.required_features.hasOwnProperty("send_binary_string")||(this.params.defaults.required_features=this.params.defaults.required_features||{},this.params.defaults.required_features.send_binary_string=!0),this.uploader=new plupload.Uploader(this.params.defaults),this.uploader.bind("Init",function(t){var s=i("#"+e.params.defaults.container),a=i("#"+e.params.defaults.drop_element);"html4"===t.runtime&&(t.settings.multipart_params.html4=!0),"bp_avatar_upload"===t.settings.multipart_params.action&&(t.settings.multipart_params.bp_params.ui_available_width=s.width()),t.features.dragdrop&&!e.params.browser.mobile?(s.addClass("drag-drop"),a.bind("dragover.wp-uploader",function(){s.addClass("drag-over")}).bind("dragleave.wp-uploader, drop.wp-uploader",function(){s.removeClass("drag-over")})):(s.removeClass("drag-drop"),a.unbind(".wp-uploader"))}),this.uploader.bind("postinit",function(e){e.refresh()}),this.uploader.init(),this.feedback=function(e,i,t){!_.isNull(t)&&t.item&&t.item.clear(),bp.Uploader.filesError.unshift({message:e,data:i,file:t})},this.uploader.bind("FilesAdded",function(t,s){var a=parseInt(t.settings.max_file_size,10),r=this;if(!t.settings.multi_selection&&s.length>1){for(var n in s)t.removeFile(s[n]);i(e).trigger("bp-uploader-warning",e.strings.unique_file_warning)}else _.each(s,function(e){var i;plupload.FAILED!==e.status&&(a>104857600&&e.size>104857600&&"html5"!==t.runtime?r.uploadSizeError(t,e,!0):(i=_.extend({id:e.id,file:e,uploading:!0,date:new Date,filename:e.name},_.pick(e,"loaded","size","percent")),e.item=new bp.Models.File(i),bp.Uploader.filesQueue.add(e.item)))}),t.refresh(),t.start()}),this.uploader.bind("UploadProgress",function(e,i){i.item.set(_.pick(i,"loaded","percent"))}),this.uploader.bind("FileUploaded",function(i,t,s){var a=e.strings.default_error;try{s=JSON.parse(s.response)}catch(i){return e.feedback(a,i,t)}return!_.isObject(s)||_.isUndefined(s.success)?e.feedback(a,null,t):s.success?(_.each(["file","loaded","size","percent"],function(e){t.item.unset(e)}),t.item.set(_.extend(s.data,{uploading:!1})),void bp.Uploader.filesUploaded.add(t.item)):(s.data&&s.data.message&&(a=s.data.message),e.feedback(a,s.data,t))}),this.uploader.bind("BeforeUpload",function(t,s){i(e).trigger("bp-uploader-new-upload",t,s)}),this.uploader.bind("UploadComplete",function(t,s){i(e).trigger("bp-uploader-upload-complete",t,s),bp.Uploader.filesQueue.reset()}),this.uploader.bind("Error",function(t,s){var a,r=e.strings.default_error,n={FAILED:e.strings.upload_failed,FILE_EXTENSION_ERROR:e.strings.invalid_filetype,IMAGE_FORMAT_ERROR:e.strings.not_an_image,IMAGE_MEMORY_ERROR:e.strings.image_memory_exceeded,IMAGE_DIMENSIONS_ERROR:e.strings.image_dimensions_exceeded,GENERIC_ERROR:e.strings.upload_failed,IO_ERROR:e.strings.io_error,HTTP_ERROR:e.strings.http_error,SECURITY_ERROR:e.strings.security_error,FILE_SIZE_ERROR:e.strings.file_exceeds_size_limit.replace("%s",i("<span />").text(s.file.name).html())};for(a in n)if(s.code===plupload[a]){r=n[a];break}i(e).trigger("bp-uploader-warning",r),t.refresh()})):BP_Uploader=void 0},bp.Models.File=Backbone.Model.extend({file:{}}),i.extend(bp.Uploader,{filesQueue:new Backbone.Collection,filesUploaded:new Backbone.Collection,filesError:new Backbone.Collection}),bp.View=bp.Backbone.View.extend({inject:function(e){this.render(),i(e).html(this.el),this.views.ready()},prepare:function(){return!_.isUndefined(this.model)&&_.isFunction(this.model.toJSON)?this.model.toJSON():{}}}),bp.Views.Uploader=bp.View.extend({className:"bp-uploader-window",template:bp.template("upload-window"),defaults:_.pick(BP_Uploader.settings.defaults,"container","drop_element","browse_button"),initialize:function(){this.warnings=[],this.model=new Backbone.Model(this.defaults),this.on("ready",this.initUploader)},initUploader:function(){this.uploader=new bp.Uploader.uploader,i(this.uploader).on("bp-uploader-warning",_.bind(this.setWarning,this)),i(this.uploader).on("bp-uploader-new-upload",_.bind(this.resetWarning,this))},setWarning:function(e,i){if(!_.isUndefined(i)){var t=new bp.Views.uploaderWarning({value:i}).render();this.warnings.push(t),this.$el.after(t.el)}},resetWarning:function(){0!==this.warnings.length&&(_.each(this.warnings,function(e){e.remove()}),this.warnings=[])}}),bp.Views.uploaderWarning=bp.View.extend({tagName:"p",className:"warning",initialize:function(){this.value=this.options.value},render:function(){return this.$el.html(this.value),this}}),bp.Views.uploaderStatus=bp.View.extend({className:"files",initialize:function(){_.each(this.collection.models,this.addFile,this),this.collection.on("change:percent",this.progress,this),bp.Uploader.filesError.on("add",this.feedback,this)},addFile:function(e){this.views.add(new bp.Views.uploaderProgress({model:e}))},progress:function(e){_.isUndefined(e.get("percent"))||i("#"+e.get("id")+" .bp-progress .bp-bar").css("width",e.get("percent")+"%")},feedback:function(e){_.isUndefined(e.get("message"))||_.isUndefined(e.get("file"))||i("#"+e.get("file").id).html(e.get("message")).addClass("error")}}),bp.Views.uploaderProgress=bp.View.extend({className:"bp-uploader-progress",template:bp.template("progress-window")}))}(bp,jQuery);
bp-core/js/confirm.js CHANGED
@@ -2,11 +2,11 @@
2
  /* global BP_Confirm */
3
 
4
  jQuery( document ).ready( function() {
5
- jQuery( 'a.confirm').click( function() {
6
  if ( confirm( BP_Confirm.are_you_sure ) ) {
7
  return true;
8
  } else {
9
  return false;
10
  }
11
- });
12
- });
2
  /* global BP_Confirm */
3
 
4
  jQuery( document ).ready( function() {
5
+ jQuery( '#buddypress' ).on( 'click', 'a.confirm', function() {
6
  if ( confirm( BP_Confirm.are_you_sure ) ) {
7
  return true;
8
  } else {
9
  return false;
10
  }
11
+ } );
12
+ } );
bp-core/js/confirm.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(){jQuery("a.confirm").click(function(){return confirm(BP_Confirm.are_you_sure)?!0:!1})});
1
+ jQuery(document).ready(function(){jQuery("#buddypress").on("click","a.confirm",function(){return!!confirm(BP_Confirm.are_you_sure)})});
bp-core/js/cover-image.min.js CHANGED
@@ -1 +1 @@
1
- window.bp=window.bp||{},function(a,b){"undefined"!=typeof BP_Uploader&&(bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.CoverImage={start:function(){this.views=new Backbone.Collection,this.warning=null,this.Attachment=new Backbone.Model,this.uploaderView(),this.displayWarning(BP_Uploader.strings.cover_image_warnings.dimensions),!0===BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image&&this.deleteView()},uploaderView:function(){bp.Uploader.filesQueue.on("add",this.uploadProgress,this);var a=new bp.Views.Uploader;this.views.add({id:"upload",view:a}),a.inject(".bp-cover-image")},uploadProgress:function(){var a=new bp.Views.coverImageUploadProgress({collection:bp.Uploader.filesQueue});_.isUndefined(this.views.get("status"))?this.views.add({id:"status",view:a}):this.views.set({id:"status",view:a}),a.inject(".bp-cover-image-status")},deleteView:function(){var a=new Backbone.Model(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,["object","item_id","nonces"]));if(_.isUndefined(this.views.get("delete"))){var b=new bp.Views.DeleteCoverImage({model:a});this.views.add({id:"delete",view:b}),b.inject(".bp-cover-image-manage")}},deleteCoverImage:function(a){var c,d=this;_.isUndefined(this.views.get("delete"))||(c=this.views.get("delete"),c.get("view").remove(),this.views.remove({id:"delete",view:c})),bp.ajax.post("bp_cover_image_delete",{json:!0,item_id:a.get("item_id"),object:a.get("object"),nonce:a.get("nonces").remove}).done(function(c){var e=new bp.Views.CoverImageStatus({value:BP_Uploader.strings.feedback_messages[c.feedback_code],type:"success"});d.views.add({id:"status",view:e}),e.inject(".bp-cover-image-status"),""===c.reset_url?b("#header-cover-image").css({"background-image":"none"}):b("#header-cover-image").css({"background-image":"url( "+c.reset_url+" )"}),BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image=!1,d.Attachment.set(_.extend(_.pick(a.attributes,["object","item_id"]),{url:c.reset_url,action:"deleted"}))}).fail(function(a){var b=BP_Uploader.strings.default_error;_.isUndefined(a)||(b=BP_Uploader.strings.feedback_messages[a.feedback_code]);var c=new bp.Views.CoverImageStatus({value:b,type:"error"});d.views.add({id:"status",view:c}),c.inject(".bp-cover-image-status"),bp.CoverImage.deleteView()})},removeWarning:function(){_.isNull(this.warning)||this.warning.remove()},displayWarning:function(a){this.removeWarning(),this.warning=new bp.Views.uploaderWarning({value:a}),this.warning.inject(".bp-cover-image-status")}},bp.Views.coverImageUploadProgress=bp.Views.uploaderStatus.extend({className:"files",initialize:function(){bp.Views.uploaderStatus.prototype.initialize.apply(this,arguments),this.collection.on("change:url",this.uploadResult,this)},uploadResult:function(a){var c,d;_.isUndefined(a.get("url"))||(0===a.get("feedback_code")?(c=BP_Uploader.strings.cover_image_warnings.dimensions,d="warning"):(c=BP_Uploader.strings.feedback_messages[a.get("feedback_code")],d="success"),this.views.set(".bp-uploader-progress",new bp.Views.CoverImageStatus({value:c,type:d})),b("#header-cover-image").css({"background-image":"url( "+a.get("url")+" )"}),bp.CoverImage.deleteView(),bp.CoverImage.Attachment.set(_.extend(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,["object","item_id"]),{url:a.get("url"),action:"uploaded"})))}}),bp.Views.CoverImageStatus=bp.View.extend({tagName:"p",className:"updated",id:"bp-cover-image-feedback",initialize:function(){this.el.className+=" "+this.options.type,this.value=this.options.value},render:function(){return this.$el.html(this.value),this}}),bp.Views.DeleteCoverImage=bp.View.extend({tagName:"div",id:"bp-delete-cover-image-container",template:bp.template("bp-cover-image-delete"),events:{"click #bp-delete-cover-image":"deleteCoverImage"},deleteCoverImage:function(a){a.preventDefault(),bp.CoverImage.deleteCoverImage(this.model)}}),bp.CoverImage.start())}(bp,jQuery);
1
+ window.bp=window.bp||{},function(e,i){"undefined"!=typeof BP_Uploader&&(bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.CoverImage={start:function(){this.views=new Backbone.Collection,this.warning=null,this.Attachment=new Backbone.Model,this.uploaderView(),this.displayWarning(BP_Uploader.strings.cover_image_warnings.dimensions),!0===BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image&&this.deleteView()},uploaderView:function(){bp.Uploader.filesQueue.on("add",this.uploadProgress,this);var e=new bp.Views.Uploader;this.views.add({id:"upload",view:e}),e.inject(".bp-cover-image")},uploadProgress:function(){var e=new bp.Views.coverImageUploadProgress({collection:bp.Uploader.filesQueue});_.isUndefined(this.views.get("status"))?this.views.add({id:"status",view:e}):this.views.set({id:"status",view:e}),e.inject(".bp-cover-image-status")},deleteView:function(){var e=new Backbone.Model(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,["object","item_id","nonces"]));if(_.isUndefined(this.views.get("delete"))){var i=new bp.Views.DeleteCoverImage({model:e});this.views.add({id:"delete",view:i}),i.inject(".bp-cover-image-manage")}},deleteCoverImage:function(e){var t,a=this;_.isUndefined(this.views.get("delete"))||((t=this.views.get("delete")).get("view").remove(),this.views.remove({id:"delete",view:t})),bp.ajax.post("bp_cover_image_delete",{json:!0,item_id:e.get("item_id"),object:e.get("object"),nonce:e.get("nonces").remove}).done(function(t){var s=new bp.Views.CoverImageStatus({value:BP_Uploader.strings.feedback_messages[t.feedback_code],type:"success"});a.views.add({id:"status",view:s}),s.inject(".bp-cover-image-status"),""===t.reset_url?i("#header-cover-image").css({"background-image":"none"}):i("#header-cover-image").css({"background-image":"url( "+t.reset_url+" )"}),BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image=!1,a.Attachment.set(_.extend(_.pick(e.attributes,["object","item_id"]),{url:t.reset_url,action:"deleted"}))}).fail(function(e){var i=BP_Uploader.strings.default_error;_.isUndefined(e)||(i=BP_Uploader.strings.feedback_messages[e.feedback_code]);var t=new bp.Views.CoverImageStatus({value:i,type:"error"});a.views.add({id:"status",view:t}),t.inject(".bp-cover-image-status"),bp.CoverImage.deleteView()})},removeWarning:function(){_.isNull(this.warning)||this.warning.remove()},displayWarning:function(e){this.removeWarning(),this.warning=new bp.Views.uploaderWarning({value:e}),this.warning.inject(".bp-cover-image-status")}},bp.Views.coverImageUploadProgress=bp.Views.uploaderStatus.extend({className:"files",initialize:function(){bp.Views.uploaderStatus.prototype.initialize.apply(this,arguments),this.collection.on("change:url",this.uploadResult,this)},uploadResult:function(e){var t,a;_.isUndefined(e.get("url"))||(0===e.get("feedback_code")?(t=BP_Uploader.strings.cover_image_warnings.dimensions,a="warning"):(t=BP_Uploader.strings.feedback_messages[e.get("feedback_code")],a="success"),this.views.set(".bp-uploader-progress",new bp.Views.CoverImageStatus({value:t,type:a})),i("#header-cover-image").css({"background-image":"url( "+e.get("url")+" )"}),bp.CoverImage.deleteView(),bp.CoverImage.Attachment.set(_.extend(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,["object","item_id"]),{url:e.get("url"),action:"uploaded"})))}}),bp.Views.CoverImageStatus=bp.View.extend({tagName:"p",className:"updated",id:"bp-cover-image-feedback",initialize:function(){this.el.className+=" "+this.options.type,this.value=this.options.value},render:function(){return this.$el.html(this.value),this}}),bp.Views.DeleteCoverImage=bp.View.extend({tagName:"div",id:"bp-delete-cover-image-container",template:bp.template("bp-cover-image-delete"),events:{"click #bp-delete-cover-image":"deleteCoverImage"},deleteCoverImage:function(e){e.preventDefault(),bp.CoverImage.deleteCoverImage(this.model)}}),bp.CoverImage.start())}(bp,jQuery);
bp-core/js/jquery-cookie.min.js DELETED
@@ -1 +0,0 @@
1
- !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}});
 
bp-core/js/jquery-query.min.js CHANGED
@@ -1 +1 @@
1
- function bp_get_querystring(a){var b=location.search.split(a+"=")[1];return b?decodeURIComponent(b.split("&")[0]):null}
1
+ function bp_get_querystring(n){var t=location.search.split(n+"=")[1];return t?decodeURIComponent(t.split("&")[0]):null}
bp-core/js/jquery-scroll-to.min.js DELETED
@@ -1 +0,0 @@
1
- !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){function b(b){return a.isFunction(b)||"object"==typeof b?b:{top:b,left:b}}var c=a.scrollTo=function(b,c,d){return a(window).scrollTo(b,c,d)};return c.defaults={axis:"xy",duration:parseFloat(a.fn.jquery)>=1.3?0:1,limit:!0},c.window=function(){return a(window)._scrollable()},a.fn._scrollable=function(){return this.map(function(){var b=this,c=!b.nodeName||-1!==a.inArray(b.nodeName.toLowerCase(),["iframe","#document","html","body"]);if(!c)return b;var d=(b.contentWindow||b).document||b.ownerDocument||b;return/webkit/i.test(navigator.userAgent)||"BackCompat"===d.compatMode?d.body:d.documentElement})},a.fn.scrollTo=function(d,e,f){return"object"==typeof e&&(f=e,e=0),"function"==typeof f&&(f={onAfter:f}),"max"===d&&(d=9e9),f=a.extend({},c.defaults,f),e=e||f.duration,f.queue=f.queue&&f.axis.length>1,f.queue&&(e/=2),f.offset=b(f.offset),f.over=b(f.over),this._scrollable().each(function(){function g(a){j.animate(l,e,f.easing,a&&function(){a.call(this,k,f)})}if(null!==d){var h,i=this,j=a(i),k=d,l={},m=j.is("html,body");switch(typeof k){case"number":case"string":if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(k)){k=b(k);break}if(k=m?a(k):a(k,this),!k.length)return;case"object":(k.is||k.style)&&(h=(k=a(k)).offset())}var n=a.isFunction(f.offset)&&f.offset(i,k)||f.offset;a.each(f.axis.split(""),function(a,b){var d="x"===b?"Left":"Top",e=d.toLowerCase(),o="scroll"+d,p=i[o],q=c.max(i,b);if(h)l[o]=h[e]+(m?0:p-j.offset()[e]),f.margin&&(l[o]-=parseInt(k.css("margin"+d))||0,l[o]-=parseInt(k.css("border"+d+"Width"))||0),l[o]+=n[e]||0,f.over[e]&&(l[o]+=k["x"===b?"width":"height"]()*f.over[e]);else{var r=k[e];l[o]=r.slice&&"%"===r.slice(-1)?parseFloat(r)/100*q:r}f.limit&&/^\d+$/.test(l[o])&&(l[o]=l[o]<=0?0:Math.min(l[o],q)),!a&&f.queue&&(p!==l[o]&&g(f.onAfterFirst),delete l[o])}),g(f.onAfter)}}).end()},c.max=function(b,c){var d="x"===c?"Width":"Height",e="scroll"+d;if(!a(b).is("html,body"))return b[e]-a(b)[d.toLowerCase()]();var f="client"+d,g=b.ownerDocument.documentElement,h=b.ownerDocument.body;return Math.max(g[e],h[e])-Math.min(g[f],h[f])},c});
 
bp-core/js/jquery.atwho.js DELETED
@@ -1,875 +0,0 @@
1
- /*! jquery.atwho - v0.5.2 %>
2
- * Copyright (c) 2014 chord.luo <chord.luo@gmail.com>;
3
- * homepage: http://ichord.github.com/At.js
4
- * Licensed MIT
5
- */
6
- (function (root, factory) {
7
- if (typeof define === 'function' && define.amd) {
8
- // AMD. Register as an anonymous module.
9
- define(["jquery"], function ($) {
10
- return (root.returnExportsGlobal = factory($));
11
- });
12
- } else if (typeof exports === 'object') {
13
- // Node. Does not work with strict CommonJS, but
14
- // only CommonJS-like enviroments that support module.exports,
15
- // like Node.
16
- module.exports = factory(require("jquery"));
17
- } else {
18
- factory(jQuery);
19
- }
20
- }(this, function ($) {
21
-
22
- var Api, App, Controller, DEFAULT_CALLBACKS, KEY_CODE, Model, View,
23
- __slice = [].slice;
24
-
25
- App = (function() {
26
- function App(inputor) {
27
- this.current_flag = null;
28
- this.controllers = {};
29
- this.alias_maps = {};
30
- this.$inputor = $(inputor);
31
- this.setIframe();
32
- this.listen();
33
- }
34
-
35
- App.prototype.createContainer = function(doc) {
36
- if ((this.$el = $("#atwho-container", doc)).length === 0) {
37
- return $(doc.body).append(this.$el = $("<div id='atwho-container'></div>"));
38
- }
39
- };
40
-
41
- App.prototype.setIframe = function(iframe, standalone) {
42
- var _ref;
43
- if (standalone == null) {
44
- standalone = false;
45
- }
46
- if (iframe) {
47
- this.window = iframe.contentWindow;
48
- this.document = iframe.contentDocument || this.window.document;
49
- this.iframe = iframe;
50
- } else {
51
- this.document = document;
52
- this.window = window;
53
- this.iframe = null;
54
- }
55
- if (this.iframeStandalone = standalone) {
56
- if ((_ref = this.$el) != null) {
57
- _ref.remove();
58
- }
59
- return this.createContainer(this.document);
60
- } else {
61
- return this.createContainer(document);
62
- }
63
- };
64
-
65
- App.prototype.controller = function(at) {
66
- var c, current, current_flag, _ref;
67
- if (this.alias_maps[at]) {
68
- current = this.controllers[this.alias_maps[at]];
69
- } else {
70
- _ref = this.controllers;
71
- for (current_flag in _ref) {
72
- c = _ref[current_flag];
73
- if (current_flag === at) {
74
- current = c;
75
- break;
76
- }
77
- }
78
- }
79
- if (current) {
80
- return current;
81
- } else {
82
- return this.controllers[this.current_flag];
83
- }
84
- };
85
-
86
- App.prototype.set_context_for = function(at) {
87
- this.current_flag = at;
88
- return this;
89
- };
90
-
91
- App.prototype.reg = function(flag, setting) {
92
- var controller, _base;
93
- controller = (_base = this.controllers)[flag] || (_base[flag] = new Controller(this, flag));
94
- if (setting.alias) {
95
- this.alias_maps[setting.alias] = flag;
96
- }
97
- controller.init(setting);
98
- return this;
99
- };
100
-
101
- App.prototype.listen = function() {
102
- return this.$inputor.on('keyup.atwhoInner', (function(_this) {
103
- return function(e) {
104
- return _this.on_keyup(e);
105
- };
106
- })(this)).on('keydown.atwhoInner', (function(_this) {
107
- return function(e) {
108
- return _this.on_keydown(e);
109
- };
110
- })(this)).on('scroll.atwhoInner', (function(_this) {
111
- return function(e) {
112
- var _ref;
113
- return (_ref = _this.controller()) != null ? _ref.view.hide(e) : void 0;
114
- };
115
- })(this)).on('blur.atwhoInner', (function(_this) {
116
- return function(e) {
117
- var c;
118
- if (c = _this.controller()) {
119
- return c.view.hide(e, c.get_opt("display_timeout"));
120
- }
121
- };
122
- })(this)).on('click.atwhoInner', (function(_this) {
123
- return function(e) {
124
- return _this.dispatch();
125
- };
126
- })(this));
127
- };
128
-
129
- App.prototype.shutdown = function() {
130
- var c, _, _ref;
131
- _ref = this.controllers;
132
- for (_ in _ref) {
133
- c = _ref[_];
134
- c.destroy();
135
- delete this.controllers[_];
136
- }
137
- this.$inputor.off('.atwhoInner');
138
- return this.$el.remove();
139
- };
140
-
141
- App.prototype.dispatch = function() {
142
- return $.map(this.controllers, (function(_this) {
143
- return function(c) {
144
- var delay;
145
- if (delay = c.get_opt('delay')) {
146
- clearTimeout(_this.delayedCallback);
147
- return _this.delayedCallback = setTimeout(function() {
148
- if (c.look_up()) {
149
- return _this.set_context_for(c.at);
150
- }
151
- }, delay);
152
- } else {
153
- if (c.look_up()) {
154
- return _this.set_context_for(c.at);
155
- }
156
- }
157
- };
158
- })(this));
159
- };
160
-
161
- App.prototype.on_keyup = function(e) {
162
- var _ref;
163
- switch (e.keyCode) {
164
- case KEY_CODE.ESC:
165
- e.preventDefault();
166
- if ((_ref = this.controller()) != null) {
167
- _ref.view.hide();
168
- }
169
- break;
170
- case KEY_CODE.DOWN:
171
- case KEY_CODE.UP:
172
- case KEY_CODE.CTRL:
173
- $.noop();
174
- break;
175
- case KEY_CODE.P:
176
- case KEY_CODE.N:
177
- if (!e.ctrlKey) {
178
- this.dispatch();
179
- }
180
- break;
181
- default:
182
- this.dispatch();
183
- }
184
- };
185
-
186
- App.prototype.on_keydown = function(e) {
187
- var view, _ref;
188
- view = (_ref = this.controller()) != null ? _ref.view : void 0;
189
- if (!(view && view.visible())) {
190
- return;
191
- }
192
- switch (e.keyCode) {
193
- case KEY_CODE.ESC:
194
- e.preventDefault();
195
- view.hide(e);
196
- break;
197
- case KEY_CODE.UP:
198
- e.preventDefault();
199
- view.prev();
200
- break;
201
- case KEY_CODE.DOWN:
202
- e.preventDefault();
203
- view.next();
204
- break;
205
- case KEY_CODE.P:
206
- if (!e.ctrlKey) {
207
- return;
208
- }
209
- e.preventDefault();
210
- view.prev();
211
- break;
212
- case KEY_CODE.N:
213
- if (!e.ctrlKey) {
214
- return;
215
- }
216
- e.preventDefault();
217
- view.next();
218
- break;
219
- case KEY_CODE.TAB:
220
- case KEY_CODE.ENTER:
221
- if (!view.visible()) {
222
- return;
223
- }
224
- e.preventDefault();
225
- view.choose(e);
226
- break;
227
- default:
228
- $.noop();
229
- }
230
- };
231
-
232
- return App;
233
-
234
- })();
235
-
236
- Controller = (function() {
237
- Controller.prototype.uid = function() {
238
- return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime());
239
- };
240
-
241
- function Controller(app, at) {
242
- this.app = app;
243
- this.at = at;
244
- this.$inputor = this.app.$inputor;
245
- this.id = this.$inputor[0].id || this.uid();
246
- this.setting = null;
247
- this.query = null;
248
- this.pos = 0;
249
- this.cur_rect = null;
250
- this.range = null;
251
- if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) {
252
- this.app.$el.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
253
- }
254
- this.model = new Model(this);
255
- this.view = new View(this);
256
- }
257
-
258
- Controller.prototype.init = function(setting) {
259
- this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
260
- this.view.init();
261
- return this.model.reload(this.setting.data);
262
- };
263
-
264
- Controller.prototype.destroy = function() {
265
- this.trigger('beforeDestroy');
266
- this.model.destroy();
267
- this.view.destroy();
268
- return this.$el.remove();
269
- };
270
-
271
- Controller.prototype.call_default = function() {
272
- var args, error, func_name;
273
- func_name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
274
- try {
275
- return DEFAULT_CALLBACKS[func_name].apply(this, args);
276
- } catch (_error) {
277
- error = _error;
278
- return $.error("" + error + " Or maybe At.js doesn't have function " + func_name);
279
- }
280
- };
281
-
282
- Controller.prototype.trigger = function(name, data) {
283
- var alias, event_name;
284
- if (data == null) {
285
- data = [];
286
- }
287
- data.push(this);
288
- alias = this.get_opt('alias');
289
- event_name = alias ? "" + name + "-" + alias + ".atwho" : "" + name + ".atwho";
290
- return this.$inputor.trigger(event_name, data);
291
- };
292
-
293
- Controller.prototype.callbacks = function(func_name) {
294
- return this.get_opt("callbacks")[func_name] || DEFAULT_CALLBACKS[func_name];
295
- };
296
-
297
- Controller.prototype.get_opt = function(at, default_value) {
298
- var e;
299
- try {
300
- return this.setting[at];
301
- } catch (_error) {
302
- e = _error;
303
- return null;
304
- }
305
- };
306
-
307
- Controller.prototype.content = function() {
308
- var range;
309
- if (this.$inputor.is('textarea, input')) {
310
- return this.$inputor.val();
311
- } else {
312
- if (!(range = this.mark_range())) {
313
- return;
314
- }
315
- return (range.startContainer.textContent || "").slice(0, range.startOffset);
316
- }
317
- };
318
-
319
- Controller.prototype.catch_query = function() {
320
- var caret_pos, content, end, query, start, subtext;
321
- content = this.content();
322
- caret_pos = this.$inputor.caret('pos', {
323
- iframe: this.app.iframe
324
- });
325
- subtext = content.slice(0, caret_pos);
326
- query = this.callbacks("matcher").call(this, this.at, subtext, this.get_opt('start_with_space'));
327
- if (typeof query === "string" && query.length <= this.get_opt('max_len', 20)) {
328
- start = caret_pos - query.length;
329
- end = start + query.length;
330
- this.pos = start;
331
- query = {
332
- 'text': query,
333
- 'head_pos': start,
334
- 'end_pos': end
335
- };
336
- this.trigger("matched", [this.at, query.text]);
337
- } else {
338
- query = null;
339
- this.view.hide();
340
- }
341
- return this.query = query;
342
- };
343
-
344
- Controller.prototype.rect = function() {
345
- var c, iframe_offset, scale_bottom;
346
- if (!(c = this.$inputor.caret('offset', this.pos - 1, {
347
- iframe: this.app.iframe
348
- }))) {
349
- return;
350
- }
351
- if (this.app.iframe && !this.app.iframeStandalone) {
352
- iframe_offset = $(this.app.iframe).offset();
353
- c.left += iframe_offset.left;
354
- c.top += iframe_offset.top;
355
- }
356
- if (this.$inputor.is('[contentEditable]')) {
357
- c = this.cur_rect || (this.cur_rect = c);
358
- }
359
- scale_bottom = this.app.document.selection ? 0 : 2;
360
- return {
361
- left: c.left,
362
- top: c.top,
363
- bottom: c.top + c.height + scale_bottom
364
- };
365
- };
366
-
367
- Controller.prototype.reset_rect = function() {
368
- if (this.$inputor.is('[contentEditable]')) {
369
- return this.cur_rect = null;
370
- }
371
- };
372
-
373
- Controller.prototype.mark_range = function() {
374
- var sel;
375
- if (!this.$inputor.is('[contentEditable]')) {
376
- return;
377
- }
378
- if (this.app.window.getSelection && (sel = this.app.window.getSelection()).rangeCount > 0) {
379
- return this.range = sel.getRangeAt(0);
380
- } else if (this.app.document.selection) {
381
- return this.ie8_range = this.app.document.selection.createRange();
382
- }
383
- };
384
-
385
- Controller.prototype.insert_content_for = function($li) {
386
- var data, data_value, tpl;
387
- data_value = $li.data('value');
388
- tpl = this.get_opt('insert_tpl');
389
- if (this.$inputor.is('textarea, input') || !tpl) {
390
- return data_value;
391
- }
392
- data = $.extend({}, $li.data('item-data'), {
393
- 'atwho-data-value': data_value,
394
- 'atwho-at': this.at
395
- });
396
- return this.callbacks("tpl_eval").call(this, tpl, data);
397
- };
398
-
399
- Controller.prototype.insert = function(content, $li) {
400
- var $inputor, node, pos, range, sel, source, start_str, text, wrapped_contents, _i, _len, _ref;
401
- $inputor = this.$inputor;
402
- wrapped_contents = this.callbacks('inserting_wrapper').call(this, $inputor, content, this.get_opt("suffix"));
403
- if ($inputor.is('textarea, input')) {
404
- source = $inputor.val();
405
- start_str = source.slice(0, Math.max(this.query.head_pos - this.at.length, 0));
406
- text = "" + start_str + wrapped_contents + (source.slice(this.query['end_pos'] || 0));
407
- $inputor.val(text);
408
- $inputor.caret('pos', start_str.length + wrapped_contents.length, {
409
- iframe: this.app.iframe
410
- });
411
- } else if (range = this.range) {
412
- pos = range.startOffset - (this.query.end_pos - this.query.head_pos) - this.at.length;
413
- range.setStart(range.endContainer, Math.max(pos, 0));
414
- range.setEnd(range.endContainer, range.endOffset);
415
- range.deleteContents();
416
- _ref = $(wrapped_contents, this.app.document);
417
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
418
- node = _ref[_i];
419
- range.insertNode(node);
420
- range.setEndAfter(node);
421
- range.collapse(false);
422
- }
423
- sel = this.app.window.getSelection();
424
- sel.removeAllRanges();
425
- sel.addRange(range);
426
- } else if (range = this.ie8_range) {
427
- range.moveStart('character', this.query.end_pos - this.query.head_pos - this.at.length);
428
- range.pasteHTML(wrapped_contents);
429
- range.collapse(false);
430
- range.select();
431
- }
432
- if (!$inputor.is(':focus')) {
433
- $inputor.focus();
434
- }
435
- return $inputor.change();
436
- };
437
-
438
- Controller.prototype.render_view = function(data) {
439
- var search_key;
440
- search_key = this.get_opt("search_key");
441
- data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), search_key);
442
- return this.view.render(data.slice(0, this.get_opt('limit')));
443
- };
444
-
445
- Controller.prototype.look_up = function() {
446
- var query, _callback;
447
- if (!(query = this.catch_query())) {
448
- return;
449
- }
450
- _callback = function(data) {
451
- if (data && data.length > 0) {
452
- return this.render_view(data);
453
- } else {
454
- return this.view.hide();
455
- }
456
- };
457
- this.model.query(query.text, $.proxy(_callback, this));
458
- return query;
459
- };
460
-
461
- return Controller;
462
-
463
- })();
464
-
465
- Model = (function() {
466
- function Model(context) {
467
- this.context = context;
468
- this.at = this.context.at;
469
- this.storage = this.context.$inputor;
470
- }
471
-
472
- Model.prototype.destroy = function() {
473
- return this.storage.data(this.at, null);
474
- };
475
-
476
- Model.prototype.saved = function() {
477
- return this.fetch() > 0;
478
- };
479
-
480
- Model.prototype.query = function(query, callback) {
481
- var data, search_key, _remote_filter;
482
- data = this.fetch();
483
- search_key = this.context.get_opt("search_key");
484
- data = this.context.callbacks('filter').call(this.context, query, data, search_key) || [];
485
- _remote_filter = this.context.callbacks('remote_filter');
486
- if (data.length > 0 || (!_remote_filter && data.length === 0)) {
487
- return callback(data);
488
- } else {
489
- return _remote_filter.call(this.context, query, callback);
490
- }
491
- };
492
-
493
- Model.prototype.fetch = function() {
494
- return this.storage.data(this.at) || [];
495
- };
496
-
497
- Model.prototype.save = function(data) {
498
- return this.storage.data(this.at, this.context.callbacks("before_save").call(this.context, data || []));
499
- };
500
-
501
- Model.prototype.load = function(data) {
502
- if (!(this.saved() || !data)) {
503
- return this._load(data);
504
- }
505
- };
506
-
507
- Model.prototype.reload = function(data) {
508
- return this._load(data);
509
- };
510
-
511
- Model.prototype._load = function(data) {
512
- if (typeof data === "string") {
513
- return $.ajax(data, {
514
- dataType: "json"
515
- }).done((function(_this) {
516
- return function(data) {
517
- return _this.save(data);
518
- };
519
- })(this));
520
- } else {
521
- return this.save(data);
522
- }
523
- };
524
-
525
- return Model;
526
-
527
- })();
528
-
529
- View = (function() {
530
- function View(context) {
531
- this.context = context;
532
- this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
533
- this.timeout_id = null;
534
- this.context.$el.append(this.$el);
535
- this.bind_event();
536
- }
537
-
538
- View.prototype.init = function() {
539
- var id;
540
- id = this.context.get_opt("alias") || this.context.at.charCodeAt(0);
541
- return this.$el.attr({
542
- 'id': "at-view-" + id
543
- });
544
- };
545
-
546
- View.prototype.destroy = function() {
547
- return this.$el.remove();
548
- };
549
-
550
- View.prototype.bind_event = function() {
551
- var $menu;
552
- $menu = this.$el.find('ul');
553
- return $menu.on('mouseenter.atwho-view', 'li', function(e) {
554
- $menu.find('.cur').removeClass('cur');
555
- return $(e.currentTarget).addClass('cur');
556
- }).on('click.atwho-view', 'li', (function(_this) {
557
- return function(e) {
558
- $menu.find('.cur').removeClass('cur');
559
- $(e.currentTarget).addClass('cur');
560
- _this.choose(e);
561
- return e.preventDefault();
562
- };
563
- })(this));
564
- };
565
-
566
- View.prototype.visible = function() {
567
- return this.$el.is(":visible");
568
- };
569
-
570
- View.prototype.choose = function(e) {
571
- var $li, content;
572
- if (($li = this.$el.find(".cur")).length) {
573
- content = this.context.insert_content_for($li);
574
- this.context.insert(this.context.callbacks("before_insert").call(this.context, content, $li), $li);
575
- this.context.trigger("inserted", [$li, e]);
576
- this.hide(e);
577
- }
578
- if (this.context.get_opt("hide_without_suffix")) {
579
- return this.stop_showing = true;
580
- }
581
- };
582
-
583
- View.prototype.reposition = function(rect) {
584
- var offset, overflowOffset, _ref, _window;
585
- _window = this.context.app.iframeStandalone ? this.context.app.window : window;
586
- if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) {
587
- rect.bottom = rect.top - this.$el.height();
588
- }
589
- if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) {
590
- rect.left = overflowOffset;
591
- }
592
- offset = {
593
- left: rect.left,
594
- top: rect.bottom
595
- };
596
- if ((_ref = this.context.callbacks("before_reposition")) != null) {
597
- _ref.call(this.context, offset);
598
- }
599
- this.$el.offset(offset);
600
- return this.context.trigger("reposition", [offset]);
601
- };
602
-
603
- View.prototype.next = function() {
604
- var cur, next;
605
- cur = this.$el.find('.cur').removeClass('cur');
606
- next = cur.next();
607
- if (!next.length) {
608
- next = this.$el.find('li:first');
609
- }
610
- next.addClass('cur');
611
- return this.$el.animate({
612
- scrollTop: Math.max(0, cur.innerHeight() * (next.index() + 2) - this.$el.height())
613
- }, 150);
614
- };
615
-
616
- View.prototype.prev = function() {
617
- var cur, prev;
618
- cur = this.$el.find('.cur').removeClass('cur');
619
- prev = cur.prev();
620
- if (!prev.length) {
621
- prev = this.$el.find('li:last');
622
- }
623
- prev.addClass('cur');
624
- return this.$el.animate({
625
- scrollTop: Math.max(0, cur.innerHeight() * (prev.index() + 2) - this.$el.height())
626
- }, 150);
627
- };
628
-
629
- View.prototype.show = function() {
630
- var rect;
631
- if (this.stop_showing) {
632
- this.stop_showing = false;
633
- return;
634
- }
635
- this.context.mark_range();
636
- if (!this.visible()) {
637
- this.$el.show();
638
- this.$el.scrollTop(0);
639
- this.context.trigger('shown');
640
- }
641
- if (rect = this.context.rect()) {
642
- return this.reposition(rect);
643
- }
644
- };
645
-
646
- View.prototype.hide = function(e, time) {
647
- var callback;
648
- if (!this.visible()) {
649
- return;
650
- }
651
- if (isNaN(time)) {
652
- this.context.reset_rect();
653
- this.$el.hide();
654
- return this.context.trigger('hidden', [e]);
655
- } else {
656
- callback = (function(_this) {
657
- return function() {
658
- return _this.hide();
659
- };
660
- })(this);
661
- clearTimeout(this.timeout_id);
662
- return this.timeout_id = setTimeout(callback, time);
663
- }
664
- };
665
-
666
- View.prototype.render = function(list) {
667
- var $li, $ul, item, li, tpl, _i, _len;
668
- if (!($.isArray(list) && list.length > 0)) {
669
- this.hide();
670
- return;
671
- }
672
- this.$el.find('ul').empty();
673
- $ul = this.$el.find('ul');
674
- tpl = this.context.get_opt('tpl');
675
- for (_i = 0, _len = list.length; _i < _len; _i++) {
676
- item = list[_i];
677
- item = $.extend({}, item, {
678
- 'atwho-at': this.context.at
679
- });
680
- li = this.context.callbacks("tpl_eval").call(this.context, tpl, item);
681
- $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
682
- $li.data("item-data", item);
683
- $ul.append($li);
684
- }
685
- this.show();
686
- if (this.context.get_opt('highlight_first')) {
687
- return $ul.find("li:first").addClass("cur");
688
- }
689
- };
690
-
691
- return View;
692
-
693
- })();
694
-
695
- KEY_CODE = {
696
- DOWN: 40,
697
- UP: 38,
698
- ESC: 27,
699
- TAB: 9,
700
- ENTER: 13,
701
- CTRL: 17,
702
- P: 80,
703
- N: 78
704
- };
705
-
706
- DEFAULT_CALLBACKS = {
707
- before_save: function(data) {
708
- var item, _i, _len, _results;
709
- if (!$.isArray(data)) {
710
- return data;
711
- }
712
- _results = [];
713
- for (_i = 0, _len = data.length; _i < _len; _i++) {
714
- item = data[_i];
715
- if ($.isPlainObject(item)) {
716
- _results.push(item);
717
- } else {
718
- _results.push({
719
- name: item
720
- });
721
- }
722
- }
723
- return _results;
724
- },
725
- matcher: function(flag, subtext, should_start_with_space) {
726
- var match, regexp, _a, _y;
727
- flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
728
- if (should_start_with_space) {
729
- flag = '(?:^|\\s)' + flag;
730
- }
731
- _a = decodeURI("%C3%80");
732
- _y = decodeURI("%C3%BF");
733
- regexp = new RegExp("" + flag + "([A-Za-z" + _a + "-" + _y + "0-9_\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi');
734
- match = regexp.exec(subtext);
735
- if (match) {
736
- return match[2] || match[1];
737
- } else {
738
- return null;
739
- }
740
- },
741
- filter: function(query, data, search_key) {
742
- var item, _i, _len, _results;
743
- _results = [];
744
- for (_i = 0, _len = data.length; _i < _len; _i++) {
745
- item = data[_i];
746
- if (~new String(item[search_key]).toLowerCase().indexOf(query.toLowerCase())) {
747
- _results.push(item);
748
- }
749
- }
750
- return _results;
751
- },
752
- remote_filter: null,
753
- sorter: function(query, items, search_key) {
754
- var item, _i, _len, _results;
755
- if (!query) {
756
- return items;
757
- }
758
- _results = [];
759
- for (_i = 0, _len = items.length; _i < _len; _i++) {
760
- item = items[_i];
761
- item.atwho_order = new String(item[search_key]).toLowerCase().indexOf(query.toLowerCase());
762
- if (item.atwho_order > -1) {
763
- _results.push(item);
764
- }
765
- }
766
- return _results.sort(function(a, b) {
767
- return a.atwho_order - b.atwho_order;
768
- });
769
- },
770
- tpl_eval: function(tpl, map) {
771
- var error;
772
- try {
773
- return tpl.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
774
- return map[key];
775
- });
776
- } catch (_error) {
777
- error = _error;
778
- return "";
779
- }
780
- },
781
- highlighter: function(li, query) {
782
- var regexp;
783
- if (!query) {
784
- return li;
785
- }
786
- regexp = new RegExp(">\\s*(\\w*?)(" + query.replace("+", "\\+") + ")(\\w*)\\s*<", 'ig');
787
- return li.replace(regexp, function(str, $1, $2, $3) {
788
- return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
789
- });
790
- },
791
- before_insert: function(value, $li) {
792
- return value;
793
- },
794
- inserting_wrapper: function($inputor, content, suffix) {
795
- var wrapped_content;
796
- suffix = suffix === "" ? suffix : suffix || " ";
797
- if ($inputor.is('textarea, input')) {
798
- return '' + content + suffix;
799
- } else if ($inputor.attr('contentEditable') === 'true') {
800
- suffix = suffix === " " ? "&nbsp;" : suffix;
801
- if (/firefox/i.test(navigator.userAgent)) {
802
- wrapped_content = "<span>" + content + suffix + "</span>";
803
- } else {
804
- suffix = "<span contenteditable='false'>" + suffix + "</span>";
805
- wrapped_content = "<span contenteditable='false'>" + content + suffix + "</span>";
806
- }
807
- if (this.app.document.selection) {
808
- wrapped_content = "<span contenteditable='true'>" + content + "</span>";
809
- }
810
- return wrapped_content + "<span></span>";
811
- }
812
- }
813
- };
814
-
815
- Api = {
816
- load: function(at, data) {
817
- var c;
818
- if (c = this.controller(at)) {
819
- return c.model.load(data);
820
- }
821
- },
822
- setIframe: function(iframe, standalone) {
823
- this.setIframe(iframe, standalone);
824
- return null;
825
- },
826
- run: function() {
827
- return this.dispatch();
828
- },
829
- destroy: function() {
830
- this.shutdown();
831
- return this.$inputor.data('atwho', null);
832
- }
833
- };
834
-
835
- $.fn.atwho = function(method) {
836
- var result, _args;
837
- _args = arguments;
838
- result = null;
839
- this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() {
840
- var $this, app;
841
- if (!(app = ($this = $(this)).data("atwho"))) {
842
- $this.data('atwho', (app = new App(this)));
843
- }
844
- if (typeof method === 'object' || !method) {
845
- return app.reg(method.at, method);
846
- } else if (Api[method] && app) {
847
- return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
848
- } else {
849
- return $.error("Method " + method + " does not exist on jQuery.caret");
850
- }
851
- });
852
- return result || this;
853
- };
854
-
855
- $.fn.atwho["default"] = {
856
- at: void 0,
857
- alias: void 0,
858
- data: null,
859
- tpl: "<li data-value='${atwho-at}${name}'>${name}</li>",
860
- insert_tpl: "<span id='${id}'>${atwho-data-value}</span>",
861
- callbacks: DEFAULT_CALLBACKS,
862
- search_key: "name",
863
- suffix: void 0,
864
- hide_without_suffix: false,
865
- start_with_space: true,
866
- highlight_first: true,
867
- limit: 5,
868
- max_len: 20,
869
- display_timeout: 300,
870
- delay: null
871
- };
872
-
873
-
874
-
875
- }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-core/js/jquery.atwho.min.js DELETED
@@ -1 +0,0 @@
1
- !function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(c){return a.returnExportsGlobal=b(c)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b,c,d,e,f,g,h,i=[].slice;c=function(){function b(b){this.current_flag=null,this.controllers={},this.alias_maps={},this.$inputor=a(b),this.setIframe(),this.listen()}return b.prototype.createContainer=function(b){return 0===(this.$el=a("#atwho-container",b)).length?a(b.body).append(this.$el=a("<div id='atwho-container'></div>")):void 0},b.prototype.setIframe=function(a,b){var c;return null==b&&(b=!1),a?(this.window=a.contentWindow,this.document=a.contentDocument||this.window.document,this.iframe=a):(this.document=document,this.window=window,this.iframe=null),(this.iframeStandalone=b)?(null!=(c=this.$el)&&c.remove(),this.createContainer(this.document)):this.createContainer(document)},b.prototype.controller=function(a){var b,c,d,e;if(this.alias_maps[a])c=this.controllers[this.alias_maps[a]];else{e=this.controllers;for(d in e)if(b=e[d],d===a){c=b;break}}return c?c:this.controllers[this.current_flag]},b.prototype.set_context_for=function(a){return this.current_flag=a,this},b.prototype.reg=function(a,b){var c,e;return c=(e=this.controllers)[a]||(e[a]=new d(this,a)),b.alias&&(this.alias_maps[b.alias]=a),c.init(b),this},b.prototype.listen=function(){return this.$inputor.on("keyup.atwhoInner",function(a){return function(b){return a.on_keyup(b)}}(this)).on("keydown.atwhoInner",function(a){return function(b){return a.on_keydown(b)}}(this)).on("scroll.atwhoInner",function(a){return function(b){var c;return null!=(c=a.controller())?c.view.hide(b):void 0}}(this)).on("blur.atwhoInner",function(a){return function(b){var c;return(c=a.controller())?c.view.hide(b,c.get_opt("display_timeout")):void 0}}(this)).on("click.atwhoInner",function(a){return function(b){return a.dispatch()}}(this))},b.prototype.shutdown=function(){var a,b,c;c=this.controllers;for(b in c)a=c[b],a.destroy(),delete this.controllers[b];return this.$inputor.off(".atwhoInner"),this.$el.remove()},b.prototype.dispatch=function(){return a.map(this.controllers,function(a){return function(b){var c;return(c=b.get_opt("delay"))?(clearTimeout(a.delayedCallback),a.delayedCallback=setTimeout(function(){return b.look_up()?a.set_context_for(b.at):void 0},c)):b.look_up()?a.set_context_for(b.at):void 0}}(this))},b.prototype.on_keyup=function(b){var c;switch(b.keyCode){case f.ESC:b.preventDefault(),null!=(c=this.controller())&&c.view.hide();break;case f.DOWN:case f.UP:case f.CTRL:a.noop();break;case f.P:case f.N:b.ctrlKey||this.dispatch();break;default:this.dispatch()}},b.prototype.on_keydown=function(b){var c,d;if(c=null!=(d=this.controller())?d.view:void 0,c&&c.visible())switch(b.keyCode){case f.ESC:b.preventDefault(),c.hide(b);break;case f.UP:b.preventDefault(),c.prev();break;case f.DOWN:b.preventDefault(),c.next();break;case f.P:if(!b.ctrlKey)return;b.preventDefault(),c.prev();break;case f.N:if(!b.ctrlKey)return;b.preventDefault(),c.next();break;case f.TAB:case f.ENTER:if(!c.visible())return;b.preventDefault(),c.choose(b);break;default:a.noop()}},b}(),d=function(){function b(b,c){this.app=b,this.at=c,this.$inputor=this.app.$inputor,this.id=this.$inputor[0].id||this.uid(),this.setting=null,this.query=null,this.pos=0,this.cur_rect=null,this.range=null,0===(this.$el=a("#atwho-ground-"+this.id,this.app.$el)).length&&this.app.$el.append(this.$el=a("<div id='atwho-ground-"+this.id+"'></div>")),this.model=new g(this),this.view=new h(this)}return b.prototype.uid=function(){return(Math.random().toString(16)+"000000000").substr(2,8)+(new Date).getTime()},b.prototype.init=function(b){return this.setting=a.extend({},this.setting||a.fn.atwho["default"],b),this.view.init(),this.model.reload(this.setting.data)},b.prototype.destroy=function(){return this.trigger("beforeDestroy"),this.model.destroy(),this.view.destroy(),this.$el.remove()},b.prototype.call_default=function(){var b,c,d;d=arguments[0],b=2<=arguments.length?i.call(arguments,1):[];try{return e[d].apply(this,b)}catch(f){return c=f,a.error(""+c+" Or maybe At.js doesn't have function "+d)}},b.prototype.trigger=function(a,b){var c,d;return null==b&&(b=[]),b.push(this),c=this.get_opt("alias"),d=c?""+a+"-"+c+".atwho":""+a+".atwho",this.$inputor.trigger(d,b)},b.prototype.callbacks=function(a){return this.get_opt("callbacks")[a]||e[a]},b.prototype.get_opt=function(a,b){var c;try{return this.setting[a]}catch(d){return c=d,null}},b.prototype.content=function(){var a;if(this.$inputor.is("textarea, input"))return this.$inputor.val();if(a=this.mark_range())return(a.startContainer.textContent||"").slice(0,a.startOffset)},b.prototype.catch_query=function(){var a,b,c,d,e,f;return b=this.content(),a=this.$inputor.caret("pos",{iframe:this.app.iframe}),f=b.slice(0,a),d=this.callbacks("matcher").call(this,this.at,f,this.get_opt("start_with_space")),"string"==typeof d&&d.length<=this.get_opt("max_len",20)?(e=a-d.length,c=e+d.length,this.pos=e,d={text:d,head_pos:e,end_pos:c},this.trigger("matched",[this.at,d.text])):(d=null,this.view.hide()),this.query=d},b.prototype.rect=function(){var b,c,d;if(b=this.$inputor.caret("offset",this.pos-1,{iframe:this.app.iframe}))return this.app.iframe&&!this.app.iframeStandalone&&(c=a(this.app.iframe).offset(),b.left+=c.left,b.top+=c.top),this.$inputor.is("[contentEditable]")&&(b=this.cur_rect||(this.cur_rect=b)),d=this.app.document.selection?0:2,{left:b.left,top:b.top,bottom:b.top+b.height+d}},b.prototype.reset_rect=function(){return this.$inputor.is("[contentEditable]")?this.cur_rect=null:void 0},b.prototype.mark_range=function(){var a;if(this.$inputor.is("[contentEditable]"))return this.app.window.getSelection&&(a=this.app.window.getSelection()).rangeCount>0?this.range=a.getRangeAt(0):this.app.document.selection?this.ie8_range=this.app.document.selection.createRange():void 0},b.prototype.insert_content_for=function(b){var c,d,e;return d=b.data("value"),e=this.get_opt("insert_tpl"),this.$inputor.is("textarea, input")||!e?d:(c=a.extend({},b.data("item-data"),{"atwho-data-value":d,"atwho-at":this.at}),this.callbacks("tpl_eval").call(this,e,c))},b.prototype.insert=function(b,c){var d,e,f,g,h,i,j,k,l,m,n,o;if(d=this.$inputor,l=this.callbacks("inserting_wrapper").call(this,d,b,this.get_opt("suffix")),d.is("textarea, input"))i=d.val(),j=i.slice(0,Math.max(this.query.head_pos-this.at.length,0)),k=""+j+l+i.slice(this.query.end_pos||0),d.val(k),d.caret("pos",j.length+l.length,{iframe:this.app.iframe});else if(g=this.range){for(f=g.startOffset-(this.query.end_pos-this.query.head_pos)-this.at.length,g.setStart(g.endContainer,Math.max(f,0)),g.setEnd(g.endContainer,g.endOffset),g.deleteContents(),o=a(l,this.app.document),m=0,n=o.length;n>m;m++)e=o[m],g.insertNode(e),g.setEndAfter(e),g.collapse(!1);h=this.app.window.getSelection(),h.removeAllRanges(),h.addRange(g)}else(g=this.ie8_range)&&(g.moveStart("character",this.query.end_pos-this.query.head_pos-this.at.length),g.pasteHTML(l),g.collapse(!1),g.select());return d.is(":focus")||d.focus(),d.change()},b.prototype.render_view=function(a){var b;return b=this.get_opt("search_key"),a=this.callbacks("sorter").call(this,this.query.text,a.slice(0,1001),b),this.view.render(a.slice(0,this.get_opt("limit")))},b.prototype.look_up=function(){var b,c;if(b=this.catch_query())return c=function(a){return a&&a.length>0?this.render_view(a):this.view.hide()},this.model.query(b.text,a.proxy(c,this)),b},b}(),g=function(){function b(a){this.context=a,this.at=this.context.at,this.storage=this.context.$inputor}return b.prototype.destroy=function(){return this.storage.data(this.at,null)},b.prototype.saved=function(){return this.fetch()>0},b.prototype.query=function(a,b){var c,d,e;return c=this.fetch(),d=this.context.get_opt("search_key"),c=this.context.callbacks("filter").call(this.context,a,c,d)||[],e=this.context.callbacks("remote_filter"),c.length>0||!e&&0===c.length?b(c):e.call(this.context,a,b)},b.prototype.fetch=function(){return this.storage.data(this.at)||[]},b.prototype.save=function(a){return this.storage.data(this.at,this.context.callbacks("before_save").call(this.context,a||[]))},b.prototype.load=function(a){return!this.saved()&&a?this._load(a):void 0},b.prototype.reload=function(a){return this._load(a)},b.prototype._load=function(b){return"string"==typeof b?a.ajax(b,{dataType:"json"}).done(function(a){return function(b){return a.save(b)}}(this)):this.save(b)},b}(),h=function(){function b(b){this.context=b,this.$el=a("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>"),this.timeout_id=null,this.context.$el.append(this.$el),this.bind_event()}return b.prototype.init=function(){var a;return a=this.context.get_opt("alias")||this.context.at.charCodeAt(0),this.$el.attr({id:"at-view-"+a})},b.prototype.destroy=function(){return this.$el.remove()},b.prototype.bind_event=function(){var b;return b=this.$el.find("ul"),b.on("mouseenter.atwho-view","li",function(c){return b.find(".cur").removeClass("cur"),a(c.currentTarget).addClass("cur")}).on("click.atwho-view","li",function(c){return function(d){return b.find(".cur").removeClass("cur"),a(d.currentTarget).addClass("cur"),c.choose(d),d.preventDefault()}}(this))},b.prototype.visible=function(){return this.$el.is(":visible")},b.prototype.choose=function(a){var b,c;return(b=this.$el.find(".cur")).length&&(c=this.context.insert_content_for(b),this.context.insert(this.context.callbacks("before_insert").call(this.context,c,b),b),this.context.trigger("inserted",[b,a]),this.hide(a)),this.context.get_opt("hide_without_suffix")?this.stop_showing=!0:void 0},b.prototype.reposition=function(b){var c,d,e,f;return f=this.context.app.iframeStandalone?this.context.app.window:window,b.bottom+this.$el.height()-a(f).scrollTop()>a(f).height()&&(b.bottom=b.top-this.$el.height()),b.left>(d=a(f).width()-this.$el.width()-5)&&(b.left=d),c={left:b.left,top:b.bottom},null!=(e=this.context.callbacks("before_reposition"))&&e.call(this.context,c),this.$el.offset(c),this.context.trigger("reposition",[c])},b.prototype.next=function(){var a,b;return a=this.$el.find(".cur").removeClass("cur"),b=a.next(),b.length||(b=this.$el.find("li:first")),b.addClass("cur"),this.$el.animate({scrollTop:Math.max(0,a.innerHeight()*(b.index()+2)-this.$el.height())},150)},b.prototype.prev=function(){var a,b;return a=this.$el.find(".cur").removeClass("cur"),b=a.prev(),b.length||(b=this.$el.find("li:last")),b.addClass("cur"),this.$el.animate({scrollTop:Math.max(0,a.innerHeight()*(b.index()+2)-this.$el.height())},150)},b.prototype.show=function(){var a;return this.stop_showing?void(this.stop_showing=!1):(this.context.mark_range(),this.visible()||(this.$el.show(),this.$el.scrollTop(0),this.context.trigger("shown")),(a=this.context.rect())?this.reposition(a):void 0)},b.prototype.hide=function(a,b){var c;if(this.visible())return isNaN(b)?(this.context.reset_rect(),this.$el.hide(),this.context.trigger("hidden",[a])):(c=function(a){return function(){return a.hide()}}(this),clearTimeout(this.timeout_id),this.timeout_id=setTimeout(c,b))},b.prototype.render=function(b){var c,d,e,f,g,h,i;if(!(a.isArray(b)&&b.length>0))return void this.hide();for(this.$el.find("ul").empty(),d=this.$el.find("ul"),g=this.context.get_opt("tpl"),h=0,i=b.length;i>h;h++)e=b[h],e=a.extend({},e,{"atwho-at":this.context.at}),f=this.context.callbacks("tpl_eval").call(this.context,g,e),c=a(this.context.callbacks("highlighter").call(this.context,f,this.context.query.text)),c.data("item-data",e),d.append(c);return this.show(),this.context.get_opt("highlight_first")?d.find("li:first").addClass("cur"):void 0},b}(),f={DOWN:40,UP:38,ESC:27,TAB:9,ENTER:13,CTRL:17,P:80,N:78},e={before_save:function(b){var c,d,e,f;if(!a.isArray(b))return b;for(f=[],d=0,e=b.length;e>d;d++)c=b[d],a.isPlainObject(c)?f.push(c):f.push({name:c});return f},matcher:function(a,b,c){var d,e,f,g;return a=a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),c&&(a="(?:^|\\s)"+a),f=decodeURI("%C3%80"),g=decodeURI("%C3%BF"),e=new RegExp(""+a+"([A-Za-z"+f+"-"+g+"0-9_+-]*)$|"+a+"([^\\x00-\\xff]*)$","gi"),d=e.exec(b),d?d[2]||d[1]:null},filter:function(a,b,c){var d,e,f,g;for(g=[],e=0,f=b.length;f>e;e++)d=b[e],~new String(d[c]).toLowerCase().indexOf(a.toLowerCase())&&g.push(d);return g},remote_filter:null,sorter:function(a,b,c){var d,e,f,g;if(!a)return b;for(g=[],e=0,f=b.length;f>e;e++)d=b[e],d.atwho_order=new String(d[c]).toLowerCase().indexOf(a.toLowerCase()),d.atwho_order>-1&&g.push(d);return g.sort(function(a,b){return a.atwho_order-b.atwho_order})},tpl_eval:function(a,b){var c;try{return a.replace(/\$\{([^\}]*)\}/g,function(a,c,d){return b[c]})}catch(d){return c=d,""}},highlighter:function(a,b){var c;return b?(c=new RegExp(">\\s*(\\w*?)("+b.replace("+","\\+")+")(\\w*)\\s*<","ig"),a.replace(c,function(a,b,c,d){return"> "+b+"<strong>"+c+"</strong>"+d+" <"})):a},before_insert:function(a,b){return a},inserting_wrapper:function(a,b,c){var d;return c=""===c?c:c||" ",a.is("textarea, input")?""+b+c:"true"===a.attr("contentEditable")?(c=" "===c?"&nbsp;":c,/firefox/i.test(navigator.userAgent)?d="<span>"+b+c+"</span>":(c="<span contenteditable='false'>"+c+"</span>",d="<span contenteditable='false'>"+b+c+"</span>"),this.app.document.selection&&(d="<span contenteditable='true'>"+b+"</span>"),d+"<span></span>"):void 0}},b={load:function(a,b){var c;return(c=this.controller(a))?c.model.load(b):void 0},setIframe:function(a,b){return this.setIframe(a,b),null},run:function(){return this.dispatch()},destroy:function(){return this.shutdown(),this.$inputor.data("atwho",null)}},a.fn.atwho=function(d){var e,f;return f=arguments,e=null,this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function(){var g,h;return(h=(g=a(this)).data("atwho"))||g.data("atwho",h=new c(this)),"object"!=typeof d&&d?b[d]&&h?e=b[d].apply(h,Array.prototype.slice.call(f,1)):a.error("Method "+d+" does not exist on jQuery.caret"):h.reg(d.at,d)}),e||this},a.fn.atwho["default"]={at:void 0,alias:void 0,data:null,tpl:"<li data-value='${atwho-at}${name}'>${name}</li>",insert_tpl:"<span id='${id}'>${atwho-data-value}</span>",callbacks:e,search_key:"name",suffix:void 0,hide_without_suffix:!1,start_with_space:!0,highlight_first:!0,limit:5,max_len:20,display_timeout:300,delay:null}});
 
bp-core/js/jquery.caret.min.js DELETED
@@ -1 +0,0 @@
1
- !function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(c){return a.returnExportsGlobal=b(c)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){"use strict";var b,c,d,e,f,g,h,i,j,k,l;k="caret",b=function(){function b(a){this.$inputor=a,this.domInputor=this.$inputor[0]}return b.prototype.setPos=function(a){return this.domInputor},b.prototype.getIEPosition=function(){return this.getPosition()},b.prototype.getPosition=function(){var a,b;return b=this.getOffset(),a=this.$inputor.offset(),b.left-=a.left,b.top-=a.top,b},b.prototype.getOldIEPos=function(){var a,b;return b=h.selection.createRange(),a=h.body.createTextRange(),a.moveToElementText(this.domInputor),a.setEndPoint("EndToEnd",b),a.text.length},b.prototype.getPos=function(){var a,b,c;return(c=this.range())?(a=c.cloneRange(),a.selectNodeContents(this.domInputor),a.setEnd(c.endContainer,c.endOffset),b=a.toString().length,a.detach(),b):h.selection?this.getOldIEPos():void 0},b.prototype.getOldIEOffset=function(){var a,b;return a=h.selection.createRange().duplicate(),a.moveStart("character",-1),b=a.getBoundingClientRect(),{height:b.bottom-b.top,left:b.left,top:b.top}},b.prototype.getOffset=function(b){var c,d,e,f,g;return j.getSelection&&(e=this.range())?(e.endOffset-1>0&&e.endContainer===!this.domInputor&&(c=e.cloneRange(),c.setStart(e.endContainer,e.endOffset-1),c.setEnd(e.endContainer,e.endOffset),f=c.getBoundingClientRect(),d={height:f.height,left:f.left+f.width,top:f.top},c.detach()),d&&0!==(null!=d?d.height:void 0)||(c=e.cloneRange(),g=a(h.createTextNode("|")),c.insertNode(g[0]),c.selectNode(g[0]),f=c.getBoundingClientRect(),d={height:f.height,left:f.left,top:f.top},g.remove(),c.detach())):h.selection&&(d=this.getOldIEOffset()),d&&(d.top+=a(j).scrollTop(),d.left+=a(j).scrollLeft()),d},b.prototype.range=function(){var a;if(j.getSelection)return a=j.getSelection(),a.rangeCount>0?a.getRangeAt(0):null},b}(),c=function(){function b(a){this.$inputor=a,this.domInputor=this.$inputor[0]}return b.prototype.getIEPos=function(){var a,b,c,d,e,f,g;return b=this.domInputor,f=h.selection.createRange(),e=0,f&&f.parentElement()===b&&(d=b.value.replace(/\r\n/g,"\n"),c=d.length,g=b.createTextRange(),g.moveToBookmark(f.getBookmark()),a=b.createTextRange(),a.collapse(!1),e=g.compareEndPoints("StartToEnd",a)>-1?c:-g.moveStart("character",-c)),e},b.prototype.getPos=function(){return h.selection?this.getIEPos():this.domInputor.selectionStart},b.prototype.setPos=function(a){var b,c;return b=this.domInputor,h.selection?(c=b.createTextRange(),c.move("character",a),c.select()):b.setSelectionRange&&b.setSelectionRange(a,a),b},b.prototype.getIEOffset=function(a){var b,c,d,e;return c=this.domInputor.createTextRange(),a||(a=this.getPos()),c.move("character",a),d=c.boundingLeft,e=c.boundingTop,b=c.boundingHeight,{left:d,top:e,height:b}},b.prototype.getOffset=function(b){var c,d,e;return c=this.$inputor,h.selection?(d=this.getIEOffset(b),d.top+=a(j).scrollTop()+c.scrollTop(),d.left+=a(j).scrollLeft()+c.scrollLeft(),d):(d=c.offset(),e=this.getPosition(b),d={left:d.left+e.left-c.scrollLeft(),top:d.top+e.top-c.scrollTop(),height:e.height})},b.prototype.getPosition=function(a){var b,c,e,f,g,h,i;return b=this.$inputor,f=function(a){return a=a.replace(/<|>|`|"|&/g,"?").replace(/\r\n|\r|\n/g,"<br/>"),/firefox/i.test(navigator.userAgent)&&(a=a.replace(/\s/g,"&nbsp;")),a},void 0===a&&(a=this.getPos()),i=b.val().slice(0,a),e=b.val().slice(a),g="<span style='position: relative; display: inline;'>"+f(i)+"</span>",g+="<span id='caret' style='position: relative; display: inline;'>|</span>",g+="<span style='position: relative; display: inline;'>"+f(e)+"</span>",h=new d(b),c=h.create(g).rect()},b.prototype.getIEPosition=function(a){var b,c,d,e,f;return d=this.getIEOffset(a),c=this.$inputor.offset(),e=d.left-c.left,f=d.top-c.top,b=d.height,{left:e,top:f,height:b}},b}(),d=function(){function b(a){this.$inputor=a}return b.prototype.css_attr=["borderBottomWidth","borderLeftWidth","borderRightWidth","borderTopStyle","borderRightStyle","borderBottomStyle","borderLeftStyle","borderTopWidth","boxSizing","fontFamily","fontSize","fontWeight","height","letterSpacing","lineHeight","marginBottom","marginLeft","marginRight","marginTop","outlineWidth","overflow","overflowX","overflowY","paddingBottom","paddingLeft","paddingRight","paddingTop","textAlign","textOverflow","textTransform","whiteSpace","wordBreak","wordWrap"],b.prototype.mirrorCss=function(){var b,c=this;return b={position:"absolute",left:-9999,top:0,zIndex:-2e4},"TEXTAREA"===this.$inputor.prop("tagName")&&this.css_attr.push("width"),a.each(this.css_attr,function(a,d){return b[d]=c.$inputor.css(d)}),b},b.prototype.create=function(b){return this.$mirror=a("<div></div>"),this.$mirror.css(this.mirrorCss()),this.$mirror.html(b),this.$inputor.after(this.$mirror),this},b.prototype.rect=function(){var a,b,c;return a=this.$mirror.find("#caret"),b=a.position(),c={left:b.left,top:b.top,height:a.height()},this.$mirror.remove(),c},b}(),e={contentEditable:function(a){return!(!a[0].contentEditable||"true"!==a[0].contentEditable)}},g={pos:function(a){return a||0===a?this.setPos(a):this.getPos()},position:function(a){return h.selection?this.getIEPosition(a):this.getPosition(a)},offset:function(a){var b;return b=this.getOffset(a)}},h=null,j=null,i=null,l=function(a){var b;return(b=null!=a?a.iframe:void 0)?(i=b,j=b.contentWindow,h=b.contentDocument||j.document):(i=void 0,j=window,h=document)},f=function(a){var b;h=a[0].ownerDocument,j=h.defaultView||h.parentWindow;try{return i=j.frameElement}catch(c){b=c}},a.fn.caret=function(d,f,h){var i;return g[d]?(a.isPlainObject(f)?(l(f),f=void 0):l(h),i=e.contentEditable(this)?new b(this):new c(this),g[d].apply(i,[f])):a.error("Method "+d+" does not exist on jQuery.caret")},a.fn.caret.EditableCaret=b,a.fn.caret.InputCaret=c,a.fn.caret.Utils=e,a.fn.caret.apis=g});
 
bp-core/js/{jquery-cookie.js → vendor/jquery-cookie.js} RENAMED
File without changes
bp-core/js/vendor/jquery-cookie.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e("object"==typeof exports?require("jquery"):jQuery)}(function(e){function n(e){return u.raw?e:encodeURIComponent(e)}function o(e){return u.raw?e:decodeURIComponent(e)}function i(e){return n(u.json?JSON.stringify(e):String(e))}function r(e){0===e.indexOf('"')&&(e=e.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return e=decodeURIComponent(e.replace(c," ")),u.json?JSON.parse(e):e}catch(e){}}function t(n,o){var i=u.raw?n:r(n);return e.isFunction(o)?o(i):i}var c=/\+/g,u=e.cookie=function(r,c,f){if(void 0!==c&&!e.isFunction(c)){if("number"==typeof(f=e.extend({},u.defaults,f)).expires){var a=f.expires,d=f.expires=new Date;d.setTime(+d+864e5*a)}return document.cookie=[n(r),"=",i(c),f.expires?"; expires="+f.expires.toUTCString():"",f.path?"; path="+f.path:"",f.domain?"; domain="+f.domain:"",f.secure?"; secure":""].join("")}for(var p=r?void 0:{},s=document.cookie?document.cookie.split("; "):[],m=0,x=s.length;m<x;m++){var v=s[m].split("="),k=o(v.shift()),l=v.join("=");if(r&&r===k){p=t(l,c);break}r||void 0===(l=t(l))||(p[k]=l)}return p};u.defaults={},e.removeCookie=function(n,o){return void 0!==e.cookie(n)&&(e.cookie(n,"",e.extend({},o,{expires:-1})),!e.cookie(n))}});
bp-core/js/{jquery-scroll-to.js → vendor/jquery-scroll-to.js} RENAMED
File without changes
bp-core/js/vendor/jquery-scroll-to.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e("object"==typeof exports?require("jquery"):jQuery)}(function(e){function t(t){return e.isFunction(t)||"object"==typeof t?t:{top:t,left:t}}var n=e.scrollTo=function(t,n,o){return e(window).scrollTo(t,n,o)};return n.defaults={axis:"xy",duration:parseFloat(e.fn.jquery)>=1.3?0:1,limit:!0},n.window=function(){return e(window)._scrollable()},e.fn._scrollable=function(){return this.map(function(){var t=this;if(!(!t.nodeName||-1!==e.inArray(t.nodeName.toLowerCase(),["iframe","#document","html","body"])))return t;var n=(t.contentWindow||t).document||t.ownerDocument||t;return/webkit/i.test(navigator.userAgent)||"BackCompat"===n.compatMode?n.body:n.documentElement})},e.fn.scrollTo=function(o,r,i){return"object"==typeof r&&(i=r,r=0),"function"==typeof i&&(i={onAfter:i}),"max"===o&&(o=9e9),i=e.extend({},n.defaults,i),r=r||i.duration,i.queue=i.queue&&i.axis.length>1,i.queue&&(r/=2),i.offset=t(i.offset),i.over=t(i.over),this._scrollable().each(function(){function s(e){u.animate(l,r,i.easing,e&&function(){e.call(this,c,i)})}if(null!==o){var a,f=this,u=e(f),c=o,l={},d=u.is("html,body");switch(typeof c){case"number":case"string":if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(c)){c=t(c);break}if(!(c=d?e(c):e(c,this)).length)return;case"object":(c.is||c.style)&&(a=(c=e(c)).offset())}var m=e.isFunction(i.offset)&&i.offset(f,c)||i.offset;e.each(i.axis.split(""),function(e,t){var o="x"===t?"Left":"Top",r=o.toLowerCase(),h="scroll"+o,p=f[h],y=n.max(f,t);if(a)l[h]=a[r]+(d?0:p-u.offset()[r]),i.margin&&(l[h]-=parseInt(c.css("margin"+o))||0,l[h]-=parseInt(c.css("border"+o+"Width"))||0),l[h]+=m[r]||0,i.over[r]&&(l[h]+=c["x"===t?"width":"height"]()*i.over[r]);else{var b=c[r];l[h]=b.slice&&"%"===b.slice(-1)?parseFloat(b)/100*y:b}i.limit&&/^\d+$/.test(l[h])&&(l[h]=l[h]<=0?0:Math.min(l[h],y)),!e&&i.queue&&(p!==l[h]&&s(i.onAfterFirst),delete l[h])}),s(i.onAfter)}}).end()},n.max=function(t,n){var o="x"===n?"Width":"Height",r="scroll"+o;if(!e(t).is("html,body"))return t[r]-e(t)[o.toLowerCase()]();var i="client"+o,s=t.ownerDocument.documentElement,a=t.ownerDocument.body;return Math.max(s[r],a[r])-Math.min(s[i],a[i])},n});
bp-core/js/vendor/jquery.atwho.js ADDED
@@ -0,0 +1,1212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * at.js - 1.5.4
3
+ * Copyright (c) 2017 chord.luo <chord.luo@gmail.com>;
4
+ * Homepage: http://ichord.github.com/At.js
5
+ * License: MIT
6
+ */
7
+ (function (root, factory) {
8
+ if (typeof define === 'function' && define.amd) {
9
+ // AMD. Register as an anonymous module unless amdModuleId is set
10
+ define(["jquery"], function (a0) {
11
+ return (factory(a0));
12
+ });
13
+ } else if (typeof exports === 'object') {
14
+ // Node. Does not work with strict CommonJS, but
15
+ // only CommonJS-like environments that support module.exports,
16
+ // like Node.
17
+ module.exports = factory(require("jquery"));
18
+ } else {
19
+ factory(jQuery);
20
+ }
21
+ }(this, function ($) {
22
+ var DEFAULT_CALLBACKS, KEY_CODE;
23
+
24
+ KEY_CODE = {
25
+ ESC: 27,
26
+ TAB: 9,
27
+ ENTER: 13,
28
+ CTRL: 17,
29
+ A: 65,
30
+ P: 80,
31
+ N: 78,
32
+ LEFT: 37,
33
+ UP: 38,
34
+ RIGHT: 39,
35
+ DOWN: 40,
36
+ BACKSPACE: 8,
37
+ SPACE: 32
38
+ };
39
+
40
+ DEFAULT_CALLBACKS = {
41
+ beforeSave: function(data) {
42
+ return Controller.arrayToDefaultHash(data);
43
+ },
44
+ matcher: function(flag, subtext, should_startWithSpace, acceptSpaceBar) {
45
+ var _a, _y, match, regexp, space;
46
+ flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
47
+ if (should_startWithSpace) {
48
+ flag = '(?:^|\\s)' + flag;
49
+ }
50
+ _a = decodeURI("%C3%80");
51
+ _y = decodeURI("%C3%BF");
52
+ space = acceptSpaceBar ? "\ " : "";
53
+ regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_" + space + "\'\.\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi');
54
+ match = regexp.exec(subtext);
55
+ if (match) {
56
+ return match[2] || match[1];
57
+ } else {
58
+ return null;
59
+ }
60
+ },
61
+ filter: function(query, data, searchKey) {
62
+ var _results, i, item, len;
63
+ _results = [];
64
+ for (i = 0, len = data.length; i < len; i++) {
65
+ item = data[i];
66
+ if (~new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase())) {
67
+ _results.push(item);
68
+ }
69
+ }
70
+ return _results;
71
+ },
72
+ remoteFilter: null,
73
+ sorter: function(query, items, searchKey) {
74
+ var _results, i, item, len;
75
+ if (!query) {
76
+ return items;
77
+ }
78
+ _results = [];
79
+ for (i = 0, len = items.length; i < len; i++) {
80
+ item = items[i];
81
+ item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase());
82
+ if (item.atwho_order > -1) {
83
+ _results.push(item);
84
+ }
85
+ }
86
+ return _results.sort(function(a, b) {
87
+ return a.atwho_order - b.atwho_order;
88
+ });
89
+ },
90
+ tplEval: function(tpl, map) {
91
+ var error, error1, template;
92
+ template = tpl;
93
+ try {
94
+ if (typeof tpl !== 'string') {
95
+ template = tpl(map);
96
+ }
97
+ return template.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
98
+ return map[key];
99
+ });
100
+ } catch (error1) {
101
+ error = error1;
102
+ return "";
103
+ }
104
+ },
105
+ highlighter: function(li, query) {
106
+ var regexp;
107
+ if (!query) {
108
+ return li;
109
+ }
110
+ regexp = new RegExp(">\\s*([^\<]*?)(" + query.replace("+", "\\+") + ")([^\<]*)\\s*<", 'ig');
111
+ return li.replace(regexp, function(str, $1, $2, $3) {
112
+ return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
113
+ });
114
+ },
115
+ beforeInsert: function(value, $li, e) {
116
+ return value;
117
+ },
118
+ beforeReposition: function(offset) {
119
+ return offset;
120
+ },
121
+ afterMatchFailed: function(at, el) {}
122
+ };
123
+
124
+ var App;
125
+
126
+ App = (function() {
127
+ function App(inputor) {
128
+ this.currentFlag = null;
129
+ this.controllers = {};
130
+ this.aliasMaps = {};
131
+ this.$inputor = $(inputor);
132
+ this.setupRootElement();
133
+ this.listen();
134
+ }
135
+
136
+ App.prototype.createContainer = function(doc) {
137
+ var ref;
138
+ if ((ref = this.$el) != null) {
139
+ ref.remove();
140
+ }
141
+ return $(doc.body).append(this.$el = $("<div class='atwho-container'></div>"));
142
+ };
143
+
144
+ App.prototype.setupRootElement = function(iframe, asRoot) {
145
+ var error, error1;
146
+ if (asRoot == null) {
147
+ asRoot = false;
148
+ }
149
+ if (iframe) {
150
+ this.window = iframe.contentWindow;
151
+ this.document = iframe.contentDocument || this.window.document;
152
+ this.iframe = iframe;
153
+ } else {
154
+ this.document = this.$inputor[0].ownerDocument;
155
+ this.window = this.document.defaultView || this.document.parentWindow;
156
+ try {
157
+ this.iframe = this.window.frameElement;
158
+ } catch (error1) {
159
+ error = error1;
160
+ this.iframe = null;
161
+ if ($.fn.atwho.debug) {
162
+ throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n" + error);
163
+ }
164
+ }
165
+ }
166
+ return this.createContainer((this.iframeAsRoot = asRoot) ? this.document : document);
167
+ };
168
+
169
+ App.prototype.controller = function(at) {
170
+ var c, current, currentFlag, ref;
171
+ if (this.aliasMaps[at]) {
172
+ current = this.controllers[this.aliasMaps[at]];
173
+ } else {
174
+ ref = this.controllers;
175
+ for (currentFlag in ref) {
176
+ c = ref[currentFlag];
177
+ if (currentFlag === at) {
178
+ current = c;
179
+ break;
180
+ }
181
+ }
182
+ }
183
+ if (current) {
184
+ return current;
185
+ } else {
186
+ return this.controllers[this.currentFlag];
187
+ }
188
+ };
189
+
190
+ App.prototype.setContextFor = function(at) {
191
+ this.currentFlag = at;
192
+ return this;
193
+ };
194
+
195
+ App.prototype.reg = function(flag, setting) {
196
+ var base, controller;
197
+ controller = (base = this.controllers)[flag] || (base[flag] = this.$inputor.is('[contentEditable]') ? new EditableController(this, flag) : new TextareaController(this, flag));
198
+ if (setting.alias) {
199
+ this.aliasMaps[setting.alias] = flag;
200
+ }
201
+ controller.init(setting);
202
+ return this;
203
+ };
204
+
205
+ App.prototype.listen = function() {
206
+ return this.$inputor.on('compositionstart', (function(_this) {
207
+ return function(e) {
208
+ var ref;
209
+ if ((ref = _this.controller()) != null) {
210
+ ref.view.hide();
211
+ }
212
+ _this.isComposing = true;
213
+ return null;
214
+ };
215
+ })(this)).on('compositionend', (function(_this) {
216
+ return function(e) {
217
+ _this.isComposing = false;
218
+ setTimeout(function(e) {
219
+ return _this.dispatch(e);
220
+ });
221
+ return null;
222
+ };
223
+ })(this)).on('keyup.atwhoInner', (function(_this) {
224
+ return function(e) {
225
+ return _this.onKeyup(e);
226
+ };
227
+ })(this)).on('keydown.atwhoInner', (function(_this) {
228
+ return function(e) {
229
+ return _this.onKeydown(e);
230
+ };
231
+ })(this)).on('blur.atwhoInner', (function(_this) {
232
+ return function(e) {
233
+ var c;
234
+ if (c = _this.controller()) {
235
+ c.expectedQueryCBId = null;
236
+ return c.view.hide(e, c.getOpt("displayTimeout"));
237
+ }
238
+ };
239
+ })(this)).on('click.atwhoInner', (function(_this) {
240
+ return function(e) {
241
+ return _this.dispatch(e);
242
+ };
243
+ })(this)).on('scroll.atwhoInner', (function(_this) {
244
+ return function() {
245
+ var lastScrollTop;
246
+ lastScrollTop = _this.$inputor.scrollTop();
247
+ return function(e) {
248
+ var currentScrollTop, ref;
249
+ currentScrollTop = e.target.scrollTop;
250
+ if (lastScrollTop !== currentScrollTop) {
251
+ if ((ref = _this.controller()) != null) {
252
+ ref.view.hide(e);
253
+ }
254
+ }
255
+ lastScrollTop = currentScrollTop;
256
+ return true;
257
+ };
258
+ };
259
+ })(this)());
260
+ };
261
+
262
+ App.prototype.shutdown = function() {
263
+ var _, c, ref;
264
+ ref = this.controllers;
265
+ for (_ in ref) {
266
+ c = ref[_];
267
+ c.destroy();
268
+ delete this.controllers[_];
269
+ }
270
+ this.$inputor.off('.atwhoInner');
271
+ return this.$el.remove();
272
+ };
273
+
274
+ App.prototype.dispatch = function(e) {
275
+ var _, c, ref, results;
276
+ ref = this.controllers;
277
+ results = [];
278
+ for (_ in ref) {
279
+ c = ref[_];
280
+ results.push(c.lookUp(e));
281
+ }
282
+ return results;
283
+ };
284
+
285
+ App.prototype.onKeyup = function(e) {
286
+ var ref;
287
+ switch (e.keyCode) {
288
+ case KEY_CODE.ESC:
289
+ e.preventDefault();
290
+ if ((ref = this.controller()) != null) {
291
+ ref.view.hide();
292
+ }
293
+ break;
294
+ case KEY_CODE.DOWN:
295
+ case KEY_CODE.UP:
296
+ case KEY_CODE.CTRL:
297
+ case KEY_CODE.ENTER:
298
+ $.noop();
299
+ break;
300
+ case KEY_CODE.P:
301
+ case KEY_CODE.N:
302
+ if (!e.ctrlKey) {
303
+ this.dispatch(e);
304
+ }
305
+ break;
306
+ default:
307
+ this.dispatch(e);
308
+ }
309
+ };
310
+
311
+ App.prototype.onKeydown = function(e) {
312
+ var ref, view;
313
+ view = (ref = this.controller()) != null ? ref.view : void 0;
314
+ if (!(view && view.visible())) {
315
+ return;
316
+ }
317
+ switch (e.keyCode) {
318
+ case KEY_CODE.ESC:
319
+ e.preventDefault();
320
+ view.hide(e);
321
+ break;
322
+ case KEY_CODE.UP:
323
+ e.preventDefault();
324
+ view.prev();
325
+ break;
326
+ case KEY_CODE.DOWN:
327
+ e.preventDefault();
328
+ view.next();
329
+ break;
330
+ case KEY_CODE.P:
331
+ if (!e.ctrlKey) {
332
+ return;
333
+ }
334
+ e.preventDefault();
335
+ view.prev();
336
+ break;
337
+ case KEY_CODE.N:
338
+ if (!e.ctrlKey) {
339
+ return;
340
+ }
341
+ e.preventDefault();
342
+ view.next();
343
+ break;
344
+ case KEY_CODE.TAB:
345
+ case KEY_CODE.ENTER:
346
+ case KEY_CODE.SPACE:
347
+ if (!view.visible()) {
348
+ return;
349
+ }
350
+ if (!this.controller().getOpt('spaceSelectsMatch') && e.keyCode === KEY_CODE.SPACE) {
351
+ return;
352
+ }
353
+ if (!this.controller().getOpt('tabSelectsMatch') && e.keyCode === KEY_CODE.TAB) {
354
+ return;
355
+ }
356
+ if (view.highlighted()) {
357
+ e.preventDefault();
358
+ view.choose(e);
359
+ } else {
360
+ view.hide(e);
361
+ }
362
+ break;
363
+ default:
364
+ $.noop();
365
+ }
366
+ };
367
+
368
+ return App;
369
+
370
+ })();
371
+
372
+ var Controller,
373
+ slice = [].slice;
374
+
375
+ Controller = (function() {
376
+ Controller.prototype.uid = function() {
377
+ return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime());
378
+ };
379
+
380
+ function Controller(app, at1) {
381
+ this.app = app;
382
+ this.at = at1;
383
+ this.$inputor = this.app.$inputor;
384
+ this.id = this.$inputor[0].id || this.uid();
385
+ this.expectedQueryCBId = null;
386
+ this.setting = null;
387
+ this.query = null;
388
+ this.pos = 0;
389
+ this.range = null;
390
+ if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) {
391
+ this.app.$el.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
392
+ }
393
+ this.model = new Model(this);
394
+ this.view = new View(this);
395
+ }
396
+
397
+ Controller.prototype.init = function(setting) {
398
+ this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
399
+ this.view.init();
400
+ return this.model.reload(this.setting.data);
401
+ };
402
+
403
+ Controller.prototype.destroy = function() {
404
+ this.trigger('beforeDestroy');
405
+ this.model.destroy();
406
+ this.view.destroy();
407
+ return this.$el.remove();
408
+ };
409
+
410
+ Controller.prototype.callDefault = function() {
411
+ var args, error, error1, funcName;
412
+ funcName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
413
+ try {
414
+ return DEFAULT_CALLBACKS[funcName].apply(this, args);
415
+ } catch (error1) {
416
+ error = error1;
417
+ return $.error(error + " Or maybe At.js doesn't have function " + funcName);
418
+ }
419
+ };
420
+
421
+ Controller.prototype.trigger = function(name, data) {
422
+ var alias, eventName;
423
+ if (data == null) {
424
+ data = [];
425
+ }
426
+ data.push(this);
427
+ alias = this.getOpt('alias');
428
+ eventName = alias ? name + "-" + alias + ".atwho" : name + ".atwho";
429
+ return this.$inputor.trigger(eventName, data);
430
+ };
431
+
432
+ Controller.prototype.callbacks = function(funcName) {
433
+ return this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName];
434
+ };
435
+
436
+ Controller.prototype.getOpt = function(at, default_value) {
437
+ var e, error1;
438
+ try {
439
+ return this.setting[at];
440
+ } catch (error1) {
441
+ e = error1;
442
+ return null;
443
+ }
444
+ };
445
+
446
+ Controller.prototype.insertContentFor = function($li) {
447
+ var data, tpl;
448
+ tpl = this.getOpt('insertTpl');
449
+ data = $.extend({}, $li.data('item-data'), {
450
+ 'atwho-at': this.at
451
+ });
452
+ return this.callbacks("tplEval").call(this, tpl, data, "onInsert");
453
+ };
454
+
455
+ Controller.prototype.renderView = function(data) {
456
+ var searchKey;
457
+ searchKey = this.getOpt("searchKey");
458
+ data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), searchKey);
459
+ return this.view.render(data.slice(0, this.getOpt('limit')));
460
+ };
461
+
462
+ Controller.arrayToDefaultHash = function(data) {
463
+ var i, item, len, results;
464
+ if (!$.isArray(data)) {
465
+ return data;
466
+ }
467
+ results = [];
468
+ for (i = 0, len = data.length; i < len; i++) {
469
+ item = data[i];
470
+ if ($.isPlainObject(item)) {
471
+ results.push(item);
472
+ } else {
473
+ results.push({
474
+ name: item
475
+ });
476
+ }
477
+ }
478
+ return results;
479
+ };
480
+
481
+ Controller.prototype.lookUp = function(e) {
482
+ var query, wait;
483
+ if (e && e.type === 'click' && !this.getOpt('lookUpOnClick')) {
484
+ return;
485
+ }
486
+ if (this.getOpt('suspendOnComposing') && this.app.isComposing) {
487
+ return;
488
+ }
489
+ query = this.catchQuery(e);
490
+ if (!query) {
491
+ this.expectedQueryCBId = null;
492
+ return query;
493
+ }
494
+ this.app.setContextFor(this.at);
495
+ if (wait = this.getOpt('delay')) {
496
+ this._delayLookUp(query, wait);
497
+ } else {
498
+ this._lookUp(query);
499
+ }
500
+ return query;
501
+ };
502
+
503
+ Controller.prototype._delayLookUp = function(query, wait) {
504
+ var now, remaining;
505
+ now = Date.now ? Date.now() : new Date().getTime();
506
+ this.previousCallTime || (this.previousCallTime = now);
507
+ remaining = wait - (now - this.previousCallTime);
508
+ if ((0 < remaining && remaining < wait)) {
509
+ this.previousCallTime = now;
510
+ this._stopDelayedCall();
511
+ return this.delayedCallTimeout = setTimeout((function(_this) {
512
+ return function() {
513
+ _this.previousCallTime = 0;
514
+ _this.delayedCallTimeout = null;
515
+ return _this._lookUp(query);
516
+ };
517
+ })(this), wait);
518
+ } else {
519
+ this._stopDelayedCall();
520
+ if (this.previousCallTime !== now) {
521
+ this.previousCallTime = 0;
522
+ }
523
+ return this._lookUp(query);
524
+ }
525
+ };
526
+
527
+ Controller.prototype._stopDelayedCall = function() {
528
+ if (this.delayedCallTimeout) {
529
+ clearTimeout(this.delayedCallTimeout);
530
+ return this.delayedCallTimeout = null;
531
+ }
532
+ };
533
+
534
+ Controller.prototype._generateQueryCBId = function() {
535
+ return {};
536
+ };
537
+
538
+ Controller.prototype._lookUp = function(query) {
539
+ var _callback;
540
+ _callback = function(queryCBId, data) {
541
+ if (queryCBId !== this.expectedQueryCBId) {
542
+ return;
543
+ }
544
+ if (data && data.length > 0) {
545
+ return this.renderView(this.constructor.arrayToDefaultHash(data));
546
+ } else {
547
+ return this.view.hide();
548
+ }
549
+ };
550
+ this.expectedQueryCBId = this._generateQueryCBId();
551
+ return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId));
552
+ };
553
+
554
+ return Controller;
555
+
556
+ })();
557
+
558
+ var TextareaController,
559
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
560
+ hasProp = {}.hasOwnProperty;
561
+
562
+ TextareaController = (function(superClass) {
563
+ extend(TextareaController, superClass);
564
+
565
+ function TextareaController() {
566
+ return TextareaController.__super__.constructor.apply(this, arguments);
567
+ }
568
+
569
+ TextareaController.prototype.catchQuery = function() {
570
+ var caretPos, content, end, isString, query, start, subtext;
571
+ content = this.$inputor.val();
572
+ caretPos = this.$inputor.caret('pos', {
573
+ iframe: this.app.iframe
574
+ });
575
+ subtext = content.slice(0, caretPos);
576
+ query = this.callbacks("matcher").call(this, this.at, subtext, this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
577
+ isString = typeof query === 'string';
578
+ if (isString && query.length < this.getOpt('minLen', 0)) {
579
+ return;
580
+ }
581
+ if (isString && query.length <= this.getOpt('maxLen', 20)) {
582
+ start = caretPos - query.length;
583
+ end = start + query.length;
584
+ this.pos = start;
585
+ query = {
586
+ 'text': query,
587
+ 'headPos': start,
588
+ 'endPos': end
589
+ };
590
+ this.trigger("matched", [this.at, query.text]);
591
+ } else {
592
+ query = null;
593
+ this.view.hide();
594
+ }
595
+ return this.query = query;
596
+ };
597
+
598
+ TextareaController.prototype.rect = function() {
599
+ var c, iframeOffset, scaleBottom;
600
+ if (!(c = this.$inputor.caret('offset', this.pos - 1, {
601
+ iframe: this.app.iframe
602
+ }))) {
603
+ return;
604
+ }
605
+ if (this.app.iframe && !this.app.iframeAsRoot) {
606
+ iframeOffset = $(this.app.iframe).offset();
607
+ c.left += iframeOffset.left;
608
+ c.top += iframeOffset.top;
609
+ }
610
+ scaleBottom = this.app.document.selection ? 0 : 2;
611
+ return {
612
+ left: c.left,
613
+ top: c.top,
614
+ bottom: c.top + c.height + scaleBottom
615
+ };
616
+ };
617
+
618
+ TextareaController.prototype.insert = function(content, $li) {
619
+ var $inputor, source, startStr, suffix, text;
620
+ $inputor = this.$inputor;
621
+ source = $inputor.val();
622
+ startStr = source.slice(0, Math.max(this.query.headPos - this.at.length, 0));
623
+ suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || " ";
624
+ content += suffix;
625
+ text = "" + startStr + content + (source.slice(this.query['endPos'] || 0));
626
+ $inputor.val(text);
627
+ $inputor.caret('pos', startStr.length + content.length, {
628
+ iframe: this.app.iframe
629
+ });
630
+ if (!$inputor.is(':focus')) {
631
+ $inputor.focus();
632
+ }
633
+ return $inputor.change();
634
+ };
635
+
636
+ return TextareaController;
637
+
638
+ })(Controller);
639
+
640
+ var EditableController,
641
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
642
+ hasProp = {}.hasOwnProperty;
643
+
644
+ EditableController = (function(superClass) {
645
+ extend(EditableController, superClass);
646
+
647
+ function EditableController() {
648
+ return EditableController.__super__.constructor.apply(this, arguments);
649
+ }
650
+
651
+ EditableController.prototype._getRange = function() {
652
+ var sel;
653
+ sel = this.app.window.getSelection();
654
+ if (sel.rangeCount > 0) {
655
+ return sel.getRangeAt(0);
656
+ }
657
+ };
658
+
659
+ EditableController.prototype._setRange = function(position, node, range) {
660
+ if (range == null) {
661
+ range = this._getRange();
662
+ }
663
+ if (!(range && node)) {
664
+ return;
665
+ }
666
+ node = $(node)[0];
667
+ if (position === 'after') {
668
+ range.setEndAfter(node);
669
+ range.setStartAfter(node);
670
+ } else {
671
+ range.setEndBefore(node);
672
+ range.setStartBefore(node);
673
+ }
674
+ range.collapse(false);
675
+ return this._clearRange(range);
676
+ };
677
+
678
+ EditableController.prototype._clearRange = function(range) {
679
+ var sel;
680
+ if (range == null) {
681
+ range = this._getRange();
682
+ }
683
+ sel = this.app.window.getSelection();
684
+ if (this.ctrl_a_pressed == null) {
685
+ sel.removeAllRanges();
686
+ return sel.addRange(range);
687
+ }
688
+ };
689
+
690
+ EditableController.prototype._movingEvent = function(e) {
691
+ var ref;
692
+ return e.type === 'click' || ((ref = e.which) === KEY_CODE.RIGHT || ref === KEY_CODE.LEFT || ref === KEY_CODE.UP || ref === KEY_CODE.DOWN);
693
+ };
694
+
695
+ EditableController.prototype._unwrap = function(node) {
696
+ var next;
697
+ node = $(node).unwrap().get(0);
698
+ if ((next = node.nextSibling) && next.nodeValue) {
699
+ node.nodeValue += next.nodeValue;
700
+ $(next).remove();
701
+ }
702
+ return node;
703
+ };
704
+
705
+ EditableController.prototype.catchQuery = function(e) {
706
+ var $inserted, $query, _range, index, inserted, isString, lastNode, matched, offset, query, query_content, range;
707
+ if (!(range = this._getRange())) {
708
+ return;
709
+ }
710
+ if (!range.collapsed) {
711
+ return;
712
+ }
713
+ if (e.which === KEY_CODE.ENTER) {
714
+ ($query = $(range.startContainer).closest('.atwho-query')).contents().unwrap();
715
+ if ($query.is(':empty')) {
716
+ $query.remove();
717
+ }
718
+ ($query = $(".atwho-query", this.app.document)).text($query.text()).contents().last().unwrap();
719
+ this._clearRange();
720
+ return;
721
+ }
722
+ if (/firefox/i.test(navigator.userAgent)) {
723
+ if ($(range.startContainer).is(this.$inputor)) {
724
+ this._clearRange();
725
+ return;
726
+ }
727
+ if (e.which === KEY_CODE.BACKSPACE && range.startContainer.nodeType === document.ELEMENT_NODE && (offset = range.startOffset - 1) >= 0) {
728
+ _range = range.cloneRange();
729
+ _range.setStart(range.startContainer, offset);
730
+ if ($(_range.cloneContents()).contents().last().is('.atwho-inserted')) {
731
+ inserted = $(range.startContainer).contents().get(offset);
732
+ this._setRange('after', $(inserted).contents().last());
733
+ }
734
+ } else if (e.which === KEY_CODE.LEFT && range.startContainer.nodeType === document.TEXT_NODE) {
735
+ $inserted = $(range.startContainer.previousSibling);
736
+ if ($inserted.is('.atwho-inserted') && range.startOffset === 0) {
737
+ this._setRange('after', $inserted.contents().last());
738
+ }
739
+ }
740
+ }
741
+ $(range.startContainer).closest('.atwho-inserted').addClass('atwho-query').siblings().removeClass('atwho-query');
742
+ if (($query = $(".atwho-query", this.app.document)).length > 0 && $query.is(':empty') && $query.text().length === 0) {
743
+ $query.remove();
744
+ }
745
+ if (!this._movingEvent(e)) {
746
+ $query.removeClass('atwho-inserted');
747
+ }
748
+ if ($query.length > 0) {
749
+ switch (e.which) {
750
+ case KEY_CODE.LEFT:
751
+ this._setRange('before', $query.get(0), range);
752
+ $query.removeClass('atwho-query');
753
+ return;
754
+ case KEY_CODE.RIGHT:
755
+ this._setRange('after', $query.get(0).nextSibling, range);
756
+ $query.removeClass('atwho-query');
757
+ return;
758
+ }
759
+ }
760
+ if ($query.length > 0 && (query_content = $query.attr('data-atwho-at-query'))) {
761
+ $query.empty().html(query_content).attr('data-atwho-at-query', null);
762
+ this._setRange('after', $query.get(0), range);
763
+ }
764
+ _range = range.cloneRange();
765
+ _range.setStart(range.startContainer, 0);
766
+ matched = this.callbacks("matcher").call(this, this.at, _range.toString(), this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
767
+ isString = typeof matched === 'string';
768
+ if ($query.length === 0 && isString && (index = range.startOffset - this.at.length - matched.length) >= 0) {
769
+ range.setStart(range.startContainer, index);
770
+ $query = $('<span/>', this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass('atwho-query');
771
+ range.surroundContents($query.get(0));
772
+ lastNode = $query.contents().last().get(0);
773
+ if (lastNode) {
774
+ if (/firefox/i.test(navigator.userAgent)) {
775
+ range.setStart(lastNode, lastNode.length);
776
+ range.setEnd(lastNode, lastNode.length);
777
+ this._clearRange(range);
778
+ } else {
779
+ this._setRange('after', lastNode, range);
780
+ }
781
+ }
782
+ }
783
+ if (isString && matched.length < this.getOpt('minLen', 0)) {
784
+ return;
785
+ }
786
+ if (isString && matched.length <= this.getOpt('maxLen', 20)) {
787
+ query = {
788
+ text: matched,
789
+ el: $query
790
+ };
791
+ this.trigger("matched", [this.at, query.text]);
792
+ return this.query = query;
793
+ } else {
794
+ this.view.hide();
795
+ this.query = {
796
+ el: $query
797
+ };
798
+ if ($query.text().indexOf(this.at) >= 0) {
799
+ if (this._movingEvent(e) && $query.hasClass('atwho-inserted')) {
800
+ $query.removeClass('atwho-query');
801
+ } else if (false !== this.callbacks('afterMatchFailed').call(this, this.at, $query)) {
802
+ this._setRange("after", this._unwrap($query.text($query.text()).contents().first()));
803
+ }
804
+ }
805
+ return null;
806
+ }
807
+ };
808
+
809
+ EditableController.prototype.rect = function() {
810
+ var $iframe, iframeOffset, rect;
811
+ rect = this.query.el.offset();
812
+ if (!(rect && this.query.el[0].getClientRects().length)) {
813
+ return;
814
+ }
815
+ if (this.app.iframe && !this.app.iframeAsRoot) {
816
+ iframeOffset = ($iframe = $(this.app.iframe)).offset();
817
+ rect.left += iframeOffset.left - this.$inputor.scrollLeft();
818
+ rect.top += iframeOffset.top - this.$inputor.scrollTop();
819
+ }
820
+ rect.bottom = rect.top + this.query.el.height();
821
+ return rect;
822
+ };
823
+
824
+ EditableController.prototype.insert = function(content, $li) {
825
+ var data, overrides, range, suffix, suffixNode;
826
+ if (!this.$inputor.is(':focus')) {
827
+ this.$inputor.focus();
828
+ }
829
+ overrides = this.getOpt('functionOverrides');
830
+ if (overrides.insert) {
831
+ return overrides.insert.call(this, content, $li);
832
+ }
833
+ suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || "\u00A0";
834
+ data = $li.data('item-data');
835
+ this.query.el.removeClass('atwho-query').addClass('atwho-inserted').html(content).attr('data-atwho-at-query', "" + data['atwho-at'] + this.query.text).attr('contenteditable', "false");
836
+ if (range = this._getRange()) {
837
+ if (this.query.el.length) {
838
+ range.setEndAfter(this.query.el[0]);
839
+ }
840
+ range.collapse(false);
841
+ range.insertNode(suffixNode = this.app.document.createTextNode("" + suffix));
842
+ this._setRange('after', suffixNode, range);
843
+ }
844
+ if (!this.$inputor.is(':focus')) {
845
+ this.$inputor.focus();
846
+ }
847
+ return this.$inputor.change();
848
+ };
849
+
850
+ return EditableController;
851
+
852
+ })(Controller);
853
+
854
+ var Model;
855
+
856
+ Model = (function() {
857
+ function Model(context) {
858
+ this.context = context;
859
+ this.at = this.context.at;
860
+ this.storage = this.context.$inputor;
861
+ }
862
+
863
+ Model.prototype.destroy = function() {
864
+ return this.storage.data(this.at, null);
865
+ };
866
+
867
+ Model.prototype.saved = function() {
868
+ return this.fetch() > 0;
869
+ };
870
+
871
+ Model.prototype.query = function(query, callback) {
872
+ var _remoteFilter, data, searchKey;
873
+ data = this.fetch();
874
+ searchKey = this.context.getOpt("searchKey");
875
+ data = this.context.callbacks('filter').call(this.context, query, data, searchKey) || [];
876
+ _remoteFilter = this.context.callbacks('remoteFilter');
877
+ if (data.length > 0 || (!_remoteFilter && data.length === 0)) {
878
+ return callback(data);
879
+ } else {
880
+ return _remoteFilter.call(this.context, query, callback);
881
+ }
882
+ };
883
+
884
+ Model.prototype.fetch = function() {
885
+ return this.storage.data(this.at) || [];
886
+ };
887
+
888
+ Model.prototype.save = function(data) {
889
+ return this.storage.data(this.at, this.context.callbacks("beforeSave").call(this.context, data || []));
890
+ };
891
+
892
+ Model.prototype.load = function(data) {
893
+ if (!(this.saved() || !data)) {
894
+ return this._load(data);
895
+ }
896
+ };
897
+
898
+ Model.prototype.reload = function(data) {
899
+ return this._load(data);
900
+ };
901
+
902
+ Model.prototype._load = function(data) {
903
+ if (typeof data === "string") {
904
+ return $.ajax(data, {
905
+ dataType: "json"
906
+ }).done((function(_this) {
907
+ return function(data) {
908
+ return _this.save(data);
909
+ };
910
+ })(this));
911
+ } else {
912
+ return this.save(data);
913
+ }
914
+ };
915
+
916
+ return Model;
917
+
918
+ })();
919
+
920
+ var View;
921
+
922
+ View = (function() {
923
+ function View(context) {
924
+ this.context = context;
925
+ this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
926
+ this.$elUl = this.$el.children();
927
+ this.timeoutID = null;
928
+ this.context.$el.append(this.$el);
929
+ this.bindEvent();
930
+ }
931
+
932
+ View.prototype.init = function() {
933
+ var header_tpl, id;
934
+ id = this.context.getOpt("alias") || this.context.at.charCodeAt(0);
935
+ header_tpl = this.context.getOpt("headerTpl");
936
+ if (header_tpl && this.$el.children().length === 1) {
937
+ this.$el.prepend(header_tpl);
938
+ }
939
+ return this.$el.attr({
940
+ 'id': "at-view-" + id
941
+ });
942
+ };
943
+
944
+ View.prototype.destroy = function() {
945
+ return this.$el.remove();
946
+ };
947
+
948
+ View.prototype.bindEvent = function() {
949
+ var $menu, lastCoordX, lastCoordY;
950
+ $menu = this.$el.find('ul');
951
+ lastCoordX = 0;
952
+ lastCoordY = 0;
953
+ return $menu.on('mousemove.atwho-view', 'li', (function(_this) {
954
+ return function(e) {
955
+ var $cur;
956
+ if (lastCoordX === e.clientX && lastCoordY === e.clientY) {
957
+ return;
958
+ }
959
+ lastCoordX = e.clientX;
960
+ lastCoordY = e.clientY;
961
+ $cur = $(e.currentTarget);
962
+ if ($cur.hasClass('cur')) {
963
+ return;
964
+ }
965
+ $menu.find('.cur').removeClass('cur');
966
+ return $cur.addClass('cur');
967
+ };
968
+ })(this)).on('click.atwho-view', 'li', (function(_this) {
969
+ return function(e) {
970
+ $menu.find('.cur').removeClass('cur');
971
+ $(e.currentTarget).addClass('cur');
972
+ _this.choose(e);
973
+ return e.preventDefault();
974
+ };
975
+ })(this));
976
+ };
977
+
978
+ View.prototype.visible = function() {
979
+ return $.expr.filters.visible(this.$el[0]);
980
+ };
981
+
982
+ View.prototype.highlighted = function() {
983
+ return this.$el.find(".cur").length > 0;
984
+ };
985
+
986
+ View.prototype.choose = function(e) {
987
+ var $li, content;
988
+ if (($li = this.$el.find(".cur")).length) {
989
+ content = this.context.insertContentFor($li);
990
+ this.context._stopDelayedCall();
991
+ this.context.insert(this.context.callbacks("beforeInsert").call(this.context, content, $li, e), $li);
992
+ this.context.trigger("inserted", [$li, e]);
993
+ this.hide(e);
994
+ }
995
+ if (this.context.getOpt("hideWithoutSuffix")) {
996
+ return this.stopShowing = true;
997
+ }
998
+ };
999
+
1000
+ View.prototype.reposition = function(rect) {
1001
+ var _window, offset, overflowOffset, ref;
1002
+ _window = this.context.app.iframeAsRoot ? this.context.app.window : window;
1003
+ if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) {
1004
+ rect.bottom = rect.top - this.$el.height();
1005
+ }
1006
+ if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) {
1007
+ rect.left = overflowOffset;
1008
+ }
1009
+ offset = {
1010
+ left: rect.left,
1011
+ top: rect.bottom
1012
+ };
1013
+ if ((ref = this.context.callbacks("beforeReposition")) != null) {
1014
+ ref.call(this.context, offset);
1015
+ }
1016
+ this.$el.offset(offset);
1017
+ return this.context.trigger("reposition", [offset]);
1018
+ };
1019
+
1020
+ View.prototype.next = function() {
1021
+ var cur, next, nextEl, offset;
1022
+ cur = this.$el.find('.cur').removeClass('cur');
1023
+ next = cur.next();
1024
+ if (!next.length) {
1025
+ next = this.$el.find('li:first');
1026
+ }
1027
+ next.addClass('cur');
1028
+ nextEl = next[0];
1029
+ offset = nextEl.offsetTop + nextEl.offsetHeight + (nextEl.nextSibling ? nextEl.nextSibling.offsetHeight : 0);
1030
+ return this.scrollTop(Math.max(0, offset - this.$el.height()));
1031
+ };
1032
+
1033
+ View.prototype.prev = function() {
1034
+ var cur, offset, prev, prevEl;
1035
+ cur = this.$el.find('.cur').removeClass('cur');
1036
+ prev = cur.prev();
1037
+ if (!prev.length) {
1038
+ prev = this.$el.find('li:last');
1039
+ }
1040
+ prev.addClass('cur');
1041
+ prevEl = prev[0];
1042
+ offset = prevEl.offsetTop + prevEl.offsetHeight + (prevEl.nextSibling ? prevEl.nextSibling.offsetHeight : 0);
1043
+ return this.scrollTop(Math.max(0, offset - this.$el.height()));
1044
+ };
1045
+
1046
+ View.prototype.scrollTop = function(scrollTop) {
1047
+ var scrollDuration;
1048
+ scrollDuration = this.context.getOpt('scrollDuration');
1049
+ if (scrollDuration) {
1050
+ return this.$elUl.animate({
1051
+ scrollTop: scrollTop
1052
+ }, scrollDuration);
1053
+ } else {
1054
+ return this.$elUl.scrollTop(scrollTop);
1055
+ }
1056
+ };
1057
+
1058
+ View.prototype.show = function() {
1059
+ var rect;
1060
+ if (this.stopShowing) {
1061
+ this.stopShowing = false;
1062
+ return;
1063
+ }
1064
+ if (!this.visible()) {
1065
+ this.$el.show();
1066
+ this.$el.scrollTop(0);
1067
+ this.context.trigger('shown');
1068
+ }
1069
+ if (rect = this.context.rect()) {
1070
+ return this.reposition(rect);
1071
+ }
1072
+ };
1073
+
1074
+ View.prototype.hide = function(e, time) {
1075
+ var callback;
1076
+ if (!this.visible()) {
1077
+ return;
1078
+ }
1079
+ if (isNaN(time)) {
1080
+ this.$el.hide();
1081
+ return this.context.trigger('hidden', [e]);
1082
+ } else {
1083
+ callback = (function(_this) {
1084
+ return function() {
1085
+ return _this.hide();
1086
+ };
1087
+ })(this);
1088
+ clearTimeout(this.timeoutID);
1089
+ return this.timeoutID = setTimeout(callback, time);
1090
+ }
1091
+ };
1092
+
1093
+ View.prototype.render = function(list) {
1094
+ var $li, $ul, i, item, len, li, tpl;
1095
+ if (!($.isArray(list) && list.length > 0)) {
1096
+ this.hide();
1097
+ return;
1098
+ }
1099
+ this.$el.find('ul').empty();
1100
+ $ul = this.$el.find('ul');
1101
+ tpl = this.context.getOpt('displayTpl');
1102
+ for (i = 0, len = list.length; i < len; i++) {
1103
+ item = list[i];
1104
+ item = $.extend({}, item, {
1105
+ 'atwho-at': this.context.at
1106
+ });
1107
+ li = this.context.callbacks("tplEval").call(this.context, tpl, item, "onDisplay");
1108
+ $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
1109
+ $li.data("item-data", item);
1110
+ $ul.append($li);
1111
+ }
1112
+ this.show();
1113
+ if (this.context.getOpt('highlightFirst')) {
1114
+ return $ul.find("li:first").addClass("cur");
1115
+ }
1116
+ };
1117
+
1118
+ return View;
1119
+
1120
+ })();
1121
+
1122
+ var Api;
1123
+
1124
+ Api = {
1125
+ load: function(at, data) {
1126
+ var c;
1127
+ if (c = this.controller(at)) {
1128
+ return c.model.load(data);
1129
+ }
1130
+ },
1131
+ isSelecting: function() {
1132
+ var ref;
1133
+ return !!((ref = this.controller()) != null ? ref.view.visible() : void 0);
1134
+ },
1135
+ hide: function() {
1136
+ var ref;
1137
+ return (ref = this.controller()) != null ? ref.view.hide() : void 0;
1138
+ },
1139
+ reposition: function() {
1140
+ var c;
1141
+ if (c = this.controller()) {
1142
+ return c.view.reposition(c.rect());
1143
+ }
1144
+ },
1145
+ setIframe: function(iframe, asRoot) {
1146
+ this.setupRootElement(iframe, asRoot);
1147
+ return null;
1148
+ },
1149
+ run: function() {
1150
+ return this.dispatch();
1151
+ },
1152
+ destroy: function() {
1153
+ this.shutdown();
1154
+ return this.$inputor.data('atwho', null);
1155
+ }
1156
+ };
1157
+
1158
+ $.fn.atwho = function(method) {
1159
+ var _args, result;
1160
+ _args = arguments;
1161
+ result = null;
1162
+ this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() {
1163
+ var $this, app;
1164
+ if (!(app = ($this = $(this)).data("atwho"))) {
1165
+ $this.data('atwho', (app = new App(this)));
1166
+ }
1167
+ if (typeof method === 'object' || !method) {
1168
+ return app.reg(method.at, method);
1169
+ } else if (Api[method] && app) {
1170
+ return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
1171
+ } else {
1172
+ return $.error("Method " + method + " does not exist on jQuery.atwho");
1173
+ }
1174
+ });
1175
+ if (result != null) {
1176
+ return result;
1177
+ } else {
1178
+ return this;
1179
+ }
1180
+ };
1181
+
1182
+ $.fn.atwho["default"] = {
1183
+ at: void 0,
1184
+ alias: void 0,
1185
+ data: null,
1186
+ displayTpl: "<li>${name}</li>",
1187
+ insertTpl: "${atwho-at}${name}",
1188
+ headerTpl: null,
1189
+ callbacks: DEFAULT_CALLBACKS,
1190
+ functionOverrides: {},
1191
+ searchKey: "name",
1192
+ suffix: void 0,
1193
+ hideWithoutSuffix: false,
1194
+ startWithSpace: true,
1195
+ acceptSpaceBar: false,
1196
+ highlightFirst: true,
1197
+ limit: 5,
1198
+ maxLen: 20,
1199
+ minLen: 0,
1200
+ displayTimeout: 300,
1201
+ delay: null,
1202
+ spaceSelectsMatch: false,
1203
+ tabSelectsMatch: true,
1204
+ editableAtwhoQueryAttrs: {},
1205
+ scrollDuration: 150,
1206
+ suspendOnComposing: true,
1207
+ lookUpOnClick: true
1208
+ };
1209
+
1210
+ $.fn.atwho.debug = false;
1211
+
1212
+ }));
bp-core/js/vendor/jquery.atwho.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t,e){"function"==typeof define&&define.amd?define(["jquery"],function(t){return e(t)}):"object"==typeof exports?module.exports=e(require("jquery")):e(jQuery)}(0,function(t){var e,i;i={ESC:27,TAB:9,ENTER:13,CTRL:17,A:65,P:80,N:78,LEFT:37,UP:38,RIGHT:39,DOWN:40,BACKSPACE:8,SPACE:32},e={beforeSave:function(t){return r.arrayToDefaultHash(t)},matcher:function(t,e,i,n){var r,o,s,a,l;return t=t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),i&&(t="(?:^|\\s)"+t),r=decodeURI("%C3%80"),o=decodeURI("%C3%BF"),l=n?" ":"",a=new RegExp(t+"([A-Za-z"+r+"-"+o+"0-9_"+l+"'.+-]*)$|"+t+"([^\\x00-\\xff]*)$","gi"),s=a.exec(e),s?s[2]||s[1]:null},filter:function(t,e,i){var n,r,o,s;for(n=[],r=0,s=e.length;r<s;r++)o=e[r],~new String(o[i]).toLowerCase().indexOf(t.toLowerCase())&&n.push(o);return n},remoteFilter:null,sorter:function(t,e,i){var n,r,o,s;if(!t)return e;for(n=[],r=0,s=e.length;r<s;r++)(o=e[r]).atwho_order=new String(o[i]).toLowerCase().indexOf(t.toLowerCase()),o.atwho_order>-1&&n.push(o);return n.sort(function(t,e){return t.atwho_order-e.atwho_order})},tplEval:function(t,e){var i;i=t;try{return"string"!=typeof t&&(i=t(e)),i.replace(/\$\{([^\}]*)\}/g,function(t,i,n){return e[i]})}catch(t){return t,""}},highlighter:function(t,e){var i;return e?(i=new RegExp(">\\s*([^<]*?)("+e.replace("+","\\+")+")([^<]*)\\s*<","ig"),t.replace(i,function(t,e,i,n){return"> "+e+"<strong>"+i+"</strong>"+n+" <"})):t},beforeInsert:function(t,e,i){return t},beforeReposition:function(t){return t},afterMatchFailed:function(t,e){}};var n;n=function(){function e(e){this.currentFlag=null,this.controllers={},this.aliasMaps={},this.$inputor=t(e),this.setupRootElement(),this.listen()}return e.prototype.createContainer=function(e){var i;return null!=(i=this.$el)&&i.remove(),t(e.body).append(this.$el=t("<div class='atwho-container'></div>"))},e.prototype.setupRootElement=function(e,i){var n;if(null==i&&(i=!1),e)this.window=e.contentWindow,this.document=e.contentDocument||this.window.document,this.iframe=e;else{this.document=this.$inputor[0].ownerDocument,this.window=this.document.defaultView||this.document.parentWindow;try{this.iframe=this.window.frameElement}catch(e){if(n=e,this.iframe=null,t.fn.atwho.debug)throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n"+n)}}return this.createContainer((this.iframeAsRoot=i)?this.document:document)},e.prototype.controller=function(t){var e,i,n,r;if(this.aliasMaps[t])i=this.controllers[this.aliasMaps[t]];else{r=this.controllers;for(n in r)if(e=r[n],n===t){i=e;break}}return i||this.controllers[this.currentFlag]},e.prototype.setContextFor=function(t){return this.currentFlag=t,this},e.prototype.reg=function(t,e){var i,n;return n=(i=this.controllers)[t]||(i[t]=this.$inputor.is("[contentEditable]")?new h(this,t):new s(this,t)),e.alias&&(this.aliasMaps[e.alias]=t),n.init(e),this},e.prototype.listen=function(){return this.$inputor.on("compositionstart",function(t){return function(e){var i;return null!=(i=t.controller())&&i.view.hide(),t.isComposing=!0,null}}(this)).on("compositionend",function(t){return function(e){return t.isComposing=!1,setTimeout(function(e){return t.dispatch(e)}),null}}(this)).on("keyup.atwhoInner",function(t){return function(e){return t.onKeyup(e)}}(this)).on("keydown.atwhoInner",function(t){return function(e){return t.onKeydown(e)}}(this)).on("blur.atwhoInner",function(t){return function(e){var i;if(i=t.controller())return i.expectedQueryCBId=null,i.view.hide(e,i.getOpt("displayTimeout"))}}(this)).on("click.atwhoInner",function(t){return function(e){return t.dispatch(e)}}(this)).on("scroll.atwhoInner",function(t){return function(){var e;return e=t.$inputor.scrollTop(),function(i){var n,r;return n=i.target.scrollTop,e!==n&&null!=(r=t.controller())&&r.view.hide(i),e=n,!0}}}(this)())},e.prototype.shutdown=function(){var t,e;e=this.controllers;for(t in e)e[t].destroy(),delete this.controllers[t];return this.$inputor.off(".atwhoInner"),this.$el.remove()},e.prototype.dispatch=function(t){var e,i,n,r;n=this.controllers,r=[];for(e in n)i=n[e],r.push(i.lookUp(t));return r},e.prototype.onKeyup=function(e){var n;switch(e.keyCode){case i.ESC:e.preventDefault(),null!=(n=this.controller())&&n.view.hide();break;case i.DOWN:case i.UP:case i.CTRL:case i.ENTER:t.noop();break;case i.P:case i.N:e.ctrlKey||this.dispatch(e);break;default:this.dispatch(e)}},e.prototype.onKeydown=function(e){var n,r;if((r=null!=(n=this.controller())?n.view:void 0)&&r.visible())switch(e.keyCode){case i.ESC:e.preventDefault(),r.hide(e);break;case i.UP:e.preventDefault(),r.prev();break;case i.DOWN:e.preventDefault(),r.next();break;case i.P:if(!e.ctrlKey)return;e.preventDefault(),r.prev();break;case i.N:if(!e.ctrlKey)return;e.preventDefault(),r.next();break;case i.TAB:case i.ENTER:case i.SPACE:if(!r.visible())return;if(!this.controller().getOpt("spaceSelectsMatch")&&e.keyCode===i.SPACE)return;if(!this.controller().getOpt("tabSelectsMatch")&&e.keyCode===i.TAB)return;r.highlighted()?(e.preventDefault(),r.choose(e)):r.hide(e);break;default:t.noop()}},e}();var r,o=[].slice;r=function(){function i(e,i){this.app=e,this.at=i,this.$inputor=this.app.$inputor,this.id=this.$inputor[0].id||this.uid(),this.expectedQueryCBId=null,this.setting=null,this.query=null,this.pos=0,this.range=null,0===(this.$el=t("#atwho-ground-"+this.id,this.app.$el)).length&&this.app.$el.append(this.$el=t("<div id='atwho-ground-"+this.id+"'></div>")),this.model=new u(this),this.view=new c(this)}return i.prototype.uid=function(){return(Math.random().toString(16)+"000000000").substr(2,8)+(new Date).getTime()},i.prototype.init=function(e){return this.setting=t.extend({},this.setting||t.fn.atwho.default,e),this.view.init(),this.model.reload(this.setting.data)},i.prototype.destroy=function(){return this.trigger("beforeDestroy"),this.model.destroy(),this.view.destroy(),this.$el.remove()},i.prototype.callDefault=function(){var i,n,r;r=arguments[0],i=2<=arguments.length?o.call(arguments,1):[];try{return e[r].apply(this,i)}catch(e){return n=e,t.error(n+" Or maybe At.js doesn't have function "+r)}},i.prototype.trigger=function(t,e){var i,n;return null==e&&(e=[]),e.push(this),i=this.getOpt("alias"),n=i?t+"-"+i+".atwho":t+".atwho",this.$inputor.trigger(n,e)},i.prototype.callbacks=function(t){return this.getOpt("callbacks")[t]||e[t]},i.prototype.getOpt=function(t,e){try{return this.setting[t]}catch(t){return t,null}},i.prototype.insertContentFor=function(e){var i,n;return n=this.getOpt("insertTpl"),i=t.extend({},e.data("item-data"),{"atwho-at":this.at}),this.callbacks("tplEval").call(this,n,i,"onInsert")},i.prototype.renderView=function(t){var e;return e=this.getOpt("searchKey"),t=this.callbacks("sorter").call(this,this.query.text,t.slice(0,1001),e),this.view.render(t.slice(0,this.getOpt("limit")))},i.arrayToDefaultHash=function(e){var i,n,r,o;if(!t.isArray(e))return e;for(o=[],i=0,r=e.length;i<r;i++)n=e[i],t.isPlainObject(n)?o.push(n):o.push({name:n});return o},i.prototype.lookUp=function(t){var e,i;if((!t||"click"!==t.type||this.getOpt("lookUpOnClick"))&&(!this.getOpt("suspendOnComposing")||!this.app.isComposing))return(e=this.catchQuery(t))?(this.app.setContextFor(this.at),(i=this.getOpt("delay"))?this._delayLookUp(e,i):this._lookUp(e),e):(this.expectedQueryCBId=null,e)},i.prototype._delayLookUp=function(t,e){var i,n;return i=Date.now?Date.now():(new Date).getTime(),this.previousCallTime||(this.previousCallTime=i),n=e-(i-this.previousCallTime),0<n&&n<e?(this.previousCallTime=i,this._stopDelayedCall(),this.delayedCallTimeout=setTimeout(function(e){return function(){return e.previousCallTime=0,e.delayedCallTimeout=null,e._lookUp(t)}}(this),e)):(this._stopDelayedCall(),this.previousCallTime!==i&&(this.previousCallTime=0),this._lookUp(t))},i.prototype._stopDelayedCall=function(){if(this.delayedCallTimeout)return clearTimeout(this.delayedCallTimeout),this.delayedCallTimeout=null},i.prototype._generateQueryCBId=function(){return{}},i.prototype._lookUp=function(e){var i;return i=function(t,e){if(t===this.expectedQueryCBId)return e&&e.length>0?this.renderView(this.constructor.arrayToDefaultHash(e)):this.view.hide()},this.expectedQueryCBId=this._generateQueryCBId(),this.model.query(e.text,t.proxy(i,this,this.expectedQueryCBId))},i}();var s,a=function(t,e){function i(){this.constructor=t}for(var n in e)l.call(e,n)&&(t[n]=e[n]);return i.prototype=e.prototype,t.prototype=new i,t.__super__=e.prototype,t},l={}.hasOwnProperty;s=function(e){function i(){return i.__super__.constructor.apply(this,arguments)}return a(i,e),i.prototype.catchQuery=function(){var t,e,i,n,r,o,s;if(e=this.$inputor.val(),t=this.$inputor.caret("pos",{iframe:this.app.iframe}),s=e.slice(0,t),r=this.callbacks("matcher").call(this,this.at,s,this.getOpt("startWithSpace"),this.getOpt("acceptSpaceBar")),!((n="string"==typeof r)&&r.length<this.getOpt("minLen",0)))return n&&r.length<=this.getOpt("maxLen",20)?(i=(o=t-r.length)+r.length,this.pos=o,r={text:r,headPos:o,endPos:i},this.trigger("matched",[this.at,r.text])):(r=null,this.view.hide()),this.query=r},i.prototype.rect=function(){var e,i,n;if(e=this.$inputor.caret("offset",this.pos-1,{iframe:this.app.iframe}))return this.app.iframe&&!this.app.iframeAsRoot&&(i=t(this.app.iframe).offset(),e.left+=i.left,e.top+=i.top),n=this.app.document.selection?0:2,{left:e.left,top:e.top,bottom:e.top+e.height+n}},i.prototype.insert=function(t,e){var i,n,r,o,s;return i=this.$inputor,n=i.val(),r=n.slice(0,Math.max(this.query.headPos-this.at.length,0)),o=""===(o=this.getOpt("suffix"))?o:o||" ",t+=o,s=""+r+t+n.slice(this.query.endPos||0),i.val(s),i.caret("pos",r.length+t.length,{iframe:this.app.iframe}),i.is(":focus")||i.focus(),i.change()},i}(r);var h,a=function(t,e){function i(){this.constructor=t}for(var n in e)l.call(e,n)&&(t[n]=e[n]);return i.prototype=e.prototype,t.prototype=new i,t.__super__=e.prototype,t},l={}.hasOwnProperty;h=function(e){function n(){return n.__super__.constructor.apply(this,arguments)}return a(n,e),n.prototype._getRange=function(){var t;if((t=this.app.window.getSelection()).rangeCount>0)return t.getRangeAt(0)},n.prototype._setRange=function(e,i,n){if(null==n&&(n=this._getRange()),n&&i)return i=t(i)[0],"after"===e?(n.setEndAfter(i),n.setStartAfter(i)):(n.setEndBefore(i),n.setStartBefore(i)),n.collapse(!1),this._clearRange(n)},n.prototype._clearRange=function(t){var e;if(null==t&&(t=this._getRange()),e=this.app.window.getSelection(),null==this.ctrl_a_pressed)return e.removeAllRanges(),e.addRange(t)},n.prototype._movingEvent=function(t){var e;return"click"===t.type||(e=t.which)===i.RIGHT||e===i.LEFT||e===i.UP||e===i.DOWN},n.prototype._unwrap=function(e){var i;return e=t(e).unwrap().get(0),(i=e.nextSibling)&&i.nodeValue&&(e.nodeValue+=i.nodeValue,t(i).remove()),e},n.prototype.catchQuery=function(e){var n,r,o,s,a,l,h,u,c,p,f,d;if((d=this._getRange())&&d.collapsed){if(e.which===i.ENTER)return(r=t(d.startContainer).closest(".atwho-query")).contents().unwrap(),r.is(":empty")&&r.remove(),(r=t(".atwho-query",this.app.document)).text(r.text()).contents().last().unwrap(),void this._clearRange();if(/firefox/i.test(navigator.userAgent)){if(t(d.startContainer).is(this.$inputor))return void this._clearRange();e.which===i.BACKSPACE&&d.startContainer.nodeType===document.ELEMENT_NODE&&(c=d.startOffset-1)>=0?((o=d.cloneRange()).setStart(d.startContainer,c),t(o.cloneContents()).contents().last().is(".atwho-inserted")&&(a=t(d.startContainer).contents().get(c),this._setRange("after",t(a).contents().last()))):e.which===i.LEFT&&d.startContainer.nodeType===document.TEXT_NODE&&(n=t(d.startContainer.previousSibling)).is(".atwho-inserted")&&0===d.startOffset&&this._setRange("after",n.contents().last())}if(t(d.startContainer).closest(".atwho-inserted").addClass("atwho-query").siblings().removeClass("atwho-query"),(r=t(".atwho-query",this.app.document)).length>0&&r.is(":empty")&&0===r.text().length&&r.remove(),this._movingEvent(e)||r.removeClass("atwho-inserted"),r.length>0)switch(e.which){case i.LEFT:return this._setRange("before",r.get(0),d),void r.removeClass("atwho-query");case i.RIGHT:return this._setRange("after",r.get(0).nextSibling,d),void r.removeClass("atwho-query")}if(r.length>0&&(f=r.attr("data-atwho-at-query"))&&(r.empty().html(f).attr("data-atwho-at-query",null),this._setRange("after",r.get(0),d)),(o=d.cloneRange()).setStart(d.startContainer,0),u=this.callbacks("matcher").call(this,this.at,o.toString(),this.getOpt("startWithSpace"),this.getOpt("acceptSpaceBar")),l="string"==typeof u,0===r.length&&l&&(s=d.startOffset-this.at.length-u.length)>=0&&(d.setStart(d.startContainer,s),r=t("<span/>",this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass("atwho-query"),d.surroundContents(r.get(0)),(h=r.contents().last().get(0))&&(/firefox/i.test(navigator.userAgent)?(d.setStart(h,h.length),d.setEnd(h,h.length),this._clearRange(d)):this._setRange("after",h,d))),!(l&&u.length<this.getOpt("minLen",0)))return l&&u.length<=this.getOpt("maxLen",20)?(p={text:u,el:r},this.trigger("matched",[this.at,p.text]),this.query=p):(this.view.hide(),this.query={el:r},r.text().indexOf(this.at)>=0&&(this._movingEvent(e)&&r.hasClass("atwho-inserted")?r.removeClass("atwho-query"):!1!==this.callbacks("afterMatchFailed").call(this,this.at,r)&&this._setRange("after",this._unwrap(r.text(r.text()).contents().first()))),null)}},n.prototype.rect=function(){var e,i;if((i=this.query.el.offset())&&this.query.el[0].getClientRects().length)return this.app.iframe&&!this.app.iframeAsRoot&&(e=t(this.app.iframe).offset(),i.left+=e.left-this.$inputor.scrollLeft(),i.top+=e.top-this.$inputor.scrollTop()),i.bottom=i.top+this.query.el.height(),i},n.prototype.insert=function(t,e){var i,n,r,o,s;return this.$inputor.is(":focus")||this.$inputor.focus(),(n=this.getOpt("functionOverrides")).insert?n.insert.call(this,t,e):(o=""===(o=this.getOpt("suffix"))?o:o||" ",i=e.data("item-data"),this.query.el.removeClass("atwho-query").addClass("atwho-inserted").html(t).attr("data-atwho-at-query",""+i["atwho-at"]+this.query.text).attr("contenteditable","false"),(r=this._getRange())&&(this.query.el.length&&r.setEndAfter(this.query.el[0]),r.collapse(!1),r.insertNode(s=this.app.document.createTextNode(""+o)),this._setRange("after",s,r)),this.$inputor.is(":focus")||this.$inputor.focus(),this.$inputor.change())},n}(r);var u;u=function(){function e(t){this.context=t,this.at=this.context.at,this.storage=this.context.$inputor}return e.prototype.destroy=function(){return this.storage.data(this.at,null)},e.prototype.saved=function(){return this.fetch()>0},e.prototype.query=function(t,e){var i,n,r;return n=this.fetch(),r=this.context.getOpt("searchKey"),n=this.context.callbacks("filter").call(this.context,t,n,r)||[],i=this.context.callbacks("remoteFilter"),n.length>0||!i&&0===n.length?e(n):i.call(this.context,t,e)},e.prototype.fetch=function(){return this.storage.data(this.at)||[]},e.prototype.save=function(t){return this.storage.data(this.at,this.context.callbacks("beforeSave").call(this.context,t||[]))},e.prototype.load=function(t){if(!this.saved()&&t)return this._load(t)},e.prototype.reload=function(t){return this._load(t)},e.prototype._load=function(e){return"string"==typeof e?t.ajax(e,{dataType:"json"}).done(function(t){return function(e){return t.save(e)}}(this)):this.save(e)},e}();var c;c=function(){function e(e){this.context=e,this.$el=t("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>"),this.$elUl=this.$el.children(),this.timeoutID=null,this.context.$el.append(this.$el),this.bindEvent()}return e.prototype.init=function(){var t,e;return e=this.context.getOpt("alias")||this.context.at.charCodeAt(0),(t=this.context.getOpt("headerTpl"))&&1===this.$el.children().length&&this.$el.prepend(t),this.$el.attr({id:"at-view-"+e})},e.prototype.destroy=function(){return this.$el.remove()},e.prototype.bindEvent=function(){var e,i,n;return e=this.$el.find("ul"),i=0,n=0,e.on("mousemove.atwho-view","li",function(r){return function(r){var o;if((i!==r.clientX||n!==r.clientY)&&(i=r.clientX,n=r.clientY,!(o=t(r.currentTarget)).hasClass("cur")))return e.find(".cur").removeClass("cur"),o.addClass("cur")}}()).on("click.atwho-view","li",function(i){return function(n){return e.find(".cur").removeClass("cur"),t(n.currentTarget).addClass("cur"),i.choose(n),n.preventDefault()}}(this))},e.prototype.visible=function(){return t.expr.filters.visible(this.$el[0])},e.prototype.highlighted=function(){return this.$el.find(".cur").length>0},e.prototype.choose=function(t){var e,i;if((e=this.$el.find(".cur")).length&&(i=this.context.insertContentFor(e),this.context._stopDelayedCall(),this.context.insert(this.context.callbacks("beforeInsert").call(this.context,i,e,t),e),this.context.trigger("inserted",[e,t]),this.hide(t)),this.context.getOpt("hideWithoutSuffix"))return this.stopShowing=!0},e.prototype.reposition=function(e){var i,n,r,o;return i=this.context.app.iframeAsRoot?this.context.app.window:window,e.bottom+this.$el.height()-t(i).scrollTop()>t(i).height()&&(e.bottom=e.top-this.$el.height()),e.left>(r=t(i).width()-this.$el.width()-5)&&(e.left=r),n={left:e.left,top:e.bottom},null!=(o=this.context.callbacks("beforeReposition"))&&o.call(this.context,n),this.$el.offset(n),this.context.trigger("reposition",[n])},e.prototype.next=function(){var t,e,i,n;return t=this.$el.find(".cur").removeClass("cur"),(e=t.next()).length||(e=this.$el.find("li:first")),e.addClass("cur"),i=e[0],n=i.offsetTop+i.offsetHeight+(i.nextSibling?i.nextSibling.offsetHeight:0),this.scrollTop(Math.max(0,n-this.$el.height()))},e.prototype.prev=function(){var t,e,i,n;return t=this.$el.find(".cur").removeClass("cur"),(i=t.prev()).length||(i=this.$el.find("li:last")),i.addClass("cur"),n=i[0],e=n.offsetTop+n.offsetHeight+(n.nextSibling?n.nextSibling.offsetHeight:0),this.scrollTop(Math.max(0,e-this.$el.height()))},e.prototype.scrollTop=function(t){var e;return e=this.context.getOpt("scrollDuration"),e?this.$elUl.animate({scrollTop:t},e):this.$elUl.scrollTop(t)},e.prototype.show=function(){var t;{if(!this.stopShowing)return this.visible()||(this.$el.show(),this.$el.scrollTop(0),this.context.trigger("shown")),(t=this.context.rect())?this.reposition(t):void 0;this.stopShowing=!1}},e.prototype.hide=function(t,e){var i;if(this.visible())return isNaN(e)?(this.$el.hide(),this.context.trigger("hidden",[t])):(i=function(t){return function(){return t.hide()}}(this),clearTimeout(this.timeoutID),this.timeoutID=setTimeout(i,e))},e.prototype.render=function(e){var i,n,r,o,s,a,l;{if(t.isArray(e)&&e.length>0){for(this.$el.find("ul").empty(),n=this.$el.find("ul"),l=this.context.getOpt("displayTpl"),r=0,s=e.length;r<s;r++)o=e[r],o=t.extend({},o,{"atwho-at":this.context.at}),a=this.context.callbacks("tplEval").call(this.context,l,o,"onDisplay"),(i=t(this.context.callbacks("highlighter").call(this.context,a,this.context.query.text))).data("item-data",o),n.append(i);return this.show(),this.context.getOpt("highlightFirst")?n.find("li:first").addClass("cur"):void 0}this.hide()}},e}();var p;p={load:function(t,e){var i;if(i=this.controller(t))return i.model.load(e)},isSelecting:function(){var t;return!!(null!=(t=this.controller())?t.view.visible():void 0)},hide:function(){var t;return null!=(t=this.controller())?t.view.hide():void 0},reposition:function(){var t;if(t=this.controller())return t.view.reposition(t.rect())},setIframe:function(t,e){return this.setupRootElement(t,e),null},run:function(){return this.dispatch()},destroy:function(){return this.shutdown(),this.$inputor.data("atwho",null)}},t.fn.atwho=function(e){var i,r;return i=arguments,r=null,this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function(){var o,s;return(s=(o=t(this)).data("atwho"))||o.data("atwho",s=new n(this)),"object"!=typeof e&&e?p[e]&&s?r=p[e].apply(s,Array.prototype.slice.call(i,1)):t.error("Method "+e+" does not exist on jQuery.atwho"):s.reg(e.at,e)}),null!=r?r:this},t.fn.atwho.default={at:void 0,alias:void 0,data:null,displayTpl:"<li>${name}</li>",insertTpl:"${atwho-at}${name}",headerTpl:null,callbacks:e,functionOverrides:{},searchKey:"name",suffix:void 0,hideWithoutSuffix:!1,startWithSpace:!0,acceptSpaceBar:!1,highlightFirst:!0,limit:5,maxLen:20,minLen:0,displayTimeout:300,delay:null,spaceSelectsMatch:!1,tabSelectsMatch:!0,editableAtwhoQueryAttrs:{},scrollDuration:150,suspendOnComposing:!0,lookUpOnClick:!0},t.fn.atwho.debug=!1});
bp-core/js/{jquery.atwho.txt → vendor/jquery.atwho.txt} RENAMED
File without changes
bp-core/js/{jquery.caret.js → vendor/jquery.caret.js} RENAMED
@@ -40,6 +40,37 @@ EditableCaret = (function() {
40
  }
41
 
42
  EditableCaret.prototype.setPos = function(pos) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  return this.domInputor;
44
  };
45
 
@@ -94,7 +125,7 @@ EditableCaret = (function() {
94
  EditableCaret.prototype.getOffset = function(pos) {
95
  var clonedRange, offset, range, rect, shadowCaret;
96
  if (oWindow.getSelection && (range = this.range())) {
97
- if (range.endOffset - 1 > 0 && range.endContainer === !this.domInputor) {
98
  clonedRange = range.cloneRange();
99
  clonedRange.setStart(range.endContainer, range.endOffset - 1);
100
  clonedRange.setEnd(range.endContainer, range.endOffset);
40
  }
41
 
42
  EditableCaret.prototype.setPos = function(pos) {
43
+ var fn, found, offset, sel;
44
+ if (sel = oWindow.getSelection()) {
45
+ offset = 0;
46
+ found = false;
47
+ (fn = function(pos, parent) {
48
+ var node, range, _i, _len, _ref, _results;
49
+ _ref = parent.childNodes;
50
+ _results = [];
51
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
52
+ node = _ref[_i];
53
+ if (found) {
54
+ break;
55
+ }
56
+ if (node.nodeType === 3) {
57
+ if (offset + node.length >= pos) {
58
+ found = true;
59
+ range = oDocument.createRange();
60
+ range.setStart(node, pos - offset);
61
+ sel.removeAllRanges();
62
+ sel.addRange(range);
63
+ break;
64
+ } else {
65
+ _results.push(offset += node.length);
66
+ }
67
+ } else {
68
+ _results.push(fn(pos, node));
69
+ }
70
+ }
71
+ return _results;
72
+ })(pos, this.domInputor);
73
+ }
74
  return this.domInputor;
75
  };
76
 
125
  EditableCaret.prototype.getOffset = function(pos) {
126
  var clonedRange, offset, range, rect, shadowCaret;
127
  if (oWindow.getSelection && (range = this.range())) {
128
+ if (range.endOffset - 1 > 0 && range.endContainer !== this.domInputor) {
129
  clonedRange = range.cloneRange();
130
  clonedRange.setStart(range.endContainer, range.endOffset - 1);
131
  clonedRange.setEnd(range.endContainer, range.endOffset);
bp-core/js/vendor/jquery.caret.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t,e){"function"==typeof define&&define.amd?define(["jquery"],function(o){return t.returnExportsGlobal=e(o)}):"object"==typeof exports?module.exports=e(require("jquery")):e(jQuery)}(this,function(t){"use strict";var e,o,n,r,i,s,a,l,p;e=function(){function e(t){this.$inputor=t,this.domInputor=this.$inputor[0]}return e.prototype.setPos=function(t){var e,o,n,r;return(r=l.getSelection())&&(n=0,o=!1,(e=function(t,i){var a,l,p,c,f,u;for(u=[],p=0,c=(f=i.childNodes).length;p<c&&(a=f[p],!o);p++)if(3===a.nodeType){if(n+a.length>=t){o=!0,(l=s.createRange()).setStart(a,t-n),r.removeAllRanges(),r.addRange(l);break}u.push(n+=a.length)}else u.push(e(t,a));return u})(t,this.domInputor)),this.domInputor},e.prototype.getIEPosition=function(){return this.getPosition()},e.prototype.getPosition=function(){var t,e;return e=this.getOffset(),t=this.$inputor.offset(),e.left-=t.left,e.top-=t.top,e},e.prototype.getOldIEPos=function(){var t,e;return e=s.selection.createRange(),(t=s.body.createTextRange()).moveToElementText(this.domInputor),t.setEndPoint("EndToEnd",e),t.text.length},e.prototype.getPos=function(){var t,e,o;return(o=this.range())?((t=o.cloneRange()).selectNodeContents(this.domInputor),t.setEnd(o.endContainer,o.endOffset),e=t.toString().length,t.detach(),e):s.selection?this.getOldIEPos():void 0},e.prototype.getOldIEOffset=function(){var t,e;return(t=s.selection.createRange().duplicate()).moveStart("character",-1),e=t.getBoundingClientRect(),{height:e.bottom-e.top,left:e.left,top:e.top}},e.prototype.getOffset=function(e){var o,n,r,i,a;return l.getSelection&&(r=this.range())?(r.endOffset-1>0&&r.endContainer!==this.domInputor&&((o=r.cloneRange()).setStart(r.endContainer,r.endOffset-1),o.setEnd(r.endContainer,r.endOffset),n={height:(i=o.getBoundingClientRect()).height,left:i.left+i.width,top:i.top},o.detach()),n&&0!==(null!=n?n.height:void 0)||(o=r.cloneRange(),a=t(s.createTextNode("|")),o.insertNode(a[0]),o.selectNode(a[0]),n={height:(i=o.getBoundingClientRect()).height,left:i.left,top:i.top},a.remove(),o.detach())):s.selection&&(n=this.getOldIEOffset()),n&&(n.top+=t(l).scrollTop(),n.left+=t(l).scrollLeft()),n},e.prototype.range=function(){var t;if(l.getSelection)return t=l.getSelection(),t.rangeCount>0?t.getRangeAt(0):null},e}(),o=function(){function e(t){this.$inputor=t,this.domInputor=this.$inputor[0]}return e.prototype.getIEPos=function(){var t,e,o,n,r,i;return e=this.domInputor,r=s.selection.createRange(),n=0,r&&r.parentElement()===e&&(o=e.value.replace(/\r\n/g,"\n").length,(i=e.createTextRange()).moveToBookmark(r.getBookmark()),(t=e.createTextRange()).collapse(!1),n=i.compareEndPoints("StartToEnd",t)>-1?o:-i.moveStart("character",-o)),n},e.prototype.getPos=function(){return s.selection?this.getIEPos():this.domInputor.selectionStart},e.prototype.setPos=function(t){var e,o;return e=this.domInputor,s.selection?((o=e.createTextRange()).move("character",t),o.select()):e.setSelectionRange&&e.setSelectionRange(t,t),e},e.prototype.getIEOffset=function(t){var e,o,n,r;return o=this.domInputor.createTextRange(),t||(t=this.getPos()),o.move("character",t),n=o.boundingLeft,r=o.boundingTop,e=o.boundingHeight,{left:n,top:r,height:e}},e.prototype.getOffset=function(e){var o,n,r;return o=this.$inputor,s.selection?(n=this.getIEOffset(e),n.top+=t(l).scrollTop()+o.scrollTop(),n.left+=t(l).scrollLeft()+o.scrollLeft(),n):(n=o.offset(),r=this.getPosition(e),n={left:n.left+r.left-o.scrollLeft(),top:n.top+r.top-o.scrollTop(),height:r.height})},e.prototype.getPosition=function(t){var e,o,r,i,s,a;return e=this.$inputor,r=function(t){return t=t.replace(/<|>|`|"|&/g,"?").replace(/\r\n|\r|\n/g,"<br/>"),/firefox/i.test(navigator.userAgent)&&(t=t.replace(/\s/g,"&nbsp;")),t},void 0===t&&(t=this.getPos()),a=e.val().slice(0,t),o=e.val().slice(t),i="<span style='position: relative; display: inline;'>"+r(a)+"</span>",i+="<span id='caret' style='position: relative; display: inline;'>|</span>",i+="<span style='position: relative; display: inline;'>"+r(o)+"</span>",s=new n(e),s.create(i).rect()},e.prototype.getIEPosition=function(t){var e,o,n,r,i;return n=this.getIEOffset(t),o=this.$inputor.offset(),r=n.left-o.left,i=n.top-o.top,e=n.height,{left:r,top:i,height:e}},e}(),n=function(){function e(t){this.$inputor=t}return e.prototype.css_attr=["borderBottomWidth","borderLeftWidth","borderRightWidth","borderTopStyle","borderRightStyle","borderBottomStyle","borderLeftStyle","borderTopWidth","boxSizing","fontFamily","fontSize","fontWeight","height","letterSpacing","lineHeight","marginBottom","marginLeft","marginRight","marginTop","outlineWidth","overflow","overflowX","overflowY","paddingBottom","paddingLeft","paddingRight","paddingTop","textAlign","textOverflow","textTransform","whiteSpace","wordBreak","wordWrap"],e.prototype.mirrorCss=function(){var e,o=this;return e={position:"absolute",left:-9999,top:0,zIndex:-2e4},"TEXTAREA"===this.$inputor.prop("tagName")&&this.css_attr.push("width"),t.each(this.css_attr,function(t,n){return e[n]=o.$inputor.css(n)}),e},e.prototype.create=function(e){return this.$mirror=t("<div></div>"),this.$mirror.css(this.mirrorCss()),this.$mirror.html(e),this.$inputor.after(this.$mirror),this},e.prototype.rect=function(){var t,e,o;return t=this.$mirror.find("#caret"),e=t.position(),o={left:e.left,top:e.top,height:t.height()},this.$mirror.remove(),o},e}(),r={contentEditable:function(t){return!(!t[0].contentEditable||"true"!==t[0].contentEditable)}},i={pos:function(t){return t||0===t?this.setPos(t):this.getPos()},position:function(t){return s.selection?this.getIEPosition(t):this.getPosition(t)},offset:function(t){return this.getOffset(t)}},s=null,l=null,a=null,p=function(t){var e;return(e=null!=t?t.iframe:void 0)?(a=e,l=e.contentWindow,s=e.contentDocument||l.document):(a=void 0,l=window,s=document)},t.fn.caret=function(n,s,a){var l;return i[n]?(t.isPlainObject(s)?(p(s),s=void 0):p(a),l=r.contentEditable(this)?new e(this):new o(this),i[n].apply(l,[s])):t.error("Method "+n+" does not exist on jQuery.caret")},t.fn.caret.EditableCaret=e,t.fn.caret.InputCaret=o,t.fn.caret.Utils=r,t.fn.caret.apis=i});
bp-core/js/{jquery.caret.txt → vendor/jquery.caret.txt} RENAMED
File without changes
bp-core/js/vendor/livestamp.js ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Livestamp.js / v1.1.2 / (c) 2012 Matt Bradley / MIT License
2
+ (function($, moment) {
3
+ var updateInterval = 1e3,
4
+ paused = false,
5
+ $livestamps = $([]),
6
+
7
+ init = function() {
8
+ livestampGlobal.resume();
9
+ },
10
+
11
+ prep = function($el, timestamp) {
12
+ var oldData = $el.data('livestampdata');
13
+ if (typeof timestamp == 'number')
14
+ timestamp *= 1e3;
15
+
16
+ $el.removeAttr('data-livestamp')
17
+ .removeData('livestamp');
18
+
19
+ timestamp = moment(timestamp);
20
+ if (moment.isMoment(timestamp) && !isNaN(+timestamp)) {
21
+ var newData = $.extend({ }, { 'original': $el.contents() }, oldData);
22
+ newData.moment = moment(timestamp);
23
+
24
+ $el.data('livestampdata', newData).empty();
25
+ $livestamps.push($el[0]);
26
+ }
27
+ },
28
+
29
+ run = function() {
30
+ if (paused) return;
31
+ livestampGlobal.update();
32
+ setTimeout(run, updateInterval);
33
+ },
34
+
35
+ livestampGlobal = {
36
+ update: function() {
37
+ $('[data-livestamp]').each(function() {
38
+ var $this = $(this);
39
+ prep($this, $this.data('livestamp'));
40
+ });
41
+
42
+ var toRemove = [];
43
+ $livestamps.each(function() {
44
+ var $this = $(this),
45
+ data = $this.data('livestampdata');
46
+
47
+ if (data === undefined)
48
+ toRemove.push(this);
49
+ else if (moment.isMoment(data.moment)) {
50
+ var from = $this.html(),
51
+ to = data.moment.fromNow();
52
+
53
+ if (from != to) {
54
+ var e = $.Event('change.livestamp');
55
+ $this.trigger(e, [from, to]);
56
+ if (!e.isDefaultPrevented())
57
+ $this.html(to);
58
+ }
59
+ }
60
+ });
61
+
62
+ $livestamps = $livestamps.not(toRemove);
63
+ },
64
+
65
+ pause: function() {
66
+ paused = true;
67
+ },
68
+
69
+ resume: function() {
70
+ paused = false;
71
+ run();
72
+ },
73
+
74
+ interval: function(interval) {
75
+ if (interval === undefined)
76
+ return updateInterval;
77
+ updateInterval = interval;
78
+ }
79
+ },
80
+
81
+ livestampLocal = {
82
+ add: function($el, timestamp) {
83
+ if (typeof timestamp == 'number')
84
+ timestamp *= 1e3;
85
+ timestamp = moment(timestamp);
86
+
87
+ if (moment.isMoment(timestamp) && !isNaN(+timestamp)) {
88
+ $el.each(function() {
89
+ prep($(this), timestamp);
90
+ });
91
+ livestampGlobal.update();
92
+ }
93
+
94
+ return $el;
95
+ },
96
+
97
+ destroy: function($el) {
98
+ $livestamps = $livestamps.not($el);
99
+ $el.each(function() {
100
+ var $this = $(this),
101
+ data = $this.data('livestampdata');
102
+
103
+ if (data === undefined)
104
+ return $el;
105
+
106
+ $this
107
+ .html(data.original ? data.original : '')
108
+ .removeData('livestampdata');
109
+ });
110
+
111
+ return $el;
112
+ },
113
+
114
+ isLivestamp: function($el) {
115
+ return $el.data('livestampdata') !== undefined;
116
+ }
117
+ };
118
+
119
+ $.livestamp = livestampGlobal;
120
+ $(init);
121
+ $.fn.livestamp = function(method, options) {
122
+ if (!livestampLocal[method]) {
123
+ options = method;
124
+ method = 'add';
125
+ }
126
+
127
+ return livestampLocal[method](this, options);
128
+ };
129
+ })(jQuery, moment);
bp-core/js/vendor/livestamp.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t,a){var e=1e3,i=!1,n=t([]),o=function(){s.resume()},r=function(e,i){var o=e.data("livestampdata");if("number"==typeof i&&(i*=1e3),e.removeAttr("data-livestamp").removeData("livestamp"),i=a(i),a.isMoment(i)&&!isNaN(+i)){var r=t.extend({},{original:e.contents()},o);r.moment=a(i),e.data("livestampdata",r).empty(),n.push(e[0])}},m=function(){i||(s.update(),setTimeout(m,e))},s={update:function(){t("[data-livestamp]").each(function(){var a=t(this);r(a,a.data("livestamp"))});var e=[];n.each(function(){var i=t(this),n=i.data("livestampdata");if(void 0===n)e.push(this);else if(a.isMoment(n.moment)){var o=i.html(),r=n.moment.fromNow();if(o!=r){var m=t.Event("change.livestamp");i.trigger(m,[o,r]),m.isDefaultPrevented()||i.html(r)}}}),n=n.not(e)},pause:function(){i=!0},resume:function(){i=!1,m()},interval:function(t){if(void 0===t)return e;e=t}},u={add:function(e,i){return"number"==typeof i&&(i*=1e3),i=a(i),a.isMoment(i)&&!isNaN(+i)&&(e.each(function(){r(t(this),i)}),s.update()),e},destroy:function(a){return n=n.not(a),a.each(function(){var e=t(this),i=e.data("livestampdata");if(void 0===i)return a;e.html(i.original?i.original:"").removeData("livestampdata")}),a},isLivestamp:function(t){return void 0!==t.data("livestampdata")}};t.livestamp=s,t(o),t.fn.livestamp=function(t,a){return u[t]||(a=t,t="add"),u[t](this,a)}}(jQuery,moment);
bp-core/js/vendor/moment-js/locale/af.js ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Afrikaans [af]
3
+ //! author : Werner Mollentze : https://github.com/wernerm
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var af = moment.defineLocale('af', {
14
+ months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
15
+ monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
16
+ weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
17
+ weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
18
+ weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
19
+ meridiemParse: /vm|nm/i,
20
+ isPM : function (input) {
21
+ return /^nm$/i.test(input);
22
+ },
23
+ meridiem : function (hours, minutes, isLower) {
24
+ if (hours < 12) {
25
+ return isLower ? 'vm' : 'VM';
26
+ } else {
27
+ return isLower ? 'nm' : 'NM';
28
+ }
29
+ },
30
+ longDateFormat : {
31
+ LT : 'HH:mm',
32
+ LTS : 'HH:mm:ss',
33
+ L : 'DD/MM/YYYY',
34
+ LL : 'D MMMM YYYY',
35
+ LLL : 'D MMMM YYYY HH:mm',
36
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
37
+ },
38
+ calendar : {
39
+ sameDay : '[Vandag om] LT',
40
+ nextDay : '[Môre om] LT',
41
+ nextWeek : 'dddd [om] LT',
42
+ lastDay : '[Gister om] LT',
43
+ lastWeek : '[Laas] dddd [om] LT',
44
+ sameElse : 'L'
45
+ },
46
+ relativeTime : {
47
+ future : 'oor %s',
48
+ past : '%s gelede',
49
+ s : '\'n paar sekondes',
50
+ m : '\'n minuut',
51
+ mm : '%d minute',
52
+ h : '\'n uur',
53
+ hh : '%d ure',
54
+ d : '\'n dag',
55
+ dd : '%d dae',
56
+ M : '\'n maand',
57
+ MM : '%d maande',
58
+ y : '\'n jaar',
59
+ yy : '%d jaar'
60
+ },
61
+ ordinalParse: /\d{1,2}(ste|de)/,
62
+ ordinal : function (number) {
63
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
64
+ },
65
+ week : {
66
+ dow : 1, // Maandag is die eerste dag van die week.
67
+ doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
68
+ }
69
+ });
70
+
71
+ return af;
72
+
73
+ }));
bp-core/js/vendor/moment-js/locale/af.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?n(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],n):n(e.moment)}(this,function(e){"use strict";return e.defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des".split("_"),weekdays:"Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag".split("_"),weekdaysShort:"Son_Maa_Din_Woe_Don_Vry_Sat".split("_"),weekdaysMin:"So_Ma_Di_Wo_Do_Vr_Sa".split("_"),meridiemParse:/vm|nm/i,isPM:function(e){return/^nm$/i.test(e)},meridiem:function(e,n,a){return e<12?a?"vm":"VM":a?"nm":"NM"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Vandag om] LT",nextDay:"[Môre om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gister om] LT",lastWeek:"[Laas] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oor %s",past:"%s gelede",s:"'n paar sekondes",m:"'n minuut",mm:"%d minute",h:"'n uur",hh:"%d ure",d:"'n dag",dd:"%d dae",M:"'n maand",MM:"%d maande",y:"'n jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/ar-ly.js ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Arabic (Lybia) [ar-ly]
3
+ //! author : Ali Hmer: https://github.com/kikoanis
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var symbolMap = {
14
+ '1': '1',
15
+ '2': '2',
16
+ '3': '3',
17
+ '4': '4',
18
+ '5': '5',
19
+ '6': '6',
20
+ '7': '7',
21
+ '8': '8',
22
+ '9': '9',
23
+ '0': '0'
24
+ }, pluralForm = function (n) {
25
+ return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
26
+ }, plurals = {
27
+ s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
28
+ m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
29
+ h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
30
+ d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
31
+ M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
32
+ y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
33
+ }, pluralize = function (u) {
34
+ return function (number, withoutSuffix, string, isFuture) {
35
+ var f = pluralForm(number),
36
+ str = plurals[u][pluralForm(number)];
37
+ if (f === 2) {
38
+ str = str[withoutSuffix ? 0 : 1];
39
+ }
40
+ return str.replace(/%d/i, number);
41
+ };
42
+ }, months = [
43
+ 'يناير',
44
+ 'فبراير',
45
+ 'مارس',
46
+ 'أبريل',
47
+ 'مايو',
48
+ 'يونيو',
49
+ 'يوليو',
50
+ 'أغسطس',
51
+ 'سبتمبر',
52
+ 'أكتوبر',
53
+ 'نوفمبر',
54
+ 'ديسمبر'
55
+ ];
56
+
57
+ var ar_ly = moment.defineLocale('ar-ly', {
58
+ months : months,
59
+ monthsShort : months,
60
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
61
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
62
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
63
+ weekdaysParseExact : true,
64
+ longDateFormat : {
65
+ LT : 'HH:mm',
66
+ LTS : 'HH:mm:ss',
67
+ L : 'D/\u200FM/\u200FYYYY',
68
+ LL : 'D MMMM YYYY',
69
+ LLL : 'D MMMM YYYY HH:mm',
70
+ LLLL : 'dddd D MMMM YYYY HH:mm'
71
+ },
72
+ meridiemParse: /ص|م/,
73
+ isPM : function (input) {
74
+ return 'م' === input;
75
+ },
76
+ meridiem : function (hour, minute, isLower) {
77
+ if (hour < 12) {
78
+ return 'ص';
79
+ } else {
80
+ return 'م';
81
+ }
82
+ },
83
+ calendar : {
84
+ sameDay: '[اليوم عند الساعة] LT',
85
+ nextDay: '[غدًا عند الساعة] LT',
86
+ nextWeek: 'dddd [عند الساعة] LT',
87
+ lastDay: '[أمس عند الساعة] LT',
88
+ lastWeek: 'dddd [عند الساعة] LT',
89
+ sameElse: 'L'
90
+ },
91
+ relativeTime : {
92
+ future : 'بعد %s',
93
+ past : 'منذ %s',
94
+ s : pluralize('s'),
95
+ m : pluralize('m'),
96
+ mm : pluralize('m'),
97
+ h : pluralize('h'),
98
+ hh : pluralize('h'),
99
+ d : pluralize('d'),
100
+ dd : pluralize('d'),
101
+ M : pluralize('M'),
102
+ MM : pluralize('M'),
103
+ y : pluralize('y'),
104
+ yy : pluralize('y')
105
+ },
106
+ preparse: function (string) {
107
+ return string.replace(/\u200f/g, '').replace(/،/g, ',');
108
+ },
109
+ postformat: function (string) {
110
+ return string.replace(/\d/g, function (match) {
111
+ return symbolMap[match];
112
+ }).replace(/,/g, '،');
113
+ },
114
+ week : {
115
+ dow : 6, // Saturday is the first day of the week.
116
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
117
+ }
118
+ });
119
+
120
+ return ar_ly;
121
+
122
+ }));
bp-core/js/vendor/moment-js/locale/ar-ly.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,d){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?d(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],d):d(e.moment)}(this,function(e){"use strict";var d={1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",0:"0"},t=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},n={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},r=function(e){return function(d,r,i,m){var o=t(d),a=n[e][t(d)];return 2===o&&(a=a[r?0:1]),a.replace(/%d/i,d)}},i=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];return e.defineLocale("ar-ly",{months:i,monthsShort:i,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,d,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:r("s"),m:r("m"),mm:r("m"),h:r("h"),hh:r("h"),d:r("d"),dd:r("d"),M:r("M"),MM:r("M"),y:r("y"),yy:r("y")},preparse:function(e){return e.replace(/\u200f/g,"").replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return d[e]}).replace(/,/g,"،")},week:{dow:6,doy:12}})});
bp-core/js/vendor/moment-js/locale/ar-ma.js ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Arabic (Morocco) [ar-ma]
3
+ //! author : ElFadili Yassine : https://github.com/ElFadiliY
4
+ //! author : Abdel Said : https://github.com/abdelsaid
5
+
6
+ ;(function (global, factory) {
7
+ typeof exports === 'object' && typeof module !== 'undefined'
8
+ && typeof require === 'function' ? factory(require('../moment')) :
9
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
10
+ factory(global.moment)
11
+ }(this, function (moment) { 'use strict';
12
+
13
+
14
+ var ar_ma = moment.defineLocale('ar-ma', {
15
+ months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
16
+ monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
17
+ weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
18
+ weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
19
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
20
+ weekdaysParseExact : true,
21
+ longDateFormat : {
22
+ LT : 'HH:mm',
23
+ LTS : 'HH:mm:ss',
24
+ L : 'DD/MM/YYYY',
25
+ LL : 'D MMMM YYYY',
26
+ LLL : 'D MMMM YYYY HH:mm',
27
+ LLLL : 'dddd D MMMM YYYY HH:mm'
28
+ },
29
+ calendar : {
30
+ sameDay: '[اليوم على الساعة] LT',
31
+ nextDay: '[غدا على الساعة] LT',
32
+ nextWeek: 'dddd [على الساعة] LT',
33
+ lastDay: '[أمس على الساعة] LT',
34
+ lastWeek: 'dddd [على الساعة] LT',
35
+ sameElse: 'L'
36
+ },
37
+ relativeTime : {
38
+ future : 'في %s',
39
+ past : 'منذ %s',
40
+ s : 'ثوان',
41
+ m : 'دقيقة',
42
+ mm : '%d دقائق',
43
+ h : 'ساعة',
44
+ hh : '%d ساعات',
45
+ d : 'يوم',
46
+ dd : '%d أيام',
47
+ M : 'شهر',
48
+ MM : '%d أشهر',
49
+ y : 'سنة',
50
+ yy : '%d سنوات'
51
+ },
52
+ week : {
53
+ dow : 6, // Saturday is the first day of the week.
54
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
55
+ }
56
+ });
57
+
58
+ return ar_ma;
59
+
60
+ }));
bp-core/js/vendor/moment-js/locale/ar-ma.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,_){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?_(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],_):_(e.moment)}(this,function(e){"use strict";return e.defineLocale("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,doy:12}})});
bp-core/js/vendor/moment-js/locale/ar-sa.js ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Arabic (Saudi Arabia) [ar-sa]
3
+ //! author : Suhail Alkowaileet : https://github.com/xsoh
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var symbolMap = {
14
+ '1': '١',
15
+ '2': '٢',
16
+ '3': '٣',
17
+ '4': '٤',
18
+ '5': '٥',
19
+ '6': '٦',
20
+ '7': '٧',
21
+ '8': '٨',
22
+ '9': '٩',
23
+ '0': '٠'
24
+ }, numberMap = {
25
+ '١': '1',
26
+ '٢': '2',
27
+ '٣': '3',
28
+ '٤': '4',
29
+ '٥': '5',
30
+ '٦': '6',
31
+ '٧': '7',
32
+ '٨': '8',
33
+ '٩': '9',
34
+ '٠': '0'
35
+ };
36
+
37
+ var ar_sa = moment.defineLocale('ar-sa', {
38
+ months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
39
+ monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
40
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
41
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
42
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
43
+ weekdaysParseExact : true,
44
+ longDateFormat : {
45
+ LT : 'HH:mm',
46
+ LTS : 'HH:mm:ss',
47
+ L : 'DD/MM/YYYY',
48
+ LL : 'D MMMM YYYY',
49
+ LLL : 'D MMMM YYYY HH:mm',
50
+ LLLL : 'dddd D MMMM YYYY HH:mm'
51
+ },
52
+ meridiemParse: /ص|م/,
53
+ isPM : function (input) {
54
+ return 'م' === input;
55
+ },
56
+ meridiem : function (hour, minute, isLower) {
57
+ if (hour < 12) {
58
+ return 'ص';
59
+ } else {
60
+ return 'م';
61
+ }
62
+ },
63
+ calendar : {
64
+ sameDay: '[اليوم على الساعة] LT',
65
+ nextDay: '[غدا على الساعة] LT',
66
+ nextWeek: 'dddd [على الساعة] LT',
67
+ lastDay: '[أمس على الساعة] LT',
68
+ lastWeek: 'dddd [على الساعة] LT',
69
+ sameElse: 'L'
70
+ },
71
+ relativeTime : {
72
+ future : 'في %s',
73
+ past : 'منذ %s',
74
+ s : 'ثوان',
75
+ m : 'دقيقة',
76
+ mm : '%d دقائق',
77
+ h : 'ساعة',
78
+ hh : '%d ساعات',
79
+ d : 'يوم',
80
+ dd : '%d أيام',
81
+ M : 'شهر',
82
+ MM : '%d أشهر',
83
+ y : 'سنة',
84
+ yy : '%d سنوات'
85
+ },
86
+ preparse: function (string) {
87
+ return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
88
+ return numberMap[match];
89
+ }).replace(/،/g, ',');
90
+ },
91
+ postformat: function (string) {
92
+ return string.replace(/\d/g, function (match) {
93
+ return symbolMap[match];
94
+ }).replace(/,/g, '،');
95
+ },
96
+ week : {
97
+ dow : 6, // Saturday is the first day of the week.
98
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
99
+ }
100
+ });
101
+
102
+ return ar_sa;
103
+
104
+ }));
bp-core/js/vendor/moment-js/locale/ar-sa.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?t(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],t):t(e.moment)}(this,function(e){"use strict";var t={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},_={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"};return e.defineLocale("ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,t,_){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(e){return _[e]}).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]}).replace(/,/g,"،")},week:{dow:6,doy:12}})});
bp-core/js/vendor/moment-js/locale/ar-tn.js ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Arabic (Tunisia) [ar-tn]
3
+ //! author : Nader Toukabri : https://github.com/naderio
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var ar_tn = moment.defineLocale('ar-tn', {
14
+ months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
15
+ monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
16
+ weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
17
+ weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
18
+ weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
19
+ weekdaysParseExact : true,
20
+ longDateFormat: {
21
+ LT: 'HH:mm',
22
+ LTS: 'HH:mm:ss',
23
+ L: 'DD/MM/YYYY',
24
+ LL: 'D MMMM YYYY',
25
+ LLL: 'D MMMM YYYY HH:mm',
26
+ LLLL: 'dddd D MMMM YYYY HH:mm'
27
+ },
28
+ calendar: {
29
+ sameDay: '[اليوم على الساعة] LT',
30
+ nextDay: '[غدا على الساعة] LT',
31
+ nextWeek: 'dddd [على الساعة] LT',
32
+ lastDay: '[أمس على الساعة] LT',
33
+ lastWeek: 'dddd [على الساعة] LT',
34
+ sameElse: 'L'
35
+ },
36
+ relativeTime: {
37
+ future: 'في %s',
38
+ past: 'منذ %s',
39
+ s: 'ثوان',
40
+ m: 'دقيقة',
41
+ mm: '%d دقائق',
42
+ h: 'ساعة',
43
+ hh: '%d ساعات',
44
+ d: 'يوم',
45
+ dd: '%d أيام',
46
+ M: 'شهر',
47
+ MM: '%d أشهر',
48
+ y: 'سنة',
49
+ yy: '%d سنوات'
50
+ },
51
+ week: {
52
+ dow: 1, // Monday is the first day of the week.
53
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
54
+ }
55
+ });
56
+
57
+ return ar_tn;
58
+
59
+ }));
bp-core/js/vendor/moment-js/locale/ar-tn.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,_){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?_(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],_):_(e.moment)}(this,function(e){"use strict";return e.defineLocale("ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/ar.js ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Arabic [ar]
3
+ //! author : Abdel Said: https://github.com/abdelsaid
4
+ //! author : Ahmed Elkhatib
5
+ //! author : forabi https://github.com/forabi
6
+
7
+ ;(function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined'
9
+ && typeof require === 'function' ? factory(require('../moment')) :
10
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
11
+ factory(global.moment)
12
+ }(this, function (moment) { 'use strict';
13
+
14
+
15
+ var symbolMap = {
16
+ '1': '١',
17
+ '2': '٢',
18
+ '3': '٣',
19
+ '4': '٤',
20
+ '5': '٥',
21
+ '6': '٦',
22
+ '7': '٧',
23
+ '8': '٨',
24
+ '9': '٩',
25
+ '0': '٠'
26
+ }, numberMap = {
27
+ '١': '1',
28
+ '٢': '2',
29
+ '٣': '3',
30
+ '٤': '4',
31
+ '٥': '5',
32
+ '٦': '6',
33
+ '٧': '7',
34
+ '٨': '8',
35
+ '٩': '9',
36
+ '٠': '0'
37
+ }, pluralForm = function (n) {
38
+ return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
39
+ }, plurals = {
40
+ s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
41
+ m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
42
+ h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
43
+ d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
44
+ M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
45
+ y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
46
+ }, pluralize = function (u) {
47
+ return function (number, withoutSuffix, string, isFuture) {
48
+ var f = pluralForm(number),
49
+ str = plurals[u][pluralForm(number)];
50
+ if (f === 2) {
51
+ str = str[withoutSuffix ? 0 : 1];
52
+ }
53
+ return str.replace(/%d/i, number);
54
+ };
55
+ }, months = [
56
+ 'كانون الثاني يناير',
57
+ 'شباط فبراير',
58
+ 'آذار مارس',
59
+ 'نيسان أبريل',
60
+ 'أيار مايو',
61
+ 'حزيران يونيو',
62
+ 'تموز يوليو',
63
+ 'آب أغسطس',
64
+ 'أيلول سبتمبر',
65
+ 'تشرين الأول أكتوبر',
66
+ 'تشرين الثاني نوفمبر',
67
+ 'كانون الأول ديسمبر'
68
+ ];
69
+
70
+ var ar = moment.defineLocale('ar', {
71
+ months : months,
72
+ monthsShort : months,
73
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
74
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
75
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
76
+ weekdaysParseExact : true,
77
+ longDateFormat : {
78
+ LT : 'HH:mm',
79
+ LTS : 'HH:mm:ss',
80
+ L : 'D/\u200FM/\u200FYYYY',
81
+ LL : 'D MMMM YYYY',
82
+ LLL : 'D MMMM YYYY HH:mm',
83
+ LLLL : 'dddd D MMMM YYYY HH:mm'
84
+ },
85
+ meridiemParse: /ص|م/,
86
+ isPM : function (input) {
87
+ return 'م' === input;
88
+ },
89
+ meridiem : function (hour, minute, isLower) {
90
+ if (hour < 12) {
91
+ return 'ص';
92
+ } else {
93
+ return 'م';
94
+ }
95
+ },
96
+ calendar : {
97
+ sameDay: '[اليوم عند الساعة] LT',
98
+ nextDay: '[غدًا عند الساعة] LT',
99
+ nextWeek: 'dddd [عند الساعة] LT',
100
+ lastDay: '[أمس عند الساعة] LT',
101
+ lastWeek: 'dddd [عند الساعة] LT',
102
+ sameElse: 'L'
103
+ },
104
+ relativeTime : {
105
+ future : 'بعد %s',
106
+ past : 'منذ %s',
107
+ s : pluralize('s'),
108
+ m : pluralize('m'),
109
+ mm : pluralize('m'),
110
+ h : pluralize('h'),
111
+ hh : pluralize('h'),
112
+ d : pluralize('d'),
113
+ dd : pluralize('d'),
114
+ M : pluralize('M'),
115
+ MM : pluralize('M'),
116
+ y : pluralize('y'),
117
+ yy : pluralize('y')
118
+ },
119
+ preparse: function (string) {
120
+ return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
121
+ return numberMap[match];
122
+ }).replace(/،/g, ',');
123
+ },
124
+ postformat: function (string) {
125
+ return string.replace(/\d/g, function (match) {
126
+ return symbolMap[match];
127
+ }).replace(/,/g, '،');
128
+ },
129
+ week : {
130
+ dow : 6, // Saturday is the first day of the week.
131
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
132
+ }
133
+ });
134
+
135
+ return ar;
136
+
137
+ }));
bp-core/js/vendor/moment-js/locale/ar.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,d){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?d(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],d):d(e.moment)}(this,function(e){"use strict";var d={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},n=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},r={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},i=function(e){return function(d,t,i,o){var a=n(d),m=r[e][n(d)];return 2===a&&(m=m[t?0:1]),m.replace(/%d/i,d)}},o=["كانون الثاني يناير","شباط فبراير","آذار مارس","نيسان أبريل","أيار مايو","حزيران يونيو","تموز يوليو","آب أغسطس","أيلول سبتمبر","تشرين الأول أكتوبر","تشرين الثاني نوفمبر","كانون الأول ديسمبر"];return e.defineLocale("ar",{months:o,monthsShort:o,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,d,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:i("s"),m:i("m"),mm:i("m"),h:i("h"),hh:i("h"),d:i("d"),dd:i("d"),M:i("M"),MM:i("M"),y:i("y"),yy:i("y")},preparse:function(e){return e.replace(/\u200f/g,"").replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(e){return t[e]}).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return d[e]}).replace(/,/g,"،")},week:{dow:6,doy:12}})});
bp-core/js/vendor/moment-js/locale/az.js ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Azerbaijani [az]
3
+ //! author : topchiyev : https://github.com/topchiyev
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var suffixes = {
14
+ 1: '-inci',
15
+ 5: '-inci',
16
+ 8: '-inci',
17
+ 70: '-inci',
18
+ 80: '-inci',
19
+ 2: '-nci',
20
+ 7: '-nci',
21
+ 20: '-nci',
22
+ 50: '-nci',
23
+ 3: '-üncü',
24
+ 4: '-üncü',
25
+ 100: '-üncü',
26
+ 6: '-ncı',
27
+ 9: '-uncu',
28
+ 10: '-uncu',
29
+ 30: '-uncu',
30
+ 60: '-ıncı',
31
+ 90: '-ıncı'
32
+ };
33
+
34
+ var az = moment.defineLocale('az', {
35
+ months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
36
+ monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
37
+ weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
38
+ weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
39
+ weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
40
+ weekdaysParseExact : true,
41
+ longDateFormat : {
42
+ LT : 'HH:mm',
43
+ LTS : 'HH:mm:ss',
44
+ L : 'DD.MM.YYYY',
45
+ LL : 'D MMMM YYYY',
46
+ LLL : 'D MMMM YYYY HH:mm',
47
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
48
+ },
49
+ calendar : {
50
+ sameDay : '[bugün saat] LT',
51
+ nextDay : '[sabah saat] LT',
52
+ nextWeek : '[gələn həftə] dddd [saat] LT',
53
+ lastDay : '[dünən] LT',
54
+ lastWeek : '[keçən həftə] dddd [saat] LT',
55
+ sameElse : 'L'
56
+ },
57
+ relativeTime : {
58
+ future : '%s sonra',
59
+ past : '%s əvvəl',
60
+ s : 'birneçə saniyyə',
61
+ m : 'bir dəqiqə',
62
+ mm : '%d dəqiqə',
63
+ h : 'bir saat',
64
+ hh : '%d saat',
65
+ d : 'bir gün',
66
+ dd : '%d gün',
67
+ M : 'bir ay',
68
+ MM : '%d ay',
69
+ y : 'bir il',
70
+ yy : '%d il'
71
+ },
72
+ meridiemParse: /gecə|səhər|gündüz|axşam/,
73
+ isPM : function (input) {
74
+ return /^(gündüz|axşam)$/.test(input);
75
+ },
76
+ meridiem : function (hour, minute, isLower) {
77
+ if (hour < 4) {
78
+ return 'gecə';
79
+ } else if (hour < 12) {
80
+ return 'səhər';
81
+ } else if (hour < 17) {
82
+ return 'gündüz';
83
+ } else {
84
+ return 'axşam';
85
+ }
86
+ },
87
+ ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
88
+ ordinal : function (number) {
89
+ if (number === 0) { // special case for zero
90
+ return number + '-ıncı';
91
+ }
92
+ var a = number % 10,
93
+ b = number % 100 - a,
94
+ c = number >= 100 ? 100 : null;
95
+ return number + (suffixes[a] || suffixes[b] || suffixes[c]);
96
+ },
97
+ week : {
98
+ dow : 1, // Monday is the first day of the week.
99
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
100
+ }
101
+ });
102
+
103
+ return az;
104
+
105
+ }));
bp-core/js/vendor/moment-js/locale/az.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(n,a){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?a(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],a):a(n.moment)}(this,function(n){"use strict";var a={1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"};return n.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"birneçə saniyyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(n){return/^(gündüz|axşam)$/.test(n)},meridiem:function(n,a,e){return n<4?"gecə":n<12?"səhər":n<17?"gündüz":"axşam"},ordinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(n){if(0===n)return n+"-ıncı";var e=n%10,i=n%100-e,t=n>=100?100:null;return n+(a[e]||a[i]||a[t])},week:{dow:1,doy:7}})});
bp-core/js/vendor/moment-js/locale/be.js ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Belarusian [be]
3
+ //! author : Dmitry Demidov : https://github.com/demidov91
4
+ //! author: Praleska: http://praleska.pro/
5
+ //! Author : Menelion Elensúle : https://github.com/Oire
6
+
7
+ ;(function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined'
9
+ && typeof require === 'function' ? factory(require('../moment')) :
10
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
11
+ factory(global.moment)
12
+ }(this, function (moment) { 'use strict';
13
+
14
+
15
+ function plural(word, num) {
16
+ var forms = word.split('_');
17
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
18
+ }
19
+ function relativeTimeWithPlural(number, withoutSuffix, key) {
20
+ var format = {
21
+ 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
22
+ 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
23
+ 'dd': 'дзень_дні_дзён',
24
+ 'MM': 'месяц_месяцы_месяцаў',
25
+ 'yy': 'год_гады_гадоў'
26
+ };
27
+ if (key === 'm') {
28
+ return withoutSuffix ? 'хвіліна' : 'хвіліну';
29
+ }
30
+ else if (key === 'h') {
31
+ return withoutSuffix ? 'гадзіна' : 'гадзіну';
32
+ }
33
+ else {
34
+ return number + ' ' + plural(format[key], +number);
35
+ }
36
+ }
37
+
38
+ var be = moment.defineLocale('be', {
39
+ months : {
40
+ format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
41
+ standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
42
+ },
43
+ monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
44
+ weekdays : {
45
+ format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
46
+ standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
47
+ isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
48
+ },
49
+ weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
50
+ weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
51
+ longDateFormat : {
52
+ LT : 'HH:mm',
53
+ LTS : 'HH:mm:ss',
54
+ L : 'DD.MM.YYYY',
55
+ LL : 'D MMMM YYYY г.',
56
+ LLL : 'D MMMM YYYY г., HH:mm',
57
+ LLLL : 'dddd, D MMMM YYYY г., HH:mm'
58
+ },
59
+ calendar : {
60
+ sameDay: '[Сёння ў] LT',
61
+ nextDay: '[Заўтра ў] LT',
62
+ lastDay: '[Учора ў] LT',
63
+ nextWeek: function () {
64
+ return '[У] dddd [ў] LT';
65
+ },
66
+ lastWeek: function () {
67
+ switch (this.day()) {
68
+ case 0:
69
+ case 3:
70
+ case 5:
71
+ case 6:
72
+ return '[У мінулую] dddd [ў] LT';
73
+ case 1:
74
+ case 2:
75
+ case 4:
76
+ return '[У мінулы] dddd [ў] LT';
77
+ }
78
+ },
79
+ sameElse: 'L'
80
+ },
81
+ relativeTime : {
82
+ future : 'праз %s',
83
+ past : '%s таму',
84
+ s : 'некалькі секунд',
85
+ m : relativeTimeWithPlural,
86
+ mm : relativeTimeWithPlural,
87
+ h : relativeTimeWithPlural,
88
+ hh : relativeTimeWithPlural,
89
+ d : 'дзень',
90
+ dd : relativeTimeWithPlural,
91
+ M : 'месяц',
92
+ MM : relativeTimeWithPlural,
93
+ y : 'год',
94
+ yy : relativeTimeWithPlural
95
+ },
96
+ meridiemParse: /ночы|раніцы|дня|вечара/,
97
+ isPM : function (input) {
98
+ return /^(дня|вечара)$/.test(input);
99
+ },
100
+ meridiem : function (hour, minute, isLower) {
101
+ if (hour < 4) {
102
+ return 'ночы';
103
+ } else if (hour < 12) {
104
+ return 'раніцы';
105
+ } else if (hour < 17) {
106
+ return 'дня';
107
+ } else {
108
+ return 'вечара';
109
+ }
110
+ },
111
+ ordinalParse: /\d{1,2}-(і|ы|га)/,
112
+ ordinal: function (number, period) {
113
+ switch (period) {
114
+ case 'M':
115
+ case 'd':
116
+ case 'DDD':
117
+ case 'w':
118
+ case 'W':
119
+ return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
120
+ case 'D':
121
+ return number + '-га';
122
+ default:
123
+ return number;
124
+ }
125
+ },
126
+ week : {
127
+ dow : 1, // Monday is the first day of the week.
128
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
129
+ }
130
+ });
131
+
132
+ return be;
133
+
134
+ }));
bp-core/js/vendor/moment-js/locale/be.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,_){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?_(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],_):_(e.moment)}(this,function(e){"use strict";function _(e,_){var t=e.split("_");return _%10==1&&_%100!=11?t[0]:_%10>=2&&_%10<=4&&(_%100<10||_%100>=20)?t[1]:t[2]}function t(e,t,n){var s={mm:t?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:t?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"};return"m"===n?t?"хвіліна":"хвіліну":"h"===n?t?"гадзіна":"гадзіну":e+" "+_(s[n],+e)}return e.defineLocale("be",{months:{format:"студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня".split("_"),standalone:"студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань".split("_")},monthsShort:"студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж".split("_"),weekdays:{format:"нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу".split("_"),standalone:"нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота".split("_"),isFormat:/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/},weekdaysShort:"нд_пн_ат_ср_чц_пт_сб".split("_"),weekdaysMin:"нд_пн_ат_ср_чц_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сёння ў] LT",nextDay:"[Заўтра ў] LT",lastDay:"[Учора ў] LT",nextWeek:function(){return"[У] dddd [ў] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[У мінулую] dddd [ў] LT";case 1:case 2:case 4:return"[У мінулы] dddd [ў] LT"}},sameElse:"L"},relativeTime:{future:"праз %s",past:"%s таму",s:"некалькі секунд",m:t,mm:t,h:t,hh:t,d:"дзень",dd:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночы|раніцы|дня|вечара/,isPM:function(e){return/^(дня|вечара)$/.test(e)},meridiem:function(e,_,t){return e<4?"ночы":e<12?"раніцы":e<17?"дня":"вечара"},ordinalParse:/\d{1,2}-(і|ы|га)/,ordinal:function(e,_){switch(_){case"M":case"d":case"DDD":case"w":case"W":return e%10!=2&&e%10!=3||e%100==12||e%100==13?e+"-ы":e+"-і";case"D":return e+"-га";default:return e}},week:{dow:1,doy:7}})});
bp-core/js/vendor/moment-js/locale/bg.js ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Bulgarian [bg]
3
+ //! author : Krasen Borisov : https://github.com/kraz
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var bg = moment.defineLocale('bg', {
14
+ months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
15
+ monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
16
+ weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
17
+ weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
18
+ weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
19
+ longDateFormat : {
20
+ LT : 'H:mm',
21
+ LTS : 'H:mm:ss',
22
+ L : 'D.MM.YYYY',
23
+ LL : 'D MMMM YYYY',
24
+ LLL : 'D MMMM YYYY H:mm',
25
+ LLLL : 'dddd, D MMMM YYYY H:mm'
26
+ },
27
+ calendar : {
28
+ sameDay : '[Днес в] LT',
29
+ nextDay : '[Утре в] LT',
30
+ nextWeek : 'dddd [в] LT',
31
+ lastDay : '[Вчера в] LT',
32
+ lastWeek : function () {
33
+ switch (this.day()) {
34
+ case 0:
35
+ case 3:
36
+ case 6:
37
+ return '[В изминалата] dddd [в] LT';
38
+ case 1:
39
+ case 2:
40
+ case 4:
41
+ case 5:
42
+ return '[В изминалия] dddd [в] LT';
43
+ }
44
+ },
45
+ sameElse : 'L'
46
+ },
47
+ relativeTime : {
48
+ future : 'след %s',
49
+ past : 'преди %s',
50
+ s : 'няколко секунди',
51
+ m : 'минута',
52
+ mm : '%d минути',
53
+ h : 'час',
54
+ hh : '%d часа',
55
+ d : 'ден',
56
+ dd : '%d дни',
57
+ M : 'месец',
58
+ MM : '%d месеца',
59
+ y : 'година',
60
+ yy : '%d години'
61
+ },
62
+ ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
63
+ ordinal : function (number) {
64
+ var lastDigit = number % 10,
65
+ last2Digits = number % 100;
66
+ if (number === 0) {
67
+ return number + '-ев';
68
+ } else if (last2Digits === 0) {
69
+ return number + '-ен';
70
+ } else if (last2Digits > 10 && last2Digits < 20) {
71
+ return number + '-ти';
72
+ } else if (lastDigit === 1) {
73
+ return number + '-ви';
74
+ } else if (lastDigit === 2) {
75
+ return number + '-ри';
76
+ } else if (lastDigit === 7 || lastDigit === 8) {
77
+ return number + '-ми';
78
+ } else {
79
+ return number + '-ти';
80
+ }
81
+ },
82
+ week : {
83
+ dow : 1, // Monday is the first day of the week.
84
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
85
+ }
86
+ });
87
+
88
+ return bg;
89
+
90
+ }));
bp-core/js/vendor/moment-js/locale/bg.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,_){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?_(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],_):_(e.moment)}(this,function(e){"use strict";return e.defineLocale("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var _=e%10,d=e%100;return 0===e?e+"-ев":0===d?e+"-ен":d>10&&d<20?e+"-ти":1===_?e+"-ви":2===_?e+"-ри":7===_||8===_?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})});
bp-core/js/vendor/moment-js/locale/bn.js ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Bengali [bn]
3
+ //! author : Kaushik Gandhi : https://github.com/kaushikgandhi
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var symbolMap = {
14
+ '1': '১',
15
+ '2': '২',
16
+ '3': '৩',
17
+ '4': '৪',
18
+ '5': '৫',
19
+ '6': '৬',
20
+ '7': '৭',
21
+ '8': '৮',
22
+ '9': '৯',
23
+ '0': '০'
24
+ },
25
+ numberMap = {
26
+ '১': '1',
27
+ '২': '2',
28
+ '৩': '3',
29
+ '৪': '4',
30
+ '৫': '5',
31
+ '৬': '6',
32
+ '৭': '7',
33
+ '৮': '8',
34
+ '৯': '9',
35
+ '০': '0'
36
+ };
37
+
38
+ var bn = moment.defineLocale('bn', {
39
+ months : 'জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
40
+ monthsShort : 'জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে'.split('_'),
41
+ weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split('_'),
42
+ weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
43
+ weekdaysMin : 'রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি'.split('_'),
44
+ longDateFormat : {
45
+ LT : 'A h:mm সময়',
46
+ LTS : 'A h:mm:ss সময়',
47
+ L : 'DD/MM/YYYY',
48
+ LL : 'D MMMM YYYY',
49
+ LLL : 'D MMMM YYYY, A h:mm সময়',
50
+ LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
51
+ },
52
+ calendar : {
53
+ sameDay : '[আজ] LT',
54
+ nextDay : '[আগামীকাল] LT',
55
+ nextWeek : 'dddd, LT',
56
+ lastDay : '[গতকাল] LT',
57
+ lastWeek : '[গত] dddd, LT',
58
+ sameElse : 'L'
59
+ },
60
+ relativeTime : {
61
+ future : '%s পরে',
62
+ past : '%s আগে',
63
+ s : 'কয়েক সেকেন্ড',
64
+ m : 'এক মিনিট',
65
+ mm : '%d মিনিট',
66
+ h : 'এক ঘন্টা',
67
+ hh : '%d ঘন্টা',
68
+ d : 'এক দিন',
69
+ dd : '%d দিন',
70
+ M : 'এক মাস',
71
+ MM : '%d মাস',
72
+ y : 'এক বছর',
73
+ yy : '%d বছর'
74
+ },
75
+ preparse: function (string) {
76
+ return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
77
+ return numberMap[match];
78
+ });
79
+ },
80
+ postformat: function (string) {
81
+ return string.replace(/\d/g, function (match) {
82
+ return symbolMap[match];
83
+ });
84
+ },
85
+ meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
86
+ meridiemHour : function (hour, meridiem) {
87
+ if (hour === 12) {
88
+ hour = 0;
89
+ }
90
+ if ((meridiem === 'রাত' && hour >= 4) ||
91
+ (meridiem === 'দুপুর' && hour < 5) ||
92
+ meridiem === 'বিকাল') {
93
+ return hour + 12;
94
+ } else {
95
+ return hour;
96
+ }
97
+ },
98
+ meridiem : function (hour, minute, isLower) {
99
+ if (hour < 4) {
100
+ return 'রাত';
101
+ } else if (hour < 10) {
102
+ return 'সকাল';
103
+ } else if (hour < 17) {
104
+ return 'দুপুর';
105
+ } else if (hour < 20) {
106
+ return 'বিকাল';
107
+ } else {
108
+ return 'রাত';
109
+ }
110
+ },
111
+ week : {
112
+ dow : 0, // Sunday is the first day of the week.
113
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
114
+ }
115
+ });
116
+
117
+ return bn;
118
+
119
+ }));
bp-core/js/vendor/moment-js/locale/bn.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?t(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],t):t(e.moment)}(this,function(e){"use strict";var t={1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"},_={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"};return e.defineLocale("bn",{months:"জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি".split("_"),weekdaysMin:"রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(e){return e.replace(/[১২৩৪৫৬৭৮৯০]/g,function(e){return _[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]})},meridiemParse:/রাত|সকাল|দুপুর|বিকাল|রাত/,meridiemHour:function(e,t){return 12===e&&(e=0),"রাত"===t&&e>=4||"দুপুর"===t&&e<5||"বিকাল"===t?e+12:e},meridiem:function(e,t,_){return e<4?"রাত":e<10?"সকাল":e<17?"দুপুর":e<20?"বিকাল":"রাত"},week:{dow:0,doy:6}})});
bp-core/js/vendor/moment-js/locale/bo.js ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Tibetan [bo]
3
+ //! author : Thupten N. Chakrishar : https://github.com/vajradog
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var symbolMap = {
14
+ '1': '༡',
15
+ '2': '༢',
16
+ '3': '༣',
17
+ '4': '༤',
18
+ '5': '༥',
19
+ '6': '༦',
20
+ '7': '༧',
21
+ '8': '༨',
22
+ '9': '༩',
23
+ '0': '༠'
24
+ },
25
+ numberMap = {
26
+ '༡': '1',
27
+ '༢': '2',
28
+ '༣': '3',
29
+ '༤': '4',
30
+ '༥': '5',
31
+ '༦': '6',
32
+ '༧': '7',
33
+ '༨': '8',
34
+ '༩': '9',
35
+ '༠': '0'
36
+ };
37
+
38
+ var bo = moment.defineLocale('bo', {
39
+ months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
40
+ monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
41
+ weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
42
+ weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
43
+ weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
44
+ longDateFormat : {
45
+ LT : 'A h:mm',
46
+ LTS : 'A h:mm:ss',
47
+ L : 'DD/MM/YYYY',
48
+ LL : 'D MMMM YYYY',
49
+ LLL : 'D MMMM YYYY, A h:mm',
50
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
51
+ },
52
+ calendar : {
53
+ sameDay : '[དི་རིང] LT',
54
+ nextDay : '[སང་ཉིན] LT',
55
+ nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
56
+ lastDay : '[ཁ་སང] LT',
57
+ lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
58
+ sameElse : 'L'
59
+ },
60
+ relativeTime : {
61
+ future : '%s ལ་',
62
+ past : '%s སྔན་ལ',
63
+ s : 'ལམ་སང',
64
+ m : 'སྐར་མ་གཅིག',
65
+ mm : '%d སྐར་མ',
66
+ h : 'ཆུ་ཚོད་གཅིག',
67
+ hh : '%d ཆུ་ཚོད',
68
+ d : 'ཉིན་གཅིག',
69
+ dd : '%d ཉིན་',
70
+ M : 'ཟླ་བ་གཅིག',
71
+ MM : '%d ཟླ་བ',
72
+ y : 'ལོ་གཅིག',
73
+ yy : '%d ལོ'
74
+ },
75
+ preparse: function (string) {
76
+ return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
77
+ return numberMap[match];
78
+ });
79
+ },
80
+ postformat: function (string) {
81
+ return string.replace(/\d/g, function (match) {
82
+ return symbolMap[match];
83
+ });
84
+ },
85
+ meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
86
+ meridiemHour : function (hour, meridiem) {
87
+ if (hour === 12) {
88
+ hour = 0;
89
+ }
90
+ if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
91
+ (meridiem === 'ཉིན་གུང' && hour < 5) ||
92
+ meridiem === 'དགོང་དག') {
93
+ return hour + 12;
94
+ } else {
95
+ return hour;
96
+ }
97
+ },
98
+ meridiem : function (hour, minute, isLower) {
99
+ if (hour < 4) {
100
+ return 'མཚན་མོ';
101
+ } else if (hour < 10) {
102
+ return 'ཞོགས་ཀས';
103
+ } else if (hour < 17) {
104
+ return 'ཉིན་གུང';
105
+ } else if (hour < 20) {
106
+ return 'དགོང་དག';
107
+ } else {
108
+ return 'མཚན་མོ';
109
+ }
110
+ },
111
+ week : {
112
+ dow : 0, // Sunday is the first day of the week.
113
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
114
+ }
115
+ });
116
+
117
+ return bo;
118
+
119
+ }));
bp-core/js/vendor/moment-js/locale/bo.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?t(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],t):t(e.moment)}(this,function(e){"use strict";var t={1:"༡",2:"༢",3:"༣",4:"༤",5:"༥",6:"༦",7:"༧",8:"༨",9:"༩",0:"༠"},_={"༡":"1","༢":"2","༣":"3","༤":"4","༥":"5","༦":"6","༧":"7","༨":"8","༩":"9","༠":"0"};return e.defineLocale("bo",{months:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),monthsShort:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),weekdays:"གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་".split("_"),weekdaysShort:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),weekdaysMin:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[དི་རིང] LT",nextDay:"[སང་ཉིན] LT",nextWeek:"[བདུན་ཕྲག་རྗེས་མ], LT",lastDay:"[ཁ་སང] LT",lastWeek:"[བདུན་ཕྲག་མཐའ་མ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ལ་",past:"%s སྔན་ལ",s:"ལམ་སང",m:"སྐར་མ་གཅིག",mm:"%d སྐར་མ",h:"ཆུ་ཚོད་གཅིག",hh:"%d ཆུ་ཚོད",d:"ཉིན་གཅིག",dd:"%d ཉིན་",M:"ཟླ་བ་གཅིག",MM:"%d ཟླ་བ",y:"ལོ་གཅིག",yy:"%d ལོ"},preparse:function(e){return e.replace(/[༡༢༣༤༥༦༧༨༩༠]/g,function(e){return _[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]})},meridiemParse:/མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,meridiemHour:function(e,t){return 12===e&&(e=0),"མཚན་མོ"===t&&e>=4||"ཉིན་གུང"===t&&e<5||"དགོང་དག"===t?e+12:e},meridiem:function(e,t,_){return e<4?"མཚན་མོ":e<10?"ཞོགས་ཀས":e<17?"ཉིན་གུང":e<20?"དགོང་དག":"མཚན་མོ"},week:{dow:0,doy:6}})});
bp-core/js/vendor/moment-js/locale/br.js ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Breton [br]
3
+ //! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ function relativeTimeWithMutation(number, withoutSuffix, key) {
14
+ var format = {
15
+ 'mm': 'munutenn',
16
+ 'MM': 'miz',
17
+ 'dd': 'devezh'
18
+ };
19
+ return number + ' ' + mutation(format[key], number);
20
+ }
21
+ function specialMutationForYears(number) {
22
+ switch (lastNumber(number)) {
23
+ case 1:
24
+ case 3:
25
+ case 4:
26
+ case 5:
27
+ case 9:
28
+ return number + ' bloaz';
29
+ default:
30
+ return number + ' vloaz';
31
+ }
32
+ }
33
+ function lastNumber(number) {
34
+ if (number > 9) {
35
+ return lastNumber(number % 10);
36
+ }
37
+ return number;
38
+ }
39
+ function mutation(text, number) {
40
+ if (number === 2) {
41
+ return softMutation(text);
42
+ }
43
+ return text;
44
+ }
45
+ function softMutation(text) {
46
+ var mutationTable = {
47
+ 'm': 'v',
48
+ 'b': 'v',
49
+ 'd': 'z'
50
+ };
51
+ if (mutationTable[text.charAt(0)] === undefined) {
52
+ return text;
53
+ }
54
+ return mutationTable[text.charAt(0)] + text.substring(1);
55
+ }
56
+
57
+ var br = moment.defineLocale('br', {
58
+ months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
59
+ monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
60
+ weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
61
+ weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
62
+ weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
63
+ weekdaysParseExact : true,
64
+ longDateFormat : {
65
+ LT : 'h[e]mm A',
66
+ LTS : 'h[e]mm:ss A',
67
+ L : 'DD/MM/YYYY',
68
+ LL : 'D [a viz] MMMM YYYY',
69
+ LLL : 'D [a viz] MMMM YYYY h[e]mm A',
70
+ LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
71
+ },
72
+ calendar : {
73
+ sameDay : '[Hiziv da] LT',
74
+ nextDay : '[Warc\'hoazh da] LT',
75
+ nextWeek : 'dddd [da] LT',
76
+ lastDay : '[Dec\'h da] LT',
77
+ lastWeek : 'dddd [paset da] LT',
78
+ sameElse : 'L'
79
+ },
80
+ relativeTime : {
81
+ future : 'a-benn %s',
82
+ past : '%s \'zo',
83
+ s : 'un nebeud segondennoù',
84
+ m : 'ur vunutenn',
85
+ mm : relativeTimeWithMutation,
86
+ h : 'un eur',
87
+ hh : '%d eur',
88
+ d : 'un devezh',
89
+ dd : relativeTimeWithMutation,
90
+ M : 'ur miz',
91
+ MM : relativeTimeWithMutation,
92
+ y : 'ur bloaz',
93
+ yy : specialMutationForYears
94
+ },
95
+ ordinalParse: /\d{1,2}(añ|vet)/,
96
+ ordinal : function (number) {
97
+ var output = (number === 1) ? 'añ' : 'vet';
98
+ return number + output;
99
+ },
100
+ week : {
101
+ dow : 1, // Monday is the first day of the week.
102
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
103
+ }
104
+ });
105
+
106
+ return br;
107
+
108
+ }));
bp-core/js/vendor/moment-js/locale/br.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?n(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],n):n(e.moment)}(this,function(e){"use strict";function n(e,n,r){return e+" "+a({mm:"munutenn",MM:"miz",dd:"devezh"}[r],e)}function r(e){switch(t(e)){case 1:case 3:case 4:case 5:case 9:return e+" bloaz";default:return e+" vloaz"}}function t(e){return e>9?t(e%10):e}function a(e,n){return 2===n?u(e):e}function u(e){var n={m:"v",b:"v",d:"z"};return void 0===n[e.charAt(0)]?e:n[e.charAt(0)]+e.substring(1)}return e.defineLocale("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h[e]mm A",LTS:"h[e]mm:ss A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY h[e]mm A",LLLL:"dddd, D [a viz] MMMM YYYY h[e]mm A"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondennoù",m:"ur vunutenn",mm:n,h:"un eur",hh:"%d eur",d:"un devezh",dd:n,M:"ur miz",MM:n,y:"ur bloaz",yy:r},ordinalParse:/\d{1,2}(añ|vet)/,ordinal:function(e){return e+(1===e?"añ":"vet")},week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/bs.js ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Bosnian [bs]
3
+ //! author : Nedim Cholich : https://github.com/frontyard
4
+ //! based on (hr) translation by Bojan Marković
5
+
6
+ ;(function (global, factory) {
7
+ typeof exports === 'object' && typeof module !== 'undefined'
8
+ && typeof require === 'function' ? factory(require('../moment')) :
9
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
10
+ factory(global.moment)
11
+ }(this, function (moment) { 'use strict';
12
+
13
+
14
+ function translate(number, withoutSuffix, key) {
15
+ var result = number + ' ';
16
+ switch (key) {
17
+ case 'm':
18
+ return withoutSuffix ? 'jedna minuta' : 'jedne minute';
19
+ case 'mm':
20
+ if (number === 1) {
21
+ result += 'minuta';
22
+ } else if (number === 2 || number === 3 || number === 4) {
23
+ result += 'minute';
24
+ } else {
25
+ result += 'minuta';
26
+ }
27
+ return result;
28
+ case 'h':
29
+ return withoutSuffix ? 'jedan sat' : 'jednog sata';
30
+ case 'hh':
31
+ if (number === 1) {
32
+ result += 'sat';
33
+ } else if (number === 2 || number === 3 || number === 4) {
34
+ result += 'sata';
35
+ } else {
36
+ result += 'sati';
37
+ }
38
+ return result;
39
+ case 'dd':
40
+ if (number === 1) {
41
+ result += 'dan';
42
+ } else {
43
+ result += 'dana';
44
+ }
45
+ return result;
46
+ case 'MM':
47
+ if (number === 1) {
48
+ result += 'mjesec';
49
+ } else if (number === 2 || number === 3 || number === 4) {
50
+ result += 'mjeseca';
51
+ } else {
52
+ result += 'mjeseci';
53
+ }
54
+ return result;
55
+ case 'yy':
56
+ if (number === 1) {
57
+ result += 'godina';
58
+ } else if (number === 2 || number === 3 || number === 4) {
59
+ result += 'godine';
60
+ } else {
61
+ result += 'godina';
62
+ }
63
+ return result;
64
+ }
65
+ }
66
+
67
+ var bs = moment.defineLocale('bs', {
68
+ months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
69
+ monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
70
+ monthsParseExact: true,
71
+ weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
72
+ weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
73
+ weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
74
+ weekdaysParseExact : true,
75
+ longDateFormat : {
76
+ LT : 'H:mm',
77
+ LTS : 'H:mm:ss',
78
+ L : 'DD.MM.YYYY',
79
+ LL : 'D. MMMM YYYY',
80
+ LLL : 'D. MMMM YYYY H:mm',
81
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
82
+ },
83
+ calendar : {
84
+ sameDay : '[danas u] LT',
85
+ nextDay : '[sutra u] LT',
86
+ nextWeek : function () {
87
+ switch (this.day()) {
88
+ case 0:
89
+ return '[u] [nedjelju] [u] LT';
90
+ case 3:
91
+ return '[u] [srijedu] [u] LT';
92
+ case 6:
93
+ return '[u] [subotu] [u] LT';
94
+ case 1:
95
+ case 2:
96
+ case 4:
97
+ case 5:
98
+ return '[u] dddd [u] LT';
99
+ }
100
+ },
101
+ lastDay : '[jučer u] LT',
102
+ lastWeek : function () {
103
+ switch (this.day()) {
104
+ case 0:
105
+ case 3:
106
+ return '[prošlu] dddd [u] LT';
107
+ case 6:
108
+ return '[prošle] [subote] [u] LT';
109
+ case 1:
110
+ case 2:
111
+ case 4:
112
+ case 5:
113
+ return '[prošli] dddd [u] LT';
114
+ }
115
+ },
116
+ sameElse : 'L'
117
+ },
118
+ relativeTime : {
119
+ future : 'za %s',
120
+ past : 'prije %s',
121
+ s : 'par sekundi',
122
+ m : translate,
123
+ mm : translate,
124
+ h : translate,
125
+ hh : translate,
126
+ d : 'dan',
127
+ dd : translate,
128
+ M : 'mjesec',
129
+ MM : translate,
130
+ y : 'godinu',
131
+ yy : translate
132
+ },
133
+ ordinalParse: /\d{1,2}\./,
134
+ ordinal : '%d.',
135
+ week : {
136
+ dow : 1, // Monday is the first day of the week.
137
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
138
+ }
139
+ });
140
+
141
+ return bs;
142
+
143
+ }));
bp-core/js/vendor/moment-js/locale/bs.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,a){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?a(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],a):a(e.moment)}(this,function(e){"use strict";function a(e,a,t){var s=e+" ";switch(t){case"m":return a?"jedna minuta":"jedne minute";case"mm":return s+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return a?"jedan sat":"jednog sata";case"hh":return s+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return s+=1===e?"dan":"dana";case"MM":return s+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return s+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}return e.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})});
bp-core/js/vendor/moment-js/locale/ca.js ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Catalan [ca]
3
+ //! author : Juan G. Hurtado : https://github.com/juanghurtado
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var ca = moment.defineLocale('ca', {
14
+ months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
15
+ monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
16
+ monthsParseExact : true,
17
+ weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
18
+ weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
19
+ weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
20
+ weekdaysParseExact : true,
21
+ longDateFormat : {
22
+ LT : 'H:mm',
23
+ LTS : 'H:mm:ss',
24
+ L : 'DD/MM/YYYY',
25
+ LL : 'D MMMM YYYY',
26
+ LLL : 'D MMMM YYYY H:mm',
27
+ LLLL : 'dddd D MMMM YYYY H:mm'
28
+ },
29
+ calendar : {
30
+ sameDay : function () {
31
+ return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
32
+ },
33
+ nextDay : function () {
34
+ return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
35
+ },
36
+ nextWeek : function () {
37
+ return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
38
+ },
39
+ lastDay : function () {
40
+ return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
41
+ },
42
+ lastWeek : function () {
43
+ return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
44
+ },
45
+ sameElse : 'L'
46
+ },
47
+ relativeTime : {
48
+ future : 'en %s',
49
+ past : 'fa %s',
50
+ s : 'uns segons',
51
+ m : 'un minut',
52
+ mm : '%d minuts',
53
+ h : 'una hora',
54
+ hh : '%d hores',
55
+ d : 'un dia',
56
+ dd : '%d dies',
57
+ M : 'un mes',
58
+ MM : '%d mesos',
59
+ y : 'un any',
60
+ yy : '%d anys'
61
+ },
62
+ ordinalParse: /\d{1,2}(r|n|t|è|a)/,
63
+ ordinal : function (number, period) {
64
+ var output = (number === 1) ? 'r' :
65
+ (number === 2) ? 'n' :
66
+ (number === 3) ? 'r' :
67
+ (number === 4) ? 't' : 'è';
68
+ if (period === 'w' || period === 'W') {
69
+ output = 'a';
70
+ }
71
+ return number + output;
72
+ },
73
+ week : {
74
+ dow : 1, // Monday is the first day of the week.
75
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
76
+ }
77
+ });
78
+
79
+ return ca;
80
+
81
+ }));
bp-core/js/vendor/moment-js/locale/ca.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,s){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?s(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],s):s(e.moment)}(this,function(e){"use strict";return e.defineLocale("ca",{months:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),monthsShort:"gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(e,s){var n=1===e?"r":2===e?"n":3===e?"r":4===e?"t":"è";return"w"!==s&&"W"!==s||(n="a"),e+n},week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/cs.js ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Czech [cs]
3
+ //! author : petrbela : https://github.com/petrbela
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'),
14
+ monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
15
+ function plural(n) {
16
+ return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
17
+ }
18
+ function translate(number, withoutSuffix, key, isFuture) {
19
+ var result = number + ' ';
20
+ switch (key) {
21
+ case 's': // a few seconds / in a few seconds / a few seconds ago
22
+ return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
23
+ case 'm': // a minute / in a minute / a minute ago
24
+ return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
25
+ case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
26
+ if (withoutSuffix || isFuture) {
27
+ return result + (plural(number) ? 'minuty' : 'minut');
28
+ } else {
29
+ return result + 'minutami';
30
+ }
31
+ break;
32
+ case 'h': // an hour / in an hour / an hour ago
33
+ return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
34
+ case 'hh': // 9 hours / in 9 hours / 9 hours ago
35
+ if (withoutSuffix || isFuture) {
36
+ return result + (plural(number) ? 'hodiny' : 'hodin');
37
+ } else {
38
+ return result + 'hodinami';
39
+ }
40
+ break;
41
+ case 'd': // a day / in a day / a day ago
42
+ return (withoutSuffix || isFuture) ? 'den' : 'dnem';
43
+ case 'dd': // 9 days / in 9 days / 9 days ago
44
+ if (withoutSuffix || isFuture) {
45
+ return result + (plural(number) ? 'dny' : 'dní');
46
+ } else {
47
+ return result + 'dny';
48
+ }
49
+ break;
50
+ case 'M': // a month / in a month / a month ago
51
+ return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
52
+ case 'MM': // 9 months / in 9 months / 9 months ago
53
+ if (withoutSuffix || isFuture) {
54
+ return result + (plural(number) ? 'měsíce' : 'měsíců');
55
+ } else {
56
+ return result + 'měsíci';
57
+ }
58
+ break;
59
+ case 'y': // a year / in a year / a year ago
60
+ return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
61
+ case 'yy': // 9 years / in 9 years / 9 years ago
62
+ if (withoutSuffix || isFuture) {
63
+ return result + (plural(number) ? 'roky' : 'let');
64
+ } else {
65
+ return result + 'lety';
66
+ }
67
+ break;
68
+ }
69
+ }
70
+
71
+ var cs = moment.defineLocale('cs', {
72
+ months : months,
73
+ monthsShort : monthsShort,
74
+ monthsParse : (function (months, monthsShort) {
75
+ var i, _monthsParse = [];
76
+ for (i = 0; i < 12; i++) {
77
+ // use custom parser to solve problem with July (červenec)
78
+ _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
79
+ }
80
+ return _monthsParse;
81
+ }(months, monthsShort)),
82
+ shortMonthsParse : (function (monthsShort) {
83
+ var i, _shortMonthsParse = [];
84
+ for (i = 0; i < 12; i++) {
85
+ _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
86
+ }
87
+ return _shortMonthsParse;
88
+ }(monthsShort)),
89
+ longMonthsParse : (function (months) {
90
+ var i, _longMonthsParse = [];
91
+ for (i = 0; i < 12; i++) {
92
+ _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
93
+ }
94
+ return _longMonthsParse;
95
+ }(months)),
96
+ weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
97
+ weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
98
+ weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
99
+ longDateFormat : {
100
+ LT: 'H:mm',
101
+ LTS : 'H:mm:ss',
102
+ L : 'DD.MM.YYYY',
103
+ LL : 'D. MMMM YYYY',
104
+ LLL : 'D. MMMM YYYY H:mm',
105
+ LLLL : 'dddd D. MMMM YYYY H:mm',
106
+ l : 'D. M. YYYY'
107
+ },
108
+ calendar : {
109
+ sameDay: '[dnes v] LT',
110
+ nextDay: '[zítra v] LT',
111
+ nextWeek: function () {
112
+ switch (this.day()) {
113
+ case 0:
114
+ return '[v neděli v] LT';
115
+ case 1:
116
+ case 2:
117
+ return '[v] dddd [v] LT';
118
+ case 3:
119
+ return '[ve středu v] LT';
120
+ case 4:
121
+ return '[ve čtvrtek v] LT';
122
+ case 5:
123
+ return '[v pátek v] LT';
124
+ case 6:
125
+ return '[v sobotu v] LT';
126
+ }
127
+ },
128
+ lastDay: '[včera v] LT',
129
+ lastWeek: function () {
130
+ switch (this.day()) {
131
+ case 0:
132
+ return '[minulou neděli v] LT';
133
+ case 1:
134
+ case 2:
135
+ return '[minulé] dddd [v] LT';
136
+ case 3:
137
+ return '[minulou středu v] LT';
138
+ case 4:
139
+ case 5:
140
+ return '[minulý] dddd [v] LT';
141
+ case 6:
142
+ return '[minulou sobotu v] LT';
143
+ }
144
+ },
145
+ sameElse: 'L'
146
+ },
147
+ relativeTime : {
148
+ future : 'za %s',
149
+ past : 'před %s',
150
+ s : translate,
151
+ m : translate,
152
+ mm : translate,
153
+ h : translate,
154
+ hh : translate,
155
+ d : translate,
156
+ dd : translate,
157
+ M : translate,
158
+ MM : translate,
159
+ y : translate,
160
+ yy : translate
161
+ },
162
+ ordinalParse : /\d{1,2}\./,
163
+ ordinal : '%d.',
164
+ week : {
165
+ dow : 1, // Monday is the first day of the week.
166
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
167
+ }
168
+ });
169
+
170
+ return cs;
171
+
172
+ }));
bp-core/js/vendor/moment-js/locale/cs.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?n(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],n):n(e.moment)}(this,function(e){"use strict";function n(e){return e>1&&e<5&&1!=~~(e/10)}function t(e,t,r,s){var u=e+" ";switch(r){case"s":return t||s?"pár sekund":"pár sekundami";case"m":return t?"minuta":s?"minutu":"minutou";case"mm":return t||s?u+(n(e)?"minuty":"minut"):u+"minutami";case"h":return t?"hodina":s?"hodinu":"hodinou";case"hh":return t||s?u+(n(e)?"hodiny":"hodin"):u+"hodinami";case"d":return t||s?"den":"dnem";case"dd":return t||s?u+(n(e)?"dny":"dní"):u+"dny";case"M":return t||s?"měsíc":"měsícem";case"MM":return t||s?u+(n(e)?"měsíce":"měsíců"):u+"měsíci";case"y":return t||s?"rok":"rokem";case"yy":return t||s?u+(n(e)?"roky":"let"):u+"lety"}}var r="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),s="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");return e.defineLocale("cs",{months:r,monthsShort:s,monthsParse:function(e,n){var t,r=[];for(t=0;t<12;t++)r[t]=new RegExp("^"+e[t]+"$|^"+n[t]+"$","i");return r}(r,s),shortMonthsParse:function(e){var n,t=[];for(n=0;n<12;n++)t[n]=new RegExp("^"+e[n]+"$","i");return t}(s),longMonthsParse:function(e){var n,t=[];for(n=0;n<12;n++)t[n]=new RegExp("^"+e[n]+"$","i");return t}(r),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/cv.js ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Chuvash [cv]
3
+ //! author : Anatoly Mironov : https://github.com/mirontoli
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var cv = moment.defineLocale('cv', {
14
+ months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'),
15
+ monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
16
+ weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'),
17
+ weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
18
+ weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
19
+ longDateFormat : {
20
+ LT : 'HH:mm',
21
+ LTS : 'HH:mm:ss',
22
+ L : 'DD-MM-YYYY',
23
+ LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
24
+ LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
25
+ LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm'
26
+ },
27
+ calendar : {
28
+ sameDay: '[Паян] LT [сехетре]',
29
+ nextDay: '[Ыран] LT [сехетре]',
30
+ lastDay: '[Ӗнер] LT [сехетре]',
31
+ nextWeek: '[Ҫитес] dddd LT [сехетре]',
32
+ lastWeek: '[Иртнӗ] dddd LT [сехетре]',
33
+ sameElse: 'L'
34
+ },
35
+ relativeTime : {
36
+ future : function (output) {
37
+ var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран';
38
+ return output + affix;
39
+ },
40
+ past : '%s каялла',
41
+ s : 'пӗр-ик ҫеккунт',
42
+ m : 'пӗр минут',
43
+ mm : '%d минут',
44
+ h : 'пӗр сехет',
45
+ hh : '%d сехет',
46
+ d : 'пӗр кун',
47
+ dd : '%d кун',
48
+ M : 'пӗр уйӑх',
49
+ MM : '%d уйӑх',
50
+ y : 'пӗр ҫул',
51
+ yy : '%d ҫул'
52
+ },
53
+ ordinalParse: /\d{1,2}-мӗш/,
54
+ ordinal : '%d-мӗш',
55
+ week : {
56
+ dow : 1, // Monday is the first day of the week.
57
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
58
+ }
59
+ });
60
+
61
+ return cv;
62
+
63
+ }));
bp-core/js/vendor/moment-js/locale/cv.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,_){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?_(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],_):_(e.moment)}(this,function(e){"use strict";return e.defineLocale("cv",{months:"кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав".split("_"),monthsShort:"кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кӗҫ_эрн_шӑм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кҫ_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]",LLL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm",LLLL:"dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ӗнер] LT [сехетре]",nextWeek:"[Ҫитес] dddd LT [сехетре]",lastWeek:"[Иртнӗ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(e){return e+(/сехет$/i.exec(e)?"рен":/ҫул$/i.exec(e)?"тан":"ран")},past:"%s каялла",s:"пӗр-ик ҫеккунт",m:"пӗр минут",mm:"%d минут",h:"пӗр сехет",hh:"%d сехет",d:"пӗр кун",dd:"%d кун",M:"пӗр уйӑх",MM:"%d уйӑх",y:"пӗр ҫул",yy:"%d ҫул"},ordinalParse:/\d{1,2}-мӗш/,ordinal:"%d-мӗш",week:{dow:1,doy:7}})});
bp-core/js/vendor/moment-js/locale/cy.js ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Welsh [cy]
3
+ //! author : Robert Allen : https://github.com/robgallen
4
+ //! author : https://github.com/ryangreaves
5
+
6
+ ;(function (global, factory) {
7
+ typeof exports === 'object' && typeof module !== 'undefined'
8
+ && typeof require === 'function' ? factory(require('../moment')) :
9
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
10
+ factory(global.moment)
11
+ }(this, function (moment) { 'use strict';
12
+
13
+
14
+ var cy = moment.defineLocale('cy', {
15
+ months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
16
+ monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
17
+ weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
18
+ weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
19
+ weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
20
+ weekdaysParseExact : true,
21
+ // time formats are the same as en-gb
22
+ longDateFormat: {
23
+ LT: 'HH:mm',
24
+ LTS : 'HH:mm:ss',
25
+ L: 'DD/MM/YYYY',
26
+ LL: 'D MMMM YYYY',
27
+ LLL: 'D MMMM YYYY HH:mm',
28
+ LLLL: 'dddd, D MMMM YYYY HH:mm'
29
+ },
30
+ calendar: {
31
+ sameDay: '[Heddiw am] LT',
32
+ nextDay: '[Yfory am] LT',
33
+ nextWeek: 'dddd [am] LT',
34
+ lastDay: '[Ddoe am] LT',
35
+ lastWeek: 'dddd [diwethaf am] LT',
36
+ sameElse: 'L'
37
+ },
38
+ relativeTime: {
39
+ future: 'mewn %s',
40
+ past: '%s yn ôl',
41
+ s: 'ychydig eiliadau',
42
+ m: 'munud',
43
+ mm: '%d munud',
44
+ h: 'awr',
45
+ hh: '%d awr',
46
+ d: 'diwrnod',
47
+ dd: '%d diwrnod',
48
+ M: 'mis',
49
+ MM: '%d mis',
50
+ y: 'blwyddyn',
51
+ yy: '%d flynedd'
52
+ },
53
+ ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
54
+ // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
55
+ ordinal: function (number) {
56
+ var b = number,
57
+ output = '',
58
+ lookup = [
59
+ '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
60
+ 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
61
+ ];
62
+ if (b > 20) {
63
+ if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
64
+ output = 'fed'; // not 30ain, 70ain or 90ain
65
+ } else {
66
+ output = 'ain';
67
+ }
68
+ } else if (b > 0) {
69
+ output = lookup[b];
70
+ }
71
+ return number + output;
72
+ },
73
+ week : {
74
+ dow : 1, // Monday is the first day of the week.
75
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
76
+ }
77
+ });
78
+
79
+ return cy;
80
+
81
+ }));
bp-core/js/vendor/moment-js/locale/cy.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,d){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?d(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],d):d(e.moment)}(this,function(e){"use strict";return e.defineLocale("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn ôl",s:"ychydig eiliadau",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},ordinalParse:/\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,ordinal:function(e){var d=e,a="",n=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed","eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"];return d>20?a=40===d||50===d||60===d||80===d||100===d?"fed":"ain":d>0&&(a=n[d]),e+a},week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/da.js ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Danish [da]
3
+ //! author : Ulrik Nielsen : https://github.com/mrbase
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var da = moment.defineLocale('da', {
14
+ months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
15
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
16
+ weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
17
+ weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
18
+ weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
19
+ longDateFormat : {
20
+ LT : 'HH:mm',
21
+ LTS : 'HH:mm:ss',
22
+ L : 'DD/MM/YYYY',
23
+ LL : 'D. MMMM YYYY',
24
+ LLL : 'D. MMMM YYYY HH:mm',
25
+ LLLL : 'dddd [d.] D. MMMM YYYY HH:mm'
26
+ },
27
+ calendar : {
28
+ sameDay : '[I dag kl.] LT',
29
+ nextDay : '[I morgen kl.] LT',
30
+ nextWeek : 'dddd [kl.] LT',
31
+ lastDay : '[I går kl.] LT',
32
+ lastWeek : '[sidste] dddd [kl] LT',
33
+ sameElse : 'L'
34
+ },
35
+ relativeTime : {
36
+ future : 'om %s',
37
+ past : '%s siden',
38
+ s : 'få sekunder',
39
+ m : 'et minut',
40
+ mm : '%d minutter',
41
+ h : 'en time',
42
+ hh : '%d timer',
43
+ d : 'en dag',
44
+ dd : '%d dage',
45
+ M : 'en måned',
46
+ MM : '%d måneder',
47
+ y : 'et år',
48
+ yy : '%d år'
49
+ },
50
+ ordinalParse: /\d{1,2}\./,
51
+ ordinal : '%d.',
52
+ week : {
53
+ dow : 1, // Monday is the first day of the week.
54
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
55
+ }
56
+ });
57
+
58
+ return da;
59
+
60
+ }));
bp-core/js/vendor/moment-js/locale/da.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,d){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?d(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],d):d(e.moment)}(this,function(e){"use strict";return e.defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY HH:mm"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/de-at.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : German (Austria) [de-at]
3
+ //! author : lluchs : https://github.com/lluchs
4
+ //! author: Menelion Elensúle: https://github.com/Oire
5
+ //! author : Martin Groller : https://github.com/MadMG
6
+ //! author : Mikolaj Dadela : https://github.com/mik01aj
7
+
8
+ ;(function (global, factory) {
9
+ typeof exports === 'object' && typeof module !== 'undefined'
10
+ && typeof require === 'function' ? factory(require('../moment')) :
11
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
12
+ factory(global.moment)
13
+ }(this, function (moment) { 'use strict';
14
+
15
+
16
+ function processRelativeTime(number, withoutSuffix, key, isFuture) {
17
+ var format = {
18
+ 'm': ['eine Minute', 'einer Minute'],
19
+ 'h': ['eine Stunde', 'einer Stunde'],
20
+ 'd': ['ein Tag', 'einem Tag'],
21
+ 'dd': [number + ' Tage', number + ' Tagen'],
22
+ 'M': ['ein Monat', 'einem Monat'],
23
+ 'MM': [number + ' Monate', number + ' Monaten'],
24
+ 'y': ['ein Jahr', 'einem Jahr'],
25
+ 'yy': [number + ' Jahre', number + ' Jahren']
26
+ };
27
+ return withoutSuffix ? format[key][0] : format[key][1];
28
+ }
29
+
30
+ var de_at = moment.defineLocale('de-at', {
31
+ months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
32
+ monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
33
+ monthsParseExact : true,
34
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
35
+ weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
36
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
37
+ weekdaysParseExact : true,
38
+ longDateFormat : {
39
+ LT: 'HH:mm',
40
+ LTS: 'HH:mm:ss',
41
+ L : 'DD.MM.YYYY',
42
+ LL : 'D. MMMM YYYY',
43
+ LLL : 'D. MMMM YYYY HH:mm',
44
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
45
+ },
46
+ calendar : {
47
+ sameDay: '[heute um] LT [Uhr]',
48
+ sameElse: 'L',
49
+ nextDay: '[morgen um] LT [Uhr]',
50
+ nextWeek: 'dddd [um] LT [Uhr]',
51
+ lastDay: '[gestern um] LT [Uhr]',
52
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
53
+ },
54
+ relativeTime : {
55
+ future : 'in %s',
56
+ past : 'vor %s',
57
+ s : 'ein paar Sekunden',
58
+ m : processRelativeTime,
59
+ mm : '%d Minuten',
60
+ h : processRelativeTime,
61
+ hh : '%d Stunden',
62
+ d : processRelativeTime,
63
+ dd : processRelativeTime,
64
+ M : processRelativeTime,
65
+ MM : processRelativeTime,
66
+ y : processRelativeTime,
67
+ yy : processRelativeTime
68
+ },
69
+ ordinalParse: /\d{1,2}\./,
70
+ ordinal : '%d.',
71
+ week : {
72
+ dow : 1, // Monday is the first day of the week.
73
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
74
+ }
75
+ });
76
+
77
+ return de_at;
78
+
79
+ }));
bp-core/js/vendor/moment-js/locale/de-at.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?n(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],n):n(e.moment)}(this,function(e){"use strict";function n(e,n,t,a){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return n?r[t][0]:r[t][1]}return e.defineLocale("de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:n,mm:"%d Minuten",h:n,hh:"%d Stunden",d:n,dd:n,M:n,MM:n,y:n,yy:n},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/de.js ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : German [de]
3
+ //! author : lluchs : https://github.com/lluchs
4
+ //! author: Menelion Elensúle: https://github.com/Oire
5
+ //! author : Mikolaj Dadela : https://github.com/mik01aj
6
+
7
+ ;(function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined'
9
+ && typeof require === 'function' ? factory(require('../moment')) :
10
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
11
+ factory(global.moment)
12
+ }(this, function (moment) { 'use strict';
13
+
14
+
15
+ function processRelativeTime(number, withoutSuffix, key, isFuture) {
16
+ var format = {
17
+ 'm': ['eine Minute', 'einer Minute'],
18
+ 'h': ['eine Stunde', 'einer Stunde'],
19
+ 'd': ['ein Tag', 'einem Tag'],
20
+ 'dd': [number + ' Tage', number + ' Tagen'],
21
+ 'M': ['ein Monat', 'einem Monat'],
22
+ 'MM': [number + ' Monate', number + ' Monaten'],
23
+ 'y': ['ein Jahr', 'einem Jahr'],
24
+ 'yy': [number + ' Jahre', number + ' Jahren']
25
+ };
26
+ return withoutSuffix ? format[key][0] : format[key][1];
27
+ }
28
+
29
+ var de = moment.defineLocale('de', {
30
+ months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
31
+ monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
32
+ monthsParseExact : true,
33
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
34
+ weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
35
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
36
+ weekdaysParseExact : true,
37
+ longDateFormat : {
38
+ LT: 'HH:mm',
39
+ LTS: 'HH:mm:ss',
40
+ L : 'DD.MM.YYYY',
41
+ LL : 'D. MMMM YYYY',
42
+ LLL : 'D. MMMM YYYY HH:mm',
43
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
44
+ },
45
+ calendar : {
46
+ sameDay: '[heute um] LT [Uhr]',
47
+ sameElse: 'L',
48
+ nextDay: '[morgen um] LT [Uhr]',
49
+ nextWeek: 'dddd [um] LT [Uhr]',
50
+ lastDay: '[gestern um] LT [Uhr]',
51
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
52
+ },
53
+ relativeTime : {
54
+ future : 'in %s',
55
+ past : 'vor %s',
56
+ s : 'ein paar Sekunden',
57
+ m : processRelativeTime,
58
+ mm : '%d Minuten',
59
+ h : processRelativeTime,
60
+ hh : '%d Stunden',
61
+ d : processRelativeTime,
62
+ dd : processRelativeTime,
63
+ M : processRelativeTime,
64
+ MM : processRelativeTime,
65
+ y : processRelativeTime,
66
+ yy : processRelativeTime
67
+ },
68
+ ordinalParse: /\d{1,2}\./,
69
+ ordinal : '%d.',
70
+ week : {
71
+ dow : 1, // Monday is the first day of the week.
72
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
73
+ }
74
+ });
75
+
76
+ return de;
77
+
78
+ }));
bp-core/js/vendor/moment-js/locale/de.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?n(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],n):n(e.moment)}(this,function(e){"use strict";function n(e,n,t,a){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return n?r[t][0]:r[t][1]}return e.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:n,mm:"%d Minuten",h:n,hh:"%d Stunden",d:n,dd:n,M:n,MM:n,y:n,yy:n},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})});
bp-core/js/vendor/moment-js/locale/dv.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! moment.js locale configuration
2
+ //! locale : Maldivian [dv]
3
+ //! author : Jawish Hameed : https://github.com/jawish
4
+
5
+ ;(function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined'
7
+ && typeof require === 'function' ? factory(require('../moment')) :
8
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
9
+ factory(global.moment)
10
+ }(this, function (moment) { 'use strict';
11
+
12
+
13
+ var months = [
14
+ 'ޖެނުއަރީ',
15
+ 'ފެބްރުއަރީ',
16
+ 'މާރިޗު',
17
+ 'އޭޕްރީލު',
18
+ 'މޭ',
19
+ 'ޖޫން',
20
+ 'ޖުލައި',
21
+ 'އޯގަސްޓު',
22
+ 'ސެޕްޓެމްބަރު',
23
+ 'އޮކްޓޯބަރު',
24
+ 'ނޮވެމްބަރު',
25
+ 'ޑިސެމްބަރު'
26
+ ], weekdays = [
27
+ 'އާދިއްތަ',
28
+ 'ހޯމަ',
29
+ 'އަންގާރަ',
30
+ 'ބުދަ',
31
+ 'ބުރާސްފަތި',
32
+ 'ހުކުރު',
33
+ 'ހޮނިހިރު'
34
+ ];
35
+
36
+ var dv = moment.defineLocale('dv', {
37
+ months : months,
38
+ monthsShort : months,
39
+ weekdays : weekdays,
40
+ weekdaysShort : weekdays,
41
+ weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
42
+ longDateFormat : {
43
+
44
+ LT : 'HH:mm',
45
+ LTS : 'HH:mm:ss',
46
+ L : 'D/M/YYYY',
47
+ LL : 'D MMMM YYYY',
48
+ LLL : 'D MMMM YYYY HH:mm',
49
+ LLLL : 'dddd D MMMM YYYY HH:mm'
50
+ },
51
+ meridiemParse: /މކ|މފ/,
52
+ isPM : function (input) {
53
+ return 'މފ' === input;
54
+ },
55
+ meridiem : function (hour, minute, isLower) {
56
+ if (hour < 12) {
57
+ return 'މކ';
58
+ } else {
59
+ return 'މފ';
60
+ }
61
+ },
62
+ calendar : {
63
+ sameDay : '[މިއަދު] LT',
64
+ nextDay : '[މާދަމާ] LT',
65
+ nextWeek : 'dddd LT',
66
+ lastDay : '[އިއްޔެ] LT',
67
+ lastWeek : '[ފާއިތުވި] dddd LT',
68
+ sameElse : 'L'
69
+ },
70
+ relativeTime : {
71
+ future : 'ތެރޭގައި %s',
72
+ past : 'ކުރިން %s',
73
+ s : 'ސިކުންތުކޮޅެއް',
74
+ m : 'މިނިޓެއް',
75
+ mm : 'މިނިޓު %d',
76
+ h : 'ގަޑިއިރެއް',
77
+ hh : 'ގަޑިއިރު %d',
78
+ d : 'ދުވަހެއް',
79
+ dd : 'ދުވަސް %d',
80
+ M : 'މަހެއް',
81
+ MM : 'މަސް %d',
82
+ y : 'އަހަރެއް',
83
+ yy : 'އަހަރު %d'
84
+ },
85
+ preparse: function (string) {
86
+ return string.replace(/،/g, ',');
87
+ },
88
+ postformat: function (string) {
89
+ return string.replace(/,/g, '،');
90
+ },
91
+ week : {
92
+ dow : 7, // Sunday is the first day of the week.
93
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
94
+ }
95
+ });
96
+
97
+ return dv;
98
+
99
+ }));
bp-core/js/vendor/moment-js/locale/dv.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?t(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],t):t(e.moment)}(this,function(e){"use strict";var t=["ޖެނުއަރީ","ފެބްރުއަރީ","މާރިޗު","އޭޕްރީލު","މޭ","ޖޫން","ޖުލައި","އޯގަސްޓު","ސެޕްޓެމްބަރު","އޮކްޓޯބަރު","ނޮވެމްބަރު","ޑިސެމްބަރު"],d=["އާދިއްތަ","ހޯމަ","އަންގާރަ","ބުދަ","ބުރާސްފަތި","ހުކުރު","ހޮނިހިރު"];return e.defineLocale("dv",{months:t,monthsShort:t,weekdays:d,weekdaysShort:d,weekdaysMin:"އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/މކ|މފ/,isPM:function(e){return"މފ"===e},meridiem:function(e,t,d){return e<12?"މކ":"މފ"},calendar:{sameDay:"[މިއަދު] LT",nextDay:"[މާދަމާ] LT",nextWeek:"dddd LT",lastDay:"[އިއްޔެ] LT",lastWeek:"[ފާއިތުވި] dddd LT",sameElse:"L"},relativeTime:{future:"ތެރޭގައި %s",past:"ކުރިން %s",s:"ސިކުންތުކޮޅެއް",m:"މިނިޓެއް",mm:"މިނިޓު %d",h:"ގަޑިއިރެއް",hh:"ގަޑިއިރު %d",d:"ދުވަހެއް",dd:"ދުވަސް %d",M:"މަހެއް",MM:"މަސް %d",y:"އަހަރެއް",yy:"އަހަރު %d"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:7,doy:12}})});
bp-core/js/vendor/moment-js/locale/el.js ADDED
File without changes