BuddyPress - Version 3.2.1

Version Description

= 3.2.0 = See: https://codex.buddypress.org/releases/version-3-2-0/

Download this release

Release Info

Developer imath
Plugin Icon 128x128 BuddyPress
Version 3.2.1
Comparing to
See all releases

Code changes from version 2.9.5.1 to 3.2.1

Files changed (166) 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/bp-activity-actions.php +0 -854
  9. bp-activity/bp-activity-admin.php +8 -9
  10. bp-activity/bp-activity-embeds.php +1 -3
  11. bp-activity/bp-activity-filters.php +1 -33
  12. bp-activity/bp-activity-functions.php +335 -20
  13. bp-activity/bp-activity-notifications.php +101 -5
  14. bp-activity/bp-activity-screens.php +0 -379
  15. bp-activity/bp-activity-template.php +6 -4
  16. bp-activity/classes/class-bp-activity-activity.php +31 -4
  17. bp-activity/classes/class-bp-activity-component.php +58 -4
  18. bp-activity/classes/class-bp-activity-list-table.php +2 -2
  19. bp-activity/classes/class-bp-activity-query.php +1 -1
  20. bp-activity/classes/class-bp-activity-template.php +1 -1
  21. bp-activity/classes/class-bp-akismet.php +18 -5
  22. bp-activity/js/mentions.js +10 -9
  23. bp-activity/js/mentions.min.js +1 -1
  24. bp-activity/screens/directory.php +37 -0
  25. bp-activity/screens/favorites.php +33 -0
  26. bp-activity/screens/friends.php +36 -0
  27. bp-activity/screens/groups.php +36 -0
  28. bp-activity/screens/just-me.php +32 -0
  29. bp-activity/screens/mentions.php +45 -0
  30. bp-activity/screens/permalink.php +166 -0
  31. bp-blogs/{bp-blogs-actions.php → actions/random.php} +3 -6
  32. bp-blogs/bp-blogs-activity.php +27 -9
  33. bp-blogs/bp-blogs-functions.php +16 -1
  34. bp-blogs/bp-blogs-screens.php +0 -73
  35. bp-blogs/classes/class-bp-blogs-component.php +40 -2
  36. bp-blogs/screens/create.php +32 -0
  37. bp-blogs/screens/directory.php +29 -0
  38. bp-blogs/screens/my-blogs.php +27 -0
  39. bp-core/admin/bp-core-admin-components.php +10 -17
  40. bp-core/admin/bp-core-admin-functions.php +11 -29
  41. bp-core/admin/bp-core-admin-schema.php +6 -0
  42. bp-core/admin/bp-core-admin-settings.php +7 -41
  43. bp-core/admin/css/common-rtl.css +240 -348
  44. bp-core/admin/css/common-rtl.min.css +1 -1
  45. bp-core/admin/css/common.css +240 -348
  46. bp-core/admin/css/common.min.css +1 -1
  47. bp-core/admin/css/hello-rtl.css +335 -0
  48. bp-core/admin/css/hello-rtl.min.css +1 -0
  49. bp-core/admin/css/hello.css +335 -0
  50. bp-core/admin/css/hello.min.css +1 -0
  51. bp-core/admin/js/hello.js +116 -0
  52. bp-core/admin/js/hello.min.js +1 -0
  53. bp-core/admin/sass/hello.scss +399 -0
  54. bp-core/bp-core-actions.php +11 -2
  55. bp-core/bp-core-adminbar.php +0 -2
  56. bp-core/bp-core-attachments.php +104 -53
  57. bp-core/bp-core-avatars.php +3 -6
  58. bp-core/bp-core-buddybar.php +7 -4
  59. bp-core/bp-core-cache.php +17 -0
  60. bp-core/bp-core-customizer-email.php +0 -6
  61. bp-core/bp-core-dependency.php +17 -0
  62. bp-core/bp-core-filters.php +6 -8
  63. bp-core/bp-core-functions.php +95 -62
  64. bp-core/bp-core-options.php +3 -59
  65. bp-core/bp-core-template.php +13 -103
  66. bp-core/bp-core-theme-compatibility.php +23 -0
  67. bp-core/classes/class-bp-admin.php +343 -303
  68. bp-core/classes/class-bp-attachment-cover-image.php +1 -34
  69. bp-core/classes/class-bp-component.php +14 -0
  70. bp-core/classes/class-bp-core-nav.php +1 -1
  71. bp-core/classes/class-bp-core-user.php +3 -13
  72. bp-core/classes/class-bp-core.php +1 -1
  73. bp-core/classes/class-bp-email.php +1 -1
  74. bp-core/classes/class-bp-embed.php +0 -5
  75. bp-core/classes/class-bp-members-suggestions.php +5 -4
  76. bp-core/classes/class-bp-user-query.php +6 -11
  77. bp-core/deprecated/1.5.php +0 -13
  78. bp-core/deprecated/2.8.php +8 -4
  79. bp-core/deprecated/3.0.php +187 -0
  80. bp-core/js/confirm.js +3 -3
  81. bp-core/js/confirm.min.js +1 -1
  82. bp-core/js/vendor/jquery.atwho.js +724 -387
  83. bp-core/js/vendor/jquery.atwho.min.js +1 -1
  84. bp-core/js/vendor/jquery.caret.js +32 -1
  85. bp-core/js/vendor/jquery.caret.min.js +1 -1
  86. bp-core/js/webcam.js +34 -23
  87. bp-core/js/webcam.min.js +1 -1
  88. bp-forums/bb-config.php +0 -14
  89. bp-forums/bbpress/bb-admin/admin-action.php +0 -5
  90. bp-forums/bbpress/bb-admin/admin-ajax.php +0 -264
  91. bp-forums/bbpress/bb-admin/admin-base.php +0 -23
  92. bp-forums/bbpress/bb-admin/admin-footer.php +0 -33
  93. bp-forums/bbpress/bb-admin/admin-header.php +0 -57
  94. bp-forums/bbpress/bb-admin/admin.php +0 -45
  95. bp-forums/bbpress/bb-admin/bb-forum.php +0 -61
  96. bp-forums/bbpress/bb-admin/delete-post.php +0 -81
  97. bp-forums/bbpress/bb-admin/delete-topic.php +0 -53
  98. bp-forums/bbpress/bb-admin/export.php +0 -305
  99. bp-forums/bbpress/bb-admin/forums.php +0 -106
  100. bp-forums/bbpress/bb-admin/images/admin-header-logo.gif +0 -0
  101. bp-forums/bbpress/bb-admin/images/bbpress-logo.png +0 -0
  102. bp-forums/bbpress/bb-admin/images/blank.gif +0 -0
  103. bp-forums/bbpress/bb-admin/images/button-grad.png +0 -0
  104. bp-forums/bbpress/bb-admin/images/drag.gif +0 -0
  105. bp-forums/bbpress/bb-admin/images/favicon.ico +0 -0
  106. bp-forums/bbpress/bb-admin/images/gray-grad.png +0 -0
  107. bp-forums/bbpress/bb-admin/images/icons32.png +0 -0
  108. bp-forums/bbpress/bb-admin/images/input-lock.png +0 -0
  109. bp-forums/bbpress/bb-admin/images/menu-arrows.gif +0 -0
  110. bp-forums/bbpress/bb-admin/images/menu-bits-rtl.gif +0 -0
  111. bp-forums/bbpress/bb-admin/images/menu-bits.gif +0 -0
  112. bp-forums/bbpress/bb-admin/images/menu-dark-rtl.gif +0 -0
  113. bp-forums/bbpress/bb-admin/images/menu-dark.gif +0 -0
  114. bp-forums/bbpress/bb-admin/images/menu.png +0 -0
  115. bp-forums/bbpress/bb-admin/images/visit-site-button-grad.gif +0 -0
  116. bp-forums/bbpress/bb-admin/images/white-grad-active.png +0 -0
  117. bp-forums/bbpress/bb-admin/images/white-grad.png +0 -0
  118. bp-forums/bbpress/bb-admin/includes/class.bb-install.php +0 -2770
  119. bp-forums/bbpress/bb-admin/includes/defaults.bb-htaccess.php +0 -46
  120. bp-forums/bbpress/bb-admin/includes/defaults.bb-schema.php +0 -235
  121. bp-forums/bbpress/bb-admin/includes/functions.bb-admin.php +0 -1741
  122. bp-forums/bbpress/bb-admin/includes/functions.bb-plugin.php +0 -441
  123. bp-forums/bbpress/bb-admin/includes/functions.bb-recount.php +0 -461
  124. bp-forums/bbpress/bb-admin/includes/functions.bb-upgrade.php +0 -533
  125. bp-forums/bbpress/bb-admin/index.php +0 -149
  126. bp-forums/bbpress/bb-admin/install-rtl.css +0 -100
  127. bp-forums/bbpress/bb-admin/install.css +0 -433
  128. bp-forums/bbpress/bb-admin/install.php +0 -401
  129. bp-forums/bbpress/bb-admin/js/admin-forums.js +0 -140
  130. bp-forums/bbpress/bb-admin/js/common.js +0 -93
  131. bp-forums/bbpress/bb-admin/js/utils.js +0 -166
  132. bp-forums/bbpress/bb-admin/options-discussion.php +0 -156
  133. bp-forums/bbpress/bb-admin/options-general.php +0 -244
  134. bp-forums/bbpress/bb-admin/options-permalinks.php +0 -188
  135. bp-forums/bbpress/bb-admin/options-reading.php +0 -77
  136. bp-forums/bbpress/bb-admin/options-wordpress.php +0 -313
  137. bp-forums/bbpress/bb-admin/options-writing.php +0 -92
  138. bp-forums/bbpress/bb-admin/plugins.php +0 -268
  139. bp-forums/bbpress/bb-admin/posts.php +0 -195
  140. bp-forums/bbpress/bb-admin/rewrite-rules.php +0 -4
  141. bp-forums/bbpress/bb-admin/sticky.php +0 -29
  142. bp-forums/bbpress/bb-admin/style-rtl.css +0 -465
  143. bp-forums/bbpress/bb-admin/style.css +0 -1932
  144. bp-forums/bbpress/bb-admin/tag-destroy.php +0 -20
  145. bp-forums/bbpress/bb-admin/tag-merge.php +0 -29
  146. bp-forums/bbpress/bb-admin/tag-rename.php +0 -23
  147. bp-forums/bbpress/bb-admin/themes.php +0 -159
  148. bp-forums/bbpress/bb-admin/tools-recount.php +0 -121
  149. bp-forums/bbpress/bb-admin/topic-move.php +0 -30
  150. bp-forums/bbpress/bb-admin/topic-toggle.php +0 -33
  151. bp-forums/bbpress/bb-admin/topics.php +0 -267
  152. bp-forums/bbpress/bb-admin/upgrade.php +0 -210
  153. bp-forums/bbpress/bb-admin/user-add-new.php +0 -49
  154. bp-forums/bbpress/bb-admin/users.php +0 -68
  155. bp-forums/bbpress/bb-config-sample.php +0 -63
  156. bp-forums/bbpress/bb-cron.php +0 -54
  157. bp-forums/bbpress/bb-edit.php +0 -68
  158. bp-forums/bbpress/bb-includes/action.subscribe.php +0 -29
  159. bp-forums/bbpress/bb-includes/backpress/class.bp-log.php +0 -550
  160. bp-forums/bbpress/bb-includes/backpress/class.bp-roles.php +0 -90
  161. bp-forums/bbpress/bb-includes/backpress/class.bp-sql-schema-parser.php +0 -615
  162. bp-forums/bbpress/bb-includes/backpress/class.bp-user.php +0 -402
  163. bp-forums/bbpress/bb-includes/backpress/class.bpdb-multi.php +0 -196
  164. bp-forums/bbpress/bb-includes/backpress/class.bpdb.php +0 -1164
  165. bp-forums/bbpress/bb-includes/backpress/class.ixr.php +0 -1115
  166. bp-forums/bbpress/bb-includes/backpress/class.mailer-smtp.php +0 -580
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/bp-activity-actions.php DELETED
@@ -1,854 +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( $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
- * AJAX endpoint for Suggestions API lookups.
609
- *
610
- * @since 2.1.0
611
- */
612
- function bp_ajax_get_suggestions() {
613
- if ( ! bp_is_user_active() || empty( $_GET['term'] ) || empty( $_GET['type'] ) ) {
614
- wp_send_json_error( 'missing_parameter' );
615
- exit;
616
- }
617
-
618
- $args = array(
619
- 'term' => sanitize_text_field( $_GET['term'] ),
620
- 'type' => sanitize_text_field( $_GET['type'] ),
621
- );
622
-
623
- // Support per-Group suggestions.
624
- if ( ! empty( $_GET['group-id'] ) ) {
625
- $args['group_id'] = absint( $_GET['group-id'] );
626
- }
627
-
628
- $results = bp_core_get_suggestions( $args );
629
-
630
- if ( is_wp_error( $results ) ) {
631
- wp_send_json_error( $results->get_error_message() );
632
- exit;
633
- }
634
-
635
- wp_send_json_success( $results );
636
- }
637
- add_action( 'wp_ajax_bp_get_suggestions', 'bp_ajax_get_suggestions' );
638
-
639
- /**
640
- * Detect a change in post type status, and initiate an activity update if necessary.
641
- *
642
- * @since 2.2.0
643
- *
644
- * @todo Support untrashing better.
645
- *
646
- * @param string $new_status New status for the post.
647
- * @param string $old_status Old status for the post.
648
- * @param object $post Post data.
649
- */
650
- function bp_activity_catch_transition_post_type_status( $new_status, $old_status, $post ) {
651
- if ( ! post_type_supports( $post->post_type, 'buddypress-activity' ) ) {
652
- return;
653
- }
654
-
655
- // This is an edit.
656
- if ( $new_status === $old_status ) {
657
- // An edit of an existing post should update the existing activity item.
658
- if ( $new_status == 'publish' ) {
659
- $edit = bp_activity_post_type_update( $post );
660
-
661
- // Post was never recorded into activity stream, so record it now!
662
- if ( null === $edit ) {
663
- bp_activity_post_type_publish( $post->ID, $post );
664
- }
665
-
666
- // Allow plugins to eventually deal with other post statuses.
667
- } else {
668
- /**
669
- * Fires when editing the post and the new status is not 'publish'.
670
- *
671
- * This is a variable filter that is dependent on the post type
672
- * being untrashed.
673
- *
674
- * @since 2.5.0
675
- *
676
- * @param WP_Post $post Post data.
677
- * @param string $new_status New status for the post.
678
- * @param string $old_status Old status for the post.
679
- */
680
- do_action( 'bp_activity_post_type_edit_' . $post->post_type, $post, $new_status, $old_status );
681
- }
682
-
683
- return;
684
- }
685
-
686
- // Publishing a previously unpublished post.
687
- if ( 'publish' === $new_status ) {
688
- // Untrashing the post type - nothing here yet.
689
- if ( 'trash' == $old_status ) {
690
-
691
- /**
692
- * Fires if untrashing post in a post type.
693
- *
694
- * This is a variable filter that is dependent on the post type
695
- * being untrashed.
696
- *
697
- * @since 2.2.0
698
- *
699
- * @param WP_Post $post Post data.
700
- */
701
- do_action( 'bp_activity_post_type_untrash_' . $post->post_type, $post );
702
- } else {
703
- // Record the post.
704
- bp_activity_post_type_publish( $post->ID, $post );
705
- }
706
-
707
- // Unpublishing a previously published post.
708
- } elseif ( 'publish' === $old_status ) {
709
- // Some form of pending status - only remove the activity entry.
710
- bp_activity_post_type_unpublish( $post->ID, $post );
711
-
712
- // For any other cases, allow plugins to eventually deal with it.
713
- } else {
714
- /**
715
- * Fires when the old and the new post status are not 'publish'.
716
- *
717
- * This is a variable filter that is dependent on the post type
718
- * being untrashed.
719
- *
720
- * @since 2.5.0
721
- *
722
- * @param WP_Post $post Post data.
723
- * @param string $new_status New status for the post.
724
- * @param string $old_status Old status for the post.
725
- */
726
- do_action( 'bp_activity_post_type_transition_status_' . $post->post_type, $post, $new_status, $old_status );
727
- }
728
- }
729
- add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 );
730
-
731
- /**
732
- * When a post type comment status transition occurs, update the relevant activity's status.
733
- *
734
- * @since 2.5.0
735
- *
736
- * @param string $new_status New comment status.
737
- * @param string $old_status Previous comment status.
738
- * @param WP_Comment $comment Comment data.
739
- */
740
- function bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment ) {
741
- $post_type = get_post_type( $comment->comment_post_ID );
742
- if ( ! $post_type ) {
743
- return;
744
- }
745
-
746
- // Get the post type tracking args.
747
- $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
748
-
749
- // Bail if the activity type does not exist
750
- if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
751
- return false;
752
-
753
- // Set the $activity_comment_object
754
- } else {
755
- $activity_comment_object = $activity_post_object->comments_tracking;
756
- }
757
-
758
- // Init an empty activity ID
759
- $activity_id = 0;
760
-
761
- /**
762
- * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
763
- *
764
- * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
765
- * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
766
- * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
767
- * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
768
- * Otherwise, record the comment into the activity stream.
769
- */
770
-
771
- // This clause handles delete/hold.
772
- if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
773
- return bp_activity_post_type_remove_comment( $comment->comment_ID, $activity_post_object );
774
-
775
- // These clauses handle trash, spam, and un-spams.
776
- } elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
777
- $action = 'spam_activity';
778
- } elseif ( 'approved' == $new_status ) {
779
- $action = 'ham_activity';
780
- }
781
-
782
- // Get the activity
783
- if ( bp_disable_blogforum_comments() ) {
784
- $activity_id = bp_activity_get_activity_id( array(
785
- 'component' => $activity_comment_object->component_id,
786
- 'item_id' => get_current_blog_id(),
787
- 'secondary_item_id' => $comment->comment_ID,
788
- 'type' => $activity_comment_object->action_id,
789
- ) );
790
- } else {
791
- $activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
792
- }
793
-
794
- /**
795
- * Leave a chance to plugins to manage activity comments differently.
796
- *
797
- * @since 2.5.0
798
- *
799
- * @param bool $value True to override BuddyPress management.
800
- * @param string $post_type The post type name.
801
- * @param int $activity_id The post type activity (0 if not found).
802
- * @param string $new_status The new status of the post type comment.
803
- * @param string $old_status The old status of the post type comment.
804
- * @param WP_Comment $comment Comment data.
805
- */
806
- if ( true === apply_filters( 'bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment ) ) {
807
- return false;
808
- }
809
-
810
- // Check activity item exists
811
- if ( empty( $activity_id ) ) {
812
- // If no activity exists, but the comment has been approved, record it into the activity table.
813
- if ( 'approved' == $new_status ) {
814
- return bp_activity_post_type_comment( $comment->comment_ID, true, $activity_post_object );
815
- }
816
-
817
- return;
818
- }
819
-
820
- // Create an activity object
821
- $activity = new BP_Activity_Activity( $activity_id );
822
- if ( empty( $activity->component ) ) {
823
- return;
824
- }
825
-
826
- // Spam/ham the activity if it's not already in that state
827
- if ( 'spam_activity' === $action && ! $activity->is_spam ) {
828
- bp_activity_mark_as_spam( $activity );
829
- } elseif ( 'ham_activity' == $action) {
830
- bp_activity_mark_as_ham( $activity );
831
- }
832
-
833
- // Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
834
- $post_type_comment_action = $activity_comment_object->action_id;
835
- $comment_akismet_history = function ( $activity_types ) use ( $post_type_comment_action ) {
836
- $activity_types[] = $post_type_comment_action;
837
-
838
- return $activity_types;
839
- };
840
- add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
841
-
842
- // Make sure the activity change won't edit the comment if sync is on
843
- remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
844
-
845
- // Save the updated activity
846
- $activity->save();
847
-
848
- // Restore the action
849
- add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
850
-
851
- // Remove the "new_blog_comment" activity type whitelist so we don't break anything
852
- remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
853
- }
854
- add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-admin.php CHANGED
@@ -94,7 +94,7 @@ function bp_activity_admin_reply() {
94
 
95
  // @todo: Check if user is allowed to create new activity items
96
  // if ( ! current_user_can( 'bp_new_activity' ) )
97
- if ( ! current_user_can( 'bp_moderate' ) )
98
  die( '-1' );
99
 
100
  // Add new activity comment.
@@ -232,7 +232,7 @@ function bp_activity_admin_load() {
232
  'title' => __( 'Item, Link, Type', 'buddypress' ),
233
  'content' =>
234
  '<p>' . __( '<strong>Primary Item/Secondary Item</strong> - These identify the object that created the activity. For example, the fields could reference a comment left on a specific site. Some types of activity may only use one, or none, of these fields.', 'buddypress' ) . '</p>' .
235
- '<p>' . __( '<strong>Link</strong> - Used by some types of activity (e.g blog posts and comments, and forum topics and replies) to store a link back to the original content.', 'buddypress' ) . '</p>' .
236
  '<p>' . __( '<strong>Type</strong> - Each distinct kind of activity has its own type. For example, <code>created_group</code> is used when a group is created and <code>joined_group</code> is used when a user joins a group.', 'buddypress' ) . '</p>' .
237
  '<p>' . __( 'For information about when and how BuddyPress uses all of these settings, see the Managing Activity link in the panel to the side.', 'buddypress' ) . '</p>'
238
  ) );
@@ -296,12 +296,11 @@ function bp_activity_admin_load() {
296
  );
297
 
298
  // Add accessible hidden heading and text for Activity screen pagination.
299
- if ( bp_get_major_wp_version() >= 4.4 ) {
300
- get_current_screen()->set_screen_reader_content( array(
301
- /* translators: accessibility text */
302
- 'heading_pagination' => __( 'Activity list navigation', 'buddypress' ),
303
- ) );
304
- }
305
  }
306
 
307
  // Enqueue CSS and JavaScript.
@@ -800,7 +799,7 @@ function bp_activity_admin_edit_metabox_link( $item ) {
800
  _e( 'Link', 'buddypress' );
801
  ?></label>
802
  <input type="url" name="bp-activities-link" id="bp-activities-link" value="<?php echo esc_url( $item->primary_link ); ?>" aria-describedby="bp-activities-link-description" />
803
- <p id="bp-activities-link-description"><?php _e( 'Activity generated by posts and comments, forum topics and replies, and some plugins, uses the link field for a permalink back to the content item.', 'buddypress' ); ?></p>
804
 
805
  <?php
806
  }
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.
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.
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
  }
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
 
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
 
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
 
@@ -204,36 +202,6 @@ function bp_activity_check_blacklist_keys( $activity ) {
204
  * @return string $content Filtered activity content.
205
  */
206
  function bp_activity_filter_kses( $content ) {
207
- global $allowedtags;
208
-
209
- $activity_allowedtags = $allowedtags;
210
- $activity_allowedtags['a']['aria-label'] = array();
211
- $activity_allowedtags['a']['class'] = array();
212
- $activity_allowedtags['a']['data-bp-tooltip'] = array();
213
- $activity_allowedtags['a']['id'] = array();
214
- $activity_allowedtags['a']['rel'] = array();
215
- $activity_allowedtags['a']['title'] = array();
216
-
217
- $activity_allowedtags['b'] = array();
218
- $activity_allowedtags['code'] = array();
219
- $activity_allowedtags['i'] = array();
220
-
221
- $activity_allowedtags['img'] = array();
222
- $activity_allowedtags['img']['src'] = array();
223
- $activity_allowedtags['img']['alt'] = array();
224
- $activity_allowedtags['img']['width'] = array();
225
- $activity_allowedtags['img']['height'] = array();
226
- $activity_allowedtags['img']['class'] = array();
227
- $activity_allowedtags['img']['id'] = array();
228
-
229
- $activity_allowedtags['span'] = array();
230
- $activity_allowedtags['span']['class'] = array();
231
- $activity_allowedtags['span']['data-livestamp'] = array();
232
-
233
- $activity_allowedtags['ul'] = array();
234
- $activity_allowedtags['ol'] = array();
235
- $activity_allowedtags['li'] = array();
236
-
237
  /**
238
  * Filters the allowed HTML tags for BuddyPress Activity content.
239
  *
@@ -241,7 +209,7 @@ function bp_activity_filter_kses( $content ) {
241
  *
242
  * @param array $value Array of allowed HTML tags and attributes.
243
  */
244
- $activity_allowedtags = apply_filters( 'bp_activity_allowed_tags', $activity_allowedtags );
245
  return wp_kses( $content, $activity_allowedtags );
246
  }
247
 
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
 
202
  * @return string $content Filtered activity content.
203
  */
204
  function bp_activity_filter_kses( $content ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  /**
206
  * Filters the allowed HTML tags for BuddyPress Activity content.
207
  *
209
  *
210
  * @param array $value Array of allowed HTML tags and attributes.
211
  */
212
+ $activity_allowedtags = apply_filters( 'bp_activity_allowed_tags', bp_get_allowedtags() );
213
  return wp_kses( $content, $activity_allowedtags );
214
  }
215
 
bp-activity/bp-activity-functions.php CHANGED
@@ -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
  }
@@ -937,11 +940,6 @@ function bp_activity_get_user_favorites( $user_id = 0 ) {
937
  */
938
  function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
939
 
940
- // Favorite activity stream items are for logged in users only.
941
- if ( ! is_user_logged_in() ) {
942
- return false;
943
- }
944
-
945
  // Fallback to logged in user if no user_id is passed.
946
  if ( empty( $user_id ) ) {
947
  $user_id = bp_loggedin_user_id();
@@ -1011,11 +1009,6 @@ function bp_activity_add_user_favorite( $activity_id, $user_id = 0 ) {
1011
  */
1012
  function bp_activity_remove_user_favorite( $activity_id, $user_id = 0 ) {
1013
 
1014
- // Favorite activity stream items are for logged in users only.
1015
- if ( ! is_user_logged_in() ) {
1016
- return false;
1017
- }
1018
-
1019
  // Fallback to logged in user if no user_id is passed.
1020
  if ( empty( $user_id ) ) {
1021
  $user_id = bp_loggedin_user_id();
@@ -1260,9 +1253,7 @@ function bp_activity_add_meta( $activity_id, $meta_key, $meta_value, $unique = f
1260
  * @return bool
1261
  */
1262
  function bp_activity_remove_all_user_data( $user_id = 0 ) {
1263
-
1264
- // Do not delete user data unless a logged in user says so.
1265
- if ( empty( $user_id ) || ! is_user_logged_in() ) {
1266
  return false;
1267
  }
1268
 
@@ -1427,6 +1418,21 @@ function bp_activity_ham_all_user_data( $user_id = 0 ) {
1427
  }
1428
  add_action( 'bp_make_ham_user', 'bp_activity_ham_all_user_data' );
1429
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1430
  /**
1431
  * Register the activity stream actions for updates.
1432
  *
@@ -1715,7 +1721,7 @@ function bp_activity_get( $args = '' ) {
1715
  * 'user_id' => false, // User ID to filter on.
1716
  * 'object' => false, // Object to filter on e.g. groups, profile, status, friends.
1717
  * 'action' => false, // Action to filter on e.g. activity_update, profile_updated.
1718
- * 'primary_id' => false, // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
1719
  * 'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
1720
  * );
1721
  */
@@ -2629,10 +2635,12 @@ function bp_activity_new_comment( $args = '' ) {
2629
  * Filters the content of a new comment.
2630
  *
2631
  * @since 1.2.0
 
2632
  *
2633
- * @param string $r Content for the newly posted comment.
 
2634
  */
2635
- $comment_content = apply_filters( 'bp_activity_comment_content', $r['content'] );
2636
 
2637
  // Insert the activity comment.
2638
  $comment_id = bp_activity_add( array(
@@ -3089,6 +3097,64 @@ function bp_activity_get_permalink( $activity_id, $activity_obj = false ) {
3089
  return apply_filters_ref_array( 'bp_activity_get_permalink', array( $link, &$activity_obj ) );
3090
  }
3091
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3092
  /**
3093
  * Hide a user's activity.
3094
  *
@@ -3268,7 +3334,7 @@ function bp_activity_create_summary( $content, $activity ) {
3268
  // Embeds must be subtracted from the paragraph count.
3269
  if ( ! empty( $media['has']['embeds'] ) ) {
3270
  $has_embeds = $media['has']['embeds'] > 0;
3271
- $para_count -= count( $media['has']['embeds'] );
3272
  }
3273
 
3274
  $extracted_media = array();
@@ -3849,3 +3915,252 @@ function bp_activity_do_heartbeat() {
3849
  */
3850
  return (bool) apply_filters( 'bp_activity_do_heartbeat', $retval );
3851
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
  }
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
  *
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
  */
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(
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 = true;
3111
+
3112
+ // Fallback.
3113
+ if ( empty( $user_id ) ) {
3114
+ $user_id = bp_loggedin_user_id();
3115
+ }
3116
+
3117
+ // If activity is from a group, do extra cap checks.
3118
+ if ( bp_is_active( 'groups' ) && buddypress()->groups->id === $activity->component ) {
3119
+ // Check to see if the user has access to the activity's parent group.
3120
+ $group = groups_get_group( $activity->item_id );
3121
+ if ( $group ) {
3122
+ // For logged-in user, we can check against the 'user_has_access' prop.
3123
+ if ( bp_loggedin_user_id() === $user_id ) {
3124
+ $retval = $group->user_has_access;
3125
+
3126
+ // Manually check status.
3127
+ } elseif ( 'private' === $group->status || 'hidden' === $group->status ) {
3128
+ // Only group members that are not banned can view.
3129
+ if ( ! groups_is_user_member( $user_id, $activity->item_id ) || groups_is_user_banned( $user_id, $activity->item_id ) ) {
3130
+ $retval = false;
3131
+ }
3132
+ }
3133
+ }
3134
+ }
3135
+
3136
+ // Spammed items are not visible to the public.
3137
+ if ( $activity->is_spam ) {
3138
+ $retval = false;
3139
+ }
3140
+
3141
+ // Site moderators can view anything.
3142
+ if ( bp_current_user_can( 'bp_moderate' ) ) {
3143
+ $retval = true;
3144
+ }
3145
+
3146
+ /**
3147
+ * Filters whether the current user has access to an activity item.
3148
+ *
3149
+ * @since 3.0.0
3150
+ *
3151
+ * @param bool $retval Return value.
3152
+ * @param int $user_id Current user ID.
3153
+ * @param BP_Activity_Activity $activity Activity object.
3154
+ */
3155
+ return apply_filters( 'bp_activity_user_can_read', $retval, $user_id, $activity );
3156
+ }
3157
+
3158
  /**
3159
  * Hide a user's activity.
3160
  *
3334
  // Embeds must be subtracted from the paragraph count.
3335
  if ( ! empty( $media['has']['embeds'] ) ) {
3336
  $has_embeds = $media['has']['embeds'] > 0;
3337
+ $para_count -= $media['has']['embeds'];
3338
  }
3339
 
3340
  $extracted_media = array();
3915
  */
3916
  return (bool) apply_filters( 'bp_activity_do_heartbeat', $retval );
3917
  }
3918
+
3919
+ /**
3920
+ * AJAX endpoint for Suggestions API lookups.
3921
+ *
3922
+ * @since 2.1.0
3923
+ */
3924
+ function bp_ajax_get_suggestions() {
3925
+ if ( ! bp_is_user_active() || empty( $_GET['term'] ) || empty( $_GET['type'] ) ) {
3926
+ wp_send_json_error( 'missing_parameter' );
3927
+ exit;
3928
+ }
3929
+
3930
+ $args = array(
3931
+ 'term' => sanitize_text_field( $_GET['term'] ),
3932
+ 'type' => sanitize_text_field( $_GET['type'] ),
3933
+ );
3934
+
3935
+ // Support per-Group suggestions.
3936
+ if ( ! empty( $_GET['group-id'] ) ) {
3937
+ $args['group_id'] = absint( $_GET['group-id'] );
3938
+ }
3939
+
3940
+ $results = bp_core_get_suggestions( $args );
3941
+
3942
+ if ( is_wp_error( $results ) ) {
3943
+ wp_send_json_error( $results->get_error_message() );
3944
+ exit;
3945
+ }
3946
+
3947
+ wp_send_json_success( $results );
3948
+ }
3949
+ add_action( 'wp_ajax_bp_get_suggestions', 'bp_ajax_get_suggestions' );
3950
+
3951
+ /**
3952
+ * Detect a change in post type status, and initiate an activity update if necessary.
3953
+ *
3954
+ * @since 2.2.0
3955
+ *
3956
+ * @todo Support untrashing better.
3957
+ *
3958
+ * @param string $new_status New status for the post.
3959
+ * @param string $old_status Old status for the post.
3960
+ * @param object $post Post data.
3961
+ */
3962
+ function bp_activity_catch_transition_post_type_status( $new_status, $old_status, $post ) {
3963
+ if ( ! post_type_supports( $post->post_type, 'buddypress-activity' ) ) {
3964
+ return;
3965
+ }
3966
+
3967
+ // This is an edit.
3968
+ if ( $new_status === $old_status ) {
3969
+ // An edit of an existing post should update the existing activity item.
3970
+ if ( $new_status == 'publish' ) {
3971
+ $edit = bp_activity_post_type_update( $post );
3972
+
3973
+ // Post was never recorded into activity stream, so record it now!
3974
+ if ( null === $edit ) {
3975
+ bp_activity_post_type_publish( $post->ID, $post );
3976
+ }
3977
+
3978
+ // Allow plugins to eventually deal with other post statuses.
3979
+ } else {
3980
+ /**
3981
+ * Fires when editing the post and the new status is not 'publish'.
3982
+ *
3983
+ * This is a variable filter that is dependent on the post type
3984
+ * being untrashed.
3985
+ *
3986
+ * @since 2.5.0
3987
+ *
3988
+ * @param WP_Post $post Post data.
3989
+ * @param string $new_status New status for the post.
3990
+ * @param string $old_status Old status for the post.
3991
+ */
3992
+ do_action( 'bp_activity_post_type_edit_' . $post->post_type, $post, $new_status, $old_status );
3993
+ }
3994
+
3995
+ return;
3996
+ }
3997
+
3998
+ // Publishing a previously unpublished post.
3999
+ if ( 'publish' === $new_status ) {
4000
+ // Untrashing the post type - nothing here yet.
4001
+ if ( 'trash' == $old_status ) {
4002
+
4003
+ /**
4004
+ * Fires if untrashing post in a post type.
4005
+ *
4006
+ * This is a variable filter that is dependent on the post type
4007
+ * being untrashed.
4008
+ *
4009
+ * @since 2.2.0
4010
+ *
4011
+ * @param WP_Post $post Post data.
4012
+ */
4013
+ do_action( 'bp_activity_post_type_untrash_' . $post->post_type, $post );
4014
+ } else {
4015
+ // Record the post.
4016
+ bp_activity_post_type_publish( $post->ID, $post );
4017
+ }
4018
+
4019
+ // Unpublishing a previously published post.
4020
+ } elseif ( 'publish' === $old_status ) {
4021
+ // Some form of pending status - only remove the activity entry.
4022
+ bp_activity_post_type_unpublish( $post->ID, $post );
4023
+
4024
+ // For any other cases, allow plugins to eventually deal with it.
4025
+ } else {
4026
+ /**
4027
+ * Fires when the old and the new post status are not 'publish'.
4028
+ *
4029
+ * This is a variable filter that is dependent on the post type
4030
+ * being untrashed.
4031
+ *
4032
+ * @since 2.5.0
4033
+ *
4034
+ * @param WP_Post $post Post data.
4035
+ * @param string $new_status New status for the post.
4036
+ * @param string $old_status Old status for the post.
4037
+ */
4038
+ do_action( 'bp_activity_post_type_transition_status_' . $post->post_type, $post, $new_status, $old_status );
4039
+ }
4040
+ }
4041
+ add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 );
4042
+
4043
+ /**
4044
+ * When a post type comment status transition occurs, update the relevant activity's status.
4045
+ *
4046
+ * @since 2.5.0
4047
+ *
4048
+ * @param string $new_status New comment status.
4049
+ * @param string $old_status Previous comment status.
4050
+ * @param WP_Comment $comment Comment data.
4051
+ */
4052
+ function bp_activity_transition_post_type_comment_status( $new_status, $old_status, $comment ) {
4053
+ $post_type = get_post_type( $comment->comment_post_ID );
4054
+ if ( ! $post_type ) {
4055
+ return;
4056
+ }
4057
+
4058
+ // Get the post type tracking args.
4059
+ $activity_post_object = bp_activity_get_post_type_tracking_args( $post_type );
4060
+
4061
+ // Bail if the activity type does not exist
4062
+ if ( empty( $activity_post_object->comments_tracking->action_id ) ) {
4063
+ return false;
4064
+
4065
+ // Set the $activity_comment_object
4066
+ } else {
4067
+ $activity_comment_object = $activity_post_object->comments_tracking;
4068
+ }
4069
+
4070
+ // Init an empty activity ID
4071
+ $activity_id = 0;
4072
+
4073
+ /**
4074
+ * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
4075
+ *
4076
+ * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
4077
+ * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
4078
+ * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
4079
+ * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
4080
+ * Otherwise, record the comment into the activity stream.
4081
+ */
4082
+
4083
+ // This clause handles delete/hold.
4084
+ if ( in_array( $new_status, array( 'delete', 'hold' ) ) ) {
4085
+ return bp_activity_post_type_remove_comment( $comment->comment_ID, $activity_post_object );
4086
+
4087
+ // These clauses handle trash, spam, and un-spams.
4088
+ } elseif ( in_array( $new_status, array( 'trash', 'spam', 'unapproved' ) ) ) {
4089
+ $action = 'spam_activity';
4090
+ } elseif ( 'approved' == $new_status ) {
4091
+ $action = 'ham_activity';
4092
+ }
4093
+
4094
+ // Get the activity
4095
+ if ( bp_disable_blogforum_comments() ) {
4096
+ $activity_id = bp_activity_get_activity_id( array(
4097
+ 'component' => $activity_comment_object->component_id,
4098
+ 'item_id' => get_current_blog_id(),
4099
+ 'secondary_item_id' => $comment->comment_ID,
4100
+ 'type' => $activity_comment_object->action_id,
4101
+ ) );
4102
+ } else {
4103
+ $activity_id = get_comment_meta( $comment->comment_ID, 'bp_activity_comment_id', true );
4104
+ }
4105
+
4106
+ /**
4107
+ * Leave a chance to plugins to manage activity comments differently.
4108
+ *
4109
+ * @since 2.5.0
4110
+ *
4111
+ * @param bool $value True to override BuddyPress management.
4112
+ * @param string $post_type The post type name.
4113
+ * @param int $activity_id The post type activity (0 if not found).
4114
+ * @param string $new_status The new status of the post type comment.
4115
+ * @param string $old_status The old status of the post type comment.
4116
+ * @param WP_Comment $comment Comment data.
4117
+ */
4118
+ if ( true === apply_filters( 'bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment ) ) {
4119
+ return false;
4120
+ }
4121
+
4122
+ // Check activity item exists
4123
+ if ( empty( $activity_id ) ) {
4124
+ // If no activity exists, but the comment has been approved, record it into the activity table.
4125
+ if ( 'approved' == $new_status ) {
4126
+ return bp_activity_post_type_comment( $comment->comment_ID, true, $activity_post_object );
4127
+ }
4128
+
4129
+ return;
4130
+ }
4131
+
4132
+ // Create an activity object
4133
+ $activity = new BP_Activity_Activity( $activity_id );
4134
+ if ( empty( $activity->component ) ) {
4135
+ return;
4136
+ }
4137
+
4138
+ // Spam/ham the activity if it's not already in that state
4139
+ if ( 'spam_activity' === $action && ! $activity->is_spam ) {
4140
+ bp_activity_mark_as_spam( $activity );
4141
+ } elseif ( 'ham_activity' == $action) {
4142
+ bp_activity_mark_as_ham( $activity );
4143
+ }
4144
+
4145
+ // Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
4146
+ $post_type_comment_action = $activity_comment_object->action_id;
4147
+ $comment_akismet_history = function ( $activity_types ) use ( $post_type_comment_action ) {
4148
+ $activity_types[] = $post_type_comment_action;
4149
+
4150
+ return $activity_types;
4151
+ };
4152
+ add_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
4153
+
4154
+ // Make sure the activity change won't edit the comment if sync is on
4155
+ remove_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
4156
+
4157
+ // Save the updated activity
4158
+ $activity->save();
4159
+
4160
+ // Restore the action
4161
+ add_action( 'bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20 );
4162
+
4163
+ // Remove the "new_blog_comment" activity type whitelist so we don't break anything
4164
+ remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history );
4165
+ }
4166
+ add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 );
bp-activity/bp-activity-notifications.php CHANGED
@@ -55,7 +55,7 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
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;
@@ -70,8 +70,8 @@ function bp_activity_format_notifications( $action, $item_id, $secondary_item_id
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
  }
@@ -226,9 +226,10 @@ function bp_activity_remove_screen_notifications( $user_id = 0 ) {
226
  add_action( 'bp_activity_clear_new_mentions', 'bp_activity_remove_screen_notifications', 10, 1 );
227
 
228
  /**
229
- * Mark at-mention notification as read when user visits the activity with the mention.
230
  *
231
  * @since 2.0.0
 
232
  *
233
  * @param BP_Activity_Activity $activity Activity object.
234
  */
@@ -239,6 +240,29 @@ function bp_activity_remove_screen_notifications_single_activity_permalink( $act
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
 
@@ -289,7 +313,7 @@ add_action( 'bp_activity_deleted_activities', 'bp_activity_at_mention_delete_not
289
  /**
290
  * Add a notification for post comments to the post author or post commenter.
291
  *
292
- * Requires "activity stream commenting on blog and forum posts" to be enabled.
293
  *
294
  * @since 2.6.0
295
  *
@@ -339,3 +363,75 @@ function bp_activity_add_notification_for_synced_blog_comment( $activity_id, $po
339
  }
340
  }
341
  add_action( 'bp_blogs_comment_sync_activity_comment', 'bp_activity_add_notification_for_synced_blog_comment', 10, 4 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  $text = sprintf( __( 'You have %1$d new replies', 'buddypress' ), (int) $total_items );
56
  $amount = 'multiple';
57
  } else {
58
+ $link = add_query_arg( 'rid', (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;
70
  $text = sprintf( __( 'You have %1$d new comment replies', 'buddypress' ), (int) $total_items );
71
  $amount = 'multiple';
72
  } else {
73
+ $link = add_query_arg( 'crid', (int) $id, bp_activity_get_permalink( $activity_id ) );
74
+ $text = sprintf( __( '%1$s replied to one of your activity comments', 'buddypress' ), $user_fullname );
75
  }
76
  break;
77
  }
226
  add_action( 'bp_activity_clear_new_mentions', 'bp_activity_remove_screen_notifications', 10, 1 );
227
 
228
  /**
229
+ * Mark notifications as read when a user visits an activity permalink.
230
  *
231
  * @since 2.0.0
232
+ * @since 3.2.0 Marks replies to parent update and replies to an activity comment as read.
233
  *
234
  * @param BP_Activity_Activity $activity Activity object.
235
  */
240
 
241
  // Mark as read any notifications for the current user related to this activity item.
242
  bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), $activity->id, buddypress()->activity->id, 'new_at_mention' );
243
+
244
+ $comment_id = 0;
245
+ // For replies to a parent update.
246
+ if ( ! empty( $_GET['rid'] ) ) {
247
+ $comment_id = (int) $_GET['rid'];
248
+
249
+ // For replies to an activity comment.
250
+ } elseif ( ! empty( $_GET['crid'] ) ) {
251
+ $comment_id = (int) $_GET['crid'];
252
+ }
253
+
254
+ // Mark individual activity reply notification as read.
255
+ if ( ! empty( $comment_id ) ) {
256
+ BP_Notifications_Notification::update(
257
+ array(
258
+ 'is_new' => false
259
+ ),
260
+ array(
261
+ 'user_id' => bp_loggedin_user_id(),
262
+ 'id' => $comment_id
263
+ )
264
+ );
265
+ }
266
  }
267
  add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_screen_notifications_single_activity_permalink' );
268
 
313
  /**
314
  * Add a notification for post comments to the post author or post commenter.
315
  *
316
+ * Requires "activity stream commenting on posts and comments" to be enabled.
317
  *
318
  * @since 2.6.0
319
  *
363
  }
364
  }
365
  add_action( 'bp_blogs_comment_sync_activity_comment', 'bp_activity_add_notification_for_synced_blog_comment', 10, 4 );
366
+
367
+ /**
368
+ * Add activity notifications settings to the notifications settings page.
369
+ *
370
+ * @since 1.2.0
371
+ */
372
+ function bp_activity_screen_notification_settings() {
373
+ if ( bp_activity_do_mentions() ) {
374
+ if ( ! $mention = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_mention', true ) ) {
375
+ $mention = 'yes';
376
+ }
377
+ }
378
+
379
+ if ( ! $reply = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_reply', true ) ) {
380
+ $reply = 'yes';
381
+ }
382
+
383
+ ?>
384
+
385
+ <table class="notification-settings" id="activity-notification-settings">
386
+ <thead>
387
+ <tr>
388
+ <th class="icon">&nbsp;</th>
389
+ <th class="title"><?php _e( 'Activity', 'buddypress' ) ?></th>
390
+ <th class="yes"><?php _e( 'Yes', 'buddypress' ) ?></th>
391
+ <th class="no"><?php _e( 'No', 'buddypress' )?></th>
392
+ </tr>
393
+ </thead>
394
+
395
+ <tbody>
396
+ <?php if ( bp_activity_do_mentions() ) : ?>
397
+ <tr id="activity-notification-settings-mentions">
398
+ <td>&nbsp;</td>
399
+ <td><?php printf( __( 'A member mentions you in an update using "@%s"', 'buddypress' ), bp_core_get_username( bp_displayed_user_id() ) ) ?></td>
400
+ <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
401
+ /* translators: accessibility text */
402
+ _e( 'Yes, send email', 'buddypress' );
403
+ ?></label></td>
404
+ <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
405
+ /* translators: accessibility text */
406
+ _e( 'No, do not send email', 'buddypress' );
407
+ ?></label></td>
408
+ </tr>
409
+ <?php endif; ?>
410
+
411
+ <tr id="activity-notification-settings-replies">
412
+ <td>&nbsp;</td>
413
+ <td><?php _e( "A member replies to an update or comment you've posted", 'buddypress' ) ?></td>
414
+ <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
415
+ /* translators: accessibility text */
416
+ _e( 'Yes, send email', 'buddypress' );
417
+ ?></label></td>
418
+ <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
419
+ /* translators: accessibility text */
420
+ _e( 'No, do not send email', 'buddypress' );
421
+ ?></label></td>
422
+ </tr>
423
+
424
+ <?php
425
+
426
+ /**
427
+ * Fires inside the closing </tbody> tag for activity screen notification settings.
428
+ *
429
+ * @since 1.2.0
430
+ */
431
+ do_action( 'bp_activity_screen_notification_settings' ) ?>
432
+ </tbody>
433
+ </table>
434
+
435
+ <?php
436
+ }
437
+ add_action( 'bp_notification_settings', 'bp_activity_screen_notification_settings', 1 );
bp-activity/bp-activity-screens.php DELETED
@@ -1,379 +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
- /**
18
- * Load the Activity directory.
19
- *
20
- * @since 1.5.0
21
- *
22
- */
23
- function bp_activity_screen_index() {
24
- if ( bp_is_activity_directory() ) {
25
- bp_update_is_directory( true, 'activity' );
26
-
27
- /**
28
- * Fires right before the loading of the Activity directory screen template file.
29
- *
30
- * @since 1.5.0
31
- */
32
- do_action( 'bp_activity_screen_index' );
33
-
34
- /**
35
- * Filters the template to load for the Activity directory screen.
36
- *
37
- * @since 1.5.0
38
- *
39
- * @param string $template Path to the activity template to load.
40
- */
41
- bp_core_load_template( apply_filters( 'bp_activity_screen_index', 'activity/index' ) );
42
- }
43
- }
44
- add_action( 'bp_screens', 'bp_activity_screen_index' );
45
-
46
- /**
47
- * Load the 'My Activity' page.
48
- *
49
- * @since 1.0.0
50
- *
51
- */
52
- function bp_activity_screen_my_activity() {
53
-
54
- /**
55
- * Fires right before the loading of the "My Activity" screen template file.
56
- *
57
- * @since 1.0.0
58
- */
59
- do_action( 'bp_activity_screen_my_activity' );
60
-
61
- /**
62
- * Filters the template to load for the "My Activity" screen.
63
- *
64
- * @since 1.0.0
65
- *
66
- * @param string $template Path to the activity template to load.
67
- */
68
- bp_core_load_template( apply_filters( 'bp_activity_template_my_activity', 'members/single/home' ) );
69
- }
70
-
71
- /**
72
- * Load the 'My Friends' activity page.
73
- *
74
- * @since 1.0.0
75
- *
76
- */
77
- function bp_activity_screen_friends() {
78
- if ( !bp_is_active( 'friends' ) )
79
- return false;
80
-
81
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
82
-
83
- /**
84
- * Fires right before the loading of the "My Friends" screen template file.
85
- *
86
- * @since 1.2.0
87
- */
88
- do_action( 'bp_activity_screen_friends' );
89
-
90
- /**
91
- * Filters the template to load for the "My Friends" screen.
92
- *
93
- * @since 1.0.0
94
- *
95
- * @param string $template Path to the activity template to load.
96
- */
97
- bp_core_load_template( apply_filters( 'bp_activity_template_friends_activity', 'members/single/home' ) );
98
- }
99
-
100
- /**
101
- * Load the 'My Groups' activity page.
102
- *
103
- * @since 1.2.0
104
- *
105
- */
106
- function bp_activity_screen_groups() {
107
- if ( !bp_is_active( 'groups' ) )
108
- return false;
109
-
110
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
111
-
112
- /**
113
- * Fires right before the loading of the "My Groups" screen template file.
114
- *
115
- * @since 1.2.0
116
- */
117
- do_action( 'bp_activity_screen_groups' );
118
-
119
- /**
120
- * Filters the template to load for the "My Groups" screen.
121
- *
122
- * @since 1.2.0
123
- *
124
- * @param string $template Path to the activity template to load.
125
- */
126
- bp_core_load_template( apply_filters( 'bp_activity_template_groups_activity', 'members/single/home' ) );
127
- }
128
-
129
- /**
130
- * Load the 'Favorites' activity page.
131
- *
132
- * @since 1.2.0
133
- *
134
- */
135
- function bp_activity_screen_favorites() {
136
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
137
-
138
- /**
139
- * Fires right before the loading of the "Favorites" screen template file.
140
- *
141
- * @since 1.2.0
142
- */
143
- do_action( 'bp_activity_screen_favorites' );
144
-
145
- /**
146
- * Filters the template to load for the "Favorites" screen.
147
- *
148
- * @since 1.2.0
149
- *
150
- * @param string $template Path to the activity template to load.
151
- */
152
- bp_core_load_template( apply_filters( 'bp_activity_template_favorite_activity', 'members/single/home' ) );
153
- }
154
-
155
- /**
156
- * Load the 'Mentions' activity page.
157
- *
158
- * @since 1.2.0
159
- *
160
- */
161
- function bp_activity_screen_mentions() {
162
- bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
163
-
164
- /**
165
- * Fires right before the loading of the "Mentions" screen template file.
166
- *
167
- * @since 1.2.0
168
- */
169
- do_action( 'bp_activity_screen_mentions' );
170
-
171
- /**
172
- * Filters the template to load for the "Mentions" screen.
173
- *
174
- * @since 1.2.0
175
- *
176
- * @param string $template Path to the activity template to load.
177
- */
178
- bp_core_load_template( apply_filters( 'bp_activity_template_mention_activity', 'members/single/home' ) );
179
- }
180
-
181
- /**
182
- * Reset the logged-in user's new mentions data when he visits his mentions screen.
183
- *
184
- * @since 1.5.0
185
- *
186
- */
187
- function bp_activity_reset_my_new_mentions() {
188
- if ( bp_is_my_profile() )
189
- bp_activity_clear_new_mentions( bp_loggedin_user_id() );
190
- }
191
- add_action( 'bp_activity_screen_mentions', 'bp_activity_reset_my_new_mentions' );
192
-
193
- /**
194
- * Load the page for a single activity item.
195
- *
196
- * @since 1.2.0
197
- *
198
- */
199
- function bp_activity_screen_single_activity_permalink() {
200
- $bp = buddypress();
201
-
202
- // No displayed user or not viewing activity component.
203
- if ( !bp_is_activity_component() )
204
- return false;
205
-
206
- if ( ! bp_current_action() || !is_numeric( bp_current_action() ) )
207
- return false;
208
-
209
- // Get the activity details.
210
- $activity = bp_activity_get_specific( array( 'activity_ids' => bp_current_action(), 'show_hidden' => true, 'spam' => 'ham_only', ) );
211
-
212
- // 404 if activity does not exist
213
- if ( empty( $activity['activities'][0] ) || bp_action_variables() ) {
214
- bp_do_404();
215
- return;
216
-
217
- } else {
218
- $activity = $activity['activities'][0];
219
- }
220
-
221
- // Default access is true.
222
- $has_access = true;
223
-
224
- // If activity is from a group, do an extra cap check.
225
- if ( isset( $bp->groups->id ) && $activity->component == $bp->groups->id ) {
226
-
227
- // Activity is from a group, but groups is currently disabled.
228
- if ( !bp_is_active( 'groups') ) {
229
- bp_do_404();
230
- return;
231
- }
232
-
233
- // Check to see if the group is not public, if so, check the
234
- // user has access to see this activity.
235
- if ( $group = groups_get_group( $activity->item_id ) ) {
236
-
237
- // Group is not public.
238
- if ( 'public' != $group->status ) {
239
-
240
- // User is not a member of group.
241
- if ( !groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
242
- $has_access = false;
243
- }
244
- }
245
- }
246
- }
247
-
248
- // If activity author does not match displayed user, block access.
249
- if ( true === $has_access && bp_displayed_user_id() !== $activity->user_id ) {
250
- $has_access = false;
251
- }
252
-
253
- /**
254
- * Filters the access permission for a single activity view.
255
- *
256
- * @since 1.2.0
257
- *
258
- * @param array $access Array holding the current $has_access value and current activity item instance.
259
- */
260
- $has_access = apply_filters_ref_array( 'bp_activity_permalink_access', array( $has_access, &$activity ) );
261
-
262
- /**
263
- * Fires before the loading of a single activity template file.
264
- *
265
- * @since 1.2.0
266
- *
267
- * @param BP_Activity_Activity $activity Object representing the current activity item being displayed.
268
- * @param bool $has_access Whether or not the current user has access to view activity.
269
- */
270
- do_action( 'bp_activity_screen_single_activity_permalink', $activity, $has_access );
271
-
272
- // Access is specifically disallowed.
273
- if ( false === $has_access ) {
274
-
275
- // User feedback.
276
- bp_core_add_message( __( 'You do not have access to this activity.', 'buddypress' ), 'error' );
277
-
278
- // Redirect based on logged in status.
279
- if ( is_user_logged_in() ) {
280
- $url = bp_loggedin_user_domain();
281
-
282
- } else {
283
- $url = sprintf(
284
- site_url( 'wp-login.php?redirect_to=%s' ),
285
- urlencode( esc_url_raw( bp_activity_get_permalink( bp_current_action() ) ) )
286
- );
287
- }
288
-
289
- bp_core_redirect( $url );
290
- }
291
-
292
- /**
293
- * Filters the template to load for a single activity screen.
294
- *
295
- * @since 1.0.0
296
- *
297
- * @param string $template Path to the activity template to load.
298
- */
299
- bp_core_load_template( apply_filters( 'bp_activity_template_profile_activity_permalink', 'members/single/activity/permalink' ) );
300
- }
301
- add_action( 'bp_screens', 'bp_activity_screen_single_activity_permalink' );
302
-
303
- /**
304
- * Add activity notifications settings to the notifications settings page.
305
- *
306
- * @since 1.2.0
307
- *
308
- */
309
- function bp_activity_screen_notification_settings() {
310
-
311
- if ( bp_activity_do_mentions() ) {
312
- if ( ! $mention = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_mention', true ) ) {
313
- $mention = 'yes';
314
- }
315
- }
316
-
317
- if ( ! $reply = bp_get_user_meta( bp_displayed_user_id(), 'notification_activity_new_reply', true ) ) {
318
- $reply = 'yes';
319
- }
320
-
321
- ?>
322
-
323
- <table class="notification-settings" id="activity-notification-settings">
324
- <thead>
325
- <tr>
326
- <th class="icon">&nbsp;</th>
327
- <th class="title"><?php _e( 'Activity', 'buddypress' ) ?></th>
328
- <th class="yes"><?php _e( 'Yes', 'buddypress' ) ?></th>
329
- <th class="no"><?php _e( 'No', 'buddypress' )?></th>
330
- </tr>
331
- </thead>
332
-
333
- <tbody>
334
- <?php if ( bp_activity_do_mentions() ) : ?>
335
- <tr id="activity-notification-settings-mentions">
336
- <td>&nbsp;</td>
337
- <td><?php printf( __( 'A member mentions you in an update using "@%s"', 'buddypress' ), bp_core_get_username( bp_displayed_user_id() ) ) ?></td>
338
- <td class="yes"><input type="radio" name="notifications[notification_activity_new_mention]" id="notification-activity-new-mention-yes" value="yes" <?php checked( $mention, 'yes', true ) ?>/><label for="notification-activity-new-mention-yes" class="bp-screen-reader-text"><?php
339
- /* translators: accessibility text */
340
- _e( 'Yes, send email', 'buddypress' );
341
- ?></label></td>
342
- <td class="no"><input type="radio" name="notifications[notification_activity_new_mention]" id="notification-activity-new-mention-no" value="no" <?php checked( $mention, 'no', true ) ?>/><label for="notification-activity-new-mention-no" class="bp-screen-reader-text"><?php
343
- /* translators: accessibility text */
344
- _e( 'No, do not send email', 'buddypress' );
345
- ?></label></td>
346
- </tr>
347
- <?php endif; ?>
348
-
349
- <tr id="activity-notification-settings-replies">
350
- <td>&nbsp;</td>
351
- <td><?php _e( "A member replies to an update or comment you've posted", 'buddypress' ) ?></td>
352
- <td class="yes"><input type="radio" name="notifications[notification_activity_new_reply]" id="notification-activity-new-reply-yes" value="yes" <?php checked( $reply, 'yes', true ) ?>/><label for="notification-activity-new-reply-yes" class="bp-screen-reader-text"><?php
353
- /* translators: accessibility text */
354
- _e( 'Yes, send email', 'buddypress' );
355
- ?></label></td>
356
- <td class="no"><input type="radio" name="notifications[notification_activity_new_reply]" id="notification-activity-new-reply-no" value="no" <?php checked( $reply, 'no', true ) ?>/><label for="notification-activity-new-reply-no" class="bp-screen-reader-text"><?php
357
- /* translators: accessibility text */
358
- _e( 'No, do not send email', 'buddypress' );
359
- ?></label></td>
360
- </tr>
361
-
362
- <?php
363
-
364
- /**
365
- * Fires inside the closing </tbody> tag for activity screen notification settings.
366
- *
367
- * @since 1.2.0
368
- */
369
- do_action( 'bp_activity_screen_notification_settings' ) ?>
370
- </tbody>
371
- </table>
372
-
373
- <?php
374
- }
375
- add_action( 'bp_notification_settings', 'bp_activity_screen_notification_settings', 1 );
376
-
377
- /** Theme Compatibility *******************************************************/
378
-
379
- new BP_Activity_Theme_Compat();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-activity/bp-activity-template.php CHANGED
@@ -266,8 +266,8 @@ function bp_has_activities( $args = '' ) {
266
  // Filtering
267
  'user_id' => $user_id, // user_id to filter on.
268
  'object' => $object, // Object to filter on e.g. groups, profile, status, friends.
269
- 'action' => false, // Action to filter on e.g. activity_update, new_forum_post, profile_updated.
270
- 'primary_id' => $primary_id, // Object ID to filter on e.g. a group_id or forum_id or blog_id etc.
271
  'secondary_id' => false, // Secondary object ID to filter on e.g. a post_id.
272
  'offset' => false, // Return only items >= this ID.
273
  'since' => false, // Return only items recorded since this Y-m-d H:i:s date.
@@ -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
  /**
@@ -2944,7 +2946,7 @@ function bp_activity_can_comment_reply( $comment = false ) {
2944
  * @since 1.5.0
2945
  *
2946
  * @param bool $can_comment Status on if activity reply can be commented on.
2947
- * @param string $comment Current comment being checked on.
2948
  */
2949
  return (bool) apply_filters( 'bp_activity_can_comment_reply', $can_comment, $comment );
2950
  }
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.
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
  /**
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
  }
bp-activity/classes/class-bp-activity-activity.php CHANGED
@@ -456,6 +456,21 @@ class BP_Activity_Activity {
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
  // Sorting.
@@ -598,12 +613,12 @@ class BP_Activity_Activity {
598
  $from_sql = " FROM {$bp->activity->table_name} a LEFT JOIN {$wpdb->users} u ON a.user_id = u.ID";
599
 
600
  if ( ! empty( $page ) && ! empty( $per_page ) ) {
601
- $pag_sql = $wpdb->prepare( "LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page );
602
 
603
  /** This filter is documented in bp-activity/bp-activity-classes.php */
604
- $activities = $wpdb->get_results( apply_filters( 'bp_activity_get_user_join_filter', "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}, a.id {$sort} {$pag_sql}", $select_sql, $from_sql, $where_sql, $sort, $pag_sql ) );
605
  } else {
606
- $pag_sql = '';
607
 
608
  /**
609
  * Filters the legacy MySQL query statement so plugins can alter before results are fetched.
@@ -616,9 +631,21 @@ class BP_Activity_Activity {
616
  * @param string $where_sql Final WHERE MySQL statement portion for legacy query.
617
  * @param string $sort Final sort direction for legacy query.
618
  */
619
- $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 ) );
620
  }
621
 
 
 
 
 
 
 
 
 
 
 
 
 
622
  // Integer casting for legacy activity query.
623
  foreach ( (array) $activities as $i => $ac ) {
624
  $activities[ $i ]->id = (int) $ac->id;
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.
613
  $from_sql = " FROM {$bp->activity->table_name} a LEFT JOIN {$wpdb->users} u ON a.user_id = u.ID";
614
 
615
  if ( ! empty( $page ) && ! empty( $per_page ) ) {
616
+ $pag_sql = $wpdb->prepare( "LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page );
617
 
618
  /** This filter is documented in bp-activity/bp-activity-classes.php */
619
+ $activity_sql = apply_filters( 'bp_activity_get_user_join_filter', "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}, a.id {$sort} {$pag_sql}", $select_sql, $from_sql, $where_sql, $sort, $pag_sql );
620
  } else {
621
+ $pag_sql = '';
622
 
623
  /**
624
  * Filters the legacy MySQL query statement so plugins can alter before results are fetched.
631
  * @param string $where_sql Final WHERE MySQL statement portion for legacy query.
632
  * @param string $sort Final sort direction for legacy query.
633
  */
634
+ $activity_sql = 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
+ /*
638
+ * Queries that include 'last_activity' are cached separately,
639
+ * since they are generally much less long-lived.
640
+ */
641
+ if ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $activity_sql ) ) {
642
+ $cache_group = 'bp_activity';
643
+ } else {
644
+ $cache_group = 'bp_activity_with_last_activity';
645
+ }
646
+
647
+ $activities = $wpdb->get_results( $activity_sql );
648
+
649
  // Integer casting for legacy activity query.
650
  foreach ( (array) $activities as $i => $ac ) {
651
  $activities[ $i ]->id = (int) $ac->id;
bp-activity/classes/class-bp-activity-component.php CHANGED
@@ -51,8 +51,6 @@ 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',
@@ -73,8 +71,8 @@ class BP_Activity_Component extends BP_Component {
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,62 @@ class BP_Activity_Component extends BP_Component {
85
  parent::includes( $includes );
86
  }
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  /**
89
  * Set up component global variables.
90
  *
51
  // Files to include.
52
  $includes = array(
53
  'cssjs',
 
 
54
  'filters',
55
  'adminbar',
56
  'template',
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
+
142
  /**
143
  * Set up component global variables.
144
  *
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.
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.
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
@@ -191,7 +191,7 @@ class BP_Activity_Template {
191
  $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page'] );
192
  $this->pag_num = bp_sanitize_pagination_arg( 'num', $r['per_page'] );
193
 
194
- // Check if blog/forum replies are disabled.
195
  $this->disable_blogforum_replies = (bool) bp_core_get_root_option( 'bp-disable-blogforum-comments' );
196
 
197
  // Get an array of the logged in user's favorite activities.
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.
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/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(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,hide_without_suffix:!0,insert_tpl:"</>${atwho-data-value}</>",limit:10,start_with_space:!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:{remote_filter: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:"@",search_key:"search",tpl:'<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);
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-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
@@ -1148,6 +1148,7 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1148
 
1149
  $allow_comments = bp_blogs_comments_open( $activity );
1150
  $thread_depth = bp_blogs_get_blogmeta( $activity->item_id, 'thread_comments_depth' );
 
1151
 
1152
  // Initialize a local object so we won't have to query this again in the
1153
  // comment loop.
@@ -1157,16 +1158,23 @@ function bp_blogs_setup_activity_loop_globals( $activity ) {
1157
  if ( empty( buddypress()->blogs->thread_depth ) ) {
1158
  buddypress()->blogs->thread_depth = array();
1159
  }
 
 
 
1160
 
1161
- // Cache comment settings in the buddypress() singleton to reference later in
1162
- // the activity comment loop
1163
- // @see bp_blogs_disable_activity_replies()
1164
- //
1165
- // thread_depth is keyed by activity ID instead of blog ID because when we're
1166
- // in a comment loop, we don't have access to the blog ID...
1167
- // should probably object cache these values instead...
1168
- buddypress()->blogs->allow_comments[ $activity->id ] = $allow_comments;
1169
- buddypress()->blogs->thread_depth[ $activity->id ] = $thread_depth;
 
 
 
 
1170
  }
1171
 
1172
  /**
@@ -1231,6 +1239,11 @@ function bp_blogs_disable_activity_commenting( $retval ) {
1231
  if ( empty( buddypress()->blogs->allow_comments[ bp_get_activity_id() ] ) ) {
1232
  $retval = false;
1233
  }
 
 
 
 
 
1234
  // The activity type does not support comments or replies
1235
  } else {
1236
  $retval = false;
@@ -1314,6 +1327,11 @@ function bp_blogs_can_comment_reply( $retval, $comment ) {
1314
  }
1315
  }
1316
 
 
 
 
 
 
1317
  return $retval;
1318
  }
1319
  add_filter( 'bp_activity_can_comment_reply', 'bp_blogs_can_comment_reply', 10, 2 );
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;
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-functions.php CHANGED
@@ -100,7 +100,7 @@ function bp_blogs_record_existing_blogs( $args = array() ) {
100
 
101
  // Query for all sites in network.
102
  $r = bp_parse_args( $args, array(
103
- 'offset' => false === bp_get_option( '_bp_record_blogs_offset' ) ? 0 : bp_get_option( '_bp_record_blogs_offset' ),
104
  'limit' => 50,
105
  'blog_ids' => array(),
106
  'site_id' => $wpdb->siteid
@@ -362,6 +362,7 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
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
 
366
  $thread_depth = get_blog_option( $blog_id, 'thread_comments' );
367
  if ( ! empty( $thread_depth ) ) {
@@ -384,6 +385,7 @@ function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
384
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_for_old_posts', $close_old_posts );
385
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_days_old', $close_days_old );
386
  bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'thread_comments_depth', $thread_depth );
 
387
 
388
  $is_private = !empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ? false : true;
389
 
@@ -525,6 +527,19 @@ function bp_blogs_update_option_thread_comments_depth( $oldvalue, $newvalue ) {
525
  }
526
  add_action( 'update_option_thread_comments_depth', 'bp_blogs_update_option_thread_comments_depth', 10, 2 );
527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  /**
529
  * Syncs site icon URLs to blogmeta.
530
  *
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
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
 
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
  *
bp-blogs/bp-blogs-screens.php DELETED
@@ -1,73 +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
- /**
14
- * Load the "My Blogs" screen.
15
- */
16
- function bp_blogs_screen_my_blogs() {
17
- if ( !is_multisite() )
18
- return false;
19
-
20
- /**
21
- * Fires right before the loading of the My Blogs screen template file.
22
- *
23
- * @since 1.0.0
24
- */
25
- do_action( 'bp_blogs_screen_my_blogs' );
26
-
27
- bp_core_load_template( apply_filters( 'bp_blogs_template_my_blogs', 'members/single/home' ) );
28
- }
29
-
30
- /**
31
- * Load the "Create a Blog" screen.
32
- */
33
- function bp_blogs_screen_create_a_blog() {
34
-
35
- if ( !is_multisite() || !bp_is_blogs_component() || !bp_is_current_action( 'create' ) )
36
- return false;
37
-
38
- if ( !is_user_logged_in() || !bp_blog_signup_enabled() )
39
- return false;
40
-
41
- /**
42
- * Fires right before the loading of the Create A Blog screen template file.
43
- *
44
- * @since 1.0.0
45
- */
46
- do_action( 'bp_blogs_screen_create_a_blog' );
47
-
48
- bp_core_load_template( apply_filters( 'bp_blogs_template_create_a_blog', 'blogs/create' ) );
49
- }
50
- add_action( 'bp_screens', 'bp_blogs_screen_create_a_blog', 3 );
51
-
52
- /**
53
- * Load the top-level Blogs directory.
54
- */
55
- function bp_blogs_screen_index() {
56
- if ( bp_is_blogs_directory() ) {
57
- bp_update_is_directory( true, 'blogs' );
58
-
59
- /**
60
- * Fires right before the loading of the top-level Blogs screen template file.
61
- *
62
- * @since 1.0.0
63
- */
64
- do_action( 'bp_blogs_screen_index' );
65
-
66
- bp_core_load_template( apply_filters( 'bp_blogs_screen_index', 'blogs/index' ) );
67
- }
68
- }
69
- add_action( 'bp_screens', 'bp_blogs_screen_index', 2 );
70
-
71
- /** Theme Compatibility *******************************************************/
72
-
73
- new BP_Blogs_Theme_Compat();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-blogs/classes/class-bp-blogs-component.php CHANGED
@@ -125,8 +125,6 @@ class BP_Blogs_Component extends BP_Component {
125
  // Files to include.
126
  $includes = array(
127
  'cache',
128
- 'actions',
129
- 'screens',
130
  'template',
131
  'filters',
132
  'functions',
@@ -144,6 +142,46 @@ class BP_Blogs_Component extends BP_Component {
144
  parent::includes( $includes );
145
  }
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  /**
148
  * Set up component navigation for bp-blogs.
149
  *
125
  // Files to include.
126
  $includes = array(
127
  'cache',
 
 
128
  'template',
129
  'filters',
130
  'functions',
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-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>
@@ -200,18 +196,14 @@ function bp_core_admin_components_options() {
200
  /* translators: accessibility text */
201
  printf( __( 'Select %s', 'buddypress' ), esc_html( $labels['title'] ) ); ?></label>
202
 
203
- <?php else : ?>
204
-
205
- <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
206
- /* translators: accessibility text */
207
- printf( __( '%s is a required component', 'buddypress' ), esc_html( $labels['title'] ) ); ?></label>
208
-
209
  <?php endif; ?>
210
 
211
  </th>
212
  <td class="plugin-title column-primary">
213
- <span aria-hidden="true"></span>
214
- <strong><?php echo esc_html( $labels['title'] ); ?></strong>
 
 
215
  </td>
216
 
217
  <td class="column-description desc">
@@ -236,9 +228,10 @@ function bp_core_admin_components_options() {
236
 
237
  <tfoot>
238
  <tr>
239
- <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
 
240
  /* translators: accessibility text */
241
- _e( 'Bulk selection is disabled', 'buddypress' );
242
  ?></label></td>
243
  <th class="manage-column column-title column-primary"><?php _e( 'Component', 'buddypress' ); ?></th>
244
  <th class="manage-column column-description"><?php _e( 'Description', 'buddypress' ); ?></th>
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>
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>
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(
@@ -366,14 +357,14 @@ function bp_do_activation_redirect() {
366
  return;
367
  }
368
 
369
- $query_args = array( 'page' => 'bp-about' );
370
  if ( get_transient( '_bp_is_new_install' ) ) {
371
  $query_args['is_new_install'] = '1';
372
  delete_transient( '_bp_is_new_install' );
373
  }
374
 
375
- // Redirect to BuddyPress about page.
376
- wp_safe_redirect( add_query_arg( $query_args, bp_get_admin_url( 'index.php' ) ) );
377
  }
378
 
379
  /** UI/Styling ****************************************************************/
@@ -430,29 +421,20 @@ function bp_core_get_admin_tabs( $active_tab = '' ) {
430
  'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-components' ), 'admin.php' ) ),
431
  'name' => __( 'Components', 'buddypress' )
432
  ),
 
 
 
 
433
  '1' => array(
434
  'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) ),
435
  'name' => __( 'Pages', 'buddypress' )
436
  ),
437
- '2' => array(
438
- 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), 'admin.php' ) ),
439
- 'name' => __( 'Options', 'buddypress' )
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
  *
@@ -863,7 +845,7 @@ function bp_admin_email_maybe_add_translation_notice() {
863
 
864
  bp_core_add_admin_notice(
865
  sprintf(
866
- __( 'Are your emails in the wrong language? Go to <a href="%s">BuddyPress Tools and run the "reinstall emails"</a> tool.', 'buddypress' ),
867
  esc_url( add_query_arg( 'page', 'bp-tools', bp_get_admin_url( $admin_page ) ) )
868
  ),
869
  'updated'
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(
357
  return;
358
  }
359
 
360
+ $query_args = array();
361
  if ( get_transient( '_bp_is_new_install' ) ) {
362
  $query_args['is_new_install'] = '1';
363
  delete_transient( '_bp_is_new_install' );
364
  }
365
 
366
+ // Redirect to dashboard and trigger the Hello screen.
367
+ wp_safe_redirect( add_query_arg( $query_args, bp_get_admin_url( '?hello=buddypress' ) ) );
368
  }
369
 
370
  /** UI/Styling ****************************************************************/
421
  'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-components' ), 'admin.php' ) ),
422
  'name' => __( 'Components', 'buddypress' )
423
  ),
424
+ '2' => array(
425
+ 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), 'admin.php' ) ),
426
+ 'name' => __( 'Options', 'buddypress' )
427
+ ),
428
  '1' => array(
429
  'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) ),
430
  'name' => __( 'Pages', 'buddypress' )
431
  ),
432
+ '3' => array(
433
+ 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-credits' ), 'admin.php' ) ),
434
+ 'name' => __( 'Credits', 'buddypress' )
435
  ),
436
  );
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  /**
439
  * Filters the tab data used in our wp-admin screens.
440
  *
845
 
846
  bp_core_add_admin_notice(
847
  sprintf(
848
+ __( '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' ),
849
  esc_url( add_query_arg( 'page', 'bp-tools', bp_get_admin_url( $admin_page ) ) )
850
  ),
851
  'updated'
bp-core/admin/bp-core-admin-schema.php CHANGED
@@ -506,6 +506,12 @@ function bp_core_install_emails() {
506
 
507
  // Add these emails to the database.
508
  foreach ( $emails as $id => $email ) {
 
 
 
 
 
 
509
  $post_id = wp_insert_post( bp_parse_args( $email, $defaults, 'install_email_' . $id ) );
510
  if ( ! $post_id ) {
511
  continue;
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;
bp-core/admin/bp-core-admin-settings.php CHANGED
@@ -70,8 +70,8 @@ function bp_admin_setting_callback_theme_package_id() {
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>
@@ -104,7 +104,7 @@ function bp_admin_setting_callback_activity_akismet() {
104
  }
105
 
106
  /**
107
- * Allow activity comments on blog posts and forum posts.
108
  *
109
  * @since 1.6.0
110
  */
@@ -112,7 +112,7 @@ function bp_admin_setting_callback_blogforum_comments() {
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 blog and forum posts', 'buddypress' ); ?></label>
116
 
117
  <?php
118
  }
@@ -134,7 +134,7 @@ function bp_admin_setting_callback_heartbeat() {
134
  /**
135
  * Sanitization for bp-disable-blogforum-comments setting.
136
  *
137
- * In the UI, a checkbox asks whether you'd like to *enable* blog/forum 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
  *
@@ -216,9 +216,9 @@ function bp_admin_setting_callback_groups_section() { }
216
  function bp_admin_setting_callback_group_creation() {
217
  ?>
218
 
219
- <input id="bp_restrict_group_creation" name="bp_restrict_group_creation" type="checkbox"value="1" <?php checked( !bp_restrict_group_creation( false ) ); ?> />
220
  <label for="bp_restrict_group_creation"><?php _e( 'Enable group creation for all users', 'buddypress' ); ?></label>
221
- <p class="description"><?php _e( 'Administrators can always create groups, regardless of this setting.', 'buddypress' ); ?></p>
222
 
223
  <?php
224
  }
@@ -247,40 +247,6 @@ function bp_admin_setting_callback_group_cover_image_uploads() {
247
  <?php
248
  }
249
 
250
- /** Forums Section ************************************************************/
251
-
252
- /**
253
- * Forums settings section description for the settings page.
254
- *
255
- * @since 1.6.0
256
- */
257
- function bp_admin_setting_callback_bbpress_section() { }
258
-
259
- /**
260
- * The bb-config.php location field.
261
- *
262
- * @since 1.6.0
263
- *
264
- */
265
- function bp_admin_setting_callback_bbpress_configuration() {
266
-
267
- $config_location = bp_get_option( 'bb-config-location' );
268
- $file_exists = (bool) ( file_exists( $config_location ) || is_file( $config_location ) ); ?>
269
-
270
- <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;" />
271
-
272
- <?php if ( false === $file_exists ) : ?>
273
-
274
- <a class="button" href="<?php bp_admin_url( 'admin.php?page=bb-forums-setup&repair=1' ); ?>"><?php _e( 'Repair', 'buddypress' ) ?></a>
275
- <span class="attention"><?php _e( 'File does not exist', 'buddypress' ); ?></span>
276
-
277
- <?php endif; ?>
278
-
279
- <p class="description"><?php _e( 'Absolute path to your bbPress configuration file.', 'buddypress' ); ?></p>
280
-
281
- <?php
282
- }
283
-
284
  /** Settings Page *************************************************************/
285
 
286
  /**
70
  }
71
 
72
  if ( $options ) : ?>
73
+ <select name="_bp_theme_package_id" id="_bp_theme_package_id" aria-describedby="_bp_theme_package_description"><?php echo $options; ?></select>
74
+ <p id="_bp_theme_package_description" class="description"><?php esc_html_e( 'The selected Template Pack will serve all BuddyPress templates.', 'buddypress' ); ?></p>
75
 
76
  <?php else : ?>
77
  <p><?php esc_html_e( 'No template packages available.', 'buddypress' ); ?></p>
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
  *
216
  function bp_admin_setting_callback_group_creation() {
217
  ?>
218
 
219
+ <input id="bp_restrict_group_creation" name="bp_restrict_group_creation" type="checkbox" aria-describedby="bp_group_creation_description" value="1" <?php checked( !bp_restrict_group_creation( false ) ); ?> />
220
  <label for="bp_restrict_group_creation"><?php _e( 'Enable group creation for all users', 'buddypress' ); ?></label>
221
+ <p class="description" id="bp_group_creation_description"><?php _e( 'Administrators can always create groups, regardless of this setting.', 'buddypress' ); ?></p>
222
 
223
  <?php
224
  }
247
  <?php
248
  }
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  /** Settings Page *************************************************************/
251
 
252
  /**
bp-core/admin/css/common-rtl.css CHANGED
@@ -10,15 +10,16 @@ TABLE OF CONTENTS:
10
  --------------------------------------------------------------------------------
11
  1.0 Welcome Screen
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 User's Lists
 
 
 
22
  4.0 Emails - Edit page
23
  5.0 Tools - BuddyPress
24
  6.0 Plugins page
@@ -41,398 +42,132 @@ TABLE OF CONTENTS:
41
  content: "\f448";
42
  }
43
 
44
- .about-wrap .bp-badge {
45
- position: absolute;
46
- top: 0;
47
- left: 0;
48
- }
49
-
50
- .index_page_bp-credits code,
51
  .index_page_bp-about code {
52
  background-color: #e0e0e0;
53
  color: #636363;
54
  font-size: 1em;
55
  }
56
 
57
- @media only screen and (max-width: 500px) {
58
-
59
- .about-wrap .bp-badge {
60
- position: relative;
61
- margin: 10px auto;
62
- top: auto;
63
- left: auto;
64
- }
65
- }
66
-
67
- /*
68
- * 1.2 About Panel
69
- */
70
-
71
  /*
72
- * 1.2.1 Headline Feature
 
 
73
  */
74
- .buddypress .bp-headline-feature {
75
- margin-bottom: 2em;
76
- margin-top: 3em;
77
- padding: 2em 3em;
78
- }
79
-
80
- .buddypress .bp-headline {
81
- margin: 0 auto;
82
- width: 45em;
83
- }
84
-
85
- .buddypress .bp-headline span.dashicons {
86
- background-color: #f1f1f1;
87
- color: #d84800;
88
- clear: right;
89
- font-size: 100px;
90
- float: right;
91
- height: 100px;
92
- line-height: 100px;
93
- margin: 0 0 15px 15px;
94
- text-align: center;
95
- width: 100px;
96
- }
97
-
98
- .buddypress .bp-headline-feature .headline-title {
99
- font-size: 2.2em;
100
- font-weight: 300;
101
- line-height: 2;
102
- margin: 0 0 1em;
103
- text-align: center;
104
- }
105
-
106
- .buddypress .bp-headline-feature p {
107
- font-size: 1.15em;
108
- margin: 1.15em 0 0.6em auto;
109
  }
110
 
111
- /*
112
- * 1.2.2 Features Section
113
- */
114
- .buddypress .bp-features-section {
115
- border-bottom: 1px solid #ccc;
116
- clear: both;
117
- margin-bottom: 3em;
118
- margin-top: 2em;
119
- overflow: hidden;
120
- padding-bottom: 2em;
121
  }
122
 
123
- .buddypress .bp-features-section p {
124
- font-size: 14px;
125
  line-height: 1.5;
 
126
  }
127
 
128
- .buddypress .bp-features-section img {
129
- margin-bottom: 20px;
130
- }
131
-
132
- .buddypress .bp-features-section span.dashicons {
133
- background-color: #fff;
134
- border-radius: 50%;
135
- clear: right;
136
- color: #d84800;
137
- font-size: 50px;
138
- float: right;
139
- height: 80px;
140
- line-height: 80px;
141
- margin: 0 0 15px 15px;
142
- text-align: center;
143
- width: 80px;
144
- }
145
-
146
- .buddypress .bp-features-section .headline-title {
147
- font-size: 2em;
148
  font-weight: 300;
149
- line-height: 1.5;
150
- margin: 1em auto 2em;
151
  text-align: center;
152
  }
153
 
154
- .buddypress .bp-features-section .bp-feature-with-images {
155
- border-bottom: 1px solid #ccc;
156
- margin-bottom: 5em;
157
- padding-bottom: 2em;
158
- }
159
-
160
- .buddypress .bp-features-section .bp-feature,
161
- .buddypress .bp-features-section .bp-feature-imaged {
162
- float: right;
163
- margin-bottom: 3em;
164
- margin-left: 4.799999999%;
165
- width: 47.6%;
166
- }
167
-
168
- .buddypress .bp-features-section .bp-feature.opposite,
169
- .buddypress .bp-features-section .bp-feature-imaged.anon {
170
- margin-left: 0;
171
- }
172
-
173
- .buddypress .bp-features-section .bp-feature code {
174
- font-size: 0.95em;
175
  line-height: 1.5;
176
  }
177
 
178
- .buddypress .bp-feature:after {
179
- clear: both;
180
- content: "";
181
- margin-bottom: 2em;
182
  }
183
 
184
- .buddypress .bp-feature-imaged .feature-title {
185
- color: #23282d;
186
- font-size: 1.25em;
187
- margin-bottom: 0.6em;
188
- margin-top: 0;
189
  }
190
 
191
- .buddypress .bp-feature-imaged p {
192
- clear: right;
193
- font-size: 1.1em;
 
 
194
  }
195
 
196
- .buddypress .bp-feature-imaged img {
197
- clear: right;
 
198
  }
199
 
200
- .buddypress .bp-feature .feature-title {
201
- font-size: 1em;
202
- line-height: 1.5;
203
  margin-bottom: 0;
204
- margin-right: 110px;
205
- margin-top: 0;
206
- text-align: right;
207
  }
208
 
209
- .buddypress .bp-feature p {
210
- margin-right: 110px;
 
 
 
 
 
211
  }
212
 
213
- /*
214
- * 1.2.3 Changelog Section
215
- */
216
- .buddypress .bp-changelog-section {
217
- clear: both;
218
- margin-bottom: 3em;
219
- margin-top: 4em;
220
  padding-bottom: 0;
 
221
  }
222
 
223
- .buddypress .bp-changelog-section:after {
224
- clear: both;
225
- content: "";
226
- display: table;
227
- }
228
-
229
- .buddypress .bp-changelog-section .changelog-title {
230
- color: #23282d;
231
- font-size: 1.25em;
232
- line-height: 1.5;
233
- margin: 0 auto 1.5em;
234
- }
235
-
236
- .buddypress .bp-two-column div {
237
- float: right;
238
- margin-left: 4.799999999%;
239
- position: relative;
240
- width: 47.6%;
241
- }
242
-
243
- .buddypress .bp-three-column .bp-column {
244
  float: right;
245
- margin-left: 5%;
246
- position: relative;
247
- width: 29.95%;
 
248
  }
249
 
250
- .buddypress .bp-two-column .bp-column:nth-of-type(2n),
251
- .buddypress .bp-three-column .bp-column:nth-of-type(3n) {
252
- margin-left: 0;
253
  }
254
 
255
- .buddypress .bp-changelog {
256
- margin-bottom: 3em;
257
- }
258
-
259
- .buddypress .bp-changelog:after {
260
- clear: both;
261
- content: "";
262
- display: table;
263
- }
264
-
265
- .buddypress .bp-changelog .title {
266
- font-size: 14px;
267
- margin-bottom: 0.75em;
268
- margin-top: 0;
269
- }
270
-
271
- .buddypress .bp-changelog p {
272
- margin-bottom: 0;
273
  }
274
 
275
- .bp-changelog-url {
276
- text-align: center;
277
  }
278
 
279
- .bp-assets {
280
- clear: both;
281
- margin-bottom: 3em;
282
  }
283
 
284
- @media screen and ( max-width: 782px ) {
285
 
286
- .bp-headline-feature,
287
- .bp-features-section,
288
- .bp-changelog-section,
289
- .bp-assets {
290
- margin-right: 20px;
291
  margin-left: 20px;
 
292
  }
293
 
294
- .buddypress .bp-headline-feature {
295
- padding: 0;
296
- }
297
-
298
- .buddypress .bp-headline {
299
- margin: 0;
300
- width: 97%;
301
- }
302
-
303
- .buddypress .bp-features-section {
304
- clear: both;
305
- margin-bottom: 0;
306
- margin-top: 2em;
307
- padding-bottom: 2em;
308
- }
309
-
310
- .buddypress .bp-features-section .bp-feature-with-images {
311
- margin-bottom: 2em;
312
- }
313
-
314
- .buddypress .bp-features-section .headline-title {
315
- margin-bottom: 1em;
316
- }
317
-
318
- .buddypress .bp-changelog-section .changelog-title {
319
- font-size: 1.25em;
320
- line-height: 1.5;
321
- margin-bottom: 0.5em;
322
- margin-top: 0.5em;
323
- }
324
-
325
- .buddypress .bp-features-section .feature-title,
326
- .buddypress .bp-changelog-section .title {
327
- font-size: 1.25em;
328
- line-height: 1.25;
329
- margin-top: 0.6em;
330
- text-align: right;
331
- }
332
-
333
- .buddypress .bp-features-section .bp-feature,
334
- .buddypress .bp-features-section .bp-feature-imaged {
335
- clear: both;
336
- float: right;
337
- margin-bottom: 1em;
338
- margin-top: 1em;
339
  margin-left: 0;
340
- padding-left: 1em;
341
- width: 100%;
342
- }
343
-
344
- .buddypress .bp-features-section .bp-feature-imaged p {
345
- font-size: 1em;
346
- }
347
-
348
- .buddypress .bp-features-section .bp-feature span {
349
- margin-top: 0.33em;
350
- }
351
-
352
- .buddypress .bp-feature.opposite .feature-title,
353
- .buddypress .bp-feature.opposite p {
354
- float: none;
355
- }
356
-
357
- .buddypress .bp-changelog-section {
358
- clear: both;
359
- margin-bottom: 2em;
360
- margin-top: 2em;
361
- }
362
-
363
- .buddypress .bp-changelog {
364
- margin-bottom: 0;
365
- }
366
-
367
- .buddypress .bp-changelog-section .changelog-title {
368
- margin-bottom: 0.5em;
369
- }
370
-
371
- .buddypress .bp-changelog .title {
372
- font-size: 1em;
373
- }
374
-
375
- .buddypress .bp-changelog p {
376
- margin-bottom: 1em;
377
- }
378
-
379
- .buddypress .bp-changelog-section .two-col > div,
380
- .buddypress .bp-changelog-section .three-col .col {
381
- margin-top: 0;
382
- padding-bottom: 0.5em;
383
- width: 100%;
384
- }
385
-
386
- .buddypress .bp-three-column .bp-column {
387
- width: 100%;
388
- }
389
- }
390
-
391
- @media screen and ( max-width: 360px ) {
392
-
393
- .buddypress .bp-headline {
394
- text-align: center;
395
- }
396
-
397
- .buddypress .bp-headline span.dashicons {
398
- clear: none;
399
- font-size: 80px;
400
- float: none;
401
- height: 80px;
402
- line-height: 80px;
403
- margin: 0 auto;
404
- width: 80px;
405
- }
406
-
407
- .buddypress .bp-headline-feature .headline-title,
408
- .buddypress .bp-features-section .headline-title {
409
- font-size: 1.5em;
410
- line-height: 1.5;
411
- text-align: right;
412
- }
413
-
414
- .buddypress .bp-headline-feature .headline-title {
415
- margin: 1em 0 0;
416
- }
417
-
418
- .buddypress .bp-headline-feature p {
419
- margin: 1.15em 0 0.6em auto;
420
- text-align: right;
421
- width: auto;
422
- }
423
-
424
- .buddypress .bp-features-section .bp-feature {
425
- text-align: center;
426
- }
427
-
428
- .buddypress .bp-features-section span.dashicons {
429
- float: none;
430
- }
431
-
432
- .buddypress .bp-features-section .feature-title,
433
- .buddypress .bp-features-section p {
434
- margin-right: 0;
435
- text-align: right;
436
  }
437
  }
438
 
@@ -523,10 +258,6 @@ TABLE OF CONTENTS:
523
  content: "\f457";
524
  }
525
 
526
- .settings_page_bp-components tr.forums td.plugin-title span:before {
527
- content: "\f452";
528
- }
529
-
530
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
531
  content: "\f120";
532
  }
@@ -571,10 +302,84 @@ TABLE OF CONTENTS:
571
  content: "";
572
  }
573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
 
575
  /*------------------------------------------------------------------------------
576
- * 3.0 User's Lists
577
  *----------------------------------------------------------------------------*/
 
 
 
 
578
  body.site-users-php th#role,
579
  body.users-php th#role,
580
  body.users_page_bp-signups th#count_sent {
@@ -611,6 +416,93 @@ body.users_page_bp-signups td.count_sent {
611
  font-weight: 700;
612
  }
613
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  /*------------------------------------------------------------------------------
615
  * 4.0 Emails - Edit Page
616
  *----------------------------------------------------------------------------*/
10
  --------------------------------------------------------------------------------
11
  1.0 Welcome Screen
12
  1.1 Version Badge
13
+ 1.2 ---
14
+ 1.3 Credits Panel
 
 
15
  2.0 Dashicons
16
  2.1 Top level menus
17
  2.2 Settings - Components
18
  2.3 Tools
19
+ 2.4 Tooltips
20
+ 3.0 Users
21
+ 3.1 Users List
22
+ 3.2 Site Notices
23
  4.0 Emails - Edit page
24
  5.0 Tools - BuddyPress
25
  6.0 Plugins page
42
  content: "\f448";
43
  }
44
 
45
+ .settings_page_bp-credits code,
 
 
 
 
 
 
46
  .index_page_bp-about code {
47
  background-color: #e0e0e0;
48
  color: #636363;
49
  font-size: 1em;
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  /*
53
+ * 1.3 Credits Panel
54
+ *
55
+ * Taken from WP 4.9.5.
56
  */
57
+ .bp-about-wrap {
58
+ position: relative;
59
+ max-width: 1050px;
60
+ font-size: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
 
63
+ .bp-about-wrap img {
64
+ margin: 0;
65
+ max-width: 100%;
66
+ height: auto;
67
+ vertical-align: middle;
 
 
 
 
 
68
  }
69
 
70
+ .bp-about-wrap p {
 
71
  line-height: 1.5;
72
+ font-size: 14px;
73
  }
74
 
75
+ .bp-about-wrap h2 {
76
+ margin: 40px 0 0.6em;
77
+ font-size: 2.7em;
78
+ line-height: 1.3;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  font-weight: 300;
 
 
80
  text-align: center;
81
  }
82
 
83
+ .bp-about-wrap h3 {
84
+ margin: 1.25em 0 0.6em;
85
+ font-size: 1.4em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  line-height: 1.5;
87
  }
88
 
89
+ .bp-about-wrap code {
90
+ font-size: 14px;
91
+ font-weight: 400;
 
92
  }
93
 
94
+ .bp-about-wrap .about-description {
95
+ margin-top: 1.4em;
96
+ font-weight: 400;
97
+ line-height: 1.6;
98
+ font-size: 19px;
99
  }
100
 
101
+ .bp-about-wrap h3.wp-people-group {
102
+ margin: 2.6em 0 1.33em;
103
+ padding: 0;
104
+ font-size: 16px;
105
+ line-height: inherit;
106
  }
107
 
108
+ .bp-about-wrap .wp-people-group {
109
+ padding: 0 5px;
110
+ margin: 0 -5px 0 -15px;
111
  }
112
 
113
+ .bp-about-wrap .compact {
 
 
114
  margin-bottom: 0;
 
 
 
115
  }
116
 
117
+ .bp-about-wrap .wp-person {
118
+ display: inline-block;
119
+ vertical-align: top;
120
+ margin-left: 10px;
121
+ padding-bottom: 15px;
122
+ height: 70px;
123
+ width: 280px;
124
  }
125
 
126
+ .bp-about-wrap .compact .wp-person {
127
+ height: auto;
128
+ width: 180px;
 
 
 
 
129
  padding-bottom: 0;
130
+ margin-bottom: 0;
131
  }
132
 
133
+ .bp-about-wrap .wp-person .gravatar {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  float: right;
135
+ margin: 0 0 10px 10px;
136
+ padding: 1px;
137
+ width: 60px;
138
+ height: 60px;
139
  }
140
 
141
+ .bp-about-wrap .compact .wp-person .gravatar {
142
+ width: 30px;
143
+ height: 30px;
144
  }
145
 
146
+ .bp-about-wrap .wp-person .web {
147
+ margin: 6px 0 2px;
148
+ font-size: 16px;
149
+ font-weight: 400;
150
+ line-height: 2;
151
+ text-decoration: none;
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
 
154
+ .bp-about-wrap .wp-person .title {
155
+ display: block;
156
  }
157
 
158
+ .bp-about-wrap p.wp-credits-list a {
159
+ white-space: nowrap;
 
160
  }
161
 
162
+ @media only screen and (max-width: 500px) {
163
 
164
+ .bp-about-wrap {
 
 
 
 
165
  margin-left: 20px;
166
+ margin-right: 10px;
167
  }
168
 
169
+ .bp-about-wrap .bp-about-wrap h1 {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  margin-left: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
172
  }
173
 
258
  content: "\f457";
259
  }
260
 
 
 
 
 
261
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
262
  content: "\f120";
263
  }
302
  content: "";
303
  }
304
 
305
+ /*
306
+ * 2.4 Tooltips
307
+ */
308
+ .bp-tooltip {
309
+ position: relative;
310
+ }
311
+
312
+ .bp-tooltip:after {
313
+ background: #fff;
314
+ border: 1px solid #aaa;
315
+ border-collapse: separate;
316
+ border-radius: 1px;
317
+ box-shadow: -1px 1px 0 1px rgba(132, 132, 132, 0.3);
318
+ color: #000;
319
+ content: attr(data-bp-tooltip);
320
+ display: none;
321
+ font-family: sans-serif;
322
+ font-size: 11px;
323
+ font-weight: 400;
324
+ letter-spacing: normal;
325
+ line-height: 1.5;
326
+ margin-top: 10px;
327
+ max-width: 240px;
328
+ opacity: 0;
329
+ padding: 3px 6px;
330
+ position: absolute;
331
+ left: 50%;
332
+ text-align: center;
333
+ text-decoration: none;
334
+ text-shadow: none;
335
+ text-transform: none;
336
+ top: 100%;
337
+ -webkit-transform: translateX(-50%);
338
+ -ms-transform: translateX(-50%);
339
+ transform: translateX(-50%);
340
+ -webkit-transition: opacity 2s ease-out;
341
+ -ms-transition: opacity 2s ease-out;
342
+ transition: opacity 2s ease-out;
343
+ white-space: pre;
344
+ word-wrap: break-word;
345
+ z-index: 998;
346
+ }
347
+
348
+ .bp-hello-close .bp-tooltip:after {
349
+ left: 0;
350
+ text-align: left;
351
+ -webkit-transform: translateX(0);
352
+ -ms-transform: translateX(0);
353
+ transform: translateX(0);
354
+ }
355
+
356
+ .bp-hello-social .bp-tooltip:after {
357
+ bottom: 120%;
358
+ margin-bottom: 20px;
359
+ margin-top: 0;
360
+ top: auto;
361
+ -webkit-transform: translateX(-15%);
362
+ -ms-transform: translateX(-15%);
363
+ transform: translateX(-15%);
364
+ }
365
+
366
+ .bp-tooltip:hover:after,
367
+ .bp-tooltip:active:after,
368
+ .bp-tooltip:focus:after {
369
+ display: inline-block;
370
+ opacity: 1;
371
+ overflow: visible;
372
+ text-decoration: none;
373
+ z-index: 999;
374
+ }
375
 
376
  /*------------------------------------------------------------------------------
377
+ * 3.0 Users
378
  *----------------------------------------------------------------------------*/
379
+
380
+ /*
381
+ * 3.1 Users List
382
+ */
383
  body.site-users-php th#role,
384
  body.users-php th#role,
385
  body.users_page_bp-signups th#count_sent {
416
  font-weight: 700;
417
  }
418
 
419
+ /*
420
+ * 3.2 Site Notices
421
+ */
422
+ .bp-new-notice-panel {
423
+ background: #fff;
424
+ border: 1px solid #e5e5e5;
425
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
426
+ font-size: 13px;
427
+ line-height: 2.1;
428
+ margin: 1.5em 0 3em;
429
+ overflow: auto;
430
+ padding: 10px 25px 25px;
431
+ position: relative;
432
+ }
433
+
434
+ .bp-new-notice-panel label {
435
+ clear: both;
436
+ float: right;
437
+ margin-left: 3%;
438
+ width: 20%;
439
+ }
440
+
441
+ .bp-new-notice-panel input,
442
+ .bp-new-notice-panel textarea {
443
+ clear: none;
444
+ margin-bottom: 1em;
445
+ width: 75%;
446
+ }
447
+
448
+ .bp-new-notice-panel input[type="text"]:after,
449
+ .bp-new-notice-panel textarea:after {
450
+ clear: both;
451
+ content: " ";
452
+ display: table;
453
+ }
454
+
455
+ .bp-new-notice-panel .button-primary {
456
+ margin-right: 23%;
457
+ width: auto;
458
+ }
459
+
460
+ .bp-notice-about {
461
+ font-size: 1em;
462
+ margin-bottom: 1em;
463
+ }
464
+
465
+ .bp-new-notice {
466
+ margin-bottom: 1em;
467
+ margin-top: 0;
468
+ }
469
+
470
+ .bp-notices-list {
471
+ margin-bottom: 0;
472
+ }
473
+
474
+ @media screen and (max-width: 782px) {
475
+
476
+ .bp-new-notice-panel {
477
+ margin-bottom: 1.5em;
478
+ }
479
+
480
+ .bp-new-notice-panel input,
481
+ .bp-new-notice-panel textarea {
482
+ margin-right: 0;
483
+ width: 100%;
484
+ }
485
+
486
+ .bp-new-notice-panel .button-primary {
487
+ margin-right: 0;
488
+ width: auto;
489
+ }
490
+
491
+ .bp-new-notice-panel .button {
492
+ max-width: 45%;
493
+ word-wrap: break-word;
494
+ }
495
+
496
+ .bp-notice-about {
497
+ margin-top: 0;
498
+ margin-bottom: 1em;
499
+ }
500
+
501
+ .bp-new-notice {
502
+ margin-bottom: 0.5em;
503
+ }
504
+ }
505
+
506
  /*------------------------------------------------------------------------------
507
  * 4.0 Emails - Edit Page
508
  *----------------------------------------------------------------------------*/
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}.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.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.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}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"}
1
+ .bp-badge{color:#d84800;display:inline-block;font:400 150px/1 dashicons!important}.bp-badge:before{content:"\f448"}.index_page_bp-about code,.settings_page_bp-credits code{background-color:#e0e0e0;color:#636363;font-size:1em}.bp-about-wrap{position:relative;max-width:1050px;font-size:15px}.bp-about-wrap img{margin:0;max-width:100%;height:auto;vertical-align:middle}.bp-about-wrap p{line-height:1.5;font-size:14px}.bp-about-wrap h2{margin:40px 0 .6em;font-size:2.7em;line-height:1.3;font-weight:300;text-align:center}.bp-about-wrap h3{margin:1.25em 0 .6em;font-size:1.4em;line-height:1.5}.bp-about-wrap code{font-size:14px;font-weight:400}.bp-about-wrap .about-description{margin-top:1.4em;font-weight:400;line-height:1.6;font-size:19px}.bp-about-wrap h3.wp-people-group{margin:2.6em 0 1.33em;padding:0;font-size:16px;line-height:inherit}.bp-about-wrap .wp-people-group{padding:0 5px;margin:0 -5px 0 -15px}.bp-about-wrap .compact{margin-bottom:0}.bp-about-wrap .wp-person{display:inline-block;vertical-align:top;margin-left:10px;padding-bottom:15px;height:70px;width:280px}.bp-about-wrap .compact .wp-person{height:auto;width:180px;padding-bottom:0;margin-bottom:0}.bp-about-wrap .wp-person .gravatar{float:right;margin:0 0 10px 10px;padding:1px;width:60px;height:60px}.bp-about-wrap .compact .wp-person .gravatar{width:30px;height:30px}.bp-about-wrap .wp-person .web{margin:6px 0 2px;font-size:16px;font-weight:400;line-height:2;text-decoration:none}.bp-about-wrap .wp-person .title{display:block}.bp-about-wrap p.wp-credits-list a{white-space:nowrap}@media only screen and (max-width:500px){.bp-about-wrap{margin-left:20px;margin-right:10px}.bp-about-wrap .bp-about-wrap h1{margin-left:0}}#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:""}.bp-tooltip{position:relative}.bp-tooltip:after{background:#fff;border:1px solid #aaa;border-collapse:separate;border-radius:1px;box-shadow:-1px 1px 0 1px rgba(132,132,132,.3);color:#000;content:attr(data-bp-tooltip);display:none;font-family:sans-serif;font-size:11px;font-weight:400;letter-spacing:normal;line-height:1.5;margin-top:10px;max-width:240px;opacity:0;padding:3px 6px;position:absolute;left:50%;text-align:center;text-decoration:none;text-shadow:none;text-transform:none;top:100%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);-webkit-transition:opacity 2s ease-out;-ms-transition:opacity 2s ease-out;transition:opacity 2s ease-out;white-space:pre;word-wrap:break-word;z-index:998}.bp-hello-close .bp-tooltip:after{left:0;text-align:left;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}.bp-hello-social .bp-tooltip:after{bottom:120%;margin-bottom:20px;margin-top:0;top:auto;-webkit-transform:translateX(-15%);-ms-transform:translateX(-15%);transform:translateX(-15%)}.bp-tooltip:active:after,.bp-tooltip:focus:after,.bp-tooltip:hover:after{display:inline-block;opacity:1;overflow:visible;text-decoration:none;z-index:999}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
@@ -10,15 +10,16 @@ TABLE OF CONTENTS:
10
  --------------------------------------------------------------------------------
11
  1.0 Welcome Screen
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 User's Lists
 
 
 
22
  4.0 Emails - Edit page
23
  5.0 Tools - BuddyPress
24
  6.0 Plugins page
@@ -41,398 +42,132 @@ TABLE OF CONTENTS:
41
  content: "\f448";
42
  }
43
 
44
- .about-wrap .bp-badge {
45
- position: absolute;
46
- top: 0;
47
- right: 0;
48
- }
49
-
50
- .index_page_bp-credits code,
51
  .index_page_bp-about code {
52
  background-color: #e0e0e0;
53
  color: #636363;
54
  font-size: 1em;
55
  }
56
 
57
- @media only screen and (max-width: 500px) {
58
-
59
- .about-wrap .bp-badge {
60
- position: relative;
61
- margin: 10px auto;
62
- top: auto;
63
- right: auto;
64
- }
65
- }
66
-
67
- /*
68
- * 1.2 About Panel
69
- */
70
-
71
  /*
72
- * 1.2.1 Headline Feature
 
 
73
  */
74
- .buddypress .bp-headline-feature {
75
- margin-bottom: 2em;
76
- margin-top: 3em;
77
- padding: 2em 3em;
78
- }
79
-
80
- .buddypress .bp-headline {
81
- margin: 0 auto;
82
- width: 45em;
83
- }
84
-
85
- .buddypress .bp-headline span.dashicons {
86
- background-color: #f1f1f1;
87
- color: #d84800;
88
- clear: left;
89
- font-size: 100px;
90
- float: left;
91
- height: 100px;
92
- line-height: 100px;
93
- margin: 0 15px 15px 0;
94
- text-align: center;
95
- width: 100px;
96
- }
97
-
98
- .buddypress .bp-headline-feature .headline-title {
99
- font-size: 2.2em;
100
- font-weight: 300;
101
- line-height: 2;
102
- margin: 0 0 1em;
103
- text-align: center;
104
- }
105
-
106
- .buddypress .bp-headline-feature p {
107
- font-size: 1.15em;
108
- margin: 1.15em auto 0.6em 0;
109
  }
110
 
111
- /*
112
- * 1.2.2 Features Section
113
- */
114
- .buddypress .bp-features-section {
115
- border-bottom: 1px solid #ccc;
116
- clear: both;
117
- margin-bottom: 3em;
118
- margin-top: 2em;
119
- overflow: hidden;
120
- padding-bottom: 2em;
121
  }
122
 
123
- .buddypress .bp-features-section p {
124
- font-size: 14px;
125
  line-height: 1.5;
 
126
  }
127
 
128
- .buddypress .bp-features-section img {
129
- margin-bottom: 20px;
130
- }
131
-
132
- .buddypress .bp-features-section span.dashicons {
133
- background-color: #fff;
134
- border-radius: 50%;
135
- clear: left;
136
- color: #d84800;
137
- font-size: 50px;
138
- float: left;
139
- height: 80px;
140
- line-height: 80px;
141
- margin: 0 15px 15px 0;
142
- text-align: center;
143
- width: 80px;
144
- }
145
-
146
- .buddypress .bp-features-section .headline-title {
147
- font-size: 2em;
148
  font-weight: 300;
149
- line-height: 1.5;
150
- margin: 1em auto 2em;
151
  text-align: center;
152
  }
153
 
154
- .buddypress .bp-features-section .bp-feature-with-images {
155
- border-bottom: 1px solid #ccc;
156
- margin-bottom: 5em;
157
- padding-bottom: 2em;
158
- }
159
-
160
- .buddypress .bp-features-section .bp-feature,
161
- .buddypress .bp-features-section .bp-feature-imaged {
162
- float: left;
163
- margin-bottom: 3em;
164
- margin-right: 4.799999999%;
165
- width: 47.6%;
166
- }
167
-
168
- .buddypress .bp-features-section .bp-feature.opposite,
169
- .buddypress .bp-features-section .bp-feature-imaged.anon {
170
- margin-right: 0;
171
- }
172
-
173
- .buddypress .bp-features-section .bp-feature code {
174
- font-size: 0.95em;
175
  line-height: 1.5;
176
  }
177
 
178
- .buddypress .bp-feature:after {
179
- clear: both;
180
- content: "";
181
- margin-bottom: 2em;
182
  }
183
 
184
- .buddypress .bp-feature-imaged .feature-title {
185
- color: #23282d;
186
- font-size: 1.25em;
187
- margin-bottom: 0.6em;
188
- margin-top: 0;
189
  }
190
 
191
- .buddypress .bp-feature-imaged p {
192
- clear: left;
193
- font-size: 1.1em;
 
 
194
  }
195
 
196
- .buddypress .bp-feature-imaged img {
197
- clear: left;
 
198
  }
199
 
200
- .buddypress .bp-feature .feature-title {
201
- font-size: 1em;
202
- line-height: 1.5;
203
  margin-bottom: 0;
204
- margin-left: 110px;
205
- margin-top: 0;
206
- text-align: left;
207
  }
208
 
209
- .buddypress .bp-feature p {
210
- margin-left: 110px;
 
 
 
 
 
211
  }
212
 
213
- /*
214
- * 1.2.3 Changelog Section
215
- */
216
- .buddypress .bp-changelog-section {
217
- clear: both;
218
- margin-bottom: 3em;
219
- margin-top: 4em;
220
  padding-bottom: 0;
 
221
  }
222
 
223
- .buddypress .bp-changelog-section:after {
224
- clear: both;
225
- content: "";
226
- display: table;
227
- }
228
-
229
- .buddypress .bp-changelog-section .changelog-title {
230
- color: #23282d;
231
- font-size: 1.25em;
232
- line-height: 1.5;
233
- margin: 0 auto 1.5em;
234
- }
235
-
236
- .buddypress .bp-two-column div {
237
- float: left;
238
- margin-right: 4.799999999%;
239
- position: relative;
240
- width: 47.6%;
241
- }
242
-
243
- .buddypress .bp-three-column .bp-column {
244
  float: left;
245
- margin-right: 5%;
246
- position: relative;
247
- width: 29.95%;
 
248
  }
249
 
250
- .buddypress .bp-two-column .bp-column:nth-of-type(2n),
251
- .buddypress .bp-three-column .bp-column:nth-of-type(3n) {
252
- margin-right: 0;
253
  }
254
 
255
- .buddypress .bp-changelog {
256
- margin-bottom: 3em;
257
- }
258
-
259
- .buddypress .bp-changelog:after {
260
- clear: both;
261
- content: "";
262
- display: table;
263
- }
264
-
265
- .buddypress .bp-changelog .title {
266
- font-size: 14px;
267
- margin-bottom: 0.75em;
268
- margin-top: 0;
269
- }
270
-
271
- .buddypress .bp-changelog p {
272
- margin-bottom: 0;
273
  }
274
 
275
- .bp-changelog-url {
276
- text-align: center;
277
  }
278
 
279
- .bp-assets {
280
- clear: both;
281
- margin-bottom: 3em;
282
  }
283
 
284
- @media screen and ( max-width: 782px ) {
285
 
286
- .bp-headline-feature,
287
- .bp-features-section,
288
- .bp-changelog-section,
289
- .bp-assets {
290
- margin-left: 20px;
291
  margin-right: 20px;
 
292
  }
293
 
294
- .buddypress .bp-headline-feature {
295
- padding: 0;
296
- }
297
-
298
- .buddypress .bp-headline {
299
- margin: 0;
300
- width: 97%;
301
- }
302
-
303
- .buddypress .bp-features-section {
304
- clear: both;
305
- margin-bottom: 0;
306
- margin-top: 2em;
307
- padding-bottom: 2em;
308
- }
309
-
310
- .buddypress .bp-features-section .bp-feature-with-images {
311
- margin-bottom: 2em;
312
- }
313
-
314
- .buddypress .bp-features-section .headline-title {
315
- margin-bottom: 1em;
316
- }
317
-
318
- .buddypress .bp-changelog-section .changelog-title {
319
- font-size: 1.25em;
320
- line-height: 1.5;
321
- margin-bottom: 0.5em;
322
- margin-top: 0.5em;
323
- }
324
-
325
- .buddypress .bp-features-section .feature-title,
326
- .buddypress .bp-changelog-section .title {
327
- font-size: 1.25em;
328
- line-height: 1.25;
329
- margin-top: 0.6em;
330
- text-align: left;
331
- }
332
-
333
- .buddypress .bp-features-section .bp-feature,
334
- .buddypress .bp-features-section .bp-feature-imaged {
335
- clear: both;
336
- float: left;
337
- margin-bottom: 1em;
338
- margin-top: 1em;
339
  margin-right: 0;
340
- padding-right: 1em;
341
- width: 100%;
342
- }
343
-
344
- .buddypress .bp-features-section .bp-feature-imaged p {
345
- font-size: 1em;
346
- }
347
-
348
- .buddypress .bp-features-section .bp-feature span {
349
- margin-top: 0.33em;
350
- }
351
-
352
- .buddypress .bp-feature.opposite .feature-title,
353
- .buddypress .bp-feature.opposite p {
354
- float: none;
355
- }
356
-
357
- .buddypress .bp-changelog-section {
358
- clear: both;
359
- margin-bottom: 2em;
360
- margin-top: 2em;
361
- }
362
-
363
- .buddypress .bp-changelog {
364
- margin-bottom: 0;
365
- }
366
-
367
- .buddypress .bp-changelog-section .changelog-title {
368
- margin-bottom: 0.5em;
369
- }
370
-
371
- .buddypress .bp-changelog .title {
372
- font-size: 1em;
373
- }
374
-
375
- .buddypress .bp-changelog p {
376
- margin-bottom: 1em;
377
- }
378
-
379
- .buddypress .bp-changelog-section .two-col > div,
380
- .buddypress .bp-changelog-section .three-col .col {
381
- margin-top: 0;
382
- padding-bottom: 0.5em;
383
- width: 100%;
384
- }
385
-
386
- .buddypress .bp-three-column .bp-column {
387
- width: 100%;
388
- }
389
- }
390
-
391
- @media screen and ( max-width: 360px ) {
392
-
393
- .buddypress .bp-headline {
394
- text-align: center;
395
- }
396
-
397
- .buddypress .bp-headline span.dashicons {
398
- clear: none;
399
- font-size: 80px;
400
- float: none;
401
- height: 80px;
402
- line-height: 80px;
403
- margin: 0 auto;
404
- width: 80px;
405
- }
406
-
407
- .buddypress .bp-headline-feature .headline-title,
408
- .buddypress .bp-features-section .headline-title {
409
- font-size: 1.5em;
410
- line-height: 1.5;
411
- text-align: left;
412
- }
413
-
414
- .buddypress .bp-headline-feature .headline-title {
415
- margin: 1em 0 0;
416
- }
417
-
418
- .buddypress .bp-headline-feature p {
419
- margin: 1.15em auto 0.6em 0;
420
- text-align: left;
421
- width: auto;
422
- }
423
-
424
- .buddypress .bp-features-section .bp-feature {
425
- text-align: center;
426
- }
427
-
428
- .buddypress .bp-features-section span.dashicons {
429
- float: none;
430
- }
431
-
432
- .buddypress .bp-features-section .feature-title,
433
- .buddypress .bp-features-section p {
434
- margin-left: 0;
435
- text-align: left;
436
  }
437
  }
438
 
@@ -523,10 +258,6 @@ TABLE OF CONTENTS:
523
  content: "\f457";
524
  }
525
 
526
- .settings_page_bp-components tr.forums td.plugin-title span:before {
527
- content: "\f452";
528
- }
529
-
530
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
531
  content: "\f120";
532
  }
@@ -571,10 +302,84 @@ TABLE OF CONTENTS:
571
  content: "";
572
  }
573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
 
575
  /*------------------------------------------------------------------------------
576
- * 3.0 User's Lists
577
  *----------------------------------------------------------------------------*/
 
 
 
 
578
  body.site-users-php th#role,
579
  body.users-php th#role,
580
  body.users_page_bp-signups th#count_sent {
@@ -611,6 +416,93 @@ body.users_page_bp-signups td.count_sent {
611
  font-weight: 700;
612
  }
613
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  /*------------------------------------------------------------------------------
615
  * 4.0 Emails - Edit Page
616
  *----------------------------------------------------------------------------*/
10
  --------------------------------------------------------------------------------
11
  1.0 Welcome Screen
12
  1.1 Version Badge
13
+ 1.2 ---
14
+ 1.3 Credits Panel
 
 
15
  2.0 Dashicons
16
  2.1 Top level menus
17
  2.2 Settings - Components
18
  2.3 Tools
19
+ 2.4 Tooltips
20
+ 3.0 Users
21
+ 3.1 Users List
22
+ 3.2 Site Notices
23
  4.0 Emails - Edit page
24
  5.0 Tools - BuddyPress
25
  6.0 Plugins page
42
  content: "\f448";
43
  }
44
 
45
+ .settings_page_bp-credits code,
 
 
 
 
 
 
46
  .index_page_bp-about code {
47
  background-color: #e0e0e0;
48
  color: #636363;
49
  font-size: 1em;
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  /*
53
+ * 1.3 Credits Panel
54
+ *
55
+ * Taken from WP 4.9.5.
56
  */
57
+ .bp-about-wrap {
58
+ position: relative;
59
+ max-width: 1050px;
60
+ font-size: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
 
63
+ .bp-about-wrap img {
64
+ margin: 0;
65
+ max-width: 100%;
66
+ height: auto;
67
+ vertical-align: middle;
 
 
 
 
 
68
  }
69
 
70
+ .bp-about-wrap p {
 
71
  line-height: 1.5;
72
+ font-size: 14px;
73
  }
74
 
75
+ .bp-about-wrap h2 {
76
+ margin: 40px 0 0.6em;
77
+ font-size: 2.7em;
78
+ line-height: 1.3;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  font-weight: 300;
 
 
80
  text-align: center;
81
  }
82
 
83
+ .bp-about-wrap h3 {
84
+ margin: 1.25em 0 0.6em;
85
+ font-size: 1.4em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  line-height: 1.5;
87
  }
88
 
89
+ .bp-about-wrap code {
90
+ font-size: 14px;
91
+ font-weight: 400;
 
92
  }
93
 
94
+ .bp-about-wrap .about-description {
95
+ margin-top: 1.4em;
96
+ font-weight: 400;
97
+ line-height: 1.6;
98
+ font-size: 19px;
99
  }
100
 
101
+ .bp-about-wrap h3.wp-people-group {
102
+ margin: 2.6em 0 1.33em;
103
+ padding: 0;
104
+ font-size: 16px;
105
+ line-height: inherit;
106
  }
107
 
108
+ .bp-about-wrap .wp-people-group {
109
+ padding: 0 5px;
110
+ margin: 0 -15px 0 -5px;
111
  }
112
 
113
+ .bp-about-wrap .compact {
 
 
114
  margin-bottom: 0;
 
 
 
115
  }
116
 
117
+ .bp-about-wrap .wp-person {
118
+ display: inline-block;
119
+ vertical-align: top;
120
+ margin-right: 10px;
121
+ padding-bottom: 15px;
122
+ height: 70px;
123
+ width: 280px;
124
  }
125
 
126
+ .bp-about-wrap .compact .wp-person {
127
+ height: auto;
128
+ width: 180px;
 
 
 
 
129
  padding-bottom: 0;
130
+ margin-bottom: 0;
131
  }
132
 
133
+ .bp-about-wrap .wp-person .gravatar {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  float: left;
135
+ margin: 0 10px 10px 0;
136
+ padding: 1px;
137
+ width: 60px;
138
+ height: 60px;
139
  }
140
 
141
+ .bp-about-wrap .compact .wp-person .gravatar {
142
+ width: 30px;
143
+ height: 30px;
144
  }
145
 
146
+ .bp-about-wrap .wp-person .web {
147
+ margin: 6px 0 2px;
148
+ font-size: 16px;
149
+ font-weight: 400;
150
+ line-height: 2;
151
+ text-decoration: none;
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
 
154
+ .bp-about-wrap .wp-person .title {
155
+ display: block;
156
  }
157
 
158
+ .bp-about-wrap p.wp-credits-list a {
159
+ white-space: nowrap;
 
160
  }
161
 
162
+ @media only screen and (max-width: 500px) {
163
 
164
+ .bp-about-wrap {
 
 
 
 
165
  margin-right: 20px;
166
+ margin-left: 10px;
167
  }
168
 
169
+ .bp-about-wrap .bp-about-wrap h1 {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  margin-right: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
172
  }
173
 
258
  content: "\f457";
259
  }
260
 
 
 
 
 
261
  .settings_page_bp-components tr.blogs td.plugin-title span:before {
262
  content: "\f120";
263
  }
302
  content: "";
303
  }
304
 
305
+ /*
306
+ * 2.4 Tooltips
307
+ */
308
+ .bp-tooltip {
309
+ position: relative;
310
+ }
311
+
312
+ .bp-tooltip:after {
313
+ background: #fff;
314
+ border: 1px solid #aaa;
315
+ border-collapse: separate;
316
+ border-radius: 1px;
317
+ box-shadow: 1px 1px 0 1px rgba(132, 132, 132, 0.3);
318
+ color: #000;
319
+ content: attr(data-bp-tooltip);
320
+ display: none;
321
+ font-family: sans-serif;
322
+ font-size: 11px;
323
+ font-weight: 400;
324
+ letter-spacing: normal;
325
+ line-height: 1.5;
326
+ margin-top: 10px;
327
+ max-width: 240px;
328
+ opacity: 0;
329
+ padding: 3px 6px;
330
+ position: absolute;
331
+ right: 50%;
332
+ text-align: center;
333
+ text-decoration: none;
334
+ text-shadow: none;
335
+ text-transform: none;
336
+ top: 100%;
337
+ -webkit-transform: translateX(50%);
338
+ -ms-transform: translateX(50%);
339
+ transform: translateX(50%);
340
+ -webkit-transition: opacity 2s ease-out;
341
+ -ms-transition: opacity 2s ease-out;
342
+ transition: opacity 2s ease-out;
343
+ white-space: pre;
344
+ word-wrap: break-word;
345
+ z-index: 998;
346
+ }
347
+
348
+ .bp-hello-close .bp-tooltip:after {
349
+ right: 0;
350
+ text-align: right;
351
+ -webkit-transform: translateX(0);
352
+ -ms-transform: translateX(0);
353
+ transform: translateX(0);
354
+ }
355
+
356
+ .bp-hello-social .bp-tooltip:after {
357
+ bottom: 120%;
358
+ margin-bottom: 20px;
359
+ margin-top: 0;
360
+ top: auto;
361
+ -webkit-transform: translateX(15%);
362
+ -ms-transform: translateX(15%);
363
+ transform: translateX(15%);
364
+ }
365
+
366
+ .bp-tooltip:hover:after,
367
+ .bp-tooltip:active:after,
368
+ .bp-tooltip:focus:after {
369
+ display: inline-block;
370
+ opacity: 1;
371
+ overflow: visible;
372
+ text-decoration: none;
373
+ z-index: 999;
374
+ }
375
 
376
  /*------------------------------------------------------------------------------
377
+ * 3.0 Users
378
  *----------------------------------------------------------------------------*/
379
+
380
+ /*
381
+ * 3.1 Users List
382
+ */
383
  body.site-users-php th#role,
384
  body.users-php th#role,
385
  body.users_page_bp-signups th#count_sent {
416
  font-weight: 700;
417
  }
418
 
419
+ /*
420
+ * 3.2 Site Notices
421
+ */
422
+ .bp-new-notice-panel {
423
+ background: #fff;
424
+ border: 1px solid #e5e5e5;
425
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
426
+ font-size: 13px;
427
+ line-height: 2.1;
428
+ margin: 1.5em 0 3em;
429
+ overflow: auto;
430
+ padding: 10px 25px 25px;
431
+ position: relative;
432
+ }
433
+
434
+ .bp-new-notice-panel label {
435
+ clear: both;
436
+ float: left;
437
+ margin-right: 3%;
438
+ width: 20%;
439
+ }
440
+
441
+ .bp-new-notice-panel input,
442
+ .bp-new-notice-panel textarea {
443
+ clear: none;
444
+ margin-bottom: 1em;
445
+ width: 75%;
446
+ }
447
+
448
+ .bp-new-notice-panel input[type="text"]:after,
449
+ .bp-new-notice-panel textarea:after {
450
+ clear: both;
451
+ content: " ";
452
+ display: table;
453
+ }
454
+
455
+ .bp-new-notice-panel .button-primary {
456
+ margin-left: 23%;
457
+ width: auto;
458
+ }
459
+
460
+ .bp-notice-about {
461
+ font-size: 1em;
462
+ margin-bottom: 1em;
463
+ }
464
+
465
+ .bp-new-notice {
466
+ margin-bottom: 1em;
467
+ margin-top: 0;
468
+ }
469
+
470
+ .bp-notices-list {
471
+ margin-bottom: 0;
472
+ }
473
+
474
+ @media screen and (max-width: 782px) {
475
+
476
+ .bp-new-notice-panel {
477
+ margin-bottom: 1.5em;
478
+ }
479
+
480
+ .bp-new-notice-panel input,
481
+ .bp-new-notice-panel textarea {
482
+ margin-left: 0;
483
+ width: 100%;
484
+ }
485
+
486
+ .bp-new-notice-panel .button-primary {
487
+ margin-left: 0;
488
+ width: auto;
489
+ }
490
+
491
+ .bp-new-notice-panel .button {
492
+ max-width: 45%;
493
+ word-wrap: break-word;
494
+ }
495
+
496
+ .bp-notice-about {
497
+ margin-top: 0;
498
+ margin-bottom: 1em;
499
+ }
500
+
501
+ .bp-new-notice {
502
+ margin-bottom: 0.5em;
503
+ }
504
+ }
505
+
506
  /*------------------------------------------------------------------------------
507
  * 4.0 Emails - Edit Page
508
  *----------------------------------------------------------------------------*/
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}.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.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.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}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"}
1
+ .bp-badge{color:#d84800;display:inline-block;font:400 150px/1 dashicons!important}.bp-badge:before{content:"\f448"}.index_page_bp-about code,.settings_page_bp-credits code{background-color:#e0e0e0;color:#636363;font-size:1em}.bp-about-wrap{position:relative;max-width:1050px;font-size:15px}.bp-about-wrap img{margin:0;max-width:100%;height:auto;vertical-align:middle}.bp-about-wrap p{line-height:1.5;font-size:14px}.bp-about-wrap h2{margin:40px 0 .6em;font-size:2.7em;line-height:1.3;font-weight:300;text-align:center}.bp-about-wrap h3{margin:1.25em 0 .6em;font-size:1.4em;line-height:1.5}.bp-about-wrap code{font-size:14px;font-weight:400}.bp-about-wrap .about-description{margin-top:1.4em;font-weight:400;line-height:1.6;font-size:19px}.bp-about-wrap h3.wp-people-group{margin:2.6em 0 1.33em;padding:0;font-size:16px;line-height:inherit}.bp-about-wrap .wp-people-group{padding:0 5px;margin:0 -15px 0 -5px}.bp-about-wrap .compact{margin-bottom:0}.bp-about-wrap .wp-person{display:inline-block;vertical-align:top;margin-right:10px;padding-bottom:15px;height:70px;width:280px}.bp-about-wrap .compact .wp-person{height:auto;width:180px;padding-bottom:0;margin-bottom:0}.bp-about-wrap .wp-person .gravatar{float:left;margin:0 10px 10px 0;padding:1px;width:60px;height:60px}.bp-about-wrap .compact .wp-person .gravatar{width:30px;height:30px}.bp-about-wrap .wp-person .web{margin:6px 0 2px;font-size:16px;font-weight:400;line-height:2;text-decoration:none}.bp-about-wrap .wp-person .title{display:block}.bp-about-wrap p.wp-credits-list a{white-space:nowrap}@media only screen and (max-width:500px){.bp-about-wrap{margin-right:20px;margin-left:10px}.bp-about-wrap .bp-about-wrap h1{margin-right:0}}#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:""}.bp-tooltip{position:relative}.bp-tooltip:after{background:#fff;border:1px solid #aaa;border-collapse:separate;border-radius:1px;box-shadow:1px 1px 0 1px rgba(132,132,132,.3);color:#000;content:attr(data-bp-tooltip);display:none;font-family:sans-serif;font-size:11px;font-weight:400;letter-spacing:normal;line-height:1.5;margin-top:10px;max-width:240px;opacity:0;padding:3px 6px;position:absolute;right:50%;text-align:center;text-decoration:none;text-shadow:none;text-transform:none;top:100%;-webkit-transform:translateX(50%);-ms-transform:translateX(50%);transform:translateX(50%);-webkit-transition:opacity 2s ease-out;-ms-transition:opacity 2s ease-out;transition:opacity 2s ease-out;white-space:pre;word-wrap:break-word;z-index:998}.bp-hello-close .bp-tooltip:after{right:0;text-align:right;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}.bp-hello-social .bp-tooltip:after{bottom:120%;margin-bottom:20px;margin-top:0;top:auto;-webkit-transform:translateX(15%);-ms-transform:translateX(15%);transform:translateX(15%)}.bp-tooltip:active:after,.bp-tooltip:focus:after,.bp-tooltip:hover:after{display:inline-block;opacity:1;overflow:visible;text-decoration:none;z-index:999}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/hello-rtl.css ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*------------------------------------------------------------------------------
2
+ Loaded in wp-admin for query string `hello=buddypress`.
3
+
4
+ @since 3.0.0
5
+
6
+ --------------------------------------------------------------------------------
7
+ TABLE OF CONTENTS:
8
+ --------------------------------------------------------------------------------
9
+ 1.0 - Typography and colour
10
+ 2.0 - Dashicons
11
+ 3.0 - Elements
12
+ 3.1 - Backdrop and container
13
+ 3.2 - Modal footer
14
+ 3.3 - Modal header
15
+ 3.4 - Modal content
16
+ 4.0 - Content styles
17
+ 4.1 - Backdrop and container
18
+ 4.2 - Footer content
19
+ 4.3 - Header content
20
+ 4.4 - Content content
21
+ 5.0 - Media
22
+ 6.0 - Media Queries
23
+ 6.1 - Desktop Medium
24
+ 6.2 - Desktop Large
25
+ ------------------------------------------------------------------------------*/
26
+ /*------------------------------------------------------------------------------
27
+ * 1.0 - Typography and colour
28
+ *----------------------------------------------------------------------------*/
29
+ :root {
30
+ --bp-hello-color-primary: #d34600;
31
+ --bp-hello-color-secondary: #e5e5e5;
32
+ --bp-hello-container-size: 15%;
33
+ }
34
+
35
+ #bp-hello-container a {
36
+ color: var(--bp-hello-color-primary);
37
+ }
38
+
39
+ #bp-hello-container a:hover {
40
+ -webkit-transition: all 0.1s ease-in-out;
41
+ -o-transition: all 0.1s ease-in-out;
42
+ transition: all 0.1s ease-in-out;
43
+ color: black;
44
+ }
45
+
46
+ #bp-hello-container .bp-hello-header h1 {
47
+ line-height: 1.7;
48
+ font-size: 21px;
49
+ font-weight: 400;
50
+ }
51
+
52
+ .bp-hello-content p {
53
+ font-size: 16px;
54
+ }
55
+
56
+ /*------------------------------------------------------------------------------
57
+ * 2.0 - Dashicons
58
+ *----------------------------------------------------------------------------*/
59
+ .bp-hello-close .button {
60
+ padding: 5px !important;
61
+ }
62
+
63
+ .bp-hello-close .close-modal:before {
64
+ content: "\f158";
65
+ color: #23282d;
66
+ /* wp toolbar */
67
+ font: 400 1.5em/1 dashicons;
68
+ speak: none;
69
+ -webkit-font-smoothing: antialiased;
70
+ -moz-osx-font-smoothing: grayscale;
71
+ background-image: none !important;
72
+ }
73
+
74
+ .bp-hello-close .close-modal:focus:before, .bp-hello-close .close-modal:hover:before {
75
+ -webkit-transition: all 0.1s ease-in-out;
76
+ -o-transition: all 0.1s ease-in-out;
77
+ transition: all 0.1s ease-in-out;
78
+ color: var(--bp-hello-color-primary);
79
+ }
80
+
81
+ .bp-hello-social li a:before {
82
+ color: #23282d;
83
+ /* wp toolbar */
84
+ font: 400 30px/0.6 dashicons;
85
+ speak: none;
86
+ -webkit-font-smoothing: antialiased;
87
+ -moz-osx-font-smoothing: grayscale;
88
+ background-image: none !important;
89
+ }
90
+
91
+ .bp-hello-social li a:hover:before {
92
+ -webkit-transition: all 0.1s ease-in-out;
93
+ -o-transition: all 0.1s ease-in-out;
94
+ transition: all 0.1s ease-in-out;
95
+ color: var(--bp-hello-color-primary);
96
+ }
97
+
98
+ .bp-hello-social li a.support:before {
99
+ content: "\f448";
100
+ }
101
+
102
+ .bp-hello-social li a.twitter:before {
103
+ content: "\f301";
104
+ }
105
+
106
+ /*------------------------------------------------------------------------------
107
+ * 3.0 - Elements
108
+ *----------------------------------------------------------------------------*/
109
+ /*
110
+ * 3.1 - Backdrop and container
111
+ */
112
+ #bp-hello-backdrop {
113
+ position: fixed;
114
+ top: 0;
115
+ right: 0;
116
+ left: 0;
117
+ bottom: 0;
118
+ z-index: 9998;
119
+ display: none;
120
+ }
121
+
122
+ #bp-hello-container {
123
+ position: fixed;
124
+ top: 0;
125
+ bottom: 80px;
126
+ z-index: 99999;
127
+ }
128
+
129
+ .bp-disable-scroll {
130
+ overflow: hidden;
131
+ }
132
+
133
+ /*
134
+ * 3.2 - Modal footer
135
+ */
136
+ .bp-hello-footer {
137
+ display: -webkit-box;
138
+ display: -ms-flexbox;
139
+ display: flex;
140
+ -ms-flex-wrap: wrap;
141
+ flex-wrap: wrap;
142
+ height: 58px;
143
+ max-height: 58px;
144
+ }
145
+
146
+ .bp-hello-social-cta,
147
+ .bp-hello-social-links {
148
+ -ms-flex-preferred-size: 50%;
149
+ flex-basis: 50%;
150
+ }
151
+
152
+ .bp-hello-social-links ul {
153
+ display: inline-block;
154
+ }
155
+
156
+ .bp-hello-social li {
157
+ position: relative;
158
+ bottom: -5px;
159
+ display: inline-block;
160
+ list-style-type: none;
161
+ margin-bottom: 0;
162
+ }
163
+
164
+ .bp-hello-social li:last-child a {
165
+ margin-right: 4px;
166
+ }
167
+
168
+ /*
169
+ * 3.3 - Modal header
170
+ */
171
+ .bp-hello-header {
172
+ height: 58px;
173
+ max-height: 58px;
174
+ }
175
+
176
+ /*
177
+ * 3.4 - Modal content
178
+ */
179
+ .bp-hello-content {
180
+ padding: 0 25px;
181
+ height: calc(100% - 58px);
182
+ overflow-y: auto;
183
+ -webkit-overflow-scrolling: touch;
184
+ }
185
+
186
+ /*------------------------------------------------------------------------------
187
+ * 4.0 - Content styles
188
+ *----------------------------------------------------------------------------*/
189
+ /*
190
+ * 4.1 - Backdrop and container
191
+ */
192
+ #bp-hello-backdrop {
193
+ background-color: rgba(0, 0, 0, 0.8);
194
+ -webkit-transition: opacity 0.15s ease-out;
195
+ -o-transition: opacity 0.15s ease-out;
196
+ transition: opacity 0.15s ease-out;
197
+ }
198
+
199
+ #bp-hello-container {
200
+ background-color: white;
201
+ }
202
+
203
+ /*
204
+ * 4.2 - Footer content
205
+ */
206
+ .bp-hello-footer {
207
+ border-radius: 0 0 3px 3px;
208
+ background-color: white;
209
+ border-top: 1px solid var(--bp-hello-color-secondary);
210
+ padding: 6px 25px;
211
+ }
212
+
213
+ .bp-hello-footer p {
214
+ font-size: 15px;
215
+ }
216
+
217
+ .bp-hello-social-cta {
218
+ text-align: right;
219
+ }
220
+
221
+ .bp-hello-social-links {
222
+ text-align: left;
223
+ }
224
+
225
+ .bp-hello-social li a {
226
+ text-decoration: none;
227
+ }
228
+
229
+ /*
230
+ * 4.3 - Header content
231
+ */
232
+ .bp-hello-header {
233
+ padding: 6px 25px;
234
+ }
235
+
236
+ .bp-hello-header h1 {
237
+ width: calc(100% - 51px);
238
+ }
239
+
240
+ #bp-hello-container .bp-hello-header {
241
+ border-bottom: 1px solid var(--bp-hello-color-secondary);
242
+ }
243
+
244
+ .bp-hello-title {
245
+ text-align: right;
246
+ }
247
+
248
+ .bp-hello-close {
249
+ position: absolute;
250
+ top: 20px;
251
+ left: 25px;
252
+ text-align: left;
253
+ }
254
+
255
+ /*
256
+ * 4.4 - Content content
257
+ */
258
+ .bp-hello-content {
259
+ background-color: white;
260
+ }
261
+
262
+ /*------------------------------------------------------------------------------
263
+ * 5.0 - Media
264
+ *----------------------------------------------------------------------------*/
265
+ .bp-hello-content img {
266
+ border-radius: 2px;
267
+ max-width: 100%;
268
+ }
269
+
270
+ .bp-hello-content iframe {
271
+ width: 100%;
272
+ }
273
+
274
+ /*------------------------------------------------------------------------------
275
+ * 6.0 - Media Queries
276
+ *----------------------------------------------------------------------------*/
277
+ /*
278
+ * 6.1 - Desktop Medium
279
+ */
280
+ @media only screen and (min-width: 1024px) {
281
+ #bp-hello-backdrop {
282
+ display: block;
283
+ }
284
+ #bp-hello-container {
285
+ position: fixed;
286
+ top: 60px;
287
+ right: var(--bp-hello-container-size);
288
+ left: var(--bp-hello-container-size);
289
+ bottom: 30px;
290
+ z-index: 9999;
291
+ border-radius: 3px;
292
+ }
293
+ #bp-hello-container .bp-hello-header h1 {
294
+ line-height: inherit;
295
+ }
296
+ .bp-hello-header {
297
+ height: auto;
298
+ max-height: inherit;
299
+ padding: 6px 30px;
300
+ }
301
+ .bp-hello-close {
302
+ left: 30px;
303
+ }
304
+ .bp-hello-close .close-modal:before {
305
+ line-height: 0.7;
306
+ }
307
+ .bp-hello-footer {
308
+ position: fixed;
309
+ right: var(--bp-hello-container-size);
310
+ left: var(--bp-hello-container-size);
311
+ bottom: 30px;
312
+ z-index: 10000;
313
+ height: auto;
314
+ max-height: inherit;
315
+ padding: 6px 30px;
316
+ }
317
+ .bp-hello-content {
318
+ height: calc(100% - 90px);
319
+ padding: 0 30px;
320
+ }
321
+ .bp-hello-content p {
322
+ font-size: 14px;
323
+ }
324
+ }
325
+
326
+ /**
327
+ * 6.2 - Desktop Large
328
+ */
329
+ @media screen and (min-width: 1280px) {
330
+ #bp-hello-container,
331
+ .bp-hello-footer {
332
+ right: calc((100% - 896px) / 2);
333
+ left: calc((100% - 896px) / 2);
334
+ }
335
+ }
bp-core/admin/css/hello-rtl.min.css ADDED
@@ -0,0 +1 @@
 
1
+ :root{--bp-hello-color-primary:#d34600;--bp-hello-color-secondary:#e5e5e5;--bp-hello-container-size:15%}#bp-hello-container a{color:var(--bp-hello-color-primary)}#bp-hello-container a:hover{-webkit-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;color:#000}#bp-hello-container .bp-hello-header h1{line-height:1.7;font-size:21px;font-weight:400}.bp-hello-content p{font-size:16px}.bp-hello-close .button{padding:5px!important}.bp-hello-close .close-modal:before{content:"\f158";color:#23282d;font:400 1.5em/1 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-image:none!important}.bp-hello-close .close-modal:focus:before,.bp-hello-close .close-modal:hover:before{-webkit-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;color:var(--bp-hello-color-primary)}.bp-hello-social li a:before{color:#23282d;font:400 30px/.6 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-image:none!important}.bp-hello-social li a:hover:before{-webkit-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;color:var(--bp-hello-color-primary)}.bp-hello-social li a.support:before{content:"\f448"}.bp-hello-social li a.twitter:before{content:"\f301"}#bp-hello-backdrop{position:fixed;top:0;right:0;left:0;bottom:0;z-index:9998;display:none}#bp-hello-container{position:fixed;top:0;bottom:80px;z-index:99999}.bp-disable-scroll{overflow:hidden}.bp-hello-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;height:58px;max-height:58px}.bp-hello-social-cta,.bp-hello-social-links{-ms-flex-preferred-size:50%;flex-basis:50%}.bp-hello-social-links ul{display:inline-block}.bp-hello-social li{position:relative;bottom:-5px;display:inline-block;list-style-type:none;margin-bottom:0}.bp-hello-social li:last-child a{margin-right:4px}.bp-hello-header{height:58px;max-height:58px}.bp-hello-content{padding:0 25px;height:calc(100% - 58px);overflow-y:auto;-webkit-overflow-scrolling:touch}#bp-hello-backdrop{background-color:rgba(0,0,0,.8);-webkit-transition:opacity .15s ease-out;-o-transition:opacity .15s ease-out;transition:opacity .15s ease-out}#bp-hello-container{background-color:#fff}.bp-hello-footer{border-radius:0 0 3px 3px;background-color:#fff;border-top:1px solid var(--bp-hello-color-secondary);padding:6px 25px}.bp-hello-footer p{font-size:15px}.bp-hello-social-cta{text-align:right}.bp-hello-social-links{text-align:left}.bp-hello-social li a{text-decoration:none}.bp-hello-header{padding:6px 25px}.bp-hello-header h1{width:calc(100% - 51px)}#bp-hello-container .bp-hello-header{border-bottom:1px solid var(--bp-hello-color-secondary)}.bp-hello-title{text-align:right}.bp-hello-close{position:absolute;top:20px;left:25px;text-align:left}.bp-hello-content{background-color:#fff}.bp-hello-content img{border-radius:2px;max-width:100%}.bp-hello-content iframe{width:100%}@media only screen and (min-width:1024px){#bp-hello-backdrop{display:block}#bp-hello-container{position:fixed;top:60px;right:var(--bp-hello-container-size);left:var(--bp-hello-container-size);bottom:30px;z-index:9999;border-radius:3px}#bp-hello-container .bp-hello-header h1{line-height:inherit}.bp-hello-header{height:auto;max-height:inherit;padding:6px 30px}.bp-hello-close{left:30px}.bp-hello-close .close-modal:before{line-height:.7}.bp-hello-footer{position:fixed;right:var(--bp-hello-container-size);left:var(--bp-hello-container-size);bottom:30px;z-index:10000;height:auto;max-height:inherit;padding:6px 30px}.bp-hello-content{height:calc(100% - 90px);padding:0 30px}.bp-hello-content p{font-size:14px}}@media screen and (min-width:1280px){#bp-hello-container,.bp-hello-footer{right:calc((100% - 896px)/ 2);left:calc((100% - 896px)/ 2)}}
bp-core/admin/css/hello.css ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*------------------------------------------------------------------------------
2
+ Loaded in wp-admin for query string `hello=buddypress`.
3
+
4
+ @since 3.0.0
5
+
6
+ --------------------------------------------------------------------------------
7
+ TABLE OF CONTENTS:
8
+ --------------------------------------------------------------------------------
9
+ 1.0 - Typography and colour
10
+ 2.0 - Dashicons
11
+ 3.0 - Elements
12
+ 3.1 - Backdrop and container
13
+ 3.2 - Modal footer
14
+ 3.3 - Modal header
15
+ 3.4 - Modal content
16
+ 4.0 - Content styles
17
+ 4.1 - Backdrop and container
18
+ 4.2 - Footer content
19
+ 4.3 - Header content
20
+ 4.4 - Content content
21
+ 5.0 - Media
22
+ 6.0 - Media Queries
23
+ 6.1 - Desktop Medium
24
+ 6.2 - Desktop Large
25
+ ------------------------------------------------------------------------------*/
26
+ /*------------------------------------------------------------------------------
27
+ * 1.0 - Typography and colour
28
+ *----------------------------------------------------------------------------*/
29
+ :root {
30
+ --bp-hello-color-primary: #d34600;
31
+ --bp-hello-color-secondary: #e5e5e5;
32
+ --bp-hello-container-size: 15%;
33
+ }
34
+
35
+ #bp-hello-container a {
36
+ color: var(--bp-hello-color-primary);
37
+ }
38
+
39
+ #bp-hello-container a:hover {
40
+ -webkit-transition: all 0.1s ease-in-out;
41
+ -o-transition: all 0.1s ease-in-out;
42
+ transition: all 0.1s ease-in-out;
43
+ color: black;
44
+ }
45
+
46
+ #bp-hello-container .bp-hello-header h1 {
47
+ line-height: 1.7;
48
+ font-size: 21px;
49
+ font-weight: 400;
50
+ }
51
+
52
+ .bp-hello-content p {
53
+ font-size: 16px;
54
+ }
55
+
56
+ /*------------------------------------------------------------------------------
57
+ * 2.0 - Dashicons
58
+ *----------------------------------------------------------------------------*/
59
+ .bp-hello-close .button {
60
+ padding: 5px !important;
61
+ }
62
+
63
+ .bp-hello-close .close-modal:before {
64
+ content: "\f158";
65
+ color: #23282d;
66
+ /* wp toolbar */
67
+ font: 400 1.5em/1 dashicons;
68
+ speak: none;
69
+ -webkit-font-smoothing: antialiased;
70
+ -moz-osx-font-smoothing: grayscale;
71
+ background-image: none !important;
72
+ }
73
+
74
+ .bp-hello-close .close-modal:focus:before, .bp-hello-close .close-modal:hover:before {
75
+ -webkit-transition: all 0.1s ease-in-out;
76
+ -o-transition: all 0.1s ease-in-out;
77
+ transition: all 0.1s ease-in-out;
78
+ color: var(--bp-hello-color-primary);
79
+ }
80
+
81
+ .bp-hello-social li a:before {
82
+ color: #23282d;
83
+ /* wp toolbar */
84
+ font: 400 30px/0.6 dashicons;
85
+ speak: none;
86
+ -webkit-font-smoothing: antialiased;
87
+ -moz-osx-font-smoothing: grayscale;
88
+ background-image: none !important;
89
+ }
90
+
91
+ .bp-hello-social li a:hover:before {
92
+ -webkit-transition: all 0.1s ease-in-out;
93
+ -o-transition: all 0.1s ease-in-out;
94
+ transition: all 0.1s ease-in-out;
95
+ color: var(--bp-hello-color-primary);
96
+ }
97
+
98
+ .bp-hello-social li a.support:before {
99
+ content: "\f448";
100
+ }
101
+
102
+ .bp-hello-social li a.twitter:before {
103
+ content: "\f301";
104
+ }
105
+
106
+ /*------------------------------------------------------------------------------
107
+ * 3.0 - Elements
108
+ *----------------------------------------------------------------------------*/
109
+ /*
110
+ * 3.1 - Backdrop and container
111
+ */
112
+ #bp-hello-backdrop {
113
+ position: fixed;
114
+ top: 0;
115
+ left: 0;
116
+ right: 0;
117
+ bottom: 0;
118
+ z-index: 9998;
119
+ display: none;
120
+ }
121
+
122
+ #bp-hello-container {
123
+ position: fixed;
124
+ top: 0;
125
+ bottom: 80px;
126
+ z-index: 99999;
127
+ }
128
+
129
+ .bp-disable-scroll {
130
+ overflow: hidden;
131
+ }
132
+
133
+ /*
134
+ * 3.2 - Modal footer
135
+ */
136
+ .bp-hello-footer {
137
+ display: -webkit-box;
138
+ display: -ms-flexbox;
139
+ display: flex;
140
+ -ms-flex-wrap: wrap;
141
+ flex-wrap: wrap;
142
+ height: 58px;
143
+ max-height: 58px;
144
+ }
145
+
146
+ .bp-hello-social-cta,
147
+ .bp-hello-social-links {
148
+ -ms-flex-preferred-size: 50%;
149
+ flex-basis: 50%;
150
+ }
151
+
152
+ .bp-hello-social-links ul {
153
+ display: inline-block;
154
+ }
155
+
156
+ .bp-hello-social li {
157
+ position: relative;
158
+ bottom: -5px;
159
+ display: inline-block;
160
+ list-style-type: none;
161
+ margin-bottom: 0;
162
+ }
163
+
164
+ .bp-hello-social li:last-child a {
165
+ margin-left: 4px;
166
+ }
167
+
168
+ /*
169
+ * 3.3 - Modal header
170
+ */
171
+ .bp-hello-header {
172
+ height: 58px;
173
+ max-height: 58px;
174
+ }
175
+
176
+ /*
177
+ * 3.4 - Modal content
178
+ */
179
+ .bp-hello-content {
180
+ padding: 0 25px;
181
+ height: calc(100% - 58px);
182
+ overflow-y: auto;
183
+ -webkit-overflow-scrolling: touch;
184
+ }
185
+
186
+ /*------------------------------------------------------------------------------
187
+ * 4.0 - Content styles
188
+ *----------------------------------------------------------------------------*/
189
+ /*
190
+ * 4.1 - Backdrop and container
191
+ */
192
+ #bp-hello-backdrop {
193
+ background-color: rgba(0, 0, 0, 0.8);
194
+ -webkit-transition: opacity 0.15s ease-out;
195
+ -o-transition: opacity 0.15s ease-out;
196
+ transition: opacity 0.15s ease-out;
197
+ }
198
+
199
+ #bp-hello-container {
200
+ background-color: white;
201
+ }
202
+
203
+ /*
204
+ * 4.2 - Footer content
205
+ */
206
+ .bp-hello-footer {
207
+ border-radius: 0 0 3px 3px;
208
+ background-color: white;
209
+ border-top: 1px solid var(--bp-hello-color-secondary);
210
+ padding: 6px 25px;
211
+ }
212
+
213
+ .bp-hello-footer p {
214
+ font-size: 15px;
215
+ }
216
+
217
+ .bp-hello-social-cta {
218
+ text-align: left;
219
+ }
220
+
221
+ .bp-hello-social-links {
222
+ text-align: right;
223
+ }
224
+
225
+ .bp-hello-social li a {
226
+ text-decoration: none;
227
+ }
228
+
229
+ /*
230
+ * 4.3 - Header content
231
+ */
232
+ .bp-hello-header {
233
+ padding: 6px 25px;
234
+ }
235
+
236
+ .bp-hello-header h1 {
237
+ width: calc(100% - 51px);
238
+ }
239
+
240
+ #bp-hello-container .bp-hello-header {
241
+ border-bottom: 1px solid var(--bp-hello-color-secondary);
242
+ }
243
+
244
+ .bp-hello-title {
245
+ text-align: left;
246
+ }
247
+
248
+ .bp-hello-close {
249
+ position: absolute;
250
+ top: 20px;
251
+ right: 25px;
252
+ text-align: right;
253
+ }
254
+
255
+ /*
256
+ * 4.4 - Content content
257
+ */
258
+ .bp-hello-content {
259
+ background-color: white;
260
+ }
261
+
262
+ /*------------------------------------------------------------------------------
263
+ * 5.0 - Media
264
+ *----------------------------------------------------------------------------*/
265
+ .bp-hello-content img {
266
+ border-radius: 2px;
267
+ max-width: 100%;
268
+ }
269
+
270
+ .bp-hello-content iframe {
271
+ width: 100%;
272
+ }
273
+
274
+ /*------------------------------------------------------------------------------
275
+ * 6.0 - Media Queries
276
+ *----------------------------------------------------------------------------*/
277
+ /*
278
+ * 6.1 - Desktop Medium
279
+ */
280
+ @media only screen and (min-width: 1024px) {
281
+ #bp-hello-backdrop {
282
+ display: block;
283
+ }
284
+ #bp-hello-container {
285
+ position: fixed;
286
+ top: 60px;
287
+ left: var(--bp-hello-container-size);
288
+ right: var(--bp-hello-container-size);
289
+ bottom: 30px;
290
+ z-index: 9999;
291
+ border-radius: 3px;
292
+ }
293
+ #bp-hello-container .bp-hello-header h1 {
294
+ line-height: inherit;
295
+ }
296
+ .bp-hello-header {
297
+ height: auto;
298
+ max-height: inherit;
299
+ padding: 6px 30px;
300
+ }
301
+ .bp-hello-close {
302
+ right: 30px;
303
+ }
304
+ .bp-hello-close .close-modal:before {
305
+ line-height: 0.7;
306
+ }
307
+ .bp-hello-footer {
308
+ position: fixed;
309
+ left: var(--bp-hello-container-size);
310
+ right: var(--bp-hello-container-size);
311
+ bottom: 30px;
312
+ z-index: 10000;
313
+ height: auto;
314
+ max-height: inherit;
315
+ padding: 6px 30px;
316
+ }
317
+ .bp-hello-content {
318
+ height: calc(100% - 90px);
319
+ padding: 0 30px;
320
+ }
321
+ .bp-hello-content p {
322
+ font-size: 14px;
323
+ }
324
+ }
325
+
326
+ /**
327
+ * 6.2 - Desktop Large
328
+ */
329
+ @media screen and (min-width: 1280px) {
330
+ #bp-hello-container,
331
+ .bp-hello-footer {
332
+ left: calc((100% - 896px) / 2);
333
+ right: calc((100% - 896px) / 2);
334
+ }
335
+ }
bp-core/admin/css/hello.min.css ADDED
@@ -0,0 +1 @@
 
1
+ :root{--bp-hello-color-primary:#d34600;--bp-hello-color-secondary:#e5e5e5;--bp-hello-container-size:15%}#bp-hello-container a{color:var(--bp-hello-color-primary)}#bp-hello-container a:hover{-webkit-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;color:#000}#bp-hello-container .bp-hello-header h1{line-height:1.7;font-size:21px;font-weight:400}.bp-hello-content p{font-size:16px}.bp-hello-close .button{padding:5px!important}.bp-hello-close .close-modal:before{content:"\f158";color:#23282d;font:400 1.5em/1 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-image:none!important}.bp-hello-close .close-modal:focus:before,.bp-hello-close .close-modal:hover:before{-webkit-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;color:var(--bp-hello-color-primary)}.bp-hello-social li a:before{color:#23282d;font:400 30px/.6 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-image:none!important}.bp-hello-social li a:hover:before{-webkit-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;color:var(--bp-hello-color-primary)}.bp-hello-social li a.support:before{content:"\f448"}.bp-hello-social li a.twitter:before{content:"\f301"}#bp-hello-backdrop{position:fixed;top:0;left:0;right:0;bottom:0;z-index:9998;display:none}#bp-hello-container{position:fixed;top:0;bottom:80px;z-index:99999}.bp-disable-scroll{overflow:hidden}.bp-hello-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;height:58px;max-height:58px}.bp-hello-social-cta,.bp-hello-social-links{-ms-flex-preferred-size:50%;flex-basis:50%}.bp-hello-social-links ul{display:inline-block}.bp-hello-social li{position:relative;bottom:-5px;display:inline-block;list-style-type:none;margin-bottom:0}.bp-hello-social li:last-child a{margin-left:4px}.bp-hello-header{height:58px;max-height:58px}.bp-hello-content{padding:0 25px;height:calc(100% - 58px);overflow-y:auto;-webkit-overflow-scrolling:touch}#bp-hello-backdrop{background-color:rgba(0,0,0,.8);-webkit-transition:opacity .15s ease-out;-o-transition:opacity .15s ease-out;transition:opacity .15s ease-out}#bp-hello-container{background-color:#fff}.bp-hello-footer{border-radius:0 0 3px 3px;background-color:#fff;border-top:1px solid var(--bp-hello-color-secondary);padding:6px 25px}.bp-hello-footer p{font-size:15px}.bp-hello-social-cta{text-align:left}.bp-hello-social-links{text-align:right}.bp-hello-social li a{text-decoration:none}.bp-hello-header{padding:6px 25px}.bp-hello-header h1{width:calc(100% - 51px)}#bp-hello-container .bp-hello-header{border-bottom:1px solid var(--bp-hello-color-secondary)}.bp-hello-title{text-align:left}.bp-hello-close{position:absolute;top:20px;right:25px;text-align:right}.bp-hello-content{background-color:#fff}.bp-hello-content img{border-radius:2px;max-width:100%}.bp-hello-content iframe{width:100%}@media only screen and (min-width:1024px){#bp-hello-backdrop{display:block}#bp-hello-container{position:fixed;top:60px;left:var(--bp-hello-container-size);right:var(--bp-hello-container-size);bottom:30px;z-index:9999;border-radius:3px}#bp-hello-container .bp-hello-header h1{line-height:inherit}.bp-hello-header{height:auto;max-height:inherit;padding:6px 30px}.bp-hello-close{right:30px}.bp-hello-close .close-modal:before{line-height:.7}.bp-hello-footer{position:fixed;left:var(--bp-hello-container-size);right:var(--bp-hello-container-size);bottom:30px;z-index:10000;height:auto;max-height:inherit;padding:6px 30px}.bp-hello-content{height:calc(100% - 90px);padding:0 30px}.bp-hello-content p{font-size:14px}}@media screen and (min-width:1280px){#bp-hello-container,.bp-hello-footer{left:calc((100% - 896px)/ 2);right:calc((100% - 896px)/ 2)}}
bp-core/admin/js/hello.js ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Loads for BuddyPress Hello in wp-admin for query string `hello=buddypress`.
3
+ *
4
+ * @since 3.0.0
5
+ */
6
+ (function() {
7
+ /**
8
+ * Open the BuddyPress Hello modal.
9
+ */
10
+ var bp_hello_open_modal = function() {
11
+ var backdrop = document.getElementById( 'bp-hello-backdrop' ),
12
+ modal = document.getElementById( 'bp-hello-container' );
13
+
14
+ document.body.classList.add( 'bp-disable-scroll' );
15
+
16
+ // Show modal and overlay.
17
+ backdrop.style.display = '';
18
+ modal.style.display = '';
19
+
20
+ // Focus the "X" so bp_hello_handle_keyboard_events() works.
21
+ var focus_target = modal.querySelectorAll( 'a[href], button' );
22
+ focus_target = Array.prototype.slice.call( focus_target );
23
+ focus_target[0].focus();
24
+
25
+ // Events.
26
+ modal.addEventListener( 'keydown', bp_hello_handle_keyboard_events );
27
+ backdrop.addEventListener( 'click', bp_hello_close_modal );
28
+ };
29
+
30
+ /**
31
+ * Close modal if "X" or background is touched.
32
+ *
33
+ * @param {Event} event - A click event.
34
+ */
35
+ document.addEventListener( 'click', function( event ) {
36
+ var backdrop = document.getElementById( 'bp-hello-backdrop' );
37
+ if ( ! backdrop || ! document.getElementById( 'bp-hello-container' ) ) {
38
+ return;
39
+ }
40
+
41
+ var backdrop_click = backdrop.contains( event.target ),
42
+ modal_close_click = event.target.classList.contains( 'close-modal' );
43
+
44
+ if ( ! modal_close_click && ! backdrop_click ) {
45
+ return;
46
+ }
47
+
48
+ bp_hello_close_modal();
49
+ }, false );
50
+
51
+ /**
52
+ * Close the Hello modal.
53
+ */
54
+ var bp_hello_close_modal = function() {
55
+ var backdrop = document.getElementById( 'bp-hello-backdrop' ),
56
+ modal = document.getElementById( 'bp-hello-container' );
57
+
58
+ document.body.classList.remove( 'bp-disable-scroll' );
59
+
60
+ // Remove modal and overlay.
61
+ modal.parentNode.removeChild( modal );
62
+ backdrop.parentNode.removeChild( backdrop );
63
+ };
64
+
65
+ /**
66
+ * Restrict keyboard focus to elements within the BuddyPress Hello modal.
67
+ *
68
+ * @param {Event} event - A keyboard focus event.
69
+ */
70
+ var bp_hello_handle_keyboard_events = function( event ) {
71
+ var modal = document.getElementById( 'bp-hello-container' ),
72
+ focus_targets = Array.prototype.slice.call(
73
+ modal.querySelectorAll( 'a[href], button' )
74
+ ),
75
+ first_tab_stop = focus_targets[0],
76
+ last_tab_stop = focus_targets[ focus_targets.length - 1 ];
77
+
78
+ // Check for TAB key press.
79
+ if ( event.keyCode !== 9 ) {
80
+ return;
81
+ }
82
+
83
+ // When SHIFT+TAB on first tab stop, go to last tab stop in modal.
84
+ if ( event.shiftKey && document.activeElement === first_tab_stop ) {
85
+ event.preventDefault();
86
+ last_tab_stop.focus();
87
+
88
+ // When TAB reaches last tab stop, go to first tab stop in modal.
89
+ } else if ( document.activeElement === last_tab_stop ) {
90
+ event.preventDefault();
91
+ first_tab_stop.focus();
92
+ }
93
+ };
94
+
95
+ /**
96
+ * Close modal if escape key is presssed.
97
+ *
98
+ * @param {Event} event - A keyboard focus event.
99
+ */
100
+ document.addEventListener( 'keyup', function( event ) {
101
+ if ( event.keyCode === 27 ) {
102
+ if ( ! document.getElementById( 'bp-hello-backdrop' ) || ! document.getElementById( 'bp-hello-container' ) ) {
103
+ return;
104
+ }
105
+
106
+ bp_hello_close_modal();
107
+ }
108
+ }, false );
109
+
110
+ // Init modal after the screen's loaded.
111
+ if ( document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading' ) {
112
+ bp_hello_open_modal();
113
+ } else {
114
+ document.addEventListener( 'DOMContentLoaded', bp_hello_open_modal );
115
+ }
116
+ }());
bp-core/admin/js/hello.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(){var e=function(){var e=document.getElementById("bp-hello-backdrop"),o=document.getElementById("bp-hello-container");document.body.classList.add("bp-disable-scroll"),e.style.display="",o.style.display="";var l=o.querySelectorAll("a[href], button");(l=Array.prototype.slice.call(l))[0].focus(),o.addEventListener("keydown",n),e.addEventListener("click",t)};document.addEventListener("click",function(e){var n=document.getElementById("bp-hello-backdrop");if(n&&document.getElementById("bp-hello-container")){var o=n.contains(e.target);(e.target.classList.contains("close-modal")||o)&&t()}},!1);var t=function(){var e=document.getElementById("bp-hello-backdrop"),t=document.getElementById("bp-hello-container");document.body.classList.remove("bp-disable-scroll"),t.parentNode.removeChild(t),e.parentNode.removeChild(e)},n=function(e){var t=document.getElementById("bp-hello-container"),n=Array.prototype.slice.call(t.querySelectorAll("a[href], button")),o=n[0],l=n[n.length-1];9===e.keyCode&&(e.shiftKey&&document.activeElement===o?(e.preventDefault(),l.focus()):document.activeElement===l&&(e.preventDefault(),o.focus()))};document.addEventListener("keyup",function(e){if(27===e.keyCode){if(!document.getElementById("bp-hello-backdrop")||!document.getElementById("bp-hello-container"))return;t()}},!1),(document.attachEvent?"complete"===document.readyState:"loading"!==document.readyState)?e():document.addEventListener("DOMContentLoaded",e)}();
bp-core/admin/sass/hello.scss ADDED
@@ -0,0 +1,399 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*------------------------------------------------------------------------------
2
+ Loaded in wp-admin for query string `hello=buddypress`.
3
+
4
+ @since 3.0.0
5
+
6
+ --------------------------------------------------------------------------------
7
+ TABLE OF CONTENTS:
8
+ --------------------------------------------------------------------------------
9
+ 1.0 - Typography and colour
10
+ 2.0 - Dashicons
11
+ 3.0 - Elements
12
+ 3.1 - Backdrop and container
13
+ 3.2 - Modal footer
14
+ 3.3 - Modal header
15
+ 3.4 - Modal content
16
+ 4.0 - Content styles
17
+ 4.1 - Backdrop and container
18
+ 4.2 - Footer content
19
+ 4.3 - Header content
20
+ 4.4 - Content content
21
+ 5.0 - Media
22
+ 6.0 - Media Queries
23
+ 6.1 - Desktop Medium
24
+ 6.2 - Desktop Large
25
+ ------------------------------------------------------------------------------*/
26
+
27
+ /*------------------------------------------------------------------------------
28
+ * 1.0 - Typography and colour
29
+ *----------------------------------------------------------------------------*/
30
+ :root {
31
+ --bp-hello-color-primary: #d34600;
32
+ --bp-hello-color-secondary: #e5e5e5;
33
+ --bp-hello-container-size: 15%;
34
+ }
35
+
36
+ #bp-hello-container {
37
+
38
+ a {
39
+ color: var(--bp-hello-color-primary);
40
+
41
+ &:hover {
42
+ -webkit-transition: all 0.1s ease-in-out;
43
+ -o-transition: all 0.1s ease-in-out;
44
+ transition: all 0.1s ease-in-out;
45
+ color: rgb(0, 0, 0);
46
+ }
47
+ }
48
+
49
+ .bp-hello-header {
50
+
51
+ h1 {
52
+ line-height: 1.7;
53
+ font-size: 21px;
54
+ font-weight: 400;
55
+ }
56
+ }
57
+ }
58
+
59
+ .bp-hello-content {
60
+
61
+ p {
62
+ font-size: 16px;
63
+ }
64
+ }
65
+
66
+ /*------------------------------------------------------------------------------
67
+ * 2.0 - Dashicons
68
+ *----------------------------------------------------------------------------*/
69
+ .bp-hello-close {
70
+
71
+ .button {
72
+ padding: 5px !important;
73
+ }
74
+
75
+ .close-modal {
76
+
77
+ &:before {
78
+ content: "\f158";
79
+ color: #23282d; /* wp toolbar */
80
+ font: 400 1.5em/1 dashicons;
81
+ speak: none;
82
+ -webkit-font-smoothing: antialiased;
83
+ -moz-osx-font-smoothing: grayscale;
84
+ background-image: none !important;
85
+ }
86
+
87
+ &:focus:before,
88
+ &:hover:before {
89
+ -webkit-transition: all 0.1s ease-in-out;
90
+ -o-transition: all 0.1s ease-in-out;
91
+ transition: all 0.1s ease-in-out;
92
+ color: var(--bp-hello-color-primary);
93
+ }
94
+ }
95
+ }
96
+
97
+ .bp-hello-social {
98
+
99
+ li a {
100
+
101
+ &:before {
102
+ color: #23282d; /* wp toolbar */
103
+ font: 400 30px/0.6 dashicons;
104
+ speak: none;
105
+ -webkit-font-smoothing: antialiased;
106
+ -moz-osx-font-smoothing: grayscale;
107
+ background-image: none !important;
108
+ }
109
+
110
+ &:hover:before {
111
+ -webkit-transition: all 0.1s ease-in-out;
112
+ -o-transition: all 0.1s ease-in-out;
113
+ transition: all 0.1s ease-in-out;
114
+ color: var(--bp-hello-color-primary);
115
+ }
116
+
117
+ &.support:before {
118
+ content: "\f448";
119
+ }
120
+
121
+ &.twitter:before {
122
+ content: "\f301";
123
+ }
124
+ }
125
+ }
126
+
127
+ /*------------------------------------------------------------------------------
128
+ * 3.0 - Elements
129
+ *----------------------------------------------------------------------------*/
130
+
131
+ /*
132
+ * 3.1 - Backdrop and container
133
+ */
134
+ #bp-hello-backdrop {
135
+ position: fixed;
136
+ top: 0;
137
+ left: 0;
138
+ right: 0;
139
+ bottom: 0;
140
+ z-index: 9998;
141
+
142
+ display: none;
143
+ }
144
+
145
+ #bp-hello-container {
146
+ position: fixed;
147
+ top: 0;
148
+ bottom: 80px;
149
+ z-index: 99999;
150
+ }
151
+
152
+ .bp-disable-scroll {
153
+ overflow: hidden;
154
+ }
155
+
156
+ /*
157
+ * 3.2 - Modal footer
158
+ */
159
+ .bp-hello-footer {
160
+ display: -webkit-box;
161
+ display: -ms-flexbox;
162
+ display: flex;
163
+ -ms-flex-wrap: wrap;
164
+ flex-wrap: wrap;
165
+
166
+ height: 58px;
167
+ max-height: 58px;
168
+ }
169
+
170
+ .bp-hello-social-cta,
171
+ .bp-hello-social-links {
172
+ -ms-flex-preferred-size: 50%;
173
+ flex-basis: 50%;
174
+ }
175
+
176
+ .bp-hello-social-links {
177
+
178
+ ul {
179
+ display: inline-block;
180
+ }
181
+ }
182
+
183
+ .bp-hello-social {
184
+
185
+ li {
186
+ position: relative;
187
+ bottom: -5px;
188
+ display: inline-block;
189
+ list-style-type: none;
190
+ margin-bottom: 0;
191
+
192
+ &:last-child a {
193
+ margin-left: 4px;
194
+ }
195
+ }
196
+ }
197
+
198
+ /*
199
+ * 3.3 - Modal header
200
+ */
201
+ .bp-hello-header {
202
+ height: 58px;
203
+ max-height: 58px;
204
+ }
205
+
206
+ /*
207
+ * 3.4 - Modal content
208
+ */
209
+ .bp-hello-content {
210
+ padding: 0 25px;
211
+
212
+ // Force scrolling.
213
+ height: calc(100% - 58px);
214
+ overflow-y: auto;
215
+ -webkit-overflow-scrolling: touch;
216
+ }
217
+
218
+ /*------------------------------------------------------------------------------
219
+ * 4.0 - Content styles
220
+ *----------------------------------------------------------------------------*/
221
+
222
+ /*
223
+ * 4.1 - Backdrop and container
224
+ */
225
+ #bp-hello-backdrop {
226
+ background-color: rgba(0, 0, 0, 0.8);
227
+ -webkit-transition: opacity 0.15s ease-out;
228
+ -o-transition: opacity 0.15s ease-out;
229
+ transition: opacity 0.15s ease-out;
230
+ }
231
+
232
+ #bp-hello-container {
233
+ background-color: rgb(255, 255, 255);
234
+ }
235
+
236
+ /*
237
+ * 4.2 - Footer content
238
+ */
239
+ .bp-hello-footer {
240
+ border-radius: 0 0 3px 3px;
241
+ background-color: rgb(255, 255, 255);
242
+ border-top: 1px solid var(--bp-hello-color-secondary);
243
+ padding: 6px 25px;
244
+
245
+ p {
246
+ font-size: 15px;
247
+ }
248
+ }
249
+
250
+ .bp-hello-social-cta {
251
+ text-align: left;
252
+ }
253
+
254
+ .bp-hello-social-links {
255
+ text-align: right;
256
+ }
257
+
258
+ .bp-hello-social {
259
+
260
+ li {
261
+
262
+ a {
263
+ text-decoration: none;
264
+ }
265
+ }
266
+ }
267
+
268
+ /*
269
+ * 4.3 - Header content
270
+ */
271
+ .bp-hello-header {
272
+ padding: 6px 25px;
273
+
274
+ h1 {
275
+ width: calc(100% - 51px); // Approx. width of "X" button block.
276
+ }
277
+ }
278
+
279
+ #bp-hello-container {
280
+
281
+ .bp-hello-header {
282
+ border-bottom: 1px solid var(--bp-hello-color-secondary);
283
+ }
284
+ }
285
+
286
+ .bp-hello-title {
287
+ text-align: left;
288
+ }
289
+
290
+ .bp-hello-close {
291
+ position: absolute;
292
+ top: 20px;
293
+ right: 25px;
294
+ text-align: right;
295
+ }
296
+
297
+ /*
298
+ * 4.4 - Content content
299
+ */
300
+ .bp-hello-content {
301
+ background-color: rgb(255, 255, 255);
302
+ }
303
+
304
+ /*------------------------------------------------------------------------------
305
+ * 5.0 - Media
306
+ *----------------------------------------------------------------------------*/
307
+ .bp-hello-content {
308
+
309
+ img {
310
+ border-radius: 2px;
311
+ max-width: 100%;
312
+ }
313
+
314
+ iframe {
315
+ width: 100%;
316
+ }
317
+ }
318
+
319
+ /*------------------------------------------------------------------------------
320
+ * 6.0 - Media Queries
321
+ *----------------------------------------------------------------------------*/
322
+
323
+ /*
324
+ * 6.1 - Desktop Medium
325
+ */
326
+ @media only screen and (min-width: 1024px) {
327
+
328
+ #bp-hello-backdrop {
329
+ display: block;
330
+ }
331
+
332
+ #bp-hello-container {
333
+ position: fixed;
334
+ top: 60px;
335
+ left: var(--bp-hello-container-size);
336
+ right: var(--bp-hello-container-size);
337
+ bottom: 30px;
338
+ z-index: 9999;
339
+
340
+ border-radius: 3px;
341
+
342
+ .bp-hello-header {
343
+
344
+ h1 {
345
+ line-height: inherit;
346
+ }
347
+ }
348
+ }
349
+
350
+ .bp-hello-header {
351
+ height: auto;
352
+ max-height: inherit;
353
+ padding: 6px 30px;
354
+ }
355
+
356
+ .bp-hello-close {
357
+ right: 30px;
358
+
359
+ .close-modal:before {
360
+ line-height: 0.7;
361
+ }
362
+ }
363
+
364
+ .bp-hello-footer {
365
+ position: fixed; // Fixed position above "content" div.
366
+ left: var(--bp-hello-container-size);
367
+ right: var(--bp-hello-container-size);
368
+ bottom: 30px;
369
+ z-index: 10000; // See #bp-hello-backdrop
370
+
371
+ height: auto;
372
+ max-height: inherit;
373
+
374
+ padding: 6px 30px;
375
+ }
376
+
377
+ .bp-hello-content {
378
+ // Very very approx. height of header and footer.
379
+ height: calc(100% - 90px);
380
+ padding: 0 30px;
381
+
382
+ p {
383
+ font-size: 14px;
384
+ }
385
+ }
386
+ }
387
+
388
+ /**
389
+ * 6.2 - Desktop Large
390
+ */
391
+ @media screen and (min-width: 1280px) {
392
+
393
+ #bp-hello-container,
394
+ .bp-hello-footer {
395
+ // Approx. max-width of modal at Desktop Medium size.
396
+ left: calc((100% - 896px) / 2);
397
+ right: calc((100% - 896px) / 2);
398
+ }
399
+ }
bp-core/bp-core-actions.php CHANGED
@@ -85,6 +85,14 @@ add_action( 'bp_init', 'bp_add_permastructs', 40 );
85
  */
86
  add_action( 'bp_register_taxonomies', 'bp_register_member_types' );
87
 
 
 
 
 
 
 
 
 
88
  /**
89
  * The bp_template_redirect hook - Attached to 'template_redirect' above.
90
  *
@@ -105,8 +113,9 @@ add_action( 'bp_template_redirect', 'bp_get_request', 10 );
105
  /**
106
  * Add the BuddyPress functions file and the Theme Compat Default features.
107
  */
108
- add_action( 'bp_after_setup_theme', 'bp_load_theme_functions', 1 );
109
- add_action( 'bp_after_setup_theme', 'bp_register_theme_compat_default_features', 10 );
 
110
 
111
  // Load the admin.
112
  if ( is_admin() ) {
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() ) {
bp-core/bp-core-adminbar.php CHANGED
@@ -47,8 +47,6 @@ 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
- * @global string $wp_version
52
  */
53
  function bp_core_load_admin_bar() {
54
 
47
  * Handle the Toolbar/BuddyBar business.
48
  *
49
  * @since 1.2.0
 
 
50
  */
51
  function bp_core_load_admin_bar() {
52
 
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
  /**
@@ -83,6 +84,58 @@ function bp_attachments_uploads_dir_get( $data = '' ) {
83
  return apply_filters( 'bp_attachments_uploads_dir_get', $retval, $data );
84
  }
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  /**
87
  * Get the max upload file size for any attachment.
88
  *
@@ -312,7 +365,7 @@ function bp_attachments_create_item_type( $type = 'avatar', $args = array() ) {
312
  $attachment_data = call_user_func_array( $r['component'] . '_avatar_upload_dir', $dir_args );
313
  }
314
  } elseif ( 'cover_image' === $type ) {
315
- $attachment_data = bp_attachments_uploads_dir_get();
316
 
317
  // The BP Attachments Uploads Dir is not set, stop.
318
  if ( ! $attachment_data ) {
@@ -921,23 +974,25 @@ function bp_attachments_json_response( $success, $is_html4 = false, $data = null
921
  * @return bool
922
  */
923
  function bp_attachments_get_template_part( $slug ) {
924
- $attachment_template_part = 'assets/_attachments/' . $slug;
925
-
926
- // Load the attachment template in WP Administration screens.
927
- if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
928
- $attachment_admin_template_part = buddypress()->themes_dir . '/bp-legacy/buddypress/' . $attachment_template_part . '.php';
929
 
930
- // Check whether the template part exists.
931
- if ( ! file_exists( $attachment_admin_template_part ) ) {
932
- return false;
 
 
 
 
 
 
933
  }
 
934
 
935
- // Load the template part.
936
- require( $attachment_admin_template_part );
937
 
938
- // Load the attachment template in WP_USE_THEMES env.
939
- } else {
940
- bp_get_template_part( $attachment_template_part );
941
  }
942
  }
943
 
@@ -1130,8 +1185,10 @@ function bp_attachments_cover_image_generate_file( $args = array(), $cover_image
1130
  $cover_image_class = new BP_Attachment_Cover_Image();
1131
  }
1132
 
 
 
1133
  // Make sure the file is inside the Cover Image Upload path.
1134
- if ( false === strpos( $args['file'], $cover_image_class->upload_path ) ) {
1135
  return false;
1136
  }
1137
 
@@ -1189,36 +1246,27 @@ function bp_attachments_cover_image_generate_file( $args = array(), $cover_image
1189
  * error message otherwise.
1190
  */
1191
  function bp_attachments_cover_image_ajax_upload() {
1192
- // Bail if not a POST action.
1193
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1194
  wp_die();
1195
  }
1196
 
1197
- /**
1198
- * Sending the json response will be different if
1199
- * the current Plupload runtime is html4
1200
- */
1201
- $is_html4 = false;
1202
- if ( ! empty( $_POST['html4' ] ) ) {
1203
- $is_html4 = true;
1204
- }
1205
-
1206
- // Check the nonce.
1207
  check_admin_referer( 'bp-uploader' );
1208
 
1209
- // Init the BuddyPress parameters.
1210
- $bp_params = array();
1211
 
1212
- // We need it to carry on.
1213
- if ( ! empty( $_POST['bp_params'] ) ) {
1214
- $bp_params = bp_parse_args( $_POST['bp_params'], array(
1215
- 'object' => 'user',
1216
- 'item_id' => bp_loggedin_user_id(),
1217
- ), 'attachments_cover_image_ajax_upload' );
1218
- } else {
1219
  bp_attachments_json_response( false, $is_html4 );
1220
  }
1221
 
 
 
 
 
 
 
 
 
1222
  // We need the object to set the uploads dir filter.
1223
  if ( empty( $bp_params['object'] ) ) {
1224
  bp_attachments_json_response( false, $is_html4 );
@@ -1297,11 +1345,9 @@ function bp_attachments_cover_image_ajax_upload() {
1297
  ) );
1298
  }
1299
 
1300
- // Default error message.
1301
  $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
1302
 
1303
- // Get BuddyPress Attachments Uploads Dir datas.
1304
- $bp_attachments_uploads_dir = bp_attachments_uploads_dir_get();
1305
 
1306
  // The BP Attachments Uploads Dir is not set, stop.
1307
  if ( ! $bp_attachments_uploads_dir ) {
@@ -1322,10 +1368,10 @@ function bp_attachments_cover_image_ajax_upload() {
1322
  ) );
1323
  }
1324
 
1325
- /**
1326
  * Generate the cover image so that it fit to feature's dimensions
1327
  *
1328
- * Unlike the Avatar, Uploading and generating the cover image is happening during
1329
  * the same Ajax request, as we already instantiated the BP_Attachment_Cover_Image
1330
  * class, let's use it.
1331
  */
@@ -1336,17 +1382,15 @@ function bp_attachments_cover_image_ajax_upload() {
1336
  ), $cover_image_attachment );
1337
 
1338
  if ( ! $cover ) {
1339
- // Upload error response.
1340
  bp_attachments_json_response( false, $is_html4, array(
1341
  'type' => 'upload_error',
1342
  'message' => $error_message,
1343
  ) );
1344
  }
1345
 
1346
- // Build the url to the file.
1347
  $cover_url = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $cover_subdir . '/' . $cover['cover_basename'];
1348
 
1349
- // Init Feedback code, 1 is success.
1350
  $feedback_code = 1;
1351
 
1352
  // 0 is the size warning.
@@ -1368,10 +1412,20 @@ function bp_attachments_cover_image_ajax_upload() {
1368
  * code once the user has set his cover image.
1369
  *
1370
  * @since 2.4.0
 
1371
  *
1372
- * @param int $item_id Inform about the item id the cover image was set for.
 
 
 
1373
  */
1374
- do_action( $object_data['component'] . '_cover_image_uploaded', (int) $bp_params['item_id'] );
 
 
 
 
 
 
1375
 
1376
  // Finally return the cover image url to the UI.
1377
  bp_attachments_json_response( true, $is_html4, array(
@@ -1391,8 +1445,7 @@ add_action( 'wp_ajax_bp_cover_image_upload', 'bp_attachments_cover_image_ajax_up
1391
  * error message otherwise.
1392
  */
1393
  function bp_attachments_cover_image_ajax_delete() {
1394
- // Bail if not a POST action.
1395
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1396
  wp_send_json_error();
1397
  }
1398
 
@@ -1438,10 +1491,9 @@ function bp_attachments_cover_image_ajax_delete() {
1438
  */
1439
  do_action( "{$component}_cover_image_deleted", (int) $args['item_id'] );
1440
 
1441
- // Defaults no cover image.
1442
  $response = array(
1443
  'reset_url' => '',
1444
- 'feedback_code' => 3 ,
1445
  );
1446
 
1447
  // Get cover image settings in case there's a default header.
@@ -1452,7 +1504,6 @@ function bp_attachments_cover_image_ajax_delete() {
1452
  $response['reset_url'] = $cover_params['default_cover'];
1453
  }
1454
 
1455
- // Finally send the reset url.
1456
  wp_send_json_success( $response );
1457
 
1458
  } 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
  /**
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
  *
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 ) {
974
  * @return bool
975
  */
976
  function bp_attachments_get_template_part( $slug ) {
977
+ $switched = false;
 
 
 
 
978
 
979
+ /*
980
+ * Use bp-legacy attachment template part for older bp-default themes or if in
981
+ * admin area.
982
+ */
983
+ if ( ! bp_use_theme_compat_with_current_theme() || ( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) ) {
984
+ $current = bp_get_theme_compat_id();
985
+ if ( 'legacy' !== $current ) {
986
+ $switched = true;
987
+ bp_setup_theme_compat( 'legacy' );
988
  }
989
+ }
990
 
991
+ // Load the template part.
992
+ bp_get_template_part( 'assets/_attachments/' . $slug );
993
 
994
+ if ( $switched ) {
995
+ bp_setup_theme_compat( $current );
 
996
  }
997
  }
998
 
1185
  $cover_image_class = new BP_Attachment_Cover_Image();
1186
  }
1187
 
1188
+ $upload_dir = bp_attachments_cover_image_upload_dir();
1189
+
1190
  // Make sure the file is inside the Cover Image Upload path.
1191
+ if ( false === strpos( $args['file'], $upload_dir['basedir'] ) ) {
1192
  return false;
1193
  }
1194
 
1246
  * error message otherwise.
1247
  */
1248
  function bp_attachments_cover_image_ajax_upload() {
1249
+ if ( ! bp_is_post_request() ) {
 
1250
  wp_die();
1251
  }
1252
 
 
 
 
 
 
 
 
 
 
 
1253
  check_admin_referer( 'bp-uploader' );
1254
 
1255
+ // Sending the json response will be different if the current Plupload runtime is html4.
1256
+ $is_html4 = ! empty( $_POST['html4' ] );
1257
 
1258
+ if ( empty( $_POST['bp_params'] ) ) {
 
 
 
 
 
 
1259
  bp_attachments_json_response( false, $is_html4 );
1260
  }
1261
 
1262
+ $bp_params = bp_parse_args( $_POST['bp_params'], array(
1263
+ 'object' => 'user',
1264
+ 'item_id' => bp_loggedin_user_id(),
1265
+ ), 'attachments_cover_image_ajax_upload' );
1266
+
1267
+ $bp_params['item_id'] = (int) $bp_params['item_id'];
1268
+ $bp_params['object'] = sanitize_text_field( $bp_params['object'] );
1269
+
1270
  // We need the object to set the uploads dir filter.
1271
  if ( empty( $bp_params['object'] ) ) {
1272
  bp_attachments_json_response( false, $is_html4 );
1345
  ) );
1346
  }
1347
 
 
1348
  $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
1349
 
1350
+ $bp_attachments_uploads_dir = bp_attachments_cover_image_upload_dir();
 
1351
 
1352
  // The BP Attachments Uploads Dir is not set, stop.
1353
  if ( ! $bp_attachments_uploads_dir ) {
1368
  ) );
1369
  }
1370
 
1371
+ /*
1372
  * Generate the cover image so that it fit to feature's dimensions
1373
  *
1374
+ * Unlike the avatar, uploading and generating the cover image is happening during
1375
  * the same Ajax request, as we already instantiated the BP_Attachment_Cover_Image
1376
  * class, let's use it.
1377
  */
1382
  ), $cover_image_attachment );
1383
 
1384
  if ( ! $cover ) {
 
1385
  bp_attachments_json_response( false, $is_html4, array(
1386
  'type' => 'upload_error',
1387
  'message' => $error_message,
1388
  ) );
1389
  }
1390
 
 
1391
  $cover_url = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $cover_subdir . '/' . $cover['cover_basename'];
1392
 
1393
+ // 1 is success.
1394
  $feedback_code = 1;
1395
 
1396
  // 0 is the size warning.
1412
  * code once the user has set his cover image.
1413
  *
1414
  * @since 2.4.0
1415
+ * @since 3.0.0 Added $cover_url, $name, $feedback_code arguments.
1416
  *
1417
+ * @param int $item_id Inform about the item id the cover image was set for.
1418
+ * @param string $name Filename.
1419
+ * @param string $cover_url URL to the image.
1420
+ * @param int $feedback_code If value not 1, an error occured.
1421
  */
1422
+ do_action(
1423
+ $object_data['component'] . '_cover_image_uploaded',
1424
+ (int) $bp_params['item_id'],
1425
+ $name,
1426
+ $cover_url,
1427
+ $feedback_code
1428
+ );
1429
 
1430
  // Finally return the cover image url to the UI.
1431
  bp_attachments_json_response( true, $is_html4, array(
1445
  * error message otherwise.
1446
  */
1447
  function bp_attachments_cover_image_ajax_delete() {
1448
+ if ( ! bp_is_post_request() ) {
 
1449
  wp_send_json_error();
1450
  }
1451
 
1491
  */
1492
  do_action( "{$component}_cover_image_deleted", (int) $args['item_id'] );
1493
 
 
1494
  $response = array(
1495
  'reset_url' => '',
1496
+ 'feedback_code' => 3,
1497
  );
1498
 
1499
  // Get cover image settings in case there's a default header.
1504
  $response['reset_url'] = $cover_params['default_cover'];
1505
  }
1506
 
 
1507
  wp_send_json_success( $response );
1508
 
1509
  } else {
bp-core/bp-core-avatars.php CHANGED
@@ -809,8 +809,7 @@ function bp_core_delete_existing_avatar( $args = '' ) {
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
 
@@ -952,8 +951,7 @@ function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) {
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
 
@@ -1237,8 +1235,7 @@ function bp_core_avatar_handle_crop( $args = '' ) {
1237
  * error message otherwise.
1238
  */
1239
  function bp_avatar_ajax_set() {
1240
- // Bail if not a POST action.
1241
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1242
  wp_send_json_error();
1243
  }
1244
 
809
  * error message otherwise.
810
  */
811
  function bp_avatar_ajax_delete() {
812
+ if ( ! bp_is_post_request() ) {
 
813
  wp_send_json_error();
814
  }
815
 
951
  * error message otherwise.
952
  */
953
  function bp_avatar_ajax_upload() {
954
+ if ( ! bp_is_post_request() ) {
 
955
  wp_die();
956
  }
957
 
1235
  * error message otherwise.
1236
  */
1237
  function bp_avatar_ajax_set() {
1238
+ if ( ! bp_is_post_request() ) {
 
1239
  wp_send_json_error();
1240
  }
1241
 
bp-core/bp-core-buddybar.php CHANGED
@@ -608,6 +608,9 @@ function bp_core_register_subnav_screen_function( $args = '', $component = 'memb
608
  }
609
 
610
  $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
 
 
 
611
 
612
  // If we *do* meet condition (2), then the added subnav item is currently being requested.
613
  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 ) ) {
@@ -670,10 +673,9 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component
670
 
671
  $bp = buddypress();
672
 
673
- // If a redirect URL has been passed to the subnav
674
- // item, respect it.
675
  if ( ! empty( $subnav_item['no_access_url'] ) ) {
676
- $message = __( 'You do not have access to this page.', 'buddypress' );
677
  $redirect_to = trailingslashit( $subnav_item['no_access_url'] );
678
 
679
  // In the case of a user page, we try to assume a
@@ -689,7 +691,7 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component
689
  // component, as long as that component is
690
  // publicly accessible.
691
  if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
692
- $message = __( 'You do not have access to this page.', 'buddypress' );
693
  $redirect_to = bp_displayed_user_domain();
694
 
695
  // In some cases, the default tab is not accessible to
@@ -717,6 +719,7 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component
717
  'message' => $message,
718
  'root' => $redirect_to,
719
  'redirect' => false,
 
720
  );
721
 
722
  } else {
608
  }
609
 
610
  $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
611
+ if ( is_array( $parent_nav ) ) {
612
+ $parent_nav = reset( $parent_nav );
613
+ }
614
 
615
  // If we *do* meet condition (2), then the added subnav item is currently being requested.
616
  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 ) ) {
673
 
674
  $bp = buddypress();
675
 
676
+ // If a redirect URL has been passed to the subnav item, respect it.
 
677
  if ( ! empty( $subnav_item['no_access_url'] ) ) {
678
+ $message = __( 'You do not have access to that page.', 'buddypress' );
679
  $redirect_to = trailingslashit( $subnav_item['no_access_url'] );
680
 
681
  // In the case of a user page, we try to assume a
691
  // component, as long as that component is
692
  // publicly accessible.
693
  if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
694
+ $message = __( 'You do not have access to that page.', 'buddypress' );
695
  $redirect_to = bp_displayed_user_domain();
696
 
697
  // In some cases, the default tab is not accessible to
719
  'message' => $message,
720
  'root' => $redirect_to,
721
  'redirect' => false,
722
+ 'mode' => 1
723
  );
724
 
725
  } else {
bp-core/bp-core-cache.php CHANGED
@@ -306,6 +306,23 @@ function bp_core_set_incremented_cache( $key, $group, $ids ) {
306
  return wp_cache_set( $cache_key, $ids, $group );
307
  }
308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  /**
310
  * Gets the key to be used when caching a value using an incremented cache key.
311
  *
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
  *
bp-core/bp-core-customizer-email.php CHANGED
@@ -18,12 +18,6 @@ defined( 'ABSPATH' ) || exit;
18
  * @param WP_Customize_Manager $wp_customize The Customizer object.
19
  */
20
  function bp_email_init_customizer( WP_Customize_Manager $wp_customize ) {
21
-
22
- // Require WP 4.0+.
23
- if ( ! method_exists( $wp_customize, 'add_panel' ) ) {
24
- return;
25
- }
26
-
27
  if ( ! bp_is_email_customizer() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
28
  return;
29
  }
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
  }
bp-core/bp-core-dependency.php CHANGED
@@ -33,6 +33,23 @@ function bp_include() {
33
  do_action( 'bp_include' );
34
  }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  /**
37
  * Fire the 'bp_setup_components' action, where plugins should initialize components.
38
  *
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
  *
bp-core/bp-core-filters.php CHANGED
@@ -101,9 +101,6 @@ function bp_core_exclude_pages( $pages = array() ) {
101
  if ( !empty( $bp->pages->register ) )
102
  $pages[] = $bp->pages->register->id;
103
 
104
- if ( !empty( $bp->pages->forums ) && ( !bp_is_active( 'forums' ) || ( bp_is_active( 'forums' ) && bp_forums_has_directory() && !bp_forums_is_installed_correctly() ) ) )
105
- $pages[] = $bp->pages->forums->id;
106
-
107
  /**
108
  * Filters specific pages that shouldn't show up on page listings.
109
  *
@@ -967,7 +964,7 @@ function bp_email_add_link_color_to_template( $value, $property_name, $transform
967
  }
968
 
969
  $settings = bp_email_get_appearance_settings();
970
- $replacement = 'style="color: ' . esc_attr( $settings['highlight_color'] ) . ';';
971
 
972
  // Find all links.
973
  preg_match_all( '#<a[^>]+>#i', $value, $links, PREG_SET_ORDER );
@@ -1008,7 +1005,7 @@ function bp_email_set_default_headers( $headers, $property, $transform, $email )
1008
  $tokens = $email->get_tokens();
1009
 
1010
  // Add 'List-Unsubscribe' header if applicable.
1011
- if ( ! empty( $tokens['unsubscribe'] ) && $tokens['unsubscribe'] !== site_url( 'wp-login.php' ) ) {
1012
  $user = get_user_by( 'email', $tokens['recipient.email'] );
1013
 
1014
  $link = bp_email_get_unsubscribe_link( array(
@@ -1039,6 +1036,7 @@ add_filter( 'bp_email_get_headers', 'bp_email_set_default_headers', 6, 4 );
1039
  function bp_email_set_default_tokens( $tokens, $property_name, $transform, $email ) {
1040
  $tokens['site.admin-email'] = bp_get_option( 'admin_email' );
1041
  $tokens['site.url'] = home_url();
 
1042
 
1043
  // These options are escaped with esc_html on the way into the database in sanitize_option().
1044
  $tokens['site.description'] = wp_specialchars_decode( bp_get_option( 'blogdescription' ), ENT_QUOTES );
@@ -1050,7 +1048,6 @@ function bp_email_set_default_tokens( $tokens, $property_name, $transform, $emai
1050
  $tokens['recipient.name'] = '';
1051
  $tokens['recipient.username'] = '';
1052
 
1053
-
1054
  // Who is the email going to?
1055
  $recipient = $email->get( 'to' );
1056
  if ( $recipient ) {
@@ -1066,6 +1063,7 @@ function bp_email_set_default_tokens( $tokens, $property_name, $transform, $emai
1066
 
1067
  if ( $user_obj ) {
1068
  $tokens['recipient.username'] = $user_obj->user_login;
 
1069
  if ( bp_is_active( 'settings' ) && empty( $tokens['unsubscribe'] ) ) {
1070
  $tokens['unsubscribe'] = esc_url( sprintf(
1071
  '%s%s/notifications/',
@@ -1078,7 +1076,7 @@ function bp_email_set_default_tokens( $tokens, $property_name, $transform, $emai
1078
 
1079
  // Set default unsubscribe link if not passed.
1080
  if ( empty( $tokens['unsubscribe'] ) ) {
1081
- $tokens['unsubscribe'] = site_url( 'wp-login.php' );
1082
  }
1083
 
1084
  // Email preheader.
@@ -1133,7 +1131,7 @@ function bp_core_render_email_template( $template ) {
1133
 
1134
  // Make sure we add a <title> tag so WP Customizer picks it up.
1135
  $template = str_replace( '<head>', '<head><title>' . esc_html_x( 'BuddyPress Emails', 'screen heading', 'buddypress' ) . '</title>', $template );
1136
- echo str_replace( '{{{content}}}', nl2br( get_post()->post_content ), $template );
1137
 
1138
  /*
1139
  * Link colours are applied directly in the email template before sending, so we
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
  *
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 );
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(
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 );
1048
  $tokens['recipient.name'] = '';
1049
  $tokens['recipient.username'] = '';
1050
 
 
1051
  // Who is the email going to?
1052
  $recipient = $email->get( 'to' );
1053
  if ( $recipient ) {
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/',
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.
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
@@ -445,6 +445,27 @@ function bp_use_wp_admin_bar() {
445
  return (bool) apply_filters( 'bp_use_wp_admin_bar', $use_admin_bar );
446
  }
447
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  /** Directory *****************************************************************/
449
 
450
  /**
@@ -467,12 +488,6 @@ function bp_core_get_packaged_component_ids() {
467
  'notifications',
468
  );
469
 
470
- // Only add legacy forums if it is enabled
471
- // prevents conflicts with bbPress, which also uses the same 'forums' id.
472
- if ( class_exists( 'BP_Forums_Component' ) ) {
473
- $components[] = 'forums';
474
- }
475
-
476
  return $components;
477
  }
478
 
@@ -1022,7 +1037,11 @@ function bp_core_redirect( $location = '', $status = 302 ) {
1022
  buddypress()->no_status_set = true;
1023
 
1024
  wp_safe_redirect( $location, $status );
1025
- die;
 
 
 
 
1026
  }
1027
 
1028
  /**
@@ -1729,26 +1748,6 @@ function bp_use_embed_in_activity_replies() {
1729
  return apply_filters( 'bp_use_embed_in_activity_replies', !defined( 'BP_EMBED_DISABLE_ACTIVITY_REPLIES' ) || !BP_EMBED_DISABLE_ACTIVITY_REPLIES );
1730
  }
1731
 
1732
- /**
1733
- * Are oembeds allowed in forum posts?
1734
- *
1735
- * @since 1.5.0
1736
- *
1737
- * @return bool False when forum post embed support is disabled; true when
1738
- * enabled. Default: true.
1739
- */
1740
- function bp_use_embed_in_forum_posts() {
1741
-
1742
- /**
1743
- * Filters whether or not oEmbeds are allowed in forum posts.
1744
- *
1745
- * @since 1.5.0
1746
- *
1747
- * @param bool $value Whether or not oEmbeds are allowed.
1748
- */
1749
- return apply_filters( 'bp_use_embed_in_forum_posts', !defined( 'BP_EMBED_DISABLE_FORUM_POSTS' ) || !BP_EMBED_DISABLE_FORUM_POSTS );
1750
- }
1751
-
1752
  /**
1753
  * Are oembeds allowed in private messages?
1754
  *
@@ -2355,11 +2354,6 @@ function bp_core_action_search_site( $slug = '' ) {
2355
  $slug = bp_is_active( 'blogs' ) ? bp_get_blogs_root_slug() : '';
2356
  break;
2357
 
2358
- case 'forums':
2359
- $slug = bp_is_active( 'forums' ) ? bp_get_forums_root_slug() : '';
2360
- $query_string = '/?fs=';
2361
- break;
2362
-
2363
  case 'groups':
2364
  $slug = bp_is_active( 'groups' ) ? bp_get_groups_root_slug() : '';
2365
  break;
@@ -2463,10 +2457,6 @@ function bp_core_get_components( $type = 'all' ) {
2463
  );
2464
 
2465
  $retired_components = array(
2466
- 'forums' => array(
2467
- 'title' => __( 'Group Forums', 'buddypress' ),
2468
- 'description' => sprintf( __( 'BuddyPress Forums are retired. Use %s.', 'buddypress' ), '<a href="https://bbpress.org/">bbPress</a>' )
2469
- ),
2470
  );
2471
 
2472
  $optional_components = array(
@@ -2498,10 +2488,6 @@ function bp_core_get_components( $type = 'all' ) {
2498
  'title' => __( 'User Groups', 'buddypress' ),
2499
  'description' => __( 'Groups allow your users to organize themselves into specific public, private or hidden sections with separate activity streams and member listings.', 'buddypress' )
2500
  ),
2501
- 'forums' => array(
2502
- 'title' => __( 'Group Forums (Legacy)', 'buddypress' ),
2503
- 'description' => __( 'Group forums allow for focused, bulletin-board style conversations.', 'buddypress' )
2504
- ),
2505
  'blogs' => array(
2506
  'title' => __( 'Site Tracking', 'buddypress' ),
2507
  'description' => __( 'Record activity for new posts and comments from your site.', 'buddypress' )
@@ -3242,6 +3228,8 @@ function bp_send_email( $email_type, $to, $args = array() ) {
3242
  * Return email appearance settings.
3243
  *
3244
  * @since 2.5.0
 
 
3245
  *
3246
  * @return array
3247
  */
@@ -3258,6 +3246,7 @@ function bp_email_get_appearance_settings() {
3258
  'highlight_color' => '#D84800',
3259
  'header_text_color' => '#000000',
3260
  'header_text_size' => 30,
 
3261
 
3262
  'footer_text' => sprintf(
3263
  /* translators: email disclaimer, e.g. "© 2016 Site Name". */
@@ -3267,11 +3256,18 @@ function bp_email_get_appearance_settings() {
3267
  ),
3268
  );
3269
 
3270
- return bp_parse_args(
3271
  bp_get_option( 'bp_email_options', array() ),
3272
  $default_args,
3273
  'email_appearance_settings'
3274
  );
 
 
 
 
 
 
 
3275
  }
3276
 
3277
  /**
@@ -3294,6 +3290,7 @@ function bp_email_get_template( WP_Post $object ) {
3294
  * @param WP_Post $object WP_Post object.
3295
  */
3296
  return apply_filters( 'bp_email_get_template', array(
 
3297
  "{$single}-{$object->post_name}.php",
3298
  "{$single}.php",
3299
  "assets/emails/{$single}.php",
@@ -3388,9 +3385,9 @@ function bp_email_get_schema() {
3388
  /* translators: do not remove {} brackets or translate its contents. */
3389
  'post_title' => __( '[{{{site.name}}}] Activate your account', 'buddypress' ),
3390
  /* translators: do not remove {} brackets or translate its contents. */
3391
- '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' ),
3392
  /* translators: do not remove {} brackets or translate its contents. */
3393
- 'post_excerpt' => __( "Thanks for registering!\n\nTo complete the activation of your account, go to the following link: {{{activate.url}}}", 'buddypress' ),
3394
  ),
3395
  'core-user-registration-with-blog' => array(
3396
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3399,6 +3396,9 @@ function bp_email_get_schema() {
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
  ),
3403
  'friends-request' => array(
3404
  /* translators: do not remove {} brackets or translate its contents. */
@@ -3568,14 +3568,6 @@ function bp_email_get_type_schema( $field = 'description' ) {
3568
  ),
3569
  );
3570
 
3571
- $groups_details_updated = array(
3572
- 'description' => __( "A group's details were updated.", 'buddypress' ),
3573
- 'unsubscribe' => array(
3574
- 'meta_key' => 'notification_groups_group_updated',
3575
- 'message' => __( 'You will no longer receive emails when one of your groups is updated.', 'buddypress' ),
3576
- ),
3577
- );
3578
-
3579
  $groups_invitation = array(
3580
  'description' => __( 'A member has sent a group invitation to the recipient.', 'buddypress' ),
3581
  'unsubscribe' => array(
@@ -3592,14 +3584,6 @@ function bp_email_get_type_schema( $field = 'description' ) {
3592
  ),
3593
  );
3594
 
3595
- $groups_member_promoted = array(
3596
- 'description' => __( "Recipient's status within a group has changed.", 'buddypress' ),
3597
- 'unsubscribe' => array(
3598
- 'meta_key' => 'notification_groups_admin_promotion',
3599
- 'message' => __( 'You will no longer receive emails when you have been promoted in a group.', 'buddypress' ),
3600
- ),
3601
- );
3602
-
3603
  $groups_membership_request = array(
3604
  'description' => __( 'A member has requested permission to join a group.', 'buddypress' ),
3605
  'unsubscribe' => array(
@@ -3677,13 +3661,13 @@ function bp_email_unsubscribe_handler() {
3677
 
3678
  // Check required values.
3679
  if ( ! $raw_user_id || ! $raw_email_type || ! $raw_hash || ! array_key_exists( $raw_email_type, $emails ) ) {
3680
- $redirect_to = site_url( 'wp-login.php' );
3681
  $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3682
  $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' );
3683
 
3684
  // Check valid hash.
3685
  } elseif ( ! hash_equals( $new_hash, $raw_hash ) ) {
3686
- $redirect_to = site_url( 'wp-login.php' );
3687
  $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3688
  $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' );
3689
 
@@ -3753,7 +3737,7 @@ function bp_email_get_unsubscribe_link( $args ) {
3753
  $emails = bp_email_get_unsubscribe_type_schema();
3754
 
3755
  if ( empty( $args['notification_type'] ) || ! array_key_exists( $args['notification_type'], $emails ) ) {
3756
- return site_url( 'wp-login.php' );
3757
  }
3758
 
3759
  $email_type = $args['notification_type'];
@@ -3816,3 +3800,52 @@ function bp_email_get_unsubscribe_type_schema() {
3816
  */
3817
  return (array) apply_filters( 'bp_email_get_unsubscribe_type_schema', $emails );
3818
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
 
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
  /**
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
  *
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;
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' )
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",
3385
  /* translators: do not remove {} brackets or translate its contents. */
3386
  'post_title' => __( '[{{{site.name}}}] Activate your account', 'buddypress' ),
3387
  /* translators: do not remove {} brackets or translate its contents. */
3388
+ 'post_content' => __( "Thanks for registering!\n\nTo complete the activation of your account, go to the following link and click on the <strong>Activate</strong> button:\n<a href=\"{{{activate.url}}}\">{{{activate.url}}}</a>\n\nIf the 'Activation Key' field is empty, copy and paste the following into the field - {{key}}", '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 and click on the 'Activate' button: {{{activate.url}}}\n\nIf the 'Activation Key' field is empty, copy and paste the following into the field - {{key}}", 'buddypress' )
3391
  ),
3392
  'core-user-registration-with-blog' => array(
3393
  /* translators: do not remove {} brackets or translate its contents. */
3396
  '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' ),
3397
  /* translators: do not remove {} brackets or translate its contents. */
3398
  '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' ),
3399
+ 'args' => array(
3400
+ 'multisite' => true,
3401
+ ),
3402
  ),
3403
  'friends-request' => array(
3404
  /* translators: do not remove {} brackets or translate its contents. */
3568
  ),
3569
  );
3570
 
 
 
 
 
 
 
 
 
3571
  $groups_invitation = array(
3572
  'description' => __( 'A member has sent a group invitation to the recipient.', 'buddypress' ),
3573
  'unsubscribe' => array(
3584
  ),
3585
  );
3586
 
 
 
 
 
 
 
 
 
3587
  $groups_membership_request = array(
3588
  'description' => __( 'A member has requested permission to join a group.', 'buddypress' ),
3589
  'unsubscribe' => array(
3661
 
3662
  // Check required values.
3663
  if ( ! $raw_user_id || ! $raw_email_type || ! $raw_hash || ! array_key_exists( $raw_email_type, $emails ) ) {
3664
+ $redirect_to = wp_login_url();
3665
  $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3666
  $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' );
3667
 
3668
  // Check valid hash.
3669
  } elseif ( ! hash_equals( $new_hash, $raw_hash ) ) {
3670
+ $redirect_to = wp_login_url();
3671
  $result_msg = __( 'Something has gone wrong.', 'buddypress' );
3672
  $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' );
3673
 
3737
  $emails = bp_email_get_unsubscribe_type_schema();
3738
 
3739
  if ( empty( $args['notification_type'] ) || ! array_key_exists( $args['notification_type'], $emails ) ) {
3740
+ return wp_login_url();
3741
  }
3742
 
3743
  $email_type = $args['notification_type'];
3800
  */
3801
  return (array) apply_filters( 'bp_email_get_unsubscribe_type_schema', $emails );
3802
  }
3803
+
3804
+ /**
3805
+ * Get BuddyPress content allowed tags.
3806
+ *
3807
+ * @since 3.0.0
3808
+ *
3809
+ * @global array $allowedtags KSES allowed HTML elements.
3810
+ * @return array BuddyPress content allowed tags.
3811
+ */
3812
+ function bp_get_allowedtags() {
3813
+ global $allowedtags;
3814
+
3815
+ return array_merge_recursive( $allowedtags, array(
3816
+ 'a' => array(
3817
+ 'aria-label' => array(),
3818
+ 'class' => array(),
3819
+ 'data-bp-tooltip' => array(),
3820
+ 'id' => array(),
3821
+ 'rel' => array(),
3822
+ ),
3823
+ 'img' => array(
3824
+ 'src' => array(),
3825
+ 'alt' => array(),
3826
+ 'width' => array(),
3827
+ 'height' => array(),
3828
+ 'class' => array(),
3829
+ 'id' => array(),
3830
+ ),
3831
+ 'span'=> array(
3832
+ 'class' => array(),
3833
+ 'data-livestamp' => array(),
3834
+ ),
3835
+ 'ul' => array(),
3836
+ 'ol' => array(),
3837
+ 'li' => array(),
3838
+ ) );
3839
+ }
3840
+
3841
+ /**
3842
+ * Remove script and style tags from a string.
3843
+ *
3844
+ * @since 3.0.1
3845
+ *
3846
+ * @param string $string The string to strip tags from.
3847
+ * @return string The stripped tags string.
3848
+ */
3849
+ function bp_strip_script_and_style_tags( $string ) {
3850
+ return preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string );
3851
+ }
bp-core/bp-core-options.php CHANGED
@@ -29,11 +29,6 @@ function bp_get_default_options() {
29
 
30
  'bp-deactivated-components' => array(),
31
 
32
- /* bbPress ***********************************************************/
33
-
34
- // Legacy bbPress config location.
35
- 'bb-config-location' => ABSPATH . 'bb-config.php',
36
-
37
  /* XProfile **********************************************************/
38
 
39
  // Base profile groups name.
@@ -70,11 +65,11 @@ function bp_get_default_options() {
70
  // Allow users to delete their own accounts.
71
  'bp-disable-account-deletion' => false,
72
 
73
- // Allow comments on blog and forum activity items.
74
  'bp-disable-blogforum-comments' => true,
75
 
76
  // The ID for the current theme package.
77
- '_bp_theme_package_id' => 'legacy',
78
 
79
  // Email unsubscribe salt.
80
  'bp-emails-unsubscribe-salt' => '',
@@ -626,7 +621,7 @@ function bp_disable_account_deletion( $default = false ) {
626
  }
627
 
628
  /**
629
- * Are blog and forum activity stream comments disabled?
630
  *
631
  * @since 1.6.0
632
  *
@@ -693,57 +688,6 @@ function bp_force_buddybar( $default = true ) {
693
  return (bool) apply_filters( 'bp_force_buddybar', (bool) bp_get_option( '_bp_force_buddybar', $default ) );
694
  }
695
 
696
- /**
697
- * Output the group forums root parent forum id.
698
- *
699
- * @since 1.6.0
700
- *
701
- * @param bool|string $default Optional. Default: '0'.
702
- */
703
- function bp_group_forums_root_id( $default = '0' ) {
704
- echo bp_get_group_forums_root_id( $default );
705
- }
706
- /**
707
- * Return the group forums root parent forum id.
708
- *
709
- * @since 1.6.0
710
- *
711
- * @param bool|string $default Optional. Default: '0'.
712
- * @return int The ID of the group forums root forum.
713
- */
714
- function bp_get_group_forums_root_id( $default = '0' ) {
715
-
716
- /**
717
- * Filters the group forums root parent forum id.
718
- *
719
- * @since 1.6.0
720
- *
721
- * @param int $value The group forums root parent forum id.
722
- */
723
- return (int) apply_filters( 'bp_get_group_forums_root_id', (int) bp_get_option( '_bp_group_forums_root_id', $default ) );
724
- }
725
-
726
- /**
727
- * Check whether BuddyPress Group Forums are enabled.
728
- *
729
- * @since 1.6.0
730
- *
731
- * @param bool $default Optional. Fallback value if not found in the database.
732
- * Default: true.
733
- * @return bool True if group forums are active, otherwise false.
734
- */
735
- function bp_is_group_forums_active( $default = true ) {
736
-
737
- /**
738
- * Filters whether or not BuddyPress Group Forums are enabled.
739
- *
740
- * @since 1.6.0
741
- *
742
- * @param bool $value Whether or not BuddyPress Group Forums are enabled.
743
- */
744
- return (bool) apply_filters( 'bp_is_group_forums_active', (bool) bp_get_option( '_bp_enable_group_forums', $default ) );
745
- }
746
-
747
  /**
748
  * Check whether Akismet is enabled.
749
  *
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' => '',
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-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.
@@ -796,7 +792,14 @@ function bp_form_field_attributes( $name = '', $attributes = array() ) {
796
  $attributes = (array) apply_filters( 'bp_get_form_field_attributes', $attributes, $name );
797
 
798
  foreach( $attributes as $attr => $value ) {
799
- $retval .= sprintf( ' %s="%s"', sanitize_key( $attr ), esc_attr( $value ) );
 
 
 
 
 
 
 
800
  }
801
 
802
  return $retval;
@@ -1154,10 +1157,7 @@ function bp_blog_signup_allowed() {
1154
  * otherwise false.
1155
  */
1156
  function bp_account_was_activated() {
1157
- $bp = buddypress();
1158
- $activation_complete = !empty( $bp->activation_complete )
1159
- ? $bp->activation_complete
1160
- : false;
1161
 
1162
  return $activation_complete;
1163
  }
@@ -2199,6 +2199,7 @@ function bp_is_groups_component() {
2199
  * Check whether the current page is part of the Forums component.
2200
  *
2201
  * @since 1.5.0
 
2202
  *
2203
  * @return bool True if the current page is part of the Forums component.
2204
  */
@@ -2472,54 +2473,6 @@ function bp_is_user_change_cover_image() {
2472
  return (bool) ( bp_is_profile_component() && bp_is_current_action( 'change-cover-image' ) );
2473
  }
2474
 
2475
- /**
2476
- * Is this a user's forums page?
2477
- *
2478
- * Eg http://example.com/members/joe/forums/ (or a subpage thereof).
2479
- *
2480
- * @since 1.5.0
2481
- *
2482
- * @return bool True if the current page is a user's forums page.
2483
- */
2484
- function bp_is_user_forums() {
2485
-
2486
- if ( ! bp_is_active( 'forums' ) ) {
2487
- return false;
2488
- }
2489
-
2490
- if ( bp_is_user() && bp_is_forums_component() ) {
2491
- return true;
2492
- }
2493
-
2494
- return false;
2495
- }
2496
-
2497
- /**
2498
- * Is this a user's "Topics Started" page?
2499
- *
2500
- * Eg http://example.com/members/joe/forums/topics/.
2501
- *
2502
- * @since 1.5.0
2503
- *
2504
- * @return bool True if the current page is a user's Topics Started page.
2505
- */
2506
- function bp_is_user_forums_started() {
2507
- return (bool) ( bp_is_user_forums() && bp_is_current_action( 'topics' ) );
2508
- }
2509
-
2510
- /**
2511
- * Is this a user's "Replied To" page?
2512
- *
2513
- * Eg http://example.com/members/joe/forums/replies/.
2514
- *
2515
- * @since 1.5.0
2516
- *
2517
- * @return bool True if the current page is a user's Replied To forums page.
2518
- */
2519
- function bp_is_user_forums_replied_to() {
2520
- return (bool) ( bp_is_user_forums() && bp_is_current_action( 'replies' ) );
2521
- }
2522
-
2523
  /**
2524
  * Is the current page part of a user's Groups page?
2525
  *
@@ -2754,32 +2707,6 @@ function bp_is_group_admin_page() {
2754
  return (bool) ( bp_is_single_item() && bp_is_groups_component() && bp_is_current_action( 'admin' ) );
2755
  }
2756
 
2757
- /**
2758
- * Is the current page a group's forum page?
2759
- *
2760
- * Only applies to legacy bbPress forums.
2761
- *
2762
- * @since 1.1.0
2763
- *
2764
- * @return bool True if the current page is a group forum page.
2765
- */
2766
- function bp_is_group_forum() {
2767
- $retval = false;
2768
-
2769
- // At a forum URL.
2770
- if ( bp_is_single_item() && bp_is_groups_component() && bp_is_current_action( 'forum' ) ) {
2771
- $retval = true;
2772
-
2773
- // If at a forum URL, set back to false if forums are inactive, or not
2774
- // installed correctly.
2775
- if ( ! bp_is_active( 'forums' ) || ! bp_forums_is_installed_correctly() ) {
2776
- $retval = false;
2777
- }
2778
- }
2779
-
2780
- return $retval;
2781
- }
2782
-
2783
  /**
2784
  * Is the current page a group's activity page?
2785
  *
@@ -2804,9 +2731,8 @@ function bp_is_group_activity() {
2804
  /**
2805
  * Is the current page a group forum topic?
2806
  *
2807
- * Only applies to legacy bbPress (1.x) forums.
2808
- *
2809
  * @since 1.1.0
 
2810
  *
2811
  * @return bool True if the current page is part of a group forum topic.
2812
  */
@@ -2817,9 +2743,8 @@ function bp_is_group_forum_topic() {
2817
  /**
2818
  * Is the current page a group forum topic edit page?
2819
  *
2820
- * Only applies to legacy bbPress (1.x) forums.
2821
- *
2822
  * @since 1.2.0
 
2823
  *
2824
  * @return bool True if the current page is part of a group forum topic edit page.
2825
  */
@@ -3320,7 +3245,7 @@ function bp_the_body_class() {
3320
  $bp_classes[] = 'my-activity';
3321
  }
3322
  } else {
3323
- if ( bp_get_current_member_type() ) {
3324
  $bp_classes[] = 'type';
3325
  }
3326
  }
@@ -3416,18 +3341,6 @@ function bp_the_body_class() {
3416
  $bp_classes[] = 'group-members';
3417
  }
3418
 
3419
- if ( bp_is_group_forum_topic() ) {
3420
- $bp_classes[] = 'group-forum-topic';
3421
- }
3422
-
3423
- if ( bp_is_group_forum_topic_edit() ) {
3424
- $bp_classes[] = 'group-forum-topic-edit';
3425
- }
3426
-
3427
- if ( bp_is_group_forum() ) {
3428
- $bp_classes[] = 'group-forum';
3429
- }
3430
-
3431
  if ( bp_is_group_admin_page() ) {
3432
  $bp_classes[] = 'group-admin';
3433
  $bp_classes[] = bp_get_group_current_admin_tab();
@@ -3525,9 +3438,6 @@ function bp_get_the_post_class( $wp_classes = array() ) {
3525
 
3526
  } elseif ( bp_is_activation_page() ) {
3527
  $bp_classes[] = 'bp_activate';
3528
-
3529
- } elseif ( bp_is_forums_component() && bp_is_directory() ) {
3530
- $bp_classes[] = 'bp_forum';
3531
  }
3532
 
3533
  if ( empty( $bp_classes ) ) {
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.
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
  */
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
  *
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
  *
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
  */
3245
  $bp_classes[] = 'my-activity';
3246
  }
3247
  } else {
3248
+ if ( bp_get_current_member_type() || ( bp_is_groups_directory() && bp_get_current_group_directory_type() ) ) {
3249
  $bp_classes[] = 'type';
3250
  }
3251
  }
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();
3438
 
3439
  } elseif ( bp_is_activation_page() ) {
3440
  $bp_classes[] = 'bp_activate';
 
 
 
3441
  }
3442
 
3443
  if ( empty( $bp_classes ) ) {
bp-core/bp-core-theme-compatibility.php CHANGED
@@ -987,3 +987,26 @@ function bp_theme_compat_loop_end( $query ) {
987
  unset( $bp->theme_compat->is_page_toggled );
988
  }
989
  add_action( 'loop_end', 'bp_theme_compat_loop_end' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ if ( bp_is_deactivation() ) {
998
+ return;
999
+ }
1000
+
1001
+ $all_packages = array_keys( buddypress()->theme_compat->packages );
1002
+
1003
+ foreach ( $all_packages as $package ) {
1004
+ // e.g. "buddypress-use-nouveau", "buddypress-use-legacy".
1005
+ if ( ! current_theme_supports( "buddypress-use-{$package}" ) ) {
1006
+ continue;
1007
+ }
1008
+
1009
+ bp_setup_theme_compat( $package );
1010
+ return;
1011
+ }
1012
+ }
bp-core/classes/class-bp-admin.php CHANGED
@@ -155,8 +155,8 @@ class BP_Admin {
155
  // Add settings.
156
  add_action( 'bp_register_admin_settings', array( $this, 'register_admin_settings' ) );
157
 
158
- // Add a link to BuddyPress About page to the admin bar.
159
- add_action( 'admin_bar_menu', array( $this, 'admin_bar_about_link' ), 15 );
160
 
161
  // Add a description of new BuddyPress tools in the available tools page.
162
  add_action( 'tool_box', 'bp_core_admin_available_tools_intro' );
@@ -169,6 +169,9 @@ class BP_Admin {
169
  add_filter( 'manage_' . bp_get_email_post_type() . '_posts_columns', array( $this, 'emails_register_situation_column' ) );
170
  add_action( 'manage_' . bp_get_email_post_type() . '_posts_custom_column', array( $this, 'emails_display_situation_column_data' ), 10, 2 );
171
 
 
 
 
172
  /* Filters ***********************************************************/
173
 
174
  // Add link to settings page.
@@ -197,24 +200,6 @@ class BP_Admin {
197
  return;
198
  }
199
 
200
- // About.
201
- add_dashboard_page(
202
- __( 'Welcome to BuddyPress', 'buddypress' ),
203
- __( 'Welcome to BuddyPress', 'buddypress' ),
204
- 'manage_options',
205
- 'bp-about',
206
- array( $this, 'about_screen' )
207
- );
208
-
209
- // Credits.
210
- add_dashboard_page(
211
- __( 'Welcome to BuddyPress', 'buddypress' ),
212
- __( 'Welcome to BuddyPress', 'buddypress' ),
213
- 'manage_options',
214
- 'bp-credits',
215
- array( $this, 'credits_screen' )
216
- );
217
-
218
  $hooks = array();
219
 
220
  // Changed in BP 1.6 . See bp_core_admin_backpat_menu().
@@ -264,6 +249,16 @@ class BP_Admin {
264
  'bp_core_admin_settings'
265
  );
266
 
 
 
 
 
 
 
 
 
 
 
267
  // For consistency with non-Multisite, we add a Tools menu in
268
  // the Network Admin as a home for our Tools panel.
269
  if ( is_multisite() && bp_core_do_network_admin() ) {
@@ -336,27 +331,24 @@ class BP_Admin {
336
 
337
  $hooks = array();
338
 
339
- // Require WP 4.0+.
340
- if ( bp_is_root_blog() && version_compare( $GLOBALS['wp_version'], '4.0', '>=' ) ) {
341
- // Appearance > Emails.
342
- $hooks[] = add_theme_page(
343
- _x( 'Emails', 'screen heading', 'buddypress' ),
344
- _x( 'Emails', 'screen heading', 'buddypress' ),
345
- $this->capability,
346
- 'bp-emails-customizer-redirect',
347
- 'bp_email_redirect_to_customizer'
348
- );
349
 
350
- // Emails > Customize.
351
- $hooks[] = add_submenu_page(
352
- 'edit.php?post_type=' . bp_get_email_post_type(),
353
- _x( 'Customize', 'email menu label', 'buddypress' ),
354
- _x( 'Customize', 'email menu label', 'buddypress' ),
355
- $this->capability,
356
- 'bp-emails-customizer-redirect',
357
- 'bp_email_redirect_to_customizer'
358
- );
359
- }
360
 
361
  foreach( $hooks as $hook ) {
362
  add_action( "admin_head-$hook", 'bp_core_modify_admin_menu_highlight' );
@@ -396,7 +388,7 @@ class BP_Admin {
396
  register_setting( 'buddypress', 'bp-disable-account-deletion', 'intval' );
397
 
398
  // Template pack picker.
399
- add_settings_field( '_bp_theme_package_id', __( 'Template Pack', 'buddypress' ), 'bp_admin_setting_callback_theme_package_id', 'buddypress', 'bp_main' );
400
  register_setting( 'buddypress', '_bp_theme_package_id', 'sanitize_text_field' );
401
 
402
  /* XProfile Section **************************************************/
@@ -443,18 +435,6 @@ class BP_Admin {
443
  }
444
  }
445
 
446
- /* Forums ************************************************************/
447
-
448
- if ( bp_is_active( 'forums' ) ) {
449
-
450
- // Add the main section.
451
- add_settings_section( 'bp_forums', __( 'Legacy Group Forums', 'buddypress' ), 'bp_admin_setting_callback_bbpress_section', 'buddypress' );
452
-
453
- // Allow subscriptions setting.
454
- add_settings_field( 'bb-config-location', __( 'bbPress Configuration', 'buddypress' ), 'bp_admin_setting_callback_bbpress_configuration', 'buddypress', 'bp_forums' );
455
- register_setting( 'buddypress', 'bb-config-location', '' );
456
- }
457
-
458
  /* Activity Section **************************************************/
459
 
460
  if ( bp_is_active( 'activity' ) ) {
@@ -462,8 +442,8 @@ class BP_Admin {
462
  // Add the main section.
463
  add_settings_section( 'bp_activity', __( 'Activity Settings', 'buddypress' ), 'bp_admin_setting_callback_activity_section', 'buddypress' );
464
 
465
- // Activity commenting on blog and forum posts.
466
- add_settings_field( 'bp-disable-blogforum-comments', __( 'Blog &amp; Forum Comments', 'buddypress' ), 'bp_admin_setting_callback_blogforum_comments', 'buddypress', 'bp_activity' );
467
  register_setting( 'buddypress', 'bp-disable-blogforum-comments', 'bp_admin_sanitize_callback_blogforum_comments' );
468
 
469
  // Activity Heartbeat refresh.
@@ -479,21 +459,27 @@ class BP_Admin {
479
  }
480
 
481
  /**
482
- * Add a link to BuddyPress About page to the admin bar.
483
  *
484
  * @since 1.9.0
 
485
  *
486
- * @param WP_Admin_Bar $wp_admin_bar As passed to 'admin_bar_menu'.
487
  */
488
  public function admin_bar_about_link( $wp_admin_bar ) {
489
- if ( is_user_logged_in() ) {
490
- $wp_admin_bar->add_menu( array(
491
- 'parent' => 'wp-logo',
492
- 'id' => 'bp-about',
493
- 'title' => esc_html__( 'About BuddyPress', 'buddypress' ),
494
- 'href' => add_query_arg( array( 'page' => 'bp-about' ), bp_get_admin_url( 'index.php' ) ),
495
- ) );
496
  }
 
 
 
 
 
 
 
 
 
 
497
  }
498
 
499
  /**
@@ -515,7 +501,7 @@ class BP_Admin {
515
  // Add a few links to the existing links array.
516
  return array_merge( $links, array(
517
  'settings' => '<a href="' . esc_url( add_query_arg( array( 'page' => 'bp-components' ), bp_get_admin_url( $this->settings_page ) ) ) . '">' . esc_html__( 'Settings', 'buddypress' ) . '</a>',
518
- 'about' => '<a href="' . esc_url( add_query_arg( array( 'page' => 'bp-about' ), bp_get_admin_url( 'index.php' ) ) ) . '">' . esc_html__( 'About', 'buddypress' ) . '</a>'
519
  ) );
520
  }
521
 
@@ -529,6 +515,7 @@ class BP_Admin {
529
  // Settings pages.
530
  remove_submenu_page( $this->settings_page, 'bp-page-settings' );
531
  remove_submenu_page( $this->settings_page, 'bp-settings' );
 
532
 
533
  // Network Admin Tools.
534
  remove_submenu_page( 'network-tools', 'network-tools' );
@@ -545,156 +532,200 @@ class BP_Admin {
545
  */
546
  public function enqueue_scripts() {
547
  wp_enqueue_style( 'bp-admin-common-css' );
 
 
 
 
 
 
548
  }
549
 
550
  /** About *****************************************************************/
551
 
552
  /**
553
- * Output the about screen.
554
  *
555
- * @since 1.7.0
 
556
  */
557
  public function about_screen() {
 
 
 
558
  ?>
559
 
560
- <div class="wrap about-wrap">
561
-
562
- <?php self::welcome_text(); ?>
563
-
564
- <?php self::tab_navigation( __METHOD__ ); ?>
565
-
566
- <?php if ( self::is_new_install() ) : ?>
567
-
568
- <div id="welcome-panel" class="welcome-panel">
569
- <div class="welcome-panel-content">
570
- <h3 style="margin:0;"><?php _e( 'Getting Started with BuddyPress', 'buddypress' ); ?></h3>
571
- <div class="welcome-panel-column-container">
572
- <div class="welcome-panel-column">
573
- <h4><?php _e( 'Configure BuddyPress', 'buddypress' ); ?></h4>
574
- <ul>
575
- <li><?php printf(
576
- '<a href="%s" class="welcome-icon welcome-edit-page">' . __( 'Set Up Components', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-components' ), $this->settings_page ) ) )
577
- ); ?></li>
578
- <li><?php printf(
579
- '<a href="%s" class="welcome-icon welcome-edit-page">' . __( 'Assign Components to Pages', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), $this->settings_page ) ) )
580
- ); ?></li>
581
- <li><?php printf(
582
- '<a href="%s" class="welcome-icon welcome-edit-page">' . __( 'Customize Settings', 'buddypress' ) . '</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), $this->settings_page ) ) )
583
- ); ?></li>
584
- </ul>
585
- <a class="button button-primary button-hero" style="margin-bottom:20px;margin-top:0;" href="<?php echo esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-components' ), $this->settings_page ) ) ); ?>"><?php _e( 'Get Started', 'buddypress' ); ?></a>
586
- </div>
587
- <div class="welcome-panel-column">
588
- <h4><?php _e( 'Administration Tools', 'buddypress' ); ?></h4>
589
- <ul>
590
- <?php if ( bp_is_active( 'members' ) ) : ?>
591
- <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>
592
- <?php endif; ?>
593
- <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>
594
- <?php if ( bp_is_active( 'activity' ) ) : ?>
595
- <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>
596
- <?php endif; ?>
597
- <?php if ( bp_is_active( 'groups' ) ) : ?>
598
- <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>
599
- <?php endif; ?>
600
- <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' ) ) ) ); ?>
601
- </li>
602
- </ul>
603
- </div>
604
- <div class="welcome-panel-column welcome-panel-last">
605
- <h4><?php _e( 'Community and Support', 'buddypress' ); ?></h4>
606
- <p class="welcome-icon welcome-learn-more" style="margin-right:10px"><?php _e( 'Looking for help? The <a href="https://codex.buddypress.org/">BuddyPress Codex</a> has you covered.', 'buddypress' ) ?></p>
607
- <p class="welcome-icon welcome-learn-more" style="margin-right:10px"><?php _e( 'Can&#8217;t find what you need? Stop by <a href="https://buddypress.org/support/">our support forums</a>, where active BuddyPress users and developers are waiting to share tips and more.', 'buddypress' ) ?></p>
608
- </div>
609
- </div>
610
- </div>
611
- </div>
612
-
613
- <?php endif; ?>
614
-
615
- <div class="bp-features-section">
616
-
617
- <h3 class="headline-title"><?php esc_html_e( 'For Developers &amp; Site Builders', 'buddypress' ); ?></h3>
618
-
619
- <div class="bp-feature">
620
- <span class="dashicons dashicons-groups" aria-hidden="true"></span>
621
- <h4 class="feature-title"><?php esc_html_e( 'Edit Group Slug', 'buddypress' ); ?></h4>
622
- <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>
623
- </div>
624
-
625
- <div class="bp-feature opposite">
626
- <span class="dashicons dashicons-admin-users" aria-hidden="true"></span>
627
- <h4 class="feature-title"><?php esc_html_e( 'Improve accessibility of Extended Profile Fields', 'buddypress' ); ?></h4>
628
- <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>
629
- </div>
630
 
631
- <div class="bp-feature">
632
- <span class="dashicons dashicons-email" aria-hidden="true"></span>
633
- <h4 class="feature-title"><?php esc_html_e( 'Send group invitation only once per user', 'buddypress' ); ?></h4>
634
- <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>
 
 
635
  </div>
636
 
637
- <div class="bp-feature opposite">
638
- <span class="dashicons dashicons-testimonial" aria-hidden="true"></span>
639
- <h4 class="feature-title"><?php esc_html_e( 'Tooltips Usable for All Devices', 'buddypress' ); ?></h4>
640
-
641
- <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' );
642
- ?></p>
643
  </div>
 
644
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
645
  </div>
646
 
647
- <div class="bp-changelog-section">
648
-
649
- <h3 class="changelog-title"><?php esc_html_e( 'More under the hood &#8230;', 'buddypress' ); ?></h3>
650
- <div class="bp-changelog bp-three-column">
651
- <div class="bp-column">
652
- <h4 class="title"><?php esc_html_e( 'Better support for private message thread links in emails', 'buddypress' ); ?></h4>
653
- <p><?php esc_html_e( 'Redirect non-authenticated users to the login screen and authenticated users to the message linked.', 'buddypress' ); ?></p>
654
- </div>
655
- <div class="bp-column">
656
- <h4 class="title"><?php esc_html_e( 'Compatibility with Bootstrap themes', 'buddypress' ); ?></h4>
657
- <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>
658
- </div>
659
-
660
- <div class="bp-column">
661
- <h4 class="title"><?php esc_html_e( 'Improve profile image uploads', 'buddypress' ); ?></h4>
662
- <p><?php esc_html_e( 'Fixed issues with uploading in iOS Safari and uploading files with non-ASCII filenames.', 'buddypress' ); ?></p>
663
- </div>
664
  </div>
665
 
666
- <div class="bp-changelog bp-three-column">
667
- <div class="bp-column">
668
- <h4 class="title"><?php esc_html_e( 'URL compatibility for LightSpeed Servers', 'buddypress' ); ?></h4>
669
- <p><?php
670
- /* translators: %s: trailingslashit() */
671
- printf( __( 'Audited and changed template link functions to use %s where necessary.', 'buddypress' ),
672
- '<code>trailingslashit()</code>' );
673
- ?></p>
674
- </div>
675
- <div class="bp-column">
676
- <h4 class="title"><?php esc_html_e( 'Template Packs UI in BuddyPress > Settings.', 'buddypress' ); ?></h4>
677
- <p><?php esc_html_e( 'Register your new BuddyPress theme package and allow the user to select which template pack to use.', 'buddypress' ); ?></p>
678
- </div>
679
-
680
- <div class="bp-column">
681
- <h4 class="title"><?php
682
- /* translators: %s: bp_group_link() */
683
- printf( __( 'New template function %s', 'buddypress' ),
684
- '<code>bp_group_link()</code>' );
685
- ?></h4>
686
- <p><?php esc_html_e( 'Output a group name as a text hyperlink where appropriate.', 'buddypress' ); ?></p>
687
- </div>
 
 
688
  </div>
689
-
690
- </div>
691
-
692
- <div class="bp-assets">
693
- <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>
694
-
695
- <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>
696
  </div>
697
-
698
  </div>
699
 
700
  <?php
@@ -711,168 +742,193 @@ class BP_Admin {
711
  public function credits_screen() {
712
  ?>
713
 
714
- <div class="wrap about-wrap">
715
 
716
- <?php self::welcome_text(); ?>
717
 
718
- <?php self::tab_navigation( __METHOD__ ); ?>
719
 
720
- <p class="about-description"><?php _e( 'BuddyPress is created by a worldwide network of friendly folks like these.', 'buddypress' ); ?></p>
721
 
722
  <h3 class="wp-people-group"><?php _e( 'Project Leaders', 'buddypress' ); ?></h3>
723
  <ul class="wp-people-group " id="wp-people-group-project-leaders">
724
  <li class="wp-person" id="wp-person-johnjamesjacoby">
725
- <a class="web" href="https://profiles.wordpress.org/johnjamesjacoby"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7a2644fb53ae2f7bfd7143b504af396c?s=60">
726
  John James Jacoby</a>
727
  <span class="title"><?php _e( 'Project Lead', 'buddypress' ); ?></span>
728
  </li>
729
  <li class="wp-person" id="wp-person-boonebgorges">
730
- <a class="web" href="https://profiles.wordpress.org/boonebgorges"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/9cf7c4541a582729a5fc7ae484786c0c?s=60">
731
  Boone B. Gorges</a>
732
  <span class="title"><?php _e( 'Lead Developer', 'buddypress' ); ?></span>
733
  </li>
734
  <li class="wp-person" id="wp-person-djpaul">
735
- <a class="web" href="https://profiles.wordpress.org/djpaul"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3bc9ab796299d67ce83dceb9554f75df?s=60">
736
  Paul Gibbs</a>
737
- <span class="title"><?php _e( 'Lead Developer', 'buddypress' ); ?></span>
738
  </li>
739
  </ul>
740
 
741
  <h3 class="wp-people-group"><?php _e( 'BuddyPress Team', 'buddypress' ); ?></h3>
742
  <ul class="wp-people-group " id="wp-people-group-core-team">
743
- <li class="wp-person" id="wp-person-hnla">
744
- <a class="web" href="https://profiles.wordpress.org/hnla"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3860c955aa3f79f13b92826ae47d07fe?s=60">
745
- Hugo Ashmore</a>
746
- <span class="title"><?php _e( '2.9 Release Lead', 'buddypress' ); ?></span>
747
- </li>
748
  <li class="wp-person" id="wp-person-r-a-y">
749
- <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3bfa556a62b5bfac1012b6ba5f42ebfa?s=60">
750
  Ray</a>
751
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
752
  </li>
 
 
 
 
 
753
  <li class="wp-person" id="wp-person-imath">
754
- <a class="web" href="https://profiles.wordpress.org/imath"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/8b208ca408dad63888253ee1800d6a03?s=60">
755
  Mathieu Viet</a>
756
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
757
  </li>
758
  <li class="wp-person" id="wp-person-mercime">
759
- <a class="web" href="https://profiles.wordpress.org/mercime"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/fae451be6708241627983570a1a1817a?s=60">
760
  Mercime</a>
761
  <span class="title"><?php _e( 'Navigator', 'buddypress' ); ?></span>
762
  </li>
763
  <li class="wp-person" id="wp-person-dcavins">
764
- <a class="web" href="https://profiles.wordpress.org/dcavins"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/a5fa7e83d59cb45ebb616235a176595a?s=60">
765
  David Cavins</a>
766
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
767
  </li>
768
  <li class="wp-person" id="wp-person-tw2113">
769
- <a class="web" href="https://profiles.wordpress.org/tw2113"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/a5d7c934621fa1c025b83ee79bc62366?s=60">
770
  Michael Beckwith</a>
771
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
772
  </li>
773
  <li class="wp-person" id="wp-person-henry-wright">
774
- <a class="web" href="https://profiles.wordpress.org/henry.wright"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0da2f1a9340d6af196b870f6c107a248?s=60">
775
  Henry Wright</a>
776
  <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
777
  </li>
778
  <li class="wp-person" id="wp-person-danbp">
779
- <a class="web" href="https://profiles.wordpress.org/danbp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0deae2e7003027fbf153500cd3fa5501?s=60">
780
  danbp</a>
781
  <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
782
  </li>
783
  <li class="wp-person" id="wp-person-shanebp">
784
- <a class="web" href="https://profiles.wordpress.org/shanebp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ffd294ab5833ba14aaf175f9acc71cc4?s=60">
785
  shanebp</a>
786
  <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
787
  </li>
788
  <li class="wp-person" id="wp-person-slaffik">
789
- <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/61fb07ede3247b63f19015f200b3eb2c?s=60">
790
  Slava Abakumov</a>
791
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
792
  </li>
793
  <li class="wp-person" id="wp-person-offereins">
794
- <a class="web" href="https://profiles.wordpress.org/Offereins"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/2404ed0a35bb41aedefd42b0a7be61c1?s=60">
795
  Laurens Offereins</a>
796
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
797
  </li>
798
  <li class="wp-person" id="wp-person-netweb">
799
- <a class="web" href="https://profiles.wordpress.org/netweb"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/97e1620b501da675315ba7cfb740e80f?s=60">
800
  Stephen Edgar</a>
801
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
802
  </li>
 
 
 
 
 
 
 
 
 
 
803
  </ul>
804
 
805
- <h3 class="wp-people-group"><?php _e( '&#x1f31f;Recent Rockstars&#x1f31f;', 'buddypress' ); ?></h3>
806
  <ul class="wp-people-group " id="wp-people-group-rockstars">
807
  <li class="wp-person" id="wp-person-dimensionmedia">
808
- <a class="web" href="https://profiles.wordpress.org/dimensionmedia"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7735aada1ec39d0c1118bd92ed4551f1?s=60">
809
  David Bisset</a>
810
  </li>
811
  <li class="wp-person" id="wp-person-garrett-eclipse">
812
- <a class="web" href="https://profiles.wordpress.org/garrett-eclipse"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7f68f24441c61514d5d0e1451bb5bc9d?s=60">
813
  Garrett Hyder</a>
814
  </li>
815
  <li class="wp-person" id="wp-person-thebrandonallen">
816
- <a class="web" href="https://profiles.wordpress.org/thebrandonallen"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/6d3f77bf3c9ca94c406dea401b566950?s=60">
817
  Brandon Allen</a>
818
  </li>
819
  <li class="wp-person" id="wp-person-ramiy">
820
- <a class="web" href="https://profiles.wordpress.org/ramiy"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ce2a269e424156d79cb0c4e1d4d82db1?s=60">
821
  Rami Yushuvaev</a>
822
  </li>
 
 
 
 
823
  </ul>
824
 
825
  <h3 class="wp-people-group"><?php printf( esc_html__( 'Contributors to BuddyPress %s', 'buddypress' ), self::display_version() ); ?></h3>
826
  <p class="wp-credits-list">
827
- <a href="https://profiles.wordpress.org/55don/">55don</a>,
828
- <a href="https://profiles.wordpress.org/aaronoftomorrow/">AaronOfTomorrow</a>,
829
- <a href="https://profiles.wordpress.org/allianse/">allianse</a>,
 
830
  <a href="https://profiles.wordpress.org/antonioeatgoat/">Antonio Mangiacapra (antonioeatgoat)</a>,
831
- <a href="https://profiles.wordpress.org/benjlipchak/">Benj (benjlipchak)</a>,
832
  <a href="https://profiles.wordpress.org/boonebgorges/">Boone B Gorges (boonebgorges)</a>,
833
- <a href="https://profiles.wordpress.org/bhargavbhandari90/">Bunty (bhargavbhandari90)</a>,
 
834
  <a href="https://profiles.wordpress.org/sbrajesh/">Brajesh Singh (sbrajesh)</a>,
 
 
835
  <a href="https://profiles.wordpress.org/needle/">Christian Wach (needle)</a>,
836
- <a href="https://profiles.wordpress.org/brandonliles/">brandonliles</a>,
 
837
  <a href="https://profiles.wordpress.org/danbp/">danbp</a>,
838
  <a href="https://profiles.wordpress.org/dcavins/">David Cavins (dcavins)</a>,
839
- <a href="https://profiles.wordpress.org/dkelm/">dkelm</a>,
840
- <a href="https://profiles.wordpress.org/dsar/">dsar</a>,
841
- <a href="https://profiles.wordpress.org/dsided/">dsided</a>,
 
 
 
 
 
 
842
  <a href="https://profiles.wordpress.org/henry.wright">Henry Wright (henry.wright)</a>,
843
  <a href="https://profiles.wordpress.org/hnla/">Hugo (hnla)</a>,
844
  <a href="https://profiles.wordpress.org/idofri/">Ido Friedlander (idofri)</a>,
845
- <a href="https://profiles.wordpress.org/uscore713/">Jay (uscore713)</a>,
846
- <a href="https://profiles.wordpress.org/johnbillion/">John Blackbourn (johnbillion)</a>,
847
  <a href="https://profiles.wordpress.org/johnjamesjacoby/">John James Jacoby (johnjamesjacoby)</a>,
848
- <a href="https://profiles.wordpress.org/juanho/">Juanho</a>,
849
- <a href="https://profiles.wordpress.org/lakrisgubben/">lakrisgubben</a>,
850
  <a href="https://profiles.wordpress.org/Offereins">Laurens Offereins (Offereins)</a>,
851
- <a href="https://profiles.wordpress.org/lne1030/">lne1030</a>,
852
- <a href="https://profiles.wordpress.org/lenasterg/">lenasterg</a>,
853
- <a href="https://profiles.wordpress.org/maniou/">Maniou</a>,
854
  <a href="https://profiles.wordpress.org/imath/">Mathieu Viet (imath)</a>,
 
855
  <a href="https://profiles.wordpress.org/mercime/">mercime</a>,
856
  <a href="https://profiles.wordpress.org/tw2113/">Michael Beckwith (tw2113)</a>,
857
- <a href="https://profiles.wordpress.org/mikegillihan/">Mike Gillihan (MikeGillihan)</a>,
858
- <a href="https://profiles.wordpress.org/milindmore22/">Milind More (milindmore22)</a>,
859
  <a href="https://profiles.wordpress.org/modemlooper/">modemlooper</a>,
860
- <a href="https://profiles.wordpress.org/mrjarbenne/">mrjarbenne</a>,
861
- <a href="https://profiles.wordpress.org/nicolaskulka/">Nicolas Kulka (NicolasKulka)</a>,
862
- <a href="https://profiles.wordpress.org/oelita/">Oelita</a>,
863
- <a href="https://profiles.wordpress.org/DJPaul/">Paul Gibbs (DJPaul)</a>,
864
  <a href="https://profiles.wordpress.org/pareshradadiya/">paresh.radadiya (pareshradadiya)</a>,
 
 
 
865
  <a href="https://profiles.wordpress.org/r-a-y/">r-a-y</a>,
 
 
866
  <a href="https://profiles.wordpress.org/espellcaste/">Renato Alves (espellcaste)</a>,
867
  <a href="https://profiles.wordpress.org/rianrietveld/">Rian Rietveld (rianrietvelde)</a>,
868
- <a href="https://profiles.wordpress.org/elhardoum/">Samuel Elh (elhardoum)</a>,
869
- <a href="https://profiles.wordpress.org/seventhqueen/">seventhqueen</a>,
870
  <a href="https://profiles.wordpress.org/slaffik/">Slava Abakumov (slaffik)</a>,
871
  <a href="https://profiles.wordpress.org/netweb/">Stephen Edgar (netweb)</a>,
872
- <a href="https://profiles.wordpress.org/vishalkakadiya/">Vishal Kakadiya (vishalkakadiya)</a>
 
 
 
 
873
  </p>
874
 
875
- <h3 class="wp-people-group"><?php _e( '&#x1f496;With our thanks to these Open Source projects&#x1f496;', 'buddypress' ); ?></h3>
876
  <p class="wp-credits-list">
877
  <a href="https://github.com/ichord/At.js">At.js</a>,
878
  <a href="https://bbpress.org">bbPress</a>,
@@ -882,67 +938,39 @@ class BP_Admin {
882
  <a href="https://github.com/carhartl/jquery-cookie">jquery.cookie</a>,
883
  <a href="https://mattbradley.github.io/livestampjs/">Livestamp.js</a>,
884
  <a href="https://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a>,
885
- <a href="http://momentjs.com/">Moment.js</a>,
886
  <a href="https://wordpress.org">WordPress</a>.
887
  </p>
888
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
889
  </div>
890
 
891
  <?php
892
  }
893
 
894
- /**
895
- * Output welcome text and badge for What's New and Credits pages.
896
- *
897
- * @since 2.2.0
898
- */
899
- public static function welcome_text() {
900
-
901
- // Switch welcome text based on whether this is a new installation or not.
902
- $welcome_text = ( self::is_new_install() )
903
- ? __( 'Thank you for installing BuddyPress! BuddyPress adds community features to WordPress. Member Profiles, Activity Streams, Direct Messaging, Notifications, and more!', 'buddypress' )
904
- : __( 'Thank you for updating! BuddyPress %s has many new improvements that you will enjoy.', 'buddypress' );
905
-
906
- ?>
907
-
908
- <h1><?php printf( esc_html__( 'Welcome to BuddyPress %s', 'buddypress' ), self::display_version() ); ?></h1>
909
-
910
- <div class="about-text">
911
- <?php
912
- if ( self::is_new_install() ) {
913
- echo $welcome_text;
914
- } else {
915
- printf( $welcome_text, self::display_version() );
916
- }
917
- ?>
918
- </div>
919
-
920
- <div class="bp-badge"></div>
921
-
922
- <?php
923
- }
924
-
925
- /**
926
- * Output tab navigation for `What's New` and `Credits` pages.
927
- *
928
- * @since 2.2.0
929
- *
930
- * @param string $tab Tab to highlight as active.
931
- */
932
- public static function tab_navigation( $tab = 'whats_new' ) {
933
- ?>
934
-
935
- <h2 class="nav-tab-wrapper">
936
- <a class="nav-tab <?php if ( 'BP_Admin::about_screen' === $tab ) : ?>nav-tab-active<?php endif; ?>" href="<?php echo esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-about' ), 'index.php' ) ) ); ?>">
937
- <?php esc_html_e( 'What&#8217;s New', 'buddypress' ); ?>
938
- </a><a class="nav-tab <?php if ( 'BP_Admin::credits_screen' === $tab ) : ?>nav-tab-active<?php endif; ?>" href="<?php echo esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-credits' ), 'index.php' ) ) ); ?>">
939
- <?php esc_html_e( 'Credits', 'buddypress' ); ?>
940
- </a>
941
- </h2>
942
-
943
- <?php
944
- }
945
-
946
  /** Emails ****************************************************************/
947
 
948
  /**
@@ -1092,8 +1120,13 @@ class BP_Admin {
1092
  'file' => "{$url}customizer-controls{$min}.css",
1093
  'dependencies' => array(),
1094
  ),
1095
- ) );
1096
 
 
 
 
 
 
 
1097
 
1098
  $version = bp_get_version();
1099
 
@@ -1130,6 +1163,13 @@ class BP_Admin {
1130
  'dependencies' => array( 'jquery' ),
1131
  'footer' => true,
1132
  ),
 
 
 
 
 
 
 
1133
  ) );
1134
 
1135
  $version = bp_get_version();
155
  // Add settings.
156
  add_action( 'bp_register_admin_settings', array( $this, 'register_admin_settings' ) );
157
 
158
+ // Add a link to BuddyPress Hello in the admin bar.
159
+ add_action( 'admin_bar_menu', array( $this, 'admin_bar_about_link' ), 100 );
160
 
161
  // Add a description of new BuddyPress tools in the available tools page.
162
  add_action( 'tool_box', 'bp_core_admin_available_tools_intro' );
169
  add_filter( 'manage_' . bp_get_email_post_type() . '_posts_columns', array( $this, 'emails_register_situation_column' ) );
170
  add_action( 'manage_' . bp_get_email_post_type() . '_posts_custom_column', array( $this, 'emails_display_situation_column_data' ), 10, 2 );
171
 
172
+ // BuddyPress Hello.
173
+ add_action( 'admin_footer', array( $this, 'about_screen' ) );
174
+
175
  /* Filters ***********************************************************/
176
 
177
  // Add link to settings page.
200
  return;
201
  }
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  $hooks = array();
204
 
205
  // Changed in BP 1.6 . See bp_core_admin_backpat_menu().
249
  'bp_core_admin_settings'
250
  );
251
 
252
+ // Credits.
253
+ $hooks[] = add_submenu_page(
254
+ $this->settings_page,
255
+ __( 'BuddyPress Credits', 'buddypress' ),
256
+ __( 'BuddyPress Credits', 'buddypress' ),
257
+ $this->capability,
258
+ 'bp-credits',
259
+ array( $this, 'credits_screen' )
260
+ );
261
+
262
  // For consistency with non-Multisite, we add a Tools menu in
263
  // the Network Admin as a home for our Tools panel.
264
  if ( is_multisite() && bp_core_do_network_admin() ) {
331
 
332
  $hooks = array();
333
 
334
+ // Appearance > Emails.
335
+ $hooks[] = add_theme_page(
336
+ _x( 'Emails', 'screen heading', 'buddypress' ),
337
+ _x( 'Emails', 'screen heading', 'buddypress' ),
338
+ $this->capability,
339
+ 'bp-emails-customizer-redirect',
340
+ 'bp_email_redirect_to_customizer'
341
+ );
 
 
342
 
343
+ // Emails > Customize.
344
+ $hooks[] = add_submenu_page(
345
+ 'edit.php?post_type=' . bp_get_email_post_type(),
346
+ _x( 'Customize', 'email menu label', 'buddypress' ),
347
+ _x( 'Customize', 'email menu label', 'buddypress' ),
348
+ $this->capability,
349
+ 'bp-emails-customizer-redirect',
350
+ 'bp_email_redirect_to_customizer'
351
+ );
 
352
 
353
  foreach( $hooks as $hook ) {
354
  add_action( "admin_head-$hook", 'bp_core_modify_admin_menu_highlight' );
388
  register_setting( 'buddypress', 'bp-disable-account-deletion', 'intval' );
389
 
390
  // Template pack picker.
391
+ add_settings_field( '_bp_theme_package_id', __( 'Template Pack', 'buddypress' ), 'bp_admin_setting_callback_theme_package_id', 'buddypress', 'bp_main', array( 'label_for' => '_bp_theme_package_id' ) );
392
  register_setting( 'buddypress', '_bp_theme_package_id', 'sanitize_text_field' );
393
 
394
  /* XProfile Section **************************************************/
435
  }
436
  }
437
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  /* Activity Section **************************************************/
439
 
440
  if ( bp_is_active( 'activity' ) ) {
442
  // Add the main section.
443
  add_settings_section( 'bp_activity', __( 'Activity Settings', 'buddypress' ), 'bp_admin_setting_callback_activity_section', 'buddypress' );
444
 
445
+ // Activity commenting on post and comments.
446
+ add_settings_field( 'bp-disable-blogforum-comments', __( 'Post Comments', 'buddypress' ), 'bp_admin_setting_callback_blogforum_comments', 'buddypress', 'bp_activity' );
447
  register_setting( 'buddypress', 'bp-disable-blogforum-comments', 'bp_admin_sanitize_callback_blogforum_comments' );
448
 
449
  // Activity Heartbeat refresh.
459
  }
460
 
461
  /**
462
+ * Add a link to BuddyPress Hello to the admin bar.
463
  *
464
  * @since 1.9.0
465
+ * @since 3.0.0 Hooked at priority 100 (was 15).
466
  *
467
+ * @param WP_Admin_Bar $wp_admin_bar
468
  */
469
  public function admin_bar_about_link( $wp_admin_bar ) {
470
+ if ( ! is_user_logged_in() ) {
471
+ return;
 
 
 
 
 
472
  }
473
+
474
+ $wp_admin_bar->add_menu( array(
475
+ 'parent' => 'wp-logo',
476
+ 'id' => 'bp-about',
477
+ 'title' => esc_html_x( 'Hello, BuddyPress!', 'Colloquial alternative to "learn about BuddyPress"', 'buddypress' ),
478
+ 'href' => bp_get_admin_url( '?hello=buddypress' ),
479
+ 'meta' => array(
480
+ 'class' => 'say-hello-buddypress',
481
+ ),
482
+ ) );
483
  }
484
 
485
  /**
501
  // Add a few links to the existing links array.
502
  return array_merge( $links, array(
503
  'settings' => '<a href="' . esc_url( add_query_arg( array( 'page' => 'bp-components' ), bp_get_admin_url( $this->settings_page ) ) ) . '">' . esc_html__( 'Settings', 'buddypress' ) . '</a>',
504
+ 'about' => '<a href="' . esc_url( bp_get_admin_url( '?hello=buddypress' ) ) . '">' . esc_html_x( 'Hello, BuddyPress!', 'Colloquial alternative to "learn about BuddyPress"', 'buddypress' ) . '</a>'
505
  ) );
506
  }
507
 
515
  // Settings pages.
516
  remove_submenu_page( $this->settings_page, 'bp-page-settings' );
517
  remove_submenu_page( $this->settings_page, 'bp-settings' );
518
+ remove_submenu_page( $this->settings_page, 'bp-credits' );
519
 
520
  // Network Admin Tools.
521
  remove_submenu_page( 'network-tools', 'network-tools' );
532
  */
533
  public function enqueue_scripts() {
534
  wp_enqueue_style( 'bp-admin-common-css' );
535
+
536
+ // BuddyPress Hello
537
+ if ( 0 === strpos( get_current_screen()->id, 'dashboard' ) && ! empty( $_GET['hello'] ) && $_GET['hello'] === 'buddypress' ) {
538
+ wp_enqueue_style( 'bp-hello-css' );
539
+ wp_enqueue_script( 'bp-hello-js' );
540
+ }
541
  }
542
 
543
  /** About *****************************************************************/
544
 
545
  /**
546
+ * Output the BuddyPress Hello template.
547
  *
548
+ * @since 1.7.0 Screen content.
549
+ * @since 3.0.0 Now outputs BuddyPress Hello template.
550
  */
551
  public function about_screen() {
552
+ if ( 0 !== strpos( get_current_screen()->id, 'dashboard' ) || empty( $_GET['hello'] ) || $_GET['hello'] !== 'buddypress' ) {
553
+ return;
554
+ }
555
  ?>
556
 
557
+ <div id="bp-hello-backdrop" style="display: none;">
558
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
 
560
+ <div id="bp-hello-container" role="dialog" aria-labelledby="bp-hello-title" style="display: none;">
561
+ <div class="bp-hello-header" role="document">
562
+ <div class="bp-hello-close">
563
+ <button type="button" class="close-modal button bp-tooltip" data-bp-tooltip="<?php echo esc_attr( 'Close pop-up', 'buddypress' ); ?>">
564
+ <span class="screen-reader-text"><?php esc_html_e( 'Close pop-up', 'buddypress' ); ?></span>
565
+ </button>
566
  </div>
567
 
568
+ <div class="bp-hello-title">
569
+ <h1 id="bp-hello-title" tabindex="-1"><?php esc_html_e( _x( 'New in BuddyPress', 'section heading', 'buddypress' ) ); ?></h1>
 
 
 
 
570
  </div>
571
+ </div>
572
 
573
+ <div class="bp-hello-content">
574
+ <h2><?php echo esc_html( _n( 'Maintenance Release', 'Maintenance Releases', 1, 'buddypress' ) ); ?></h2>
575
+ <p>
576
+ <?php
577
+ printf(
578
+ /* translators: 1: BuddyPress version number, 2: plural number of bugs. */
579
+ _n(
580
+ '<strong>Version %1$s</strong> addressed %2$s bug.',
581
+ '<strong>Version %1$s</strong> addressed %2$s bugs.',
582
+ 23,
583
+ 'buddypress'
584
+ ),
585
+ '3.2.0',
586
+ number_format_i18n( 25 )
587
+ );
588
+ ?>
589
+ </p>
590
+ <p>
591
+ <?php
592
+ printf(
593
+ /* translators: 1: BuddyPress version number, 2: plural number of bugs. */
594
+ _n(
595
+ '<strong>Version %1$s</strong> addressed %2$s bug.',
596
+ '<strong>Version %1$s</strong> addressed %2$s bugs.',
597
+ 23,
598
+ 'buddypress'
599
+ ),
600
+ '3.1.0',
601
+ number_format_i18n( 23 )
602
+ );
603
+ ?>
604
+ </p>
605
+
606
+ <hr>
607
+ <h2><?php esc_html_e( __( 'Say hello to &ldquo;Nouveau&rdquo;!', 'buddypress' ) ); ?></h2>
608
+ <p>
609
+ <?php
610
+ printf(
611
+ __( 'A bold reimagining of our legacy templates, Nouveau is our celebration of <a href="%s">10 years of BuddyPress</a>! Nouveau delivers modern markup with fresh JavaScript-powered templates, and full integration with WordPress\' Customizer, allowing more out-of-the-box control of your BuddyPress content than ever before.', 'buddypress' ),
612
+ esc_url( 'https://buddypress.org/2018/03/10-years/' )
613
+ );
614
+ ?>
615
+ </p>
616
+ <p><?php esc_html_e( 'Nouveau provides vertical and horizontal layout options for BuddyPress navigation, and for the component directories, you can choose between a grid layout, and a classic flat list.', 'buddypress' ); ?></p>
617
+ <p>
618
+ <?php
619
+ printf(
620
+ __( 'Nouveau is fully compatible with WordPress. Existing BuddyPress themes have been written for our legacy template pack, and until they are updated, resolve any compatibility issues by choosing the legacy template pack option in <a href="%s">Settings &gt; BuddyPress</a>.', 'buddypress' ),
621
+ esc_url( bp_get_admin_url( 'admin.php?page=bp-settings' ) )
622
+ );
623
+ ?>
624
+ </p>
625
+
626
+ <?php echo $GLOBALS['wp_embed']->autoembed( 'https://player.vimeo.com/video/270507360' ); ?>
627
+
628
+ <h2><?php esc_html_e( __( 'Support for WP-CLI', 'buddypress' ) ); ?></h2>
629
+ <p>
630
+ <?php
631
+ printf(
632
+ __( '<a href="%s">WP-CLI</a> is the command-line interface for WordPress. You can update plugins, configure multisite installs, and much more, without using a web browser. With this version of BuddyPress, you can now manage your BuddyPress content from WP-CLI.', 'buddypress' ),
633
+ esc_url( 'https://wp-cli.org' )
634
+ );
635
+ ?>
636
+ </p>
637
+
638
+ <h2><?php esc_html_e( _x( 'Control site-wide notices from your dashboard', 'section heading', 'buddypress' ) ); ?></h2>
639
+ <p><?php esc_html_e( 'Site Notices are a feature within the Private Messaging component that allows community managers to share important messages with all members of their community. With Nouveau, the management interface for Site Notices has been removed from the front-end theme templates.', 'buddypress' ); ?></p>
640
+
641
+ <?php if ( bp_is_active( 'messages' ) ) : ?>
642
+ <p>
643
+ <?php
644
+ printf(
645
+ __( 'Explore the new management interface at <a href="%s">Users &gt; Site Notices</a>.', 'buddypress' ),
646
+ esc_url( bp_get_admin_url( 'users.php?page=bp-notices' ) )
647
+ );
648
+ ?>
649
+ </p>
650
+ <?php endif; ?>
651
+
652
+ <h2><?php esc_html_e( __( 'New profile field type: telephone numbers', 'buddypress' ) ); ?></h2>
653
+ <p><?php esc_html_e( 'A new telephone number field type has been added to the Extended Profiles component, with support for all international number formats. With a modern web browser, your members can use this field type to touch-to-dial a number directly.', 'buddypress' ); ?></p>
654
+
655
+ <h2><?php esc_html_e( __( "BuddyPress: leaner, faster, stronger", 'buddypress' ) ); ?></h2>
656
+ <p><?php esc_html_e( 'With every BuddyPress version, we strive to make performance improvements alongside new features and fixes; this version is no exception. Memory use has been optimised &mdash; within active components, we now only load each individual code file when it\'s needed, not before.', 'buddypress' ); ?></p>
657
+ <p>
658
+ <?php
659
+ printf(
660
+ __( 'Most notably, the <a href="%s">Legacy Forums component has been removed</a> after 9 years of service. If your site was using Legacy Forums, you need to <a href="%s">migrate to the bbPress plugin</a>.', 'buddypress' ),
661
+ esc_url( 'https://bpdevel.wordpress.com/2017/12/07/legacy-forums-support-will-be/' ),
662
+ esc_url( 'https://codex.buddypress.org/getting-started/guides/migrating-from-old-forums-to-bbpress-2/' )
663
+ );
664
+ ?>
665
+ </p>
666
+
667
+ <p><em>
668
+ <?php
669
+ printf(
670
+ __( 'To read the full list of features, fixes, and changes in this version of BuddyPress, <a href="%s">visit Trac</a>.', 'buddypress' ),
671
+ esc_url( 'https://buddypress.trac.wordpress.org/query?group=status&milestone=3.0' )
672
+ );
673
+ ?>
674
+ </em></p>
675
+
676
+ <h2><?php esc_html_e( _x( 'Your feedback', 'screen heading', 'buddypress' ) ); ?></h2>
677
+ <p>
678
+ <?php
679
+ printf(
680
+ __( ' How are you using BuddyPress? Receiving your feedback and suggestions for future versions of BuddyPress genuinely motivates and encourages our contributors. Please <a href="%s">share your feedback</a> about this version of BuddyPress on our website. ', 'buddypress' ),
681
+ esc_url( 'https://buddypress.org/support/' )
682
+ );
683
+ ?>
684
+ </p>
685
+ <p><?php esc_html_e( 'Thank you for using BuddyPress! 😊', 'buddypress' ); ?></p>
686
+
687
+ <br /><br />
688
  </div>
689
 
690
+ <div class="bp-hello-footer">
691
+ <div class="bp-hello-social-cta">
692
+ <p>
693
+ <?php
694
+ printf(
695
+ _n( 'Built by <a href="%s">%s volunteer</a>.', 'Built by <a href="%s">%s volunteers</a>.', 57, 'buddypress' ),
696
+ esc_url( bp_get_admin_url( 'admin.php?page=bp-credits' ) ),
697
+ number_format_i18n( 57 )
698
+ );
699
+ ?>
700
+ </p>
 
 
 
 
 
 
701
  </div>
702
 
703
+ <div class="bp-hello-social-links">
704
+ <ul class="bp-hello-social">
705
+ <li>
706
+ <?php
707
+ printf(
708
+ '<a class="twitter bp-tooltip" data-bp-tooltip="%1$s" href="%2$s"><span class="screen-reader-text">%3$s</span></a>',
709
+ esc_attr( 'Follow BuddyPress on Twitter', 'buddypress' ),
710
+ esc_url( 'https://twitter.com/buddypress' ),
711
+ esc_html( 'Follow BuddyPress on Twitter', 'buddypress' )
712
+ );
713
+ ?>
714
+ </li>
715
+
716
+ <li>
717
+ <?php
718
+ printf(
719
+ '<a class="support bp-tooltip" data-bp-tooltip="%1$s" href="%2$s"><span class="screen-reader-text">%3$s</span></a>',
720
+ esc_attr( 'Visit the Support Forums', 'buddypress' ),
721
+ esc_url( 'https://buddypress.org/support/' ),
722
+ esc_html( 'Visit the Support Forums', 'buddypress' )
723
+ );
724
+ ?>
725
+ </li>
726
+ </ul>
727
  </div>
 
 
 
 
 
 
 
728
  </div>
 
729
  </div>
730
 
731
  <?php
742
  public function credits_screen() {
743
  ?>
744
 
745
+ <div class="wrap bp-about-wrap">
746
 
747
+ <h1><?php _e( 'BuddyPress Settings', 'buddypress' ); ?> </h1>
748
 
749
+ <h2 class="nav-tab-wrapper"><?php bp_core_admin_tabs( __( 'Credits', 'buddypress' ) ); ?></h2>
750
 
751
+ <p class="about-description"><?php _e( 'Meet the contributors behind BuddyPress:', 'buddypress' ); ?></p>
752
 
753
  <h3 class="wp-people-group"><?php _e( 'Project Leaders', 'buddypress' ); ?></h3>
754
  <ul class="wp-people-group " id="wp-people-group-project-leaders">
755
  <li class="wp-person" id="wp-person-johnjamesjacoby">
756
+ <a class="web" href="https://profiles.wordpress.org/johnjamesjacoby"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7a2644fb53ae2f7bfd7143b504af396c?s=120">
757
  John James Jacoby</a>
758
  <span class="title"><?php _e( 'Project Lead', 'buddypress' ); ?></span>
759
  </li>
760
  <li class="wp-person" id="wp-person-boonebgorges">
761
+ <a class="web" href="https://profiles.wordpress.org/boonebgorges"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/9cf7c4541a582729a5fc7ae484786c0c?s=120">
762
  Boone B. Gorges</a>
763
  <span class="title"><?php _e( 'Lead Developer', 'buddypress' ); ?></span>
764
  </li>
765
  <li class="wp-person" id="wp-person-djpaul">
766
+ <a class="web" href="https://profiles.wordpress.org/djpaul"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3bc9ab796299d67ce83dceb9554f75df?s=120">
767
  Paul Gibbs</a>
768
+ <span class="title"><?php _e( 'Release Lead', 'buddypress' ); ?></span>
769
  </li>
770
  </ul>
771
 
772
  <h3 class="wp-people-group"><?php _e( 'BuddyPress Team', 'buddypress' ); ?></h3>
773
  <ul class="wp-people-group " id="wp-people-group-core-team">
 
 
 
 
 
774
  <li class="wp-person" id="wp-person-r-a-y">
775
+ <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3bfa556a62b5bfac1012b6ba5f42ebfa?s=120">
776
  Ray</a>
777
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
778
  </li>
779
+ <li class="wp-person" id="wp-person-hnla">
780
+ <a class="web" href="https://profiles.wordpress.org/hnla"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/3860c955aa3f79f13b92826ae47d07fe?s=120">
781
+ Hugo Ashmore</a>
782
+ <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
783
+ </li>
784
  <li class="wp-person" id="wp-person-imath">
785
+ <a class="web" href="https://profiles.wordpress.org/imath"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/8b208ca408dad63888253ee1800d6a03?s=120">
786
  Mathieu Viet</a>
787
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
788
  </li>
789
  <li class="wp-person" id="wp-person-mercime">
790
+ <a class="web" href="https://profiles.wordpress.org/mercime"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/fae451be6708241627983570a1a1817a?s=120">
791
  Mercime</a>
792
  <span class="title"><?php _e( 'Navigator', 'buddypress' ); ?></span>
793
  </li>
794
  <li class="wp-person" id="wp-person-dcavins">
795
+ <a class="web" href="https://profiles.wordpress.org/dcavins"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/a5fa7e83d59cb45ebb616235a176595a?s=120">
796
  David Cavins</a>
797
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
798
  </li>
799
  <li class="wp-person" id="wp-person-tw2113">
800
+ <a class="web" href="https://profiles.wordpress.org/tw2113"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/a5d7c934621fa1c025b83ee79bc62366?s=120">
801
  Michael Beckwith</a>
802
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
803
  </li>
804
  <li class="wp-person" id="wp-person-henry-wright">
805
+ <a class="web" href="https://profiles.wordpress.org/henry.wright"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0da2f1a9340d6af196b870f6c107a248?s=120">
806
  Henry Wright</a>
807
  <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
808
  </li>
809
  <li class="wp-person" id="wp-person-danbp">
810
+ <a class="web" href="https://profiles.wordpress.org/danbp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/0deae2e7003027fbf153500cd3fa5501?s=120">
811
  danbp</a>
812
  <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
813
  </li>
814
  <li class="wp-person" id="wp-person-shanebp">
815
+ <a class="web" href="https://profiles.wordpress.org/shanebp"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ffd294ab5833ba14aaf175f9acc71cc4?s=120">
816
  shanebp</a>
817
  <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
818
  </li>
819
  <li class="wp-person" id="wp-person-slaffik">
820
+ <a class="web" href="https://profiles.wordpress.org/r-a-y"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/61fb07ede3247b63f19015f200b3eb2c?s=120">
821
  Slava Abakumov</a>
822
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
823
  </li>
824
  <li class="wp-person" id="wp-person-offereins">
825
+ <a class="web" href="https://profiles.wordpress.org/Offereins"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/2404ed0a35bb41aedefd42b0a7be61c1?s=120">
826
  Laurens Offereins</a>
827
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
828
  </li>
829
  <li class="wp-person" id="wp-person-netweb">
830
+ <a class="web" href="https://profiles.wordpress.org/netweb"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/97e1620b501da675315ba7cfb740e80f?s=120">
831
  Stephen Edgar</a>
832
  <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
833
  </li>
834
+ <li class="wp-person" id="wp-person-espellcaste">
835
+ <a class="web" href="https://profiles.wordpress.org/espellcaste"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/b691e67be0ba5cad6373770656686bc3?s=120">
836
+ Renato Alves</a>
837
+ <span class="title"><?php _e( 'Core Developer', 'buddypress' ); ?></span>
838
+ </li>
839
+ <li class="wp-person" id="wp-person-venutius">
840
+ <a class="web" href="https://profiles.wordpress.org/venutius"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/6a7c42a77fd94b82b217a7a97afdddbc?s=120">
841
+ Venutius</a>
842
+ <span class="title"><?php _e( 'Community Support', 'buddypress' ); ?></span>
843
+ </li>
844
  </ul>
845
 
846
+ <h3 class="wp-people-group"><?php _e( 'Recent Rockstars', 'buddypress' ); ?></h3>
847
  <ul class="wp-people-group " id="wp-people-group-rockstars">
848
  <li class="wp-person" id="wp-person-dimensionmedia">
849
+ <a class="web" href="https://profiles.wordpress.org/dimensionmedia"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7735aada1ec39d0c1118bd92ed4551f1?s=120">
850
  David Bisset</a>
851
  </li>
852
  <li class="wp-person" id="wp-person-garrett-eclipse">
853
+ <a class="web" href="https://profiles.wordpress.org/garrett-eclipse"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/7f68f24441c61514d5d0e1451bb5bc9d?s=120">
854
  Garrett Hyder</a>
855
  </li>
856
  <li class="wp-person" id="wp-person-thebrandonallen">
857
+ <a class="web" href="https://profiles.wordpress.org/thebrandonallen"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/6d3f77bf3c9ca94c406dea401b566950?s=120">
858
  Brandon Allen</a>
859
  </li>
860
  <li class="wp-person" id="wp-person-ramiy">
861
+ <a class="web" href="https://profiles.wordpress.org/ramiy"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ce2a269e424156d79cb0c4e1d4d82db1?s=120">
862
  Rami Yushuvaev</a>
863
  </li>
864
+ <li class="wp-person" id="wp-person-vapvarun">
865
+ <a class="web" href="https://profiles.wordpress.org/vapvarun"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/78a3bf7eb3a1132fc667f96f2631e448?s=120">
866
+ Vapvarun</a>
867
+ </li>
868
  </ul>
869
 
870
  <h3 class="wp-people-group"><?php printf( esc_html__( 'Contributors to BuddyPress %s', 'buddypress' ), self::display_version() ); ?></h3>
871
  <p class="wp-credits-list">
872
+ <a href="https://profiles.wordpress.org/1naveengiri">1naveengiri</a>,
873
+ <a href="https://profiles.wordpress.org/abhishekfdd/">Abhishek Kumar (abhishekfdd)</a>,
874
+ <a href="https://profiles.wordpress.org/andrewteg/">Andrew Tegenkamp (andrewteg)</a>,
875
+ <a href="https://profiles.wordpress.org/ankit-k-gupta/">Ankit K Gupta (ankit-k-gupta)</a>,
876
  <a href="https://profiles.wordpress.org/antonioeatgoat/">Antonio Mangiacapra (antonioeatgoat)</a>,
 
877
  <a href="https://profiles.wordpress.org/boonebgorges/">Boone B Gorges (boonebgorges)</a>,
878
+ <a href="https://profiles.wordpress.org/thebrandonallen/">Brandon Allen (thebrandonallen)</a>,
879
+ <a href="https://profiles.wordpress.org/brandonliles/">brandonliles</a>,
880
  <a href="https://profiles.wordpress.org/sbrajesh/">Brajesh Singh (sbrajesh)</a>,
881
+ <a href="https://profiles.wordpress.org/ketuchetan/">chetansatasiya (ketuchetan)</a>,
882
+ <a href="https://profiles.wordpress.org/chherbst/">chherbst</a>,
883
  <a href="https://profiles.wordpress.org/needle/">Christian Wach (needle)</a>,
884
+ <a href="https://profiles.wordpress.org/coach-afrane/">Coach Afrane</a>,
885
+ <a href="https://profiles.wordpress.org/cshinkin/">cshinkin</a>,
886
  <a href="https://profiles.wordpress.org/danbp/">danbp</a>,
887
  <a href="https://profiles.wordpress.org/dcavins/">David Cavins (dcavins)</a>,
888
+ <a href="https://profiles.wordpress.org/devitate/">devitate</a>,
889
+ <a href="https://profiles.wordpress.org/garrett-eclipse/">Garrett Hyder (garrett-eclipse)</a>,
890
+ <a href="https://profiles.wordpress.org/geminorum/">geminorum</a>,
891
+ <a href="https://profiles.wordpress.org/Mamaduka/">George Mamadashvili (Mamaduka)</a>,
892
+ <a href="https://profiles.wordpress.org/januzi_pl/">januzi_pl</a>,
893
+ <a href="https://profiles.wordpress.org/jcrr/">jcrr</a>,
894
+ <a href="https://profiles.wordpress.org/jdgrimes/">J.D. Grimes (jdgrimes)</a>,
895
+ <a href="https://profiles.wordpress.org/JohnPBloch/">John P. Bloch (JohnPBloch)</a>,
896
+ <a href="https://profiles.wordpress.org/joost-abrahams/">Joost Abrahams (joost-abrahams)</a>,
897
  <a href="https://profiles.wordpress.org/henry.wright">Henry Wright (henry.wright)</a>,
898
  <a href="https://profiles.wordpress.org/hnla/">Hugo (hnla)</a>,
899
  <a href="https://profiles.wordpress.org/idofri/">Ido Friedlander (idofri)</a>,
900
+ <a href="https://profiles.wordpress.org/dunhakdis/">Joseph G. (dunhakdis)</a>,
 
901
  <a href="https://profiles.wordpress.org/johnjamesjacoby/">John James Jacoby (johnjamesjacoby)</a>,
 
 
902
  <a href="https://profiles.wordpress.org/Offereins">Laurens Offereins (Offereins)</a>,
903
+ <a href="https://profiles.wordpress.org/mechter/">Markus Echterhoff (mechter)</a>,
 
 
904
  <a href="https://profiles.wordpress.org/imath/">Mathieu Viet (imath)</a>,
905
+ <a href="https://profiles.wordpress.org/meitar/">meitar</a>,
906
  <a href="https://profiles.wordpress.org/mercime/">mercime</a>,
907
  <a href="https://profiles.wordpress.org/tw2113/">Michael Beckwith (tw2113)</a>,
908
+ <a href="https://profiles.wordpress.org/mauteri/">Mike Auteri (mauteri)</a>,
 
909
  <a href="https://profiles.wordpress.org/modemlooper/">modemlooper</a>,
910
+ <a href="https://profiles.wordpress.org/m_uysl/">Mustafa Uysal (m_uysl)</a>,
 
 
 
911
  <a href="https://profiles.wordpress.org/pareshradadiya/">paresh.radadiya (pareshradadiya)</a>,
912
+ <a href="https://profiles.wordpress.org/DJPaul/">Paul Gibbs (DJPaul)</a>,
913
+ <a href="https://profiles.wordpress.org/pavloopanasenko/">pavlo.opanasenko (pavloopanasenko)</a>,
914
+ <a href="https://profiles.wordpress.org/pscolv/">pscolv</a>,
915
  <a href="https://profiles.wordpress.org/r-a-y/">r-a-y</a>,
916
+ <a href="https://profiles.wordpress.org/rachelbaker/">Rachel Baker (rachelbaker)</a>,
917
+ <a href="https://profiles.wordpress.org/rekmla/">rekmla</a>,
918
  <a href="https://profiles.wordpress.org/espellcaste/">Renato Alves (espellcaste)</a>,
919
  <a href="https://profiles.wordpress.org/rianrietveld/">Rian Rietveld (rianrietvelde)</a>,
920
+ <a href="https://profiles.wordpress.org/ripstechcom/">ripstechcom</a>,
921
+ <a href="https://profiles.wordpress.org/cyclic/">Ryan Williams (cyclic)</a>,
922
  <a href="https://profiles.wordpress.org/slaffik/">Slava Abakumov (slaffik)</a>,
923
  <a href="https://profiles.wordpress.org/netweb/">Stephen Edgar (netweb)</a>,
924
+ <a href="https://profiles.wordpress.org/tobiashonold/">Tobias Honold (tobiashonold)</a>,
925
+ <a href="https://profiles.wordpress.org/uzosky/">uzosky</a>,
926
+ <a href="https://profiles.wordpress.org/vapvarun/">vapvarun</a>,
927
+ <a href="https://profiles.wordpress.org/Venutius/">Venutius</a>,
928
+ <a href="https://profiles.wordpress.org/yahil/">Yahil Madakiya (yahil)</a>
929
  </p>
930
 
931
+ <h3 class="wp-people-group"><?php _e( 'With our thanks to these Open Source projects', 'buddypress' ); ?></h3>
932
  <p class="wp-credits-list">
933
  <a href="https://github.com/ichord/At.js">At.js</a>,
934
  <a href="https://bbpress.org">bbPress</a>,
938
  <a href="https://github.com/carhartl/jquery-cookie">jquery.cookie</a>,
939
  <a href="https://mattbradley.github.io/livestampjs/">Livestamp.js</a>,
940
  <a href="https://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a>,
941
+ <a href="https://momentjs.com/">Moment.js</a>,
942
  <a href="https://wordpress.org">WordPress</a>.
943
  </p>
944
 
945
+ <h3 class="wp-people-group"><?php _e( 'Contributor Emeriti', 'buddypress' ); ?></h3>
946
+ <ul class="wp-people-group " id="wp-people-group-emeriti">
947
+ <li class="wp-person" id="wp-person-apeatling">
948
+ <a class="web" href="https://profiles.wordpress.org/johnjamesjacoby"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/bb29d699b5cba218c313b61aa82249da?s=120">
949
+ Andy Peatling</a>
950
+ <span class="title"><?php _e( 'Project Founder', 'buddypress' ); ?></span>
951
+ </li>
952
+ <li class="wp-person" id="wp-person-burtadsit">
953
+ <a class="web" href="https://profiles.wordpress.org/burtadsit"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/185e1d3e2d653af9d49a4e8e4fc379df?s=120">
954
+ Burt Adsit</a>
955
+ </li>
956
+ <li class="wp-person" id="wp-person-jeffsayre">
957
+ <a class="web" href="https://profiles.wordpress.org/jeffsayre"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/8e009a84ff5d245c22a69c7df6ab45f7?s=120">
958
+ Jeff Sayre</a>
959
+ </li>
960
+ <li class="wp-person" id="wp-person-karmatosed">
961
+ <a class="web" href="https://profiles.wordpress.org/karmatosed"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/ca7d4273a689cdbf524d8332771bb1ca?s=120">
962
+ Tammie Lister</a>
963
+ </li>
964
+ <li class="wp-person" id="wp-person-modemlooper">
965
+ <a class="web" href="https://profiles.wordpress.org/modemlooper"><img alt="" class="gravatar" src="//www.gravatar.com/avatar/1c07be1016e845de514931477c939307?s=120">
966
+ modemlooper</a>
967
+ </li>
968
+ </ul>
969
  </div>
970
 
971
  <?php
972
  }
973
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
974
  /** Emails ****************************************************************/
975
 
976
  /**
1120
  'file' => "{$url}customizer-controls{$min}.css",
1121
  'dependencies' => array(),
1122
  ),
 
1123
 
1124
+ // 3.0
1125
+ 'bp-hello-css' => array(
1126
+ 'file' => "{$url}hello{$min}.css",
1127
+ 'dependencies' => array( 'bp-admin-common-css' ),
1128
+ ),
1129
+ ) );
1130
 
1131
  $version = bp_get_version();
1132
 
1163
  'dependencies' => array( 'jquery' ),
1164
  'footer' => true,
1165
  ),
1166
+
1167
+ // 3.0
1168
+ 'bp-hello-js' => array(
1169
+ 'file' => "{$url}hello{$min}.js",
1170
+ 'dependencies' => array(),
1171
+ 'footer' => true,
1172
+ ),
1173
  ) );
1174
 
1175
  $version = bp_get_version();
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
  /**
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
  /**
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-nav.php CHANGED
@@ -352,7 +352,7 @@ class BP_Core_Nav {
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 array The list of secondary objects nav
356
  */
357
  public function get_secondary( $args = array(), $sort = true ) {
358
  $params = wp_parse_args( $args, array( 'parent_slug' => '' ) );
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' => '' ) );
bp-core/classes/class-bp-core-user.php CHANGED
@@ -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 ) );
@@ -749,18 +744,13 @@ class BP_Core_User {
749
  /**
750
  * Get WordPress user details for a specified user.
751
  *
752
- * @global wpdb $wpdb WordPress database object.
753
  *
754
  * @param int $user_id User ID.
755
- * @return array Associative array.
756
  */
757
  public static function get_core_userdata( $user_id ) {
758
- global $wpdb;
759
-
760
- if ( !$user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->users} WHERE ID = %d LIMIT 1", $user_id ) ) )
761
- return false;
762
-
763
- return $user;
764
  }
765
 
766
  /**
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 ) );
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
  /**
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.
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.
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-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-user-query.php CHANGED
@@ -413,13 +413,16 @@ class BP_User_Query {
413
  $search_terms_space = '%' . $search_terms . '%';
414
  }
415
 
416
- $sql['where']['search'] = $wpdb->prepare(
417
- "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 ) )",
418
  $search_terms_nospace,
419
  $search_terms_space,
420
  $search_terms_nospace,
421
  $search_terms_space
422
- );
 
 
 
423
  }
424
 
425
  // Only use $member_type__in if $member_type is not set.
@@ -570,14 +573,6 @@ class BP_User_Query {
570
 
571
  ), $this ) );
572
 
573
- // WP_User_Query doesn't cache the data it pulls from wp_users,
574
- // and it does not give us a way to save queries by fetching
575
- // only uncached users. However, BP does cache this data, so
576
- // we set it here.
577
- foreach ( $wp_user_query->results as $u ) {
578
- wp_cache_set( 'bp_core_userdata_' . $u->ID, $u, 'bp' );
579
- }
580
-
581
  // We calculate total_users using a standalone query, except
582
  // when a whitelist of user_ids is passed to the constructor.
583
  // This clause covers the latter situation, and ensures that
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
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
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
bp-core/deprecated/2.8.php CHANGED
@@ -19,6 +19,7 @@ defined( 'ABSPATH' ) || exit;
19
  * @return bool
20
  */
21
  function bp_core_admin_is_running_php53_or_greater() {
 
22
  return version_compare( PHP_VERSION, '5.3', '>=' );
23
  }
24
 
@@ -70,6 +71,8 @@ function bp_core_admin_maybe_remove_from_update_core() {
70
  * @return object
71
  */
72
  function bp_core_admin_remove_buddypress_from_update_transient( $retval ) {
 
 
73
  $loader = basename( constant( 'BP_PLUGIN_DIR' ) ) . '/bp-loader.php';
74
 
75
  // Remove BP from update plugins list.
@@ -96,6 +99,8 @@ function bp_core_admin_remove_buddypress_from_update_transient( $retval ) {
96
  * plugins API.
97
  */
98
  function bp_core_admin_php52_plugin_row( $file, $plugin_data ) {
 
 
99
  if ( is_multisite() && ! is_network_admin() ) {
100
  return;
101
  }
@@ -156,6 +161,8 @@ function bp_core_admin_php52_plugin_row( $file, $plugin_data ) {
156
  * @deprecated 2.8.0
157
  */
158
  function bp_core_admin_php53_admin_notice() {
 
 
159
  // If not on the Plugins page, stop now.
160
  if ( 'plugins' !== get_current_screen()->parent_base ) {
161
  return;
@@ -184,14 +191,11 @@ function bp_core_admin_php53_admin_notice() {
184
  bp_get_version(),
185
  true
186
  );
187
-
188
- $php_version = PHP_VERSION;
189
-
190
  ?>
191
 
192
  <div id="message" class="error notice is-dismissible bp-is-dismissible" data-noticeid="<?php echo esc_attr( $notice_id ); ?>">
193
  <p><strong><?php esc_html_e( 'Your site is not ready for BuddyPress 2.8.', 'buddypress' ); ?></strong></p>
194
- <p><?php printf( esc_html__( 'Your site is currently running PHP version %s, while BuddyPress 2.8 will require version 5.3+.', 'buddypress' ), $php_version ); ?> <?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>
195
  <?php wp_nonce_field( "bp-dismissible-notice-$notice_id", "bp-dismissible-nonce-$notice_id" ); ?>
196
  </div>
197
  <?php
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
 
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.
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
  }
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;
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
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/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)})});
1
+ jQuery(document).ready(function(){jQuery("#buddypress").on("click","a.confirm",function(){return!!confirm(BP_Confirm.are_you_sure)})});
bp-core/js/vendor/jquery.atwho.js CHANGED
@@ -1,76 +1,180 @@
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
  }
@@ -79,58 +183,87 @@ App = (function() {
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
  }
@@ -138,54 +271,46 @@ App = (function() {
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
  }
@@ -218,11 +343,22 @@ App = (function() {
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();
@@ -233,20 +369,23 @@ App = (function() {
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>"));
@@ -268,70 +407,185 @@ Controller = (function() {
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 {
@@ -341,126 +595,263 @@ Controller = (function() {
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) {
@@ -478,15 +869,15 @@ Model = (function() {
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
 
@@ -495,7 +886,7 @@ Model = (function() {
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) {
@@ -526,18 +917,25 @@ Model = (function() {
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
  });
@@ -547,13 +945,27 @@ View = (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');
@@ -564,25 +976,30 @@ View = (function() {
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
  }
@@ -593,46 +1010,57 @@ View = (function() {
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);
@@ -649,7 +1077,6 @@ View = (function() {
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 {
@@ -658,32 +1085,32 @@ View = (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
  };
@@ -692,125 +1119,7 @@ View = (function() {
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) {
@@ -819,8 +1128,22 @@ Api = {
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() {
@@ -833,7 +1156,7 @@ Api = {
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() {
@@ -846,30 +1169,44 @@ $.fn.atwho = function(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
  }));
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
  }
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
  }
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
  }
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();
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>"));
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 {
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) {
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
 
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) {
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
  });
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');
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
  }
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);
1077
  return;
1078
  }
1079
  if (isNaN(time)) {
 
1080
  this.$el.hide();
1081
  return this.context.trigger('hidden', [e]);
1082
  } else {
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
  };
1119
 
1120
  })();
1121
 
1122
+ var Api;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1123
 
1124
  Api = {
1125
  load: function(at, data) {
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() {
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() {
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 CHANGED
@@ -1 +1 @@
1
- !function(t,e){"function"==typeof define&&define.amd?define(["jquery"],function(i){return t.returnExportsGlobal=e(i)}):"object"==typeof exports?module.exports=e(require("jquery")):e(jQuery)}(this,function(t){var e,i,n,r,o,s,a,h=[].slice;i=function(){function e(e){this.current_flag=null,this.controllers={},this.alias_maps={},this.$inputor=t(e),this.setIframe(),this.listen()}return e.prototype.createContainer=function(e){if(0===(this.$el=t("#atwho-container",e)).length)return t(e.body).append(this.$el=t("<div id='atwho-container'></div>"))},e.prototype.setIframe=function(t,e){var i;return null==e&&(e=!1),t?(this.window=t.contentWindow,this.document=t.contentDocument||this.window.document,this.iframe=t):(this.document=document,this.window=window,this.iframe=null),(this.iframeStandalone=e)?(null!=(i=this.$el)&&i.remove(),this.createContainer(this.document)):this.createContainer(document)},e.prototype.controller=function(t){var e,i,n,r;if(this.alias_maps[t])i=this.controllers[this.alias_maps[t]];else{r=this.controllers;for(n in r)if(e=r[n],n===t){i=e;break}}return i||this.controllers[this.current_flag]},e.prototype.set_context_for=function(t){return this.current_flag=t,this},e.prototype.reg=function(t,e){var i,r;return i=(r=this.controllers)[t]||(r[t]=new n(this,t)),e.alias&&(this.alias_maps[e.alias]=t),i.init(e),this},e.prototype.listen=function(){return this.$inputor.on("keyup.atwhoInner",function(t){return function(e){return t.on_keyup(e)}}(this)).on("keydown.atwhoInner",function(t){return function(e){return t.on_keydown(e)}}(this)).on("scroll.atwhoInner",function(t){return function(e){var i;return null!=(i=t.controller())?i.view.hide(e):void 0}}(this)).on("blur.atwhoInner",function(t){return function(e){var i;if(i=t.controller())return i.view.hide(e,i.get_opt("display_timeout"))}}(this)).on("click.atwhoInner",function(t){return function(e){return t.dispatch()}}(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(){return t.map(this.controllers,function(t){return function(e){var i;return(i=e.get_opt("delay"))?(clearTimeout(t.delayedCallback),t.delayedCallback=setTimeout(function(){if(e.look_up())return t.set_context_for(e.at)},i)):e.look_up()?t.set_context_for(e.at):void 0}}(this))},e.prototype.on_keyup=function(e){var i;switch(e.keyCode){case o.ESC:e.preventDefault(),null!=(i=this.controller())&&i.view.hide();break;case o.DOWN:case o.UP:case o.CTRL:t.noop();break;case o.P:case o.N:e.ctrlKey||this.dispatch();break;default:this.dispatch()}},e.prototype.on_keydown=function(e){var i,n;if((i=null!=(n=this.controller())?n.view:void 0)&&i.visible())switch(e.keyCode){case o.ESC:e.preventDefault(),i.hide(e);break;case o.UP:e.preventDefault(),i.prev();break;case o.DOWN:e.preventDefault(),i.next();break;case o.P:if(!e.ctrlKey)return;e.preventDefault(),i.prev();break;case o.N:if(!e.ctrlKey)return;e.preventDefault(),i.next();break;case o.TAB:case o.ENTER:if(!i.visible())return;e.preventDefault(),i.choose(e);break;default:t.noop()}},e}(),n=function(){function e(e,i){this.app=e,this.at=i,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=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 s(this),this.view=new a(this)}return e.prototype.uid=function(){return(Math.random().toString(16)+"000000000").substr(2,8)+(new Date).getTime()},e.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)},e.prototype.destroy=function(){return this.trigger("beforeDestroy"),this.model.destroy(),this.view.destroy(),this.$el.remove()},e.prototype.call_default=function(){var e,i,n;n=arguments[0],e=2<=arguments.length?h.call(arguments,1):[];try{return r[n].apply(this,e)}catch(e){return i=e,t.error(i+" Or maybe At.js doesn't have function "+n)}},e.prototype.trigger=function(t,e){var i,n;return null==e&&(e=[]),e.push(this),i=this.get_opt("alias"),n=i?t+"-"+i+".atwho":t+".atwho",this.$inputor.trigger(n,e)},e.prototype.callbacks=function(t){return this.get_opt("callbacks")[t]||r[t]},e.prototype.get_opt=function(t,e){try{return this.setting[t]}catch(t){return t,null}},e.prototype.content=function(){var t;if(this.$inputor.is("textarea, input"))return this.$inputor.val();if(t=this.mark_range())return(t.startContainer.textContent||"").slice(0,t.startOffset)},e.prototype.catch_query=function(){var t,e,i,n,r,o;return e=this.content(),t=this.$inputor.caret("pos",{iframe:this.app.iframe}),o=e.slice(0,t),"string"==typeof(n=this.callbacks("matcher").call(this,this.at,o,this.get_opt("start_with_space")))&&n.length<=this.get_opt("max_len",20)?(i=(r=t-n.length)+n.length,this.pos=r,n={text:n,head_pos:r,end_pos:i},this.trigger("matched",[this.at,n.text])):(n=null,this.view.hide()),this.query=n},e.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.iframeStandalone&&(i=t(this.app.iframe).offset(),e.left+=i.left,e.top+=i.top),this.$inputor.is("[contentEditable]")&&(e=this.cur_rect||(this.cur_rect=e)),n=this.app.document.selection?0:2,{left:e.left,top:e.top,bottom:e.top+e.height+n}},e.prototype.reset_rect=function(){if(this.$inputor.is("[contentEditable]"))return this.cur_rect=null},e.prototype.mark_range=function(){var t;if(this.$inputor.is("[contentEditable]"))return this.app.window.getSelection&&(t=this.app.window.getSelection()).rangeCount>0?this.range=t.getRangeAt(0):this.app.document.selection?this.ie8_range=this.app.document.selection.createRange():void 0},e.prototype.insert_content_for=function(e){var i,n,r;return n=e.data("value"),r=this.get_opt("insert_tpl"),this.$inputor.is("textarea, input")||!r?n:(i=t.extend({},e.data("item-data"),{"atwho-data-value":n,"atwho-at":this.at}),this.callbacks("tpl_eval").call(this,r,i))},e.prototype.insert=function(e,i){var n,r,o,s,a,h,l,u,c,p,f,d;if(n=this.$inputor,c=this.callbacks("inserting_wrapper").call(this,n,e,this.get_opt("suffix")),n.is("textarea, input"))u=""+(l=(h=n.val()).slice(0,Math.max(this.query.head_pos-this.at.length,0)))+c+h.slice(this.query.end_pos||0),n.val(u),n.caret("pos",l.length+c.length,{iframe:this.app.iframe});else if(s=this.range){for(o=s.startOffset-(this.query.end_pos-this.query.head_pos)-this.at.length,s.setStart(s.endContainer,Math.max(o,0)),s.setEnd(s.endContainer,s.endOffset),s.deleteContents(),p=0,f=(d=t(c,this.app.document)).length;p<f;p++)r=d[p],s.insertNode(r),s.setEndAfter(r),s.collapse(!1);(a=this.app.window.getSelection()).removeAllRanges(),a.addRange(s)}else(s=this.ie8_range)&&(s.moveStart("character",this.query.end_pos-this.query.head_pos-this.at.length),s.pasteHTML(c),s.collapse(!1),s.select());return n.is(":focus")||n.focus(),n.change()},e.prototype.render_view=function(t){var e;return e=this.get_opt("search_key"),t=this.callbacks("sorter").call(this,this.query.text,t.slice(0,1001),e),this.view.render(t.slice(0,this.get_opt("limit")))},e.prototype.look_up=function(){var e,i;if(e=this.catch_query())return i=function(t){return t&&t.length>0?this.render_view(t):this.view.hide()},this.model.query(e.text,t.proxy(i,this)),e},e}(),s=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 i=this.fetch(),n=this.context.get_opt("search_key"),i=this.context.callbacks("filter").call(this.context,t,i,n)||[],r=this.context.callbacks("remote_filter"),i.length>0||!r&&0===i.length?e(i):r.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("before_save").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}(),a=function(){function e(e){this.context=e,this.$el=t("<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 e.prototype.init=function(){var t;return t=this.context.get_opt("alias")||this.context.at.charCodeAt(0),this.$el.attr({id:"at-view-"+t})},e.prototype.destroy=function(){return this.$el.remove()},e.prototype.bind_event=function(){var e;return(e=this.$el.find("ul")).on("mouseenter.atwho-view","li",function(i){return e.find(".cur").removeClass("cur"),t(i.currentTarget).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 this.$el.is(":visible")},e.prototype.choose=function(t){var e,i;if((e=this.$el.find(".cur")).length&&(i=this.context.insert_content_for(e),this.context.insert(this.context.callbacks("before_insert").call(this.context,i,e),e),this.context.trigger("inserted",[e,t]),this.hide(t)),this.context.get_opt("hide_without_suffix"))return this.stop_showing=!0},e.prototype.reposition=function(e){var i,n,r,o;return o=this.context.app.iframeStandalone?this.context.app.window:window,e.bottom+this.$el.height()-t(o).scrollTop()>t(o).height()&&(e.bottom=e.top-this.$el.height()),e.left>(n=t(o).width()-this.$el.width()-5)&&(e.left=n),i={left:e.left,top:e.bottom},null!=(r=this.context.callbacks("before_reposition"))&&r.call(this.context,i),this.$el.offset(i),this.context.trigger("reposition",[i])},e.prototype.next=function(){var t,e;return t=this.$el.find(".cur").removeClass("cur"),(e=t.next()).length||(e=this.$el.find("li:first")),e.addClass("cur"),this.$el.animate({scrollTop:Math.max(0,t.innerHeight()*(e.index()+2)-this.$el.height())},150)},e.prototype.prev=function(){var t,e;return t=this.$el.find(".cur").removeClass("cur"),(e=t.prev()).length||(e=this.$el.find("li:last")),e.addClass("cur"),this.$el.animate({scrollTop:Math.max(0,t.innerHeight()*(e.index()+2)-this.$el.height())},150)},e.prototype.show=function(){var t;{if(!this.stop_showing)return this.context.mark_range(),this.visible()||(this.$el.show(),this.$el.scrollTop(0),this.context.trigger("shown")),(t=this.context.rect())?this.reposition(t):void 0;this.stop_showing=!1}},e.prototype.hide=function(t,e){var i;if(this.visible())return isNaN(e)?(this.context.reset_rect(),this.$el.hide(),this.context.trigger("hidden",[t])):(i=function(t){return function(){return t.hide()}}(this),clearTimeout(this.timeout_id),this.timeout_id=setTimeout(i,e))},e.prototype.render=function(e){var i,n,r,o,s,a,h;{if(t.isArray(e)&&e.length>0){for(this.$el.find("ul").empty(),n=this.$el.find("ul"),s=this.context.get_opt("tpl"),a=0,h=e.length;a<h;a++)r=e[a],r=t.extend({},r,{"atwho-at":this.context.at}),o=this.context.callbacks("tpl_eval").call(this.context,s,r),(i=t(this.context.callbacks("highlighter").call(this.context,o,this.context.query.text))).data("item-data",r),n.append(i);return this.show(),this.context.get_opt("highlight_first")?n.find("li:first").addClass("cur"):void 0}this.hide()}},e}(),o={DOWN:40,UP:38,ESC:27,TAB:9,ENTER:13,CTRL:17,P:80,N:78},r={before_save:function(e){var i,n,r,o;if(!t.isArray(e))return e;for(o=[],n=0,r=e.length;n<r;n++)i=e[n],t.isPlainObject(i)?o.push(i):o.push({name:i});return o},matcher:function(t,e,i){var n,r,o,s;return t=t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),i&&(t="(?:^|\\s)"+t),o=decodeURI("%C3%80"),s=decodeURI("%C3%BF"),r=new RegExp(t+"([A-Za-z"+o+"-"+s+"0-9_+-]*)$|"+t+"([^\\x00-\\xff]*)$","gi"),(n=r.exec(e))?n[2]||n[1]:null},filter:function(t,e,i){var n,r,o,s;for(s=[],r=0,o=e.length;r<o;r++)n=e[r],~new String(n[i]).toLowerCase().indexOf(t.toLowerCase())&&s.push(n);return s},remote_filter:null,sorter:function(t,e,i){var n,r,o,s;if(!t)return e;for(s=[],r=0,o=e.length;r<o;r++)(n=e[r]).atwho_order=new String(n[i]).toLowerCase().indexOf(t.toLowerCase()),n.atwho_order>-1&&s.push(n);return s.sort(function(t,e){return t.atwho_order-e.atwho_order})},tpl_eval:function(t,e){try{return t.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*(\\w*?)("+e.replace("+","\\+")+")(\\w*)\\s*<","ig"),t.replace(i,function(t,e,i,n){return"> "+e+"<strong>"+i+"</strong>"+n+" <"})):t},before_insert:function(t,e){return t},inserting_wrapper:function(t,e,i){var n;return i=""===i?i:i||" ",t.is("textarea, input")?""+e+i:"true"===t.attr("contentEditable")?(i=" "===i?"&nbsp;":i,n=/firefox/i.test(navigator.userAgent)?"<span>"+e+i+"</span>":"<span contenteditable='false'>"+e+(i="<span contenteditable='false'>"+i+"</span>")+"</span>",this.app.document.selection&&(n="<span contenteditable='true'>"+e+"</span>"),n+"<span></span>"):void 0}},e={load:function(t,e){var i;if(i=this.controller(t))return i.model.load(e)},setIframe:function(t,e){return this.setIframe(t,e),null},run:function(){return this.dispatch()},destroy:function(){return this.shutdown(),this.$inputor.data("atwho",null)}},t.fn.atwho=function(n){var r,o;return o=arguments,r=null,this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function(){var s,a;return(a=(s=t(this)).data("atwho"))||s.data("atwho",a=new i(this)),"object"!=typeof n&&n?e[n]&&a?r=e[n].apply(a,Array.prototype.slice.call(o,1)):t.error("Method "+n+" does not exist on jQuery.caret"):a.reg(n.at,n)}),r||this},t.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:r,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}});
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[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),0<(n=e-(i-this.previousCallTime))&&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,r),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}();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,r),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}();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){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"))?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/vendor/jquery.caret.js CHANGED
@@ -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 CHANGED
@@ -1 +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,p,l;e=function(){function e(t){this.$inputor=t,this.domInputor=this.$inputor[0]}return e.prototype.setPos=function(t){return 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 p.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(p).scrollTop(),n.left+=t(p).scrollLeft()),n},e.prototype.range=function(){var t;if(p.getSelection)return(t=p.getSelection()).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(p).scrollTop()+o.scrollTop(),n.left+=t(p).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,p=null,a=null,l=function(t){var e;return(e=null!=t?t.iframe:void 0)?(a=e,p=e.contentWindow,s=e.contentDocument||p.document):(a=void 0,p=window,s=document)},t.fn.caret=function(n,s,a){var p;return i[n]?(t.isPlainObject(s)?(l(s),s=void 0):l(a),p=r.contentEditable(this)?new e(this):new o(this),i[n].apply(p,[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});
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()).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/webcam.js CHANGED
@@ -83,20 +83,18 @@ window.bp = window.bp || {};
83
 
84
  stream.onended = bp.WebCam.noStream();
85
 
86
- if ( video.mozSrcObject !== undefined ) {
87
- video.mozSrcObject = stream;
88
- video.play();
89
- } else if ( navigator.mozGetUserMedia ) {
90
- video.src = stream;
91
- video.play();
92
- } else if ( video.srcObject !== undefined ) {
93
  video.srcObject = stream;
94
- } else if ( window.URL ) {
95
- video.src = window.URL.createObjectURL( stream );
96
  } else {
97
- video.src = stream;
 
98
  }
99
 
 
 
 
 
100
  bp.WebCam.params.capture_enable = true;
101
  },
102
 
@@ -172,8 +170,16 @@ window.bp = window.bp || {};
172
  initialize: function() {
173
  var params;
174
 
175
- if ( navigator.getUserMedia || navigator.oGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia ) {
 
 
 
 
 
 
 
176
 
 
177
  // We need to add some cropping stuff to use bp.Avatar.setAvatar()
178
  params = _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
179
  'object',
@@ -213,19 +219,24 @@ window.bp = window.bp || {};
213
  // User Feedback
214
  bp.WebCam.displayWarning( 'requesting' );
215
 
216
- if ( navigator.getUserMedia ) {
217
- navigator.getUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream );
218
- } else if ( navigator.oGetUserMedia ) {
219
- navigator.oGetUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream );
220
- } else if ( navigator.mozGetUserMedia ) {
221
- navigator.mozGetUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream );
222
- } else if ( navigator.webkitGetUserMedia ) {
223
- navigator.webkitGetUserMedia( { video:true }, bp.WebCam.gotStream, bp.WebCam.noStream );
224
- } else if (navigator.msGetUserMedia) {
225
- navigator.msGetUserMedia( { video:true, audio:false }, bp.WebCams.gotStream, bp.WebCam.noStream );
226
  } else {
227
- // User Feedback
228
- bp.WebCam.displayWarning( 'errormsg' );
 
 
 
 
 
 
 
229
  }
230
  },
231
 
83
 
84
  stream.onended = bp.WebCam.noStream();
85
 
86
+ // Older browsers may not have srcObject
87
+ if ( 'srcObject' in video ) {
 
 
 
 
 
88
  video.srcObject = stream;
 
 
89
  } else {
90
+ // Avoid using this in new browsers, as it is going away.
91
+ video.src = window.URL.createObjectURL( stream );
92
  }
93
 
94
+ video.onloadedmetadata = function() {
95
+ video.play();
96
+ };
97
+
98
  bp.WebCam.params.capture_enable = true;
99
  },
100
 
170
  initialize: function() {
171
  var params;
172
 
173
+ // Standardize getUserMedia browser call.
174
+ navigator.getUserMedia = (
175
+ navigator.getUserMedia ||
176
+ navigator.webkitGetUserMedia ||
177
+ navigator.mozGetUserMedia ||
178
+ navigator.msGetUserMedia ||
179
+ navigator.oGetUserMedia
180
+ );
181
 
182
+ if ( typeof navigator.getUserMedia !== 'undefined' ) {
183
  // We need to add some cropping stuff to use bp.Avatar.setAvatar()
184
  params = _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
185
  'object',
219
  // User Feedback
220
  bp.WebCam.displayWarning( 'requesting' );
221
 
222
+ // Use deprecated getUserMedia call for browsers that require it.
223
+ if ( typeof navigator.mediaDevices.getUserMedia === 'undefined' ) {
224
+ navigator.getUserMedia({
225
+ audio: false,
226
+ video: true
227
+ }, bp.WebCam.gotStream, bp.WebCam.noStream);
228
+
229
+ // Teh new hotness!
 
 
230
  } else {
231
+ navigator.mediaDevices.getUserMedia({
232
+ audio: false,
233
+ video: true
234
+ }).then(bp.WebCam.gotStream, bp.WebCam.noStream)
235
+ // ES3 compatibility.
236
+ ['catch'](function() {
237
+ // User Feedback
238
+ bp.WebCam.displayWarning( 'errormsg' );
239
+ });
240
  }
241
  },
242
 
bp-core/js/webcam.min.js CHANGED
@@ -1 +1 @@
1
- window.bp=window.bp||{},bp,jQuery,"undefined"!=typeof BP_Uploader&&(bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.WebCam={start:function(){this.params={video:null,videoStream:null,capture_enable:!1,capture:null,canvas:null,warning:null,flipped:!1},bp.Avatar.nav.on("bp-avatar-view:changed",_.bind(this.setView,this))},setView:function(e){if("camera"===e){var a=new bp.Views.WebCamAvatar({model:new Backbone.Model({user_media:!1})});this.params.flipped=!1,bp.Avatar.views.add({id:"camera",view:a}),a.inject(".bp-avatar")}else _.isNull(this.params.video)||(this.stop(),this.removeWarning())},removeView:function(){var e;_.isUndefined(bp.Avatar.views.get("camera"))||((e=bp.Avatar.views.get("camera")).get("view").remove(),bp.Avatar.views.remove({id:"camera",view:e}))},gotStream:function(e){var a=bp.WebCam.params.video;bp.WebCam.params.videoStream=e,bp.WebCam.displayWarning("loaded"),a.onerror=function(){bp.WebCam.displayWarning("videoerror"),a&&bp.WebCam.stop()},e.onended=bp.WebCam.noStream(),void 0!==a.mozSrcObject?(a.mozSrcObject=e,a.play()):navigator.mozGetUserMedia?(a.src=e,a.play()):void 0!==a.srcObject?a.srcObject=e:window.URL?a.src=window.URL.createObjectURL(e):a.src=e,bp.WebCam.params.capture_enable=!0},stop:function(){bp.WebCam.params.capture_enable=!1,bp.WebCam.params.videoStream&&(bp.WebCam.params.videoStream.stop?bp.WebCam.params.videoStream.stop():bp.WebCam.params.videoStream.msStop&&bp.WebCam.params.videoStream.msStop(),bp.WebCam.params.videoStream.onended=null,bp.WebCam.params.videoStream=null),bp.WebCam.params.video&&(bp.WebCam.params.video.onerror=null,bp.WebCam.params.video.pause(),bp.WebCam.params.video.mozSrcObject&&(bp.WebCam.params.video.mozSrcObject=null),bp.WebCam.params.video.src="")},noStream:function(){_.isNull(bp.WebCam.params.videoStream)&&(bp.WebCam.displayWarning("noaccess"),bp.WebCam.removeView())},setAvatar:function(e){e.get("url")||bp.WebCam.displayWarning("nocapture"),bp.WebCam.removeView(),bp.Avatar.setAvatar(e)},removeWarning:function(){_.isNull(this.params.warning)||this.params.warning.remove()},displayWarning:function(e){this.removeWarning(),this.params.warning=new bp.Views.uploaderWarning({value:BP_Uploader.strings.camera_warnings[e]}),this.params.warning.inject(".bp-avatar-status")}},bp.Views.WebCamAvatar=bp.View.extend({tagName:"div",id:"bp-webcam-avatar",template:bp.template("bp-avatar-webcam"),events:{"click .avatar-webcam-capture":"captureStream","click .avatar-webcam-save":"saveCapture"},initialize:function(){var e;(navigator.getUserMedia||navigator.oGetUserMedia||navigator.mozGetUserMedia||navigator.webkitGetUserMedia||navigator.msGetUserMedia)&&(e=_.extend(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,"object","item_id","nonces"),{user_media:!0,w:BP_Uploader.settings.crop.full_w,h:BP_Uploader.settings.crop.full_h,x:0,y:0,type:"camera"}),this.model.set(e)),this.on("ready",this.useStream,this)},useStream:function(){this.model.get("user_media")&&(this.options.video=new bp.Views.WebCamVideo,this.options.canvas=new bp.Views.WebCamCanvas,this.$el.find("#avatar-to-crop").append(this.options.video.el),this.$el.find("#avatar-crop-pane").append(this.options.canvas.el),bp.WebCam.params.video=this.options.video.el,bp.WebCam.params.canvas=this.options.canvas.el,bp.WebCam.displayWarning("requesting"),navigator.getUserMedia?navigator.getUserMedia({video:!0},bp.WebCam.gotStream,bp.WebCam.noStream):navigator.oGetUserMedia?navigator.oGetUserMedia({video:!0},bp.WebCam.gotStream,bp.WebCam.noStream):navigator.mozGetUserMedia?navigator.mozGetUserMedia({video:!0},bp.WebCam.gotStream,bp.WebCam.noStream):navigator.webkitGetUserMedia?navigator.webkitGetUserMedia({video:!0},bp.WebCam.gotStream,bp.WebCam.noStream):navigator.msGetUserMedia?navigator.msGetUserMedia({video:!0,audio:!1},bp.WebCams.gotStream,bp.WebCam.noStream):bp.WebCam.displayWarning("errormsg"))},captureStream:function(e){var a,t;e.preventDefault(),bp.WebCam.params.capture_enable?this.model.get("h")>this.options.video.el.videoHeight||this.model.get("w")>this.options.video.el.videoWidth?bp.WebCam.displayWarning("videoerror"):(t=this.options.video.el.videoHeight,a=(this.options.video.el.videoWidth-t)/2,bp.WebCam.params.flipped||(this.options.canvas.el.getContext("2d").translate(this.model.get("w"),0),this.options.canvas.el.getContext("2d").scale(-1,1),bp.WebCam.params.flipped=!0),this.options.canvas.el.getContext("2d").drawImage(this.options.video.el,a,0,t,t,0,0,this.model.get("w"),this.model.get("h")),bp.WebCam.params.capture=this.options.canvas.el.toDataURL("image/png"),this.model.set("url",bp.WebCam.params.capture),bp.WebCam.displayWarning("ready")):bp.WebCam.displayWarning("loading")},saveCapture:function(e){e.preventDefault(),bp.WebCam.params.capture?(bp.WebCam.stop(),bp.WebCam.setAvatar(this.model)):bp.WebCam.displayWarning("nocapture")}}),bp.Views.WebCamVideo=bp.View.extend({tagName:"video",id:"bp-webcam-video",attributes:{autoplay:"autoplay"}}),bp.Views.WebCamCanvas=bp.View.extend({tagName:"canvas",id:"bp-webcam-canvas",attributes:{width:150,height:150},initialize:function(){_.isUndefined(BP_Uploader.settings.crop.full_h)||_.isUndefined(BP_Uploader.settings.crop.full_w)||(this.el.attributes.width.value=BP_Uploader.settings.crop.full_w,this.el.attributes.height.value=BP_Uploader.settings.crop.full_h)}}),bp.WebCam.start());
1
+ window.bp=window.bp||{},bp,jQuery,"undefined"!=typeof BP_Uploader&&(bp.Models=bp.Models||{},bp.Collections=bp.Collections||{},bp.Views=bp.Views||{},bp.WebCam={start:function(){this.params={video:null,videoStream:null,capture_enable:!1,capture:null,canvas:null,warning:null,flipped:!1},bp.Avatar.nav.on("bp-avatar-view:changed",_.bind(this.setView,this))},setView:function(e){if("camera"===e){var a=new bp.Views.WebCamAvatar({model:new Backbone.Model({user_media:!1})});this.params.flipped=!1,bp.Avatar.views.add({id:"camera",view:a}),a.inject(".bp-avatar")}else _.isNull(this.params.video)||(this.stop(),this.removeWarning())},removeView:function(){var e;_.isUndefined(bp.Avatar.views.get("camera"))||((e=bp.Avatar.views.get("camera")).get("view").remove(),bp.Avatar.views.remove({id:"camera",view:e}))},gotStream:function(e){var a=bp.WebCam.params.video;bp.WebCam.params.videoStream=e,bp.WebCam.displayWarning("loaded"),a.onerror=function(){bp.WebCam.displayWarning("videoerror"),a&&bp.WebCam.stop()},e.onended=bp.WebCam.noStream(),"srcObject"in a?a.srcObject=e:a.src=window.URL.createObjectURL(e),a.onloadedmetadata=function(){a.play()},bp.WebCam.params.capture_enable=!0},stop:function(){bp.WebCam.params.capture_enable=!1,bp.WebCam.params.videoStream&&(bp.WebCam.params.videoStream.stop?bp.WebCam.params.videoStream.stop():bp.WebCam.params.videoStream.msStop&&bp.WebCam.params.videoStream.msStop(),bp.WebCam.params.videoStream.onended=null,bp.WebCam.params.videoStream=null),bp.WebCam.params.video&&(bp.WebCam.params.video.onerror=null,bp.WebCam.params.video.pause(),bp.WebCam.params.video.mozSrcObject&&(bp.WebCam.params.video.mozSrcObject=null),bp.WebCam.params.video.src="")},noStream:function(){_.isNull(bp.WebCam.params.videoStream)&&(bp.WebCam.displayWarning("noaccess"),bp.WebCam.removeView())},setAvatar:function(e){e.get("url")||bp.WebCam.displayWarning("nocapture"),bp.WebCam.removeView(),bp.Avatar.setAvatar(e)},removeWarning:function(){_.isNull(this.params.warning)||this.params.warning.remove()},displayWarning:function(e){this.removeWarning(),this.params.warning=new bp.Views.uploaderWarning({value:BP_Uploader.strings.camera_warnings[e]}),this.params.warning.inject(".bp-avatar-status")}},bp.Views.WebCamAvatar=bp.View.extend({tagName:"div",id:"bp-webcam-avatar",template:bp.template("bp-avatar-webcam"),events:{"click .avatar-webcam-capture":"captureStream","click .avatar-webcam-save":"saveCapture"},initialize:function(){var e;navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia||navigator.oGetUserMedia,void 0!==navigator.getUserMedia&&(e=_.extend(_.pick(BP_Uploader.settings.defaults.multipart_params.bp_params,"object","item_id","nonces"),{user_media:!0,w:BP_Uploader.settings.crop.full_w,h:BP_Uploader.settings.crop.full_h,x:0,y:0,type:"camera"}),this.model.set(e)),this.on("ready",this.useStream,this)},useStream:function(){this.model.get("user_media")&&(this.options.video=new bp.Views.WebCamVideo,this.options.canvas=new bp.Views.WebCamCanvas,this.$el.find("#avatar-to-crop").append(this.options.video.el),this.$el.find("#avatar-crop-pane").append(this.options.canvas.el),bp.WebCam.params.video=this.options.video.el,bp.WebCam.params.canvas=this.options.canvas.el,bp.WebCam.displayWarning("requesting"),void 0===navigator.mediaDevices.getUserMedia?navigator.getUserMedia({audio:!1,video:!0},bp.WebCam.gotStream,bp.WebCam.noStream):navigator.mediaDevices.getUserMedia({audio:!1,video:!0}).then(bp.WebCam.gotStream,bp.WebCam.noStream).catch(function(){bp.WebCam.displayWarning("errormsg")}))},captureStream:function(e){var a,t;e.preventDefault(),bp.WebCam.params.capture_enable?this.model.get("h")>this.options.video.el.videoHeight||this.model.get("w")>this.options.video.el.videoWidth?bp.WebCam.displayWarning("videoerror"):(t=this.options.video.el.videoHeight,a=(this.options.video.el.videoWidth-t)/2,bp.WebCam.params.flipped||(this.options.canvas.el.getContext("2d").translate(this.model.get("w"),0),this.options.canvas.el.getContext("2d").scale(-1,1),bp.WebCam.params.flipped=!0),this.options.canvas.el.getContext("2d").drawImage(this.options.video.el,a,0,t,t,0,0,this.model.get("w"),this.model.get("h")),bp.WebCam.params.capture=this.options.canvas.el.toDataURL("image/png"),this.model.set("url",bp.WebCam.params.capture),bp.WebCam.displayWarning("ready")):bp.WebCam.displayWarning("loading")},saveCapture:function(e){e.preventDefault(),bp.WebCam.params.capture?(bp.WebCam.stop(),bp.WebCam.setAvatar(this.model)):bp.WebCam.displayWarning("nocapture")}}),bp.Views.WebCamVideo=bp.View.extend({tagName:"video",id:"bp-webcam-video",attributes:{autoplay:"autoplay"}}),bp.Views.WebCamCanvas=bp.View.extend({tagName:"canvas",id:"bp-webcam-canvas",attributes:{width:150,height:150},initialize:function(){_.isUndefined(BP_Uploader.settings.crop.full_h)||_.isUndefined(BP_Uploader.settings.crop.full_w)||(this.el.attributes.width.value=BP_Uploader.settings.crop.full_w,this.el.attributes.height.value=BP_Uploader.settings.crop.full_h)}}),bp.WebCam.start());
bp-forums/bb-config.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
- /**
3
- * *** IMPORTANT ****
4
- * This file will stop people from accessing your bbPress installation directly.
5
- * It is very important from a security standpoint that this file is not moved.
6
- * Your actual bb-config.php file will be installed in the root of your WordPress
7
- * installation once you have set up the forums component in BuddyPress.
8
- *
9
- * @package BuddyPress
10
- * @subpackage ForumsbbPressConfig
11
- * @since 1.1.0
12
- */
13
-
14
- header("HTTP/1.0 403 Forbidden"); die;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/admin-action.php DELETED
@@ -1,5 +0,0 @@
1
- <?php
2
- require_once('../bb-load.php');
3
-
4
- bb_auth();
5
- ?>
 
 
 
 
 
bp-forums/bbpress/bb-admin/admin-ajax.php DELETED
@@ -1,264 +0,0 @@
1
- <?php
2
-
3
- define( 'BB_IS_ADMIN', true );
4
- define( 'DOING_AJAX', true );
5
-
6
- require_once('../bb-load.php');
7
-
8
- if ( !class_exists( 'WP_Ajax_Response' ) )
9
- require_once( BACKPRESS_PATH . 'class.wp-ajax-response.php' );
10
-
11
- require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
12
-
13
- if ( !$bb_current_id = bb_get_current_user_info( 'id' ) )
14
- die('-1');
15
-
16
- function bb_grab_results() {
17
- global $ajax_results;
18
- $ajax_results = @ unserialize(func_get_arg(0));
19
- if ( false === $ajax_results )
20
- $ajax_results = func_get_args();
21
- return;
22
- }
23
-
24
- $id = (int) @$_POST['id'];
25
-
26
- switch ( $action = $_POST['action'] ) :
27
- case 'add-tag' : // $id is topic_id
28
- if ( !bb_current_user_can('edit_tag_by_on', $bb_current_id, $id) )
29
- die('-1');
30
-
31
- bb_check_ajax_referer( "add-tag_$id" );
32
-
33
- global $tag, $topic;
34
- add_action('bb_tag_added', 'bb_grab_results', 10, 3);
35
- add_action('bb_already_tagged', 'bb_grab_results', 10, 3);
36
- $tag_name = @$_POST['tag'];
37
- $tag_name = stripslashes( $tag_name );
38
-
39
- $topic = get_topic( $id );
40
- if ( !$topic )
41
- die('0');
42
-
43
- $tag_name = rawurldecode($tag_name);
44
- $x = new WP_Ajax_Response();
45
- foreach ( bb_add_topic_tags( $id, $tag_name ) as $tag_id ) {
46
- if ( !is_numeric($tag_id) || !$tag = bb_get_tag( (int) $tag_id, bb_get_current_user_info( 'id' ), $topic->topic_id ) ) {
47
- if ( !$tag = bb_get_tag( $tag_id ) ) {
48
- continue;
49
- }
50
- }
51
- $tag->tag_id = $tag_id;
52
- $tag->user_id = bb_get_current_user_info( 'id' );
53
- $tag_id_val = $tag->tag_id . '_' . $tag->user_id;
54
- $tag->raw_tag = esc_attr( $tag_name );
55
- $x->add( array(
56
- 'what' => 'tag',
57
- 'id' => $tag_id_val,
58
- 'data' => _bb_list_tag_item( $tag, array( 'list_id' => 'tags-list', 'format' => 'list' ) )
59
- ) );
60
- }
61
- $x->send();
62
- break;
63
-
64
- case 'delete-tag' :
65
- list($tag_id, $user_id) = explode('_', $_POST['id']);
66
- $tag_id = (int) $tag_id;
67
- $user_id = (int) $user_id;
68
- $topic_id = (int) $_POST['topic_id'];
69
-
70
- if ( !bb_current_user_can('edit_tag_by_on', $user_id, $topic_id) )
71
- die('-1');
72
-
73
- bb_check_ajax_referer( "remove-tag_$tag_id|$topic_id" );
74
-
75
- add_action('bb_rpe_tag_removed', 'bb_grab_results', 10, 3);
76
-
77
- $tag = bb_get_tag( $tag_id );
78
- $user = bb_get_user( $user_id );
79
- $topic = get_topic ( $topic_id );
80
- if ( !$tag || !$topic )
81
- die('0');
82
- if ( false !== bb_remove_topic_tag( $tag_id, $user_id, $topic_id ) )
83
- die('1');
84
- break;
85
-
86
- case 'dim-favorite' :
87
- $user_id = bb_get_current_user_info( 'id' );
88
-
89
- if ( !$topic = get_topic( $id ) )
90
- die('0');
91
-
92
- if ( !bb_current_user_can( 'edit_favorites_of', $user_id ) )
93
- die('-1');
94
-
95
- bb_check_ajax_referer( "toggle-favorite_$topic->topic_id" );
96
-
97
- $is_fav = is_user_favorite( $user_id, $topic->topic_id );
98
-
99
- if ( 1 == $is_fav ) {
100
- if ( bb_remove_user_favorite( $user_id, $topic->topic_id ) )
101
- die('1');
102
- } elseif ( false === $is_fav ) {
103
- if ( bb_add_user_favorite( $user_id, $topic->topic_id ) )
104
- die('1');
105
- }
106
- break;
107
-
108
- case 'delete-post' : // $id is post_id
109
- if ( !bb_current_user_can( 'delete_post', $id ) )
110
- die('-1');
111
-
112
- bb_check_ajax_referer( "delete-post_$id" );
113
-
114
- $status = (int) $_POST['status'];
115
-
116
- if ( !$bb_post = bb_get_post( $id ) )
117
- die('0');
118
-
119
- if ( $status == $bb_post->post_status )
120
- die('1'); // We're already there
121
-
122
- if ( bb_delete_post( $id, $status ) ) {
123
- $topic = get_topic( $bb_post->topic_id );
124
- if ( 0 == $topic->topic_posts ) {
125
- // If we deleted the only post, send back a WP_Ajax_Response object with a URL to redirect to
126
- if ( $ref = wp_get_referer() ) {
127
- $ref_topic = bb_get_topic_from_uri( $ref );
128
- if ( $ref_topic && $ref_topic->topic_id == $topic->topic_id )
129
- $ref = add_query_arg( 'view', 'all', $ref );
130
- if ( false === strpos( $ref, '#' ) )
131
- $ref .= "#post-{$bb_post->post_id}";
132
- } else {
133
- $ref = add_query_arg( 'view', 'all', get_post_link( $topic->topic_id ) );
134
- }
135
- $x = new WP_Ajax_Response( array(
136
- 'what' => 'post',
137
- 'id' => $bb_post->post_id,
138
- 'data' => $ref,
139
- ) );
140
- $x->send();
141
- }
142
- die('1');
143
- }
144
- break;
145
- /*
146
- case 'add-post' : // Can put last_modified stuff back in later
147
- bb_check_ajax_referer( $action );
148
- $error = false;
149
- $post_id = 0;
150
- $topic_id = (int) $_POST['topic_id'];
151
- $last_mod = (int) $_POST['last_mod'];
152
- if ( !$post_content = trim($_POST['post_content']) )
153
- $error = new WP_Error( 'no-content', __('You need to actually submit some content!') );
154
- if ( !bb_current_user_can( 'write_post', $topic_id ) )
155
- die('-1');
156
- if ( !$topic = get_topic( $topic_id ) )
157
- die('0');
158
- if ( !topic_is_open( $topic_id ) )
159
- $error = new WP_Error( 'topic-closed', __('This topic is closed.') );
160
- if ( $throttle_time = bb_get_option( 'throttle_time' ) )
161
- if ( isset($bb_current_user->data->last_posted) && time() < $bb_current_user->data->last_posted + $throttle_time && !bb_current_user_can('throttle') )
162
- $error = new WP_Error( 'throttle-limit', sprintf( __('Slow down! You can only post every %d seconds.'), $throttle_time );
163
-
164
- if ( !$error ) :
165
- if ( !$post_id = bb_new_post( $topic_id, rawurldecode($_POST['post_content']) ) )
166
- die('0');
167
-
168
- $bb_post = bb_get_post( $post_id );
169
-
170
- $new_page = bb_get_page_number( $bb_post->post_position );
171
-
172
- ob_start();
173
- echo "<li id='post-$post_id'>";
174
- bb_post_template();
175
- echo '</li>';
176
- $data = ob_get_contents();
177
- ob_end_clean();
178
- endif;
179
- $x = new WP_Ajax_Response( array(
180
- 'what' => 'post',
181
- 'id' => $post_id,
182
- 'data' => is_wp_error($error) ? $error : $data
183
- ) );
184
- $x->send();
185
- break;
186
- */
187
- case 'add-forum' :
188
- if ( !bb_current_user_can( 'manage_forums' ) )
189
- die('-1');
190
-
191
- bb_check_ajax_referer( $action );
192
-
193
- if ( !$forum_id = bb_new_forum( $_POST ) )
194
- die('0');
195
-
196
- global $forums_count;
197
- $forums_count = 2; // Hack
198
-
199
- $data = bb_forum_row( $forum_id, false, true );
200
-
201
- $forum = bb_get_forum( $forum_id );
202
- if ( $forum->forum_parent ) {
203
- $siblings = bb_get_forums( $forum->forum_parent );
204
- $last_sibling = array_pop( $siblings );
205
- if ( $last_sibling->forum_id == $forum_id )
206
- $last_sibling = array_pop( $siblings );
207
- if ( $last_sibling ) {
208
- $position = "forum-$last_sibling->forum_id";
209
- } else {
210
- $position = "+forum-$forum->forum_parent";
211
- $data = "<ul id='forum-root-$forum->forum_parent' class='list-block holder'>$data</ul>";
212
- }
213
- } else {
214
- $position = 1;
215
- }
216
-
217
- $x = new WP_Ajax_Response( array(
218
- 'what' => 'forum',
219
- 'id' => $forum_id,
220
- 'data' => $data,
221
- 'position' => $position,
222
- 'supplemental' => array( 'name' => $forum->forum_name )
223
- ) );
224
- $x->send();
225
- break;
226
-
227
- case 'order-forums' :
228
- if ( !bb_current_user_can( 'manage_forums' ) )
229
- die('-1');
230
-
231
- bb_check_ajax_referer( $action );
232
-
233
- if ( !is_array($_POST['order']) )
234
- die('0');
235
-
236
- global $bbdb;
237
-
238
- $forums = array();
239
-
240
- bb_get_forums(); // cache
241
-
242
- foreach ( $_POST['order'] as $pos => $forum_id ) :
243
- $forum = $bbdb->escape_deep( get_object_vars( bb_get_forum( $forum_id ) ) );
244
- $forum['forum_order'] = $pos;
245
- $forums[(int) $forum_id] = $forum;
246
- endforeach;
247
-
248
- foreach ( $_POST['root'] as $root => $ids )
249
- foreach ( $ids as $forum_id )
250
- $forums[(int) $forum_id]['forum_parent'] = (int) $root;
251
-
252
- foreach ( $forums as $forum )
253
- bb_update_forum( $forum );
254
-
255
- die('1');
256
- break;
257
-
258
- default :
259
- do_action( 'bb_ajax_' . $_POST['action'] );
260
- break;
261
- endswitch;
262
-
263
- die('0');
264
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/admin-base.php DELETED
@@ -1,23 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- do_action( $bb_admin_page . '_pre_head' );
5
-
6
- bb_get_admin_header();
7
- ?>
8
-
9
- <div class="wrap">
10
-
11
- <?php if ( is_callable($bb_admin_page) ) : call_user_func( $bb_admin_page ); else : ?>
12
-
13
- <h2><?php _e( 'Page not found' ); ?></h2>
14
- <?php
15
- bb_admin_notice( __( 'There is no administration page at the requested address. Please check the address you entered and try again.' ), 'error' );
16
- do_action( 'bb_admin_notices' );
17
- ?>
18
-
19
- <?php endif; ?>
20
-
21
- </div>
22
-
23
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/admin-footer.php DELETED
@@ -1,33 +0,0 @@
1
- </div>
2
- <div class="clear"></div>
3
- <!-- If you like showing off the fact that your server rocks -->
4
- <!-- <p id="bbShowOff">
5
- <?php
6
- global $bbdb;
7
- printf(
8
- __( 'This page generated in %s seconds, using %d queries.' ),
9
- bb_number_format_i18n( bb_timer_stop(), 2 ),
10
- bb_number_format_i18n( $bbdb->num_queries )
11
- );
12
- ?>
13
- </p> -->
14
- <div class="clear"></div>
15
- </div>
16
- </div>
17
- <div id="bbFoot">
18
- <p id="bbThanks">
19
- <?php
20
- printf(
21
- __( 'Thank you for using <a href="%s">bbPress</a>. | <a href="%s">Documentation</a> | <a href="%s">Feedback</a>' ),
22
- 'http://bbpress.org/',
23
- 'http://bbpress.org/documentation/',
24
- 'http://bbpress.org/forums/forum/requests-and-feedback'
25
- );
26
- ?>
27
- </p>
28
- <p id="bbVersion"><?php printf( __( 'Version %s' ), bb_get_option( 'version' ) ); ?></p>
29
- </div>
30
-
31
- <?php do_action( 'bb_admin_footer' ); ?>
32
- </body>
33
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/admin-header.php DELETED
@@ -1,57 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml"<?php bb_language_attributes( '1.1' ); ?>>
3
- <head>
4
- <meta http-equiv="X-UA-Compatible" content="IE=8" />
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
- <title><?php bb_admin_title() ?></title>
7
- <link rel="stylesheet" href="<?php bb_uri('bb-admin/style.css', null, BB_URI_CONTEXT_LINK_STYLESHEET_HREF + BB_URI_CONTEXT_BB_ADMIN); ?>" type="text/css" />
8
- <?php if ( 'rtl' == bb_get_option( 'text_direction' ) ) : ?>
9
- <link rel="stylesheet" href="<?php bb_uri('bb-admin/style-rtl.css', null, BB_URI_CONTEXT_LINK_STYLESHEET_HREF + BB_URI_CONTEXT_BB_ADMIN); ?>" type="text/css" />
10
- <?php endif; do_action('bb_admin_print_scripts'); ?>
11
- <!--[if IE 6]>
12
- <style type="text/css">
13
- ul#bbAdminMenu{ margin: 15px 5px 15px -85px; } body.bb-menu-folded div#bbBody{ margin-left: 110px; }
14
- </style>
15
- <![endif]-->
16
- <link rel="shortcut icon" type="image/ico" href="<?php bb_uri('bb-admin/images/favicon.ico', null, BB_URI_CONTEXT_BB_ADMIN); ?>" />
17
- <script type="text/javascript">
18
- //<![CDATA[
19
- addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
20
- var userSettings = {'url':'<?php echo $bb->cookie_path; ?>','uid':'<?php if ( ! isset($bb_current_user) ) $bb_current_user = bb_get_current_user(); echo $bb_current_user->ID; ?>','time':'<?php echo time(); ?>'};
21
- //]]>
22
- </script>
23
- <?php do_action( 'bb_admin_head' ); ?>
24
- </head>
25
-
26
- <?php
27
- global $bb_admin_body_class;
28
- if ( 'f' == bb_get_user_setting( 'fm' ) ) {
29
- $bb_admin_body_class .= ' bb-menu-folded';
30
- }
31
- ?>
32
-
33
- <body class="bb-admin no-js <?php echo trim( $bb_admin_body_class ); ?>">
34
- <script type="text/javascript">
35
- //<![CDATA[
36
- (function(){
37
- var c = document.body.className;
38
- c = c.replace(/no-js/, 'js');
39
- document.body.className = c;
40
- })();
41
- //]]>
42
- </script>
43
- <div id="bbWrap">
44
- <div id="bbContent">
45
- <div id="bbHead">
46
- <h1><a href="<?php bb_uri(); ?>"><span><?php bb_option('name'); ?></span> <em><?php _e('Visit Site'); ?></em></a></h1>
47
- <div id="bbUserInfo">
48
- <p>
49
- <?php printf( __('Howdy, %1$s'), bb_get_profile_link( array( 'text' => bb_get_current_user_info( 'name' ) ) ) );?>
50
- | <?php bb_logout_link( array( 'redirect' => bb_get_uri( null, null, BB_URI_CONTEXT_HEADER ) ) ); ?>
51
- </p>
52
- </div>
53
- </div>
54
-
55
- <div id="bbBody">
56
-
57
- <?php bb_admin_menu(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/admin.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
- define( 'BB_IS_ADMIN', true );
3
-
4
- require_once('../bb-load.php');
5
-
6
- bb_ssl_redirect();
7
-
8
- bb_auth();
9
-
10
- if ( bb_get_option( 'bb_db_version' ) > bb_get_option_from_db( 'bb_db_version' ) ) {
11
- bb_safe_redirect( 'upgrade.php' );
12
- die();
13
- }
14
-
15
- require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
16
-
17
- $bb_admin_page = bb_find_filename( $_SERVER['PHP_SELF'] );
18
-
19
- $_check_callback = false;
20
- if ( $bb_admin_page == 'admin-base.php' ) {
21
- $bb_admin_page = (string) @$_GET['plugin'];
22
- $_check_callback = true;
23
- }
24
-
25
- wp_enqueue_script( 'common' );
26
-
27
- bb_user_settings();
28
- if ( isset( $_GET['foldmenu'] ) ) {
29
- if ( $_GET['foldmenu'] ) {
30
- bb_update_user_setting( 'fm', 'f' );
31
- } else {
32
- bb_delete_user_setting( 'fm' );
33
- }
34
- bb_safe_redirect( remove_query_arg( 'foldmenu', stripslashes( $_SERVER['REQUEST_URI'] ) ) );
35
- die;
36
- }
37
- bb_admin_menu_generator();
38
- bb_get_current_admin_menu();
39
-
40
- if ( $_check_callback ) {
41
- if ( empty( $bb_registered_plugin_callbacks ) || empty( $bb_admin_page ) || !in_array( $bb_admin_page, $bb_registered_plugin_callbacks ) ) {
42
- unset( $bb_admin_page );
43
- }
44
- }
45
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/bb-forum.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- if ( !bb_current_user_can('manage_forums') )
5
- bb_die(__("You don't have the authority to mess with the forums."));
6
-
7
- if ( !isset($_POST['action']) ) {
8
- wp_redirect( bb_get_uri('bb-admin/forums.php', null, BB_URI_CONTEXT_HEADER + BB_URI_CONTEXT_BB_ADMIN) );
9
- exit;
10
- }
11
-
12
- $sent_from = wp_get_referer();
13
-
14
- switch ( $_POST['action'] ) :
15
- case 'add' :
16
- if ( !isset($_POST['forum_name']) || '' === $_POST['forum_name'] )
17
- bb_die(__('Bad forum name. Go back and try again.'));
18
-
19
- bb_check_admin_referer( 'add-forum' );
20
-
21
- if ( false !== bb_new_forum( $_POST ) ) :
22
- bb_safe_redirect( $sent_from );
23
- exit;
24
- else :
25
- bb_die(__('The forum was not added'));
26
- endif;
27
- break;
28
- case 'update' :
29
- bb_check_admin_referer( 'update-forum' );
30
-
31
- if ( !$forums = bb_get_forums() )
32
- bb_die(__('No forums to update!'));
33
- if ( (int) $_POST['forum_id'] && isset($_POST['forum_name']) && '' !== $_POST['forum_name'] )
34
- bb_update_forum( $_POST );
35
- foreach ( array('action', 'id') as $arg )
36
- $sent_from = remove_query_arg( $arg, $sent_from );
37
- bb_safe_redirect( add_query_arg( 'message', 'updated', $sent_from ) );
38
- exit;
39
- break;
40
- case 'delete' :
41
- bb_check_admin_referer( 'delete-forums' );
42
-
43
- $forum_id = (int) $_POST['forum_id'];
44
- $move_topics_forum = (int) $_POST['move_topics_forum'];
45
-
46
- if ( !bb_current_user_can( 'delete_forum', $forum_id ) )
47
- bb_die(__("You don't have the authority to kill off the forums."));
48
-
49
- if ( isset($_POST['move_topics']) && $_POST['move_topics'] != 'delete' )
50
- bb_move_forum_topics( $forum_id, $move_topics_forum );
51
-
52
- if ( !bb_delete_forum( $forum_id ) )
53
- bb_die( __('Error occured while trying to delete forum') );
54
-
55
- foreach ( array('action', 'id') as $arg )
56
- $sent_from = remove_query_arg( $arg, $sent_from );
57
- bb_safe_redirect( add_query_arg( 'message', 'deleted', $sent_from ) );
58
- exit;
59
- break;
60
- endswitch;
61
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/delete-post.php DELETED
@@ -1,81 +0,0 @@
1
- <?php
2
- require('admin-action.php');
3
-
4
- $post_id = (int) $_GET['id'];
5
-
6
- if ( !bb_current_user_can( 'delete_post', $post_id ) ) {
7
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
8
- exit;
9
- }
10
-
11
- bb_check_admin_referer( 'delete-post_' . $post_id );
12
-
13
- $status = (int) $_GET['status'];
14
- $bb_post = bb_get_post ( $post_id );
15
- $old_status = (int) $bb_post->post_status;
16
-
17
- if ( !$bb_post )
18
- bb_die(__('There is a problem with that post, pardner.'));
19
-
20
- if ( 0 == $status && 0 != $bb_post->post_status ) // We're undeleting
21
- add_filter('bb_delete_post', 'bb_topics_replied_on_undelete_post');
22
-
23
- bb_delete_post( $post_id, $status );
24
-
25
- $message = '';
26
- switch ( $old_status ) {
27
- case 0:
28
- switch ( $status ) {
29
- case 0:
30
- break;
31
- case 1:
32
- $message = 'deleted';
33
- break;
34
- default:
35
- $message = 'spammed';
36
- break;
37
- }
38
- break;
39
- case 1:
40
- switch ( $status ) {
41
- case 0:
42
- $message = 'undeleted';
43
- break;
44
- case 1:
45
- break;
46
- default:
47
- $message = 'spammed';
48
- break;
49
- }
50
- break;
51
- default:
52
- switch ( $status ) {
53
- case 0:
54
- $message = 'unspammed-normal';
55
- break;
56
- case 1:
57
- $message = 'unspammed-deleted';
58
- break;
59
- default:
60
- break;
61
- }
62
- break;
63
- }
64
-
65
- $topic = get_topic( $bb_post->topic_id );
66
-
67
- if ( $sendto = wp_get_referer() ) {
68
- $sendto = remove_query_arg( 'message', $sendto );
69
- $sendto = add_query_arg( 'message', $message, $sendto );
70
- $send_to_topic = bb_get_topic_from_uri( $sendto );
71
- if ( $send_to_topic && $topic->topic_id == $send_to_topic->topic_id )
72
- $sendto = add_query_arg( 'view', 'all', $sendto );
73
- } else if ( $topic->topic_posts == 0 ) {
74
- $sendto = get_forum_link( $topic->forum_id );
75
- } else {
76
- $the_page = bb_get_page_number( $bb_post->post_position );
77
- $sendto = get_topic_link( $bb_post->topic_id, $the_page );
78
- }
79
-
80
- bb_safe_redirect( $sendto );
81
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/delete-topic.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
- require('admin-action.php');
3
-
4
- $topic_id = (int) $_GET['id'];
5
-
6
- if ( !bb_current_user_can( 'delete_topic', $topic_id ) ) {
7
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
8
- exit;
9
- }
10
-
11
- bb_check_admin_referer( 'delete-topic_' . $topic_id );
12
-
13
- $topic = get_topic( $topic_id );
14
- $old_status = (int) $topic->topic_status;
15
-
16
- if ( !$topic )
17
- bb_die(__('There is a problem with that topic, pardner.'));
18
-
19
- $status = $topic->topic_status ? 0 : 1;
20
- bb_delete_topic( $topic->topic_id, $status );
21
-
22
- $message = '';
23
- switch ( $old_status ) {
24
- case 0:
25
- switch ( $status ) {
26
- case 0:
27
- break;
28
- case 1:
29
- $message = 'deleted';
30
- break;
31
- }
32
- break;
33
- case 1:
34
- switch ( $status ) {
35
- case 0:
36
- $message = 'undeleted';
37
- break;
38
- case 1:
39
- break;
40
- }
41
- break;
42
- }
43
-
44
- if ( $sendto = wp_get_referer() ) {
45
- $sendto = remove_query_arg( 'message', $sendto );
46
- $sendto = add_query_arg( 'message', $message, $sendto );
47
- } elseif ( 0 == $topic->topic_status )
48
- $sendto = get_forum_link( $topic->forum_id );
49
- else
50
- $sendto = get_topic_link( $topic_id );
51
-
52
- wp_redirect( $sendto );
53
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/export.php DELETED
@@ -1,305 +0,0 @@
1
- <?php
2
-
3
- require_once( '../bb-load.php' );
4
- require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
5
-
6
- define('BB_EXPORT_USERS', 1);
7
- define('BB_EXPORT_FORUMS', 2);
8
- define('BB_EXPORT_TOPICS', 4);
9
-
10
- // Some example usage of the bitwise export levels (can be defined in bb-config.php)
11
- //define('BB_EXPORT_LEVEL', BB_EXPORT_USERS);
12
- //define('BB_EXPORT_LEVEL', BB_EXPORT_USERS + BB_EXPORT_FORUMS);
13
- //define('BB_EXPORT_LEVEL', BB_EXPORT_USERS + BB_EXPORT_FORUMS + BB_EXPORT_TOPICS);
14
-
15
- if ( !defined('BB_EXPORT_LEVEL') )
16
- define('BB_EXPORT_LEVEL', 0);
17
-
18
- if ( !BB_EXPORT_LEVEL || !bb_current_user_can( 'import_export' ) )
19
- bb_die( __('Either export is disabled or you are not allowed to export.') );
20
-
21
- // See bb_export_user for syntax
22
- function _bb_export_object( $object, $properties = null, $tabs = 1 ) {
23
- $r = '';
24
-
25
- if ( !$type = $object['type'] )
26
- return;
27
- unset($object['type']);
28
-
29
- $atts = '';
30
- $id = 0;
31
- foreach ( $object as $att => $v ) {
32
- if ( 'id' == $att ) {
33
- $id = $v;
34
- $v = $type . '_' . $v;
35
- }
36
- $atts .= " $att='$v'";
37
- }
38
- unset($att, $v);
39
-
40
- $r .= str_repeat("\t", $tabs) . "<$type{$atts}>\n";
41
-
42
- foreach ( (array) $properties as $k => $v ) {
43
- if ( 'meta' == $k ) {
44
- $data = '';
45
- foreach ( $v as $mk => $mv )
46
- $data .= str_repeat("\t", $tabs + 1) . "<meta key='$mk'><![CDATA[$mv]]></meta>\n";
47
- } else {
48
- if ( '!' == $k{0} ) {
49
- $k = substr($k, 1);
50
- $v = "<![CDATA[$v]]>";
51
- }
52
- $data = str_repeat("\t", $tabs + 1) . "<$k>$v</$k>\n";
53
- }
54
- $r .= $data;
55
- }
56
-
57
- $r .= apply_filters( 'in_bb_export_object_' . $type, '', $id );
58
-
59
- $r .= str_repeat("\t", $tabs) . "</$type>\n\n";
60
-
61
- return $r;
62
- }
63
-
64
- // See bb_export_user for syntax
65
- function _bb_translate_for_export( $translate, &$data ) {
66
- $r = array();
67
- foreach ( $translate as $prop => $export ) {
68
- if ( '?' == $export{0} ) {
69
- $export = substr($export, 1);
70
- if ( !$data[$prop] ) {
71
- unset($data[$prop]);
72
- continue;
73
- }
74
- }
75
- if ( false === $export ) {
76
- unset($data[$prop]);
77
- continue;
78
- }
79
- $r[$export] = $data[$prop];
80
- unset($data[$prop]);
81
- }
82
- unset($export, $prop);
83
- return $r;
84
- }
85
-
86
- function bb_export_user( $user_id ) {
87
- global $bbdb;
88
- if ( !$_user = bb_get_user( $user_id ) )
89
- return;
90
-
91
- $_user = get_object_vars($_user);
92
-
93
- $atts = array(
94
- 'type' => 'user',
95
- 'id' => $_user['ID']
96
- );
97
-
98
- // ?url means url is optional. Only include it in the export if it exists
99
- // !title means the title should be wrapped in CDATA
100
- // ?! is the correct order, not !?
101
- $translate = array(
102
- 'user_login' => 'login',
103
- 'user_pass' => 'pass',
104
- 'user_email' => 'email',
105
- 'user_url' => '?url',
106
- 'user_registered' => 'incept',
107
- 'display_name' => '?!title',
108
- 'user_nicename' => '?nicename',
109
- 'user_status' => '?status',
110
- 'ID' => false
111
- );
112
-
113
- $user = _bb_translate_for_export( $translate, $_user );
114
-
115
- $meta = array();
116
- foreach ( $_user as $k => $v ) {
117
- if ( 0 !== strpos($k, $bbdb->prefix) && isset($_user[$bbdb->prefix . $k]) )
118
- continue;
119
- $meta[$k] = maybe_serialize($v);
120
- }
121
- unset($_user, $k, $v);
122
-
123
- $user['meta'] = $meta;
124
-
125
- return _bb_export_object( $atts, $user );
126
- }
127
-
128
- function bb_export_forum( $forum_id ) {
129
- if ( !$_forum = bb_get_forum( $forum_id ) )
130
- return;
131
-
132
- $_forum = get_object_vars( $_forum );
133
-
134
- $translate = array(
135
- 'forum_name' => '!title',
136
- 'forum_desc' => '?!content',
137
- 'forum_parent' => '?parent'
138
- );
139
-
140
- $forum = _bb_translate_for_export( $translate, $_forum );
141
-
142
- return _bb_export_object( array('type' => 'forum', 'id' => $_forum['forum_id']), $forum );
143
- }
144
-
145
- function bb_export_topic( $topic_id ) {
146
- if ( !$_topic = get_topic( $topic_id ) )
147
- return;
148
-
149
- $_topic = get_object_vars( $_topic );
150
-
151
- $atts = array(
152
- 'type' => 'topic',
153
- 'id' => $_topic['topic_id'],
154
- 'author' => 'user_' . $_topic['topic_poster'],
155
- 'in' => 'forum_' . $_topic['forum_id']
156
- );
157
-
158
- $translate = array(
159
- 'topic_title' => '!title',
160
- 'topic_start_time' => 'incept',
161
- 'topic_status' => '?status',
162
- 'topic_id' => false,
163
- 'topic_poster' => false,
164
- 'topic_poster_name' => false,
165
- 'topic_last_poster' => false,
166
- 'topic_last_poster_name' => false,
167
- 'topic_time' => false,
168
- 'forum_id' => false,
169
- 'topic_last_post_id' => false,
170
- 'topic_posts' => false,
171
- 'tag_count' => false
172
- );
173
-
174
- $topic = _bb_translate_for_export( $translate, $_topic );
175
-
176
- $meta = array();
177
- foreach ( $_topic as $k => $v )
178
- $meta[$k] = maybe_serialize($v);
179
- unset($_topic, $k, $v);
180
-
181
- $topic['meta'] = $meta;
182
-
183
- return _bb_export_object( $atts, $topic );
184
- }
185
-
186
- function bb_export_post( $post_id ) {
187
- if ( !$_post = bb_get_post( $post_id ) )
188
- return;
189
-
190
- $_post = get_object_vars($_post);
191
-
192
- $atts = array(
193
- 'type' => 'post',
194
- 'id' => $_post['post_id'],
195
- 'author' => 'user_' . $_post['poster_id']
196
- );
197
-
198
- $translate = array(
199
- 'post_time' => 'incept',
200
- 'post_text' => '!content',
201
- 'post_status' => '?status',
202
- 'post_id' => false,
203
- 'poster_id' => false,
204
- 'forum_id' => false,
205
- 'topic_id' => false,
206
- 'post_position' => false
207
- );
208
-
209
- $post = _bb_translate_for_export( $translate, $_post );
210
-
211
- $post['meta'] = $_post;
212
-
213
- return _bb_export_object( $atts, $post, 2 );
214
- }
215
-
216
- // One of these things is not like the others...
217
- function bb_export_tag( $tag ) {
218
- // id here is not numeric. does not currently preserve tagged_on
219
- return "\t\t<tag author='user_$tag->user_id' id='tag_$tag->tag'><![CDATA[$tag->raw_tag]]></tag>\n";
220
- }
221
-
222
- function bb_export_topic_tags( $r, $topic_id ) {
223
- global $topic_tag_cache;
224
- if ( !get_topic( $topic_id ) )
225
- return;
226
-
227
- if ( !$tags = bb_get_topic_tags( $topic_id ) )
228
- return $r;
229
-
230
- $r .= "\n";
231
-
232
- foreach ( (array) $tags as $tag )
233
- $r .= bb_export_tag( $tag );
234
- $topic_tag_cache = array();
235
-
236
- return $r;
237
- }
238
-
239
- function bb_export_topic_posts( $r, $topic_id ) {
240
- if ( !get_topic( $topic_id ) )
241
- return;
242
-
243
- $r .= "\n";
244
-
245
- $page = 1;
246
- while ( $posts = get_thread( $topic_id, array( 'post_status' => 'all', 'page' => $page++ ) ) ) {
247
- foreach ( $posts as $post )
248
- $r .= bb_export_post( $post->post_id );
249
- }
250
-
251
- return $r;
252
- }
253
-
254
- function bb_export() {
255
- global $bb;
256
-
257
- define( 'BB_EXPORTING', true );
258
- do_action( 'bb_pre_export' );
259
-
260
- $bb->use_cache = false; // Turn off hard cache
261
- $bb->page_topics = 100;
262
-
263
- echo "<forums-data version='0.75'>\n";
264
-
265
- if (BB_EXPORT_LEVEL & BB_EXPORT_USERS) {
266
- $page = 1;
267
- while ( ( $users = bb_user_search( array('page' => $page++) ) ) && !is_wp_error( $users ) ) {
268
- foreach ( $users as $user )
269
- echo bb_export_user( $user->ID );
270
- }
271
- unset($users, $user, $page);
272
- }
273
-
274
- if (BB_EXPORT_LEVEL & BB_EXPORT_FORUMS) {
275
- $forums = bb_get_forums();
276
- foreach ( $forums as $forum )
277
- echo bb_export_forum( $forum->forum_id );
278
- unset($forums, $forum);
279
- }
280
-
281
- if (BB_EXPORT_LEVEL & BB_EXPORT_TOPICS) {
282
- $page = 1;
283
- while ( $topics = get_latest_topics( 0, $page++ ) ) {
284
- foreach ( $topics as $topic )
285
- echo bb_export_topic( $topic->topic_id );
286
- }
287
- unset($topics, $topic, $page);
288
- }
289
-
290
- do_action( 'bb_export' );
291
-
292
- echo '</forums-data>';
293
- }
294
-
295
- add_filter( 'in_bb_export_object_topic', 'bb_export_topic_tags', 10, 2 );
296
- add_filter( 'in_bb_export_object_topic', 'bb_export_topic_posts', 10, 2 );
297
- add_filter( 'get_forum_where', 'bb_no_where', 9999 );
298
- add_filter( 'get_forums_where', 'bb_no_where', 9999 );
299
- add_filter( 'get_latest_topics_where', 'bb_no_where', 9999 );
300
- add_filter( 'get_user_where', 'bb_no_where', 9999 );
301
- add_filter( 'cache_users_where', 'bb_no_where', 9999 );
302
-
303
- bb_export();
304
-
305
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/forums.php DELETED
@@ -1,106 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- $forums = bb_get_forums();
5
- $forums_count = $forums ? count($forums) : 0;
6
-
7
- if ( isset($_GET['action']) && 'delete' == $_GET['action'] ) {
8
- $forum_to_delete = (int) $_GET['id'];
9
- $deleted_forum = bb_get_forum( $forum_to_delete );
10
- if ( !$deleted_forum || $forums_count < 2 || !bb_current_user_can( 'delete_forum', $forum_to_delete ) ) {
11
- bb_safe_redirect( add_query_arg( array('action' => false, 'id' => false) ) );
12
- exit;
13
- }
14
- }
15
-
16
- if ( isset($_GET['message']) ) {
17
- switch ( $_GET['message'] ) :
18
- case 'updated' :
19
- bb_admin_notice( __( '<strong>Forum Updated.</strong>' ) );
20
- break;
21
- case 'deleted' :
22
- bb_admin_notice( sprintf(
23
- __( '<strong>Forum deleted.</strong> You should <a href="%s">recount your site information</a>.' ),
24
- bb_get_uri('bb-admin/tools-recount.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN)
25
- ) );
26
- break;
27
- endswitch;
28
- }
29
-
30
- if ( !isset($_GET['action']) )
31
- wp_enqueue_script( 'admin-forums' );
32
- elseif ( 'delete' == @$_GET['action'] )
33
- bb_admin_notice( sprintf( __( 'Are you sure you want to delete the "<strong>%s</strong>" forum?' ), $deleted_forum->forum_name ) );
34
-
35
- $bb_admin_body_class = ' bb-admin-forums';
36
-
37
- bb_get_admin_header();
38
- ?>
39
-
40
- <div class="wrap">
41
-
42
- <h2><?php _e('Forums'); ?></h2>
43
- <?php do_action( 'bb_admin_notices' ); ?>
44
- <?php switch ( @$_GET['action'] ) : ?>
45
- <?php case 'edit' : ?>
46
- <?php bb_forum_form( (int) $_GET['id'] ); ?>
47
- <?php break; case 'delete' : ?>
48
-
49
- <form class="settings" method="post" id="delete-forums" action="<?php bb_uri('bb-admin/bb-forum.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>">
50
- <fieldset>
51
- <legend><?php _e('Delete Forum'); ?></legend>
52
- <p><?php _e('This forum contains:'); ?></p>
53
- <ul>
54
- <li><?php printf(__ngettext('%d topic', '%d topics', $deleted_forum->topics), $deleted_forum->topics); ?></li>
55
- <li><?php printf(__ngettext('%d post', '%d posts', $deleted_forum->posts), $deleted_forum->posts); ?></li>
56
- </ul>
57
- <div id="option-forum-delete-contents">
58
- <div class="label"><?php _e( 'Action' ); ?></div>
59
- <div class="inputs">
60
- <label class="radios">
61
- <input type="radio" name="move_topics" id="move-topics-delete" value="delete" /> <?php _e('Delete all topics and posts in this forum. <em>This can never be undone.</em>'); ?>
62
- </label>
63
- <label class="radios">
64
- <input type="radio" name="move_topics" id="move-topics-move" value="move" checked="checked" /> <?php _e('Move topics from this forum into the replacement forum below.'); ?>
65
- </label>
66
- </div>
67
- </div>
68
- <div id="option-forum-delete-contents">
69
- <label for="move-topics-forum"><?php _e( 'Replacement forum' ); ?></label>
70
- <div class="inputs">
71
- <?php bb_forum_dropdown( array('id' => 'move_topics_forum', 'callback' => 'strcmp', 'callback_args' => array($deleted_forum->forum_id), 'selected' => $deleted_forum->forum_parent) ); ?>
72
- </div>
73
- </div>
74
- </fieldset>
75
- <fieldset class="submit">
76
- <?php bb_nonce_field( 'delete-forums' ); ?>
77
- <input type="hidden" name="action" value="delete" />
78
- <input type="hidden" name="forum_id" value="<?php echo $deleted_forum->forum_id; ?>" />
79
- <a href="<?php bb_uri('bb-admin/forums.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN); ?>" class="cancel"><?php _e('Cancel') ?></a>
80
- <input class="submit delete" type="submit" name="submit" value="<?php _e('Delete Forum') ?>" />
81
- </fieldset>
82
- </form>
83
-
84
- <?php break; default : ?>
85
-
86
-
87
- <?php if ( bb_forums( 'type=list&walker=BB_Walker_ForumAdminlistitems' ) ) : ?>
88
- <ul id="forum-list" class="list:forum list-block holder">
89
- <li class="thead list-block"><?php _e('Forum'); ?></li>
90
- <?php while ( bb_forum() ) : ?>
91
- <?php bb_forum_row(); ?>
92
- <?php endwhile; ?>
93
- </ul>
94
- <?php endif; // bb_forums() ?>
95
-
96
- <hr class="settings" />
97
-
98
- <?php bb_forum_form(); ?>
99
-
100
- <?php break; endswitch; // action ?>
101
-
102
- <div id="ajax-response"></div>
103
-
104
- </div>
105
-
106
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/images/admin-header-logo.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/bbpress-logo.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/blank.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/button-grad.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/drag.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/favicon.ico DELETED
Binary file
bp-forums/bbpress/bb-admin/images/gray-grad.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/icons32.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/input-lock.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/menu-arrows.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/menu-bits-rtl.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/menu-bits.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/menu-dark-rtl.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/menu-dark.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/menu.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/visit-site-button-grad.gif DELETED
Binary file
bp-forums/bbpress/bb-admin/images/white-grad-active.png DELETED
Binary file
bp-forums/bbpress/bb-admin/images/white-grad.png DELETED
Binary file
bp-forums/bbpress/bb-admin/includes/class.bb-install.php DELETED
@@ -1,2770 +0,0 @@
1
- <?php
2
- /**
3
- * bbPress Installation class
4
- *
5
- * @since 0.9
6
- */
7
- class BB_Install
8
- {
9
- /**
10
- * The file where the class was instantiated
11
- *
12
- * @var string
13
- */
14
- var $caller;
15
-
16
- /**
17
- * Whether or not we need to load some of the includes normally loaded by bb-settings.php
18
- *
19
- * @var boolean
20
- */
21
- var $load_includes = false;
22
-
23
- /**
24
- * An array of available languages to use in the installer
25
- *
26
- * @var array
27
- */
28
- var $languages = array( 'en_US' => 'en_US' );
29
-
30
- /**
31
- * The currently selected language for the installer
32
- *
33
- * @var string
34
- */
35
- var $language = 'en_US';
36
-
37
- /**
38
- * The current step in the install process
39
- *
40
- * @var integer
41
- */
42
- var $step;
43
-
44
- /**
45
- * Info about config files and their locations
46
- *
47
- * @var array
48
- */
49
- var $configs = array(
50
- 'writable' => false,
51
- 'bb-config.php' => false,
52
- 'config.php' => false
53
- );
54
-
55
- /**
56
- * An array of the current status of each step
57
- *
58
- * @var array
59
- */
60
- var $step_status = array(
61
- 0 => 'incomplete',
62
- 1 => 'incomplete',
63
- 2 => 'incomplete',
64
- 3 => 'incomplete',
65
- 4 => 'incomplete'
66
- );
67
-
68
- /**
69
- * An array of most strings in use, including errors
70
- *
71
- * @var array
72
- */
73
- var $strings = array();
74
-
75
- /**
76
- * The data being manipulated as we go through the forms
77
- *
78
- * @var array
79
- */
80
- var $data = array();
81
-
82
- /**
83
- * A boolean that can get flagged to stop posting of a form getting processed
84
- *
85
- * @var boolean
86
- */
87
- var $stop_process = false;
88
-
89
- /**
90
- * Keeps track of where the tabindex is up to
91
- *
92
- * @var integer
93
- */
94
- var $tabindex = 0;
95
-
96
- /**
97
- * Constructor
98
- *
99
- * Loads everything we might need to do the business
100
- *
101
- * @param string $caller The full path of the file that instantiated the class
102
- * @return boolean Always returns true
103
- */
104
- function __construct( $caller )
105
- {
106
- $this->caller = $caller;
107
-
108
- $this->set_initial_step();
109
- $this->define_paths();
110
-
111
- // We need to load these when bb-settings.php isn't loaded
112
- if ( $this->load_includes ) {
113
- require_once( BACKPRESS_PATH . 'functions.core.php' );
114
- require_once( BACKPRESS_PATH . 'functions.compat.php' );
115
- require_once( BACKPRESS_PATH . 'functions.formatting.php' );
116
- require_once( BACKPRESS_PATH . 'functions.plugin-api.php' );
117
- require_once( BACKPRESS_PATH . 'class.wp-error.php' );
118
- require_once( BB_PATH . BB_INC . 'functions.bb-core.php' );
119
- require_once( BB_PATH . BB_INC . 'functions.bb-meta.php' );
120
- require_once( BB_PATH . BB_INC . 'class.bp-options.php' );
121
- require_once( BACKPRESS_PATH . 'functions.bp-options.php' );
122
- require_once( BACKPRESS_PATH . 'functions.kses.php' );
123
- require_once( BB_PATH . BB_INC . 'functions.bb-l10n.php' );
124
- require_once( BB_PATH . BB_INC . 'functions.bb-template.php' );
125
- }
126
-
127
- $this->get_languages();
128
- $this->set_language();
129
-
130
- if ( $this->language ) {
131
- global $locale;
132
- global $l10n;
133
- $locale = $this->language;
134
- unset( $l10n['default'] );
135
-
136
- if ( !class_exists( 'MO' ) ) {
137
- require_once( BACKPRESS_PATH . 'pomo/mo.php' );
138
- }
139
- }
140
-
141
- // Load the default text localization domain. Doing this twice doesn't hurt too much.
142
- bb_load_default_textdomain();
143
-
144
- // Pull in locale data after loading text domain.
145
- if ( $this->load_includes ) {
146
- require_once( BB_PATH . BB_INC . 'class.bb-locale.php' );
147
- }
148
- global $bb_locale;
149
- $bb_locale = new BB_Locale();
150
-
151
- $this->prepare_strings();
152
- $this->check_prerequisites();
153
- $this->check_configs();
154
-
155
- if ( $this->step > -1 ) {
156
- $this->set_step();
157
- $this->prepare_data();
158
- $this->process_form();
159
- }
160
-
161
- return true;
162
- }
163
-
164
- function BB_Install( $caller ) {
165
- $this->__construct( $caller );
166
- }
167
-
168
- /**
169
- * Set initial step
170
- *
171
- * Sets the step from the post data and keeps it within range
172
- *
173
- * @return integer The calculated step
174
- */
175
- function set_initial_step()
176
- {
177
- // Set the step based on the $_POST value or 0
178
- $this->step = $_POST['step'] ? (integer) $_POST['step'] : 0;
179
-
180
- // Make sure the requested step is from 0-4
181
- if ( 0 > $this->step || 4 < $this->step ) {
182
- $this->step = 0;
183
- }
184
- return $this->step;
185
- }
186
-
187
- /**
188
- * Prepare text strings
189
- *
190
- * Sets up many of the strings to be used by the class that may
191
- * be later subject to change due to processing of the forms
192
- */
193
- function prepare_strings()
194
- {
195
- $this->strings = array(
196
- -1 => array(
197
- 'title' => __( 'bbPress &rsaquo; Error' ),
198
- 'h1' => __( 'Oh dear!' ),
199
- 'messages' => array()
200
- ),
201
- 0 => array(
202
- 'title' => sprintf( __( '%1$s &rsaquo; %2$s' ), __( 'bbPress installer' ), __( 'Welcome' ) ),
203
- 'h2' => __( 'Welcome to the bbPress installer' ),
204
- 'status' => '',
205
- 'messages' => array(),
206
- 'intro' => array(
207
- __( 'We\'re now going to go through a few steps to get you up and running.' ),
208
- __( 'Ready? Then let\'s get started!' )
209
- )
210
- ),
211
- 1 => array(
212
- 'title' => sprintf( __( '%1$s &rsaquo; %2$s' ), __( 'bbPress installer' ), __( 'Step 1' ) ),
213
- 'h2' => sprintf( __( '%1$s - %2$s' ), __( 'Step 1' ), __( 'Database configuration' ) ),
214
- 'status' => '',
215
- 'intro' => array(
216
- __( 'In this step you need to enter your database connection details. The installer will attempt to create a file called <code>bb-config.php</code> in the root directory of your bbPress installation.' ),
217
- __( 'If you\'re not sure what to put here, contact your web hosting provider.' )
218
- ),
219
- 'messages' => array()
220
- ),
221
- 2 => array(
222
- 'title' => sprintf( __( '%1$s &rsaquo; %2$s' ), __( 'bbPress installer' ), __( 'Step 2' ) ),
223
- 'h2' => sprintf( __( '%1$s - %2$s' ), __( 'Step 2' ), __( 'WordPress integration (optional)' ) ),
224
- 'status' => __( '&laquo; skipped' ),
225
- 'intro' => array(
226
- __( 'bbPress can integrate login and user data seamlessly with WordPress. You can safely skip this step if you do not wish to integrate with an existing WordPress install.' )
227
- ),
228
- 'messages' => array(),
229
- 'form_errors' => array()
230
- ),
231
- 3 => array(
232
- 'title' => sprintf( __( '%1$s &rsaquo; %2$s' ), __( 'bbPress installer' ), __( 'Step 3' ) ),
233
- 'h2' => sprintf( __( '%1$s - %2$s' ), __( 'Step 3' ), __( 'Site settings' ) ),
234
- 'status' => '',
235
- 'intro' => array(
236
- __( 'Finalize your installation by adding a name, your first user and your first forum.' )
237
- ),
238
- 'messages' => array(),
239
- 'form_errors' => array(),
240
- 'scripts' => array()
241
- ),
242
- 4 => array(
243
- 'title' => sprintf( __( '%1$s &rsaquo; %2$s' ), __( 'bbPress installer' ), __( 'Finished' ) ),
244
- 'h2' => __( 'Installation complete!' ),
245
- 'messages' => array()
246
- )
247
- );
248
- }
249
-
250
- /**
251
- * Check installation pre-requisites
252
- *
253
- * Checks for appropriate PHP extensions.
254
- *
255
- * @return boolean False if any pre-requisites are not met, otherwise true
256
- */
257
- function check_prerequisites()
258
- {
259
- // BPDB wants the MySQL extension - this is also checked when BPDB is initialised so may be a bit redundant here
260
- if ( !extension_loaded( 'mysql' ) ) {
261
- $this->strings[-1]['messages']['error'][] = __( 'Your PHP installation appears to be missing the MySQL extension which is required for bbPress' );
262
- $this->step = -1;
263
- }
264
-
265
- if ( defined( 'BB_IS_WP_LOADED' ) && BB_IS_WP_LOADED ) {
266
- $this->strings[-1]['messages']['error'][] = __( 'Please complete your installation before attempting to include WordPress within bbPress' );
267
- $this->step = -1;
268
- }
269
-
270
- if ( $this->step === -1 ) {
271
- return false;
272
- }
273
-
274
- return true;
275
- }
276
-
277
- /**
278
- * Define path constants
279
- *
280
- * Sets some bbPress constants if they are not otherwise available based
281
- * on the classes initiating file path.
282
- *
283
- * @return boolean False if no path was supplied, otherwise always true
284
- */
285
- function define_paths()
286
- {
287
- if ( !$this->caller ) {
288
- return false;
289
- }
290
-
291
- if ( !defined( 'BACKPRESS_PATH' ) ) {
292
- // Define BACKPRESS_PATH
293
- // Tell us to load includes because bb-settings.php was not loaded
294
- // bb-settings.php is generally not loaded on steps -1, 0 and 1 but
295
- // there are exceptions, so this is safer than just reading the step
296
- $this->load_includes = true;
297
- define( 'BACKPRESS_PATH', BB_PATH . BB_INC . 'backpress/' );
298
- }
299
-
300
- // Define the language file directory
301
- if ( !defined( 'BB_LANG_DIR' ) ) {
302
- define( 'BB_LANG_DIR', BB_PATH . 'my-languages/' );
303
- }
304
-
305
- return true;
306
- }
307
-
308
- /**
309
- * Gets an array of available languages form the language directory
310
- *
311
- * @return array
312
- */
313
- function get_languages()
314
- {
315
- foreach ( bb_glob( BB_LANG_DIR . '*.mo' ) as $language ) {
316
- if ( substr( $language, 0, 18 ) === 'continents-cities-' ) {
317
- continue;
318
- }
319
- $language = str_replace( '.mo', '', basename( $language ) );
320
- $this->languages[$language] = $language;
321
- }
322
-
323
- return $this->languages;
324
- }
325
-
326
- /**
327
- * Returns a language selector for switching installation languages
328
- *
329
- * @return string|false Either the html for the selector or false if there are no languages
330
- */
331
- function get_language_selector()
332
- {
333
- // Don't provide a selection if there is only english
334
- if ( 2 > count( $this->languages ) ) {
335
- return false;
336
- }
337
-
338
- $r = '<script type="text/javascript" charset="utf-8">' . "\n";
339
- $r .= "\t" . 'function changeLanguage(selectObj) {' . "\n";
340
- $r .= "\t\t" . 'var selectedLanguage = selectObj.options[selectObj.selectedIndex].value;' . "\n";
341
- $r .= "\t\t" . 'location.href = "install.php?language=" + selectedLanguage;' . "\n";
342
- $r .= "\t" . '}' . "\n";
343
- $r .= '</script>' . "\n";
344
- //$r .= '<form id="lang" action="install.php">' . "\n";
345
- $r .= "\t" . '<fieldset>' . "\n";
346
- $r .= "\t\t" . '<label class="has-note has-label for-select">' . "\n";
347
- $r .= "\t\t\t" . '<span>' . __( 'Installation language' ) . '</span>' . "\n";
348
- $this->tabindex++;
349
- $r .= "\t\t\t" . '<select class="has-note" onchange="changeLanguage(this);" name="language" tabindex="' . $this->tabindex . '">' . "\n";
350
- foreach ( $this->languages as $language ) {
351
- $selected = '';
352
- if ( $language == $this->language ) {
353
- $selected = ' selected="selected"';
354
- }
355
- $r .= "\t\t\t\t" . '<option value="' . $language . '"' . $selected . '>' . $language . '</option>' . "\n";
356
- }
357
- $r .= "\t\t\t" . '</select>' . "\n";
358
- $r .= "\t\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-language\');">?</a>' . "\n";
359
- $r .= "\t\t\t" . '<p id="note-language" class="note" style="display:none">' . __( 'Sets the language to be used during the installation process only.' ) . '</p>' . "\n";
360
- $r .= "\t\t\t" . '<div class="clear"></div>' . "\n";
361
- $r .= "\t\t" . '</label>' . "\n";
362
- $r .= "\t" . '</fieldset>' . "\n";
363
- //$r .= '</form>' . "\n";
364
-
365
- echo $r;
366
- }
367
-
368
- /**
369
- * Sets the current installation language
370
- *
371
- * @return string The currently set language
372
- */
373
- function set_language()
374
- {
375
- if ( isset( $_COOKIE['bb_install_language'] ) && 1 < count( $this->languages ) ) {
376
- if ( in_array( $_COOKIE['bb_install_language'], $this->languages ) ) {
377
- $this->language = $_COOKIE['bb_install_language'];
378
- }
379
- }
380
-
381
- $language_requested = false;
382
- if ( isset( $_POST['language'] ) && $_POST['language'] ) {
383
- $language_requested = (string) $_POST['language'];
384
- } elseif ( isset( $_GET['language'] ) && $_GET['language'] ) {
385
- $language_requested = (string) $_GET['language'];
386
- }
387
-
388
- if ( $language_requested && 1 < count( $this->languages ) ) {
389
- if ( in_array( $language_requested, $this->languages ) ) {
390
- $this->language = $language_requested;
391
- setcookie( 'bb_install_language', $this->language );
392
- }
393
- }
394
-
395
- if ( !$this->language || 'en_US' === $this->language ) {
396
- $this->language = 'en_US';
397
- setcookie( 'bb_install_language', ' ', time() - 31536000 );
398
- }
399
-
400
- return $this->language;
401
- }
402
-
403
- /**
404
- * Tests whether database tables exist
405
- *
406
- * Checks for the existence of the forum table in the database that is
407
- * currently configured.
408
- *
409
- * @return boolean False if the table isn't found, otherwise true
410
- */
411
- function database_tables_are_installed()
412
- {
413
- global $bbdb;
414
- $bbdb->suppress_errors();
415
- $installed = (boolean) $bbdb->get_results( 'DESCRIBE `' . $bbdb->forums . '`;', ARRAY_A );
416
- $bbdb->suppress_errors( false );
417
- return $installed;
418
- }
419
-
420
- /**
421
- * Tests whether an option is set in the database
422
- *
423
- * @return boolean False if the option isn't set, otherwise true
424
- */
425
- function bb_options_are_set()
426
- {
427
- if ( $this->load_includes ) {
428
- return false;
429
- }
430
- if ( !bb_get_option( 'uri' ) ) {
431
- return false;
432
- }
433
- return true;
434
- }
435
-
436
- /**
437
- * Tests whether bbPress is installed
438
- *
439
- * @return boolean False if bbPress isn't installed, otherwise true
440
- */
441
- function is_installed()
442
- {
443
- if ( !$this->database_tables_are_installed() ) {
444
- return false;
445
- }
446
- if ( !$this->bb_options_are_set() ) {
447
- return false;
448
- }
449
- return true;
450
- }
451
-
452
- /**
453
- * Checks for configs and sets variables describing current install state
454
- *
455
- * @return integer The current step we should be on based on the existence of the config file
456
- */
457
- function check_configs()
458
- {
459
- // Check for a config file
460
- if ( file_exists( BB_PATH . 'bb-config.php' ) ) {
461
- $this->configs['bb-config.php'] = BB_PATH . 'bb-config.php';
462
- } elseif ( file_exists( dirname( BB_PATH ) . '/bb-config.php' ) ) {
463
- $this->configs['bb-config.php'] = dirname( BB_PATH ) . '/bb-config.php';
464
- }
465
-
466
- // Check for an old config file
467
- if ( file_exists( BB_PATH . 'config.php' ) ) {
468
- $this->configs['config.php'] = BB_PATH . 'config.php';
469
- } elseif ( file_exists( dirname( BB_PATH ) . '/config.php' ) ) {
470
- $this->configs['config.php'] = dirname( BB_PATH ) . '/config.php';
471
- }
472
-
473
- if ( $this->configs['config.php'] && !$this->configs['bb-config.php'] ) {
474
- // There is an old school config file
475
- // Step -1 is where we send fatal errors from any screen
476
- $this->strings[-1]['messages']['error'][] = __( 'An old <code>config.php</code> file has been detected in your installation. You should remove it and run the <a href="install.php">installer</a> again. You can use the same database connection details if you do.' );
477
- $this->step = -1;
478
- return $this->step;
479
- }
480
-
481
- // Check if bbPress is already installed
482
- // Is there a current config file
483
- if ( $this->configs['bb-config.php'] ) {
484
-
485
- // Is it valid
486
- if ( $this->validate_current_config() ) {
487
- // Step 1 is complete
488
- $this->step_status[1] = 'complete';
489
- $this->strings[1]['status'] = __( '&laquo; completed' );
490
-
491
- // On step 1 we want to report that the file is good and allow the user to continue
492
- if ( $this->step === 1 ) {
493
- // Stop form processing if it is posted
494
- $this->stop_process = true;
495
-
496
- // Display a nice message saying the config file exists
497
- $this->strings[1]['messages']['message'][] = __( 'A valid configuration file was found at <code>bb-config.php</code><br />You may continue to the next step.' );
498
- return $this->step;
499
- }
500
- } else {
501
- // Invalid config files on any step cause us to exit to step 0
502
- $this->strings[-1]['messages']['error'][] = __( 'An invalid configuration file was found at <code>bb-config.php</code><br />The installation cannot continue.' );
503
- $this->strings[-1]['messages'][0][] = __( 'Usually this is caused by one of the database connection settings being incorrect. Make sure that the specified user has appropriate permission to access the database.' );
504
- $this->step = -1;
505
- }
506
-
507
- // If we have made it this far, then we can check if the database tables exist and have content
508
- if ( $this->is_installed() ) {
509
- // The database is installed
510
- // The following standard functions should be available
511
- if ( bb_get_option( 'bb_db_version' ) > bb_get_option_from_db( 'bb_db_version' ) ) {
512
- // The database needs upgrading
513
- $this->strings[-1]['messages'][0][] = __( 'bbPress is already installed, but appears to require an upgrade.' );
514
- } else {
515
- $this->strings[-1]['messages'][0][] = __( 'bbPress is already installed.' );
516
- }
517
- $this->strings[-1]['messages'][0][] = sprintf(
518
- __( 'Perhaps you meant to run the <a href="%s">upgrade script</a> instead?' ),
519
- bb_get_uri( 'bb-admin/upgrade.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN )
520
- );
521
- $this->step = -1;
522
- }
523
-
524
- } else {
525
-
526
- if ( 2 > $this->step && !file_exists( BB_PATH . 'bb-config-sample.php' ) ) {
527
- // There is no sample config file
528
- $this->strings[0]['messages']['error'][] = __( 'I could not find the file <code>bb-config-sample.php</code><br />Please upload it to the root directory of your bbPress installation.' );
529
- $this->step = 0;
530
- }
531
-
532
- if ( 1 !== $this->step ) {
533
- // There is no config file, go back to the beginning
534
- $this->strings[0]['messages']['message'][] = __( 'There doesn\'t seem to be a <code>bb-config.php</code> file. This usually means that you want to install bbPress.' );
535
- $this->step = 0;
536
- }
537
-
538
- }
539
-
540
- // Check if the config file path is writable
541
- if ( file_exists( $this->configs['bb-config.php'] ) ) {
542
- if ( is_writable( $this->configs['bb-config.php'] ) ) {
543
- $this->configs['writable'] = true;
544
- }
545
- } elseif ( is_writable( BB_PATH ) ) {
546
- $this->configs['writable'] = true;
547
- }
548
-
549
- return $this->step;
550
- }
551
-
552
- /**
553
- * Determines if the current config is valid
554
- *
555
- * @return boolean False if the config is bad, otherwise true
556
- */
557
- function validate_current_config()
558
- {
559
- // If we are validating then the config file has already been included
560
- // So we can just check for valid constants
561
-
562
- // The required constants for a valid config file
563
- $required_constants = array(
564
- 'BBDB_NAME',
565
- 'BBDB_USER',
566
- 'BBDB_PASSWORD',
567
- 'BBDB_HOST'
568
- );
569
-
570
- // Check the required constants are defined
571
- foreach ( $required_constants as $required_constant ) {
572
- if ( !defined( $required_constant ) ) {
573
- return false;
574
- }
575
- }
576
-
577
- global $bb_table_prefix;
578
-
579
- if ( !isset( $bb_table_prefix ) ) {
580
- return false;
581
- }
582
-
583
- // Everthing is OK so far, validate the connection as well
584
- return $this->validate_current_database();
585
- }
586
-
587
- /**
588
- * Validates the current database settings
589
- *
590
- * @return boolean False if the current database isn't valid, otherwise true
591
- */
592
- function validate_current_database()
593
- {
594
- global $bbdb;
595
- $db = $bbdb->db_connect( "SELECT * FROM $bbdb->forums LIMIT 1" );
596
-
597
- if ( !is_resource( $db ) ) {
598
- return false;
599
- }
600
-
601
- return true;
602
- }
603
-
604
- /**
605
- * Sets up default values for input data as well as labels and notes
606
- *
607
- * @return void
608
- */
609
- function prepare_data()
610
- {
611
- /**
612
- * Should be exactly the same as the default value of the KEYS in bb-config-sample.php
613
- * @since 1.0
614
- */
615
- $_bb_default_secret_key = 'put your unique phrase here';
616
-
617
- $this->data = array(
618
- 0 => array(
619
- 'form' => array(
620
- 'forward_0_0' => array(
621
- 'value' => __( 'Go to step 1' )
622
- )
623
- )
624
- ),
625
- 1 => array(
626
- 'form' => array(
627
- 'bbdb_name' => array(
628
- 'value' => '',
629
- 'label' => __( 'Database name' ),
630
- 'note' => __( 'The name of the database in which you want to run bbPress.' )
631
- ),
632
- 'bbdb_user' => array(
633
- 'value' => '',
634
- 'label' => __( 'Database user' ),
635
- 'note' => __( 'The database user that has access to that database.' ),
636
- 'autocomplete' => 'off'
637
- ),
638
- 'bbdb_password' => array(
639
- 'type' => 'password',
640
- 'value' => '',
641
- 'label' => __( 'Database password' ),
642
- 'note' => __( 'That database user\'s password.' ),
643
- 'autocomplete' => 'off'
644
- ),
645
- 'bb_lang' => array(
646
- 'value' => '',
647
- 'label' => __( 'Language' ),
648
- 'note' => sprintf( __( 'The language which bbPress will be presented in once installed. Your current installer language choice (%s) will be the same for the rest of the install process.' ), $this->language )
649
- ),
650
- 'toggle_1' => array(
651
- 'value' => 0,
652
- 'label' => __( 'Show advanced settings' ),
653
- 'note' => __( 'These settings usually do not have to be changed.' ),
654
- 'checked' => '',
655
- 'display' => 'none'
656
- ),
657
- 'bbdb_host' => array(
658
- 'value' => 'localhost',
659
- 'label' => __( 'Database host' ),
660
- 'note' => __( 'The domain name or IP address of the server where the database is located. If the database is on the same server as the web site, then this probably should remain <strong>localhost</strong>.' ),
661
- 'prerequisite' => 'toggle_1'
662
- ),
663
- 'bbdb_charset' => array(
664
- 'value' => 'utf8',
665
- 'label' => __( 'Database character set' ),
666
- 'note' => __( 'The best choice is <strong>utf8</strong>, but you will need to match the character set which you created the database with.' ),
667
- 'prerequisite' => 'toggle_1'
668
- ),
669
- 'bbdb_collate' => array(
670
- 'value' => '',
671
- 'label' => __( 'Database character collation' ),
672
- 'note' => __( 'The character collation value set when the database was created.' ),
673
- 'prerequisite' => 'toggle_1'
674
- ),
675
- /*
676
- 'bb_auth_key' => array(
677
- 'value' => $_bb_default_secret_key,
678
- 'label' => __( 'bbPress "auth" cookie key' ),
679
- 'note' => __( 'This should be a unique and secret phrase, it will be used to make your bbPress "auth" cookie unique and harder for an attacker to decipher.' ),
680
- 'prerequisite' => 'toggle_1'
681
- ),
682
- 'bb_secure_auth_key' => array(
683
- 'value' => $_bb_default_secret_key,
684
- 'label' => __( 'bbPress "secure auth" cookie key' ),
685
- 'note' => __( 'This should be a unique and secret phrase, it will be used to make your bbPress "secure auth" cookie unique and harder for an attacker to decipher.' ),
686
- 'prerequisite' => 'toggle_1'
687
- ),
688
- 'bb_logged_in_key' => array(
689
- 'value' => $_bb_default_secret_key,
690
- 'label' => __( 'bbPress "logged in" cookie key' ),
691
- 'note' => __( 'This should be a unique and secret phrase, it will be used to make your bbPress "logged in" cookie unique and harder for an attacker to decipher.' ),
692
- 'prerequisite' => 'toggle_1'
693
- ),
694
- 'bb_nonce_key' => array(
695
- 'value' => $_bb_default_secret_key,
696
- 'label' => __( 'bbPress "nonce" key' ),
697
- 'note' => __( 'This should be a unique and secret phrase, it will be used to make form submission harder for an attacker to spoof.' ),
698
- 'prerequisite' => 'toggle_1'
699
- ),
700
- */
701
- 'bb_table_prefix' => array(
702
- 'value' => 'bb_',
703
- 'label' => __( 'Table name prefix' ),
704
- 'note' => __( 'If you are running multiple bbPress sites in a single database, you will probably want to change this.' ),
705
- 'prerequisite' => 'toggle_1'
706
- ),
707
- 'config' => array(
708
- 'value' => '',
709
- 'label' => __( 'Contents for <code>bb-config.php</code>' ),
710
- 'note' => __( 'Once you have created the configuration file, you can check for it below.' )
711
- ),
712
- 'forward_1_0' => array(
713
- 'value' => __( 'Save database configuration file' )
714
- ),
715
- 'back_1_1' => array(
716
- 'value' => __( '&laquo; Go back' )
717
- ),
718
- 'forward_1_1' => array(
719
- 'value' => __( 'Check for configuration file' )
720
- ),
721
- 'forward_1_2' => array(
722
- 'value' => __( 'Go to step 2' )
723
- )
724
- )
725
- ),
726
-
727
- 2 => array(
728
- 'form' => array(
729
- 'toggle_2_0' => array(
730
- 'value' => 0,
731
- 'label' => __( 'Add integration settings' ),
732
- 'note' => __( 'If you want to integrate bbPress with an existing WordPress site.' ),
733
- 'checked' => '',
734
- 'display' => 'none',
735
- 'toggle_value' => array(
736
- 'target' => 'forward_2_0',
737
- 'off_value' => __( 'Skip WordPress integration' ),
738
- 'on_value' => __( 'Save WordPress integration settings' )
739
- )
740
- ),
741
- 'toggle_2_1' => array(
742
- 'value' => 0,
743
- 'label' => __( 'Add cookie integration settings' ),
744
- 'note' => __( 'If you want to allow shared logins with an existing WordPress site.' ),
745
- 'checked' => '',
746
- 'display' => 'none',
747
- 'prerequisite' => 'toggle_2_0'
748
- ),
749
- 'wp_siteurl' => array(
750
- 'value' => '',
751
- 'label' => __( 'WordPress address (URL)' ),
752
- 'note' => __( 'This value should exactly match the <strong>WordPress address (URL)</strong> setting in your WordPress general settings.' ),
753
- 'prerequisite' => 'toggle_2_1'
754
- ),
755
- 'wp_home' => array(
756
- 'value' => '',
757
- 'label' => __( 'Blog address (URL)' ),
758
- 'note' => __( 'This value should exactly match the <strong>Blog address (URL)</strong> setting in your WordPress general settings.' ),
759
- 'prerequisite' => 'toggle_2_1'
760
- ),
761
- 'wp_auth_key' => array(
762
- 'value' => '',
763
- 'label' => __( 'WordPress "auth" cookie key' ),
764
- 'note' => __( 'This value must match the value of the constant named "AUTH_KEY" in your WordPress <code>wp-config.php</code> file. This will replace the bbPress "auth" cookie key set in the first step.' ),
765
- 'prerequisite' => 'toggle_2_1',
766
- 'autocomplete' => 'off'
767
- ),
768
- 'wp_auth_salt' => array(
769
- 'value' => '',
770
- 'label' => __( 'WordPress "auth" cookie salt' ),
771
- 'note' => __( 'This must match the value of the WordPress setting named "auth_salt" in your WordPress site. Look for the option labeled "auth_salt" in <a href="#" id="getAuthSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. If you leave this blank the installer will try to fetch the value based on your WordPress database integration settings.' ),
772
- 'prerequisite' => 'toggle_2_1',
773
- 'autocomplete' => 'off'
774
- ),
775
- 'wp_secure_auth_key' => array(
776
- 'value' => '',
777
- 'label' => __( 'WordPress "secure auth" cookie key' ),
778
- 'note' => __( 'This value must match the value of the constant named "SECURE_AUTH_KEY" in your WordPress <code>wp-config.php</code> file. This will replace the bbPress "secure auth" cookie key set in the first step.' ),
779
- 'prerequisite' => 'toggle_2_1',
780
- 'autocomplete' => 'off'
781
- ),
782
- 'wp_secure_auth_salt' => array(
783
- 'value' => '',
784
- 'label' => __( 'WordPress "secure auth" cookie salt' ),
785
- 'note' => __( 'This must match the value of the WordPress setting named "secure_auth_salt" in your WordPress site. Look for the option labeled "secure_auth_salt" in <a href="#" id="getSecureAuthSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. If you leave this blank the installer will try to fetch the value based on your WordPress database integration settings. Sometimes this value is not set in WordPress, in that case you can leave this setting blank as well.' ),
786
- 'prerequisite' => 'toggle_2_1',
787
- 'autocomplete' => 'off'
788
- ),
789
- 'wp_logged_in_key' => array(
790
- 'value' => '',
791
- 'label' => __( 'WordPress "logged in" cookie key' ),
792
- 'note' => __( 'This value must match the value of the constant named "LOGGED_IN_KEY" in your WordPress <code>wp-config.php</code> file. This will replace the bbPress "logged in" cookie key set in the first step.' ),
793
- 'prerequisite' => 'toggle_2_1',
794
- 'autocomplete' => 'off'
795
- ),
796
- 'wp_logged_in_salt' => array(
797
- 'value' => '',
798
- 'label' => __( 'WordPress "logged in" cookie salt' ),
799
- 'note' => __( 'This must match the value of the WordPress setting named "logged_in_salt" in your WordPress site. Look for the option labeled "logged_in_salt" in <a href="#" id="getLoggedInSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. If you leave this blank the installer will try to fetch the value based on your WordPress database integration settings.' ),
800
- 'prerequisite' => 'toggle_2_1',
801
- 'autocomplete' => 'off'
802
- ),
803
- 'toggle_2_2' => array(
804
- 'value' => 0,
805
- 'label' => __( 'Add user database integration settings' ),
806
- 'note' => __( 'If you want to share user data with an existing WordPress site.' ),
807
- 'checked' => '',
808
- 'display' => 'none',
809
- 'prerequisite' => 'toggle_2_0'
810
- ),
811
- 'wp_table_prefix' => array(
812
- 'value' => 'wp_',
813
- 'default_value' => '', // Used when setting is ignored
814
- 'label' => __( 'User database table prefix' ),
815
- 'note' => __( 'If your bbPress and WordPress sites share the same database, then this is the same value as <code>$table_prefix</code> in your WordPress <code>wp-config.php</code> file. It is usually <strong>wp_</strong>.' ),
816
- 'prerequisite' => 'toggle_2_2'
817
- ),
818
- 'wordpress_mu_primary_blog_id' => array(
819
- 'value' => '',
820
- 'default_value' => '',
821
- 'label' => __( 'WordPress MU primary blog ID' ),
822
- 'note' => __( 'If you are integrating with a WordPress MU site you need to specify the primary blog ID for that site. It is usually <strong>1</strong>. You should probably leave this blank if you are integrating with a standard WordPress site' ),
823
- 'prerequisite' => 'toggle_2_2'
824
- ),
825
- 'toggle_2_3' => array(
826
- 'value' => 0,
827
- 'label' => __( 'Show advanced database settings' ),
828
- 'note' => __( 'If your bbPress and WordPress site do not share the same database, then you will need to add advanced settings.' ),
829
- 'checked' => '',
830
- 'display' => 'none',
831
- 'prerequisite' => 'toggle_2_2'
832
- ),
833
- 'user_bbdb_name' => array(
834
- 'value' => '',
835
- 'label' => __( 'User database name' ),
836
- 'note' => __( 'The name of the database in which your user tables reside.' ),
837
- 'prerequisite' => 'toggle_2_3'
838
- ),
839
- 'user_bbdb_user' => array(
840
- 'value' => '',
841
- 'label' => __( 'User database user' ),
842
- 'note' => __( 'The database user that has access to that database.' ),
843
- 'prerequisite' => 'toggle_2_3',
844
- 'autocomplete' => 'off'
845
- ),
846
- 'user_bbdb_password' => array(
847
- 'type' => 'password',
848
- 'value' => '',
849
- 'label' => __( 'User database password' ),
850
- 'note' => __( 'That database user\'s password.' ),
851
- 'prerequisite' => 'toggle_2_3',
852
- 'autocomplete' => 'off'
853
- ),
854
- 'user_bbdb_host' => array(
855
- 'value' => '',
856
- 'label' => __( 'User database host' ),
857
- 'note' => __( 'The domain name or IP address of the server where the database is located. If the database is on the same server as the web site, then this probably should be <strong>localhost</strong>.' ),
858
- 'prerequisite' => 'toggle_2_3'
859
- ),
860
- 'user_bbdb_charset' => array(
861
- 'value' => '',
862
- 'label' => __( 'User database character set' ),
863
- 'note' => __( 'The best choice is <strong>utf8</strong>, but you will need to match the character set which you created the database with.' ),
864
- 'prerequisite' => 'toggle_2_3'
865
- ),
866
- 'user_bbdb_collate' => array(
867
- 'value' => '',
868
- 'label' => __( 'User database character collation' ),
869
- 'note' => __( 'The character collation value set when the user database was created.' ),
870
- 'prerequisite' => 'toggle_2_3'
871
- ),
872
- 'custom_user_table' => array(
873
- 'value' => '',
874
- 'label' => __( 'User database "user" table' ),
875
- 'note' => __( 'The complete table name, including any prefix.' ),
876
- 'prerequisite' => 'toggle_2_3'
877
- ),
878
- 'custom_user_meta_table' => array(
879
- 'value' => '',
880
- 'label' => __( 'User database "user meta" table' ),
881
- 'note' => __( 'The complete table name, including any prefix.' ),
882
- 'prerequisite' => 'toggle_2_3'
883
- ),
884
- 'forward_2_0' => array(
885
- 'value' => __( 'Skip WordPress integration' )
886
- ),
887
- 'back_2_1' => array(
888
- 'value' => __( '&laquo; Go back' )
889
- ),
890
- 'forward_2_1' => array(
891
- 'value' => __( 'Go to step 3' )
892
- )
893
- )
894
- ),
895
-
896
- 3 => array(
897
- 'form' => array(
898
- 'name' => array(
899
- 'value' => '',
900
- 'label' => __( 'Site name' ),
901
- 'note' => __( 'This is what you are going to call your bbPress site.' )
902
- ),
903
- 'uri' => array(
904
- 'value' => $this->guess_uri(),
905
- 'label' => __( 'Site address (URL)' ),
906
- 'note' => __( 'We have attempted to guess this; it\'s usually correct, but change it here if you wish.' )
907
- ),
908
- 'keymaster_user_login' => array(
909
- 'value' => '',
910
- 'maxlength' => 60,
911
- 'label' => __( '"Key Master" Username' ),
912
- 'note' => __( 'This is the user login for the initial bbPress administrator (known as a "Key Master").' ),
913
- 'autocomplete' => 'off'
914
- ),
915
- 'keymaster_user_email' => array(
916
- 'value' => '',
917
- 'maxlength' => 100,
918
- 'label' => __( '"Key Master" Email address' ),
919
- 'note' => __( 'The login details will be emailed to this address.' ),
920
- 'autocomplete' => 'off'
921
- ),
922
- 'keymaster_user_type' => array(
923
- 'value' => 'new'
924
- ),
925
- 'forum_name' => array(
926
- 'value' => '',
927
- 'maxlength' => 150,
928
- 'label' => __( 'First forum name' ),
929
- 'note' => __( 'This can be changed after installation, so don\'t worry about it too much.' )
930
- ),
931
- 'forward_3_0' => array(
932
- 'value' => __( 'Save site settings' )
933
- ),
934
- 'back_3_1' => array(
935
- 'value' => __( '&laquo; Go back' )
936
- ),
937
- 'forward_3_1' => array(
938
- 'value' => __( 'Complete the installation' )
939
- )
940
- )
941
- ),
942
-
943
- 4 => array(
944
- 'form' => array(
945
- 'toggle_4' => array(
946
- 'value' => 0,
947
- 'label' => __( 'Show installation messages' )
948
- ),
949
- 'error_log' => array(
950
- 'value' => '',
951
- 'label' => __( 'Installation errors' )
952
- ),
953
- 'installation_log' => array(
954
- 'value' => '',
955
- 'label' => __( 'Installation log' )
956
- )
957
- )
958
- )
959
- );
960
- }
961
-
962
- /**
963
- * Guesses the final installed URI based on the location of the install script
964
- *
965
- * @return string The guessed URI
966
- */
967
- function guess_uri()
968
- {
969
- global $bb;
970
-
971
- if ( $bb->uri ) {
972
- $uri = $bb->uri;
973
- } else {
974
- $schema = 'http://';
975
- if ( isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on' ) {
976
- $schema = 'https://';
977
- }
978
- $uri = preg_replace( '|/bb-admin/.*|i', '/', $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
979
- }
980
-
981
- return rtrim( $uri, " \t\n\r\0\x0B/" ) . '/';
982
- }
983
-
984
- /**
985
- * Writes the given alterations to file
986
- *
987
- * @param $file_source string The full path to the file to be read from
988
- * @param $file_target string The full path to the file to be written to
989
- * @param $alterations array An array of arrays containing alterations to be made
990
- * @return void
991
- */
992
- function write_lines_to_file( $file_source, $file_target, $alterations )
993
- {
994
- if ( !$file_source || !file_exists( $file_source ) || !is_file( $file_source ) ) {
995
- return -1;
996
- }
997
-
998
- if ( !$file_target ) {
999
- $file_target = $file_source;
1000
- }
1001
-
1002
- if ( !$alterations || !is_array( $alterations ) ) {
1003
- return -2;
1004
- }
1005
-
1006
- /*
1007
- Alterations array takes the form
1008
- array(
1009
- '1st 20 chars of line' => array( 'Search string', 'Replacement string' ),
1010
- '1st 20 chars of line' => array( 'Search string', 'Replacement string' )
1011
- );
1012
- */
1013
-
1014
- // Get the existing lines in the file
1015
- $lines = file( $file_source );
1016
-
1017
- // Initialise an array to store the modified lines
1018
- $modified_lines = array();
1019
-
1020
- // Loop through the lines and modify them
1021
- foreach ( $lines as $line ) {
1022
- if ( isset( $alterations[substr( $line, 0, 20 )] ) ) {
1023
- $alteration = $alterations[substr( $line, 0, 20 )];
1024
- $modified_lines[] = str_replace( $alteration[0], $alteration[1], $line );
1025
- } else {
1026
- $modified_lines[] = $line;
1027
- }
1028
- }
1029
-
1030
- $writable = true;
1031
- if ( file_exists( $file_target ) ) {
1032
- if ( !is_writable( $file_target ) ) {
1033
- $writable = false;
1034
- }
1035
- } else {
1036
- $dir_target = dirname( $file_target );
1037
- if ( file_exists( $dir_target ) ) {
1038
- if ( !is_writable( $dir_target ) || !is_dir( $dir_target ) ) {
1039
- $writable = false;
1040
- }
1041
- } else {
1042
- $writable = false;
1043
- }
1044
- }
1045
-
1046
- if ( !$writable ) {
1047
- return trim( join( null, $modified_lines ) );
1048
- }
1049
-
1050
- // Open the file for writing - rewrites the whole file
1051
- $file_handle = fopen( $file_target, 'w' );
1052
-
1053
- // Write lines one by one to avoid OS specific newline hassles
1054
- foreach ( $modified_lines as $modified_line ) {
1055
- if ( false !== strpos( $modified_line, '?>' ) ) {
1056
- $modified_line = '?>';
1057
- }
1058
- fwrite( $file_handle, $modified_line );
1059
- if ( $modified_line == '?>' ) {
1060
- break;
1061
- }
1062
- }
1063
-
1064
- // Close the config file
1065
- fclose( $file_handle );
1066
-
1067
- @chmod( $file_target, 0666 );
1068
-
1069
- return 1;
1070
- }
1071
-
1072
- /**
1073
- * Reports whether the request method is post or not
1074
- *
1075
- * @return boolean True if the page was posted, otherwise false
1076
- */
1077
- function is_posted()
1078
- {
1079
- if ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
1080
- return true;
1081
- }
1082
- return false;
1083
- }
1084
-
1085
- /**
1086
- * Determines which step the installer is on based on user input
1087
- *
1088
- * @return boolean Always returns true
1089
- **/
1090
- function set_step()
1091
- {
1092
- if ( $this->is_posted() ) {
1093
- switch ( $this->step ) {
1094
- case 1:
1095
- $this->set_language();
1096
- if ( $_POST['forward_0_0'] ) {
1097
- $this->stop_process = 1;
1098
- }
1099
- break;
1100
-
1101
- case 2:
1102
- if ( $_POST['forward_1_2'] ) {
1103
- $this->stop_process = 1;
1104
- }
1105
- break;
1106
-
1107
- case 3:
1108
- // If this is actually a request to go back to step 2
1109
- if ( $_POST['back_2_1'] ) {
1110
- $this->step = 2;
1111
- break;
1112
- }
1113
-
1114
- // If we have come forward from step 2 then don't process form 3
1115
- if ( $_POST['forward_2_1'] ) {
1116
- $this->stop_process = true;
1117
- }
1118
-
1119
- // Determine what the status of the previous step was based on input
1120
- if ( $_POST['toggle_2_0'] ) {
1121
- $this->strings[2]['status'] = __( '&laquo; completed' );
1122
- $this->step_status[2] = 'complete';
1123
- }
1124
- break;
1125
-
1126
- case 4:
1127
- // Determine what the status of the previous step was based on input
1128
- if ( $_POST['toggle_2_0'] ) {
1129
- $this->strings[2]['status'] = __( '&laquo; completed' );
1130
- $this->step_status[2] = 'complete';
1131
- }
1132
-
1133
- // If this is actually a request to go back to step 3
1134
- if ( $_POST['back_3_1'] ) {
1135
- $this->step = 3;
1136
- break;
1137
- }
1138
-
1139
- // We have to have come forward from step 3
1140
- if ( $_POST['forward_3_1'] ) {
1141
- $this->strings[3]['status'] = __( '&laquo; completed' );
1142
- $this->step_status[3] = 'complete';
1143
- } else {
1144
- $this->step = 2;
1145
- }
1146
- break;
1147
- }
1148
- }
1149
- return true;
1150
- }
1151
-
1152
- /**
1153
- * Sanitizes all data stored in the data array
1154
- *
1155
- * @return boolean Always returns true
1156
- **/
1157
- function sanitize_form_data()
1158
- {
1159
- foreach ( $this->data as $step => $data ) {
1160
- if ( isset( $data['form'] ) && is_array( $data['form'] ) ) {
1161
- foreach ( $data['form'] as $key => $value ) {
1162
- $this->data[$step]['form'][$key]['value'] = esc_attr( $value['value'] );
1163
- }
1164
- }
1165
- }
1166
- return true;
1167
- }
1168
-
1169
- /**
1170
- * Directs processing of the form data based on the current step
1171
- *
1172
- * @return boolean Always returns true
1173
- **/
1174
- function process_form()
1175
- {
1176
- if ( $this->is_posted() && !$this->stop_process ) {
1177
- switch ( $this->step ) {
1178
- case 1:
1179
- $this->process_form_config_file();
1180
- break;
1181
-
1182
- case 2:
1183
- $this->process_form_wordpress_integration();
1184
- break;
1185
-
1186
- case 3:
1187
- $this->process_form_site_options();
1188
- break;
1189
-
1190
- case 4:
1191
- $this->process_form_finalise_installation();
1192
- break;
1193
- }
1194
- }
1195
- return true;
1196
- }
1197
-
1198
- /**
1199
- * Takes inputted form data and injects it into the data array
1200
- *
1201
- * @param integer $step Which steps data to process
1202
- * @return boolean Always returns true
1203
- **/
1204
- function inject_form_values_into_data( $step )
1205
- {
1206
- $data =& $this->data[$step]['form'];
1207
-
1208
- foreach ( $data as $key => $value ) {
1209
- if ( 'forward_' !== substr( $key, 0, 8 ) && 'back_' !== substr( $key, 0, 5 ) ) {
1210
- if ( isset( $data[$key]['prerequisite'] ) && !$_POST[$data[$key]['prerequisite']] ) {
1211
- if ( isset( $data[$key]['default_value'] ) ) {
1212
- $data[$key]['value'] = $data[$key]['default_value'];
1213
- }
1214
- // do nothing - keep the default value
1215
- } else {
1216
- $data[$key]['value'] = stripslashes_deep( trim( $_POST[$key] ) );
1217
- }
1218
- }
1219
- }
1220
-
1221
- return true;
1222
- }
1223
-
1224
- /**
1225
- * Validates the supplied config file data and writes it to the config file.
1226
- *
1227
- * @return void
1228
- **/
1229
- function process_form_config_file()
1230
- {
1231
- $this->inject_form_values_into_data( 1 );
1232
-
1233
- $data =& $this->data[1]['form'];
1234
-
1235
- if ( 'en_US' == $data['bb_lang']['value'] ) {
1236
- $data['bb_lang']['value'] = '';
1237
- }
1238
-
1239
- if ( $data['toggle_1']['value'] ) {
1240
- $data['toggle_1']['checked'] = 'checked="checked"';
1241
- $data['toggle_1']['display'] = 'block';
1242
-
1243
- // Deal with slashes in the keys
1244
- //$data['bb_auth_key']['value'] = addslashes( stripslashes( $data['bb_auth_key']['value'] ) );
1245
- //$data['bb_secure_auth_key']['value'] = addslashes( stripslashes( $data['bb_secure_auth_key']['value'] ) );
1246
- //$data['bb_logged_in_key']['value'] = addslashes( stripslashes( $data['bb_logged_in_key']['value'] ) );
1247
- //$data['bb_nonce_key']['value'] = addslashes( stripslashes( $data['bb_nonce_key']['value'] ) );
1248
- }
1249
-
1250
- $requested_prefix = $data['bb_table_prefix']['value'];
1251
- $data['bb_table_prefix']['value'] = preg_replace( '/[^0-9a-zA-Z_]/', '', $data['bb_table_prefix']['value'] );
1252
- if ( $requested_prefix !== $data['bb_table_prefix']['value'] ) {
1253
- $data['toggle_1']['checked'] = 'checked="checked"';
1254
- $data['toggle_1']['display'] = 'block';
1255
- $this->step_status[1] = 'incomplete';
1256
- $this->strings[1]['messages']['error'][] = __( 'The table prefix can only contain letters, numbers and underscores.<br />Please review the suggestion below.' );
1257
- $this->strings[1]['form_errors']['bb_table_prefix'][] = __( '&bull; Based on your input the following prefix is suggested.' );
1258
- return 'incomplete';
1259
- }
1260
- if ( empty( $data['bb_table_prefix']['value'] ) ) {
1261
- $data['bb_table_prefix']['value'] = 'bb_';
1262
- $data['toggle_1']['checked'] = 'checked="checked"';
1263
- $data['toggle_1']['display'] = 'block';
1264
- $this->step_status[1] = 'incomplete';
1265
- $this->strings[1]['messages']['error'][] = __( 'The table prefix can not be blank.<br />Please review the suggestion below.' );
1266
- $this->strings[1]['form_errors']['bb_table_prefix'][] = __( '&bull; The default prefix has been inserted.' );
1267
- return 'incomplete';
1268
- }
1269
-
1270
- // Stop here if we are going backwards
1271
- if ( $_POST['back_1_1'] ) {
1272
- $this->step_status[1] = 'incomplete';
1273
- return 'incomplete';
1274
- }
1275
-
1276
- // Test the db connection.
1277
- define( 'BBDB_NAME', $data['bbdb_name']['value'] );
1278
- define( 'BBDB_USER', $data['bbdb_user']['value'] );
1279
- define( 'BBDB_PASSWORD', $data['bbdb_password']['value'] );
1280
- define( 'BBDB_HOST', $data['bbdb_host']['value'] );
1281
- define( 'BBDB_CHARSET', $data['bbdb_charset']['value'] );
1282
- define( 'BBDB_COLLATE', $data['bbdb_collate']['value'] );
1283
-
1284
- // We'll fail here if the values are no good.
1285
- require_once( BACKPRESS_PATH . 'class.bpdb-multi.php' );
1286
-
1287
- $bbdb = new BPDB_Multi( array(
1288
- 'name' => BBDB_NAME,
1289
- 'user' => BBDB_USER,
1290
- 'password' => BBDB_PASSWORD,
1291
- 'host' => BBDB_HOST,
1292
- 'charset' => defined( 'BBDB_CHARSET' ) ? BBDB_CHARSET : false,
1293
- 'collate' => defined( 'BBDB_COLLATE' ) ? BBDB_COLLATE : false,
1294
- 'errors' => 'suppress'
1295
- ) );
1296
-
1297
- if ( !$bbdb->db_connect( 'SHOW TABLES;' ) ) {
1298
- $bbdb->suppress_errors( false );
1299
- $this->step_status[1] = 'incomplete';
1300
- $this->strings[1]['messages']['error'][] = __( 'There was a problem connecting to the database you specified.<br />Please check the settings, then try again.' );
1301
- return 'error';
1302
- }
1303
- $bbdb->suppress_errors( false );
1304
-
1305
- $config_result = $this->write_lines_to_file(
1306
- BB_PATH . 'bb-config-sample.php',
1307
- BB_PATH . 'bb-config.php',
1308
- array(
1309
- "define( 'BBDB_NAME'," => array( "'bbpress'", "'" . $data['bbdb_name']['value'] . "'" ),
1310
- "define( 'BBDB_USER'," => array( "'username'", "'" . $data['bbdb_user']['value'] . "'" ),
1311
- "define( 'BBDB_PASSWO" => array( "'password'", "'" . $data['bbdb_password']['value'] . "'" ),
1312
- "define( 'BBDB_HOST'," => array( "'localhost'", "'" . $data['bbdb_host']['value'] . "'" ),
1313
- "define( 'BBDB_CHARSE" => array( "'utf8'", "'" . $data['bbdb_charset']['value'] . "'" ),
1314
- "define( 'BBDB_COLLAT" => array( "''", "'" . $data['bbdb_collate']['value'] . "'" ),
1315
- //"define( 'BB_AUTH_KEY" => array( "'put your unique phrase here'", "'" . $data['bb_auth_key']['value'] . "'" ),
1316
- //"define( 'BB_SECURE_A" => array( "'put your unique phrase here'", "'" . $data['bb_secure_auth_key']['value'] . "'" ),
1317
- //"define( 'BB_LOGGED_I" => array( "'put your unique phrase here'", "'" . $data['bb_logged_in_key']['value'] . "'" ),
1318
- //"define( 'BB_NONCE_KE" => array( "'put your unique phrase here'", "'" . $data['bb_nonce_key']['value'] . "'" ),
1319
- "\$bb_table_prefix = '" => array( "'bb_'", "'" . $data['bb_table_prefix']['value'] . "'" ),
1320
- "define( 'BB_LANG', '" => array( "''", "'" . $data['bb_lang']['value'] . "'" )
1321
- )
1322
- );
1323
-
1324
- switch ( $config_result ) {
1325
- case -1:
1326
- $this->step_status[1] = 'error';
1327
- $this->strings[1]['messages']['error'][] = __( 'I could not find the file <code>bb-config-sample.php</code><br />Please upload it to the root directory of your bbPress installation.' );
1328
- return 'error';
1329
- break;
1330
- case 1:
1331
- $this->configs['bb-config.php'] = BB_PATH . 'bb-config.php';
1332
- $this->step_status[1] = 'complete';
1333
- $this->strings[1]['messages']['message'][] = __( 'Your settings have been saved to the file <code>bb-config.php</code><br />You can now continue to the next step.' );
1334
- break;
1335
- default:
1336
- // Just write the contents to screen
1337
- $this->data[1]['form']['config']['value'] = $config_result;
1338
-
1339
- $this->step_status[1] = 'manual';
1340
- $this->strings[1]['messages']['error'][] = __( 'Your settings could not be saved to a configuration file. You will need to save the text shown below into a file named <code>bb-config.php</code> in the root directory of your bbPress installation before you can continue.' );
1341
- break;
1342
- }
1343
- }
1344
-
1345
- /**
1346
- * Validates the WordPress integration settings
1347
- *
1348
- * @return void
1349
- **/
1350
- function process_form_wordpress_integration()
1351
- {
1352
- // Check the referer
1353
- bb_check_admin_referer( 'bbpress-installer' );
1354
-
1355
- $this->inject_form_values_into_data( 2 );
1356
-
1357
- $data =& $this->data[2]['form'];
1358
-
1359
- // If there are no settings then goto step 3
1360
- if ( !$data['toggle_2_0']['value'] && !$_POST['back_2_1'] ) {
1361
- $this->step_status[2] = 'complete';
1362
- $this->strings[2]['messages']['message'][] = __( 'You have chosen to skip the WordPress integration step. You can always integrate WordPress later from within the admin area of bbPress.' );
1363
- return 'complete';
1364
- }
1365
-
1366
- // If integration is selected
1367
- if ( $data['toggle_2_0']['value'] ) {
1368
- $data['toggle_2_0']['checked'] = 'checked="checked"';
1369
- $data['toggle_2_0']['display'] = 'block';
1370
- $data['forward_2_0']['value'] = $data['toggle_2_0']['toggle_value']['on_value'];
1371
-
1372
- if ( $data['toggle_2_1']['value'] ) {
1373
- $data['toggle_2_1']['checked'] = 'checked="checked"';
1374
- $data['toggle_2_1']['display'] = 'block';
1375
-
1376
- // Check the wp_siteurl URL for errors
1377
- $data['wp_siteurl']['value'] = $data['wp_siteurl']['value'] ? rtrim( $data['wp_siteurl']['value'], " \t\n\r\0\x0B/" ) . '/' : '';
1378
- $this->strings[2]['form_errors']['wp_siteurl'][] = empty( $data['wp_siteurl']['value'] ) ? 'empty' : false;
1379
- if ( $parsed = parse_url( $data['wp_siteurl']['value'] ) ) {
1380
- $this->strings[2]['form_errors']['wp_siteurl'][] = preg_match( '/https?/i', $parsed['scheme'] ) ? false : 'urlscheme';
1381
- $this->strings[2]['form_errors']['wp_siteurl'][] = empty( $parsed['host'] ) ? 'urlhost' : false;
1382
- } else {
1383
- $this->strings[2]['form_errors']['wp_siteurl'][] = 'urlparse';
1384
- }
1385
-
1386
- // Check the wp_home URL for errors
1387
- $data['wp_home']['value'] = $data['wp_home']['value'] ? rtrim( $data['wp_home']['value'], " \t\n\r\0\x0B/" ) . '/' : '';
1388
- $this->strings[2]['form_errors']['wp_home'][] = empty( $data['wp_home']['value'] ) ? 'empty' : false;
1389
- if ( $parsed = parse_url( $data['wp_home']['value'] ) ) {
1390
- $this->strings[2]['form_errors']['wp_home'][] = preg_match( '/https?/i', $parsed['scheme'] ) ? false : 'urlscheme';
1391
- $this->strings[2]['form_errors']['wp_home'][] = empty( $parsed['host'] ) ? 'urlhost' : false;
1392
- } else {
1393
- $this->strings[2]['form_errors']['wp_home'][] = 'urlparse';
1394
- }
1395
-
1396
- // Deal with slashes in the keys
1397
- $data['wp_auth_key']['value'] = addslashes( stripslashes( $data['wp_auth_key']['value'] ) );
1398
- $data['wp_auth_salt']['value'] = addslashes( stripslashes( $data['wp_auth_salt']['value'] ) );
1399
- $data['wp_secure_auth_key']['value'] = addslashes( stripslashes( $data['wp_secure_auth_key']['value'] ) );
1400
- $data['wp_secure_auth_salt']['value'] = addslashes( stripslashes( $data['wp_secure_auth_salt']['value'] ) );
1401
- $data['wp_logged_in_key']['value'] = addslashes( stripslashes( $data['wp_logged_in_key']['value'] ) );
1402
- $data['wp_logged_in_salt']['value'] = addslashes( stripslashes( $data['wp_logged_in_salt']['value'] ) );
1403
-
1404
- // Check the keys for errors
1405
- $this->strings[2]['form_errors']['wp_auth_key'][] = empty( $data['wp_auth_key']['value'] ) ? 'empty' : false;
1406
- $this->strings[2]['form_errors']['wp_secure_auth_key'][] = empty( $data['wp_secure_auth_key']['value'] ) ? 'empty' : false;
1407
- $this->strings[2]['form_errors']['wp_logged_in_key'][] = empty( $data['wp_logged_in_key']['value'] ) ? 'empty' : false;
1408
-
1409
- // Salts can be taken from the database if specified
1410
- if ( !$data['toggle_2_2']['value'] ) {
1411
- $this->strings[2]['form_errors']['wp_auth_salt'][] = empty( $data['wp_auth_salt']['value'] ) ? 'empty' : false;
1412
- // NB; secure_auth_salt is not always set in WordPress
1413
- $this->strings[2]['form_errors']['wp_logged_in_salt'][] = empty( $data['wp_logged_in_salt']['value'] ) ? 'empty' : false;
1414
- }
1415
- }
1416
-
1417
- // If database integration is selected
1418
- if ( $data['toggle_2_2']['value'] ) {
1419
- $data['toggle_2_2']['checked'] = 'checked="checked"';
1420
- $data['toggle_2_2']['display'] = 'block';
1421
-
1422
- // Make the wp_table_prefix valid
1423
- $data['wp_table_prefix']['value'] = preg_replace( '/[^0-9a-zA-Z_]/', '', $data['wp_table_prefix']['value'] );
1424
- $data['wp_table_prefix']['value'] = empty( $data['wp_table_prefix']['value'] ) ? 'wp_' : $data['wp_table_prefix']['value'];
1425
-
1426
- // Make the wordpress_mu_primary_blog_id valid
1427
- $data['wordpress_mu_primary_blog_id']['value'] = preg_replace( '/[^0-9]/', '', $data['wordpress_mu_primary_blog_id']['value'] );
1428
-
1429
- // If advanced database integration is selected
1430
- if ( $data['toggle_2_3']['value'] ) {
1431
- $data['toggle_2_3']['checked'] = 'checked="checked"';
1432
- $data['toggle_2_3']['display'] = 'block';
1433
- }
1434
- }
1435
-
1436
- if ( !$data['toggle_2_1']['value'] && !$data['toggle_2_2']['value'] ) {
1437
- $this->step_status[2] = 'incomplete';
1438
- $this->strings[2]['messages']['error'][] = __( 'You must enter your settings for integration setup to complete. Choose which integration settings you wish to enter from the options below.' );
1439
- $this->strings[2]['form_errors']['toggle_2_1'][] = true;
1440
- $this->strings[2]['form_errors']['toggle_2_2'][] = true;
1441
- return 'incomplete';
1442
- }
1443
-
1444
- // Remove empty values from the error array
1445
- foreach ( $this->strings[2]['form_errors'] as $input => $types) {
1446
- $types = array_filter( $types);
1447
- if ( !count( $types ) ) {
1448
- unset( $this->strings[2]['form_errors'][$input] );
1449
- }
1450
- }
1451
-
1452
- // Check for errors and build error messages
1453
- if ( count( $this->strings[2]['form_errors'] ) ) {
1454
-
1455
- $this->step_status[2] = 'incomplete';
1456
- $this->strings[2]['messages']['error'][] = __( 'Your integration settings have not been processed due to errors with the items marked below.' );
1457
-
1458
- foreach ( $this->strings[2]['form_errors'] as $input => $types ) {
1459
- $errors = array();
1460
-
1461
- foreach ( $types as $type ) {
1462
- switch ( $type ) {
1463
- case 'empty':
1464
- // Only return this error when empty
1465
- $errors = array( __( '&bull; This value is required to continue.' ) );
1466
- break(2);
1467
- case 'urlparse':
1468
- $errors[] = __( '&bull; This does not appear to be a valid URL.' );
1469
- break;
1470
- case 'urlscheme':
1471
- $errors[] = __( '&bull; The URL must begin with "http" or "https".' );
1472
- break;
1473
- case 'urlhost':
1474
- $errors[] = __( '&bull; The URL does not contain a host name.' );
1475
- break;
1476
- }
1477
- }
1478
-
1479
- $this->strings[2]['form_errors'][$input] = $errors;
1480
- }
1481
-
1482
- return 'incomplete';
1483
- }
1484
-
1485
- // If database integration is selected
1486
- if ( $data['toggle_2_2']['value'] ) {
1487
-
1488
- // Test the db connection.
1489
-
1490
- // Setup variables and constants if available
1491
- global $bb;
1492
- $bb->wp_table_prefix = $data['wp_table_prefix']['value'];
1493
- if ( $data['toggle_2_3']['value'] ) {
1494
- // These may be empty at this particular stage
1495
- if ( !empty( $data['user_bbdb_name']['value'] ) ) {
1496
- $bb->user_bbdb_name = $data['user_bbdb_name']['value'];
1497
- }
1498
- if ( !empty( $data['user_bbdb_user']['value'] ) ) {
1499
- $bb->user_bbdb_user = $data['user_bbdb_user']['value'];
1500
- }
1501
- if ( !empty( $data['user_bbdb_password']['value'] ) ) {
1502
- $bb->user_bbdb_password = $data['user_bbdb_password']['value'];
1503
- }
1504
- if ( !empty( $data['user_bbdb_host']['value'] ) ) {
1505
- $bb->user_bbdb_host = $data['user_bbdb_host']['value'];
1506
- }
1507
- if ( !empty( $data['user_bbdb_charset']['value'] ) ) {
1508
- $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $data['user_bbdb_charset']['value'] );
1509
- }
1510
- if ( !empty( $data['user_bbdb_collate']['value'] ) ) {
1511
- $bb->user_bbdb_collate = preg_replace( '/[^a-z0-9_-]/i', '', $data['user_bbdb_collate']['value'] );
1512
- }
1513
- if ( !empty( $data['custom_user_table']['value'] ) ) {
1514
- $bb->custom_user_table = preg_replace( '/[^a-z0-9_-]/i', '', $data['custom_user_table']['value'] );
1515
- }
1516
- if ( !empty( $data['custom_user_meta_table']['value'] ) ) {
1517
- $bb->custom_user_meta_table = preg_replace( '/[^a-z0-9_-]/i', '', $data['custom_user_meta_table']['value'] );
1518
- }
1519
- }
1520
-
1521
- // Bring in the database object
1522
- global $bbdb;
1523
- global $bb_table_prefix;
1524
-
1525
- // Resolve the custom user tables for bpdb
1526
- bb_set_custom_user_tables();
1527
-
1528
- if ( isset( $bb->custom_databases) && isset( $bb->custom_databases['user'] ) ) {
1529
- $bbdb->add_db_server( 'user', $bb->custom_databases['user'] );
1530
- }
1531
-
1532
- // Add custom tables if required
1533
- if ( isset( $bb->custom_tables['users'] ) || isset( $bb->custom_tables['usermeta'] ) ) {
1534
- $bbdb->tables = array_merge( $bbdb->tables, $bb->custom_tables );
1535
- if ( is_wp_error( $bbdb->set_prefix( $bb_table_prefix ) ) ) {
1536
- die( __( 'Your user table prefix may only contain letters, numbers and underscores.' ) );
1537
- }
1538
- }
1539
-
1540
- // Hide errors for the test
1541
- $bbdb->hide_errors();
1542
-
1543
- $result = $bbdb->query( 'DESCRIBE ' . $bbdb->users . ';' );
1544
- $result_error = $bbdb->get_error();
1545
-
1546
- // Select from the user table (may fail if there are no records in the table)
1547
- if ( !$result && $result_error ) {
1548
- // We couldn't connect to the database at all
1549
-
1550
- // Turn errors back on
1551
- $bbdb->show_errors();
1552
-
1553
- // Set the status
1554
- $this->step_status[2] = 'incomplete';
1555
- if ( !empty( $data['user_bbdb_name']['value'] ) ) {
1556
- $this->strings[2]['form_errors']['user_bbdb_name'][] = true;
1557
- }
1558
- if ( !empty( $data['user_bbdb_user']['value'] ) ) {
1559
- $this->strings[2]['form_errors']['user_bbdb_user'][] = true;
1560
- }
1561
- if ( !empty( $data['user_bbdb_password']['value'] ) ) {
1562
- $this->strings[2]['form_errors']['user_bbdb_password'][] = true;
1563
- }
1564
- if ( !empty( $data['user_bbdb_host']['value'] ) ) {
1565
- $this->strings[2]['form_errors']['user_bbdb_host'][] = true;
1566
- }
1567
- if ( !empty( $data['custom_user_table']['value'] ) ) {
1568
- $this->strings[2]['form_errors']['custom_user_table'][] = true;
1569
- }
1570
- if ( !empty( $data['custom_user_meta_table']['value'] ) ) {
1571
- $this->strings[2]['form_errors']['custom_user_meta_table'][] = true;
1572
- }
1573
- $this->strings[2]['messages']['error'][] = __( 'There was a problem connecting to the WordPress user database you specified. Please check the settings, then try again.' );
1574
- return 'incomplete';
1575
- }
1576
-
1577
- if ( $result_error ) {
1578
- // The result is an error, presumably telling us the table doesn't exist
1579
-
1580
- // Turn errors back on
1581
- $bbdb->show_errors();
1582
-
1583
- // Set the status
1584
- $this->step_status[2] = 'incomplete';
1585
-
1586
- if ( $data['toggle_2_3']['value'] ) {
1587
- $this->strings[2]['messages']['error'][] = __( 'Existing WordPress user tables could not be found in the WordPress database you specified.' );
1588
- } else {
1589
- $this->strings[2]['messages']['error'][] = __( 'Existing WordPress user tables could not be found in the bbPress database you specified in step 1.<br /><br />This is probably because the database does not already contain working WordPress tables. You may need to specify advanced database settings or leave integration until after installation.' );
1590
- }
1591
- $this->strings[2]['form_errors']['wp_table_prefix'][] = __( '&bull; This may not be a valid user table prefix.' );
1592
- return 'incomplete';
1593
- }
1594
-
1595
- // Turn errors back on
1596
- $bbdb->show_errors();
1597
- }
1598
- }
1599
-
1600
- // Stop here if we are going backwards
1601
- if ( $_POST['back_2_1'] ) {
1602
- $this->step_status[2] = 'incomplete';
1603
- return 'incomplete';
1604
- }
1605
-
1606
- // If we make it this may we are complete, so set the status to complete
1607
- $this->step_status[2] = 'complete';
1608
- $this->strings[2]['messages']['message'][] = __( 'Your WordPress integration cookie and database settings have been successfully validated. They will be saved after the next step.<br /><br />Once you have finished installing, you should visit the WordPress integration section of the bbPress admin area for further options and integration instructions, including user mapping and the correct cookie settings to add to your WordPress configuration file.' );
1609
- return 'complete';
1610
- }
1611
-
1612
- /**
1613
- * Validates the site options.
1614
- *
1615
- * @return void
1616
- **/
1617
- function process_form_site_options()
1618
- {
1619
- // Check the referer
1620
- bb_check_admin_referer( 'bbpress-installer' );
1621
-
1622
- $this->inject_form_values_into_data( 2 );
1623
- $this->inject_form_values_into_data( 3 );
1624
-
1625
- $data =& $this->data[3]['form'];
1626
-
1627
- $this->strings[3]['form_errors']['name'][] = empty( $data['name']['value'] ) ? 'empty' : false;
1628
-
1629
- $data['uri']['value'] = $data['uri']['value'] ? rtrim( $data['uri']['value'], " \t\n\r\0\x0B/" ) . '/' : '';
1630
- $this->strings[3]['form_errors']['uri'][] = empty( $data['uri']['value'] ) ? 'empty' : false;
1631
- if ( $parsed = parse_url( $data['uri']['value'] ) ) {
1632
- $this->strings[3]['form_errors']['uri'][] = preg_match( '/https?/i', $parsed['scheme'] ) ? false : 'urlscheme';
1633
- $this->strings[3]['form_errors']['uri'][] = empty( $parsed['host'] ) ? 'urlhost' : false;
1634
- } else {
1635
- $this->strings[3]['form_errors']['uri'][] = 'urlparse';
1636
- }
1637
-
1638
- $this->strings[3]['form_errors']['keymaster_user_login'][] = empty( $data['keymaster_user_login']['value'] ) ? 'empty' : false;
1639
- if ( $data['keymaster_user_login']['value'] != sanitize_user( $data['keymaster_user_login']['value'], true ) ) {
1640
- $this->strings[3]['form_errors']['keymaster_user_login'][] = 'userlogin';
1641
- }
1642
- $data['keymaster_user_login']['value'] = sanitize_user( $data['keymaster_user_login']['value'], true );
1643
-
1644
- // Check for a valid email
1645
- $this->strings[3]['form_errors']['keymaster_user_email'][] = empty( $data['keymaster_user_email']['value'] ) ? 'empty' : false;
1646
- $this->strings[3]['form_errors']['keymaster_user_email'][] = !is_email( $data['keymaster_user_email']['value'] ) ? 'email' : false;
1647
-
1648
- // Check for a forum name
1649
- if ( !$this->database_tables_are_installed() ) {
1650
- $this->strings[3]['form_errors']['forum_name'][] = empty( $data['forum_name']['value'] ) ? 'empty' : false;
1651
- }
1652
-
1653
- // Remove empty values from the error array
1654
- foreach ( $this->strings[3]['form_errors'] as $input => $types ) {
1655
- $types = array_filter( $types );
1656
- if ( !count( $types ) ) {
1657
- unset( $this->strings[3]['form_errors'][$input] );
1658
- }
1659
- }
1660
-
1661
- // Check for errors and build error messages
1662
- if ( count( $this->strings[3]['form_errors'] ) ) {
1663
-
1664
- $this->step_status[3] = 'incomplete';
1665
- $this->strings[3]['messages']['error'][] = __( 'Your site settings have not been processed due to errors with the items marked below.' );
1666
-
1667
- foreach ( $this->strings[3]['form_errors'] as $input => $types ) {
1668
- $errors = array();
1669
-
1670
- foreach ( $types as $type ) {
1671
- switch ( $type ) {
1672
- case 'empty':
1673
- // Only return this error when empty
1674
- $errors = array( __( '&bull; This value is required to continue.' ) );
1675
- break(2);
1676
- case 'urlparse':
1677
- $errors[] = __( '&bull; This does not appear to be a valid URL.' );
1678
- break;
1679
- case 'urlscheme':
1680
- $errors[] = __( '&bull; The URL must begin with "http" or "https".' );
1681
- break;
1682
- case 'urlhost':
1683
- $errors[] = __( '&bull; The URL does not contain a host name.' );
1684
- break;
1685
- case 'userlogin':
1686
- $errors[] = __( '&bull; Contains disallowed characters which have been removed.' );
1687
- break;
1688
- case 'email':
1689
- $errors[] = __( '&bull; The user email address appears to be invalid.' );
1690
- break;
1691
- }
1692
- }
1693
-
1694
- $this->strings[3]['form_errors'][$input] = $errors;
1695
- }
1696
-
1697
- return 'incomplete';
1698
- }
1699
-
1700
- // Stop here if we are going backwards
1701
- if ( $_POST['back_3_1'] ) {
1702
- $this->step_status[3] = 'incomplete';
1703
- return 'incomplete';
1704
- }
1705
-
1706
- // If we make it this far we are good to go
1707
- $this->step_status[3] = 'complete';
1708
- $this->strings[3]['messages']['message'][] = __( 'Your site settings have been saved and we are now ready to complete the installation. So what are you waiting for?' );
1709
- return 'complete';
1710
- }
1711
-
1712
- /**
1713
- * Finalises the installation by creating the database and writing all the supplied data to the database.
1714
- *
1715
- * @return void
1716
- **/
1717
- function process_form_finalise_installation()
1718
- {
1719
- require_once( BB_PATH . 'bb-admin/includes/functions.bb-upgrade.php' );
1720
- require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
1721
-
1722
- $this->inject_form_values_into_data( 2 );
1723
- $this->inject_form_values_into_data( 3 );
1724
-
1725
- $data2 =& $this->data[2]['form'];
1726
- $data3 =& $this->data[3]['form'];
1727
- $data4 =& $this->data[4]['form'];
1728
-
1729
- $error_log = array();
1730
- $installation_log = array();
1731
-
1732
- // Check the referer
1733
- bb_check_admin_referer( 'bbpress-installer' );
1734
- $installation_log[] = __( 'Referrer is OK, beginning installation&hellip;' );
1735
-
1736
- global $bbdb;
1737
-
1738
- // Setup user table variables and constants if available
1739
- if ( $data2['toggle_2_2']['value'] ) {
1740
-
1741
- $installation_log[] = '>>> ' . __( 'Setting up custom user table constants' );
1742
-
1743
- global $bb;
1744
- global $bb_table_prefix;
1745
-
1746
- if ( !empty( $data2['wp_table_prefix']['value'] ) ) {
1747
- $bb->wp_table_prefix = $data2['wp_table_prefix']['value'];
1748
- }
1749
- if ( !empty( $data2['user_bbdb_name']['value'] ) ) {
1750
- $bb->user_bbdb_name = $data2['user_bbdb_name']['value'];
1751
- }
1752
- if ( !empty( $data2['user_bbdb_user']['value'] ) ) {
1753
- $bb->user_bbdb_user = $data2['user_bbdb_user']['value'];
1754
- }
1755
- if ( !empty( $data2['user_bbdb_password']['value'] ) ) {
1756
- $bb->user_bbdb_password = $data2['user_bbdb_password']['value'];
1757
- }
1758
- if ( !empty( $data2['user_bbdb_host']['value'] ) ) {
1759
- $bb->user_bbdb_host = $data2['user_bbdb_host']['value'];
1760
- }
1761
- if ( !empty( $data2['user_bbdb_charset']['value'] ) ) {
1762
- $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $data2['user_bbdb_charset']['value'] );
1763
- }
1764
- if ( !empty( $data2['user_bbdb_collate']['value'] ) ) {
1765
- $bb->user_bbdb_collate = preg_replace( '/[^a-z0-9_-]/i', '', $data2['user_bbdb_collate']['value'] );
1766
- }
1767
-
1768
- bb_set_custom_user_tables();
1769
-
1770
- // Add custom user database if required
1771
- if ( isset( $bb->custom_databases['user'] ) ) {
1772
- $bbdb->add_db_server( 'user', $bb->custom_databases['user'] );
1773
- }
1774
-
1775
- // Add custom tables if required
1776
- if ( isset( $bb->custom_tables ) ) {
1777
- $bbdb->tables = array_merge( $bbdb->tables, $bb->custom_tables );
1778
- if ( is_wp_error( $bbdb->set_prefix( $bb_table_prefix ) ) )
1779
- die( __( 'Your user table prefix may only contain letters, numbers and underscores.' ) );
1780
- }
1781
- }
1782
-
1783
- // Create the database
1784
- $installation_log[] = "\n" . __( 'Step 1 - Creating database tables' );
1785
-
1786
- if ( !$this->database_tables_are_installed() ) {
1787
- // Hide db errors
1788
- $bbdb->hide_errors();
1789
- // Install the database
1790
- $alterations = bb_install();
1791
- // Show db errors
1792
- $bbdb->show_errors();
1793
-
1794
- if ( isset( $alterations['errors'] ) && is_array( $alterations['errors'] ) ) {
1795
- $error_log = array_merge( $error_log, $alterations['errors'] );
1796
- }
1797
- if ( isset( $alterations['messages'] ) && is_array( $alterations['messages'] ) ) {
1798
- $installation_log = array_merge( $installation_log, $alterations['messages'] );
1799
- }
1800
-
1801
- if ( !$this->database_tables_are_installed() ) {
1802
- $installation_log[] = '>>> ' . __( 'Database installation failed!!!' );
1803
- $installation_log[] = '>>>>>> ' . __( 'Halting installation!' );
1804
- $error_log[] = __( 'Database installation failed!!!' );
1805
-
1806
- $this->step_status[4] = 'incomplete';
1807
- $this->strings[4]['h2'] = __( 'Installation failed!' );
1808
- $this->strings[4]['messages']['error'][] = __( 'The database failed to install. You may need to replace bbPress with a fresh copy and start again.' );
1809
-
1810
- $data4['installation_log']['value'] = join( "\n", $installation_log );
1811
- $data4['error_log']['value'] = join( "\n", $error_log );
1812
-
1813
- return 'incomplete';
1814
- }
1815
- } else {
1816
- $installation_log[] = '>>> ' . __( 'Database is already installed!!!' );
1817
- }
1818
-
1819
- // Integration settings passed from step 2
1820
- // These are already validated provided that the referer checks out
1821
- $installation_log[] = "\n" . __( 'Step 2 - WordPress integration (optional)' );
1822
- if ( $data2['toggle_2_0']['value'] ) {
1823
- if ( $data2['toggle_2_1']['value'] ) {
1824
- bb_update_option( 'wp_siteurl', $data2['wp_siteurl']['value'] );
1825
- $installation_log[] = '>>> ' . __( 'WordPress address (URL):' ) . ' ' . $data2['wp_siteurl']['value'];
1826
-
1827
- bb_update_option( 'wp_home', $data2['wp_home']['value'] );
1828
- $installation_log[] = '>>> ' . __( 'Blog address (URL):' ) . ' ' . $data2['wp_home']['value'];
1829
-
1830
- $config_result = $this->write_lines_to_file(
1831
- BB_PATH . 'bb-config.php',
1832
- false,
1833
- array(
1834
- "define( 'BB_AUTH_KEY" => array( "'" . BB_AUTH_KEY . "'", "'" . $data2['wp_auth_key']['value'] . "'" ),
1835
- "define( 'BB_SECURE_A" => array( "'" . BB_SECURE_AUTH_KEY . "'", "'" . $data2['wp_secure_auth_key']['value'] . "'" ),
1836
- "define( 'BB_LOGGED_I" => array( "'" . BB_LOGGED_IN_KEY . "'", "'" . $data2['wp_logged_in_key']['value'] . "'" ),
1837
- )
1838
- );
1839
-
1840
- switch ( $config_result ) {
1841
- case 1:
1842
- $installation_log[] = '>>> ' . __( 'WordPress cookie keys set.' );
1843
- break;
1844
- default:
1845
- $error_log[] = '>>> ' . __( 'WordPress cookie keys not set.' );
1846
- $error_log[] = '>>>>>> ' . __( 'Your "bb-config.php" file was not writable.' );
1847
- $error_log[] = '>>>>>> ' . __( 'You will need to manually re-define "BB_AUTH_KEY", "BB_SECURE_AUTH_KEY" and "BB_LOGGED_IN_KEY" in your "bb-config.php" file.' );
1848
- $installation_log[] = '>>> ' . __( 'WordPress cookie keys not set.' );
1849
- break;
1850
- }
1851
-
1852
- if ( !empty( $data2['wp_auth_salt']['value'] ) ) {
1853
- bb_update_option( 'bb_auth_salt', $data2['wp_auth_salt']['value'] );
1854
- $installation_log[] = '>>> ' . __( 'WordPress "auth" cookie salt set from input.' );
1855
- }
1856
-
1857
- if ( !empty( $data2['wp_secure_auth_salt']['value'] ) ) {
1858
- bb_update_option( 'bb_secure_auth_salt', $data2['wp_secure_auth_salt']['value'] );
1859
- $installation_log[] = '>>> ' . __( 'WordPress "secure auth" cookie salt set from input.' );
1860
- }
1861
-
1862
- if ( !empty( $data2['wp_logged_in_salt']['value'] ) ) {
1863
- bb_update_option( 'bb_logged_in_salt', $data2['wp_logged_in_salt']['value'] );
1864
- $installation_log[] = '>>> ' . __( 'WordPress "logged in" cookie salt set from input.' );
1865
- }
1866
- }
1867
-
1868
- if ( $data2['toggle_2_2']['value'] ) {
1869
- if (
1870
- !bb_get_option( 'bb_auth_salt' ) ||
1871
- !bb_get_option( 'bb_secure_auth_salt' ) ||
1872
- !bb_get_option( 'bb_logged_in_salt' )
1873
- ) {
1874
- $installation_log[] = '>>> ' . __( 'Fetching missing WordPress cookie salts.' );
1875
-
1876
- $_prefix = $bb->wp_table_prefix;
1877
- if ( !empty( $data2['wordpress_mu_primary_blog_id']['value'] ) ) {
1878
- $_prefix .= $data2['wordpress_mu_primary_blog_id']['value'] . '_';
1879
- }
1880
-
1881
- if ( isset( $bb->custom_databases['user'] ) ) {
1882
- $bbdb->tables['options'] = array( 'user', $_prefix . 'options' );
1883
- } else {
1884
- $bbdb->tables['options'] = $_prefix . 'options';
1885
- }
1886
-
1887
- unset( $_prefix );
1888
-
1889
- $bbdb->set_prefix( $bb_table_prefix );
1890
-
1891
- if ( !bb_get_option( 'bb_auth_salt' ) ) {
1892
- $wp_auth_salt = $bbdb->get_var( "SELECT `option_value` FROM $bbdb->options WHERE `option_name` = 'auth_salt' LIMIT 1" );
1893
- if ( $wp_auth_salt ) {
1894
- bb_update_option( 'bb_auth_salt', $wp_auth_salt );
1895
- $installation_log[] = '>>>>>> ' . __( 'WordPress "auth" cookie salt set.' );
1896
- } else {
1897
- $error_log[] = '>>> ' . __( 'WordPress "auth" cookie salt not set.' );
1898
- $error_log[] = '>>>>>> ' . __( 'Could not fetch "auth" cookie salt from the WordPress options table.' );
1899
- $error_log[] = '>>>>>> ' . __( 'You will need to manually define the "auth" cookie salt in your database.' );
1900
- $installation_log[] = '>>>>>> ' . __( 'WordPress "auth" cookie salt not set.' );
1901
- }
1902
- }
1903
-
1904
- if ( !bb_get_option( 'bb_secure_auth_salt' ) ) {
1905
- $wp_secure_auth_salt = $bbdb->get_var( "SELECT `option_value` FROM $bbdb->options WHERE `option_name` = 'secure_auth_salt' LIMIT 1" );
1906
- if ( $wp_secure_auth_salt ) {
1907
- bb_update_option( 'bb_secure_auth_salt', $wp_secure_auth_salt );
1908
- $installation_log[] = '>>>>>> ' . __( 'WordPress "secure auth" cookie salt set.' );
1909
- } else {
1910
- // This cookie salt is sometimes empty so don't error
1911
- $installation_log[] = '>>>>>> ' . __( 'WordPress "secure auth" cookie salt not set.' );
1912
- }
1913
- }
1914
-
1915
- if ( !bb_get_option( 'bb_logged_in_salt' ) ) {
1916
- $wp_logged_in_salt = $bbdb->get_var( "SELECT `option_value` FROM $bbdb->options WHERE `option_name` = 'logged_in_salt' LIMIT 1" );
1917
- if ( $wp_logged_in_salt ) {
1918
- bb_update_option( 'bb_logged_in_salt', $wp_logged_in_salt );
1919
- $installation_log[] = '>>>>>> ' . __( 'WordPress "logged in" cookie salt set.' );
1920
- } else {
1921
- $error_log[] = '>>> ' . __( 'WordPress "logged in" cookie salt not set.' );
1922
- $error_log[] = '>>>>>> ' . __( 'Could not fetch "logged in" cookie salt from the WordPress options table.' );
1923
- $error_log[] = '>>>>>> ' . __( 'You will need to manually define the "logged in" cookie salt in your database.' );
1924
- $installation_log[] = '>>>>>> ' . __( 'WordPress "logged in" cookie salt not set.' );
1925
- }
1926
- }
1927
- }
1928
-
1929
- if ( !empty( $data2['wp_table_prefix']['value'] ) ) {
1930
- bb_update_option( 'wp_table_prefix', $data2['wp_table_prefix']['value'] );
1931
- $installation_log[] = '>>> ' . __( 'User database table prefix:' ) . ' ' . $data2['wp_table_prefix']['value'];
1932
- }
1933
-
1934
- if ( !empty( $data2['wordpress_mu_primary_blog_id']['value'] ) ) {
1935
- bb_update_option( 'wordpress_mu_primary_blog_id', $data2['wordpress_mu_primary_blog_id']['value'] );
1936
- $installation_log[] = '>>> ' . __( 'WordPress MU primary blog ID:' ) . ' ' . $data2['wordpress_mu_primary_blog_id']['value'];
1937
- }
1938
-
1939
- if ( $data2['toggle_2_3']['value'] ) {
1940
- if ( !empty( $data2['user_bbdb_name']['value'] ) ) {
1941
- bb_update_option( 'user_bbdb_name', $data2['user_bbdb_name']['value'] );
1942
- $installation_log[] = '>>> ' . __( 'User database name:' ) . ' ' . $data2['user_bbdb_name']['value'];
1943
- }
1944
- if ( !empty( $data2['user_bbdb_user']['value'] ) ) {
1945
- bb_update_option( 'user_bbdb_user', $data2['user_bbdb_user']['value'] );
1946
- $installation_log[] = '>>> ' . __( 'User database user:' ) . ' ' . $data2['user_bbdb_user']['value'];
1947
- }
1948
- if ( !empty( $data2['user_bbdb_password']['value'] ) ) {
1949
- bb_update_option( 'user_bbdb_password', $data2['user_bbdb_password']['value'] );
1950
- $installation_log[] = '>>> ' . __( 'User database password:' ) . ' ' . $data2['user_bbdb_password']['value'];
1951
- }
1952
- if ( !empty( $data2['user_bbdb_host']['value'] ) ) {
1953
- bb_update_option( 'user_bbdb_host', $data2['user_bbdb_host']['value'] );
1954
- $installation_log[] = '>>> ' . __( 'User database host:' ) . ' ' . $data2['user_bbdb_host']['value'];
1955
- }
1956
- if ( !empty( $data2['user_bbdb_charset']['value'] ) ) {
1957
- bb_update_option( 'user_bbdb_charset', $data2['user_bbdb_charset']['value'] );
1958
- $installation_log[] = '>>> ' . __( 'User database character set:' ) . ' ' . $data2['user_bbdb_charset']['value'];
1959
- }
1960
- if ( !empty( $data2['user_bbdb_collate']['value'] ) ) {
1961
- bb_update_option( 'user_bbdb_collate', $data2['user_bbdb_collate']['value'] );
1962
- $installation_log[] = '>>> ' . __( 'User database collation:' ) . ' ' . $data2['user_bbdb_collate']['value'];
1963
- }
1964
- if ( !empty( $data2['custom_user_table']['value'] ) ) {
1965
- bb_update_option( 'custom_user_table', $data2['custom_user_table']['value'] );
1966
- $installation_log[] = '>>> ' . __( 'User database "user" table:' ) . ' ' . $data2['custom_user_table']['value'];
1967
- }
1968
- if ( !empty( $data2['custom_user_meta_table']['value'] ) ) {
1969
- bb_update_option( 'custom_user_meta_table', $data2['custom_user_meta_table']['value'] );
1970
- $installation_log[] = '>>> ' . __( 'User database "user meta" table:' ) . ' ' . $data2['custom_user_meta_table']['value'];
1971
- }
1972
- }
1973
- }
1974
- } else {
1975
- $installation_log[] = '>>> ' . __( 'Integration not enabled' );
1976
- }
1977
-
1978
- // Site settings passed from step 3
1979
- // These are already validated provided that the referer checks out
1980
- $installation_log[] = "\n" . __( 'Step 3 - Site settings' );
1981
- bb_update_option( 'name', $data3['name']['value'] );
1982
- $installation_log[] = '>>> ' . __( 'Site name:' ) . ' ' . $data3['name']['value'];
1983
- bb_update_option( 'uri', $data3['uri']['value'] );
1984
- $installation_log[] = '>>> ' . __( 'Site address (URL):' ) . ' ' . $data3['uri']['value'];
1985
- bb_update_option( 'from_email', $data3['keymaster_user_email']['value'] );
1986
- $installation_log[] = '>>> ' . __( 'From email address:' ) . ' ' . $data3['keymaster_user_email']['value'];
1987
-
1988
- // Create the key master
1989
- $keymaster_created = false;
1990
-
1991
- switch ( $data3['keymaster_user_type']['value'] ) {
1992
- case 'new':
1993
-
1994
- // Check to see if the user login already exists
1995
- if ( $keymaster_user = bb_get_user( $data3['keymaster_user_login']['value'], array( 'by' => 'login' ) ) ) {
1996
- // The keymaster is an existing bbPress user
1997
- $installation_log[] = '>>> ' . __( 'Key master could not be created!' );
1998
- $installation_log[] = '>>>>>> ' . __( 'That login is already taken!' );
1999
- $error_log[] = __( 'Key master could not be created!' );
2000
-
2001
- if ( $keymaster_user->bb_capabilities['keymaster'] ) {
2002
- // The existing user is a key master - continue
2003
- $bb_current_user = bb_set_current_user( $keymaster_user->ID );
2004
- $installation_log[] = '>>>>>> ' . __( 'Existing key master entered!' );
2005
- $data4['keymaster_user_password']['value'] = __( 'Your bbPress password' );
2006
- $data3['keymaster_user_email']['value'] = $keymaster_user->user_email;
2007
- bb_update_option( 'from_email', $keymaster_user->user_email);
2008
- $installation_log[] = '>>>>>> ' . __( 'Re-setting admin email address.' );
2009
- $keymaster_created = true;
2010
- } else {
2011
- // The existing user is a non-key master user - halt installation
2012
- $installation_log[] = '>>>>>> ' . __( 'Existing user without key master role entered!' );
2013
- $installation_log[] = '>>>>>>>>> ' . __( 'Halting installation!' );
2014
- $this->step_status[4] = 'incomplete';
2015
- $this->strings[4]['h2'] = __( 'Installation failed!' );
2016
- $this->strings[4]['messages']['error'][] = __( 'The key master could not be created. An existing user was found with that user login.' );
2017
-
2018
- $data4['installation_log']['value'] = join( "\n", $installation_log );
2019
- $data4['error_log']['value'] = join( "\n", $error_log );
2020
-
2021
- return 'incomplete';
2022
- }
2023
-
2024
- break;
2025
- }
2026
-
2027
- // Helper function to let us know the password that was created
2028
- global $keymaster_password;
2029
- function bb_get_keymaster_password( $user_id, $pass ) {
2030
- global $keymaster_password;
2031
- $keymaster_password = $pass;
2032
- }
2033
- add_action( 'bb_new_user', 'bb_get_keymaster_password', 10, 2 );
2034
-
2035
- // Create the new user (automattically given key master role when BB_INSTALLING is true)
2036
- if ( $keymaster_user_id = bb_new_user( $data3['keymaster_user_login']['value'], $data3['keymaster_user_email']['value'], '' ) ) {
2037
- $bb_current_user = bb_set_current_user( $keymaster_user_id );
2038
- $data4['keymaster_user_password']['value'] = $keymaster_password;
2039
- $installation_log[] = '>>> ' . __( 'Key master created' );
2040
- $installation_log[] = '>>>>>> ' . __( 'Username:' ) . ' ' . $data3['keymaster_user_login']['value'];
2041
- $installation_log[] = '>>>>>> ' . __( 'Email address:' ) . ' ' . $data3['keymaster_user_email']['value'];
2042
- $installation_log[] = '>>>>>> ' . __( 'Password:' ) . ' ' . $data4['keymaster_user_password']['value'];
2043
- $keymaster_created = true;
2044
- } else {
2045
- $installation_log[] = '>>> ' . __( 'Key master could not be created!' );
2046
- $installation_log[] = '>>>>>> ' . __( 'Halting installation!' );
2047
- $error_log[] = __( 'Key master could not be created!' );
2048
- $this->step_status[4] = 'incomplete';
2049
- $this->strings[4]['h2'] = __( 'Installation failed!' );
2050
- $this->strings[4]['messages']['error'][] = __( 'The key master could not be created. You may need to replace bbPress with a fresh copy and start again.' );
2051
-
2052
- $data4['installation_log']['value'] = join( "\n", $installation_log );
2053
- $data4['error_log']['value'] = join( "\n", $error_log );
2054
-
2055
- return 'incomplete';
2056
- }
2057
- break;
2058
-
2059
- case 'old':
2060
- if ( $keymaster_user = bb_get_user( $data3['keymaster_user_login']['value'], array( 'by' => 'login' ) ) ) {
2061
- // The keymaster is an existing bbPress or WordPress user
2062
- $bb_current_user = bb_set_current_user( $keymaster_user->ID );
2063
- $bb_current_user->set_role( 'keymaster' );
2064
- $data4['keymaster_user_password']['value'] = __( 'Your existing password' );
2065
- $installation_log[] = '>>> ' . __( 'Key master role assigned to existing user' );
2066
- $installation_log[] = '>>>>>> ' . __( 'Username:' ) . ' ' . $data3['keymaster_user_login']['value'];
2067
- $installation_log[] = '>>>>>> ' . __( 'Email address:' ) . ' ' . $data3['keymaster_user_email']['value'];
2068
- $installation_log[] = '>>>>>> ' . __( 'Password:' ) . ' ' . $data4['keymaster_user_password']['value'];
2069
- $keymaster_created = true;
2070
- } else {
2071
- $installation_log[] = '>>> ' . __( 'Key master role could not be assigned to existing user!' );
2072
- $installation_log[] = '>>>>>> ' . __( 'Halting installation!' );
2073
- $error_log[] = __( 'Key master could not be created!' );
2074
- $this->step_status[4] = 'incomplete';
2075
- $this->strings[4]['h2'] = __( 'Installation failed!' );
2076
- $this->strings[4]['messages']['error'][] = __( 'The key master could not be assigned. You may need to replace bbPress with a fresh copy and start again.' );
2077
-
2078
- $data4['installation_log']['value'] = join( "\n", $installation_log );
2079
- $data4['error_log']['value'] = join( "\n", $error_log );
2080
-
2081
- return 'incomplete';
2082
- }
2083
- break;
2084
- }
2085
-
2086
- // Don't create an initial forum if any forums already exist
2087
- if (!$bbdb->get_results( 'SELECT `forum_id` FROM `' . $bbdb->forums . '` LIMIT 1;' ) ) {
2088
- if ( $this->language != BB_LANG) {
2089
- global $locale, $l10n;
2090
- $locale = BB_LANG;
2091
- unset( $l10n['default'] );
2092
- bb_load_default_textdomain();
2093
- }
2094
-
2095
- $description = __( 'Just another bbPress community' );
2096
- bb_update_option( 'description', $description);
2097
-
2098
- if ( $this->language != BB_LANG) {
2099
- $locale = $this->language;
2100
- unset( $l10n['default'] );
2101
- bb_load_default_textdomain();
2102
- }
2103
-
2104
- $installation_log[] = '>>> ' . __( 'Description:' ) . ' ' . $description;
2105
-
2106
- if ( $forum_id = bb_new_forum( array( 'forum_name' => $data3['forum_name']['value'] ) ) ) {
2107
- $installation_log[] = '>>> ' . __( 'Forum name:' ) . ' ' . $data3['forum_name']['value'];
2108
-
2109
- if ( $this->language != BB_LANG) {
2110
- $locale = BB_LANG;
2111
- unset( $l10n['default'] );
2112
- bb_load_default_textdomain();
2113
- }
2114
-
2115
- $topic_title = __( 'Your first topic' );
2116
- $topic_id = bb_insert_topic(
2117
- array(
2118
- 'topic_title' => $topic_title,
2119
- 'forum_id' => $forum_id,
2120
- 'tags' => 'bbPress'
2121
- )
2122
- );
2123
- $post_text = __( 'First Post! w00t.' );
2124
- bb_insert_post(
2125
- array(
2126
- 'topic_id' => $topic_id,
2127
- 'post_text' => $post_text
2128
- )
2129
- );
2130
-
2131
- if ( $this->language != BB_LANG ) {
2132
- $locale = $this->language;
2133
- unset( $l10n['default'] );
2134
- bb_load_default_textdomain();
2135
- }
2136
-
2137
- $installation_log[] = '>>>>>> ' . __( 'Topic:' ) . ' ' . $topic_title;
2138
- $installation_log[] = '>>>>>>>>> ' . __( 'Post:' ) . ' ' . $post_text;
2139
- } else {
2140
- $installation_log[] = '>>> ' . __( 'Forum could not be created!' );
2141
- $error_log[] = __( 'Forum could not be created!' );
2142
- }
2143
- } else {
2144
- $installation_log[] = '>>> ' . __( 'There are existing forums in this database.' );
2145
- $installation_log[] = '>>>>>> ' . __( 'No new forum created.' );
2146
- $error_log[] = __( 'Forums already exist!' );
2147
- }
2148
-
2149
- if ( defined( 'BB_PLUGIN_DIR' ) && BB_PLUGIN_DIR && !file_exists( BB_PLUGIN_DIR ) ) {
2150
- // Just suppress errors as this is not critical
2151
- if ( @mkdir( BB_PLUGIN_DIR, 0755 ) ) {
2152
- $installation_log[] = '>>> ' . sprintf( __( 'Making plugin directory at %s.' ), BB_PLUGIN_DIR );
2153
- }
2154
- }
2155
-
2156
- if ( defined( 'BB_THEME_DIR' ) && BB_THEME_DIR && !file_exists( BB_THEME_DIR ) ) {
2157
- // Just suppress errors as this is not critical
2158
- if ( @mkdir( BB_THEME_DIR, 0755 ) ) {
2159
- $installation_log[] = '>>> ' . sprintf( __( 'Making theme directory at %s.' ), BB_THEME_DIR );
2160
- }
2161
- }
2162
-
2163
- if ( $keymaster_created ) {
2164
- $keymaster_email_message = sprintf(
2165
- __( "Your new bbPress site has been successfully set up at:\n\n%1\$s\n\nYou can log in to the key master account with the following information:\n\nUsername: %2\$s\nPassword: %3\$s\n\nWe hope you enjoy your new forums. Thanks!\n\n--The bbPress Team\nhttp://bbpress.org/" ),
2166
- bb_get_uri( null, null, BB_URI_CONTEXT_TEXT ),
2167
- $data3['keymaster_user_login']['value'],
2168
- $data4['keymaster_user_password']['value']
2169
- );
2170
-
2171
- if ( bb_mail( $data3['keymaster_user_email']['value'], __( 'New bbPress installation' ), $keymaster_email_message ) ) {
2172
- $installation_log[] = '>>> ' . __( 'Key master email sent' );
2173
- } else {
2174
- $installation_log[] = '>>> ' . __( 'Key master email not sent!' );
2175
- $error_log[] = __( 'Key master email not sent!' );
2176
- }
2177
- }
2178
-
2179
- if ( count( $error_log ) ) {
2180
- $this->strings[4]['h2'] = __( 'Installation completed with some errors!' );
2181
- $this->strings[4]['messages']['error'][] = __( 'Your installation completed with some minor errors. See the error log below for more specific information.' );
2182
- $installation_log[] = "\n" . __( 'There were some errors encountered during installation!' );
2183
- } else {
2184
- $this->strings[4]['messages']['message'][] = __( 'Your installation completed successfully.' );
2185
- $installation_log[] = "\n" . __( 'Installation complete!' );
2186
- }
2187
-
2188
- $this->step_status[4] = 'complete';
2189
-
2190
- $data4['installation_log']['value'] = join( "\n", $installation_log );
2191
- $data4['error_log']['value'] = join( "\n", $error_log );
2192
-
2193
- return 'complete';
2194
- }
2195
-
2196
- /**
2197
- * Prints a text input form element.
2198
- *
2199
- * @param $key string The key of the data to populate the element with.
2200
- * @param $direction string Optional. The text direction, only 'ltr' or 'rtl' are acceptable.
2201
- * @return void
2202
- **/
2203
- function input_text( $key, $direction = false )
2204
- {
2205
- $data = $this->data[$this->step]['form'][$key];
2206
-
2207
- $class = '';
2208
- $classes = array();
2209
- if ( isset( $data['note'] ) ) {
2210
- $classes[] = 'has-note';
2211
- }
2212
- if ( isset( $data['label'] ) ) {
2213
- $classes[] = 'has-label';
2214
- }
2215
-
2216
- if ( isset( $this->data[$this->step]['form'][$key]['type'] ) ) {
2217
- $type = $this->data[$this->step]['form'][$key]['type'];
2218
- } else {
2219
- $type = 'text';
2220
- }
2221
- $classes[] = 'for-input-' . $type;
2222
-
2223
- if ( isset( $this->strings[$this->step]['form_errors'][$key] ) ) {
2224
- $classes[] = 'error';
2225
- }
2226
- if ( count( $classes ) ) {
2227
- $class = ' class="' . join( ' ', $classes ) . '"';
2228
- }
2229
-
2230
- $r = "\t" . '<label id="label-' . esc_attr( $key ) . '" for="' . esc_attr( $key ) . '"' . $class . '>' . "\n";
2231
-
2232
- if ( isset( $data['label'] ) ) {
2233
- $r .= "\t\t" . '<span>' . $data['label'] . '</span>' . "\n";
2234
- }
2235
-
2236
- if ( isset( $this->strings[$this->step]['form_errors'][$key] ) ) {
2237
- foreach ( $this->strings[$this->step]['form_errors'][$key] as $error ) {
2238
- if ( !is_bool( $error ) ) {
2239
- $r .= "\t\t" . '<span class="error">' . $error . '</span>' . "\n";
2240
- }
2241
- }
2242
- }
2243
-
2244
- if ( isset( $data['maxlength'] ) && is_integer( $data['maxlength'] ) ) {
2245
- $maxlength = ' maxlength="' . esc_attr( $data['maxlength'] ) . '"';
2246
- }
2247
-
2248
- if ( $direction && in_array( strtolower( $direction ), array( 'ltr', 'rtl' ) ) ) {
2249
- $direction = ' dir="' . esc_attr( strtolower( $direction ) ) . '"';
2250
- }
2251
-
2252
- if ( isset( $data['autocomplete'] ) ) {
2253
- $autocomplete = ' autocomplete="' . esc_attr( $data['autocomplete'] ) . '"';
2254
- } else {
2255
- $autocomplete = '';
2256
- }
2257
-
2258
- $this->tabindex++;
2259
- $r .= "\t\t" . '<input' . $direction . ' type="' . esc_attr( $type ) . '" id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '" class="text' . $has_note_class . '" value="' . esc_attr( $data['value'] ) . '"' . $maxlength . $autocomplete . ' tabindex="' . $this->tabindex . '" />' . "\n";
2260
-
2261
- if ( isset( $data['note'] ) ) {
2262
- $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2263
- $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2264
- }
2265
-
2266
- $r .= "\t\t" . '<div class="clear"></div>' . "\n";
2267
- $r .= "\t" . '</label>' . "\n";
2268
-
2269
- echo $r;
2270
- }
2271
-
2272
- /**
2273
- * Prints a hidden input form element.
2274
- *
2275
- * @param $key string The key of the data to populate the element with.
2276
- * @return void
2277
- **/
2278
- function input_hidden( $key )
2279
- {
2280
- $r = "\t" . '<input type="hidden" id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '" value="' . esc_attr( $this->data[$this->step]['form'][$key]['value'] ) . '" />' . "\n";
2281
-
2282
- echo $r;
2283
- }
2284
-
2285
- /**
2286
- * Prints a textarea form element.
2287
- *
2288
- * @param $key string The key of the data to populate the element with.
2289
- * @param $direction string Optional. The text direction, only 'ltr' or 'rtl' are acceptable.
2290
- * @return void
2291
- **/
2292
- function textarea( $key, $direction = false)
2293
- {
2294
- $data = $this->data[$this->step]['form'][$key];
2295
-
2296
- $class = '';
2297
- $classes = array( 'for-textarea' );
2298
- if ( isset( $data['note'] ) ) {
2299
- $classes[] = 'has-note';
2300
- }
2301
- if ( isset( $data['label'] ) ) {
2302
- $classes[] = 'has-label';
2303
- }
2304
- if ( count( $classes ) ) {
2305
- $class = ' class="' . join( ' ', $classes ) . '"';
2306
- }
2307
-
2308
- $r = "\t" . '<label id="label-' . esc_attr( $key ) . '"' . $class . ' for="' . esc_attr( $key ) . '">' . "\n";
2309
-
2310
- if ( isset( $data['label'] ) ) {
2311
- $r .= "\t\t" . '<span>' . $data['label'] . '</span>' . "\n";
2312
- }
2313
-
2314
- if ( isset( $data['note'] ) ) {
2315
- $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2316
- $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2317
- }
2318
-
2319
- if ( $direction && in_array( strtolower( $direction ), array( 'ltr', 'rtl' ) ) ) {
2320
- $direction = ' dir="' . esc_attr( strtolower( $direction ) ) . '"';
2321
- }
2322
-
2323
- $this->tabindex++;
2324
- $r .= "\t\t" . '<textarea id="' . esc_attr( $key ) . '" rows="5" cols="30"' . $direction . ' tabindex="' . $this->tabindex . '">' . esc_html( $data['value'] ) . '</textarea>' . "\n";
2325
-
2326
- $r .= "\t" . '</label>' . "\n";
2327
-
2328
- echo $r;
2329
- }
2330
-
2331
- /**
2332
- * Prints a select form element populated with options.
2333
- *
2334
- * @param $key string The key of the data to populate the element with.
2335
- * @return void
2336
- **/
2337
- function select( $key )
2338
- {
2339
- $data = $this->data[$this->step]['form'][$key];
2340
-
2341
- $class = '';
2342
- $classes = array( 'for-select' );
2343
- if ( isset( $data['note'] ) ) {
2344
- $classes[] = 'has-note';
2345
- }
2346
- if ( isset( $data['label'] ) ) {
2347
- $classes[] = 'has-label';
2348
- }
2349
- if ( count( $classes ) ) {
2350
- $class = ' class="' . join( ' ', $classes ) . '"';
2351
- }
2352
-
2353
- $r = "\t" . '<label id="label-' . esc_attr( $key ) . '"' . $class . ' for="' . esc_attr( $key ) . '">' . "\n";
2354
-
2355
- if ( isset( $data['label'] ) ) {
2356
- $r .= "\t\t" . '<span>' . $data['label'] . '</span>' . "\n";
2357
- }
2358
-
2359
- if ( isset( $data['options'] ) ) {
2360
- $r .= "\t\t" . '<select id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '"';
2361
- if ( isset( $data['onchange'] ) ) {
2362
- $r .= ' onchange="' . esc_attr( $data['onchange'] ) . '"';
2363
- }
2364
- $this->tabindex++;
2365
- $r .= ' tabindex="' . $this->tabindex . '">' . "\n";
2366
-
2367
- foreach ( $data['options'] as $value => $display ) {
2368
- if ( $data['value'] == $value ) {
2369
- $selected = ' selected="selected"';
2370
- } else {
2371
- $selected = '';
2372
- }
2373
-
2374
- $r .= "\t\t\t" . '<option value="' . esc_attr( $value ) . '"' . $selected . '>' . esc_html( $display ) . '</option>' . "\n";
2375
- }
2376
-
2377
- $r .= "\t\t" . '</select>';
2378
- }
2379
-
2380
- if ( isset( $data['note'] ) ) {
2381
- $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2382
- $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2383
- }
2384
-
2385
- $r .= "\t\t" . '<div class="clear"></div>' . "\n";
2386
- $r .= "\t" . '</label>' . "\n";
2387
-
2388
- echo $r;
2389
- }
2390
-
2391
- /**
2392
- * Prints an appropriate language selection form element if there are any available.
2393
- *
2394
- * @return void
2395
- **/
2396
- function select_language()
2397
- {
2398
- if ( count( $this->languages ) > 1 ) {
2399
- $this->data[1]['form']['bb_lang']['value'] = $this->language;
2400
- $this->data[1]['form']['bb_lang']['options'] = $this->languages;
2401
- $this->select( 'bb_lang' );
2402
- } else {
2403
- $this->data[1]['form']['bb_lang']['value'] = 'en_US';
2404
- $this->input_hidden( 'bb_lang' );
2405
- }
2406
- }
2407
-
2408
- /**
2409
- * Prints an input checkbox which controls display of an optional section of settings.
2410
- *
2411
- * @param string $key The identifier of the area to be toggled.
2412
- * @return void
2413
- **/
2414
- function input_toggle( $key )
2415
- {
2416
- $data = $this->data[$this->step]['form'][$key];
2417
-
2418
- $class = '';
2419
- $classes = array( 'for-toggle' );
2420
- if ( isset( $data['note'] ) ) {
2421
- $classes[] = 'has-note';
2422
- }
2423
- if ( isset( $data['label'] ) ) {
2424
- $classes[] = 'has-label';
2425
- }
2426
-
2427
- $onclick = 'toggleBlock(this, \'' . esc_js( $key . '_target' ) . '\' );';
2428
- if ( isset( $data['toggle_value'] ) ) {
2429
- $onclick .= ' toggleValue(this, \'' . esc_js( $data['toggle_value']['target'] ) . '\', \'' . esc_js( $data['toggle_value']['off_value'] ) . '\', \'' . esc_js( $data['toggle_value']['on_value'] ) . '\' );';
2430
- }
2431
-
2432
- $checked = $data['checked'] ? ' ' . trim( $data['checked'] ) : '';
2433
-
2434
- if ( isset( $this->strings[$this->step]['form_errors'][$key] ) ) {
2435
- $classes[] = 'error';
2436
- }
2437
- if ( count( $classes ) ) {
2438
- $class = ' class="' . join( ' ', $classes ) . '"';
2439
- }
2440
-
2441
- $r = "\t" . '<label id="label-' . esc_attr( $key ) . '"' . $class . ' for="' . esc_attr( $key ) . '">' . "\n";
2442
-
2443
- $r .= "\t\t" . '<span>' . "\n";
2444
- $this->tabindex++;
2445
- $r .= "\t\t\t" . '<input type="checkbox" id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '" class="checkbox" onclick="' . esc_attr( $onclick ) . '"' . $checked . ' value="1" tabindex="' . $this->tabindex . '" />' . "\n";
2446
- if ( isset( $data['label'] ) ) {
2447
- $r .= "\t\t\t" . $data['label'] . "\n";
2448
- }
2449
- $r .= "\t\t" . '</span>' . "\n";
2450
-
2451
- if ( isset( $data['note'] ) ) {
2452
- $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2453
- $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2454
- }
2455
-
2456
- $r .= "\t\t" . '<div class="clear"></div>' . "\n";
2457
- $r .= "\t" . '</label>' . "\n";
2458
-
2459
- echo $r;
2460
- }
2461
-
2462
- /**
2463
- * Prints the input buttons which post each step and optionally go back a step.
2464
- *
2465
- * @param string $forward The HTML element ID of the forward button.
2466
- * @param string $back Optional. The HTML element ID of the back button.
2467
- * @return void
2468
- **/
2469
- function input_buttons( $forward, $back = false, $step = false )
2470
- {
2471
- $data_back = $back ? $this->data[$this->step]['form'][$back] : false;
2472
- $data_forward = $this->data[$this->step]['form'][$forward];
2473
-
2474
- $r = '<fieldset class="buttons">' . "\n";
2475
-
2476
- if ( !$step ) {
2477
- $step = $this->step;
2478
- }
2479
- $r .= "\t" . '<input type="hidden" id="step" name="step" value="' . (int) $step . '" />' . "\n";
2480
-
2481
- if ( $back) {
2482
- $r .= "\t" . '<label id="label-' . esc_attr( $back ) . '" for="' . esc_attr( $back ) . '" class="back">' . "\n";
2483
- $this->tabindex++;
2484
- $r .= "\t\t" . '<input type="submit" id="' . esc_attr( $back ) . '" name="' . esc_attr( $back ) . '" class="button" value="' . esc_attr( $data_back['value'] ) . '" tabindex="' . $this->tabindex . '" />' . "\n";
2485
- $r .= "\t" . '</label>' . "\n";
2486
- }
2487
-
2488
- $r .= "\t" . '<label id="label-' . esc_attr( $forward ) . '" for="' . esc_attr( $forward ) . '" class="forward">' . "\n";
2489
- $this->tabindex++;
2490
- $r .= "\t\t" . '<input type="submit" id="' . esc_attr( $forward ) . '" name="' . esc_attr( $forward ) . '" class="button" value="' . esc_attr( $data_forward['value'] ) . '" tabindex="' . $this->tabindex . '" />' . "\n";
2491
- $r .= "\t" . '</label>' . "\n";
2492
-
2493
- $r .= '</fieldset>' . "\n";
2494
-
2495
- echo $r;
2496
- }
2497
-
2498
- /**
2499
- * Prints hidden input elements containing the data inputted in a given step.
2500
- *
2501
- * @param integer $step Optional. The number of the step whose hidden inputs should be printed.
2502
- * @return void
2503
- **/
2504
- function hidden_step_inputs( $step = false )
2505
- {
2506
- if ( !$step ) {
2507
- $step = $this->step;
2508
- } elseif ( $step !== $this->step ) {
2509
- $this->inject_form_values_into_data( $step );
2510
- }
2511
-
2512
- $data = $this->data[$step]['form'];
2513
-
2514
- $r = '<fieldset>' . "\n";
2515
-
2516
- foreach ( $data as $key => $value ) {
2517
- if ( 'forward_' !== substr( $key, 0, 8 ) && 'back_' !== substr( $key, 0, 5 ) ) {
2518
- $r .= "\t" . '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value['value'] ) . '" />' . "\n";
2519
- }
2520
- }
2521
-
2522
- $r .= '</fieldset>' . "\n";
2523
-
2524
- echo $r;
2525
- }
2526
-
2527
- /**
2528
- * Rewrites the admin user input into a select element containing existing WordPress administrators.
2529
- *
2530
- * @return boolean True if the select element was created, otherwise false.
2531
- **/
2532
- function populate_keymaster_user_login_from_user_tables()
2533
- {
2534
- $data =& $this->data[3]['form']['keymaster_user_login'];
2535
-
2536
- // Get the existing WordPress admin users
2537
-
2538
- // Setup variables and constants if available
2539
- global $bb;
2540
- if ( !empty( $this->data[2]['form']['wp_table_prefix']['value'] ) ) {
2541
- $bb->wp_table_prefix = $this->data[2]['form']['wp_table_prefix']['value'];
2542
- }
2543
- if ( !empty( $this->data[2]['form']['user_bbdb_name']['value'] ) ) {
2544
- $bb->user_bbdb_name = $this->data[2]['form']['user_bbdb_name']['value'];
2545
- }
2546
- if ( !empty( $this->data[2]['form']['user_bbdb_user']['value'] ) ) {
2547
- $bb->user_bbdb_user = $this->data[2]['form']['user_bbdb_user']['value'];
2548
- }
2549
- if ( !empty( $this->data[2]['form']['user_bbdb_password']['value'] ) ) {
2550
- $bb->user_bbdb_password = $this->data[2]['form']['user_bbdb_password']['value'];
2551
- }
2552
- if ( !empty( $this->data[2]['form']['user_bbdb_host']['value'] ) ) {
2553
- $bb->user_bbdb_host = $this->data[2]['form']['user_bbdb_host']['value'];
2554
- }
2555
- if ( !empty( $this->data[2]['form']['user_bbdb_charset']['value'] ) ) {
2556
- $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['user_bbdb_charset']['value'] );
2557
- }
2558
- if ( !empty( $this->data[2]['form']['user_bbdb_collate']['value'] ) ) {
2559
- $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['user_bbdb_collate']['value'] );
2560
- }
2561
- if ( !empty( $this->data[2]['form']['custom_user_table']['value'] ) ) {
2562
- $bb->custom_user_table = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['custom_user_table']['value'] );
2563
- }
2564
- if ( !empty( $this->data[2]['form']['custom_user_meta_table']['value'] ) ) {
2565
- $bb->custom_user_meta_table = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['custom_user_meta_table']['value'] );
2566
- }
2567
-
2568
- global $bbdb;
2569
- global $bb_table_prefix;
2570
-
2571
- // Resolve the custom user tables for bpdb
2572
- bb_set_custom_user_tables();
2573
-
2574
- if ( isset( $bb->custom_databases ) && isset( $bb->custom_databases['user'] ) ) {
2575
- $bbdb->add_db_server( 'user', $bb->custom_databases['user'] );
2576
- }
2577
-
2578
- // Add custom tables if required
2579
- if ( isset( $bb->custom_tables['users'] ) || isset( $bb->custom_tables['usermeta'] ) ) {
2580
- $bbdb->tables = array_merge( $bbdb->tables, $bb->custom_tables );
2581
- if ( is_wp_error( $bbdb->set_prefix( $bb_table_prefix ) ) ) {
2582
- die( __( 'Your user table prefix may only contain letters, numbers and underscores.' ) );
2583
- }
2584
- }
2585
-
2586
- $bb_keymaster_meta_key = $bbdb->escape( $bb_table_prefix . 'capabilities' );
2587
- $wp_administrator_meta_key = $bbdb->escape( $bb->wp_table_prefix . 'capabilities' );
2588
- if ( !empty( $this->data[2]['form']['wordpress_mu_primary_blog_id']['value'] ) ) {
2589
- $wp_administrator_meta_key = $bb->wp_table_prefix . $this->data[2]['form']['wordpress_mu_primary_blog_id']['value'] . '_capabilities';
2590
- }
2591
-
2592
- $keymaster_query = <<<EOQ
2593
- SELECT
2594
- user_login, user_email, display_name
2595
- FROM
2596
- $bbdb->users
2597
- LEFT JOIN
2598
- $bbdb->usermeta ON
2599
- $bbdb->users.ID = $bbdb->usermeta.user_id
2600
- WHERE
2601
- (
2602
- (
2603
- meta_key = '$wp_administrator_meta_key' AND
2604
- meta_value LIKE '%administrator%'
2605
- ) OR
2606
- (
2607
- meta_key = '$bb_keymaster_meta_key' AND
2608
- meta_value LIKE '%keymaster%'
2609
- )
2610
- ) AND
2611
- user_email IS NOT NULL AND
2612
- user_email != ''
2613
- ORDER BY
2614
- user_login;
2615
- EOQ;
2616
- $bbdb->suppress_errors();
2617
-
2618
- if ( $keymasters = $bbdb->get_results( $keymaster_query, ARRAY_A ) ) {
2619
-
2620
- $bbdb->suppress_errors( false );
2621
-
2622
- if ( count( $keymasters ) ) {
2623
- $email_maps = '';
2624
- $data['options'] = array();
2625
- $data['onchange'] = 'changeKeymasterEmail( this, \'keymaster_user_email\' );';
2626
- $data['note'] = __( 'Please select an existing bbPress Keymaster or WordPress administrator.' );
2627
-
2628
- $data['options'][''] = '';
2629
- foreach ( $keymasters as $keymaster ) {
2630
- $email_maps .= 'emailMap[\'' . $keymaster['user_login'] . '\'] = \'' . $keymaster['user_email'] . '\';' . "\n\t\t\t\t\t\t\t\t";
2631
- if ( $keymaster['display_name'] ) {
2632
- $data['options'][$keymaster['user_login']] = $keymaster['user_login'] . ' (' . $keymaster['display_name'] . ')';
2633
- } else {
2634
- $data['options'][$keymaster['user_login']] = $keymaster['user_login'];
2635
- }
2636
- }
2637
-
2638
- $this->strings[3]['scripts']['changeKeymasterEmail'] = <<<EOS
2639
- <script type="text/javascript" charset="utf-8">
2640
- function changeKeymasterEmail( selectObj, target ) {
2641
- var emailMap = new Array;
2642
- emailMap[''] = '';
2643
- $email_maps
2644
- var targetObj = document.getElementById( target );
2645
- var selectedAdmin = selectObj.options[selectObj.selectedIndex].value;
2646
- targetObj.value = emailMap[selectedAdmin];
2647
- }
2648
- </script>
2649
- EOS;
2650
-
2651
- $this->data[3]['form']['keymaster_user_type']['value'] = 'old';
2652
-
2653
- return true;
2654
- }
2655
- }
2656
-
2657
- $bbdb->suppress_errors( false );
2658
-
2659
- return false;
2660
- }
2661
-
2662
- /**
2663
- * Sends HTTP headers and prints the page header.
2664
- *
2665
- * @return void
2666
- **/
2667
- function header()
2668
- {
2669
- nocache_headers();
2670
-
2671
- bb_install_header( $this->strings[$this->step]['title'], $this->strings[$this->step]['h1'], true );
2672
- }
2673
-
2674
- /**
2675
- * Prints the page footer.
2676
- *
2677
- * @return void
2678
- **/
2679
- function footer()
2680
- {
2681
- bb_install_footer();
2682
- }
2683
-
2684
- /**
2685
- * Prints the returned messages for the current step.
2686
- *
2687
- * @return void
2688
- **/
2689
- function messages()
2690
- {
2691
- if ( isset( $this->strings[$this->step]['messages'] ) ) {
2692
- $messages = $this->strings[$this->step]['messages'];
2693
-
2694
- // This count works as long as $messages is only two-dimensional
2695
- $count = ( count( $messages, COUNT_RECURSIVE ) - count( $messages ) );
2696
- $i = 0;
2697
- $r = '';
2698
- foreach ( $messages as $type => $paragraphs ) {
2699
- $class = $type ? $type : '';
2700
-
2701
- foreach ( $paragraphs as $paragraph ) {
2702
- $i++;
2703
- $class = ( $i === $count ) ? ( $class . ' last' ) : $class;
2704
- $r .= '<p class="' . esc_attr( $class ) . '">' . $paragraph . '</p>' . "\n";
2705
- }
2706
- }
2707
- echo $r;
2708
- }
2709
- }
2710
-
2711
- /**
2712
- * Prints the introduction paragraphs for the current step.
2713
- *
2714
- * @return void
2715
- **/
2716
- function intro()
2717
- {
2718
- if ( 'incomplete' == $this->step_status[$this->step] && isset( $this->strings[$this->step]['intro'] ) ) {
2719
- $messages = $this->strings[$this->step]['intro'];
2720
- $count = count( $messages );
2721
- $i = 0;
2722
- $r = '';
2723
- foreach ( $messages as $paragraph ) {
2724
- $i++;
2725
- $class = ( $i === $count ) ? 'intro last' : 'intro';
2726
- $r .= '<p class="' . $class . '">' . $paragraph . '</p>' . "\n";
2727
- }
2728
- echo $r;
2729
- }
2730
- }
2731
-
2732
- /**
2733
- * Prints the standard header for each step.
2734
- *
2735
- * @param integer $step The number of the step whose header should be printed.
2736
- * @return void
2737
- **/
2738
- function step_header( $step )
2739
- {
2740
- $class = ( $step == $this->step ) ? 'open' : 'closed';
2741
-
2742
- $r = '<div id="' . esc_attr( 'step' . $step ) . '" class="' . $class . '">' . "\n";
2743
- $r .= '<h2 class="' . $class . '">' . $this->strings[$step]['h2'] . '</h2>' . "\n";
2744
- $r .= '<div>' . "\n";
2745
-
2746
- if ( $step < $this->step && $this->strings[$step]['status'] ) {
2747
- $r .= '<p class="status">' . $this->strings[$step]['status'] . '</p>' . "\n";
2748
- }
2749
-
2750
- echo $r;
2751
-
2752
- if ( $step == $this->step ) {
2753
- $this->intro();
2754
- }
2755
-
2756
- $this->tabindex = 0;
2757
- }
2758
-
2759
- /**
2760
- * Prints the standard step footer.
2761
- *
2762
- * @return void
2763
- **/
2764
- function step_footer()
2765
- {
2766
- $r = '</div></div>' . "\n";
2767
-
2768
- echo $r;
2769
- }
2770
- } // END class BB_Install
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/includes/defaults.bb-htaccess.php DELETED
@@ -1,46 +0,0 @@
1
- <?php
2
-
3
- $_rules = <<<EOF
4
- # BEGIN bbPress
5
-
6
- Options -MultiViews
7
-
8
- <IfModule mod_rewrite.c>
9
- RewriteEngine On
10
- RewriteBase %PATH%
11
-
12
- RewriteRule ^page/([0-9]+)/?$ %PATH%index.php?page=$1 [L,QSA]
13
- RewriteRule ^forum/([^/]+)/page/([0-9]+)/?$ %PATH%forum.php?id=$1&page=$2 [L,QSA]
14
- RewriteRule ^forum/([^/]+)/?$ %PATH%forum.php?id=$1 [L,QSA]
15
- RewriteRule ^forum/?$ %PATH% [R=302,L,QSA]
16
- RewriteRule ^topic/([^/]+)/page/([0-9]+)/?$ %PATH%topic.php?id=$1&page=$2 [L,QSA]
17
- RewriteRule ^topic/([^/]+)/?$ %PATH%topic.php?id=$1 [L,QSA]
18
- RewriteRule ^topic/?$ %PATH% [R=302,L,QSA]
19
- RewriteRule ^tags/([^/]+)/page/([0-9]+)/?$ %PATH%tags.php?tag=$1&page=$2 [L,QSA]
20
- RewriteRule ^tags/([^/]+)/?$ %PATH%tags.php?tag=$1 [L,QSA]
21
- RewriteRule ^tags/?$ %PATH%tags.php [L,QSA]
22
- RewriteRule ^profile/([^/]+)/page/([0-9]+)/?$ %PATH%profile.php?id=$1&page=$2 [L,QSA]
23
- RewriteRule ^profile/([^/]+)/([^/]+)/?$ %PATH%profile.php?id=$1&tab=$2 [L,QSA]
24
- RewriteRule ^profile/([^/]+)/([^/]+)/page/([0-9]+)/?$ %PATH%profile.php?id=$1&tab=$2&page=$3 [L,QSA]
25
- RewriteRule ^profile/([^/]+)/?$ %PATH%profile.php?id=$1 [L,QSA]
26
- RewriteRule ^profile/?$ %PATH%profile.php [L,QSA]
27
- RewriteRule ^view/([^/]+)/page/([0-9]+)/?$ %PATH%view.php?view=$1&page=$2 [L,QSA]
28
- RewriteRule ^view/([^/]+)/?$ %PATH%view.php?view=$1 [L,QSA]
29
- RewriteRule ^rss/?$ %PATH%rss.php [L,QSA]
30
- RewriteRule ^rss/topics/?$ %PATH%rss.php?topics=1 [L,QSA]
31
- RewriteRule ^rss/forum/([^/]+)/?$ %PATH%rss.php?forum=$1 [L,QSA]
32
- RewriteRule ^rss/forum/([^/]+)/topics/?$ %PATH%rss.php?forum=$1&topics=1 [L,QSA]
33
- RewriteRule ^rss/topic/([^/]+)/?$ %PATH%rss.php?topic=$1 [L,QSA]
34
- RewriteRule ^rss/tags/([^/]+)/?$ %PATH%rss.php?tag=$1 [L,QSA]
35
- RewriteRule ^rss/tags/([^/]+)/topics/?$ %PATH%rss.php?tag=$1&topics=1 [L,QSA]
36
- RewriteRule ^rss/profile/([^/]+)/?$ %PATH%rss.php?profile=$1 [L,QSA]
37
- RewriteRule ^rss/view/([^/]+)/?$ %PATH%rss.php?view=$1 [L,QSA]
38
- RewriteCond %{REQUEST_FILENAME} !-f
39
- RewriteCond %{REQUEST_FILENAME} !-d
40
- RewriteRule ^.*$ %PATH%index.php [L]
41
- </IfModule>
42
-
43
- # END bbPress
44
- EOF;
45
-
46
- $_rules = str_replace( '%PATH%', bb_get_option( 'path' ), $_rules );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/includes/defaults.bb-schema.php DELETED
@@ -1,235 +0,0 @@
1
- <?php
2
-
3
- // Globalise as this file is included within the functions bb_install() and bb_upgrade_all()
4
- global $bb_queries, $bbdb, $bb_schema_ignore;
5
-
6
- // Die if no database class is loaded
7
- if ( !isset($bbdb) || ( !is_a( $bbdb, 'BPDB' ) && !is_a( $bbdb, 'db' ) ) )
8
- die( __('Database class not loaded.') );
9
-
10
- // Initialise the query array
11
- $bb_queries = array();
12
-
13
- // forums
14
- $bb_queries['forums'] = "CREATE TABLE IF NOT EXISTS `$bbdb->forums` (
15
- `forum_id` int(10) NOT NULL auto_increment,
16
- `forum_name` varchar(150) NOT NULL default '',
17
- `forum_slug` varchar(255) NOT NULL default '',
18
- `forum_desc` text NOT NULL,
19
- `forum_parent` int(10) NOT NULL default 0,
20
- `forum_order` int(10) NOT NULL default 0,
21
- `topics` bigint(20) NOT NULL default 0,
22
- `posts` bigint(20) NOT NULL default 0,
23
- PRIMARY KEY (`forum_id`),
24
- KEY `forum_slug` (`forum_slug`)
25
- );";
26
-
27
- // meta
28
- $bb_queries['meta'] = "CREATE TABLE IF NOT EXISTS `$bbdb->meta` (
29
- `meta_id` bigint(20) NOT NULL auto_increment,
30
- `object_type` varchar(16) NOT NULL default 'bb_option',
31
- `object_id` bigint(20) NOT NULL default 0,
32
- `meta_key` varchar(255) default NULL,
33
- `meta_value` longtext default NULL,
34
- PRIMARY KEY (`meta_id`),
35
- KEY `object_type__meta_key` (`object_type`, `meta_key`),
36
- KEY `object_type__object_id__meta_key` (`object_type`, `object_id`, `meta_key`)
37
- );";
38
-
39
- // posts
40
- $bb_queries['posts'] = "CREATE TABLE IF NOT EXISTS `$bbdb->posts` (
41
- `post_id` bigint(20) NOT NULL auto_increment,
42
- `forum_id` int(10) NOT NULL default 1,
43
- `topic_id` bigint(20) NOT NULL default 1,
44
- `poster_id` int(10) NOT NULL default 0,
45
- `post_text` text NOT NULL,
46
- `post_time` datetime NOT NULL default '0000-00-00 00:00:00',
47
- `poster_ip` varchar(15) NOT NULL default '',
48
- `post_status` tinyint(1) NOT NULL default 0,
49
- `post_position` bigint(20) NOT NULL default 0,
50
- PRIMARY KEY (`post_id`),
51
- KEY `topic_time` (`topic_id`, `post_time`),
52
- KEY `poster_time` (`poster_id`, `post_time`),
53
- KEY `post_time` (`post_time`),
54
- FULLTEXT KEY `post_text` (`post_text`)
55
- ) ENGINE = MYISAM;";
56
-
57
- // terms
58
- $bb_queries['terms'] = "CREATE TABLE IF NOT EXISTS `$bbdb->terms` (
59
- `term_id` bigint(20) NOT NULL auto_increment,
60
- `name` varchar(55) NOT NULL default '',
61
- `slug` varchar(200) NOT NULL default '',
62
- `term_group` bigint(10) NOT NULL default 0,
63
- PRIMARY KEY (`term_id`),
64
- UNIQUE KEY `slug` (`slug`),
65
- KEY name (name)
66
- );";
67
-
68
- // term_relationships
69
- $bb_queries['term_relationships'] = "CREATE TABLE IF NOT EXISTS `$bbdb->term_relationships` (
70
- `object_id` bigint(20) NOT NULL default 0,
71
- `term_taxonomy_id` bigint(20) NOT NULL default 0,
72
- `user_id` bigint(20) NOT NULL default 0,
73
- `term_order` int(11) NOT NULL default 0,
74
- PRIMARY KEY (`object_id`, `term_taxonomy_id`),
75
- KEY `term_taxonomy_id` (`term_taxonomy_id`)
76
- );";
77
-
78
- // term_taxonomy
79
- $bb_queries['term_taxonomy'] = "CREATE TABLE IF NOT EXISTS `$bbdb->term_taxonomy` (
80
- `term_taxonomy_id` bigint(20) NOT NULL auto_increment,
81
- `term_id` bigint(20) NOT NULL default 0,
82
- `taxonomy` varchar(32) NOT NULL default '',
83
- `description` longtext NOT NULL,
84
- `parent` bigint(20) NOT NULL default 0,
85
- `count` bigint(20) NOT NULL default 0,
86
- PRIMARY KEY (`term_taxonomy_id`),
87
- UNIQUE KEY `term_id_taxonomy` (`term_id`, `taxonomy`),
88
- KEY `taxonomy` (`taxonomy`)
89
- );";
90
-
91
- // topics
92
- $bb_queries['topics'] = "CREATE TABLE IF NOT EXISTS `$bbdb->topics` (
93
- `topic_id` bigint(20) NOT NULL auto_increment,
94
- `topic_title` varchar(100) NOT NULL default '',
95
- `topic_slug` varchar(255) NOT NULL default '',
96
- `topic_poster` bigint(20) NOT NULL default 0,
97
- `topic_poster_name` varchar(40) NOT NULL default 'Anonymous',
98
- `topic_last_poster` bigint(20) NOT NULL default 0,
99
- `topic_last_poster_name` varchar(40) NOT NULL default '',
100
- `topic_start_time` datetime NOT NULL default '0000-00-00 00:00:00',
101
- `topic_time` datetime NOT NULL default '0000-00-00 00:00:00',
102
- `forum_id` int(10) NOT NULL default 1,
103
- `topic_status` tinyint(1) NOT NULL default 0,
104
- `topic_open` tinyint(1) NOT NULL default 1,
105
- `topic_last_post_id` bigint(20) NOT NULL default 1,
106
- `topic_sticky` tinyint(1) NOT NULL default 0,
107
- `topic_posts` bigint(20) NOT NULL default 0,
108
- `tag_count` bigint(20) NOT NULL default 0,
109
- PRIMARY KEY (`topic_id`),
110
- KEY `topic_slug` (`topic_slug`),
111
- KEY `forum_time` (`forum_id`, `topic_time`),
112
- KEY `user_start_time` (`topic_poster`, `topic_start_time`),
113
- KEY `stickies` (`topic_status`, `topic_sticky`, `topic_time`)
114
- );";
115
-
116
- if ( bb_get_option( 'wp_table_prefix' ) || ( defined( 'BB_SCHEMA_IGNORE_WP_USERS_TABLES' ) && BB_SCHEMA_IGNORE_WP_USERS_TABLES ) ) {
117
- // Don't add user tables
118
- } else {
119
- // users - 'user_login', 'user_nicename' and 'user_registered' indices are inconsistent with WordPress
120
- $bb_queries['users'] = "CREATE TABLE IF NOT EXISTS `$bbdb->users` (
121
- `ID` bigint(20) unsigned NOT NULL auto_increment,
122
- `user_login` varchar(60) NOT NULL default '',
123
- `user_pass` varchar(64) NOT NULL default '',
124
- `user_nicename` varchar(50) NOT NULL default '',
125
- `user_email` varchar(100) NOT NULL default '',
126
- `user_url` varchar(100) NOT NULL default '',
127
- `user_registered` datetime NOT NULL default '0000-00-00 00:00:00',
128
- `user_status` int(11) NOT NULL default 0,
129
- `display_name` varchar(250) NOT NULL default '',
130
- PRIMARY KEY (`ID`),
131
- UNIQUE KEY `user_login` (`user_login`),
132
- UNIQUE KEY `user_nicename` (`user_nicename`),
133
- KEY `user_registered` (`user_registered`)
134
- );";
135
-
136
- // usermeta
137
- $bb_queries['usermeta'] = "CREATE TABLE IF NOT EXISTS `$bbdb->usermeta` (
138
- `umeta_id` bigint(20) NOT NULL auto_increment,
139
- `user_id` bigint(20) NOT NULL default 0,
140
- `meta_key` varchar(255),
141
- `meta_value` longtext,
142
- PRIMARY KEY (`umeta_id`),
143
- KEY `user_id` (`user_id`),
144
- KEY `meta_key` (`meta_key`)
145
- );";
146
- }
147
-
148
- $bb_queries = apply_filters( 'bb_schema_pre_charset', $bb_queries );
149
-
150
- // Set the charset and collation on each table
151
- foreach ($bb_queries as $_table_name => $_sql) {
152
- // Skip SQL that isn't creating a table
153
- if (!preg_match('@^\s*CREATE\s+TABLE\s+@im', $_sql)) {
154
- continue;
155
- }
156
-
157
- // Skip if the table's database doesn't support collation
158
- if (!$bbdb->has_cap('collation', $bbdb->$_table_name)) {
159
- continue;
160
- }
161
-
162
- // Find out if the table has a custom database set
163
- if (
164
- isset($bbdb->db_tables) &&
165
- is_array($bbdb->db_tables) &&
166
- isset($bbdb->db_tables[$bbdb->$_table_name])
167
- ) {
168
- // Set the database for this table
169
- $_database = $bbdb->db_tables[$bbdb->$_table_name];
170
- } else {
171
- // Set the default global database
172
- $_database = 'dbh_global';
173
- }
174
-
175
- // Make sure the database exists
176
- if (
177
- isset($bbdb->db_servers) &&
178
- is_array($bbdb->db_servers) &&
179
- isset($bbdb->db_servers[$_database]) &&
180
- is_array($bbdb->db_servers[$_database])
181
- ) {
182
- $_charset_collate = '';
183
- if (isset($bbdb->db_servers[$_database]['charset']) && !empty($bbdb->db_servers[$_database]['charset'])) {
184
- // Add a charset if set
185
- $_charset_collate .= ' DEFAULT CHARACTER SET \'' . $bbdb->db_servers[$_database]['charset'] . '\'';
186
- }
187
- if (isset($bbdb->db_servers[$_database]['collate']) && !empty($bbdb->db_servers[$_database]['collate'])) {
188
- // Add a collation if set
189
- $_charset_collate .= ' COLLATE \'' . $bbdb->db_servers[$_database]['collate'] . '\'';
190
- }
191
- if ($_charset_collate) {
192
- // Modify the SQL
193
- $bb_queries[$_table_name] = str_replace(';', $_charset_collate . ';', $_sql);
194
- }
195
- }
196
- unset($_database, $_charset_collate);
197
- }
198
- unset($_table_name, $_sql);
199
-
200
- $bb_queries = apply_filters( 'bb_schema', $bb_queries );
201
-
202
- // These elements in the schema may need to be ignored when doing comparisons due to inconsistencies with WordPress
203
- if ( bb_get_option('wp_table_prefix') || ( defined( 'BB_SCHEMA_IGNORE_WP_USERS_KEYS' ) && BB_SCHEMA_IGNORE_WP_USERS_KEYS ) ) {
204
- $bb_schema_ignore = array(
205
- 'tables' => array(),
206
- 'columns' => array(),
207
- 'indices' => array(
208
- $bbdb->users => array(
209
- 'user_login',
210
- 'user_nicename',
211
- 'user_registered'
212
- )
213
- )
214
- );
215
- } else {
216
- $bb_schema_ignore = false;
217
- }
218
-
219
- if ( bb_get_option('wp_table_prefix') || ( defined( 'BB_SCHEMA_IGNORE_WP_USERS_TABLES' ) && BB_SCHEMA_IGNORE_WP_USERS_TABLES ) ) {
220
- if ( $bb_schema_ignore ) {
221
- $bb_schema_ignore['tables'] = array( $bbdb->users, $bbdb->usermeta );
222
- } else {
223
- $bb_schema_ignore = array(
224
- 'tables' => array( $bbdb->users, $bbdb->usermeta ),
225
- 'columns' => array(),
226
- 'indices' => array()
227
- );
228
- }
229
- }
230
-
231
- $bb_schema_ignore = apply_filters( 'bb_schema_ignore', $bb_schema_ignore );
232
-
233
- do_action( 'bb_schema_defined' );
234
-
235
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/includes/functions.bb-admin.php DELETED
@@ -1,1741 +0,0 @@
1
- <?php
2
-
3
- function bb_get_admin_header()
4
- {
5
- do_action( 'bb_admin-header.php' );
6
- include( 'admin-header.php' );
7
- do_action( 'bb_get_admin_header' );
8
- }
9
-
10
- function bb_get_admin_footer()
11
- {
12
- do_action( 'bb_admin-footer.php' );
13
- include( 'admin-footer.php' );
14
- }
15
-
16
- function bb_admin_notice( $message, $class = false )
17
- {
18
- if ( is_string( $message ) ) {
19
- $message = '<p>' . $message . '</p>';
20
- $class = $class ? $class : 'updated';
21
- } elseif ( is_wp_error( $message ) ) {
22
- $errors = $message->get_error_messages();
23
- switch ( count( $errors ) ) {
24
- case 0:
25
- return false;
26
- break;
27
- case 1:
28
- $message = '<p>' . $errors[0] . '</p>';
29
- break;
30
- default:
31
- $message = '<ul>' . "\n\t" . '<li>' . join( '</li>' . "\n\t" . '<li>', $errors ) . '</li>' . "\n" . '</ul>';
32
- break;
33
- }
34
- $class = $class ? $class : 'error';
35
- } else {
36
- return false;
37
- }
38
-
39
- $message = '<div id="message" class="' . esc_attr( $class ) . '">' . $message . '</div>';
40
- $message = str_replace( "'", "\'", $message );
41
- $lambda = create_function( '', "echo '$message';" );
42
- add_action( 'bb_admin_notices', $lambda );
43
- return $lambda;
44
- }
45
-
46
- /* Menu */
47
-
48
- function bb_admin_menu_generator()
49
- {
50
- global $bb_menu, $bb_submenu;
51
- $bb_menu = array();
52
- $bb_submenu = array();
53
-
54
- // Dashboard menu items < 50
55
- $bb_menu[0] = array( __( 'Dashboard' ), 'moderate', 'index.php', '', 'bb-menu-dashboard' );
56
- $bb_submenu['index.php'][5] = array( __( 'Dashboard' ), 'moderate', 'index.php' );
57
-
58
- // 50 < Plugin added menu items < 100
59
-
60
- $bb_menu[100] = array( '', 'read', 'separator' );
61
-
62
- // 100 < Plugin added menu items < 150
63
-
64
- // 150 < First menu items < 200
65
- $bb_menu[150] = array( __( 'Forums' ), 'manage_forums', 'forums.php', '', 'bb-menu-forums' );
66
- $bb_submenu['forums.php'][5] = array( __( 'Forums' ), 'manage_forums', 'forums.php' );
67
- $bb_menu[155] = array( __( 'Topics' ), 'moderate', 'topics.php', '', 'bb-menu-topics' );
68
- $bb_submenu['topics.php'][5] = array( __( 'Topics' ), 'moderate', 'topics.php' );
69
- $bb_menu[160] = array( __( 'Posts' ), 'moderate', 'posts.php', '', 'bb-menu-posts' );
70
- $bb_submenu['posts.php'][5] = array( __( 'Posts' ), 'moderate', 'posts.php' );
71
-
72
- // 200 < Plugin added menu items < 250
73
-
74
- $bb_menu[250] = array( '', 'read', 'separator' );
75
-
76
- // 250 < Plugin added menu items < 300
77
-
78
- // 300 < Second menu items < 350
79
- $bb_menu[300] = array( __( 'Appearance' ), 'manage_themes', 'themes.php', '', 'bb-menu-appearance' );
80
- $bb_submenu['themes.php'][5] = array(__('Themes'), 'manage_themes', 'themes.php');
81
- $bb_menu[305] = array( __( 'Plugins' ), 'use_keys', 'plugins.php', '', 'bb-menu-plugins' );
82
- $bb_submenu['plugins.php'][5] = array( __( 'Installed' ), 'manage_plugins', 'plugins.php' );
83
- $bb_menu[310] = array( __( 'Users' ), 'moderate', 'users.php', '', 'bb-menu-users' );
84
- $bb_submenu['users.php'][5] = array( __( 'Users' ), 'moderate', 'users.php' );
85
- $bb_submenu['users.php'][10] = array( __( 'Add New' ), 'manage_options', 'user-add-new.php' );
86
- $bb_menu[315] = array( __( 'Tools' ), 'recount', 'tools-recount.php', '', 'bb-menu-tools' );
87
- $bb_submenu['tools-recount.php'][5] = array( __( 'Re-count' ), 'recount', 'tools-recount.php' );
88
- $bb_menu[320] = array( __( 'Settings' ), 'manage_options', 'options-general.php', '', 'bb-menu-settings' );
89
- $bb_submenu['options-general.php'][5] = array( __( 'General' ), 'manage_options', 'options-general.php' );
90
- //$bb_submenu['options-general.php'][10] = array( __( 'Date and Time' ), 'manage_options', 'options-time.php' );
91
- $bb_submenu['options-general.php'][15] = array( __( 'Writing' ), 'manage_options', 'options-writing.php' );
92
- $bb_submenu['options-general.php'][20] = array( __( 'Reading' ), 'manage_options', 'options-reading.php' );
93
- $bb_submenu['options-general.php'][25] = array( __( 'Discussion' ), 'manage_options', 'options-discussion.php' );
94
- $bb_submenu['options-general.php'][30] = array( __( 'Permalinks' ), 'manage_options', 'options-permalinks.php' );
95
- $bb_submenu['options-general.php'][35] = array( __( 'WordPress Integration' ), 'manage_options', 'options-wordpress.php' );
96
-
97
- // 350 < Plugin added menu items
98
-
99
- do_action( 'bb_admin_menu_generator' );
100
- ksort( $bb_menu );
101
-
102
- $last_key = false;
103
- foreach ( $bb_menu as $key => $m ) {
104
- if ( $last_key === false || $bb_menu[$last_key][2] === 'separator' ) {
105
- $bb_menu[$key][3] .= ' bb-menu-first';
106
- }
107
- if ( $bb_menu[$key][2] === 'separator' ) {
108
- $bb_menu[$last_key][3] .= ' bb-menu-last';
109
- }
110
- $last_key = $key;
111
- if ( isset( $bb_submenu[$m[2]] ) ) {
112
- ksort( $bb_submenu[$m[2]] );
113
- }
114
- }
115
- $bb_menu[$last_key][3] .= ' bb-menu-last';
116
- }
117
-
118
- function bb_admin_add_menu( $display_name, $capability, $file_name, $menu_position = false, $class = '', $id = '' )
119
- {
120
- global $bb_menu;
121
- global $bb_registered_plugin_callbacks;
122
- if ( empty( $bb_registered_plugin_callbacks ) ) {
123
- $bb_registered_plugin_callbacks = array();
124
- }
125
-
126
- if ( $display_name && $capability && $file_name ) {
127
- // Get an array of the keys
128
- $menu_keys = array_keys( $bb_menu );
129
-
130
- if ( $menu_position ) {
131
- if ( is_numeric( $menu_position ) ) {
132
- if ( !isset( $bb_menu[$menu_position] ) ) {
133
- $plugin_menu_next = $menu_position;
134
- } else {
135
- return bb_admin_add_menu( $display_name, $capability, $file_name, ( $menu_position + 1 ), $class, $id );
136
- }
137
- } else {
138
- // Set the bounds for different menu groups (main or side)
139
- switch ( $menu_position ) {
140
- case 'dash':
141
- $lower = 50;
142
- $upper = 100;
143
- break;
144
- case 'main':
145
- $lower = 200;
146
- $upper = 250;
147
- break;
148
- default:
149
- $lower = 350;
150
- $upper = 500;
151
- break;
152
- }
153
-
154
- // Get an array of all plugin added keys
155
- $plugin_menu_keys = array_filter( $menu_keys, create_function( '$v', 'if ($v >= ' . $lower . ' && $v < ' . $upper . ') { return $v; }' ) );
156
-
157
- // If there is an array of keys
158
- if ( is_array( $plugin_menu_keys ) && count( $plugin_menu_keys ) ) {
159
- // Get the highest key value and add one
160
- $plugin_menu_next = max( $plugin_menu_keys ) + 1;
161
- } else {
162
- // It's the first one
163
- $plugin_menu_next = $lower;
164
- }
165
- }
166
- } else {
167
- $plugin_menu_next = max( array_keys( $bb_menu ) ) + 1;
168
- $bb_menu[$plugin_menu_next] = array( '', 'read', 'separator' );
169
- $plugin_menu_next++;
170
- }
171
-
172
- if ( strpos( $file_name, '.php' ) === false ) {
173
- $bb_registered_plugin_callbacks[] = $file_name;
174
- }
175
-
176
- // Add the menu item at the given key
177
- $bb_menu[$plugin_menu_next] = array( $display_name, $capability, $file_name, $class, $id );
178
-
179
- ksort( $bb_menu );
180
-
181
- return $plugin_menu_next;
182
- }
183
-
184
- return false;
185
- }
186
-
187
- function bb_admin_add_submenu( $display_name, $capability, $file_name, $parent = 'plugins.php' )
188
- {
189
- global $bb_submenu;
190
- global $bb_registered_plugin_callbacks;
191
- if ( empty( $bb_registered_plugin_callbacks ) ) {
192
- $bb_registered_plugin_callbacks = array();
193
- }
194
-
195
- if ( $display_name && $capability && $file_name ) {
196
- if ( strpos( $file_name, '.php' ) === false ) {
197
- $bb_registered_plugin_callbacks[] = $file_name;
198
- }
199
- $bb_submenu[$parent][] = array( $display_name, $capability, $file_name );
200
- ksort( $bb_submenu );
201
- }
202
- }
203
-
204
- function bb_get_current_admin_menu()
205
- {
206
- global $bb_menu, $bb_submenu, $bb_admin_page, $bb_current_menu, $bb_current_submenu;
207
- foreach ( $bb_submenu as $m => $b ) {
208
- foreach ( $b as $s ) {
209
- if ( $s[2] == $bb_admin_page ) {
210
- $bb_current_submenu = $s;
211
- $bb_current_menu = $m;
212
- break;
213
- }
214
- }
215
- }
216
- if ( !isset($bb_current_menu) ) {
217
- $bb_current_menu = $bb_menu[0];
218
- $bb_current_submenu = $bb_submenu['index.php'][5];
219
- } else {
220
- foreach ( $bb_menu as $m ) {
221
- if ( $m[2] == $bb_current_menu ) {
222
- $bb_current_menu = $m;
223
- break;
224
- }
225
- }
226
- }
227
- if ( $bb_current_submenu && !bb_current_user_can( $bb_current_submenu[1] ) || !bb_current_user_can( $bb_current_menu[1] ) ) {
228
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
229
- exit;
230
- }
231
- }
232
-
233
- function bb_admin_title()
234
- {
235
- global $bb_current_menu, $bb_current_submenu;
236
-
237
- $title = $bb_current_menu[0] . ' &lsaquo; ' . bb_get_option( 'name' ) . ' &#8212; ' . __( 'bbPress' );
238
-
239
- if ( $bb_current_submenu && $bb_current_submenu[0] !== $bb_current_menu[0] ) {
240
- $title = $bb_current_submenu[0] . ' &lsaquo; ' . $title;
241
- }
242
-
243
- echo esc_html( $title );
244
- }
245
-
246
- function bb_admin_menu()
247
- {
248
- global $bb_menu, $bb_submenu, $bb_current_menu, $bb_current_submenu;
249
-
250
- if ( !is_array( $bb_menu ) || !count( $bb_menu ) ) {
251
- return '';
252
- }
253
-
254
- $r = "\t\t\t" . '<ul id="bbAdminMenu">' . "\n";
255
-
256
- foreach ( $bb_menu as $key => $m ) {
257
- if ( !bb_current_user_can( $m[1] ) ) {
258
- continue;
259
- }
260
- $class = 'bb-menu';
261
- if ( isset( $m[3] ) ) {
262
- $class .= ' ' . $m[3];
263
- }
264
- $id = '';
265
- if ( isset( $m[4] ) ) {
266
- $id .= ' id="' . $m[4] . '"';
267
- }
268
- $m[0] = esc_html( $m[0] );
269
- if ( $m[2] === 'separator' ) {
270
- if ( 'f' == bb_get_user_setting( 'fm' ) ) {
271
- $href = '?foldmenu=0';
272
- } else {
273
- $href = '?foldmenu=1';
274
- }
275
- $m[0] = '<br />';
276
- $class .= ' bb-menu-separator';
277
- } elseif ( strpos( $m[2], 'http://' ) === 0 || strpos( $m[2], 'https://' ) === 0 ) {
278
- $href = esc_url( $m[2] );
279
- $class .= ' bb-menu-external';
280
- } else {
281
- $href = esc_url( bb_get_option( 'path' ) . 'bb-admin/' . bb_get_admin_tab_link( $m[2] ) );
282
- }
283
- if ( $m[2] == $bb_current_menu[2] ) {
284
- $class .= ' bb-menu-current';
285
- }
286
-
287
- $sr = '';
288
- if ( $m[2] !== 'separator' && isset( $bb_submenu[$m[2]] ) && is_array( $bb_submenu[$m[2]] ) && count( $bb_submenu[$m[2]] ) ) {
289
- $sr .= "\t\t\t\t\t" . '<div class="bb-menu-sub-wrap"><span>' . $m[0] . '</span>' . "\n";
290
- $sr .= "\t\t\t\t\t\t" . '<ul>' . "\n";
291
- $sc = 0;
292
- foreach ( $bb_submenu[$m[2]] as $skey => $sm ) {
293
- if ( !bb_current_user_can( $sm[1] ) ) {
294
- continue;
295
- }
296
- if ( $sc === 0 && $sm[2] === $m[2] ) {
297
- $no_submenu = true;
298
- }
299
- if ( $sc > 0 ) {
300
- $no_submenu = false;
301
- }
302
- $sc++;
303
- $sclass = 'bb-menu-sub';
304
- if ( isset( $sm[3] ) ) {
305
- $sclass .= ' ' . $sm[3];
306
- }
307
- if ( strpos( $sm[2], 'http://' ) === 0 || strpos( $sm[2], 'https://' ) === 0 ) {
308
- $shref = $sm[2];
309
- $sclass .= ' bb-menu-external';
310
- } else {
311
- $shref = bb_get_option( 'path' ) . 'bb-admin/' . bb_get_admin_tab_link( $sm[2] );
312
- }
313
- if ( $sm[2] == $bb_current_submenu[2] ) {
314
- $sclass .= ' bb-menu-sub-current';
315
- }
316
- $sr .= "\t\t\t\t\t\t\t" . '<li class="' . esc_attr( trim( $sclass ) ) . '"><a href="' . esc_url( $shref ) . '">' . esc_html( $sm[0] ) . '</a></li>' . "\n";
317
- }
318
- $sr .= "\t\t\t\t\t\t" . '</ul>' . "\n";
319
- $sr .= "\t\t\t\t\t" . '</div>' . "\n";
320
- }
321
-
322
- if ( $sr && !$no_submenu ) {
323
- $class .= ' bb-menu-has-submenu';
324
- if ( $m[2] == $bb_current_menu[2] ) {
325
- $class .= ' bb-menu-open';
326
- }
327
- }
328
-
329
- $r .= "\t\t\t\t" . '<li' . $id . ' class="' . esc_attr( trim( $class ) ) . '"><a href="' . $href . '">';
330
-
331
- if ( $m[2] !== 'separator' ) {
332
- $r .= '<div class="bb-menu-icon"></div>';
333
- }
334
-
335
- $r .= '<span>' . $m[0] . '</span></a>' . "\n";
336
-
337
- if ( $sr && !$no_submenu ) {
338
- $r .= '<div class="bb-menu-toggle"></div>';
339
- $r .= $sr;
340
- }
341
-
342
- $r .= "\t\t\t\t" . '</li>' . "\n";
343
- }
344
-
345
- $r .= "\t\t\t" . '</ul>' . "\n";
346
-
347
- echo $r;
348
- }
349
-
350
- function bb_get_admin_tab_link( $tab )
351
- {
352
- if ( is_array( $tab ) ) {
353
- $tab = $tab[2];
354
- }
355
- if ( strpos( $tab, '.php' ) !== false ) {
356
- return $tab;
357
- } else {
358
- return 'admin-base.php?plugin=' . $tab;
359
- }
360
- }
361
-
362
- /* Stats */
363
-
364
- function bb_get_recently_moderated_objects( $num = 5 ) {
365
- $post_query = new BB_Query( 'post', array( 'per_page' => $num, 'post_status' => '-normal', 'topic_status' => 0 ) ); // post_time != moderation_time;
366
- $topic_query = new BB_Query( 'topic', array( 'per_page' => $num, 'topic_status' => '-normal' ) ); // topic_time == topic_start_time != moderation_time;
367
-
368
- $objects = array();
369
- if ( $post_query->results )
370
- foreach ( array_keys($post_query->results) as $key )
371
- $objects[bb_gmtstrtotime($post_query->results[$key]->post_time)] = array('type' => 'post', 'data' => $post_query->results[$key]);
372
- if ( $topic_query->results )
373
- foreach ( array_keys($topic_query->results) as $key )
374
- $objects[bb_gmtstrtotime($topic_query->results[$key]->topic_time)] = array('type' => 'topic', 'data' => $topic_query->results[$key]);
375
- krsort($objects);
376
- return array_slice($objects, 0, $num);
377
- }
378
-
379
- /* Users */
380
-
381
- function bb_manage_user_fields( $edit_user = '' ) {
382
- global $wp_roles, $wp_users_object, $bbdb;
383
-
384
- // Cap checks
385
- $user_roles = $wp_roles->role_names;
386
- $can_keep_gate = bb_current_user_can( 'keep_gate' );
387
-
388
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
389
-
390
- bb_check_admin_referer( 'user-manage' );
391
-
392
- // Instantiate required vars
393
- $_POST = stripslashes_deep( $_POST );
394
- $create_user_errors = new WP_Error;
395
-
396
- // User login
397
- $trimmed_user_login = str_replace( ' ', '', $_POST['user_login'] );
398
- $user_login = sanitize_user( $_POST['user_login'], true );
399
- $user_meta['first_name'] = $_POST['first_name'];
400
- $user_meta['last_name'] = $_POST['last_name'];
401
- $user_display_name = $_POST['display_name'];
402
- $user_email = $_POST['user_email'];
403
- $user_url = $_POST['user_url'];
404
- $user_meta['from'] = $_POST['from'];
405
- $user_meta['occ'] = $_POST['occ'];
406
- $user_meta['interest'] = $_POST['interest'];
407
- $user_role = $_POST['userrole'];
408
- $user_meta['throttle'] = $_POST['throttle'];
409
- $user_pass1 = $_POST['pass1'];
410
- $user_pass2 = $_POST['pass2'];
411
- $user_status = 0;
412
- $user_pass = false;
413
- $user_url = $user_url ? bb_fix_link( $user_url ) : '';
414
-
415
- // Check user_login
416
- if ( !isset( $_GET['action'] ) && empty( $user_login ) ) {
417
- $create_user_errors->add( 'user_login', __( 'Username is a required field.' ) );
418
- } else {
419
- if ( $user_login !== $trimmed_user_login ) {
420
- $create_user_errors->add( 'user_login', sprintf( __( '%s is an invalid username. How\'s this one?' ), esc_html( $_POST['user_login'] ) ) );
421
- $user_login = $trimmed_user_login;
422
- }
423
- }
424
-
425
- // Check email
426
- if ( isset( $user_email ) && empty( $user_email ) )
427
- $create_user_errors->add( 'user_email', __( 'Email address is a required field.' ) );
428
-
429
- // Password Sanity Check
430
- if ( ( !empty( $user_pass1 ) || !empty( $user_pass2 ) ) && $user_pass1 !== $user_pass2 )
431
- $create_user_errors->add( 'pass', __( 'You must enter the same password twice.' ) );
432
- elseif ( !isset( $_GET['action'] ) && ( empty( $user_pass1 ) && empty( $user_pass2 ) ) )
433
- $create_user_errors->add( 'pass', __( 'You must enter a password.' ) );
434
- elseif ( isset( $_GET['action'] ) && ( empty( $user_pass1 ) && empty( $user_pass2 ) ) )
435
- $user_pass = '';
436
- else
437
- $user_pass = $user_pass1;
438
-
439
- // No errors
440
- if ( !$create_user_errors->get_error_messages() ) {
441
-
442
- // Create or udpate
443
- switch ( $_POST['action'] ) {
444
- case 'create' :
445
- $goback = bb_get_uri( 'bb-admin/users.php', array( 'created' => 'true' ), BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN );
446
- $user = $wp_users_object->new_user( compact( 'user_login', 'user_email', 'user_url', 'user_nicename', 'user_status', 'user_pass' ) );
447
-
448
- // Error handler
449
- if ( is_wp_error( $user ) ) {
450
- bb_admin_notice( $user );
451
- unset( $goback );
452
-
453
- // Update additional user data
454
- } else {
455
- // Update caps
456
- bb_update_usermeta( $user['ID'], $bbdb->prefix . 'capabilities', array( $user_role => true ) );
457
-
458
- // Update all user meta
459
- foreach ( $user_meta as $key => $value )
460
- bb_update_usermeta( $user['ID'], $key, $value );
461
-
462
- // Don't send email if empty
463
- if ( !empty( $user_pass ) )
464
- bb_send_pass( $user['ID'], $user_pass );
465
-
466
- do_action( 'bb_new_user', $user['ID'], $user_pass );
467
- }
468
-
469
- break;
470
-
471
- case 'update' :
472
- $goback = bb_get_uri( 'bb-admin/users.php', array( 'updated' => 'true' ), BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN );
473
- $user = $wp_users_object->get_user( $_GET['user_id'], array( 'output' => ARRAY_A ) );
474
- bb_update_user( $user['ID'], $user_email, $user_url, $user_display_name );
475
-
476
- // Don't change PW if empty
477
- if ( !empty( $user_pass ) )
478
- bb_update_user_password( $user['ID'], $user_pass );
479
-
480
- // Error handler
481
- if ( is_wp_error( $user ) ) {
482
- bb_admin_notice( $user );
483
- unset( $goback );
484
-
485
- // Update additional user data
486
- } else {
487
- // Update caps
488
- bb_update_usermeta( $user['ID'], $bbdb->prefix . 'capabilities', array( $user_role => true ) );
489
-
490
- // Update all user meta
491
- foreach ( $user_meta as $key => $value )
492
- bb_update_usermeta( $user['ID'], $key, $value );
493
-
494
- // Don't send email if empty
495
- if ( !empty( $user_pass ) )
496
- bb_send_pass( $user['ID'], $user_pass );
497
-
498
- do_action( 'bb_update_user', $user['ID'], $user_pass );
499
- }
500
-
501
- break;
502
- }
503
-
504
- // Redirect
505
- if ( isset( $goback ) && !empty( $goback ) )
506
- bb_safe_redirect( $goback );
507
-
508
- // Error handler
509
- } else {
510
- bb_admin_notice( $create_user_errors );
511
- }
512
- } elseif ( isset( $_GET['action'] ) && $_GET['action'] == 'edit' ) {
513
- if ( isset( $_GET['user_id'] ) && is_numeric( $_GET['user_id'] ) ) {
514
- $disabled = true;
515
-
516
- // Get the user
517
- if ( empty( $edit_user ) )
518
- $edit_user = bb_get_user( bb_get_user_id( $_GET['user_id'] ) );
519
-
520
- // Instantiate required vars
521
- $user_login = $edit_user->user_login;
522
- $user_meta['first_name'] = $edit_user->first_name;
523
- $user_meta['last_name'] = $edit_user->last_name;
524
- $user_display_name = $edit_user->display_name;
525
- $user_email = $edit_user->user_email;
526
- $user_url = $edit_user->user_url;
527
- $user_meta['from'] = $edit_user->from;
528
- $user_meta['occ'] = $edit_user->occ;
529
- $user_meta['interest'] = $edit_user->interest;
530
- $user_role = array_search( 'true', $edit_user->capabilities );
531
- $user_meta['throttle'] = $edit_user->throttle;
532
-
533
- // Keymasters can't demote themselves
534
- if ( ( $edit_user->ID == bb_get_current_user_info( 'id' ) && $can_keep_gate ) || ( isset( $edit_user->capabilities ) && is_array( $edit_user->capabilities ) && array_key_exists( 'keymaster', $edit_user->capabilities ) && !$can_keep_gate ) )
535
- $user_roles = array( 'keymaster' => $user_roles['keymaster'] );
536
-
537
- // only keymasters can promote others to keymaster status
538
- elseif ( !$can_keep_gate )
539
- unset( $user_roles['keymaster'] );
540
- }
541
- }
542
-
543
- // Load password strength checker
544
- wp_enqueue_script( 'password-strength-meter' );
545
- wp_enqueue_script( 'profile-edit' );
546
-
547
- // Generate a few PW hints
548
- $some_pass_hints = '';
549
- for ( $l = 3; $l != 0; $l-- )
550
- $some_pass_hints .= '<p>' . bb_generate_password() . '</p>';
551
-
552
- // Create the user fields
553
- $user_fields = array(
554
- 'user_login' => array(
555
- 'title' => __( 'Username' ),
556
- 'note' => __( 'Required! Unique identifier for new user.' ),
557
- 'value' => $user_login,
558
- 'disabled' => $disabled
559
- ),
560
- 'first_name' => array(
561
- 'title' => __( 'First Name' ),
562
- 'value' => $user_meta['first_name']
563
- ),
564
- 'last_name' => array(
565
- 'title' => __( 'Last Name' ),
566
- 'value' => $user_meta['last_name']
567
- ),
568
- 'display_name' => array(
569
- 'title' => __( 'Display Name' ),
570
- 'value' => $user_display_name
571
- ),
572
- 'user_email' => array(
573
- 'title' => __( 'Email' ),
574
- 'note' => __( 'Required! Will be used for notifications and profile settings changes.' ),
575
- 'value' => $user_email
576
- ),
577
- 'user_url' => array(
578
- 'title' => __( 'Website' ),
579
- 'class' => array( 'long', 'code' ),
580
- 'note' => __( 'The full URL of user\'s homepage or blog.' ),
581
- 'value' => $user_url
582
- ),
583
- 'from' => array(
584
- 'title' => __( 'Location' ),
585
- 'class' => array( 'long' ),
586
- 'value' => $user_meta['from']
587
- ),
588
- 'occ' => array(
589
- 'title' => __( 'Occupation' ),
590
- 'class' => array( 'long' ),
591
- 'value' => $user_meta['occ']
592
- ),
593
- 'interest' => array(
594
- 'title' => __( 'Interests' ),
595
- 'class' => array( 'long' ),
596
- 'value' => $user_meta['interest']
597
- ),
598
- 'userrole' => array(
599
- 'title' => __( 'User Role' ),
600
- 'type' => 'select',
601
- 'options' => $user_roles,
602
- 'note' => __( 'Allow user the above privileges.' ),
603
- 'value' => $user_role,
604
- ),
605
- 'pass1' => array(
606
- 'title' => __( 'New Password' ),
607
- 'type' => 'password',
608
- 'class' => array( 'short', 'text', 'code' ),
609
- 'note' => __( 'Hints: ' ) . $some_pass_hints,
610
- 'value' => $user_pass1,
611
- ),
612
- 'pass2' => array(
613
- 'title' => __( 'Repeat New Password' ),
614
- 'type' => 'password',
615
- 'class' => array( 'short', 'text', 'code' ),
616
- 'note' => __( 'If you ignore hints, remember: the password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ % ^ &amp; ).' ),
617
- 'value' => $user_pass2,
618
- ),
619
- 'email_pass' => array(
620
- 'title' => '',
621
- 'type' => 'checkbox',
622
- 'options' => array(
623
- '1' => array(
624
- 'label' => __( 'Email the new password.' ),
625
- 'attributes' => array( 'checked' => true )
626
- )
627
- ),
628
- ),
629
- 'pass-strength-fake-input' => array(
630
- 'title' => __( 'Password Strength' ),
631
- 'type' => 'hidden',
632
- ),
633
- );
634
-
635
- return apply_filters( 'bb_manage_user_fields', $user_fields );
636
- }
637
-
638
- // Not bbdb::prepared
639
- function bb_get_ids_by_role( $role = 'moderator', $sort = 0, $page = 1, $limit = 50 ) {
640
- global $bbdb, $bb_last_countable_query;
641
- $sort = $sort ? 'DESC' : 'ASC';
642
- $key = $bbdb->escape( $bbdb->prefix . 'capabilities' );
643
-
644
- if ( !$page = abs( (int) $page ) )
645
- $page = 1;
646
- $limit = abs( (int) $limit );
647
-
648
- $limit = ($limit * ($page - 1)) . ", $limit";
649
-
650
- $role = $bbdb->escape_deep($role);
651
-
652
- if ( is_array($role) )
653
- $and_where = "( meta_value LIKE '%" . join("%' OR meta_value LIKE '%", $role) . "%' )";
654
- else
655
- $and_where = "meta_value LIKE '%$role%'";
656
- $bb_last_countable_query = "SELECT user_id FROM $bbdb->usermeta WHERE meta_key = '$key' AND $and_where ORDER BY user_id $sort LIMIT $limit";
657
-
658
- $ids = false;
659
-
660
- $_tuple = compact( 'ids', 'role', 'sort', 'page', 'key', 'limit', 'bb_last_countable_query' );
661
- $_tuple = apply_filters( 'bb_get_ids_by_role', $_tuple );
662
- extract( $_tuple, EXTR_OVERWRITE );
663
-
664
- if ( !$ids ) {
665
- $ids = (array) $bbdb->get_col( $bb_last_countable_query );
666
- }
667
-
668
- if ( $ids ) {
669
- bb_cache_users( $ids );
670
- }
671
-
672
- return $ids;
673
- }
674
-
675
- function bb_user_row( $user, $role = '', $email = false ) {
676
- $actions = "<a href='" . esc_attr( get_user_profile_link( $user->ID ) ) . "'>" . __('View') . "</a>";
677
- $title = '';
678
- if ( bb_current_user_can( 'edit_user', $user_id ) ) {
679
- $actions .= " | <a href='" . esc_attr( bb_get_user_admin_link( $user->ID ) ) . "'>" . __('Edit') . "</a>";
680
- $title = " title='" . esc_attr( sprintf( __( 'User ID: %d' ), $user->ID ) ) . "'";
681
- }
682
- $r = "\t<tr id='user-$user->ID'" . get_alt_class("user-$role") . ">\n";
683
- $r .= "\t\t<td class=\"user\">" . bb_get_avatar( $user->ID, 32 ) . "<span class=\"row-title\"><a href='" . get_user_profile_link( $user->ID ) . "'" . $title . ">" . get_user_name( $user->ID ) . "</a></span><div><span class=\"row-actions\">$actions</span>&nbsp;</div></td>\n";
684
- $r .= "\t\t<td><a href='" . get_user_profile_link( $user->ID ) . "'>" . get_user_display_name( $user->ID ) . "</a></td>\n";
685
- if ( $email ) {
686
- $email = bb_get_user_email( $user->ID );
687
- $r .= "\t\t<td><a href='mailto:$email'>$email</a></td>\n";
688
- }
689
-
690
- $registered_time = bb_gmtstrtotime( $user->user_registered );
691
- if ( $registered_time < ( time() - 86400 ) ) {
692
- $time = date( 'Y/m/d\<\b\r \/\>H:i:s', bb_offset_time( $registered_time ) );
693
- } else {
694
- $time = sprintf( __( '%s ago' ), bb_since( $registered_time ) );
695
- }
696
-
697
- $r .= "\t\t<td>" . $time . "</td>\n";
698
-
699
- if (
700
- !isset($user->capabilities) ||
701
- !is_array($user->capabilities) ||
702
- empty($user->capabilities)
703
- ) {
704
- $role = array( __('Inactive (no role)') );
705
- } else {
706
- global $wp_roles;
707
- $_roles = $wp_roles->get_names();
708
- $role = array();
709
- foreach ( $user->capabilities as $cap => $cap_set ) {
710
- if (!$cap_set) {
711
- continue;
712
- }
713
- $role[] = $_roles[$cap];
714
- }
715
- if ( !count( $role ) ) {
716
- $role[] = __('None');
717
- }
718
- }
719
-
720
- $r .= "\t\t<td>" . join(', ', $role) . "</td>\n\t</tr>";
721
- return $r;
722
- }
723
-
724
- // BB_User_Search class
725
- // by Mark Jaquith
726
-
727
- class BB_User_Search {
728
- var $results;
729
- var $search_term;
730
- var $page;
731
- var $raw_page;
732
- var $users_per_page = 50;
733
- var $first_user;
734
- var $last_user;
735
- var $query_limit;
736
- var $total_users_for_query = 0;
737
- var $search_errors;
738
- var $paging_text;
739
- var $paging_text_bottom;
740
-
741
- function __construct($search_term = false, $page = 1, $roles = false ) { // constructor
742
- $this->search_term = $search_term ? stripslashes($search_term) : false;
743
- $this->raw_page = ( '' == $page ) ? false : (int) $page;
744
- $page = (int) $page;
745
- $this->page = $page < 2 ? 1 : $page;
746
- $roles = (array) $roles;
747
- $_roles = array();
748
- foreach ( $roles as $role ) {
749
- if ( false !== $role ) {
750
- $_roles[] = stripslashes( $role );
751
- }
752
- }
753
- $this->roles = empty( $_roles ) ? false : $_roles;
754
-
755
- $this->prepare_query();
756
- $this->query();
757
- $this->prepare_vars_for_template_usage();
758
- $this->do_paging();
759
- }
760
-
761
- function BB_User_Search( $search_term = false, $page = 1, $roles = false ) {
762
- $this->__construct( $search_term, $page, $roles );
763
- }
764
-
765
- function prepare_query() {
766
- $this->first_user = ($this->page - 1) * $this->users_per_page;
767
- }
768
-
769
- function query() {
770
- $users = bb_user_search( array(
771
- 'query' => $this->search_term,
772
- 'user_email' => true,
773
- 'users_per_page' => $this->users_per_page,
774
- 'page' => $this->page,
775
- 'roles' => $this->roles
776
- ) );
777
-
778
- if ( is_wp_error($users) )
779
- $this->search_errors = $users;
780
- else if ( $users )
781
- $this->results = $users;
782
- // foreach ( (array) $users as $user )
783
- // $this->results[] = $user->ID;
784
-
785
- if ( $this->results )
786
- $this->total_users_for_query = bb_count_last_query();
787
- elseif ( !is_wp_error($this->search_errors) )
788
- $this->search_errors = new WP_Error( 'no_matching_users_found', __( '<strong>No matching users were found!</strong>' ) );
789
-
790
- if ( is_wp_error( $this->search_errors ) )
791
- bb_admin_notice( $this->search_errors );
792
- }
793
-
794
- function prepare_vars_for_template_usage() {
795
- $this->search_term = stripslashes($this->search_term); // done with DB, from now on we want slashes gone
796
- }
797
-
798
- function do_paging() {
799
- global $bb_current_submenu;
800
- $displaying_num = sprintf(
801
- __( '%1$s to %2$s of %3$s' ),
802
- bb_number_format_i18n( ( $this->page - 1 ) * $this->users_per_page + 1 ),
803
- $this->page * $this->users_per_page < $this->total_users_for_query ? bb_number_format_i18n( $this->page * $this->users_per_page ) : '<span class="total-type-count">' . bb_number_format_i18n( $this->total_users_for_query ) . '</span>',
804
- '<span class="total-type-count">' . bb_number_format_i18n( $this->total_users_for_query ) . '</span>'
805
- );
806
- $page_number_links = $this->total_users_for_query > $this->users_per_page ? get_page_number_links( $this->page, $this->total_users_for_query, $this->users_per_page, false ) : '';
807
- $this->paging_text = "<div class='tablenav-pages'><span class='displaying-num'>$displaying_num</span><span class=\"displaying-pages\">$page_number_links</span><div class=\"clear\"></div></div>\n";
808
- $this->paging_text_bottom = "<div class='tablenav-pages'><span class=\"displaying-pages\">$page_number_links</span><div class=\"clear\"></div></div>\n";
809
- }
810
-
811
- function get_results() {
812
- return (array) $this->results;
813
- }
814
-
815
- function page_links() {
816
- echo $this->paging_text;
817
- }
818
-
819
- function results_are_paged() {
820
- if ( isset($this->paging_text) && $this->paging_text )
821
- return true;
822
- return false;
823
- }
824
-
825
- function is_search() {
826
- if ( $this->search_term )
827
- return true;
828
- return false;
829
- }
830
-
831
- function display( $show_search = true, $show_email = false ) {
832
- global $wp_roles;
833
-
834
- $r = '';
835
-
836
- if ( isset($this->title) )
837
- $title = $this->title;
838
- elseif ( $this->is_search() )
839
- $title = sprintf(__('Users Matching "%s" by Role'), esc_html( $this->search_term ));
840
-
841
- $h2_search = $this->search_term;
842
- $h2_role = $this->roles[0];
843
-
844
- $roles = $wp_roles->get_names();
845
- if ( in_array( $h2_role, array_keys( $roles ) ) ) {
846
- $h2_role = $roles[$h2_role];
847
- }
848
-
849
- $h2_search = $h2_search ? ' ' . sprintf( __('containing &#8220;%s&#8221;'), esc_html( $h2_search ) ) : '';
850
- $h2_role = $h2_role ? ' ' . sprintf( __('with role &#8220;%s&#8221;'), esc_html( $h2_role ) ) : '';
851
-
852
- $h2_span = '<span class="subtitle">';
853
- $h2_span .= apply_filters( 'bb_user_search_description', sprintf( __( '%1$s%2$s' ), $h2_search, $h2_role ), $h2_search, $h2_role, $this );
854
- $h2_span .= '</span>';
855
-
856
- echo "<h2 class=\"first\">" . apply_filters( 'bb_user_search_title', __('Users') ) . $h2_span . "</h2>\n";
857
- do_action( 'bb_admin_notices' );
858
-
859
- if ( $show_search ) {
860
- $roles = apply_filters( 'bb_user_search_form_roles', $wp_roles->get_names() );
861
-
862
- $r .= "<form action='' method='get' id='search' class='search-form'>\n";
863
- $r .= "<fieldset>\n";
864
- $r .= "<div>\n";
865
- $r .= "\t\t<label for='usersearch'>" . __('Search term') . "</label>";
866
- $r .= "\t\t<div><input type='text' name='usersearch' id='usersearch' class='text-input' value='" . esc_html( $this->search_term, 1) . "' /></div>\n";
867
- $r .= "</div>\n";
868
- $r .= "<div>\n";
869
- $r .= "\t\t<label for='userrole'>" . __('Role') . "</label>";
870
- $r .= "\t\t<div><select name='userrole[]' id='userrole'>\n";
871
- $r .= "\t\t\t<option value=''>" . _x( 'All', 'user roles' ) . "</option>\n";
872
-
873
- foreach ( $roles as $role => $display ) {
874
- $selected = '';
875
- if ( is_array( $this->roles ) && in_array( $role, $this->roles ) ) {
876
- $selected = ' selected="selected"';
877
- }
878
- $value = esc_attr($role);
879
- $display = esc_html(translate($display));
880
- $r .= "\t\t\t<option value='$value'$selected>$display</option>\n";
881
- }
882
-
883
- $r .= "\t\t</select></div>\n";
884
- $r .= "</div>\n";
885
-
886
- $r = apply_filters( 'bb_user_search_form_inputs', $r, $this );
887
-
888
- $r .= "<div class=\"submit\">\n";
889
- $r .= "\t\t<label class='hidden' for='submit'>" . __('Search') . "</label>";
890
- $r .= "\t\t<div><input type='submit' id='submit' class='button submit-input' value='" . __('Filter') . "' /></div>\n";
891
- $r .= "</div>\n";
892
- $r .= "</fieldset>\n";
893
- $r .= "</form>\n\n";
894
- }
895
-
896
- if ( $this->get_results() ) {
897
- if ( $this->results_are_paged() )
898
- $r .= "<div class='tablenav'>\n" . $this->paging_text . "</div><div class=\"clear\"></div>\n\n";
899
-
900
- //foreach($roleclasses as $role => $roleclass) {
901
- //ksort($roleclass);
902
- //if ( !empty($role) )
903
- // $r .= "\t\t<h3>{$wp_roles->role_names[$role]}</h3>\n";
904
- //else
905
- // $r .= "\t\t<h3><em>" . __('Users with no role in these forums') . "</h3>\n";
906
- $r .= "<table class='widefat'>\n";
907
- $r .= "<thead>\n";
908
- $r .= "\t<tr>\n";
909
- if ( $show_email ) {
910
- $r .= "\t\t<th style='width:30%;'>" . __('Username') . "</th>\n";
911
- $r .= "\t\t<th style='width:20%;'>" . __('Name') . "</th>\n";
912
- $r .= "\t\t<th style='width:20%;'>" . __('E-mail') . "</th>\n";
913
- } else {
914
- $r .= "\t\t<th style='width:40%;'>" . __('Username') . "</th>\n";
915
- $r .= "\t\t<th style='width:30%;'>" . __('Name') . "</th>\n";
916
- }
917
- $r .= "\t\t<th style='width:15%;'>" . __('Registered') . "</th>\n";
918
- $r .= "\t\t<th style='width:15%;'>" . __('Role') . "</th>\n";
919
- $r .= "\t</tr>\n";
920
- $r .= "</thead>\n\n";
921
- $r .= "<tfoot>\n";
922
- $r .= "\t<tr>\n";
923
- if ( $show_email ) {
924
- $r .= "\t\t<th style='width:30%;'>" . __('Username') . "</th>\n";
925
- $r .= "\t\t<th style='width:20%;'>" . __('Name') . "</th>\n";
926
- $r .= "\t\t<th style='width:20%;'>" . __('E-mail') . "</th>\n";
927
- } else {
928
- $r .= "\t\t<th style='width:40%;'>" . __('Username') . "</th>\n";
929
- $r .= "\t\t<th style='width:30%;'>" . __('Name') . "</th>\n";
930
- }
931
- $r .= "\t\t<th style='width:15%;'>" . __('Registered') . "</th>\n";
932
- $r .= "\t\t<th style='width:15%;'>" . __('Role') . "</th>\n";
933
- $r .= "\t</tr>\n";
934
- $r .= "</tfoot>\n\n";
935
-
936
- $r .= "<tbody id='role-$role'>\n";
937
- foreach ( (array) $this->get_results() as $user_object )
938
- $r .= bb_user_row($user_object, $role, $show_email);
939
- $r .= "</tbody>\n";
940
- $r .= "</table>\n\n";
941
- //}
942
-
943
- if ( $this->results_are_paged() )
944
- $r .= "<div class='tablenav bottom'>\n" . $this->paging_text_bottom . "</div><div class=\"clear\"></div>\n\n";
945
- }
946
- echo $r;
947
- }
948
-
949
- }
950
-
951
- class BB_Users_By_Role extends BB_User_Search {
952
- var $role = '';
953
- var $title = '';
954
-
955
- function __construct($role = '', $page = '') { // constructor
956
- $this->role = $role ? $role : 'member';
957
- $this->raw_page = ( '' == $page ) ? false : (int) $page;
958
- $this->page = (int) ( '' == $page ) ? 1 : $page;
959
-
960
- $this->prepare_query();
961
- $this->query();
962
- $this->do_paging();
963
- }
964
-
965
- function BB_Users_By_Role($role = '', $page = '') {
966
- $this->__construct($role, $page);
967
- }
968
-
969
- function query() {
970
- if ( $_results = bb_get_ids_by_role( $this->role, 0, $this->page, $this->users_per_page ) ) {
971
- $this->results = bb_get_user($_results);
972
- $this->total_users_for_query = bb_count_last_query();
973
- } else
974
- $this->search_errors = new WP_Error( 'no_matching_users_found', __( '<strong>No matching users were found!</strong>' ) );
975
-
976
- if ( is_wp_error( $this->search_errors ) )
977
- bb_admin_notice( $this->search_errors );
978
- }
979
- }
980
-
981
- /* Forums */
982
-
983
- // Expects forum_name, forum_desc to be pre-escaped
984
- function bb_new_forum( $args ) {
985
- global $bbdb;
986
- if ( !bb_current_user_can( 'manage_forums' ) )
987
- return false;
988
-
989
- $func_args = func_get_args();
990
- $defaults = array( 'forum_name' => '', 'forum_desc' => '', 'forum_parent' => 0, 'forum_order' => false, 'forum_is_category' => 0 );
991
- $args = wp_parse_args( $args, $defaults );
992
- if ( 1 < func_num_args() ) : // For back compat
993
- $args['forum_name'] = $func_args[0];
994
- $args['forum_desc'] = $func_args[1];
995
- $args['forum_order'] = 2 < func_num_args() ? $func_args[2] : 0;
996
- endif;
997
-
998
- extract($args, EXTR_SKIP);
999
-
1000
- if ( !is_numeric($forum_order) )
1001
- $forum_order = (int) $bbdb->get_var("SELECT MAX(forum_order) FROM $bbdb->forums") + 1;
1002
-
1003
- $forum_order = (int) $forum_order;
1004
- $forum_parent = (int) $forum_parent;
1005
- $forum_is_category = (int) $forum_is_category;
1006
-
1007
- $forum_name = apply_filters( 'bb_pre_forum_name', stripslashes( wp_specialchars_decode( $forum_name, ENT_QUOTES ) ) );
1008
- $forum_desc = apply_filters( 'bb_pre_forum_desc', stripslashes($forum_desc) );
1009
-
1010
- if ( strlen($forum_name) < 1 )
1011
- return false;
1012
-
1013
- $forum_sql = "SELECT forum_slug FROM $bbdb->forums WHERE forum_slug = %s";
1014
-
1015
- $forum_slug = $_forum_slug = bb_slug_sanitize($forum_name);
1016
- if ( strlen($_forum_slug) < 1 )
1017
- return false;
1018
-
1019
- while ( is_numeric($forum_slug) || $existing_slug = $bbdb->get_var( $bbdb->prepare( $forum_sql, $forum_slug ) ) )
1020
- $forum_slug = bb_slug_increment($_forum_slug, $existing_slug);
1021
-
1022
- $bbdb->insert( $bbdb->forums, compact( 'forum_name', 'forum_slug', 'forum_desc', 'forum_parent', 'forum_order' ) );
1023
- $forum_id = $bbdb->insert_id;
1024
- if ($forum_id && $forum_is_category)
1025
- bb_update_forummeta($forum_id, 'forum_is_category', $forum_is_category);
1026
- wp_cache_flush( 'bb_forums' );
1027
-
1028
- return $forum_id;
1029
- }
1030
-
1031
- // Expects forum_name, forum_desc to be pre-escaped
1032
- function bb_update_forum( $args ) {
1033
- global $bbdb;
1034
- if ( !bb_current_user_can( 'manage_forums' ) )
1035
- return false;
1036
-
1037
- $func_args = func_get_args();
1038
- $defaults = array( 'forum_id' => 0, 'forum_name' => '', 'forum_slug' => '', 'forum_desc' => '', 'forum_parent' => 0, 'forum_order' => 0, 'forum_is_category' => 0 );
1039
- $fields = array( 'forum_name', 'forum_desc', 'forum_parent', 'forum_order' );
1040
- $args = wp_parse_args( $args, $defaults );
1041
- if ( 1 < func_num_args() ) : // For back compat
1042
- $args['forum_id'] = $func_args[0];
1043
- $args['forum_name'] = $func_args[1];
1044
- $args['forum_desc'] = 2 < func_num_args() ? $func_args[2] : '';
1045
- $args['forum_order'] = 3 < func_num_args() && is_numeric($func_args[3]) ? $func_args[3] : 0;
1046
- endif;
1047
-
1048
- extract($args, EXTR_SKIP);
1049
-
1050
- if ( !$forum_id = (int) $forum_id )
1051
- return false;
1052
- if ( !$forum = bb_get_forum( $forum_id ) )
1053
- return false;
1054
- $forum_order = (int) $forum_order;
1055
- $forum_parent = (int) $forum_parent;
1056
- $forum_is_category = (int) $forum_is_category;
1057
-
1058
- $forum_name = apply_filters( 'bb_pre_forum_name', stripslashes( wp_specialchars_decode( $forum_name, ENT_QUOTES ) ), $forum_id );
1059
- $forum_desc = apply_filters( 'bb_pre_forum_desc', stripslashes($forum_desc), $forum_id );
1060
-
1061
- if ( strlen($forum_name) < 1 )
1062
- return false;
1063
-
1064
- // Slug is not changing, don't update it
1065
- if ( !$forum_slug || $forum_slug == $forum->forum_slug ) {
1066
- // [sic]
1067
- } else {
1068
- $forum_slug = $_forum_slug = bb_slug_sanitize($forum_slug);
1069
- if ( strlen($_forum_slug) < 1 )
1070
- return false;
1071
-
1072
- $forum_sql = "SELECT forum_slug FROM $bbdb->forums WHERE forum_slug = %s";
1073
-
1074
- while ( is_numeric($forum_slug) || $existing_slug = $bbdb->get_var( $bbdb->prepare( $forum_sql, $forum_slug ) ) )
1075
- $forum_slug = bb_slug_increment($_forum_slug, $existing_slug);
1076
-
1077
- $fields[] = 'forum_slug';
1078
- }
1079
-
1080
- wp_cache_delete( $forum_id, 'bb_forum' );
1081
- wp_cache_flush( 'bb_forums' );
1082
-
1083
- $update_result = $bbdb->update( $bbdb->forums, compact( $fields ), compact( 'forum_id' ) );
1084
-
1085
- if ($forum_is_category)
1086
- bb_update_forummeta($forum_id, 'forum_is_category', $forum_is_category);
1087
- else
1088
- bb_delete_forummeta($forum_id, 'forum_is_category');
1089
-
1090
- return $update_result;
1091
- }
1092
-
1093
- // When you delete a forum, you delete *everything*
1094
- // NOT bbdb::prepared
1095
- function bb_delete_forum( $forum_id ) {
1096
- global $bbdb;
1097
- if ( !bb_current_user_can( 'delete_forum', $forum_id ) )
1098
- return false;
1099
- if ( !$forum_id = (int) $forum_id )
1100
- return false;
1101
-
1102
- if ( !$forum = bb_get_forum( $forum_id ) )
1103
- return false;
1104
-
1105
- if ( $topic_ids = $bbdb->get_col( $bbdb->prepare( "SELECT topic_id FROM $bbdb->topics WHERE forum_id = %d", $forum_id ) ) ) {
1106
- foreach ($topic_ids as $topic_id) {
1107
- bb_remove_topic_tags( $topic_id );
1108
- }
1109
- $_topic_ids = join(',', array_map('intval', $topic_ids));
1110
- $bbdb->query("DELETE FROM $bbdb->posts WHERE topic_id IN ($_topic_ids) AND topic_id != 0");
1111
- $bbdb->query("DELETE FROM $bbdb->meta WHERE object_type = 'bb_topic' AND object_id IN ($_topic_ids)");
1112
- $bbdb->query( $bbdb->prepare( "DELETE FROM $bbdb->topics WHERE forum_id = %d", $forum_id ) );
1113
- }
1114
-
1115
- $bbdb->update( $bbdb->forums, array( 'forum_parent' => $forum->forum_parent ), array( 'forum_parent' => $forum_id ) );
1116
-
1117
- $return = $bbdb->query( $bbdb->prepare( "DELETE FROM $bbdb->forums WHERE forum_id = %d", $forum_id ) );
1118
-
1119
- wp_cache_flush( 'bb_post' );
1120
-
1121
- if ( $topic_ids )
1122
- foreach ( $topic_ids as $topic_id ) {
1123
- // should maybe just flush these groups instead
1124
- wp_cache_delete( $topic_id, 'bb_topic' );
1125
- wp_cache_delete( $topic_id, 'bb_thread' );
1126
- }
1127
-
1128
- wp_cache_delete( $forum_id, 'bb_forum' );
1129
- wp_cache_flush( 'bb_forums' );
1130
-
1131
- return $return;
1132
- }
1133
-
1134
- function bb_forum_row( $forum_id = 0, $echo = true, $close = false ) {
1135
- global $forum, $forums_count;
1136
- if ( $forum_id )
1137
- $_forum = bb_get_forum( $forum_id );
1138
- else
1139
- $_forum =& $forum;
1140
-
1141
- if ( !$_forum )
1142
- return;
1143
-
1144
- $description = get_forum_description( $_forum->forum_id );
1145
-
1146
- $r = '';
1147
- if ( $close )
1148
- $r .= "\t<li id='forum-$_forum->forum_id'" . get_alt_class( 'forum', 'forum clear list-block' ) . ">\n";
1149
- $r .= "\t\t<div class='list-block posrel'>\n";
1150
- $r .= "\t\t\t<div class=\"row-title\">" . get_forum_name( $_forum->forum_id ) . "</div>\n";
1151
- if ( $description )
1152
- $r .= "\t\t\t<p class=\"row-description\">" . get_forum_description( $_forum->forum_id ) . "</p>\n";
1153
- $r .= "\t\t\t<div class=\"row-actions\"><span>\n";
1154
- $r .= "\t\t\t\t<a class='edit' href='" . get_forum_link() . "'>" . __('View') . "</a>\n";
1155
- if ( bb_current_user_can( 'manage_forums' ) )
1156
- $r .= "\t\t\t\t| <a class='edit' href='" . esc_attr( bb_get_uri('bb-admin/forums.php', array('action' => 'edit', 'id' => $_forum->forum_id), BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN) ) . "'>" . __('Edit') . "</a>\n";
1157
- if ( bb_current_user_can( 'delete_forum', $_forum->forum_id ) && 1 < $forums_count )
1158
- $r .= "\t\t\t\t| <a class='delete' href='" . esc_attr( bb_get_uri('bb-admin/forums.php', array('action' => 'delete', 'id' => $_forum->forum_id), BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN) ) . "'>" . __('Delete') . "</a>\n";
1159
- $r .= "\t\t\t</span>&nbsp;</div>\n";
1160
- $r .= "\t\t</div>\n";
1161
- if ( $close )
1162
- $r .= "\t</li>\n";
1163
-
1164
- if ( $echo )
1165
- echo $r;
1166
- return $r;
1167
- }
1168
-
1169
- function bb_forum_form( $forum_id = 0 ) {
1170
- $forum_id = (int) $forum_id;
1171
- if ( $forum_id && !$forum = bb_get_forum( $forum_id ) ) {
1172
- return;
1173
- }
1174
-
1175
- $forum_name = '';
1176
- $forum_slug = '';
1177
- $forum_description = '';
1178
- $forum_position = '';
1179
-
1180
- if ( $forum_id ) {
1181
- $forum_name = get_forum_name( $forum_id );
1182
- $forum_slug = apply_filters('editable_slug', $forum->forum_slug);
1183
- $forum_description = get_forum_description( $forum_id );
1184
- $forum_position = get_forum_position( $forum_id );
1185
- $legend = __( 'Edit Forum' );
1186
- $submit = __( 'Save Changes' );
1187
- $action = 'update';
1188
- } else {
1189
- $legend = __( 'Add Forum' );
1190
- $submit = __( 'Add Forum' );
1191
- $action = 'add';
1192
- }
1193
-
1194
- $forum_options = array(
1195
- 'forum_name' => array(
1196
- 'title' => __( 'Name' ),
1197
- 'value' => $forum_name
1198
- ),
1199
- 'forum_slug' => array(
1200
- 'title' => __( 'Slug' ),
1201
- 'value' => $forum_slug
1202
- ),
1203
- 'forum_desc' => array(
1204
- 'title' => __( 'Description' ),
1205
- 'value' => $forum_description,
1206
- 'class' => 'long'
1207
- ),
1208
- 'forum_parent' => array(
1209
- 'title' => __( 'Parent' ),
1210
- 'type' => 'select',
1211
- 'options' => bb_get_forum_dropdown( array(
1212
- 'cut_branch' => $forum_id,
1213
- 'id' => 'forum_parent',
1214
- 'none' => true,
1215
- 'selected' => $forum_id ? get_forum_parent( $forum_id ) : 0,
1216
- 'disable_categories' => 0,
1217
- 'options_only' => true
1218
- ) )
1219
- ),
1220
- 'forum_order' => array(
1221
- 'title' => __( 'Position' ),
1222
- 'value' => $forum_position,
1223
- 'class' => 'short'
1224
- ),
1225
- 'forum_is_category' => array(
1226
- 'title' => __( 'Category' ),
1227
- 'type' => 'checkbox',
1228
- 'options' => array(
1229
- 1 => array(
1230
- 'label' => __( 'Make this forum a category' ),
1231
- 'value' => bb_get_forum_is_category( $forum_id ),
1232
- )
1233
- ),
1234
- 'note' => __( 'Categories are forums where new topics cannot be created. Categories usually contain a group of sub-forums.' )
1235
- )
1236
- );
1237
-
1238
- if ( !$forum_id ) {
1239
- unset( $forum_options['forum_slug'] );
1240
- unset( $forum_options['forum_order'] );
1241
- }
1242
-
1243
- ?>
1244
- <form class="settings" method="post" id="<?php echo $action; ?>-forum" action="<?php bb_uri('bb-admin/bb-forum.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>" class="add:forum-list: forum-form">
1245
- <fieldset>
1246
- <legend><?php echo $legend; ?></legend>
1247
- <?php
1248
- foreach ( $forum_options as $option => $args ) {
1249
- bb_option_form_element( $option, $args );
1250
- }
1251
- ?>
1252
- <fieldset class="submit">
1253
- <?php if ( $forum_id ) : ?>
1254
- <input type="hidden" name="forum_id" value="<?php echo $forum_id; ?>" />
1255
- <?php endif; ?>
1256
- <?php bb_nonce_field( 'order-forums', 'order-nonce' ); ?>
1257
- <?php bb_nonce_field( $action . '-forum' ); ?>
1258
- <input type="hidden" name="action" value="<?php echo $action; ?>" />
1259
- <input class="submit" type="submit" name="submit" value="<?php echo $submit; ?>" />
1260
- </fieldset>
1261
- </fieldset>
1262
- </form>
1263
- <?php
1264
- }
1265
-
1266
- class BB_Walker_ForumAdminlistitems extends BB_Walker {
1267
- var $tree_type = 'forum';
1268
- var $db_fields = array ('parent' => 'forum_parent', 'id' => 'forum_id'); //TODO: decouple this
1269
-
1270
- function start_lvl($output, $depth) {
1271
- $indent = str_repeat("\t", $depth) . ' ';
1272
- $output .= $indent . "<ul id='forum-root-$this->forum_id' class='list-block holder'>\n";
1273
- return $output;
1274
- }
1275
-
1276
- function end_lvl($output, $depth) {
1277
- $indent = str_repeat("\t", $depth) . ' ';
1278
- $output .= $indent . "</ul>\n";
1279
- return $output;
1280
- }
1281
-
1282
- function start_el($output, $forum, $depth) {
1283
- $this->forum_id = $forum->forum_id;
1284
- $indent = str_repeat("\t", $depth + 1);
1285
- $output .= $indent . "<li id='forum-$this->forum_id'" . get_alt_class( 'forum', 'forum clear list-block' ) . ">\n";
1286
-
1287
- return $output;
1288
- }
1289
-
1290
- function end_el($output, $forum, $depth) {
1291
- $indent = str_repeat("\t", $depth + 1);
1292
- $output .= $indent . "</li>\n";
1293
- return $output;
1294
- }
1295
- }
1296
-
1297
-
1298
-
1299
- /* Topics */
1300
-
1301
- function bb_move_forum_topics( $from_forum_id, $to_forum_id ) {
1302
- global $bbdb;
1303
-
1304
- $from_forum_id = (int) $from_forum_id ;
1305
- $to_forum_id = (int) $to_forum_id;
1306
-
1307
- add_filter('get_forum_where', 'bb_no_where'); // Just in case
1308
-
1309
- $from_forum = bb_get_forum( $from_forum_id );
1310
- if ( !$to_forum = bb_get_forum( $to_forum_id ) )
1311
- return false;
1312
-
1313
- $posts = $to_forum->posts + ( $from_forum ? $from_forum->posts : 0 );
1314
- $topics = $to_forum->topics + ( $from_forum ? $from_forum->topics : 0 );
1315
-
1316
- $bbdb->update( $bbdb->forums, compact( 'topics', 'posts' ), array( 'forum_id' => $to_forum_id ) );
1317
- $bbdb->update( $bbdb->forums, array( 'topics' => 0, 'posts' => 0 ), array( 'forum_id' => $from_forum_id ) );
1318
- $bbdb->update( $bbdb->posts, array( 'forum_id' => $to_forum_id ), array( 'forum_id' => $from_forum_id ) );
1319
- $topic_ids = $bbdb->get_col( $bbdb->prepare( "SELECT topic_id FROM $bbdb->topics WHERE forum_id = %d", $from_forum_id ) );
1320
- $return = $bbdb->update( $bbdb->topics, array( 'forum_id' => $to_forum_id ), array( 'forum_id' => $from_forum_id ) );
1321
-
1322
- wp_cache_flush( 'bb_post' );
1323
-
1324
- if ( $topic_ids )
1325
- foreach ( $topic_ids as $topic_id ) {
1326
- // should maybe just flush these groups
1327
- wp_cache_delete( $topic_id, 'bb_topic' );
1328
- wp_cache_delete( $topic_id, 'bb_thread' );
1329
- }
1330
-
1331
- wp_cache_delete( $from_forum_id, 'bb_forum' );
1332
- wp_cache_delete( $to_forum_id, 'bb_forum' );
1333
- wp_cache_flush( 'bb_forums' );
1334
-
1335
- return $return;
1336
- }
1337
-
1338
- /* Posts */
1339
-
1340
- function bb_admin_list_posts() {
1341
- global $bb_posts, $bb_post;
1342
-
1343
- if ( !$bb_posts ) {
1344
- ?>
1345
- <p class="no-results"><?php _e('No posts found.'); ?></p>
1346
- <?php
1347
- } else {
1348
- ?>
1349
- <table id="posts-list" class="widefat" cellspacing="0" cellpadding="0">
1350
- <thead>
1351
- <tr>
1352
- <th scope="col" class="check-column"><input type="checkbox" /></th>
1353
- <th scope="col"><?php _e( 'Post' ); ?></th>
1354
- <th scope="col"><?php _e( 'Author' ); ?></th>
1355
- <th scope="col"><?php _e( 'Topic' ); ?></th>
1356
- <th scope="col"><?php _e( 'Date' ); ?></th>
1357
- </tr>
1358
- </thead>
1359
- <tfoot>
1360
- <tr>
1361
- <th scope="col" class="check-column"><input type="checkbox" /></th>
1362
- <th scope="col"><?php _e( 'Post' ); ?></th>
1363
- <th scope="col"><?php _e( 'Author' ); ?></th>
1364
- <th scope="col"><?php _e( 'Topic' ); ?></th>
1365
- <th scope="col"><?php _e( 'Date' ); ?></th>
1366
- </tr>
1367
- </tfoot>
1368
- <tbody>
1369
- <?php
1370
- foreach ( $bb_posts as $bb_post ) {
1371
- ?>
1372
- <tr id="post-<?php post_id(); ?>"<?php alt_class('post', post_del_class()); ?>>
1373
- <td class="check-column"><input type="checkbox" name="post[]" value="<?php post_id(); ?>" /></td>
1374
- <td class="post">
1375
- <?php post_text(); ?>
1376
- <div>
1377
- <span class="row-actions">
1378
- <a href="<?php echo esc_url( get_post_link() ); ?>"><?php _e( 'View' ); ?></a>
1379
- <?php
1380
- bb_post_admin( array(
1381
- 'before_each' => ' | ',
1382
- 'each' => array(
1383
- 'undelete' => array(
1384
- 'before' => ' '
1385
- )
1386
- ),
1387
- 'last_each' => array(
1388
- 'before' => ' | '
1389
- )
1390
- ) );
1391
- ?>
1392
- </span>&nbsp;
1393
- </div>
1394
- </td>
1395
-
1396
- <td class="author">
1397
- <?php if ( get_post_author_id() ) : ?>
1398
-
1399
- <a href="<?php user_profile_link( get_post_author_id() ); ?>">
1400
- <?php post_author_avatar( '16' ); ?>
1401
- <?php post_author(); ?>
1402
- </a>
1403
-
1404
- <?php else : ?>
1405
-
1406
- <span>
1407
- <?php post_author_avatar( '16' ); ?>
1408
- <?php post_author(); ?>
1409
- </span>
1410
-
1411
- <?php endif; ?>
1412
- </td>
1413
-
1414
- <td class="topic">
1415
- <a href="<?php topic_link( $bb_post->topic_id ); ?>"><?php topic_title( $bb_post->topic_id ); ?></a>
1416
- </td>
1417
-
1418
- <td class="date">
1419
- <?php
1420
- if ( bb_get_post_time( 'U' ) < ( time() - 86400 ) ) {
1421
- bb_post_time( 'Y/m/d\<\b\r \/\>H:i:s' );
1422
- } else {
1423
- printf( __( '%s ago' ), bb_get_post_time( 'since' ) );
1424
- }
1425
- ?>
1426
- </td>
1427
- </tr>
1428
- <?php
1429
- }
1430
- ?>
1431
- </tbody>
1432
- </table>
1433
- <?php
1434
- }
1435
- }
1436
-
1437
- /* Recounts */
1438
-
1439
- function bb_recount_list()
1440
- {
1441
- global $recount_list;
1442
- $recount_list = array(
1443
- 5 => array( 'topic-posts', __( 'Count posts of every topic' ) ),
1444
- 6 => array( 'topic-voices', __( 'Count voices of every topic' ) ),
1445
- 10 => array( 'topic-deleted-posts', __( 'Count deleted posts on every topic' ) ),
1446
- 15 => array( 'forums', __( 'Count topics and posts in every forum' ) ),
1447
- 20 => array( 'topics-replied', __( 'Count topics to which each user has replied' ) ),
1448
- 25 => array( 'topic-tag-count', __( 'Count tags for every topic' ) ),
1449
- 30 => array( 'tags-tag-count', __( 'Count topics for every tag' ) ),
1450
- 35 => array( 'tags-delete-empty', __( 'Delete tags with no topics' ) ),
1451
- 40 => array( 'clean-favorites', __( 'Remove deleted topics from users\' favorites' ) )
1452
- );
1453
- do_action( 'bb_recount_list' );
1454
- ksort( $recount_list );
1455
- return $recount_list;
1456
- }
1457
-
1458
- /* Themes */
1459
-
1460
- function bb_get_current_theme_data( $property = 'all' ) {
1461
- if (!$property) {
1462
- $property = 'all';
1463
- }
1464
- $directory = bb_get_active_theme_directory();
1465
- $stylesheet = $directory . 'style.css';
1466
- if (file_exists($stylesheet)) {
1467
- $data = bb_get_theme_data($stylesheet);
1468
- }
1469
- if ($property == 'all') {
1470
- return $data;
1471
- } elseif (isset($data[$property])) {
1472
- return $data[$property];
1473
- } else {
1474
- return false;
1475
- }
1476
- }
1477
-
1478
- // Output sanitized for display
1479
- function bb_get_theme_data( $theme_file )
1480
- {
1481
- if ( strpos($theme_file, '#') !== false ) {
1482
- $theme_file = bb_get_theme_directory( $theme_file ) . 'style.css';
1483
- }
1484
- $theme_code = implode( '', file( $theme_file ) );
1485
- $theme_code = str_replace ( '\r', '\n', $theme_code );
1486
- // Grab just the first commented area from the file
1487
- preg_match( '|/\*(.*)\*/|msU', $theme_code, $theme_block );
1488
- $theme_data = trim( $theme_block[1] );
1489
- preg_match( '|Theme Name:(.*)|i', $theme_data, $theme_name );
1490
- preg_match( '|Theme URI:(.*)|i', $theme_data, $theme_uri );
1491
- preg_match( '|Description:(.*)|i', $theme_data, $description );
1492
- preg_match( '|Author:(.*)|i', $theme_data, $author_name );
1493
- preg_match( '|Author URI:(.*)|i', $theme_data, $author_uri );
1494
- preg_match( '|Ported By:(.*)|i', $theme_data, $porter_name );
1495
- preg_match( '|Porter URI:(.*)|i', $theme_data, $porter_uri );
1496
- // preg_match( '|Template:(.*)|i', $theme_data, $template );
1497
- if ( preg_match( '|Version:(.*)|i', $theme_data, $version ) )
1498
- $version = esc_html( trim( $version[1] ) );
1499
- else
1500
- $version ='';
1501
- if ( preg_match('|Status:(.*)|i', $theme_data, $status) )
1502
- $status = esc_html( trim($status[1]) );
1503
- else
1504
- $status = 'publish';
1505
-
1506
- $description = trim($description[1]);
1507
- $description = bb_encode_bad( $description );
1508
- $description = bb_code_trick( $description );
1509
- $description = force_balance_tags( $description );
1510
- $description = bb_filter_kses( $description );
1511
- $description = bb_autop( $description );
1512
-
1513
- $name = $theme_name[1];
1514
- $name = esc_html( trim($name) );
1515
- $theme = $name;
1516
-
1517
- if ( $author_name || $author_uri ) {
1518
- if ( empty($author_uri[1]) ) {
1519
- $author = bb_filter_kses( trim($author_name[1]) );
1520
- } else {
1521
- $author = '<a href="' . esc_url( trim($author_uri[1]) ) . '" title="' . esc_attr__( 'Visit author homepage' ) . '">' . bb_filter_kses( trim($author_name[1]) ) . '</a>';
1522
- }
1523
- } else {
1524
- $author = '';
1525
- }
1526
-
1527
- if ( $porter_name || $porter_uri ) {
1528
- if ( empty($porter_uri[1]) ) {
1529
- $porter = bb_filter_kses( trim($porter_name[1]) );
1530
- } else {
1531
- $porter = '<a href="' . esc_url( trim($porter_uri[1]) ) . '" title="' . esc_attr__( 'Visit porter homepage' ) . '">' . bb_filter_kses( trim($porter_name[1]) ) . '</a>';
1532
- }
1533
- } else {
1534
- $porter = '';
1535
- }
1536
-
1537
- global $bb;
1538
-
1539
- // Normalise the path to the theme
1540
- $theme_file = str_replace( '\\', '/', $theme_file );
1541
-
1542
- foreach ( $bb->theme_locations as $_name => $_data ) {
1543
- $_directory = str_replace( '\\', '/', $_data['dir'] );
1544
- if ( 0 === strpos( $theme_file, $_directory ) ) {
1545
- $location = $_name;
1546
- break;
1547
- }
1548
- }
1549
-
1550
- return array(
1551
- 'Location' => $location,
1552
- 'Name' => $name,
1553
- 'Title' => $theme,
1554
- 'Description' => $description,
1555
- 'Author' => $author,
1556
- 'Porter' => $porter,
1557
- 'Version' => $version,
1558
- // 'Template' => $template[1],
1559
- 'Status' => $status,
1560
- 'URI' => esc_url( $theme_uri[1] )
1561
- );
1562
- }
1563
-
1564
- if ( !function_exists( 'checked' ) ) :
1565
- function checked( $checked, $current) {
1566
- if ( $checked == $current)
1567
- echo ' checked="checked"';
1568
- }
1569
- endif;
1570
-
1571
- if ( !function_exists( 'selected' ) ) :
1572
- function selected( $selected, $current) {
1573
- if ( $selected === $current)
1574
- echo ' selected="selected"';
1575
- }
1576
- endif;
1577
-
1578
- /* Options */
1579
-
1580
- function bb_option_form_element( $name = 'name', $args = null ) {
1581
- global $bb_hardcoded;
1582
-
1583
- $defaults = array(
1584
- 'title' => 'title',
1585
- 'type' => 'text',
1586
- 'value' => false,
1587
- 'options' => false,
1588
- 'message' => false,
1589
- 'class' => false,
1590
- 'default' => false,
1591
- 'before' => '',
1592
- 'after' => '',
1593
- 'note' => false,
1594
- 'attributes' => false,
1595
- 'disabled' => false,
1596
- );
1597
-
1598
- $args = wp_parse_args( $args, $defaults );
1599
-
1600
- $id = str_replace( array( '_', '[', ']' ), array( '-', '-', '' ), $name );
1601
- if ( false !== strpos( $name, '[' ) ) {
1602
- list( $option_name, $option_key ) = preg_split( '/[\[\]]/', $name, -1, PREG_SPLIT_NO_EMPTY );
1603
- $option = bb_get_option( $option_name );
1604
- $value = false === $args['value'] ? esc_attr( $option[$option_key] ) : esc_attr( $args['value'] );
1605
- $hardcoded = isset( $bb_hardcoded[$option_name][$option_key] );
1606
- } else {
1607
- $value = false === $args['value'] ? bb_get_form_option( $name ) : esc_attr( $args['value'] );
1608
- $hardcoded = isset( $bb_hardcoded[$name] );
1609
- }
1610
-
1611
- $class = $args['class'] ? (array) $args['class'] : array();
1612
- array_unshift( $class, $args['type'] );
1613
-
1614
- if ( $hardcoded || $args['disabled'] )
1615
- $disabled = ' disabled="disabled"';
1616
- else
1617
- $disabled = false;
1618
-
1619
- if ( $args['attributes'] ) {
1620
- $attributes = array();
1621
- foreach ( $args['attributes'] as $k => $v )
1622
- $attributes[] = "$k='$v'";
1623
- $attributes = ' ' . join( ' ', $attributes );
1624
- } else {
1625
- $attributes = '';
1626
- }
1627
-
1628
- ?>
1629
-
1630
- <div id="option-<?php echo $id; ?>"<?php if ( !empty( $disabled ) ) echo ' class="disabled"'; ?>>
1631
- <?php
1632
- switch ( $args['type'] ) {
1633
- case 'radio' :
1634
- case 'checkbox' :
1635
- case 'message' :
1636
- ?>
1637
- <div class="label">
1638
- <?php echo $args['title']; ?>
1639
- </div>
1640
-
1641
- <?php
1642
- break;
1643
- case 'select' :
1644
- default :
1645
- ?>
1646
- <label for="<?php echo $id; ?>">
1647
- <?php echo $args['title']; ?>
1648
- </label>
1649
-
1650
- <?php
1651
- break;
1652
- }
1653
- ?>
1654
- <div class="inputs">
1655
-
1656
- <?php
1657
- if ( $args['before'] ) {
1658
- echo '<span class="before">' . $args['before'] . '</span>';
1659
- }
1660
- switch ( $args['type'] ) {
1661
- case 'select' :
1662
- echo "<select$disabled class='" . join( ' ', $class ) . "' name='$name' id='$id'$attributes>\n";
1663
- if ( is_array( $args['options'] ) ) {
1664
- foreach ( $args['options'] as $option => $label )
1665
- echo "\t<option value='$option'" . ( $value == $option ? " selected='selected'" : '' ) . ">$label</option>\n";
1666
- } elseif ( is_string( $args['options'] ) ) {
1667
- echo $args['options'] . "\n";
1668
- }
1669
- echo "</select>\n";
1670
- break;
1671
- case 'radio' :
1672
- case 'checkbox' :
1673
- if ( is_array( $args['options'] ) ) {
1674
- $_id = 0;
1675
- if ( 'radio' === $args['type'] && !in_array( $value, array_keys( $args['options'] ) ) && empty( $value ) ) {
1676
- $use_first_value = true;
1677
- }
1678
- $type = $args['type'];
1679
- foreach ( $args['options'] as $option => $label ) {
1680
- if ( $use_first_value ) {
1681
- $use_first_value = false;
1682
- $value = $option;
1683
- }
1684
- if ( is_array( $label ) ) {
1685
- if ( isset( $label['attributes'] ) ) {
1686
- $attributes = array();
1687
- foreach ( $label['attributes'] as $k => $v )
1688
- $attributes[] = "$k='$v'";
1689
- $attributes = ' ' . join( ' ', $attributes );
1690
- } else {
1691
- $attributes = '';
1692
- }
1693
- if ( isset( $label['name'] ) ) {
1694
- $name = $label['name'];
1695
- $id = str_replace( array( '_', '[', ']' ), array( '-', '-', '' ), $name );
1696
- $hardcoded = isset( $bb_hardcoded[$name] );
1697
- }
1698
- if ( isset( $label['value'] ) ) {
1699
- $_value = $label['value'];
1700
- } else {
1701
- $_value = $args['value'];
1702
- }
1703
- $value = false === $_value ? bb_get_form_option( $name ) : esc_attr( $_value );
1704
- $label = $label['label'];
1705
- }
1706
- echo "<label class=\"{$type}s\"><input$disabled type='$type' class='" . join( ' ', $class ) . "' name='$name' id='$id-$_id' value='$option'" . ( $value == $option ? " checked='checked'" : '' ) . "{$attributes} /> $label</label>\n";
1707
- $_id++;
1708
- }
1709
- } elseif ( is_string( $args['options'] ) ) {
1710
- echo $args['options'] . "\n";
1711
- }
1712
- break;
1713
- case 'message' :
1714
- if ( $args['message'] ) {
1715
- echo $args['message'];
1716
- }
1717
- break;
1718
- default :
1719
- echo "<input$disabled type='$args[type]' class='" . join( ' ', $class ) . "' name='$name' id='$id' value='$value'$attributes />\n";
1720
- break;
1721
- }
1722
- if ( $args['after'] ) {
1723
- echo '<span class="after">' . $args['after'] . '</span>';
1724
- }
1725
-
1726
- if ( $args['note'] ) {
1727
- foreach ( (array) $args['note'] as $note ) {
1728
- ?>
1729
-
1730
- <p><?php echo $note; ?></p>
1731
-
1732
- <?php
1733
- }
1734
- }
1735
- ?>
1736
-
1737
- </div>
1738
- </div>
1739
-
1740
- <?php
1741
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/includes/functions.bb-plugin.php DELETED
@@ -1,441 +0,0 @@
1
- <?php
2
-
3
- function bb_get_plugins_callback( $type = 'normal', $path, $filename )
4
- {
5
- if ( '.php' != substr( $filename, -4 ) ) {
6
- return false;
7
- }
8
-
9
- $data = array( 'autoload' => 0 );
10
-
11
- if ( $has_underscore = '_' === substr( $filename, 0, 1 ) ) {
12
- switch ( $type ) {
13
- case 'all':
14
- case 'autoload':
15
- $data['autoload'] = 1;
16
- break;
17
- case 'normal':
18
- default:
19
- return false;
20
- break;
21
- }
22
- } elseif ( 'autoload' === $type ) {
23
- return false;
24
- }
25
-
26
- if ( $_data = bb_get_plugin_data( $path ) ) {
27
- return array_merge( $_data , $data );
28
- }
29
-
30
- return false;
31
- }
32
-
33
- function bb_get_plugins( $location = 'all', $type = 'normal', $status = 'all' )
34
- {
35
- static $plugin_cache = array();
36
-
37
- if ( !in_array( $type, array( 'all', 'autoload', 'normal' ) ) ) {
38
- $type = 'normal';
39
- }
40
-
41
- if ( 'autoload' === $type || !in_array( $status, array( 'all', 'active', 'inactive' ) ) ) {
42
- $status = 'all';
43
- }
44
-
45
- if ( isset( $plugin_cache[$location][$type][$status] ) ) {
46
- return $plugin_cache[$location][$type][$status];
47
- }
48
-
49
- global $bb;
50
- $directories = array();
51
- if ( 'all' === $location ) {
52
- foreach ( $bb->plugin_locations as $_data ) {
53
- $directories[] = $_data['dir'];
54
- }
55
- } elseif ( isset( $bb->plugin_locations[$location]['dir'] ) ) {
56
- $directories[] = $bb->plugin_locations[$location]['dir'];
57
- }
58
-
59
- require_once( BB_PATH . BB_INC . 'class.bb-dir-map.php' );
60
-
61
- $plugin_arrays = array();
62
- foreach ( $directories as $directory ) {
63
- $dir_map = new BB_Dir_Map(
64
- $directory,
65
- array(
66
- 'callback' => 'bb_get_plugins_callback',
67
- 'callback_args' => array( $type ),
68
- 'recurse' => 1
69
- )
70
- );
71
- $dir_plugins = $dir_map->get_results();
72
- $dir_plugins = is_wp_error( $dir_plugins ) ? array() : $dir_plugins;
73
- $plugin_arrays[] = $dir_plugins;
74
- unset($dir_map, $dir_plugins);
75
- }
76
-
77
- $plugins = array();
78
- foreach ($plugin_arrays as $plugin_array) {
79
- $plugins = array_merge($plugins, $plugin_array);
80
- }
81
-
82
- $active_plugins = (array) bb_get_option( 'active_plugins' );
83
-
84
- $adjusted_plugins = array();
85
- foreach ($plugins as $plugin => $plugin_data) {
86
- $_id = $plugin_data['location'] . '#' . $plugin;
87
- $plugin_data['active'] = 0;
88
- if ( 'autoload' === $type || in_array( $_id, $active_plugins ) ) {
89
- $plugin_data['active'] = 1;
90
- }
91
- if (
92
- 'active' === $status && $plugin_data['active'] ||
93
- 'inactive' === $status && !$plugin_data['active'] ||
94
- 'all' === $status
95
- ) {
96
- $adjusted_plugins[$_id] = $plugin_data;
97
- }
98
- }
99
-
100
- uasort( $adjusted_plugins, 'bb_plugins_sort' );
101
-
102
- $plugin_cache[$location][$type][$status] = $adjusted_plugins;
103
-
104
- return $adjusted_plugins;
105
- }
106
-
107
- function bb_plugins_sort( $a, $b )
108
- {
109
- return strnatcasecmp( $a['name'], $b['name'] );
110
- }
111
-
112
- function bb_get_plugin_counts()
113
- {
114
- $all_plugins = bb_get_plugins( 'all', 'all' );
115
- $active_plugins = (array) bb_get_option( 'active_plugins' );
116
- $counts = array(
117
- 'plugin_count_all' => count( $all_plugins ),
118
- 'plugin_count_active' => count( $active_plugins ),
119
- 'plugin_count_inactive' => 0,
120
- 'plugin_count_autoload' => 0
121
- );
122
- foreach ( $all_plugins as $id => $all_plugin ) {
123
- if ( $all_plugin['autoload'] ) {
124
- $counts['plugin_count_autoload']++;
125
- } elseif ( !in_array( $id, $active_plugins ) ) {
126
- $counts['plugin_count_inactive']++;
127
- }
128
- }
129
- return $counts;
130
- }
131
-
132
- /**
133
- * Parse the plugin contents to retrieve plugin's metadata.
134
- *
135
- * The metadata of the plugin's data searches for the following in the plugin's
136
- * header. All plugin data must be on its own line. For plugin description, it
137
- * must not have any newlines or only parts of the description will be displayed
138
- * and the same goes for the plugin data. The below is formatted for printing.
139
- *
140
- * <code>
141
- * /*
142
- * Plugin Name: Name of Plugin
143
- * Plugin URI: Link to plugin information
144
- * Description: Plugin Description
145
- * Author: Plugin author's name
146
- * Author URI: Link to the author's web site
147
- * Version: Must be set
148
- * Requires at least: Optional. Minimum bbPress version this plugin requires
149
- * Tested up to: Optional. Maximum bbPress version this plugin has been tested with
150
- * Text Domain: Optional. Unique identifier, should be same as the one used in
151
- * bb_load_plugin_textdomain()
152
- * Domain Path: Optional. Only useful if the translations are located in a
153
- * folder above the plugin's base path. For example, if .mo files are
154
- * located in the locale folder then Domain Path will be "/locale/" and
155
- * must have the first slash. Defaults to the base folder the plugin is
156
- * located in.
157
- * * / # You must remove the space to close comment (the space is here only for documentation purposes).
158
- * </code>
159
- *
160
- * Plugin data returned array contains the following:
161
- * 'location' - Location of plugin file
162
- * 'name' - Name of the plugin, must be unique.
163
- * 'uri' - Plugin's web site.
164
- * 'plugin_link' - Title of plugin linked to plugin's web site.
165
- * 'description' - Description of what the plugin does and/or notes
166
- * from the author.
167
- * 'author' - The author's name
168
- * 'author_uri' - The author's web site address.
169
- * 'author_link' - The author's name linked to the author's web site.
170
- * 'version' - The plugin version number.
171
- * 'requires' - Minimum bbPress version plugin requires
172
- * 'tested' - Maximum bbPress version plugin has been tested with
173
- * 'text_domain' - Plugin's text domain for localization.
174
- * 'domain_path' - Plugin's relative directory path to .mo files.
175
- *
176
- * Some users have issues with opening large files and manipulating the contents
177
- * for want is usually the first 1kiB or 2kiB. This function stops pulling in
178
- * the plugin contents when it has all of the required plugin data.
179
- *
180
- * The first 8kiB of the file will be pulled in and if the plugin data is not
181
- * within that first 8kiB, then the plugin author should correct their plugin
182
- * and move the plugin data headers to the top.
183
- *
184
- * The plugin file is assumed to have permissions to allow for scripts to read
185
- * the file. This is not checked however and the file is only opened for
186
- * reading.
187
- *
188
- * @link http://trac.wordpress.org/ticket/5651 Previous Optimizations.
189
- * @link http://trac.wordpress.org/ticket/7372 Further and better Optimizations.
190
- * @since 1.5.0
191
- *
192
- * @param string $plugin_file Path to the plugin file
193
- * @param bool $markup If the returned data should have HTML markup applied
194
- * @param bool $translate If the returned data should be translated
195
- * @return array See above for description.
196
- */
197
- function bb_get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
198
- global $bb;
199
-
200
- if ( preg_match( '/^([a-z0-9_-]+)#((?:[a-z0-9\/\\_-]+.)+)(php)$/i', $plugin_file, $_matches ) ) {
201
- $plugin_file = $bb->plugin_locations[$_matches[1]]['dir'] . $_matches[2] . $_matches[3];
202
-
203
- $_directory = $bb->plugin_locations[$_matches[1]]['dir'];
204
- $_plugin = $_matches[2] . $_matches[3];
205
-
206
- if ( !$_plugin ) {
207
- // Not likely
208
- return false;
209
- }
210
-
211
- if ( validate_file( $_plugin ) ) {
212
- // $plugin has .., :, etc.
213
- return false;
214
- }
215
-
216
- $plugin_file = $_directory . $_plugin;
217
- unset( $_matches, $_directory, $_plugin );
218
- }
219
-
220
- if ( !file_exists( $plugin_file ) ) {
221
- // The plugin isn't there
222
- return false;
223
- }
224
-
225
- // We don't need to write to the file, so just open for reading.
226
- $fp = fopen($plugin_file, 'r');
227
-
228
- // Pull only the first 8kiB of the file in.
229
- $plugin_code = fread( $fp, 8192 );
230
-
231
- // PHP will close file handle, but we are good citizens.
232
- fclose($fp);
233
-
234
- // Grab just the first commented area from the file
235
- if ( !preg_match( '|/\*(.*?Plugin Name:.*?)\*/|ims', $plugin_code, $plugin_block ) )
236
- return false;
237
- $plugin_data = trim( $plugin_block[1] );
238
-
239
- preg_match( '|Plugin Name:(.*)$|mi', $plugin_data, $name );
240
- preg_match( '|Plugin URI:(.*)$|mi', $plugin_data, $uri );
241
- preg_match( '|Version:(.*)|i', $plugin_data, $version );
242
- preg_match( '|Description:(.*)$|mi', $plugin_data, $description );
243
- preg_match( '|Author:(.*)$|mi', $plugin_data, $author );
244
- preg_match( '|Author URI:(.*)$|mi', $plugin_data, $author_uri );
245
- preg_match( '|Text Domain:(.*)$|mi', $plugin_data, $text_domain );
246
- preg_match( '|Domain Path:(.*)$|mi', $plugin_data, $domain_path );
247
- preg_match( '|Requires at least:(.*)$|mi', $plugin_data, $requires );
248
- preg_match( '|Tested up to:(.*)$|mi', $plugin_data, $tested );
249
-
250
- // Normalise the path to the plugin
251
- $plugin_file = str_replace( '\\', '/', $plugin_file );
252
-
253
- foreach ( $bb->plugin_locations as $_name => $_data ) {
254
- $_directory = str_replace( '\\', '/', $_data['dir'] );
255
- if ( 0 === strpos( $plugin_file, $_directory ) ) {
256
- $location = array( 1 => $_name );
257
- break;
258
- }
259
- }
260
-
261
- $plugins_allowedtags = array('a' => array('href' => array(),'title' => array()),'abbr' => array('title' => array()),'acronym' => array('title' => array()),'code' => array(),'em' => array(),'strong' => array());
262
-
263
- $fields = array(
264
- 'location' => '',
265
- 'name' => 'html',
266
- 'uri' => 'url',
267
- 'version' => 'text',
268
- 'description' => 'html',
269
- 'author' => 'html',
270
- 'author_uri' => 'url',
271
- 'text_domain' => '',
272
- 'domain_path' => '',
273
- 'requires' => 'text',
274
- 'tested' => 'text',
275
- );
276
- foreach ( $fields as $field => $san ) {
277
- if ( !empty( ${$field} ) ) {
278
- ${$field} = trim(${$field}[1]);
279
- switch ( $san ) {
280
- case 'html' :
281
- ${$field} = bb_filter_kses( ${$field} );
282
- break;
283
- case 'text' :
284
- ${$field} = esc_html( ${$field} );
285
- break;
286
- case 'url' :
287
- ${$field} = esc_url( ${$field} );
288
- break;
289
- }
290
- } else {
291
- ${$field} = '';
292
- }
293
- }
294
-
295
- $plugin_data = compact( array_keys( $fields ) );
296
-
297
- if ( $translate )
298
- $plugin_data = _bb_get_plugin_data_translate( $plugin_data, $plugin_file );
299
-
300
- if ( $markup )
301
- $plugin_data['description'] = bb_autop( preg_replace( '/[\r\n]+/', "\n", trim( $plugin_data['description'] ) ) );
302
-
303
- $plugin_data['plugin_link'] = ( $plugin_data['uri'] ) ?
304
- "<a href='{$plugin_data['uri']}' title='" . esc_attr__( 'Visit plugin site' ) . "'>{$plugin_data['name']}</a>" :
305
- $plugin_data['name'];
306
- $plugin_data['author_link'] = ( $plugin_data['author'] && $plugin_data['author_uri'] ) ?
307
- "<a href='{$plugin_data['author_uri']}' title='" . esc_attr__( 'Visit author homepage' ) . "'>{$plugin_data['author']}</a>" :
308
- $plugin_data['author'];
309
-
310
- return $plugin_data;
311
- }
312
-
313
- function _bb_get_plugin_data_translate( $plugin_data, $plugin_file ) {
314
- //Translate fields
315
- if( !empty($plugin_data['text_domain']) ) {
316
- if( ! empty( $plugin_data['domain_path'] ) )
317
- bb_load_plugin_textdomain($plugin_data['text_domain'], dirname($plugin_file). $plugin_data['domain_path']);
318
- else
319
- bb_load_plugin_textdomain($plugin_data['text_domain'], dirname($plugin_file));
320
-
321
- foreach ( array('name', 'plugin_url', 'description', 'author', 'author_uri', 'version') as $field )
322
- $plugin_data[$field] = translate($plugin_data[$field], $plugin_data['text_domain']);
323
- }
324
-
325
- return $plugin_data;
326
- }
327
-
328
- /**
329
- * Attempts activation of plugin in a "sandbox" and redirects on success.
330
- *
331
- * A plugin that is already activated will not attempt to be activated again.
332
- *
333
- * The way it works is by setting the redirection to the error before trying to
334
- * include the plugin file. If the plugin fails, then the redirection will not
335
- * be overwritten with the success message. Also, the options will not be
336
- * updated and the activation hook will not be called on plugin error.
337
- *
338
- * It should be noted that in no way the below code will actually prevent errors
339
- * within the file. The code should not be used elsewhere to replicate the
340
- * "sandbox", which uses redirection to work.
341
- *
342
- * If any errors are found or text is outputted, then it will be captured to
343
- * ensure that the success redirection will update the error redirection.
344
- *
345
- * @since 1.0
346
- *
347
- * @param string $plugin Plugin path to main plugin file with plugin data.
348
- * @param string $redirect Optional. URL to redirect to.
349
- * @return WP_Error|null WP_Error on invalid file or null on success.
350
- */
351
- function bb_activate_plugin( $plugin, $redirect = '' ) {
352
- $active_plugins = (array) bb_get_option( 'active_plugins' );
353
- $plugin = bb_plugin_basename( trim( $plugin ) );
354
-
355
- $valid_path = bb_validate_plugin( $plugin );
356
- if ( is_wp_error( $valid_path ) )
357
- return $valid_path;
358
-
359
- if ( in_array( $plugin, $active_plugins ) ) {
360
- return false;
361
- }
362
-
363
- if ( !empty( $redirect ) ) {
364
- // We'll override this later if the plugin can be included without fatal error
365
- wp_redirect( add_query_arg( '_scrape_nonce', bb_create_nonce( 'scrape-plugin_' . $plugin ), $redirect ) );
366
- }
367
-
368
- ob_start();
369
- @include( $valid_path );
370
- // Add to the active plugins array
371
- $active_plugins[] = $plugin;
372
- ksort( $active_plugins );
373
- bb_update_option( 'active_plugins', $active_plugins );
374
- do_action( 'bb_activate_plugin_' . $plugin );
375
- ob_end_clean();
376
-
377
- return $valid_path;
378
- }
379
-
380
- /**
381
- * Deactivate a single plugin or multiple plugins.
382
- *
383
- * The deactivation hook is disabled by the plugin upgrader by using the $silent
384
- * parameter.
385
- *
386
- * @since unknown
387
- *
388
- * @param string|array $plugins Single plugin or list of plugins to deactivate.
389
- * @param bool $silent Optional, default is false. Prevent calling deactivate hook.
390
- */
391
- function bb_deactivate_plugins( $plugins, $silent = false ) {
392
- $active_plugins = (array) bb_get_option( 'active_plugins' );
393
-
394
- if ( !is_array( $plugins ) ) {
395
- $plugins = array( $plugins );
396
- }
397
-
398
- foreach ( $plugins as $plugin ) {
399
- $plugin = bb_plugin_basename( trim( $plugin ) );
400
- if ( !in_array( $plugin, $active_plugins ) ) {
401
- continue;
402
- }
403
- // Remove the deactivated plugin
404
- array_splice( $active_plugins, array_search( $plugin, $active_plugins ), 1 );
405
- if ( !$silent ) {
406
- do_action( 'bb_deactivate_plugin_' . $plugin );
407
- }
408
- }
409
-
410
- bb_update_option( 'active_plugins', $active_plugins );
411
- }
412
-
413
- /**
414
- * Validate the plugin path.
415
- *
416
- * Checks that the file exists and is valid file.
417
- *
418
- * @since 1.0
419
- * @uses validate_file() to check the passed plugin identifier isn't malformed
420
- * @uses bb_get_plugin_path() to get the full path of the plugin
421
- * @uses bb_get_plugins() to get the plugins that actually exist
422
- *
423
- * @param string $plugin Plugin Path
424
- * @param string $location The location of plugin, one of 'user', 'core' or 'all'
425
- * @param string $type The type of plugin, one of 'all', 'autoload' or 'normal'
426
- * @return WP_Error|int 0 on success, WP_Error on failure.
427
- */
428
- function bb_validate_plugin( $plugin, $location = 'all', $type = 'all' ) {
429
- if ( validate_file( trim( $plugin ) ) ) {
430
- return new WP_Error( 'plugin_invalid', __( 'Invalid plugin path.' ) );
431
- }
432
- $path = bb_get_plugin_path( trim( $plugin ) );
433
- if ( !file_exists( $path ) ) {
434
- return new WP_Error( 'plugin_not_found', __( 'Plugin file does not exist.' ) );
435
- }
436
- if ( !in_array( trim( $plugin ), array_keys( bb_get_plugins( $location, $type ) ) ) ) {
437
- return new WP_Error( 'plugin_not_available', __( 'That type of plugin is not available in the specified location.' ) );
438
- }
439
-
440
- return $path;
441
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/includes/functions.bb-recount.php DELETED
@@ -1,461 +0,0 @@
1
- <?php
2
-
3
- function bb_recount_topic_posts()
4
- {
5
- global $bbdb;
6
-
7
- $statement = __( 'Counting the number of posts in each topic&hellip; %s' );
8
- $result = __( 'Failed!' );
9
-
10
- $sql = "INSERT INTO `$bbdb->topics` (`topic_id`, `topic_posts`) (SELECT `topic_id`, COUNT(`post_status`) as `topic_posts` FROM `$bbdb->posts` WHERE `post_status` = '0' GROUP BY `topic_id`) ON DUPLICATE KEY UPDATE `topic_posts` = VALUES(`topic_posts`);";
11
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
12
- return array( 1, sprintf( $statement, $result ) );
13
- }
14
-
15
- $result = __( 'Complete!' );
16
- return array( 0, sprintf( $statement, $result ) );
17
- }
18
-
19
- function bb_recount_topic_voices()
20
- {
21
- global $bbdb;
22
-
23
- $statement = __( 'Counting the number of voices in each topic&hellip; %s' );
24
- $result = __( 'Failed!' );
25
-
26
- $sql_delete = "DELETE FROM `$bbdb->meta` WHERE `object_type` = 'bb_topic' AND `meta_key` = 'voices_count';";
27
- if ( is_wp_error( $bbdb->query( $sql_delete ) ) ) {
28
- return array( 1, sprintf( $statement, $result ) );
29
- }
30
-
31
- $sql = "INSERT INTO `$bbdb->meta` (`object_type`, `object_id`, `meta_key`, `meta_value`) (SELECT 'bb_topic', `topic_id`, 'voices_count', COUNT(DISTINCT `poster_id`) as `meta_value` FROM `$bbdb->posts` WHERE `post_status` = '0' GROUP BY `topic_id`);";
32
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
33
- return array( 2, sprintf( $statement, $result ) );
34
- }
35
-
36
- $result = __( 'Complete!' );
37
- return array( 0, sprintf( $statement, $result ) );
38
- }
39
-
40
- function bb_recount_topic_deleted_posts()
41
- {
42
- global $bbdb;
43
-
44
- $statement = __( 'Counting the number of deleted posts in each topic&hellip; %s' );
45
- $result = __( 'Failed!' );
46
-
47
- $sql_delete = "DELETE FROM `$bbdb->meta` WHERE `object_type` = 'bb_topic' AND `meta_key` = 'deleted_posts';";
48
- if ( is_wp_error( $bbdb->query( $sql_delete ) ) ) {
49
- return array( 1, sprintf( $statement, $result ) );
50
- }
51
-
52
- $sql = "INSERT INTO `$bbdb->meta` (`object_type`, `object_id`, `meta_key`, `meta_value`) (SELECT 'bb_topic', `topic_id`, 'deleted_posts', COUNT(`post_status`) as `meta_value` FROM `$bbdb->posts` WHERE `post_status` != '0' GROUP BY `topic_id`);";
53
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
54
- return array( 2, sprintf( $statement, $result ) );
55
- }
56
-
57
- $result = __( 'Complete!' );
58
- return array( 0, sprintf( $statement, $result ) );
59
- }
60
-
61
- function bb_recount_forum_topics()
62
- {
63
- global $bbdb;
64
-
65
- $statement = __( 'Counting the number of topics in each forum&hellip; %s' );
66
- $result = __( 'Failed!' );
67
-
68
- $sql = "INSERT INTO `$bbdb->forums` (`forum_id`, `topics`) (SELECT `forum_id`, COUNT(`topic_status`) as `topics` FROM `$bbdb->topics` WHERE `topic_status` = '0' GROUP BY `forum_id`) ON DUPLICATE KEY UPDATE `topics` = VALUES(`topics`);";
69
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
70
- return array( 1, sprintf( $statement, $result ) );
71
- }
72
-
73
- $result = __( 'Complete!' );
74
- return array( 0, sprintf( $statement, $result ) );
75
- }
76
-
77
- function bb_recount_forum_posts()
78
- {
79
- global $bbdb;
80
-
81
- $statement = __( 'Counting the number of posts in each forum&hellip; %s' );
82
- $result = __( 'Failed!' );
83
-
84
- $sql = "INSERT INTO `$bbdb->forums` (`forum_id`, `posts`) (SELECT `forum_id`, COUNT(`post_status`) as `posts` FROM `$bbdb->posts` WHERE `post_status` = '0' GROUP BY `forum_id`) ON DUPLICATE KEY UPDATE `posts` = VALUES(`posts`);";
85
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
86
- return array( 1, sprintf( $statement, $result ) );
87
- }
88
-
89
- $result = __( 'Complete!' );
90
- return array( 0, sprintf( $statement, $result ) );
91
- }
92
-
93
- function bb_recount_user_topics_replied()
94
- {
95
- global $bbdb;
96
-
97
- $statement = __( 'Counting the number of topics to which each user has replied&hellip; %s' );
98
- $result = __( 'Failed!' );
99
-
100
- $sql_select = "SELECT `poster_id`, COUNT(DISTINCT `topic_id`) as `_count` FROM `$bbdb->posts` WHERE `post_status` = '0' GROUP BY `poster_id`;";
101
- $insert_rows = $bbdb->get_results( $sql_select );
102
-
103
- if ( is_wp_error( $insert_rows ) ) {
104
- return array( 1, sprintf( $statement, $result ) );
105
- }
106
-
107
- $meta_key = $bbdb->prefix . 'topics_replied';
108
-
109
- $insert_values = array();
110
- foreach ( $insert_rows as $insert_row ) {
111
- $insert_values[] = "('$insert_row->poster_id', '$meta_key', '$insert_row->_count')";
112
- }
113
-
114
- if ( !count( $insert_values ) ) {
115
- return array( 2, sprintf( $statement, $result ) );
116
- }
117
-
118
- $sql_delete = "DELETE FROM `$bbdb->usermeta` WHERE `meta_key` = '$meta_key';";
119
- if ( is_wp_error( $bbdb->query( $sql_delete ) ) ) {
120
- return array( 3, sprintf( $statement, $result ) );
121
- }
122
-
123
- $insert_values = array_chunk( $insert_values, 10000 );
124
- foreach ( $insert_values as $chunk ) {
125
- $chunk = "\n" . join( ",\n", $chunk );
126
- $sql_insert = "INSERT INTO `$bbdb->usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
127
-
128
- if ( is_wp_error( $bbdb->query( $sql_insert ) ) ) {
129
- return array( 4, sprintf( $statement, $result ) );
130
- }
131
- }
132
-
133
- $result = __( 'Complete!' );
134
- return array( 0, sprintf( $statement, $result ) );
135
- }
136
-
137
- // This function bypasses the taxonomy API
138
- function bb_recount_topic_tags()
139
- {
140
- global $bbdb;
141
-
142
- $statement = __( 'Counting the number of topic tags in each topic&hellip; %s' );
143
- $result = __( 'Failed!' );
144
-
145
- // Delete empty tags
146
- $delete = bb_recount_tag_delete_empty();
147
- if ( $delete[0] > 0 ) {
148
- $result = __( 'Could not delete empty tags.' );
149
- return array( 1, sprintf( $statement, $result ) );
150
- }
151
-
152
- // Get all tags
153
- $sql_terms = "SELECT
154
- `$bbdb->term_relationships`.`object_id`,
155
- `$bbdb->term_taxonomy`.`term_id`
156
- FROM `$bbdb->term_relationships`
157
- JOIN `$bbdb->term_taxonomy`
158
- ON `$bbdb->term_taxonomy`.`term_taxonomy_id` = `$bbdb->term_relationships`.`term_taxonomy_id`
159
- WHERE
160
- `$bbdb->term_taxonomy`.`taxonomy` = 'bb_topic_tag'
161
- ORDER BY
162
- `$bbdb->term_relationships`.`object_id`,
163
- `$bbdb->term_taxonomy`.`term_id`;";
164
-
165
- $terms = $bbdb->get_results( $sql_terms );
166
- if ( is_wp_error( $terms ) || !is_array( $terms ) ) {
167
- return array( 2, sprintf( $statement, $result ) );
168
- }
169
- if ( empty( $terms ) ) {
170
- $result = __( 'No topic tags found.' );
171
- return array( 3, sprintf( $statement, $result ) );
172
- }
173
-
174
- // Count the tags in each topic
175
- $topics = array();
176
- foreach ( $terms as $term ) {
177
- if ( !isset( $topics[$term->object_id] ) ) {
178
- $topics[$term->object_id] = 1;
179
- } else {
180
- $topics[$term->object_id]++;
181
- }
182
- }
183
- if ( empty( $topics ) ) {
184
- return array( 4, sprintf( $statement, $result ) );
185
- }
186
-
187
- // Build the values to insert into the SQL statement
188
- $values = array();
189
- foreach ($topics as $topic_id => $tag_count) {
190
- $values[] = '(' . $topic_id . ', ' . $tag_count . ')';
191
- }
192
- if ( empty( $values ) ) {
193
- return array( 5, sprintf( $statement, $result ) );
194
- }
195
-
196
- // Update the topics with the new tag counts
197
- $values = array_chunk( $values, 10000 );
198
- foreach ($values as $chunk) {
199
- $sql = "INSERT INTO `$bbdb->topics` (`topic_id`, `tag_count`) VALUES " . implode(", ", $chunk) . " ON DUPLICATE KEY UPDATE `tag_count` = VALUES(`tag_count`);";
200
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
201
- return array( 6, sprintf( $statement, $result ) );
202
- }
203
- }
204
-
205
- $result = __( 'Complete!' );
206
- return array( 0, sprintf( $statement, $result ) );
207
- }
208
-
209
- // This function bypasses the taxonomy API
210
- function bb_recount_tag_topics()
211
- {
212
- global $bbdb;
213
-
214
- $statement = __( 'Counting the number of topics in each topic tag&hellip; %s' );
215
- $result = __( 'Failed!' );
216
-
217
- // Delete empty tags
218
- $delete = bb_recount_tag_delete_empty();
219
- if ( $delete[0] > 0 ) {
220
- $result = __( 'Could not delete empty tags.' );
221
- return array( 1, sprintf( $statement, $result ) );
222
- }
223
-
224
- // Get all tags
225
- $sql_terms = "SELECT
226
- `$bbdb->term_taxonomy`.`term_taxonomy_id`,
227
- `$bbdb->term_relationships`.`object_id`
228
- FROM `$bbdb->term_relationships`
229
- JOIN `$bbdb->term_taxonomy`
230
- ON `$bbdb->term_taxonomy`.`term_taxonomy_id` = `$bbdb->term_relationships`.`term_taxonomy_id`
231
- WHERE
232
- `$bbdb->term_taxonomy`.`taxonomy` = 'bb_topic_tag'
233
- ORDER BY
234
- `$bbdb->term_taxonomy`.`term_taxonomy_id`,
235
- `$bbdb->term_relationships`.`object_id`;";
236
-
237
- $terms = $bbdb->get_results( $sql_terms );
238
- if ( is_wp_error( $terms ) || !is_array( $terms ) ) {
239
- return array( 2, sprintf( $statement, $result ) );
240
- }
241
- if ( empty( $terms ) ) {
242
- $result = __( 'No topic tags found.' );
243
- return array( 3, sprintf( $statement, $result ) );
244
- }
245
-
246
- // Count the topics in each tag
247
- $tags = array();
248
- foreach ( $terms as $term ) {
249
- if ( !isset( $tags[$term->term_taxonomy_id] ) ) {
250
- $tags[$term->term_taxonomy_id] = 1;
251
- } else {
252
- $tags[$term->term_taxonomy_id]++;
253
- }
254
- }
255
- if ( empty( $tags ) ) {
256
- return array( 4, sprintf( $statement, $result ) );
257
- }
258
-
259
- // Build the values to insert into the SQL statement
260
- $values = array();
261
- foreach ($tags as $term_taxonomy_id => $count) {
262
- $values[] = '(' . $term_taxonomy_id . ', ' . $count . ')';
263
- }
264
- if ( empty( $values ) ) {
265
- return array( 5, sprintf( $statement, $result ) );
266
- }
267
-
268
- // Update the terms with the new tag counts
269
- $values = array_chunk( $values, 10000 );
270
- foreach ($values as $chunk) {
271
- $sql = "INSERT INTO `$bbdb->term_taxonomy` (`term_taxonomy_id`, `count`) VALUES " . implode(", ", $chunk) . " ON DUPLICATE KEY UPDATE `count` = VALUES(`count`);";
272
- if ( is_wp_error( $bbdb->query( $sql ) ) ) {
273
- return array( 6, sprintf( $statement, $result ) );
274
- }
275
- }
276
-
277
- if ($return_boolean) {
278
- return true;
279
- }
280
- $result = __( 'Complete!' );
281
- return array( 0, sprintf( $statement, $result ) );
282
- }
283
-
284
- // This function bypasses the taxonomy API
285
- function bb_recount_tag_delete_empty()
286
- {
287
- global $bbdb;
288
-
289
- $statement = __( 'Deleting topic tags with no topics&hellip; %s' );
290
- $result = __( 'Failed!' );
291
-
292
- static $run_once;
293
- if ( isset( $run_once ) ) {
294
- if ($run_once > 0) {
295
- $exit = sprintf( __( 'failure (returned code %s)' ), $run_once );
296
- } else {
297
- $exit = __( 'success' );
298
- }
299
- $result = sprintf( __( 'Already run with %s.' ), $exit );
300
- return array( $run_once, sprintf( $statement, $result ) );
301
- }
302
-
303
- // Get all topic ids
304
- $sql_topics = "SELECT `topic_id` FROM $bbdb->topics ORDER BY `topic_id`;";
305
- $topics = $bbdb->get_results( $sql_topics );
306
- if ( is_wp_error( $topics ) ) {
307
- $result = __('No topics found.');
308
- $run_once = 1;
309
- return array( 1, sprintf( $statement, $result ) );
310
- }
311
- $topic_ids = array();
312
- foreach ($topics as $topic) {
313
- $topic_ids[] = $topic->topic_id;
314
- }
315
-
316
- // Get all topic tag term relationships without a valid topic id
317
- $in_topic_ids = implode(', ', $topic_ids);
318
- $sql_bad_term_relationships = "SELECT
319
- `$bbdb->term_taxonomy`.`term_taxonomy_id`,
320
- `$bbdb->term_taxonomy`.`term_id`,
321
- `$bbdb->term_relationships`.`object_id`
322
- FROM `$bbdb->term_relationships`
323
- JOIN `$bbdb->term_taxonomy`
324
- ON `$bbdb->term_taxonomy`.`term_taxonomy_id` = `$bbdb->term_relationships`.`term_taxonomy_id`
325
- WHERE
326
- `$bbdb->term_taxonomy`.`taxonomy` = 'bb_topic_tag' AND
327
- `$bbdb->term_relationships`.`object_id` NOT IN ($in_topic_ids)
328
- ORDER BY
329
- `$bbdb->term_relationships`.`object_id`,
330
- `$bbdb->term_taxonomy`.`term_id`,
331
- `$bbdb->term_taxonomy`.`term_taxonomy_id`;";
332
-
333
- $bad_term_relationships = $bbdb->get_results( $sql_bad_term_relationships );
334
- if ( is_wp_error( $bad_term_relationships ) || !is_array( $bad_term_relationships ) ) {
335
- $run_once = 2;
336
- return array( 2, sprintf( $statement, $result ) );
337
- }
338
-
339
- // Delete those bad term relationships
340
- if ( !empty( $bad_term_relationships ) ) {
341
- $values = array();
342
- foreach ( $bad_term_relationships as $bad_term_relationship ) {
343
- $values[] = '(`object_id` = ' . $bad_term_relationship->object_id . ' AND `term_taxonomy_id` = ' . $bad_term_relationship->term_taxonomy_id . ')';
344
- }
345
- if ( !empty( $values ) ) {
346
- $values = join(' OR ', $values);
347
- $sql_bad_term_relationships_delete = "DELETE
348
- FROM `$bbdb->term_relationships`
349
- WHERE $values;";
350
- if ( is_wp_error( $bbdb->query( $sql_bad_term_relationships_delete ) ) ) {
351
- $run_once = 3;
352
- return array( 3, sprintf( $statement, $result ) );
353
- }
354
- }
355
- }
356
-
357
- // Now get all term taxonomy ids with term relationships
358
- $sql_term_relationships = "SELECT `term_taxonomy_id` FROM $bbdb->term_relationships ORDER BY `term_taxonomy_id`;";
359
- $term_taxonomy_ids = $bbdb->get_col($sql_term_relationships);
360
- if ( is_wp_error( $term_taxonomy_ids ) ) {
361
- $run_once = 4;
362
- return array( 4, sprintf( $statement, $result ) );
363
- }
364
- $term_taxonomy_ids = array_unique( $term_taxonomy_ids );
365
-
366
- // Delete topic tags that don't have any term relationships
367
- if ( !empty( $term_taxonomy_ids ) ) {
368
- $in_term_taxonomy_ids = implode(', ', $term_taxonomy_ids);
369
- $sql_delete_term_relationships = "DELETE
370
- FROM $bbdb->term_taxonomy
371
- WHERE
372
- `taxonomy` = 'bb_topic_tag' AND
373
- `term_taxonomy_id` NOT IN ($in_term_taxonomy_ids);";
374
- if ( is_wp_error( $bbdb->query( $sql_delete_term_relationships ) ) ) {
375
- $run_once = 5;
376
- return array( 5, sprintf( $statement, $result ) );
377
- }
378
- }
379
-
380
- // Get all valid term ids
381
- $sql_terms = "SELECT `term_id` FROM $bbdb->term_taxonomy ORDER BY `term_id`;";
382
- $term_ids = $bbdb->get_col($sql_terms);
383
- if ( is_wp_error( $term_ids ) ) {
384
- $run_once = 6;
385
- return array( 6, sprintf( $statement, $result ) );
386
- }
387
- $term_ids = array_unique( $term_ids );
388
-
389
- // Delete terms that don't have any associated term taxonomies
390
- if ( !empty( $term_ids ) ) {
391
- $in_term_ids = implode(', ', $term_ids);
392
- $sql_delete_terms = "DELETE
393
- FROM $bbdb->terms
394
- WHERE
395
- `term_id` NOT IN ($in_term_ids);";
396
- if ( is_wp_error( $bbdb->query( $sql_delete_terms ) ) ) {
397
- $run_once = 7;
398
- return array( 7, sprintf( $statement, $result ) );
399
- }
400
- }
401
-
402
- $result = __( 'Complete!' );
403
- $run_once = 0;
404
- return array( 0, sprintf( $statement, $result ) );
405
- }
406
-
407
- function bb_recount_clean_favorites()
408
- {
409
- global $bbdb;
410
-
411
- $statement = __( 'Removing deleted topics from user favorites&hellip; %s' );
412
- $result = __( 'Failed!' );
413
-
414
- $meta_key = $bbdb->prefix . 'favorites';
415
-
416
- $users = $bbdb->get_results( "SELECT `user_id`, `meta_value` AS `favorites` FROM `$bbdb->usermeta` WHERE `meta_key` = '$meta_key';" );
417
- if ( is_wp_error( $users ) ) {
418
- return array( 1, sprintf( $statement, $result ) );
419
- }
420
-
421
- $topics = $bbdb->get_col( "SELECT `topic_id` FROM `$bbdb->topics` WHERE `topic_status` = '0';" );
422
-
423
- if ( is_wp_error( $topics ) ) {
424
- return array( 2, sprintf( $statement, $result ) );
425
- }
426
-
427
- $values = array();
428
- foreach ( $users as $user ) {
429
- if ( empty( $user->favorites ) || !is_string( $user->favorites ) ) {
430
- continue;
431
- }
432
- $favorites = explode( ',', $user->favorites );
433
- if ( empty( $favorites ) || !is_array( $favorites ) ) {
434
- continue;
435
- }
436
- $favorites = join( ',', array_intersect( $topics, $favorites ) );
437
- $values[] = "('$user->user_id', '$meta_key', '$favorites')";
438
- }
439
-
440
- if ( !count( $values ) ) {
441
- $result = __( 'Nothing to remove!' );
442
- return array( 0, sprintf( $statement, $result ) );
443
- }
444
-
445
- $sql_delete = "DELETE FROM `$bbdb->usermeta` WHERE `meta_key` = '$meta_key';";
446
- if ( is_wp_error( $bbdb->query( $sql_delete ) ) ) {
447
- return array( 4, sprintf( $statement, $result ) );
448
- }
449
-
450
- $values = array_chunk( $values, 10000 );
451
- foreach ( $values as $chunk ) {
452
- $chunk = "\n" . join( ",\n", $chunk );
453
- $sql_insert = "INSERT INTO `$bbdb->usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
454
- if ( is_wp_error( $bbdb->query( $sql_insert ) ) ) {
455
- return array( 5, sprintf( $statement, $result ) );
456
- }
457
- }
458
-
459
- $result = __( 'Complete!' );
460
- return array( 0, sprintf( $statement, $result ) );
461
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/includes/functions.bb-upgrade.php DELETED
@@ -1,533 +0,0 @@
1
- <?php
2
- function bb_install() {
3
- require_once( BACKPRESS_PATH . 'class.bp-sql-schema-parser.php' );
4
- require_once( BB_PATH . 'bb-admin/includes/defaults.bb-schema.php' );
5
- $alterations = BP_SQL_Schema_Parser::delta( $bbdb, $bb_queries, $bb_schema_ignore );
6
-
7
- bb_update_db_version();
8
-
9
- return array_filter($alterations);
10
- }
11
-
12
- function bb_upgrade_all()
13
- {
14
- if ( !ini_get( 'safe_mode' ) ) {
15
- set_time_limit(600);
16
- }
17
-
18
- $_do_user_operations = true;
19
- if ( bb_get_option( 'wp_table_prefix' ) || ( defined( 'BB_SCHEMA_IGNORE_WP_USERS_TABLES' ) && BB_SCHEMA_IGNORE_WP_USERS_TABLES ) ) {
20
- $_do_user_operations = false;
21
- }
22
-
23
- $bb_upgrade = array();
24
-
25
- // Pre DB Delta
26
- if ( $_do_user_operations ) {
27
- $bb_upgrade['messages'][] = bb_upgrade_160(); // Break blocked users
28
- $bb_upgrade['messages'][] = bb_upgrade_170(); // Escaping in usermeta
29
- $bb_upgrade['messages'][] = bb_upgrade_180(); // Delete users for real
30
- }
31
- $bb_upgrade['messages'][] = bb_upgrade_190(); // Move topic_resolved to topicmeta
32
- $bb_upgrade['messages'][] = bb_upgrade_200(); // Indices
33
- $bb_upgrade['messages'][] = bb_upgrade_210(); // Convert text slugs to varchar slugs
34
- $bb_upgrade['messages'][] = bb_upgrade_220(); // remove bb_tagged primary key, add new column and primary key
35
-
36
- require_once( BACKPRESS_PATH . 'class.bp-sql-schema-parser.php' );
37
- require_once( BB_PATH . 'bb-admin/includes/defaults.bb-schema.php' );
38
- $delta = BP_SQL_Schema_Parser::delta( $bbdb, $bb_queries, $bb_schema_ignore );
39
- if ( is_array( $delta ) ) {
40
- $bb_upgrade['messages'] = array_merge($bb_upgrade['messages'], $delta['messages']);
41
- $bb_upgrade['errors'] = $delta['errors'];
42
- } else {
43
- $bb_upgrade['errors'] = array();
44
- }
45
-
46
- // Post DB Delta
47
- $bb_upgrade['messages'][] = bb_upgrade_1000(); // Make forum and topic slugs
48
- $bb_upgrade['messages'][] = bb_upgrade_1010(); // Make sure all forums have a valid parent
49
- if ( $_do_user_operations ) {
50
- $bb_upgrade['messages'][] = bb_upgrade_1020(); // Add a user_nicename to existing users
51
- }
52
- $bb_upgrade['messages'][] = bb_upgrade_1030(); // Move admin_email option to from_email
53
- $bb_upgrade['messages'][] = bb_upgrade_1040(); // Activate Akismet and bozo plugins and convert active plugins to new convention on upgrade only
54
- $bb_upgrade['messages'][] = bb_upgrade_1050(); // Update active theme if present
55
- $bb_upgrade['messages'][] = bb_upgrade_1070(); // trim whitespace from raw_tag
56
- $bb_upgrade['messages'][] = bb_upgrade_1080(); // Convert tags to taxonomy
57
- if ( $_do_user_operations ) {
58
- $bb_upgrade['messages'][] = bb_upgrade_1090(); // Add display names
59
- }
60
- $bb_upgrade['messages'][] = bb_upgrade_1100(); // Replace forum_stickies index with stickies (#876)
61
- $bb_upgrade['messages'][] = bb_upgrade_1110(); // Create plugin directory (#1083)
62
- $bb_upgrade['messages'][] = bb_upgrade_1120(); // Create theme directory (#1083)
63
- $bb_upgrade['messages'][] = bb_upgrade_1130(); // Add subscriptions option and set it to true (#1268)
64
-
65
- bb_update_db_version();
66
- wp_cache_flush();
67
-
68
- $bb_upgrade['messages'] = array_filter($bb_upgrade['messages']);
69
- $bb_upgrade['errors'] = array_filter($bb_upgrade['errors']);
70
-
71
- return $bb_upgrade;
72
- }
73
-
74
- function bb_upgrade_process_all_slugs() {
75
- global $bbdb;
76
- // Forums
77
-
78
- $forums = (array) $bbdb->get_results("SELECT forum_id, forum_name FROM $bbdb->forums ORDER BY forum_order ASC" );
79
-
80
- $slugs = array();
81
- foreach ( $forums as $forum ) :
82
- $slug = bb_slug_sanitize( wp_specialchars_decode( $forum->forum_name, ENT_QUOTES ) );
83
- $slugs[$slug][] = $forum->forum_id;
84
- endforeach;
85
-
86
- foreach ( $slugs as $slug => $forum_ids ) :
87
- foreach ( $forum_ids as $count => $forum_id ) :
88
- $_slug = $slug;
89
- $count = - $count; // madness
90
- if ( is_numeric($slug) || $count )
91
- $_slug = bb_slug_increment( $slug, $count );
92
- $bbdb->query("UPDATE $bbdb->forums SET forum_slug = '$_slug' WHERE forum_id = '$forum_id';");
93
- endforeach;
94
- endforeach;
95
- unset($forums, $forum, $slugs, $slug, $_slug, $forum_ids, $forum_id, $count);
96
-
97
- // Topics
98
-
99
- $topics = (array) $bbdb->get_results("SELECT topic_id, topic_title FROM $bbdb->topics ORDER BY topic_start_time ASC" );
100
-
101
- $slugs = array();
102
- foreach ( $topics as $topic) :
103
- $slug = bb_slug_sanitize( wp_specialchars_decode( $topic->topic_title, ENT_QUOTES ) );
104
- $slugs[$slug][] = $topic->topic_id;
105
- endforeach;
106
-
107
- foreach ( $slugs as $slug => $topic_ids ) :
108
- foreach ( $topic_ids as $count => $topic_id ) :
109
- $_slug = $slug;
110
- $count = - $count;
111
- if ( is_numeric($slug) || $count )
112
- $_slug = bb_slug_increment( $slug, $count );
113
- $bbdb->query("UPDATE $bbdb->topics SET topic_slug = '$_slug' WHERE topic_id = '$topic_id';");
114
- endforeach;
115
- endforeach;
116
- unset($topics, $topic, $slugs, $slug, $_slug, $topic_ids, $topic_id, $count);
117
- }
118
-
119
- // Reversibly break passwords of blocked users.
120
- function bb_upgrade_160() {
121
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 535 )
122
- return;
123
-
124
- require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
125
- $blocked = bb_get_ids_by_role( 'blocked' );
126
- foreach ( $blocked as $b )
127
- bb_break_password( $b );
128
- return 'Done reversibly breaking passwords: ' . __FUNCTION__;
129
- }
130
-
131
- function bb_upgrade_170() {
132
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 536 )
133
- return;
134
-
135
- global $bbdb;
136
- foreach ( (array) $bbdb->get_results("SELECT * FROM $bbdb->usermeta WHERE meta_value LIKE '%&quot;%' OR meta_value LIKE '%&#039;%'") as $meta ) {
137
- $value = str_replace(array('&quot;', '&#039;'), array('"', "'"), $meta->meta_value);
138
- $value = stripslashes($value);
139
- bb_update_usermeta( $meta->user_id, $meta->meta_key, $value);
140
- }
141
- bb_update_option( 'bb_db_version', 536 );
142
- return 'Done updating usermeta: ' . __FUNCTION__;
143
- }
144
-
145
- function bb_upgrade_180() {
146
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 559 )
147
- return;
148
-
149
- global $bbdb;
150
-
151
- foreach ( (array) $bbdb->get_col("SELECT ID FROM $bbdb->users WHERE user_status = 1") as $user_id )
152
- bb_delete_user( $user_id );
153
- bb_update_option( 'bb_db_version', 559 );
154
- return 'Done clearing deleted users: ' . __FUNCTION__;
155
- }
156
-
157
- function bb_upgrade_190() {
158
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 630 )
159
- return;
160
-
161
- global $bbdb;
162
-
163
- $exists = false;
164
- foreach ( (array) $bbdb->get_col("DESC $bbdb->topics") as $col )
165
- if ( 'topic_resolved' == $col )
166
- $exists = true;
167
- if ( !$exists )
168
- return;
169
-
170
- $topics = (array) $bbdb->get_results("SELECT topic_id, topic_resolved FROM $bbdb->topics" );
171
- foreach ( $topics as $topic )
172
- bb_update_topicmeta( $topic->topic_id, 'topic_resolved', $topic->topic_resolved );
173
- unset($topics,$topic);
174
-
175
- $bbdb->query("ALTER TABLE $bbdb->topics DROP topic_resolved");
176
-
177
- bb_update_option( 'bb_db_version', 630 );
178
-
179
- return 'Done converting topic_resolved: ' . __FUNCTION__;
180
- }
181
-
182
- function bb_upgrade_200() {
183
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 845 )
184
- return;
185
-
186
- global $bbdb;
187
-
188
- $bbdb->hide_errors();
189
- $bbdb->query( "DROP INDEX tag_id_index ON $bbdb->tagged" );
190
- $bbdb->query( "DROP INDEX user_id ON $bbdb->topicmeta" );
191
- $bbdb->query( "DROP INDEX forum_id ON $bbdb->topics" );
192
- $bbdb->query( "DROP INDEX topic_time ON $bbdb->topics" );
193
- $bbdb->query( "DROP INDEX topic_start_time ON $bbdb->topics" );
194
- $bbdb->query( "DROP INDEX tag_id_index ON $bbdb->tagged" );
195
- $bbdb->query( "DROP INDEX topic_id ON $bbdb->posts" );
196
- $bbdb->query( "DROP INDEX poster_id ON $bbdb->posts" );
197
- $bbdb->show_errors();
198
-
199
- bb_update_option( 'bb_db_version', 845 );
200
-
201
- return 'Done removing old indices: ' . __FUNCTION__;
202
- }
203
-
204
- // 210 converts text slugs to varchar(255) width slugs (upgrading from alpha version - fires before dbDelta)
205
- // 1000 Gives new slugs (upgrading from previous release - fires after dbDelta)
206
- function bb_upgrade_210() {
207
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 846 )
208
- return;
209
-
210
- global $bbdb;
211
-
212
- $bbdb->hide_errors();
213
- if ( !$bbdb->get_var("SELECT forum_slug FROM $bbdb->forums ORDER BY forum_order ASC LIMIT 1" ) )
214
- return; // Wait till after dbDelta
215
- $bbdb->show_errors();
216
-
217
- bb_upgrade_process_all_slugs();
218
-
219
- bb_update_option( 'bb_db_version', 846 );
220
-
221
- return 'Done adding slugs: ' . __FUNCTION__;
222
- }
223
-
224
- function bb_upgrade_220() {
225
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1051 )
226
- return;
227
-
228
- global $bbdb;
229
-
230
- $bbdb->query( "ALTER TABLE $bbdb->tagged DROP PRIMARY KEY" );
231
- $bbdb->query( "ALTER TABLE $bbdb->tagged ADD tagged_id bigint(20) unsigned NOT NULL auto_increment PRIMARY KEY FIRST" );
232
-
233
- return "Done removing key from $bbdb->tagged: " . __FUNCTION__;
234
- }
235
-
236
- function bb_upgrade_1000() { // Give all topics and forums slugs
237
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 846 )
238
- return;
239
-
240
- bb_upgrade_process_all_slugs();
241
-
242
- bb_update_option( 'bb_db_version', 846 );
243
-
244
- return 'Done adding slugs: ' . __FUNCTION__;;
245
- }
246
-
247
- // Make sure all forums have a valid parent
248
- function bb_upgrade_1010() {
249
- global $bbdb;
250
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 952 )
251
- return;
252
-
253
- $forums = (array) $bbdb->get_results( "SELECT forum_id, forum_parent FROM $bbdb->forums" );
254
- $forum_ids = (array) $bbdb->get_col( '', 0 );
255
-
256
- foreach ( $forums as $forum ) {
257
- if ( $forum->forum_parent && !in_array( $forum->forum_parent, $forum_ids ) )
258
- $bbdb->query( "UPDATE $bbdb->forums SET forum_parent = 0 WHERE forum_id = '$forum->forum_id'" );
259
- }
260
-
261
- bb_update_option( 'bb_db_version', 952 );
262
-
263
- return 'Done re-parenting orphaned forums: ' . __FUNCTION__;
264
- }
265
-
266
- // Add a nicename for existing users if they don't have one already
267
- function bb_upgrade_1020() {
268
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 977 )
269
- return;
270
-
271
- global $bbdb;
272
-
273
- $users = $bbdb->get_results( "SELECT ID, user_login, user_nicename FROM $bbdb->users WHERE user_nicename IS NULL OR user_nicename = ''" );
274
-
275
- if ( $users ) {
276
- foreach ( $users as $user ) {
277
- $user_nicename = $_user_nicename = bb_user_nicename_sanitize( $user->user_login );
278
- while ( is_numeric($user_nicename) || $existing_user = bb_get_user_by_nicename( $user_nicename ) )
279
- $user_nicename = bb_slug_increment($_user_nicename, $existing_user->user_nicename, 50);
280
-
281
- $bbdb->query( "UPDATE $bbdb->users SET user_nicename = '$user_nicename' WHERE ID = $user->ID;" );
282
- }
283
- }
284
-
285
- bb_update_option( 'bb_db_version', 977 );
286
-
287
- return 'Done adding nice-names to existing users: ' . __FUNCTION__;
288
- }
289
-
290
- // Move admin_email option to from_email
291
- function bb_upgrade_1030() {
292
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1058 )
293
- return;
294
-
295
- $admin_email = bb_get_option('admin_email');
296
- if ($admin_email) {
297
- bb_update_option('from_email', $admin_email);
298
- }
299
- bb_delete_option('admin_email');
300
-
301
- bb_update_option( 'bb_db_version', 1058 );
302
-
303
- return 'Done moving admin_email to from_email: ' . __FUNCTION__;
304
- }
305
-
306
- // Activate Akismet and bozo plugins and convert active plugins to new convention on upgrade only
307
- function bb_upgrade_1040() {
308
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1230 )
309
- return;
310
-
311
- // Only do this when upgrading
312
- if ( defined( 'BB_UPGRADING' ) && BB_UPGRADING ) {
313
- $plugins = bb_get_option('active_plugins');
314
- if ( bb_get_option('akismet_key') && !in_array('core#akismet.php', $plugins) ) {
315
- $plugins[] = 'core#akismet.php';
316
- }
317
- if ( !in_array('core#bozo.php', $plugins) ) {
318
- $plugins[] = 'core#bozo.php';
319
- }
320
-
321
- $new_plugins = array();
322
- foreach ($plugins as $plugin) {
323
- if (substr($plugin, 0, 5) != 'core#') {
324
- if ($plugin != 'akismet.php' && $plugin != 'bozo.php') {
325
- $new_plugins[] = 'user#' . $plugin;
326
- }
327
- } else {
328
- $new_plugins[] = $plugin;
329
- }
330
- }
331
-
332
- bb_update_option( 'active_plugins', $new_plugins );
333
- }
334
-
335
- bb_update_option( 'bb_db_version', 1230 );
336
-
337
- return 'Done activating Akismet and Bozo plugins and converting active plugins to new convention on upgrade only: ' . __FUNCTION__;
338
- }
339
-
340
- // Update active theme if present
341
- function bb_upgrade_1050() {
342
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1234 )
343
- return;
344
-
345
- // Only do this when upgrading
346
- if ( defined( 'BB_UPGRADING' ) && BB_UPGRADING ) {
347
- if ( $theme = bb_get_option( 'bb_active_theme' ) ) {
348
- bb_update_option( 'bb_active_theme', bb_theme_basename( $theme ) );
349
- }
350
- }
351
-
352
- bb_update_option( 'bb_db_version', 1234 );
353
-
354
- return 'Done updating active theme if present: ' . __FUNCTION__;
355
- }
356
-
357
- function bb_upgrade_1070() {
358
- global $bbdb;
359
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1467 )
360
- return;
361
-
362
- $bbdb->query( "UPDATE `$bbdb->tags` SET `raw_tag` = TRIM(`raw_tag`)" );
363
-
364
- bb_update_option( 'bb_db_version', 1467 );
365
-
366
- return 'Whitespace trimmed from raw_tag: ' . __FUNCTION__;
367
- }
368
-
369
- function bb_upgrade_1080() {
370
- global $bbdb, $wp_taxonomy_object;
371
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1526 )
372
- return;
373
-
374
- $offset = 0;
375
- while ( $tags = (array) $bbdb->get_results( "SELECT * FROM $bbdb->tags LIMIT $offset, 100" ) ) {
376
- if ( !ini_get('safe_mode') ) set_time_limit(600);
377
- $wp_taxonomy_object->defer_term_counting(true);
378
- for ( $i = 0; isset($tags[$i]); $i++ ) {
379
- $bbdb->insert( $bbdb->terms, array(
380
- 'name' => $tags[$i]->raw_tag,
381
- 'slug' => $tags[$i]->tag
382
- ) );
383
- $term_id = $bbdb->insert_id;
384
- $bbdb->insert( $bbdb->term_taxonomy, array(
385
- 'term_id' => $term_id,
386
- 'taxonomy' => 'bb_topic_tag',
387
- 'description' => ''
388
- ) );
389
- $term_taxonomy_id = $bbdb->insert_id;
390
- $topics = (array) $bbdb->get_results( $bbdb->prepare( "SELECT user_id, topic_id FROM $bbdb->tagged WHERE tag_id = %d", $tags[$i]->tag_id ) );
391
- for ( $j = 0; isset($topics[$j]); $j++ ) {
392
- $bbdb->insert( $bbdb->term_relationships, array(
393
- 'object_id' => $topics[$j]->topic_id,
394
- 'term_taxonomy_id' => $term_taxonomy_id,
395
- 'user_id' => $topics[$j]->user_id
396
- ) );
397
- }
398
- $wp_taxonomy_object->update_term_count( array( $term_taxonomy_id ), 'bb_topic_tag' );
399
- }
400
- $wp_taxonomy_object->defer_term_counting(false);
401
- $offset += 100;
402
- }
403
-
404
- bb_update_option( 'bb_db_version', 1526 );
405
-
406
- return 'Tags copied to taxonomy tables: ' . __FUNCTION__;
407
- }
408
-
409
- function bb_upgrade_1090() {
410
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1589 )
411
- return;
412
-
413
- global $bbdb;
414
-
415
- $users = (array) $bbdb->get_results( "SELECT `ID`, `user_login` FROM $bbdb->users WHERE `display_name` = '' OR `display_name` IS NULL;" );
416
-
417
- if ($users) {
418
- foreach ($users as $user) {
419
- $bbdb->query( "UPDATE $bbdb->users SET `display_name` = '" . $user->user_login . "' WHERE ID = " . $user->ID . ";" );
420
- }
421
- unset($user, $users);
422
- }
423
-
424
- bb_update_option( 'bb_db_version', 1589 );
425
-
426
- return 'Display names populated: ' . __FUNCTION__;
427
- }
428
-
429
- function bb_upgrade_1100() {
430
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 1638 )
431
- return;
432
-
433
- global $bbdb;
434
-
435
- $bbdb->query( "DROP INDEX forum_stickies ON $bbdb->topics" );
436
-
437
- bb_update_option( 'bb_db_version', 1638 );
438
-
439
- return 'Index forum_stickies dropped: ' . __FUNCTION__;
440
- }
441
-
442
- function bb_upgrade_1110() {
443
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 2077 )
444
- return;
445
-
446
- // No matter what happens, update the db version
447
- bb_update_option( 'bb_db_version', 2077 );
448
-
449
- if ( !defined( 'BB_PLUGIN_DIR' ) ) {
450
- return;
451
- }
452
-
453
- if ( !BB_PLUGIN_DIR ) {
454
- return;
455
- }
456
-
457
- if ( file_exists( BB_PLUGIN_DIR ) ) {
458
- return;
459
- }
460
-
461
- // Just suppress errors as this is not critical
462
- if ( @mkdir( BB_PLUGIN_DIR, 0755 ) ) {
463
- return 'Making plugin directory at ' . BB_PLUGIN_DIR . ': ' . __FUNCTION__;
464
- }
465
-
466
- return;
467
- }
468
-
469
- function bb_upgrade_1120() {
470
- if ( ( $dbv = bb_get_option_from_db( 'bb_db_version' ) ) && $dbv >= 2078 ) {
471
- return;
472
- }
473
-
474
- // No matter what happens, update the db version
475
- bb_update_option( 'bb_db_version', 2078 );
476
-
477
- if ( !defined( 'BB_THEME_DIR' ) ) {
478
- return;
479
- }
480
-
481
- if ( !BB_THEME_DIR ) {
482
- return;
483
- }
484
-
485
- if ( file_exists( BB_THEME_DIR ) ) {
486
- return;
487
- }
488
-
489
- // Just suppress errors as this is not critical
490
- if ( @mkdir( BB_THEME_DIR, 0755 ) ) {
491
- return 'Making theme directory at ' . BB_THEME_DIR . ': ' . __FUNCTION__;
492
- }
493
-
494
- return;
495
- }
496
-
497
- // Subscription Option
498
- function bb_upgrade_1130() {
499
- if ( $dbv = bb_get_option_from_db( 'bb_db_version' ) && $dbv >= 2471 )
500
- return;
501
-
502
- // If the option is already there, then return
503
- if ( bb_get_option( 'enable_subscriptions' ) )
504
- return;
505
-
506
- bb_update_option( 'enable_subscriptions', 1 );
507
-
508
- bb_update_option( 'bb_db_version', 2471 );
509
-
510
- return 'Added subscriptions option and set its value to true: ' . __FUNCTION__;
511
- }
512
-
513
- function bb_deslash($content) {
514
- // Note: \\\ inside a regex denotes a single backslash.
515
-
516
- // Replace one or more backslashes followed by a single quote with
517
- // a single quote.
518
- $content = preg_replace("/\\\+'/", "'", $content);
519
-
520
- // Replace one or more backslashes followed by a double quote with
521
- // a double quote.
522
- $content = preg_replace('/\\\+"/', '"', $content);
523
-
524
- // Replace one or more backslashes with one backslash.
525
- $content = preg_replace("/\\\+/", "\\", $content);
526
-
527
- return $content;
528
- }
529
-
530
- function bb_update_db_version() {
531
- bb_update_option( 'bb_db_version', bb_get_option( 'bb_db_version' ) );
532
- }
533
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/index.php DELETED
@@ -1,149 +0,0 @@
1
- <?php
2
-
3
- // Get started
4
- require_once('admin.php');
5
- require_once( BB_PATH . BB_INC . 'functions.bb-statistics.php' );
6
-
7
- // Get counts and format numbers
8
- $rn_forums = number_format( get_total_forums() );
9
- $rn_forums = sprintf(__ngettext('<span>%s</span> forum', '<span>%s</span> forums', $rn_forums), $rn_forums );
10
-
11
- $rn_topics = number_format( get_total_topics() );
12
- $rn_topics = sprintf(__ngettext('<span>%s</span> topic', '<span>%s</span> topics', $rn_topics), $rn_topics );
13
-
14
- $rn_posts = number_format( get_total_posts() );
15
- $rn_posts = sprintf(__ngettext('<span>%s</span> post', '<span>%s</span> posts', $rn_posts), $rn_posts );
16
-
17
- $rn_users = number_format( bb_get_total_users() );
18
- $rn_users = sprintf(__ngettext('<span>%s</span> user', '<span>%s</span> users', $rn_users), $rn_users );
19
-
20
- $rn_topic_tags = number_format( bb_get_total_topic_tags() );
21
- $rn_topic_tags = sprintf(__ngettext('<span>%s</span> tag', '<span>%s</span> tags', $rn_topic_tags), $rn_topic_tags );
22
-
23
- $rn_topics_average = number_format( get_topics_per_day() );
24
- $rn_topics_average = sprintf(__ngettext('<span>%s</span> topic', '<span>%s</span> topics', $rn_topics_average), $rn_topics_average );
25
-
26
- $rn_posts_average = number_format( get_posts_per_day() );
27
- $rn_posts_average = sprintf(__ngettext('<span>%s</span> post', '<span>%s</span> posts', $rn_posts_average), $rn_posts_average );
28
-
29
- $rn_users_average = number_format( get_registrations_per_day() );
30
- $rn_users_average = sprintf(__ngettext('<span>%s</span> user', '<span>%s</span> users', $rn_users_average), $rn_users_average );
31
-
32
- $rn_topic_tags_average = number_format( bb_get_topic_tags_per_day() );
33
- $rn_topic_tags_average = sprintf(__ngettext('<span>%s</span> tag', '<span>%s</span> tags', $rn_topic_tags_average), $rn_topic_tags_average );
34
-
35
- // Filter the numbers
36
- $rn = apply_filters( 'bb_admin_right_now', array(
37
- 'forums' => array( $rn_forums, '-' ),
38
- 'topics' => array( $rn_topics, $rn_topics_average ),
39
- 'posts' => array( $rn_posts, $rn_posts_average ),
40
- 'topic_tags' => array( $rn_topic_tags, $rn_topic_tags_average ),
41
- 'users' => array( $rn_users, $rn_users_average )
42
- ) );
43
-
44
- $bb_admin_body_class = ' bb-admin-dashboard';
45
-
46
- bb_get_admin_header(); ?>
47
-
48
- <div class="wrap">
49
- <h2><?php _e('Dashboard'); ?></h2>
50
-
51
- <?php do_action( 'bb_admin_notices' ); ?>
52
-
53
- <div id="dashboard-right-now" class="dashboard">
54
- <h3><?php _e('Right Now'); ?></h3>
55
- <div class="table">
56
- <table cellpadding="0" cellspacing="0">
57
- <thead>
58
- <tr>
59
- <th><?php _e( 'Totals' ); ?></th>
60
- <th><?php _e( 'Per Day' ); ?></th>
61
- </tr>
62
- </thead>
63
-
64
- <?php if ( !empty( $rn ) && is_array( $rn ) ) { ?>
65
-
66
- <tbody>
67
-
68
- <?php foreach ( $rn as $rn_row ) { ?>
69
-
70
- <tr>
71
- <td><?php echo $rn_row[0]; ?></td>
72
- <td><?php echo $rn_row[1]; ?></td>
73
- </tr>
74
- <?php } ?>
75
-
76
- </tbody>
77
-
78
- <?php } ?>
79
-
80
- </table>
81
- </div>
82
-
83
- <div class="versions">
84
- <p class="theme"><a class="button" href="<?php bb_uri( 'bb-admin/themes.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN ); ?>"><?php _e( 'Change Theme' ); ?></a><?php printf ( __( 'Theme <a href="%1$s">%2$s</a>' ), bb_get_uri( 'bb-admin/themes.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN ), bb_get_current_theme_data( 'Name' ) ); ?></p>
85
- <p class="bbpress"><?php printf( __( 'You are using <span class="b">bbPress %s</span>' ), bb_get_option( 'version' ) ); ?></p>
86
- </div>
87
- </div>
88
-
89
- <div id="dashboard-moderated" class="dashboard">
90
- <h3><?php _e('Recently Moderated Items'); ?></h3>
91
- <?php if ( $objects = bb_get_recently_moderated_objects() ) : ?>
92
- <ul class="posts">
93
- <?php add_filter( 'get_topic_where', 'bb_no_where' ); foreach ( $objects as $object ) : ?>
94
- <?php if ( 'post' == $object['type'] ) : global $bb_post; $bb_post = $object['data']; ?>
95
- <li>
96
- <?php
97
- if ( $bb_post->poster_id ) {
98
- printf(
99
- __( '<a href="%1$s">Post</a> on <a href="%2$s">%3$s</a> by <a href="%4$s">%5$s</a>' ),
100
- esc_attr( add_query_arg( 'view', 'all', get_post_link() ) ),
101
- get_topic_link( $bb_post->topic_id ),
102
- get_topic_title( $bb_post->topic_id ),
103
- get_user_profile_link( $bb_post->poster_id ),
104
- get_post_author()
105
- );
106
- } else {
107
- printf(
108
- __( '<a href="%1$s">Post</a> on <a href="%2$s">%3$s</a> by %4$s' ),
109
- esc_attr( add_query_arg( 'view', 'all', get_post_link() ) ),
110
- get_topic_link( $bb_post->topic_id ),
111
- get_topic_title( $bb_post->topic_id ),
112
- get_post_author()
113
- );
114
- }
115
- ?>
116
- </li>
117
- <?php elseif ( 'topic' == $object['type'] ) : global $topic; $topic = $object['data']; ?>
118
- <li>
119
- <?php
120
- if ( $topic->topic_poster ) {
121
- printf(
122
- __( 'Topic titled <a href="%1$s">%2$s</a> started by <a href="%3$s">%4$s</a>' ),
123
- esc_attr( add_query_arg( 'view', 'all', get_topic_link() ) ),
124
- get_topic_title( $topic->topic_id ),
125
- get_user_profile_link( $topic->topic_poster ),
126
- get_topic_author( $topic->topic_id )
127
- );
128
- } else {
129
- printf(
130
- __( 'Topic titled <a href="%1$s">%2$s</a> started by %3$s' ),
131
- esc_attr( add_query_arg( 'view', 'all', get_topic_link() ) ),
132
- get_topic_title( $topic->topic_id ),
133
- get_topic_author( $topic->topic_id )
134
- );
135
- }
136
- ?>
137
- </li>
138
- <?php endif; endforeach; remove_filter( 'get_topic_where', 'bb_no_where' ); ?>
139
- </ul>
140
- <?php else : ?>
141
- <p>
142
- <?php _e('No moderated posts or topics&#8230; you must have very well behaved members.'); ?>
143
- </p>
144
- <?php endif; ?>
145
- </div>
146
- <div class="clear"></div>
147
- </div>
148
-
149
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/install-rtl.css DELETED
@@ -1,100 +0,0 @@
1
- body {
2
- font-family: Tahoma, "Times New Roman";
3
- }
4
-
5
- div#container {
6
- text-align: right;
7
- }
8
-
9
- dl {
10
- border-left-width: 0;
11
- border-right: 1px solid rgb(125, 125, 125);
12
- margin-right: 2.5em;
13
- margin-left: 0;
14
- }
15
-
16
- dt {
17
- padding-right: 0.6em;
18
- padding-left: 0;
19
- }
20
-
21
- dd {
22
- padding-right: 3.6em;
23
- padding-left: 0;
24
- }
25
-
26
- p.status {
27
- right: auto;
28
- left: 0;
29
- text-shadow: none;
30
- }
31
-
32
- h2 {
33
- text-shadow: none;
34
- }
35
-
36
- label a.note-toggle {
37
- float: right;
38
- padding-left: 0;
39
- width: 18px;
40
- margin-left: 0;
41
- margin-right: 6px;
42
- }
43
-
44
- label.has-note.for-textarea a.note-toggle {
45
- margin-left: 0;
46
- margin-right: 6px;
47
- }
48
-
49
- label.has-note.for-select a.note-toggle {
50
- margin-left: 0;
51
- margin-right: 4px;
52
- }
53
-
54
- label.has-note.for-toggle a.note-toggle {
55
- margin-left: 0;
56
- margin-right: 6px;
57
- }
58
-
59
- label.for-textarea span,
60
- label.for-toggle span {
61
- float: right;
62
- }
63
-
64
- label span.error {
65
- margin-right: 3em;
66
- margin-left: 0.4em;
67
- }
68
-
69
- fieldset.buttons label.forward {
70
- float: left;
71
- }
72
-
73
- fieldset.buttons label.back {
74
- float: right;
75
- }
76
-
77
- p.note {
78
- margin-right: 2.5em;
79
- margin-left: 0;
80
- border-left-width: 0;
81
- border-right: 1px solid rgb(50, 140, 0);
82
- }
83
-
84
- input.text {
85
- font-family: Tahoma, "Times New Roman";
86
- float: right;
87
- }
88
-
89
- select {
90
- font-family: Tahoma, "Times New Roman";
91
- float: right;
92
- }
93
-
94
- textarea {
95
- font-family: Tahoma, "Times New Roman";
96
- }
97
-
98
- input.button {
99
- font-family: Tahoma, "Times New Roman";
100
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/install.css DELETED
@@ -1,433 +0,0 @@
1
- /*
2
- Start with some basic resets
3
- */
4
-
5
- /*
6
- Copyright (c) 2009, Yahoo! Inc. All rights reserved.
7
- Code licensed under the BSD License:
8
- http://developer.yahoo.net/yui/license.txt
9
- version: 2.7.0
10
- */
11
- html{color:#000;background:#FFF;}
12
- body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}
13
- table{border-collapse:collapse;border-spacing:0;}
14
- fieldset,img{border:0;}
15
- address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}
16
- del,ins{text-decoration:none;}
17
- li{list-style:none;}
18
- caption,th{text-align:left;}
19
- h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}
20
- q:before,q:after{content:'';}
21
- abbr,acronym{border:0;font-variant:normal;}
22
- sup{vertical-align:baseline;}
23
- sub{vertical-align:baseline;}
24
- legend{color:#000;}
25
- input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}
26
- input,button,textarea,select{*font-size:100%;}
27
- body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
28
- select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}
29
- table{font-size:inherit;font:100%;}
30
- pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
31
-
32
- /*
33
- Now for our own code
34
- */
35
-
36
- html {
37
- background-color: rgb(247, 247, 247);
38
- }
39
-
40
- body {
41
- text-align: center;
42
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
43
- font-size: 1em;
44
- color: rgb(255, 255, 255);
45
- }
46
-
47
- div#container {
48
- margin: 2em auto 1em auto;
49
- padding: 1em 32px;
50
- width: 700px;
51
- background-color: rgb(255, 255, 255);
52
- text-align: left;
53
- -moz-border-radius: 11px;
54
- -khtml-border-radius: 11px;
55
- -webkit-border-radius: 11px;
56
- border-radius: 11px;
57
- border: 1px solid rgb(223, 223, 223);
58
- color: rgb(51, 51, 51);
59
- }
60
-
61
- a {
62
- color: rgb(50, 140, 0);
63
- text-decoration: none;
64
- }
65
-
66
- a:hover {
67
- text-decoration: underline;
68
- }
69
-
70
- strong {
71
- font-weight: bold;
72
- }
73
-
74
- em {
75
- font-style: italic;
76
- }
77
-
78
- div.logo img {
79
- margin: 12px 0 27px 0;
80
- width: 200px;
81
- height: 57px;
82
- display: block;
83
- }
84
-
85
- h1 {
86
- margin: 0 0 2em 0;
87
- font-size: 0.75em;
88
- font-weight: bold;
89
- }
90
-
91
- p {
92
- margin: 0 0 1em 0;
93
- font-size: 0.75em;
94
- line-height: 1.4em;
95
- }
96
-
97
- dl {
98
- border-left: 1px solid rgb(125, 125, 125);
99
- margin: 1.5em 0 1.5em 2.5em;
100
- font-size: 0.75em;
101
- }
102
-
103
- dl code {
104
- font-size: 1.4em;
105
- }
106
-
107
- dt {
108
- font-size: 1em;
109
- padding: 0.6em 0 0.2em 0.6em;
110
- }
111
-
112
- dd {
113
- font-size: 1em;
114
- padding: 0 0 0.6em 3.6em;
115
- }
116
-
117
- p.status {
118
- position: absolute;
119
- right: 0;
120
- top: -2.4em;
121
- margin: 0;
122
- padding: 0.5em 1em;
123
- line-height: 1.4em;
124
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
125
- color: rgb(70, 70, 70);
126
- }
127
-
128
- p code {
129
- font-size: 1.25em;
130
- }
131
-
132
- div.open div p.error.last,
133
- div.open div p.message.last {
134
- margin-bottom: 1.4em;
135
- }
136
-
137
- h2 {
138
- font-size: 0.75em;
139
- background-color: rgb(236, 236, 236);
140
- padding: 0.5em 1em;
141
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
142
- color: rgb(70, 70, 70);
143
- font-weight: bold;
144
- line-height: 1.4em;
145
- }
146
-
147
- div.open,
148
- div.closed {
149
- border: 1px solid rgb(223, 223, 223);
150
- -moz-border-radius: 6px;
151
- -khtml-border-radius: 6px;
152
- -webkit-border-radius: 6px;
153
- border-radius: 6px;
154
- margin-bottom: 1em;
155
- background-color: rgb(247, 247, 247);
156
- }
157
-
158
- div.open div {
159
- padding: 1em;
160
- margin: 1px 0;
161
- }
162
-
163
- div.closed div {
164
- position: relative;
165
- }
166
-
167
- p.error {
168
- border: 1px solid rgb(204, 0, 0);
169
- background-color: rgb(255, 235, 232);
170
- padding: 0.6em;
171
- -moz-border-radius: 4px;
172
- -khtml-border-radius: 4px;
173
- -webkit-border-radius: 4px;
174
- border-radius: 4px;
175
- }
176
-
177
- p.error a {
178
- color: rgb(204, 0, 0);
179
- }
180
-
181
- dl.error {
182
- margin-top: -1em;
183
- }
184
-
185
- p.message {
186
- border: 1px solid rgb(230, 219, 85);
187
- background-color: rgb(255, 251, 204);
188
- padding: 0.6em;
189
- -moz-border-radius: 4px;
190
- -khtml-border-radius: 4px;
191
- -webkit-border-radius: 4px;
192
- border-radius: 4px;
193
- }
194
-
195
- div.open div.toggle {
196
- margin: 0;
197
- padding: 0;
198
- }
199
-
200
- div.open h2 {
201
- color: rgb(0, 0, 0);
202
- }
203
-
204
- form {
205
- clear: both;
206
- border: 1px solid rgb(223, 223, 223);
207
- background-color: rgb(255, 255, 255);
208
- -moz-border-radius: 4px;
209
- -khtml-border-radius: 4px;
210
- -webkit-border-radius: 4px;
211
- border-radius: 4px;
212
- padding: 1em 1em 1em 1em;
213
- }
214
-
215
- legend {
216
- font-size: 0.9em;
217
- font-weight: bold;
218
- padding-bottom: 0.5em;
219
- }
220
-
221
- label {
222
- display: block;
223
- margin: 0 0 1.8em 0;
224
- font-size: 0.75em;
225
- color: rgb(34, 34, 34);
226
- cursor: pointer;
227
- clear: both;
228
- }
229
-
230
- label span {
231
- display: block;
232
- margin-bottom: 5px;
233
- }
234
-
235
- label.error {
236
- border: 1px solid rgb(204, 0, 0);
237
- background-color: rgb(255, 235, 232);
238
- padding: 0.6em;
239
- -moz-border-radius: 4px;
240
- -khtml-border-radius: 4px;
241
- -webkit-border-radius: 4px;
242
- border-radius: 4px;
243
- }
244
-
245
- label.forward {
246
- clear: none;
247
- }
248
-
249
- label a.note-toggle {
250
- background-color: rgb(223, 223, 223);
251
- color: rgb(255, 255, 255);
252
- display: block;
253
- text-align: center;
254
- float: left;
255
- font-weight: bold;
256
- font-size: 1.2em;
257
- padding-top: 1px;
258
- padding-left: 1px;
259
- width: 18px;
260
- height: 18px;
261
- line-height: 18px;
262
- margin-left: 6px;
263
- margin-top: 4px;
264
- -moz-border-radius: 9px;
265
- -khtml-border-radius: 9px;
266
- -webkit-border-radius: 9px;
267
- border-radius: 9px;
268
- }
269
-
270
- label a.note-toggle:hover {
271
- text-decoration: none;
272
- background-color: rgb(50, 140, 0);
273
- }
274
-
275
- label.has-note.for-textarea a.note-toggle {
276
- margin-top: -2px;
277
- margin-left: 6px;
278
- }
279
-
280
- label.has-note.for-select a.note-toggle {
281
- margin-top: 3px;
282
- margin-left: 4px;
283
- }
284
-
285
- label.has-note.for-toggle a.note-toggle {
286
- margin-top: -2px;
287
- margin-left: 6px;
288
- }
289
-
290
- label.for-textarea span,
291
- label.for-toggle span {
292
- float: left;
293
- }
294
-
295
- label.for-toggle span {
296
- margin-bottom: 0;
297
- }
298
-
299
- label span.error {
300
- color: rgb(204, 0, 0);
301
- display: block;
302
- margin: 0.4em 0.4em 0.4em 3em;
303
- }
304
-
305
- label code {
306
- font-size: 1.25em;
307
- }
308
-
309
- fieldset.buttons label.forward {
310
- margin: 0;
311
- float: right;
312
- }
313
-
314
- fieldset.buttons label.back {
315
- margin: 0;
316
- float: left;
317
- }
318
-
319
- p.note {
320
- margin: 0 0 0 2.5em;
321
- color: rgb(102, 102, 102);
322
- border-left: 1px solid rgb(50, 140, 0);
323
- padding: 0.6em;
324
- font-size: 0.9em;
325
- font-style: italic;
326
- clear: both;
327
- }
328
-
329
- input.text {
330
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
331
- font-size: 1.2em;
332
- padding: 4px;
333
- border: 1px solid rgb(187, 187, 187);
334
- width: 400px;
335
- display: block;
336
- float: left;
337
- -moz-border-radius: 4px;
338
- -khtml-border-radius: 4px;
339
- -webkit-border-radius: 4px;
340
- border-radius: 4px;
341
- clear: both;
342
- }
343
-
344
- select {
345
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
346
- font-size: 1.2em;
347
- padding: 0;
348
- border: 1px solid rgb(187, 187, 187);
349
- display: block;
350
- float: left;
351
- }
352
-
353
- textarea {
354
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
355
- font-size: 0.9em;
356
- padding: 0;
357
- border: 1px solid rgb(187, 187, 187);
358
- width: 630px;
359
- max-width: 630px;
360
- height: 38em;
361
- display: block;
362
- -moz-border-radius: 4px;
363
- -khtml-border-radius: 4px;
364
- -webkit-border-radius: 4px;
365
- border-radius: 4px;
366
- clear: both;
367
- }
368
-
369
- textarea#config {
370
- text-align: left;
371
- }
372
-
373
- textarea.short,
374
- textarea#error_log {
375
- height: 15em;
376
- }
377
-
378
- textarea#error_log {
379
- border-color: rgb(153, 0, 0);
380
- color: rgb(153, 0, 0);
381
- }
382
-
383
- input.checkbox {
384
- font-size: 1.25em;
385
- }
386
-
387
- input.button {
388
- background: url('images/white-grad.png') repeat-x 0 0 rgb(242, 242, 242);
389
- -moz-border-radius: 15px;
390
- -khtml-border-radius: 15px;
391
- -webkit-border-radius: 15px;
392
- border-radius: 15px;
393
- border: 1px solid rgb(187, 187, 187);
394
- color: rgb(70, 70, 70);
395
- cursor: pointer;
396
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
397
- font-size: 1.2em;
398
- line-height: 1.2em;
399
- padding: 0.45em 0.9em;
400
- text-decoration: none;
401
- }
402
-
403
- input.button:hover {
404
- border-color: rgb(102, 102, 102);
405
- color: rgb(0, 0, 0);
406
- }
407
-
408
- input.button:active {
409
- background-image: url('images/white-grad-active.png');
410
- }
411
-
412
- label#label-toggle_4 {
413
- margin-bottom: 0;
414
- }
415
-
416
- label#label-toggle_4 span {
417
- margin-bottom: 0.4em;
418
- }
419
-
420
- label#label-error_log,
421
- label#label-installation_log {
422
- margin-top: 1.8em;
423
- margin-bottom: 0;
424
- }
425
-
426
- div.clear {
427
- clear: both;
428
- height: 0;
429
- line-height: 0;
430
- font-size: 0;
431
- margin: 0 !important;
432
- padding: 0 !important;
433
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/install.php DELETED
@@ -1,401 +0,0 @@
1
- <?php
2
- // Modify error reporting levels
3
- error_reporting(E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING);
4
-
5
- // Let everyone know we are installing
6
- define('BB_INSTALLING', true);
7
-
8
- // Load bbPress
9
- require_once('../bb-load.php');
10
-
11
- // Instantiate the install class
12
- require_once( BB_PATH . 'bb-admin/includes/class.bb-install.php' );
13
- $bb_install = new BB_Install(__FILE__);
14
-
15
- $bb_install->header();
16
- ?>
17
- <script type="text/javascript" charset="utf-8">
18
- function toggleNote(target) {
19
- var targetObj = document.getElementById(target);
20
- if (targetObj.style.display == 'none') {
21
- targetObj.style.display = 'block';
22
- } else {
23
- targetObj.style.display = 'none';
24
- }
25
- }
26
- function toggleBlock(toggleObj, target) {
27
- var targetObj = document.getElementById(target);
28
- if (toggleObj.checked) {
29
- targetObj.style.display = 'block';
30
- } else {
31
- targetObj.style.display = 'none';
32
- }
33
- }
34
- function toggleValue(toggleObj, target, offValue, onValue) {
35
- var targetObj = document.getElementById(target);
36
- if (toggleObj.checked) {
37
- targetObj.value = onValue;
38
- } else {
39
- targetObj.value = offValue;
40
- }
41
- }
42
- </script>
43
- <?php
44
- switch ($bb_install->step) {
45
- case -1:
46
- $bb_install->messages();
47
- $bb_install->intro();
48
- break;
49
-
50
- default:
51
- $bb_install->step_header(0);
52
-
53
- if ($bb_install->step === 0) {
54
- ?>
55
- <form action="install.php" method="post">
56
- <?php
57
- $bb_install->messages();
58
- $bb_install->get_language_selector();
59
- $bb_install->input_buttons('forward_0_0', false, 1);
60
- ?>
61
- </form>
62
- <?php
63
- } else {
64
- $bb_install->sanitize_form_data();
65
- }
66
-
67
- $bb_install->step_footer();
68
-
69
- $bb_install->step_header(1);
70
-
71
- if ($bb_install->step === 1) {
72
-
73
- switch($bb_install->step_status[1]) {
74
- case 'incomplete':
75
- ?>
76
- <form action="install.php" method="post">
77
- <?php
78
- $bb_install->messages();
79
- ?>
80
- <fieldset>
81
- <?php
82
- $bb_install->input_text('bbdb_name');
83
- $bb_install->input_text('bbdb_user');
84
- $bb_install->input_text('bbdb_password');
85
- $bb_install->input_text('bbdb_host');
86
- $bb_install->select_language();
87
- $bb_install->input_toggle('toggle_1');
88
- ?>
89
- <div class="toggle" id="toggle_1_target" style="<?php echo esc_attr( 'display:' . $bb_install->data[$bb_install->step]['form']['toggle_1']['display'] ); ?>;">
90
- <?php
91
- $bb_install->input_text('bbdb_charset');
92
- $bb_install->input_text('bbdb_collate');
93
- //$bb_install->input_text('bb_auth_key');
94
- //$bb_install->input_text('bb_secure_auth_key');
95
- //$bb_install->input_text('bb_logged_in_key');
96
- //$bb_install->input_text('bb_nonce_key');
97
- $bb_install->input_text('bb_table_prefix', 'ltr');
98
- ?>
99
- </div>
100
- </fieldset>
101
- <?php
102
- $bb_install->input_buttons('forward_1_0');
103
- ?>
104
- </form>
105
- <?php
106
- break;
107
-
108
- case 'manual':
109
- ?>
110
- <form action="install.php" method="post">
111
- <?php
112
- $bb_install->messages();
113
- $bb_install->hidden_step_inputs();
114
- ?>
115
- <fieldset>
116
- <?php
117
- $bb_install->textarea('config', 'ltr');
118
- ?>
119
- </fieldset>
120
- <?php
121
- $bb_install->input_buttons('forward_1_1', 'back_1_1');
122
- ?>
123
- </form>
124
- <?php
125
- break;
126
-
127
- case 'complete':
128
- ?>
129
- <form action="install.php" method="post">
130
- <?php
131
- $bb_install->messages();
132
- $bb_install->input_buttons('forward_1_2', false, 2);
133
- ?>
134
- </form>
135
- <?php
136
- break;
137
- }
138
- }
139
-
140
- $bb_install->step_footer();
141
-
142
- $bb_install->step_header(2);
143
-
144
- if ($bb_install->step === 2) {
145
-
146
- switch ($bb_install->step_status[2]) {
147
- case 'incomplete':
148
- ?>
149
- <form action="install.php" method="post">
150
- <?php
151
- $bb_install->messages();
152
- ?>
153
- <fieldset>
154
- <?php
155
- bb_nonce_field('bbpress-installer');
156
- $bb_install->input_toggle('toggle_2_0');
157
- ?>
158
- </fieldset>
159
- <div class="toggle" id="toggle_2_0_target" style="<?php echo esc_attr( 'display:' . $bb_install->data[$bb_install->step]['form']['toggle_2_0']['display'] ); ?>;">
160
- <fieldset>
161
- <?php
162
- $bb_install->input_toggle('toggle_2_1');
163
- ?>
164
- </fieldset>
165
- <div class="toggle" id="toggle_2_1_target" style="<?php echo esc_attr( 'display:' . $bb_install->data[$bb_install->step]['form']['toggle_2_1']['display'] ); ?>;">
166
- <fieldset>
167
- <legend><?php _e('Cookies'); ?></legend>
168
- <p><?php _e('Integrating cookies allows you and your users to login to either your bbPress or your WordPress site and be automatically logged into both.'); ?></p>
169
- <p><?php _e('You may need to make changes to your WordPress configuration once installation is complete. See the "WordPress Integration" section of the bbPress administration area when you are done.'); ?></p>
170
- <?php
171
- $bb_install->input_text('wp_siteurl', 'ltr');
172
- $bb_install->input_text('wp_home', 'ltr');
173
- $bb_install->input_text('wp_auth_key');
174
- $bb_install->input_text('wp_auth_salt');
175
- $bb_install->input_text('wp_secure_auth_key');
176
- $bb_install->input_text('wp_secure_auth_salt');
177
- $bb_install->input_text('wp_logged_in_key');
178
- $bb_install->input_text('wp_logged_in_salt');
179
- ?>
180
- </fieldset>
181
- </div>
182
- <fieldset>
183
- <?php
184
- $bb_install->input_toggle('toggle_2_2');
185
- ?>
186
- </fieldset>
187
- <div class="toggle" id="toggle_2_2_target" style="<?php echo esc_attr( 'display:' . $bb_install->data[$bb_install->step]['form']['toggle_2_2']['display'] ); ?>;">
188
- <fieldset>
189
- <legend><?php _e('User database'); ?></legend>
190
- <p><?php _e('Integrating your WordPress database user tables allows you to store user data in one location, instead of having separate user data for both bbPress and WordPress.'); ?></p>
191
- <?php
192
- $bb_install->input_text('wp_table_prefix', 'ltr');
193
- $bb_install->input_text('wordpress_mu_primary_blog_id', 'ltr');
194
- $bb_install->input_toggle('toggle_2_3');
195
- ?>
196
- </fieldset>
197
- <div class="toggle" id="toggle_2_3_target" style="<?php echo esc_attr( 'display:' . $bb_install->data[$bb_install->step]['form']['toggle_2_3']['display'] ); ?>;">
198
- <fieldset>
199
- <legend><?php _e('Separate user database settings'); ?></legend>
200
- <p><?php _e('Most of the time these settings are <em>not</em> required. Look before you leap!'); ?></p>
201
- <p><?php _e('If required, then all settings except for the character set must be specified.'); ?></p>
202
- <?php
203
- $bb_install->input_text('user_bbdb_name');
204
- $bb_install->input_text('user_bbdb_user');
205
- $bb_install->input_text('user_bbdb_password');
206
- $bb_install->input_text('user_bbdb_host');
207
- $bb_install->input_text('user_bbdb_charset');
208
- $bb_install->input_text('user_bbdb_collate');
209
- ?>
210
- </fieldset>
211
- <fieldset>
212
- <legend><?php _e('Custom user tables'); ?></legend>
213
- <p><?php _e('Only set these options if your integrated user tables do not fit the usual mould of <em>wp_user</em> and <em>wp_usermeta</em>.'); ?></p>
214
- <?php
215
- $bb_install->input_text('custom_user_table');
216
- $bb_install->input_text('custom_user_meta_table');
217
- ?>
218
- </fieldset>
219
- </div>
220
- </div>
221
- </div>
222
- <?php
223
- $bb_install->input_buttons('forward_2_0');
224
- ?>
225
- </form>
226
- <script type="text/javascript" charset="utf-8">
227
- function updateWordPressOptionURL () {
228
- var siteURLInputValue = document.getElementById('wp_siteurl').value;
229
- if (siteURLInputValue && siteURLInputValue.substr(-1,1) != '/') {
230
- siteURLInputValue += '/';
231
- }
232
- var authSaltAnchor = document.getElementById('getAuthSaltOption');
233
- var secureAuthSaltAnchor = document.getElementById('getSecureAuthSaltOption');
234
- var loggedInSaltAnchor = document.getElementById('getLoggedInSaltOption');
235
- if (siteURLInputValue) {
236
- authSaltAnchor.href = siteURLInputValue + 'wp-admin/options.php';
237
- secureAuthSaltAnchor.href = siteURLInputValue + 'wp-admin/options.php';
238
- loggedInSaltAnchor.href = siteURLInputValue + 'wp-admin/options.php';
239
- } else {
240
- authSaltAnchor.href = '';
241
- secureAuthSaltAnchor.href = '';
242
- loggedInSaltAnchor.href = '';
243
- }
244
- }
245
- var siteURLInput = document.getElementById('wp_siteurl');
246
- if (siteURLInput.value) {
247
- updateWordPressOptionURL();
248
- }
249
- siteURLInput.onkeyup = updateWordPressOptionURL;
250
- siteURLInput.onblur = updateWordPressOptionURL;
251
- siteURLInput.onclick = updateWordPressOptionURL;
252
- siteURLInput.onchange = updateWordPressOptionURL;
253
- </script>
254
- <?php
255
- break;
256
-
257
- case 'complete':
258
- ?>
259
- <form action="install.php" method="post">
260
- <?php
261
- $bb_install->messages();
262
- ?>
263
- <fieldset>
264
- <?php
265
- bb_nonce_field('bbpress-installer');
266
- ?>
267
- </fieldset>
268
- <?php
269
- $bb_install->hidden_step_inputs();
270
- $bb_install->input_buttons('forward_2_1', 'back_2_1', 3);
271
- ?>
272
- </form>
273
- <?php
274
- break;
275
- }
276
- }
277
-
278
- $bb_install->step_footer();
279
-
280
- $bb_install->step_header(3);
281
-
282
- if ($bb_install->step === 3) {
283
-
284
- switch($bb_install->step_status[3]) {
285
- case 'incomplete':
286
- ?>
287
- <form action="install.php" method="post">
288
- <?php
289
- $bb_install->messages();
290
- ?>
291
- <fieldset>
292
- <?php
293
- bb_nonce_field('bbpress-installer');
294
- ?>
295
- </fieldset>
296
- <?php
297
- $bb_install->hidden_step_inputs(2);
298
- ?>
299
- <fieldset>
300
- <?php
301
- $bb_install->input_text('name');
302
- $bb_install->input_text('uri', 'ltr');
303
-
304
- if ($bb_install->populate_keymaster_user_login_from_user_tables()) {
305
- echo $bb_install->strings[3]['scripts']['changeKeymasterEmail'];
306
- $bb_install->select('keymaster_user_login');
307
- $bb_install->input_hidden('keymaster_user_email');
308
- } else {
309
- $bb_install->input_text('keymaster_user_login');
310
- $bb_install->input_text('keymaster_user_email', 'ltr');
311
- }
312
- $bb_install->input_hidden('keymaster_user_type');
313
-
314
- if (!$bb_install->database_tables_are_installed()) {
315
- $bb_install->input_text('forum_name');
316
- }
317
- ?>
318
- </fieldset>
319
- <?php
320
- $bb_install->input_buttons('forward_3_0');
321
- ?>
322
- </form>
323
- <?php
324
- break;
325
-
326
- case 'complete':
327
- ?>
328
- <form action="install.php" method="post">
329
- <?php
330
- $bb_install->messages();
331
- ?>
332
- <fieldset>
333
- <?php
334
- bb_nonce_field('bbpress-installer');
335
- ?>
336
- </fieldset>
337
- <?php
338
- $bb_install->hidden_step_inputs(2);
339
- $bb_install->hidden_step_inputs(); // The current step (3) is assumed here
340
- $bb_install->input_buttons('forward_3_1', 'back_3_1', 4);
341
- ?>
342
- </form>
343
- <?php
344
- break;
345
- }
346
- }
347
-
348
- $bb_install->step_footer();
349
-
350
- if ($bb_install->step === 4) {
351
-
352
- $bb_install->step_header(4);
353
- $bb_install->messages();
354
-
355
- if ($bb_install->step_status[4] == 'complete') {
356
- ?>
357
- <p><?php _e('You can now log in with the following details:'); ?></p>
358
- <dl>
359
- <dt><?php _e('Username:'); ?></dt>
360
- <dd><code><?php echo esc_html( $bb_install->data[3]['form']['keymaster_user_login']['value'] ); ?></code></dd>
361
- <dt><?php _e('Password:'); ?></dt>
362
- <dd><code><?php echo esc_html( $bb_install->data[4]['form']['keymaster_user_password']['value'] ); ?></code></dd>
363
- <dt><?php _e('Site address:'); ?></dt>
364
- <dd dir="ltr"><a href="<?php bb_uri(); ?>"><?php bb_uri(null, null, BB_URI_CONTEXT_TEXT); ?></a></dd>
365
- </dl>
366
- <?php
367
- if ($bb_install->data[3]['form']['keymaster_user_type']['value'] == 'bbPress') {
368
- ?>
369
- <p><?php _e('<strong><em>Note that password</em></strong> carefully! It is a <em>random</em> password that was generated just for you. If you lose it, you will have to delete the tables from the database yourself, and re-install bbPress.'); ?></p>
370
- <?php
371
- }
372
- }
373
- ?>
374
- <form action="<?php bb_uri(null, null, BB_URI_CONTEXT_FORM_ACTION); ?>">
375
- <fieldset>
376
- <?php
377
- $bb_install->input_toggle('toggle_4');
378
- ?>
379
- <div class="toggle" id="toggle_4_target" style="display:none;">
380
- <?php
381
- if ($bb_install->data[4]['form']['error_log']['value']) {
382
- $bb_install->textarea('error_log');
383
- }
384
- $bb_install->textarea('installation_log');
385
- ?>
386
- </div>
387
- </fieldset>
388
- </form>
389
- <?php
390
- $bb_install->step_footer();
391
-
392
- } else {
393
- //? >
394
- // <div id="step4" class="closed"></div>
395
- //<?php
396
- }
397
-
398
- break;
399
- }
400
- $bb_install->footer();
401
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/js/admin-forums.js DELETED
@@ -1,140 +0,0 @@
1
- jQuery( function($) { // In here $ is jQuery
2
-
3
- bbSortForums = {
4
- handleText: 'drag',
5
- handle: '',
6
- sortCfg: {
7
- accept: 'forum',
8
- handle: 'img.sort-handle',
9
- opacity: .3,
10
- helperclass: 'helper',
11
- onStop: function() {
12
- bbSortForums.place = null;
13
- bbSortForums.recolor();
14
- }
15
- },
16
- editText: 'Edit Forum Order',
17
- saveText: 'Save Forum Order',
18
- place: null, // The id of the list item it's currently hovering before
19
- placed: null, // The id of the list item it's been made a child of
20
- rtl: 'rtl' == $('html').attr( 'dir' ),
21
-
22
- recolor: function() {
23
- $('#forum-list li:gt(0)').css( 'background-color', '' ).filter(':even').removeClass('alt').end().filter(':odd').addClass('alt');
24
- },
25
-
26
- checkHover: function(el, doit) {
27
- if ( this.place == el.id && doit )
28
- return;
29
-
30
- if ( !doit ) {
31
- this.place = null;
32
- return;
33
- }
34
-
35
- this.place = el.id;
36
- if ( $('#' + this.place).children('ul:has(li:visible)').size() ) // Don't shift over if there's already a UL with stuff in it
37
- return;
38
-
39
- var id = this.place.split('-')[1];
40
- $('#' + this.place).not(':has(ul)').append("<ul id='forum-root-" + id + "' class='list-block holder'></ul>").end().children('ul').append(jQuery.iSort.helper.get(0)); // Place in shifted box
41
- this.placed = 'forum-' + id;
42
- },
43
-
44
- serialize: function () {
45
- h = '';
46
- $('#forum-list, #forum-list ul').each( function() {
47
- var i = this.id;
48
- $('#' + i + '> .forum').each( function () {
49
- if (h.length > 0)
50
- h += '&';
51
- var root = 'forum-list' == i ? 0 : i.split('-')[2];
52
- h += 'root[' + root + '][]=' + this.id.split('-')[1];
53
- } );
54
- } );
55
- return h;
56
- },
57
-
58
- init: function() {
59
- this.handle = "<img class='sort-handle' src='images/drag.gif' alt='" + this.handleText + "' />";
60
- var div = document.createElement('div');
61
- div.innerHTML = this.saveText; // Save the raquo!
62
- this.saveText = div.childNodes[0].nodeValue;
63
- div.innerHTML = this.editText; // Save the raquo!
64
- this.editText = div.childNodes[0].nodeValue;
65
- div = null;
66
- $('#forum-list').after("<form class='settings' action='' onsubmit='return false;'><fieldset class='submit'><input class='submit' type='submit' name='submit' id='forum-order-edit' value='" + this.editText + "' /></fieldset></form>");
67
-
68
- $('#forum-order-edit').toggle( function() {
69
- $(this).val(bbSortForums.saveText);
70
- $('#forum-list li:gt(0) div.row-title').before(bbSortForums.handle);
71
- $('#forum-list').Sortable( bbSortForums.sortCfg );
72
- $('body').addClass('sorting');
73
- }, function() {
74
- $(this).val(bbSortForums.editText);
75
- $('.sort-handle').remove();
76
-
77
- var hash = bbSortForums.serialize();
78
- hash += '&' + $.SortSerialize('forum-list').hash.replace(/forum-list/g, 'order').replace(/forum-/g, '')
79
- $('#forum-list').SortableDestroy();
80
- $('body').removeClass('sorting');
81
-
82
- $.post(
83
- 'admin-ajax.php',
84
- 'action=order-forums&_ajax_nonce=' + $('#add-forum input[name=order-nonce]').val() + '&' + hash
85
- );
86
- } );
87
- }
88
- }
89
-
90
- // overwrite with more advanced function
91
- jQuery.iSort.checkhover = function(e,o) {
92
- if (!jQuery.iDrag.dragged)
93
- return;
94
-
95
- if ( e.dropCfg.el.size() > 0 ) {
96
- var bottom = jQuery.grep(e.dropCfg.el, function(i) { // All the list items whose bottom edges are inside the draggable
97
- var x = bbSortForums.rtl ? i.pos.x + i.pos.wb > jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.wb : i.pos.x < jQuery.iDrag.dragged.dragCfg.nx;
98
- return i.pos.y + i.pos.hb > jQuery.iDrag.dragged.dragCfg.ny && i.pos.y + i.pos.hb < jQuery.iDrag.dragged.dragCfg.ny + 30 && x;
99
- } );
100
-
101
- if ( bottom.length > 0 ) { // Use the lowest one one the totem pole
102
- var x = bbSortForums.rtl ? bottom[bottom.length-1].pos.x + bottom[bottom.length-1].pos.wb - 30 > jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.wb : bottom[bottom.length-1].pos.x + 30 < jQuery.iDrag.dragged.dragCfg.nx;
103
- if ( bbSortForums.placed != bottom[bottom.length-1].id || !x ) { // Testing to see if still placed in shifted box
104
- bbSortForums.placed = null;
105
- jQuery(bottom[bottom.length-1]).after(jQuery.iSort.helper.get(0));
106
- }
107
- bbSortForums.checkHover(bottom[bottom.length-1], x); // If far enough right, shift it over
108
- return;
109
- }
110
-
111
- // Didn't find anything by checking bottems. Look at tops
112
- var top = jQuery.grep(e.dropCfg.el, function(i) { // All the list items whose top edges are inside the draggable
113
- var x = bbSortForums.rtl ? i.pos.x + i.pos.wb > jQuery.iDrag.dragged.dragCfg.nx : i.pos.x < jQuery.iDrag.dragged.dragCfg.nx;
114
- return i.pos.y > jQuery.iDrag.dragged.dragCfg.ny && i.pos.y < jQuery.iDrag.dragged.dragCfg.ny + 30 && x;
115
- } );
116
-
117
- if ( top.length ) { // Use the highest one (should be only one)
118
- jQuery(top[0]).before(jQuery.iSort.helper.get(0));
119
- bbSortForums.checkHover(top[0], false);
120
- return;
121
- }
122
- }
123
- jQuery.iSort.helper.get(0).style.display = 'block';
124
- }
125
-
126
- if ( 'undefined' != typeof bbSortForumsL10n )
127
- $.extend( bbSortForums, bbSortForumsL10n );
128
-
129
- bbSortForums.init();
130
-
131
- var options = $('#forum-parent').get(0).options;
132
- var addAfter = function( r, settings ) {
133
- var name = $("<span>" + $('name', r).text() + "</span>").html();
134
- var id = $('forum', r).attr('id');
135
- options[options.length] = new Option(name, id);
136
- }
137
-
138
- $('#forum-list').wpList( { addAfter: addAfter } );
139
-
140
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/js/common.js DELETED
@@ -1,93 +0,0 @@
1
- var showNotice, adminMenu, columns;
2
- (function($){
3
- // sidebar admin menu
4
- adminMenu = {
5
-
6
- init : function() {
7
- $('ul#bbAdminMenu li.bb-menu div.bb-menu-toggle').each( function() {
8
- if ( $(this).siblings('div.bb-menu-sub-wrap').length )
9
- $(this).click(function(){ adminMenu.toggle( $(this).siblings('div.bb-menu-sub-wrap') ); });
10
- else
11
- $(this).hide();
12
- });
13
-
14
- $('#bbAdminMenu li.bb-menu.bb-menu-separator a').click(function(){
15
- if ( $('body').hasClass('bb-menu-folded') ) {
16
- adminMenu.fold(1);
17
- deleteUserSetting( 'fm' );
18
- } else {
19
- adminMenu.fold();
20
- setUserSetting( 'fm', 'f' );
21
- }
22
- return false;
23
- });
24
-
25
- if ( $('body').hasClass('bb-menu-folded') ) {
26
- this.fold();
27
- }
28
- this.restoreMenuState();
29
- },
30
-
31
- restoreMenuState : function() {
32
- $('ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu').each(function(i, e) {
33
- var v = getUserSetting( 'm'+i );
34
- if ( $(e).hasClass('bb-menu-current') ) return true; // leave the current parent open
35
-
36
- if ( 'o' == v ) $(e).addClass('bb-menu-open');
37
- else if ( 'c' == v ) $(e).removeClass('bb-menu-open');
38
- });
39
- },
40
-
41
- toggle : function(el) {
42
- el['slideToggle'](150, function(){el.css('display','');}).parent().toggleClass( 'bb-menu-open' );
43
-
44
- $('ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu').each(function(i, e) {
45
- var v = $(e).hasClass('bb-menu-open') ? 'o' : 'c';
46
- setUserSetting( 'm'+i, v );
47
- });
48
-
49
- return false;
50
- },
51
-
52
- fold : function(off) {
53
- if (off) {
54
- $('body').removeClass('bb-menu-folded');
55
- $('#bbAdminMenu li.bb-menu.bb-menu-has-submenu').unbind();
56
- } else {
57
- $('body').addClass('bb-menu-folded');
58
- $('#bbAdminMenu li.bb-menu.bb-menu-has-submenu').hoverIntent({
59
- over: function(e){
60
- var m, b, h, o, f;
61
- m = $(this).find('div.bb-menu-sub-wrap');
62
- b = m.parent().offset().top + m.height() + 1; // Bottom offset of the menu
63
- h = $('#bbWrap').height(); // Height of the entire page
64
- o = 60 + b - h;
65
- f = $(window).height() + $('body').scrollTop() - 15; // The fold
66
- if (f < (b - o)) {
67
- o = b - f;
68
- }
69
- if (o > 1) {
70
- m.css({'marginTop':'-'+o+'px'});
71
- } else if ( m.css('marginTop') ) {
72
- m.css({'marginTop':''});
73
- }
74
- m.addClass('bb-menu-sub-open');
75
- },
76
- out: function(){ $(this).find('div.bb-menu-sub-wrap').removeClass('bb-menu-sub-open').css({'marginTop':''}); },
77
- timeout: 220,
78
- sensitivity: 8,
79
- interval: 100
80
- });
81
- }
82
- }
83
- };
84
-
85
- $(document).ready(function(){
86
- adminMenu.init();
87
- $('thead .check-column :checkbox, tfoot .check-column :checkbox').click( function() {
88
- $(this).parents( 'table' ).find( '.check-column :checkbox' ).attr( 'checked', $(this).is( ':checked' ) ? 'checked' : false );
89
- } );
90
- });
91
-
92
-
93
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/js/utils.js DELETED
@@ -1,166 +0,0 @@
1
- // utility functions
2
- function convertEntities(o) {
3
- var c, v;
4
- c = function(s) {
5
- if (/&[^;]+;/.test(s)) {
6
- var e = document.createElement("div");
7
- e.innerHTML = s;
8
- return !e.firstChild ? s : e.firstChild.nodeValue;
9
- }
10
- return s;
11
- }
12
-
13
- if ( typeof o === 'string' ) {
14
- return c(o);
15
- } else if ( typeof o === 'object' ) {
16
- for (v in o) {
17
- if ( typeof o[v] === 'string' ) {
18
- o[v] = c(o[v]);
19
- }
20
- }
21
- }
22
- return o;
23
- }
24
-
25
- var wpCookies = {
26
- // The following functions are from Cookie.js class in TinyMCE, Moxiecode, used under LGPL.
27
-
28
- each : function(o, cb, s) {
29
- var n, l;
30
-
31
- if (!o)
32
- return 0;
33
-
34
- s = s || o;
35
-
36
- if (typeof(o.length) != 'undefined') {
37
- for (n=0, l = o.length; n<l; n++) {
38
- if (cb.call(s, o[n], n, o) === false)
39
- return 0;
40
- }
41
- } else {
42
- for (n in o) {
43
- if (o.hasOwnProperty(n)) {
44
- if (cb.call(s, o[n], n, o) === false) {
45
- return 0;
46
- }
47
- }
48
- }
49
- }
50
- return 1;
51
- },
52
-
53
- getHash : function(n) {
54
- var v = this.get(n), h;
55
-
56
- if (v) {
57
- this.each(v.split('&'), function(v) {
58
- v = v.split('=');
59
- h = h || {};
60
- h[v[0]] = v[1];
61
- });
62
- }
63
- return h;
64
- },
65
-
66
- setHash : function(n, v, e, p, d, s) {
67
- var o = '';
68
-
69
- this.each(v, function(v, k) {
70
- o += (!o ? '' : '&') + k + '=' + v;
71
- });
72
-
73
- this.set(n, o, e, p, d, s);
74
- },
75
-
76
- get : function(n) {
77
- var c = document.cookie, e, p = n + "=", b;
78
-
79
- if (!c)
80
- return;
81
-
82
- b = c.indexOf("; " + p);
83
-
84
- if (b == -1) {
85
- b = c.indexOf(p);
86
-
87
- if (b != 0)
88
- return null;
89
-
90
- } else {
91
- b += 2;
92
- }
93
-
94
- e = c.indexOf(";", b);
95
-
96
- if (e == -1)
97
- e = c.length;
98
-
99
- return decodeURIComponent(c.substring(b + p.length, e));
100
- },
101
-
102
- set : function(n, v, e, p, d, s) {
103
- document.cookie = n + "=" + encodeURIComponent(v) +
104
- ((e) ? "; expires=" + e.toGMTString() : "") +
105
- ((p) ? "; path=" + p : "") +
106
- ((d) ? "; domain=" + d : "") +
107
- ((s) ? "; secure" : "");
108
- },
109
-
110
- remove : function(n, p) {
111
- var d = new Date();
112
-
113
- d.setTime(d.getTime() - 1000);
114
-
115
- this.set(n, '', d, p, d);
116
- }
117
- };
118
-
119
- // Returns the value as string. Second arg or empty string is returned when value is not set.
120
- function getUserSetting( name, def ) {
121
- var o = getAllUserSettings();
122
-
123
- if ( o.hasOwnProperty(name) )
124
- return o[name];
125
-
126
- if ( typeof def != 'undefined' )
127
- return def;
128
-
129
- return '';
130
- }
131
-
132
- // Both name and value must be only ASCII letters, numbers or underscore
133
- // and the shorter, the better (cookies can store maximum 4KB). Not suitable to store text.
134
- function setUserSetting( name, value, del ) {
135
- if ( 'object' !== typeof userSettings )
136
- return false;
137
-
138
- var c = 'bb-user-settings-' + userSettings.uid, o = wpCookies.getHash(c) || {}, d = new Date(), p,
139
- n = name.toString().replace(/[^A-Za-z0-9_]/, ''), v = value.toString().replace(/[^A-Za-z0-9_]/, '');
140
-
141
- if ( del ) {
142
- delete o[n];
143
- } else {
144
- o[n] = v;
145
- }
146
-
147
- d.setTime( d.getTime() + 31536000000 );
148
- p = userSettings.url;
149
-
150
- wpCookies.setHash(c, o, d, p);
151
- wpCookies.set('bb-user-settings-time-'+userSettings.uid, userSettings.time, d, p);
152
-
153
- return name;
154
- }
155
-
156
- function deleteUserSetting( name ) {
157
- return setUserSetting( name, '', 1 );
158
- }
159
-
160
- // Returns all settings as js object.
161
- function getAllUserSettings() {
162
- if ( 'object' !== typeof userSettings )
163
- return {};
164
-
165
- return wpCookies.getHash('bb-user-settings-' + userSettings.uid) || {};
166
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/options-discussion.php DELETED
@@ -1,156 +0,0 @@
1
- <?php
2
-
3
- require_once('admin.php');
4
-
5
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && $_POST['action'] == 'update') {
6
-
7
- bb_check_admin_referer( 'options-discussion-update' );
8
-
9
- // Deal with pingbacks checkbox when it isn't checked
10
- if ( !isset( $_POST['enable_pingback'] ) ) {
11
- $_POST['enable_pingback'] = false;
12
- }
13
-
14
- if ( !isset( $_POST['enable_loginless'] ) ) {
15
- $_POST['enable_loginless'] = false;
16
- }
17
-
18
- if ( !isset( $_POST['enable_subscriptions'] ) ) {
19
- $_POST['enable_subscriptions'] = false;
20
- }
21
-
22
- // Deal with avatars checkbox when it isn't checked
23
- if ( !isset( $_POST['avatars_show'] ) ) {
24
- $_POST['avatars_show'] = false;
25
- }
26
-
27
- foreach ( (array) $_POST as $option => $value ) {
28
- if ( !in_array( $option, array( '_wpnonce', '_wp_http_referer', 'action', 'submit' ) ) ) {
29
- $option = trim( $option );
30
- $value = is_array( $value ) ? $value : trim( $value );
31
- $value = stripslashes_deep( $value );
32
- if ( $value ) {
33
- bb_update_option( $option, $value );
34
- } else {
35
- bb_delete_option( $option );
36
- }
37
- }
38
- }
39
-
40
- $goback = add_query_arg('updated', 'true', wp_get_referer());
41
- bb_safe_redirect($goback);
42
- exit;
43
- }
44
-
45
- if ( !empty($_GET['updated']) ) {
46
- bb_admin_notice( __( '<strong>Settings saved.</strong>' ) );
47
- }
48
-
49
- $general_options = array(
50
- 'enable_pingback' => array(
51
- 'title' => __( 'Enable Pingbacks' ),
52
- 'type' => 'checkbox',
53
- 'options' => array(
54
- 1 => __( 'Allow link notifications from other sites.' )
55
- )
56
- ),
57
-
58
- 'enable_loginless' => array(
59
- 'title' => __( 'Enable Login-less Posting' ),
60
- 'type' => 'checkbox',
61
- 'options' => array(
62
- 1 => __( 'Allow users to create topics and posts without logging in.' )
63
- ),
64
- ),
65
-
66
- 'enable_subscriptions' => array(
67
- 'title' => __( 'Enable Subscriptions' ),
68
- 'type' => 'checkbox',
69
- 'options' => array(
70
- 1 => __( 'Allow users to subscribe to topics and receive new posts via email.' )
71
- ),
72
- ),
73
- );
74
-
75
- $bb_get_option_avatars_show = create_function( '$a', 'return 1;' );
76
- add_filter( 'bb_get_option_avatars_show', $bb_get_option_avatars_show );
77
- $avatar_options = array(
78
- 'avatars_show' => array(
79
- 'title' => __( 'Avatar display' ),
80
- 'type' => 'radio',
81
- 'options' => array(
82
- 0 => __( 'Don&#8217;t show avatars' ),
83
- 1 => __( 'Show avatars' )
84
- )
85
- ),
86
- 'avatars_rating' => array(
87
- 'title' => __( 'Maximum rating' ),
88
- 'type' => 'radio',
89
- 'options' => array(
90
- 'g' => __( 'G &#8212; Suitable for all audiences' ),
91
- 'pg' => __( 'PG &#8212; Possibly offensive, usually for audiences 13 and above' ),
92
- 'r' => __( 'R &#8212; Intended for adult audiences above 17' ),
93
- 'x' => __( 'X &#8212; Even more mature than above' )
94
- )
95
- ),
96
- 'avatars_default' => array(
97
- 'title' => __( 'Default avatar' ),
98
- 'type' => 'radio',
99
- 'options' => array(
100
- 'default' => bb_get_avatar( '', 32, 'default' ) . ' ' . __( 'Mystery Man' ),
101
- 'blank' => bb_get_avatar( '', 32, 'blank' ) . ' ' . __( 'Blank' ),
102
- 'logo' => bb_get_avatar( '', 32, 'logo' ) . ' ' . __( 'Gravatar Logo' ),
103
- 'identicon' => bb_get_avatar( rand( 0, 999 ), 32, 'identicon' ) . ' ' . __( 'Identicon (Generated)' ),
104
- 'wavatar' => bb_get_avatar( rand( 0, 999 ), 32, 'wavatar' ) . ' ' . __( 'Wavatar (Generated)' ),
105
- 'monsterid' => bb_get_avatar( rand( 0, 999 ), 32, 'monsterid' ) . ' ' . __( 'MonsterID (Generated)' ),
106
- 'retro' => bb_get_avatar( rand( 0, 999 ), 32, 'retro' ) . ' ' . __( 'Retro (Generated)' )
107
- ),
108
- 'note' => array(
109
- __( 'For users without a custom avatar of their own, you can either display a generic logo or a generated one based on their email address.' )
110
- ),
111
- )
112
- );
113
- remove_filter( 'bb_get_option_avatars_show', $bb_get_option_avatars_show );
114
-
115
- $bb_admin_body_class = ' bb-admin-settings';
116
-
117
- bb_get_admin_header();
118
-
119
- ?>
120
-
121
- <div class="wrap">
122
-
123
- <h2><?php _e('Discussion Settings'); ?></h2>
124
- <?php do_action( 'bb_admin_notices' ); ?>
125
-
126
- <form class="settings" method="post" action="<?php bb_uri( 'bb-admin/options-discussion.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN ); ?>">
127
- <fieldset>
128
- <?php
129
- foreach ( $general_options as $option => $args ) {
130
- bb_option_form_element( $option, $args );
131
- }
132
- ?>
133
- </fieldset>
134
- <fieldset>
135
- <legend><?php _e('Avatars'); ?></legend>
136
- <p>
137
- <?php _e('bbPress includes built-in support for <a href="http://gravatar.com/">Gravatars</a>. A Gravatar is an image that follows you from site to site, appearing beside your name when you comment on Gravatar enabled sites. Here you can enable the display of Gravatars on your site.'); ?>
138
- </p>
139
- <?php
140
- foreach ( $avatar_options as $option => $args ) {
141
- bb_option_form_element( $option, $args );
142
- }
143
- ?>
144
- </fieldset>
145
- <fieldset class="submit">
146
- <?php bb_nonce_field( 'options-discussion-update' ); ?>
147
- <input type="hidden" name="action" value="update" />
148
- <input class="submit" type="submit" name="submit" value="<?php _e('Save Changes') ?>" />
149
- </fieldset>
150
- </form>
151
-
152
- </div>
153
-
154
- <?php
155
-
156
- bb_get_admin_footer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/options-general.php DELETED
@@ -1,244 +0,0 @@
1
- <?php
2
-
3
- require_once('admin.php');
4
-
5
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && $_POST['action'] == 'update' ) {
6
-
7
- bb_check_admin_referer( 'options-general-update' );
8
-
9
- foreach ( (array) $_POST as $option => $value ) {
10
- if ( !in_array( $option, array( '_wpnonce', '_wp_http_referer', 'action', 'submit' ) ) ) {
11
- $option = trim( $option );
12
- $value = is_array( $value ) ? $value : trim( $value );
13
- $value = stripslashes_deep( $value );
14
- if ( $option == 'uri' && !empty( $value ) ) {
15
- $value = rtrim( $value, " \t\n\r\0\x0B/" ) . '/';
16
- }
17
- if ( $value ) {
18
- bb_update_option( $option, $value );
19
- } else {
20
- bb_delete_option( $option );
21
- }
22
- }
23
- }
24
-
25
- $goback = add_query_arg( 'updated', 'true', wp_get_referer() );
26
- bb_safe_redirect( $goback );
27
- exit;
28
- }
29
-
30
- if ( !empty( $_GET['updated'] ) ) {
31
- bb_admin_notice( __( '<strong>Settings saved.</strong>' ) );
32
- }
33
-
34
- $general_options = array(
35
- 'name' => array(
36
- 'title' => __( 'Site title' ),
37
- 'class' => 'long',
38
- ),
39
- 'description' => array(
40
- 'title' => __( 'Tagline' ),
41
- 'class' => 'long',
42
- 'note' => __( 'In a few words, explain what this site is about.' )
43
- ),
44
- 'uri' => array(
45
- 'title' => __( 'bbPress address (URL)' ),
46
- 'class' => array('long', 'code'),
47
- 'note' => __( 'The full URL of your bbPress install.' ),
48
- ),
49
- 'from_email' => array(
50
- 'title' => __( 'E-mail address' ),
51
- 'note' => __( 'This address is used for admin purposes, like new user notification.' ),
52
- )
53
- );
54
-
55
- $time_options = array(
56
- 'gmt_offset' => array(
57
- 'title' => __( 'Time zone' ),
58
- 'type' => 'select',
59
- 'options' => array(
60
- '-12' => '-12:00',
61
- '-11.5' => '-11:30',
62
- '-11' => '-11:00',
63
- '-10.5' => '-10:30',
64
- '-10' => '-10:00',
65
- '-9.5' => '-9:30',
66
- '-9' => '-9:00',
67
- '-8.5' => '-8:30',
68
- '-8' => '-8:00',
69
- '-7.5' => '-7:30',
70
- '-7' => '-7:00',
71
- '-6.5' => '-6:30',
72
- '-6' => '-6:00',
73
- '-5.5' => '-5:30',
74
- '-5' => '-5:00',
75
- '-4.5' => '-4:30',
76
- '-4' => '-4:00',
77
- '-3.5' => '-3:30',
78
- '-3' => '-3:00',
79
- '-2.5' => '-2:30',
80
- '-2' => '-2:00',
81
- '-1.5' => '-1:30',
82
- '-1' => '-1:00',
83
- '-0.5' => '-0:30',
84
- '0' => '',
85
- '0.5' => '+0:30',
86
- '1' => '+1:00',
87
- '1.5' => '+1:30',
88
- '2' => '+2:00',
89
- '2.5' => '+2:30',
90
- '3' => '+3:00',
91
- '3.5' => '+3:30',
92
- '4' => '+4:00',
93
- '4.5' => '+4:30',
94
- '5' => '+5:00',
95
- '5.5' => '+5:30',
96
- '5.75' => '+5:45',
97
- '6' => '+6:00',
98
- '6.5' => '+6:30',
99
- '7' => '+7:00',
100
- '7.5' => '+7:30',
101
- '8' => '+8:00',
102
- '8.5' => '+8:30',
103
- '8.75' => '+8:45',
104
- '9' => '+9:00',
105
- '9.5' => '+9:30',
106
- '10' => '+10:00',
107
- '10.5' => '+10:30',
108
- '11' => '+11:00',
109
- '11.5' => '+11:30',
110
- '12' => '+12:00',
111
- '12.75' => '+12:45',
112
- '13' => '+13:00',
113
- '13.75' => '+13:45',
114
- '14' => '+14:00'
115
- ),
116
- 'after' => __( 'hours' )
117
- ),
118
- 'datetime_format' => array(
119
- 'title' => __( 'Date and time format' ),
120
- 'class' => 'short',
121
- 'value' => bb_get_datetime_formatstring_i18n(),
122
- 'after' => bb_datetime_format_i18n( bb_current_time() ),
123
- 'note' => array(
124
- __( '<a href="http://codex.wordpress.org/Formatting_Date_and_Time">Documentation on date formatting</a>.' ),
125
- __( 'Click "Save Changes" to update sample output.' )
126
- )
127
- ),
128
- 'date_format' => array(
129
- 'title' => __( 'Date format' ),
130
- 'class' => 'short',
131
- 'value' => bb_get_datetime_formatstring_i18n( 'date' ),
132
- 'after' => bb_datetime_format_i18n( bb_current_time(), 'date' )
133
- )
134
- );
135
-
136
- if ( !$gmt_offset = bb_get_option( 'gmt_offset' ) ) {
137
- $gmt_offset = 0;
138
- }
139
-
140
- if ( wp_timezone_supported() ) {
141
- unset( $time_options['gmt_offset'] );
142
-
143
- if ( !$timezone_string = bb_get_option( 'timezone_string' ) ) {
144
- // set the Etc zone if no timezone string exists
145
- $_gmt_offset = (integer) round( $gmt_offset );
146
- if ( $_gmt_offset === 0 ) {
147
- $timezone_string = 'Etc/UTC';
148
- } elseif ( $_gmt_offset > 0 ) {
149
- // Zoneinfo has these signed backwards to common convention
150
- $timezone_string = 'Etc/GMT-' . abs( $_gmt_offset );
151
- } else {
152
- // Zoneinfo has these signed backwards to common convention
153
- $timezone_string = 'Etc/GMT+' . abs( $_gmt_offset );
154
- }
155
- unset( $_gmt_offset );
156
- }
157
-
158
- // Build the new selector
159
- $_time_options = array(
160
- 'timezone_string' => array(
161
- 'title' => __( 'Time zone' ),
162
- 'type' => 'select',
163
- 'options' => wp_timezone_choice( $timezone_string ), // This passes a string of html, which gets used verbatim
164
- 'note' => array(
165
- __( 'Choose a city in the same time zone as you.' ),
166
- sprintf( __( '<abbr title="Coordinated Universal Time">UTC</abbr> time is <code>%s</code>' ), bb_gmdate_i18n( bb_get_datetime_formatstring_i18n(), bb_current_time() ) ),
167
- sprintf( __( 'Local time is <code>%s</code>' ), bb_datetime_format_i18n( bb_current_time() ) )
168
- )
169
- )
170
- );
171
-
172
- $_now = localtime( bb_current_time(), true );
173
- if ( $now['tm_isdst'] ) {
174
- $_time_options['timezone_string']['note'][] = __( 'This time zone is currently in daylight savings time.' );
175
- } else {
176
- $_time_options['timezone_string']['note'][] = __( 'This time zone is currently in standard time.' );
177
- }
178
-
179
- if ( function_exists( 'timezone_transitions_get' ) ) {
180
- $timezone_object = new DateTimeZone( $timezone_string );
181
- $found_transition = false;
182
- foreach ( timezone_transitions_get( $timezone_object ) as $timezone_transition ) {
183
- if ( $timezone_transition['ts'] > time() ) {
184
- $note = $timezone_transition['isdst'] ? __('Daylight savings time begins on <code>%s</code>') : __('Standard time begins on <code>%s</code>');
185
- $_time_options['timezone_string']['note'][] = sprintf( $note, bb_gmdate_i18n( bb_get_datetime_formatstring_i18n(), $timezone_transition['ts'], false ) );
186
- break;
187
- }
188
- }
189
- }
190
-
191
- $time_options = array_merge( $_time_options, $time_options );
192
-
193
- } else {
194
- // Tidy up the old style dropdown
195
- $time_options['gmt_offset']['note'] = array(
196
- 1 => sprintf( __( '<abbr title="Coordinated Universal Time">UTC</abbr> %s is <code>%s</code>' ), $time_options['gmt_offset']['options'][$gmt_offset], bb_datetime_format_i18n( bb_current_time() ) ),
197
- 2 => __( 'Unfortunately, you have to manually update this for Daylight Savings Time.' )
198
- );
199
-
200
- if ( $gmt_offset ) {
201
- $time_options['gmt_offset']['note'][0] = sprintf( __( '<abbr title="Coordinated Universal Time">UTC</abbr> time is <code>%s</code>' ), bb_gmdate_i18n( bb_get_datetime_formatstring_i18n(), bb_current_time(), true ) );
202
- ksort($time_options['gmt_offset']['note']);
203
- }
204
-
205
- foreach ( $time_options['gmt_offset']['options'] as $_key => $_value ) {
206
- $time_options['gmt_offset']['options'][$_key] = sprintf( __( 'UTC %s' ), $_value );
207
- }
208
- }
209
-
210
-
211
- $bb_admin_body_class = ' bb-admin-settings';
212
-
213
- bb_get_admin_header();
214
-
215
- ?>
216
-
217
- <div class="wrap">
218
-
219
- <h2><?php _e('General Settings'); ?></h2>
220
- <?php do_action( 'bb_admin_notices' ); ?>
221
-
222
- <form class="settings" method="post" action="<?php bb_uri( 'bb-admin/options-general.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN ); ?>">
223
- <fieldset>
224
- <?php
225
- foreach ( $general_options as $option => $args ) {
226
- bb_option_form_element( $option, $args );
227
- }
228
- foreach ( $time_options as $option => $args ) {
229
- bb_option_form_element( $option, $args );
230
- }
231
- ?>
232
- </fieldset>
233
- <fieldset class="submit">
234
- <?php bb_nonce_field( 'options-general-update' ); ?>
235
- <input type="hidden" name="action" value="update" />
236
- <input class="submit" type="submit" name="submit" value="<?php _e('Save Changes') ?>" />
237
- </fieldset>
238
- </form>
239
-
240
- </div>
241
-
242
- <?php
243
-
244
- bb_get_admin_footer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/options-permalinks.php DELETED
@@ -1,188 +0,0 @@
1
- <?php
2
-
3
- require_once('admin.php');
4
-
5
- $file_source = BB_PATH . 'bb-admin/includes/defaults.bb-htaccess.php';
6
- $file_target = BB_PATH . '.htaccess';
7
- include( $file_source );
8
- $file_source_rules = $_rules; // This is a string
9
-
10
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && $_POST['action'] == 'update') {
11
-
12
- bb_check_admin_referer( 'options-permalinks-update' );
13
-
14
- foreach ( (array) $_POST as $option => $value ) {
15
- if ( !in_array( $option, array('_wpnonce', '_wp_http_referer', 'action', 'submit') ) ) {
16
- $option = trim( $option );
17
- $value = is_array( $value ) ? $value : trim( $value );
18
- $value = stripslashes_deep( $value );
19
- if ( $value ) {
20
- bb_update_option( $option, $value );
21
- } else {
22
- bb_delete_option( $option );
23
- }
24
- }
25
- }
26
-
27
- $mod_rewrite = (string) bb_get_option( 'mod_rewrite' );
28
-
29
- $goback = remove_query_arg( array( 'updated', 'notapache', 'notmodrewrite' ), wp_get_referer() );
30
-
31
- // Make sure mod_rewrite is possible on the server
32
- if ( !$is_apache ) {
33
- bb_delete_option( 'mod_rewrite_writable' );
34
- $goback = add_query_arg( 'notapache', 'true', $goback );
35
- bb_safe_redirect( $goback );
36
- exit;
37
- } elseif ( '0' !== $mod_rewrite && !apache_mod_loaded( 'mod_rewrite', true ) ) {
38
- bb_delete_option( 'mod_rewrite_writable' );
39
- bb_update_option( 'mod_rewrite', '0' );
40
- $goback = add_query_arg( 'notmodrewrite', 'true', $goback );
41
- bb_safe_redirect( $goback );
42
- exit;
43
- }
44
-
45
- $file_target_rules = array();
46
-
47
- $file_target_exists = false;
48
- $file_target_writable = true;
49
- if ( file_exists( $file_target ) ) {
50
- if ( is_readable( $file_target ) ) {
51
- $file_target_rules = explode( "\n", implode( '', file( $file_target ) ) );
52
- }
53
- $file_target_exists = true;
54
- if ( !is_writable( $file_target ) ) {
55
- $file_target_writable = false;
56
- }
57
- } else {
58
- $file_target_dir = dirname( $file_target );
59
- if ( file_exists( $file_target_dir ) ) {
60
- if ( !is_writable( $file_target_dir ) || !is_dir( $file_target_dir ) ) {
61
- $file_target_writable = false;
62
- }
63
- } else {
64
- $file_target_writable = false;
65
- }
66
- }
67
-
68
- // Strip out existing bbPress rules
69
- $_keep_rule = true;
70
- $_kept_rules = array();
71
- foreach ( $file_target_rules as $_rule ) {
72
- if ( false !== strpos( $_rule, '# BEGIN bbPress' ) ) {
73
- $_keep_rule = false;
74
- continue;
75
- } elseif ( false !== strpos( $_rule, '# END bbPress' ) ) {
76
- $_keep_rule = true;
77
- continue;
78
- }
79
- if ( $_keep_rule ) {
80
- $_kept_rules[] = $_rule;
81
- }
82
- }
83
-
84
- $file_target_rules = join( "\n", $_kept_rules ) . "\n" . $file_source_rules;
85
-
86
- $file_target_written = 0;
87
- if ( $file_target_writable ) {
88
- // Open the file for writing - rewrites the whole file
89
- if ( $file_target_handle = fopen( $file_target, 'w' ) ) {
90
- if ( fwrite( $file_target_handle, $file_target_rules ) ) {
91
- $file_target_written = 1;
92
- }
93
- // Close the file
94
- fclose( $file_target_handle );
95
- @chmod( $file_target, 0666 );
96
- }
97
- }
98
-
99
- bb_update_option( 'mod_rewrite_writable', $file_target_writable );
100
- $goback = add_query_arg( 'updated', 'true', $goback );
101
- bb_safe_redirect( $goback );
102
- exit;
103
- }
104
-
105
- if ( $is_apache && bb_get_option( 'mod_rewrite' ) && !bb_get_option( 'mod_rewrite_writable' ) ) {
106
- $manual_instructions = true;
107
- }
108
-
109
- if ( !empty( $_GET['notmodrewrite'] ) ) {
110
- $manual_instructions = false;
111
- bb_admin_notice( __( '<strong>It appears that your server does not support custom permalink structures.</strong>' ), 'error' );
112
- }
113
-
114
- if ( !empty( $_GET['notapache'] ) ) {
115
- $manual_instructions = false;
116
- bb_admin_notice( __( '<strong>Rewriting on webservers other than Apache using mod_rewrite is currently unsupported, but we won&#8217;t stop you from trying.</strong>' ), 'error' );
117
- }
118
-
119
- if ( !empty( $_GET['updated'] ) ) {
120
- if ( $manual_instructions ) {
121
- bb_admin_notice( __( '<strong>You should update your .htaccess now.</strong>' ) );
122
- } else {
123
- bb_admin_notice( __( '<strong>Permalink structure updated.</strong>' ) );
124
- }
125
- }
126
-
127
- $permalink_options = array(
128
- 'mod_rewrite' => array(
129
- 'title' => __( 'Permalink type' ),
130
- 'type' => 'radio',
131
- 'options' => array(
132
- '0' => sprintf( __( '<span>None</span> <code>%s</code>' ), bb_get_uri( 'forum.php', array( 'id' => 1 ), BB_URI_CONTEXT_TEXT ) ),
133
- '1' => sprintf( __( '<span>Numeric</span> <code>%s</code>' ), bb_get_uri( 'forum/1', null, BB_URI_CONTEXT_TEXT ) ),
134
- 'slugs' => sprintf( __( '<span>Name based</span> <code>%s</code>' ), bb_get_uri( '/forum/first-forum', null, BB_URI_CONTEXT_TEXT ) )
135
- )
136
- )
137
- );
138
-
139
- $bb_admin_body_class = ' bb-admin-settings';
140
-
141
- bb_get_admin_header();
142
-
143
- ?>
144
-
145
- <div class="wrap">
146
-
147
- <h2><?php _e( 'Permalink Settings' ); ?></h2>
148
- <?php do_action( 'bb_admin_notices' ); ?>
149
-
150
- <form class="settings" method="post" action="<?php bb_uri( 'bb-admin/options-permalinks.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN ); ?>">
151
- <fieldset>
152
- <p>
153
- <?php _e( 'By default bbPress uses web URLs which have question marks and lots of numbers in them, however bbPress offers you the ability to choose an alternative URL structure for your permalinks. This can improve the aesthetics, usability, and forward-compatibility of your links.' ); ?>
154
- </p>
155
- <?php
156
- foreach ( $permalink_options as $option => $args ) {
157
- bb_option_form_element( $option, $args );
158
- }
159
- ?>
160
- </fieldset>
161
- <fieldset class="submit">
162
- <?php bb_nonce_field( 'options-permalinks-update' ); ?>
163
- <input type="hidden" name="action" value="update" />
164
- <input class="submit" type="submit" name="submit" value="<?php _e('Save Changes') ?>" />
165
- </fieldset>
166
- </form>
167
-
168
- <?php
169
- if ( $manual_instructions ) {
170
- ?>
171
- <form class="settings" method="post" action="<?php bb_uri( 'bb-admin/options-permalinks.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN ); ?>">
172
- <fieldset>
173
- <p>
174
- <?php _e( 'If your <code>.htaccess</code> file were <a href="http://codex.wordpress.org/Changing_File_Permissions">writable</a>, we could do this automatically, but it isn&#8217;t so these are the mod_rewrite rules you should have in your <code>.htaccess</code> file. Click in the field and press <kbd>CTRL + a</kbd> to select all.' ); ?>
175
- </p>
176
- <textarea dir="ltr" id="rewrite-rules" class="readonly" readonly="readonly" rows="6"><?php echo esc_html( trim( $file_source_rules ) ); ?></textarea>
177
- </fieldset>
178
- </form>
179
-
180
- <?php
181
- }
182
- ?>
183
-
184
- </div>
185
-
186
- <?php
187
-
188
- bb_get_admin_footer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/options-reading.php DELETED
@@ -1,77 +0,0 @@
1
- <?php
2
-
3
- require_once( 'admin.php' );
4
-
5
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && $_POST['action'] == 'update') {
6
-
7
- bb_check_admin_referer( 'options-reading-update' );
8
-
9
- foreach ( (array) $_POST as $option => $value ) {
10
- if ( !in_array( $option, array('_wpnonce', '_wp_http_referer', 'action', 'submit') ) ) {
11
- $option = trim( $option );
12
- $value = is_array( $value ) ? $value : trim( $value );
13
- $value = stripslashes_deep( $value );
14
- if ( $value ) {
15
- bb_update_option( $option, $value );
16
- } else {
17
- bb_delete_option( $option );
18
- }
19
- }
20
- }
21
-
22
- $goback = add_query_arg('updated', 'true', wp_get_referer());
23
- bb_safe_redirect($goback);
24
- exit;
25
- }
26
-
27
- if ( !empty( $_GET['updated'] ) )
28
- bb_admin_notice( '<strong>' . __( 'Settings saved.' ) . '</strong>' );
29
-
30
- $reading_options = array(
31
- 'page_topics' => array(
32
- 'title' => __( 'Items per page' ),
33
- 'class' => 'short',
34
- 'note' => __( 'Number of topics, posts or tags to show per page.' )
35
- ),
36
- 'name_link_profile' => array(
37
- 'title' => __( 'Link name to' ),
38
- 'type' => 'radio',
39
- 'options' => array(
40
- 0 => __( 'Website' ),
41
- 1 => __( 'Profile' )
42
- ),
43
- 'note' => __( 'What should the user\'s name link to on the topic page? The user\'s title would automatically get linked to the option you don\'t choose. By default, the user\'s name is linked to his/her website.' )
44
- )
45
- );
46
-
47
- $bb_admin_body_class = ' bb-admin-settings';
48
-
49
- bb_get_admin_header();
50
-
51
- ?>
52
-
53
- <div class="wrap">
54
-
55
- <h2><?php _e( 'Reading Settings' ); ?></h2>
56
- <?php do_action( 'bb_admin_notices' ); ?>
57
-
58
- <form class="settings" method="post" action="<?php bb_uri( 'bb-admin/options-reading.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN ); ?>">
59
- <fieldset>
60
- <?php
61
- foreach ( $reading_options as $option => $args ) {
62
- bb_option_form_element( $option, $args );
63
- }
64
- ?>
65
- </fieldset>
66
- <fieldset class="submit">
67
- <?php bb_nonce_field( 'options-reading-update' ); ?>
68
- <input type="hidden" name="action" value="update" />
69
- <input class="submit" type="submit" name="submit" value="<?php _e( 'Save Changes' ) ?>" />
70
- </fieldset>
71
- </form>
72
-
73
- </div>
74
-
75
- <?php
76
-
77
- bb_get_admin_footer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/options-wordpress.php DELETED
@@ -1,313 +0,0 @@
1
- <?php
2
-
3
- require_once('admin.php');
4
-
5
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) )
6
- $action = @$_POST['action'];
7
- else
8
- $action = false;
9
-
10
- if ( in_array( $action, array('update-users', 'update-options') ) ) {
11
- bb_check_admin_referer( 'options-wordpress-' . $action );
12
-
13
- // Deal with advanced user database checkbox when it isn't checked
14
- if (!isset($_POST['user_bbdb_advanced'])) {
15
- $_POST['user_bbdb_advanced'] = false;
16
- }
17
-
18
- foreach ( (array) $_POST as $option => $value ) {
19
- if ( !in_array( $option, array('_wpnonce', '_wp_http_referer', 'action', 'submit') ) ) {
20
- $option = trim( $option );
21
- $value = is_array( $value ) ? $value : trim( $value );
22
- $value = stripslashes_deep( $value );
23
- if ( ( $option == 'wp_siteurl' || $option == 'wp_home' ) && !empty( $value ) ) {
24
- $value = rtrim( $value, " \t\n\r\0\x0B/" ) . '/';
25
- }
26
- if ( $value ) {
27
- bb_update_option( $option, $value );
28
- } else {
29
- bb_delete_option( $option );
30
- }
31
- }
32
- }
33
-
34
- if ($action == 'update-users') {
35
- bb_apply_wp_role_map_to_orphans();
36
- }
37
-
38
- $goback = add_query_arg('updated', $action, wp_get_referer());
39
- bb_safe_redirect($goback);
40
- exit;
41
- }
42
-
43
- switch (@$_GET['updated']) {
44
- case 'update-users':
45
- bb_admin_notice( __( '<strong>User role mapping saved.</strong>' ) );
46
- break;
47
- case 'update-options':
48
- bb_admin_notice( __( '<strong>User integration settings saved.</strong>' ) );
49
- break;
50
- }
51
-
52
-
53
-
54
- $bb_role_names[''] = _c( 'none|no bbPress role' );
55
- $bb_role_names = array_merge( $bb_role_names, array_map( create_function( '$a', 'return sprintf( _c( "bbPress %s|bbPress role" ), $a );' ), $wp_roles->get_names() ) );
56
-
57
- $wpRoles = array(
58
- 'administrator' => __('WordPress Administrator'),
59
- 'editor' => __('WordPress Editor'),
60
- 'author' => __('WordPress Author'),
61
- 'contributor' => __('WordPress Contributor'),
62
- 'subscriber' => __('WordPress Subscriber')
63
- );
64
-
65
- $wpRoles = apply_filters( 'role_map_wp_roles', $wpRoles );
66
-
67
- $cookie_options = array(
68
- 'wp_siteurl' => array(
69
- 'title' => __( 'WordPress address (URL)' ),
70
- 'class' => 'long',
71
- 'note' => __( 'This value should exactly match the <strong>WordPress address (URL)</strong> setting in your WordPress general settings.' )
72
- ),
73
- 'wp_home' => array(
74
- 'title' => __( 'Blog address (URL)' ),
75
- 'class' => 'long',
76
- 'note' => __( 'This value should exactly match the <strong>Blog address (URL)</strong> setting in your WordPress general settings.' )
77
- ),
78
- 'bb_auth_salt' => array(
79
- 'title' => __( 'WordPress "auth" cookie salt' ),
80
- 'note' => __( 'This must match the value of the WordPress setting named "auth_salt" in your WordPress site. Look for the option labeled "auth_salt" in <a href="#" id="getAuthSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>.' )
81
- ),
82
- 'bb_secure_auth_salt' => array(
83
- 'title' => __( 'WordPress "secure auth" cookie salt' ),
84
- 'note' => __( 'This must match the value of the WordPress setting named "secure_auth_salt" in your WordPress site. Look for the option labeled "secure_auth_salt" in <a href="#" id="getSecureAuthSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. Sometimes this value is not set in WordPress, in that case you can leave this setting blank as well.' )
85
- ),
86
- 'bb_logged_in_salt' => array(
87
- 'title' => __( 'WordPress "logged in" cookie salt' ),
88
- 'note' => __( 'This must match the value of the WordPress setting named "logged_in_salt" in your WordPress site. Look for the option labeled "logged_in_salt" in <a href="#" id="getLoggedInSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>.' )
89
- )
90
- );
91
-
92
- foreach ( array( 'bb_auth_salt', 'bb_secure_auth_salt', 'bb_logged_in_salt' ) as $salt_constant ) {
93
- if ( defined( strtoupper( $salt_constant ) ) ) {
94
- $cookie_options[$salt_constant]['note'] = array(
95
- sprintf( __( 'You have defined the "%s" constant which locks this setting.' ), strtoupper( $salt_constant ) ),
96
- $cookie_options[$salt_constant]['note'],
97
- );
98
- $cookie_options[$salt_constant]['value'] = constant( strtoupper( $salt_constant ) );
99
- $bb_hardcoded[$salt_constant] = true;
100
- }
101
- }
102
-
103
- $user_db_options = array(
104
- 'wp_table_prefix' => array(
105
- 'title' => __( 'User database table prefix' ),
106
- 'note' => __( 'If your bbPress and WordPress sites share the same database, then this is the same value as <code>$table_prefix</code> in your WordPress <code>wp-config.php</code> file. It is usually <strong>wp_</strong>.' )
107
- ),
108
- 'wordpress_mu_primary_blog_id' => array(
109
- 'title' => __( 'WordPress MU primary blog ID' ),
110
- 'note' => __( 'If you are integrating with a WordPress MU site you need to specify the primary blog ID for that site. It is usually <strong>1</strong>. You should probably leave this blank if you are integrating with a standard WordPress site' )
111
- ),
112
- 'user_bbdb_advanced' => array(
113
- 'title' => __( 'Show advanced database settings' ),
114
- 'type' => 'checkbox',
115
- 'options' => array(
116
- 1 => array(
117
- 'label' => __( 'If your bbPress and WordPress site do not share the same database, then you will need to add advanced settings.' ),
118
- 'attributes' => array( 'onclick' => 'toggleAdvanced(this);' )
119
- )
120
- )
121
- )
122
- );
123
-
124
- $advanced_user_db_options = array(
125
- 'user_bbdb_name' => array(
126
- 'title' => __( 'User database name' ),
127
- 'note' => __( 'The name of the database in which your user tables reside.' )
128
- ),
129
- 'user_bbdb_user' => array(
130
- 'title' => __( 'User database user' ),
131
- 'note' => __( 'The database user that has access to that database.' )
132
- ),
133
- 'user_bbdb_password' => array(
134
- 'title' => __( 'User database password' ),
135
- 'note' => __( 'That database user\'s password.' )
136
- ),
137
- 'user_bbdb_host' => array(
138
- 'title' => __( 'User database host' ),
139
- 'note' => __( 'The domain name or IP address of the server where the database is located. If the database is on the same server as the web site, then this probably should be <strong>localhost</strong>.' )
140
- ),
141
- 'user_bbdb_charset' => array(
142
- 'title' => __( 'User database character set' ),
143
- 'note' => __( 'The best choice is <strong>utf8</strong>, but you will need to match the character set which you created the database with.' )
144
- ),
145
- 'user_bbdb_collate' => array(
146
- 'title' => __( 'User database character collation' ),
147
- 'note' => __( 'The character collation value set when the user database was created.' )
148
- )
149
- );
150
-
151
- $custom_table_options = array(
152
- 'custom_user_table' => array(
153
- 'title' => __( 'User database "user" table' ),
154
- 'note' => __( 'The complete table name, including any prefix.' ),
155
- ),
156
- 'custom_user_meta_table' => array(
157
- 'title' => __( 'User database "user meta" table' ),
158
- 'note' => __( 'The complete table name, including any prefix.' ),
159
- ),
160
- );
161
-
162
- $advanced_display = bb_get_option( 'user_bbdb_advanced' ) ? 'block' : 'none';
163
-
164
- $bb_admin_body_class = ' bb-admin-settings';
165
-
166
- bb_get_admin_header();
167
-
168
- ?>
169
-
170
- <div class="wrap">
171
-
172
- <h2><?php _e( 'WordPress Integration Settings' ); ?></h2>
173
- <?php do_action( 'bb_admin_notices' ); ?>
174
-
175
- <form class="settings" method="post" action="<?php bb_uri('bb-admin/options-wordpress.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>">
176
- <fieldset>
177
- <legend><?php _e('User Role Map'); ?></legend>
178
- <p><?php _e('Here you can match WordPress roles to bbPress roles.'); ?></p>
179
- <p><?php _e('This will have no effect until your user tables are integrated below. Only standard WordPress roles are supported. Changes do not affect users with existing roles in both WordPress and bbPress.'); ?></p>
180
- <?php foreach ( $wpRoles as $wpRole => $wpRoleName ) bb_option_form_element( "wp_roles_map[$wpRole]", array( 'title' => $wpRoleName, 'type' => 'select', 'options' => $bb_role_names ) ); ?>
181
- </fieldset>
182
- <fieldset class="submit">
183
- <?php bb_nonce_field( 'options-wordpress-update-users' ); ?>
184
- <input type="hidden" name="action" value="update-users" />
185
- <input class="submit" type="submit" name="submit" value="<?php _e('Save Changes') ?>" />
186
- </fieldset>
187
- </form>
188
-
189
- <hr class="settings" />
190
-
191
- <div class="settings">
192
- <h3><?php _e('User Integration'); ?></h3>
193
- <p><?php _e('Usually, you will have to specify both cookie integration and user database integration settings. Make sure you have a "User role map" setup above before trying to add user integration.'); ?></p>
194
- <p><?php _e('<em><strong>Note:</strong> changing the settings below may cause you to be logged out!</em>'); ?></p>
195
- </div>
196
-
197
- <form class="settings" method="post" action="<?php bb_uri('bb-admin/options-wordpress.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>">
198
- <fieldset>
199
- <legend><?php _e('Cookies'); ?></legend>
200
- <p><?php _e('Cookie sharing allows users to log in to either your bbPress or your WordPress site, and have access to both.'); ?></p>
201
- <?php foreach ( $cookie_options as $option => $args ) bb_option_form_element( $option, $args ); ?>
202
- <script type="text/javascript" charset="utf-8">
203
- /* <![CDATA[ */
204
- function updateWordPressOptionURL () {
205
- var siteURLInputValue = document.getElementById('wp-siteurl').value;
206
- if (siteURLInputValue && siteURLInputValue.substr(-1,1) != '/') {
207
- siteURLInputValue += '/';
208
- }
209
- var authSaltAnchor = document.getElementById('getAuthSaltOption');
210
- var secureAuthSaltAnchor = document.getElementById('getSecureAuthSaltOption');
211
- var loggedInSaltAnchor = document.getElementById('getLoggedInSaltOption');
212
- if (siteURLInputValue) {
213
- authSaltAnchor.href = siteURLInputValue + 'wp-admin/options.php';
214
- secureAuthSaltAnchor.href = siteURLInputValue + 'wp-admin/options.php';
215
- loggedInSaltAnchor.href = siteURLInputValue + 'wp-admin/options.php';
216
- } else {
217
- authSaltAnchor.href = '';
218
- secureAuthSaltAnchor.href = '';
219
- loggedInSaltAnchor.href = '';
220
- }
221
- }
222
- var siteURLInput = document.getElementById('wp-siteurl');
223
- if (siteURLInput.value) {
224
- updateWordPressOptionURL();
225
- }
226
- siteURLInput.onkeyup = updateWordPressOptionURL;
227
- siteURLInput.onblur = updateWordPressOptionURL;
228
- siteURLInput.onclick = updateWordPressOptionURL;
229
- siteURLInput.onchange = updateWordPressOptionURL;
230
- /* ]]> */
231
- </script>
232
- <?php
233
- $cookie_settings = array(
234
- 'cookiedomain' => 'COOKIE_DOMAIN',
235
- 'cookiepath' => 'COOKIEPATH'
236
- );
237
- $wp_settings = '';
238
- foreach ($cookie_settings as $bb_setting => $wp_setting) {
239
- if ( isset($bb->$bb_setting) ) {
240
- $wp_settings .= 'define(\'' . $wp_setting . '\', \'' . $bb->$bb_setting . '\');' . "\n";
241
- }
242
- }
243
- ?>
244
- <p><?php printf(__('To complete cookie integration, you will need to add some settings to your <code>wp-config.php</code> file in the root directory of your WordPress installation. To get those settings, you will need to install and configure the <a href="%s">"bbPress Integration" plugin for WordPress</a>.'), 'http://wordpress.org/extend/plugins/bbpress-integration/'); ?></p>
245
- <p><?php _e('You will also have to manually ensure that the following constants are equivalent in WordPress\' and bbPress\' respective config files.'); ?></p>
246
- <div class="table">
247
- <table>
248
- <tr>
249
- <th><?php _e('WordPress'); ?></th>
250
- <td></td>
251
- <th><?php _e('bbPress'); ?></th>
252
- </tr>
253
- <tr>
254
- <td>AUTH_KEY</td>
255
- <td>&lt;=&gt;</td>
256
- <td>BB_AUTH_KEY</td>
257
- </tr>
258
- <tr>
259
- <td>SECURE_AUTH_KEY</td>
260
- <td>&lt;=&gt;</td>
261
- <td>BB_SECURE_AUTH_KEY</td>
262
- </tr>
263
- <tr>
264
- <td>LOGGED_IN_KEY</td>
265
- <td>&lt;=&gt;</td>
266
- <td>BB_LOGGED_IN_KEY</td>
267
- </tr>
268
- </table>
269
- </div>
270
- </fieldset>
271
-
272
- <fieldset>
273
- <legend><?php _e('User database'); ?></legend>
274
- <p><?php _e('User database sharing allows you to store user data in your WordPress database.'); ?></p>
275
- <p><?php _e('You should setup a "User role map" before'); ?></p>
276
- <script type="text/javascript" charset="utf-8">
277
- function toggleAdvanced(checkedObj) {
278
- var advanced1 = document.getElementById('advanced1');
279
- var advanced2 = document.getElementById('advanced2');
280
- if (checkedObj.checked) {
281
- advanced1.style.display = 'block';
282
- advanced2.style.display = 'block';
283
- } else {
284
- advanced1.style.display = 'none';
285
- advanced2.style.display = 'none';
286
- }
287
- }
288
- </script>
289
- <?php foreach ( $user_db_options as $option => $args ) bb_option_form_element( $option, $args ); ?>
290
- </fieldset>
291
- <fieldset id="advanced1" style="display:<?php echo $advanced_display; ?>">
292
- <legend><?php _e('Separate user database settings'); ?></legend>
293
- <p><?php _e('Most of the time these settings are <em>not</em> required. Look before you leap!'); ?></p>
294
- <p><?php _e('All settings except for the character set must be specified.'); ?></p>
295
- <?php foreach ( $advanced_user_db_options as $option => $args ) bb_option_form_element( $option, $args ); ?>
296
- </fieldset>
297
- <fieldset id="advanced2" style="display:<?php echo $advanced_display; ?>">
298
- <legend><?php _e('Custom user tables'); ?></legend>
299
- <p><?php _e('Only set these values if your user tables differ from the default WordPress naming convention.'); ?></p>
300
- <?php foreach ( $custom_table_options as $option => $args ) bb_option_form_element( $option, $args ); ?>
301
- </fieldset>
302
- <fieldset class="submit">
303
- <?php bb_nonce_field( 'options-wordpress-update-options' ); ?>
304
- <input type="hidden" name="action" value="update-options" />
305
- <input class="submit" type="submit" name="submit" value="<?php _e('Save Changes') ?>" />
306
- </fieldset>
307
- </form>
308
-
309
- </div>
310
-
311
- <?php
312
- bb_get_admin_footer();
313
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/options-writing.php DELETED
@@ -1,92 +0,0 @@
1
- <?php
2
-
3
- require_once('admin.php');
4
-
5
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && $_POST['action'] == 'update' ) {
6
-
7
- bb_check_admin_referer( 'options-writing-update' );
8
-
9
- // Deal with xmlrpc checkbox when it isn't checked
10
- if ( !isset( $_POST['enable_xmlrpc'] ) ) {
11
- $_POST['enable_xmlrpc'] = false;
12
- }
13
-
14
- foreach ( (array) $_POST as $option => $value ) {
15
- if ( !in_array( $option, array( '_wpnonce', '_wp_http_referer', 'action', 'submit' ) ) ) {
16
- $option = trim( $option );
17
- $value = is_array( $value ) ? $value : trim( $value );
18
- $value = stripslashes_deep( $value );
19
- if ( $value ) {
20
- bb_update_option( $option, $value );
21
- } else {
22
- bb_delete_option( $option );
23
- }
24
- }
25
- }
26
-
27
- $goback = add_query_arg( 'updated', 'true', wp_get_referer() );
28
- bb_safe_redirect( $goback );
29
- exit;
30
- }
31
-
32
- if ( !empty($_GET['updated']) ) {
33
- bb_admin_notice( __( '<strong>Settings saved.</strong>' ) );
34
- }
35
-
36
- $general_options = array(
37
- 'edit_lock' => array(
38
- 'title' => __( 'Lock post editing after' ),
39
- 'class' => 'short',
40
- 'after' => __( 'minutes' ),
41
- 'note' => __( 'A user can edit a post for this many minutes after submitting.' ),
42
- ),
43
- 'throttle_time' => array(
44
- 'title' => __( 'Throttle time' ),
45
- 'class' => 'short',
46
- 'after' => __( 'seconds' ),
47
- 'note' => __( 'Users must wait this many seconds between posts. By default, moderators, administrators and keymasters are not throttled.' )
48
- )
49
- );
50
-
51
- $remote_options = array(
52
- 'enable_xmlrpc' => array(
53
- 'title' => __( 'XML-RPC' ),
54
- 'type' => 'checkbox',
55
- 'options' => array(
56
- 1 => __( 'Enable the bbPress XML-RPC publishing protocol.' )
57
- )
58
- )
59
- );
60
-
61
- $bb_admin_body_class = ' bb-admin-settings';
62
-
63
- bb_get_admin_header();
64
-
65
- ?>
66
-
67
- <div class="wrap">
68
-
69
- <h2><?php _e( 'Writing Settings' ); ?></h2>
70
- <?php do_action( 'bb_admin_notices' ); ?>
71
-
72
- <form class="settings" method="post" action="<?php bb_uri( 'bb-admin/options-writing.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN ); ?>">
73
- <fieldset><?php foreach ( $general_options as $option => $args ) bb_option_form_element( $option, $args ); ?></fieldset>
74
- <fieldset>
75
- <legend><?php _e( 'Remote Publishing' ); ?></legend>
76
- <p>
77
- <?php _e( 'To interact with bbPress from a desktop client or remote website that uses the XML-RPC publishing interface you must enable it below.' ); ?>
78
- </p>
79
- <?php foreach ( $remote_options as $option => $args ) bb_option_form_element( $option, $args ); ?>
80
- </fieldset>
81
- <fieldset class="submit">
82
- <?php bb_nonce_field( 'options-writing-update' ); ?>
83
- <input type="hidden" name="action" value="update" />
84
- <input class="submit" type="submit" name="submit" value="<?php _e( 'Save Changes' ); ?>" />
85
- </fieldset>
86
- </form>
87
-
88
- </div>
89
-
90
- <?php
91
-
92
- bb_get_admin_footer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/plugins.php DELETED
@@ -1,268 +0,0 @@
1
- <?php
2
- require_once( 'admin.php' );
3
-
4
- require_once( 'includes/functions.bb-plugin.php' );
5
-
6
- $plugin_request = 'all';
7
-
8
- if ( isset( $_GET['plugin_request'] ) ) {
9
- $plugin_request = (string) $_GET['plugin_request'];
10
- }
11
-
12
- switch ( $plugin_request ) {
13
- case 'active':
14
- $_plugin_type = 'normal';
15
- $_plugin_status = 'active';
16
- break;
17
- case 'inactive':
18
- $_plugin_type = 'normal';
19
- $_plugin_status = 'inactive';
20
- break;
21
- case 'autoload':
22
- $_plugin_type = 'autoload';
23
- $_plugin_status = 'all';
24
- break;
25
- default:
26
- $plugin_request = 'all'; // For sanitisation
27
- $_plugin_type = 'all';
28
- $_plugin_status = 'all';
29
- break;
30
- }
31
-
32
- $plugin_nav_class = array(
33
- 'all' => '',
34
- 'active' => '',
35
- 'inactive' => '',
36
- 'autoload' => ''
37
- );
38
- $plugin_nav_class[$plugin_request] = ' class="current"';
39
-
40
- // Get plugin counts
41
- extract( bb_get_plugin_counts() );
42
-
43
- // Get requested plugins
44
- $requested_plugins = bb_get_plugins( 'all', $_plugin_type, $_plugin_status );
45
-
46
- // Get currently active
47
- $active_plugins = (array) bb_get_option( 'active_plugins' );
48
-
49
- // Check for missing plugin files and remove them from the active plugins array
50
- $update = false;
51
- foreach ( $active_plugins as $index => $plugin ) {
52
- if ( !file_exists( bb_get_plugin_path( $plugin ) ) ) {
53
- $update = true;
54
- unset( $active_plugins[$index] );
55
- }
56
- }
57
- if ( $update ) {
58
- bb_update_option( 'active_plugins', $active_plugins );
59
- }
60
- unset( $update, $index, $plugin );
61
-
62
- // Set the action
63
- $action = '';
64
- if( isset( $_GET['action'] ) && !empty( $_GET['action'] ) ) {
65
- $action = trim( $_GET['action'] );
66
- }
67
-
68
- // Set the plugin
69
- $plugin = isset( $_GET['plugin'] ) ? trim( stripslashes( $_GET['plugin'] ) ) : '';
70
-
71
- // Deal with user actions
72
- if ( !empty( $action ) ) {
73
- switch ( $action ) {
74
- case 'activate':
75
- // Activation
76
- bb_check_admin_referer( 'activate-plugin_' . $plugin );
77
-
78
- $result = bb_activate_plugin( $plugin, 'plugins.php?message=error&plugin=' . urlencode( $plugin ) );
79
- if ( is_wp_error( $result ) )
80
- bb_die( $result );
81
-
82
- // Overrides the ?message=error one above
83
- wp_redirect( 'plugins.php?plugin_request=' . $plugin_request . '&message=activate&plugin=' . urlencode( $plugin ) );
84
- break;
85
-
86
- case 'deactivate':
87
- // Deactivation
88
- bb_check_admin_referer( 'deactivate-plugin_' . $plugin );
89
-
90
- // Remove the deactivated plugin
91
- bb_deactivate_plugins( $plugin );
92
-
93
- // Redirect
94
- wp_redirect( 'plugins.php?plugin_request=' . $plugin_request . '&message=deactivate&plugin=' . urlencode( $plugin ) );
95
- break;
96
-
97
- case 'scrape':
98
- // Scrape php errors from the plugin
99
- bb_check_admin_referer('scrape-plugin_' . $plugin);
100
-
101
- $valid_path = bb_validate_plugin( $plugin );
102
- if ( is_wp_error( $valid_path ) )
103
- bb_die( $valid_path );
104
-
105
- // Pump up the errors and output them to screen
106
- error_reporting( E_ALL ^ E_NOTICE );
107
- @ini_set( 'display_errors', true );
108
-
109
- include( $valid_path );
110
- break;
111
- }
112
-
113
- // Stop processing
114
- exit;
115
- }
116
-
117
- // Display notices
118
- if ( isset($_GET['message']) ) {
119
- switch ( $_GET['message'] ) {
120
- case 'error' :
121
- bb_admin_notice( __( '<strong>Plugin could not be activated, it produced a Fatal Error</strong>. The error is shown below.' ), 'error' );
122
- break;
123
- case 'activate' :
124
- $plugin_data = bb_get_plugin_data( $plugin );
125
- bb_admin_notice( sprintf( __( '<strong>"%s" plugin activated</strong>' ), esc_attr( $plugin_data['name'] ) ) );
126
- break;
127
- case 'deactivate' :
128
- $plugin_data = bb_get_plugin_data( $plugin );
129
- bb_admin_notice( sprintf( __( '<strong>"%s" plugin deactivated</strong>' ), esc_attr( $plugin_data['name'] ) ) );
130
- break;
131
- }
132
- }
133
-
134
- if ( isset( $bb->safemode ) && $bb->safemode === true ) {
135
- bb_admin_notice( __( '<strong>"Safe mode" is on, all plugins are disabled even if they are listed as active.</strong>' ), 'error' );
136
- }
137
-
138
- $bb_admin_body_class = ' bb-admin-plugins';
139
-
140
- bb_get_admin_header();
141
- ?>
142
-
143
- <div class="wrap">
144
-
145
- <h2><?php _e( 'Manage Plugins' ); ?></h2>
146
- <?php do_action( 'bb_admin_notices' ); ?>
147
-
148
- <?php
149
- if ( bb_verify_nonce( $_GET['_scrape_nonce'], 'scrape-plugin_' . $plugin ) ) {
150
- $scrape_src = esc_attr(
151
- bb_nonce_url(
152
- bb_get_uri(
153
- 'bb-admin/plugins.php',
154
- array(
155
- 'action' => 'scrape',
156
- 'plugin' => urlencode( $plugin )
157
- ),
158
- BB_URI_CONTEXT_IFRAME_SRC + BB_URI_CONTEXT_BB_ADMIN
159
- ),
160
- 'scrape-plugin_' . $plugin
161
- )
162
- );
163
- ?>
164
-
165
- <div class="plugin-error"><iframe src="<?php echo $scrape_src; ?>"></iframe></div>
166
-
167
- <?php
168
- }
169
- ?>
170
-
171
- <div class="table-filter">
172
- <a<?php echo $plugin_nav_class['all']; ?> href="<?php bb_uri( 'bb-admin/plugins.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN ); ?>"><?php printf( __( 'All <span class="count">(%d)</span>' ), $plugin_count_all ); ?></a> |
173
- <a<?php echo $plugin_nav_class['active']; ?> href="<?php bb_uri( 'bb-admin/plugins.php', array( 'plugin_request' => 'active' ), BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN ); ?>"><?php printf( __( 'Active <span class="count">(%d)</span>' ), $plugin_count_active ); ?></a> |
174
- <a<?php echo $plugin_nav_class['inactive']; ?> href="<?php bb_uri( 'bb-admin/plugins.php', array( 'plugin_request' => 'inactive' ), BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN ); ?>"><?php printf( __( 'Inactive <span class="count">(%d)</span>' ), $plugin_count_inactive ); ?></a> |
175
- <a<?php echo $plugin_nav_class['autoload']; ?> href="<?php bb_uri( 'bb-admin/plugins.php', array( 'plugin_request' => 'autoload' ), BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN ); ?>"><?php printf( __( 'Autoloaded <span class="count">(%d)</span>' ), $plugin_count_autoload ); ?></a>
176
- </div>
177
-
178
- <?php
179
- if ( $requested_plugins ) :
180
- ?>
181
-
182
- <table id="plugins-list" class="widefat">
183
- <thead>
184
- <tr>
185
- <th><?php _e( 'Plugin' ); ?></th>
186
- <th><?php _e( 'Description' ); ?></th>
187
- </tr>
188
- </thead>
189
- <tfoot>
190
- <tr>
191
- <th><?php _e( 'Plugin' ); ?></th>
192
- <th><?php _e( 'Description' ); ?></th>
193
- </tr>
194
- </tfoot>
195
- <tbody>
196
-
197
- <?php
198
- foreach ( $requested_plugins as $plugin => $plugin_data ) :
199
- $class = ' class="inactive"';
200
- $action = 'activate';
201
- $action_class = 'edit';
202
- $action_text = __( 'Activate' );
203
- if ( $plugin_data['autoload'] ) {
204
- $class = ' class="autoload"';
205
- } elseif ( in_array( $plugin, $active_plugins ) ) {
206
- $class = ' class="active"';
207
- $action = 'deactivate';
208
- $action_class = 'delete';
209
- $action_text = __( 'Deactivate' );
210
- }
211
- $href = esc_attr(
212
- bb_nonce_url(
213
- bb_get_uri(
214
- 'bb-admin/plugins.php',
215
- array(
216
- 'plugin_request' => $plugin_request,
217
- 'action' => $action,
218
- 'plugin' => urlencode($plugin)
219
- ),
220
- BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN
221
- ),
222
- $action . '-plugin_' . $plugin
223
- )
224
- );
225
- $meta = array();
226
- if ( $plugin_data['version'] ) $meta[] = sprintf( __( 'Version %s' ), $plugin_data['version'] );
227
- if ( $plugin_data['author_link'] ) $meta[] = sprintf( __( 'By %s' ), $plugin_data['author_link'] );
228
- if ( $plugin_data['uri'] ) $meta[] = '<a href="' . $plugin_data['uri'] . '">' . esc_html__( 'Visit plugin site' ) . '</a>';
229
- if ( count( $meta ) ) {
230
- $meta = '<p class="meta">' . join( ' | ', $meta ) . '</p>';
231
- } else {
232
- $meta = '';
233
- }
234
- ?>
235
-
236
- <tr<?php echo $class; ?>>
237
- <td class="plugin-name">
238
- <span class="row-title"><?php echo $plugin_data['name']; ?></span>
239
- <div><span class="row-actions"><?php if ( !$plugin_data['autoload'] ) : ?><a class="<?php echo $action_class; ?>" href="<?php echo $href; ?>"><?php echo $action_text; ?></a><?php else : ?><span class="note"><?php _e( 'Autoloaded' ); ?></span><?php endif; ?></span>&nbsp;</div>
240
- </td>
241
- <td class="plugin-description">
242
- <?php echo $plugin_data['description']; ?>
243
- <?php echo $meta; ?>
244
- </td>
245
- </tr>
246
-
247
- <?php
248
- endforeach;
249
- ?>
250
-
251
- </tbody>
252
- </table>
253
-
254
- <?php
255
- else :
256
- ?>
257
-
258
- <p class="no-results"><?php _e( 'No plugins found.' ); ?></p>
259
-
260
- <?php
261
- endif;
262
- ?>
263
-
264
- </div>
265
-
266
- <?php
267
- bb_get_admin_footer();
268
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/posts.php DELETED
@@ -1,195 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
5
- bb_check_admin_referer( 'post-bulk' );
6
-
7
- $post_ids = array_map( 'absint', $_POST['post'] );
8
-
9
- $count = 0;
10
-
11
- $action = trim( $_POST['action'] );
12
-
13
- switch ( $action ) {
14
- case 'delete' :
15
- foreach ( $post_ids as $post_id ) {
16
- $count += (int) (bool) bb_delete_post( $post_id, 1 );
17
- }
18
- $query_vars = array( 'message' => 'deleted', 'count' => $count );
19
- break;
20
- case 'undelete' :
21
- foreach ( $post_ids as $post_id ) {
22
- $count += (int) (bool) bb_delete_post( $post_id, 0 );
23
- }
24
- $query_vars = array( 'message' => 'undeleted', 'count' => $count );
25
- break;
26
- default :
27
- if ( $action )
28
- $query_vars = apply_filters( "bulk_post__$action", array(), $post_ids, $action );
29
- break;
30
- }
31
-
32
- bb_safe_redirect( add_query_arg( $query_vars ) );
33
- exit;
34
- }
35
-
36
- if ( !empty( $_GET['message'] ) ) {
37
- $message_count = isset( $_GET['count'] ) ? (int) $_GET['count'] : 1;
38
-
39
- switch ( (string) $_GET['message'] ) {
40
- case 'undeleted':
41
- bb_admin_notice( sprintf( _n( '<strong>Post undeleted.</strong>', '<strong>%s posts undeleted.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
42
- break;
43
- case 'deleted':
44
- bb_admin_notice( sprintf( _n( '<strong>Post deleted.</strong>', '<strong>%s posts deleted.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
45
- break;
46
- case 'spammed':
47
- bb_admin_notice( sprintf( _n( '<strong>Post spammed.</strong>', '<strong>%s posts spammed.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
48
- break;
49
- case 'unspammed-normal':
50
- bb_admin_notice( sprintf( _n( '<strong>Post removed from spam.</strong> It is now a normal post.', '<strong>%s posts removed from spam.</strong> They are now normal posts.', $message_count ), bb_number_format_i18n( $message_count ) ) );
51
- break;
52
- case 'unspammed-deleted':
53
- bb_admin_notice( sprintf( _n( '<strong>Post removed from spam.</strong> It is now a deleted post.', '<strong>%s posts removed from spam.</strong> They are nowdeleted posts.', $message_count ), bb_number_format_i18n( $message_count ) ) );
54
- break;
55
- }
56
- }
57
-
58
- $ip_available = false;
59
- if ( bb_current_user_can( 'view_by_ip' ) ) {
60
- $ip_available = true;
61
- } elseif (isset($_GET['poster_ip'])) {
62
- unset( $_GET['poster_ip'] );
63
- }
64
-
65
- $bb_admin_body_class = ' bb-admin-posts';
66
-
67
- bb_get_admin_header();
68
-
69
- if ( !bb_current_user_can('browse_deleted') )
70
- die(__("Now how'd you get here? And what did you think you'd being doing?")); //This should never happen.
71
- add_filter( 'get_topic_where', 'bb_no_where' );
72
- add_filter( 'get_topic_link', 'bb_make_link_view_all' );
73
- add_filter( 'post_edit_uri', 'bb_make_link_view_all' );
74
- $post_query = new BB_Query_Form( 'post', array( 'post_status' => 'normal', 'count' => true, 'per_page' => 20 ) );
75
- $bb_posts =& $post_query->results;
76
- $total = $post_query->found_rows;
77
- ?>
78
-
79
- <div class="wrap">
80
-
81
- <h2><?php _e( 'Posts' ); ?>
82
- <?php
83
- $h2_search = $post_query->get( 'post_text' );
84
- $h2_forum = $post_query->get( 'forum_id' );
85
- $h2_tag = $post_query->get( 'tag_id' );
86
- $h2_author = $post_query->get( 'post_author_id' );
87
-
88
- $h2_search = $h2_search ? ' ' . sprintf( __('containing &#8220;%s&#8221;'), esc_html( $h2_search ) ) : '';
89
- $h2_forum = $h2_forum ? ' ' . sprintf( __('in &#8220;%s&#8221;') , get_forum_name( $h2_forum ) ) : '';
90
- $h2_tag = $h2_tag ? ' ' . sprintf( __('with tag &#8220;%s&#8221;'), esc_html( bb_get_tag_name( $h2_tag ) ) ) : '';
91
- $h2_author = $h2_author ? ' ' . sprintf( __('by %s') , esc_html( get_user_name( $h2_author ) ) ) : '';
92
-
93
- if ($ip_available) {
94
- $h2_ip = $post_query->get( 'poster_ip' );
95
- $h2_ip = $h2_ip ? ' ' . sprintf( __('from IP address %s'), esc_html( $h2_ip ) ) : '';
96
- } else {
97
- $h2_ip = '';
98
- }
99
-
100
- if ( $h2_search || $h2_forum || $h2_tag || $h2_author || $h2_ip ) {
101
- echo '<span class="subtitle">';
102
-
103
- printf( __( '%1$s%2$s%3$s%4$s%5$s' ), $h2_search, $h2_forum, $h2_tag, $h2_author, $h2_ip );
104
-
105
- echo '</span>';
106
- }
107
- ?>
108
- </h2>
109
- <?php
110
-
111
- do_action( 'bb_admin_notices' );
112
-
113
- $post_query->form( array( 'poster_ip' => $ip_available, 'tag' => true, 'post_author' => true, 'post_status' => true, 'submit' => __( 'Filter' ) ) );
114
-
115
- $bulk_actions = array(
116
- 'delete' => __( 'Delete' ),
117
- 'undelete' => __( 'Undelete' ),
118
- );
119
-
120
- if ( is_numeric( $bulk_action = $post_query->get( 'post_status' ) ) ) {
121
- switch ( $bulk_action ) {
122
- case 0 :
123
- unset( $bulk_actions['undelete'] );
124
- break;
125
- case 1 :
126
- unset( $bulk_actions['delete'] );
127
- }
128
- }
129
-
130
- unset( $bulk_action );
131
-
132
- do_action_ref_array( 'bulk_post_actions', array( &$bulk_actions, &$post_query ) );
133
-
134
- ?>
135
-
136
- <div class="clear"></div>
137
-
138
- <form class="table-form bulk-form" method="post" action="">
139
-
140
- <fieldset>
141
- <select name="action">
142
- <option><?php _e( 'Bulk Actions' ); ?></option>
143
- <?php foreach ( $bulk_actions as $value => $label ) : ?>
144
-
145
- <option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $label ); ?></option>
146
- <?php endforeach; ?>
147
- </select>
148
- <input type="submit" value="<?php esc_attr_e( 'Apply' ); ?>" class="button submit-input" />
149
- <?php bb_nonce_field( 'post-bulk' ); ?>
150
- </fieldset>
151
-
152
- <div class="tablenav">
153
- <?php if ( $total ) : ?>
154
- <div class="tablenav-pages">
155
- <span class="displaying-num"><?php echo $displaying_num = sprintf(
156
- __( '%1$s to %2$s of %3$s' ),
157
- bb_number_format_i18n( ( $page - 1 ) * $post_query->get( 'per_page' ) + 1 ),
158
- $page * $post_query->get( 'per_page' ) < $total ? bb_number_format_i18n( $page * $post_query->get( 'per_page' ) ) : '<span class="total-type-count">' . bb_number_format_i18n( $total ) . '</span>',
159
- '<span class="total-type-count">' . bb_number_format_i18n( $total ) . '</span>'
160
- ); ?></span><span class="displaying-pages">
161
- <?php
162
- $_page_link_args = array(
163
- 'page' => $page,
164
- 'total' => $total,
165
- 'per_page' => $post_query->get( 'per_page' ),
166
- 'mod_rewrite' => false,
167
- 'prev_text' => __( '&laquo;' ),
168
- 'next_text' => __( '&raquo;' )
169
- );
170
- echo $page_number_links = get_page_number_links( $_page_link_args );
171
- ?></span>
172
- <div class="clear"></div>
173
- </div>
174
- <?php endif; ?>
175
- </div>
176
-
177
- <div class="clear"></div>
178
-
179
- <?php bb_admin_list_posts(); ?>
180
-
181
- </form>
182
-
183
- <div class="tablenav bottom">
184
- <?php if ( $total ) : ?>
185
- <div class="tablenav-pages">
186
- <span class="displaying-pages"><?php echo $page_number_links; ?></span>
187
- <div class="clear"></div>
188
- </div>
189
- <?php endif; ?>
190
- </div>
191
- <div class="clear"></div>
192
-
193
- </div>
194
-
195
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/rewrite-rules.php DELETED
@@ -1,4 +0,0 @@
1
- <?php
2
- require('admin-action.php');
3
-
4
- wp_redirect( bb_get_uri('bb-admin/options-permalinks.php', null, BB_URI_CONTEXT_BB_ADMIN + BB_URI_CONTEXT_HEADER) );
 
 
 
 
bp-forums/bbpress/bb-admin/sticky.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
- require('admin-action.php');
3
-
4
- $topic_id = (int) $_GET['id'];
5
- $topic = get_topic ( $topic_id );
6
- $super = ( isset($_GET['super']) && 1 == (int) $_GET['super'] ) ? 1 : 0;
7
-
8
- if ( !$topic )
9
- bb_die(__('There is a problem with that topic, pardner.'));
10
-
11
- if ( !bb_current_user_can( 'stick_topic', $topic_id ) ) {
12
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
13
- exit;
14
- }
15
-
16
- bb_check_admin_referer( 'stick-topic_' . $topic_id );
17
-
18
- if ( topic_is_sticky( $topic_id ) )
19
- bb_unstick_topic ( $topic_id );
20
- else
21
- bb_stick_topic ( $topic_id, $super );
22
-
23
- if ( !$redirect = wp_get_referer() )
24
- $redirect = get_topic_link( $topic_id );
25
-
26
- bb_safe_redirect( $redirect );
27
- exit;
28
-
29
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/style-rtl.css DELETED
@@ -1,465 +0,0 @@
1
- /*
2
- Start with some basic resets
3
- */
4
-
5
- caption,th{text-align:right;}
6
-
7
-
8
- body {
9
- font-family: Tahoma, "Times New Roman";
10
- }
11
-
12
-
13
-
14
- /* Header */
15
-
16
- div#bbHead h1 {
17
- padding-right: 39px;
18
- padding-left: 0;
19
- margin-right: 16px;
20
- margin-left: 0;
21
- background-position: 100% 7px;
22
- font-family: "Times New Roman", Tahoma;
23
- }
24
-
25
- div#bbHead h1 a em {
26
- margin-left: auto;
27
- margin-right: 5px;
28
- }
29
-
30
- div#bbUserInfo {
31
- right: auto;
32
- left: 15px;
33
- }
34
-
35
-
36
-
37
- /* Body */
38
-
39
- div#bbBody {
40
- margin-left: 0;
41
- margin-right: 175px;
42
- padding-right: 0;
43
- padding-left: 15px;
44
- }
45
-
46
- body.bb-menu-folded div#bbBody {
47
- margin-left: auto;
48
- margin-right: 59px;
49
- }
50
-
51
- h2 {
52
- padding-right: 0;
53
- padding-left: 15px;
54
- font-family: "Times New Roman", Tahoma;
55
- }
56
-
57
- body.bb-admin-dashboard h2 {
58
- padding-left: auto;
59
- padding-right: 47px;
60
- background-position: 100% -172px;
61
- }
62
-
63
- body.bb-admin-forums h2 {
64
- padding-left: auto;
65
- padding-right: 47px;
66
- background-position: 100% -802px;
67
- }
68
-
69
- body.bb-admin-topics h2 {
70
- padding-left: auto;
71
- padding-right: 47px;
72
- background-position: 100% -802px;
73
- }
74
-
75
- body.bb-admin-posts h2 {
76
- padding-left: auto;
77
- padding-right: 47px;
78
- background-position: 100% -802px;
79
- }
80
-
81
- body.bb-admin-appearance h2 {
82
- padding-left: auto;
83
- padding-right: 47px;
84
- background-position: 100% 8px;
85
- }
86
-
87
- body.bb-admin-plugins h2 {
88
- padding-left: auto;
89
- padding-right: 47px;
90
- background-position: 100% -532px;
91
- }
92
-
93
- body.bb-admin-users h2 {
94
- padding-left: auto;
95
- padding-right: 47px;
96
- background-position: 100% -891px;
97
- }
98
-
99
- body.bb-admin-tools h2 {
100
- padding-left: auto;
101
- padding-right: 47px;
102
- background-position: 100% -621px;
103
- }
104
-
105
- body.bb-admin-settings h2 {
106
- padding-left: auto;
107
- padding-right: 47px;
108
- background-position: 100% -712px;
109
- }
110
-
111
-
112
-
113
-
114
-
115
- /* Menu */
116
- ul#bbAdminMenu {
117
- float: right;
118
- margin-right: -160px;
119
- margin-left: 5px;
120
- }
121
-
122
- body.bb-menu-folded ul#bbAdminMenu {
123
- margin-left: 5px;
124
- margin-right: -44px;
125
- }
126
-
127
- ul#bbAdminMenu li.bb-menu a {
128
- font-family: "Times New Roman", Tahoma;
129
- }
130
-
131
- ul#bbAdminMenu li.bb-menu div.bb-menu-toggle {
132
- float: left;
133
- background-image: url('images/menu-bits-rtl.gif');
134
- background-position: 100% -110px;
135
- }
136
-
137
- ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu.bb-menu-current div.bb-menu-toggle {
138
- background-position: 100% -208px;
139
- }
140
-
141
- ul#bbAdminMenu li.bb-menu a div.bb-menu-icon {
142
- float: right;
143
- background-position: -331px -39px;
144
- }
145
-
146
- ul#bbAdminMenu li.bb-menu.bb-menu-current a div.bb-menu-icon,
147
- ul#bbAdminMenu li.bb-menu a:hover div.bb-menu-icon {
148
- background-position: -331px -7px;
149
- }
150
-
151
- ul#bbAdminMenu li#bb-menu-dashboard a div.bb-menu-icon {
152
- background-position: -62px -39px;
153
- }
154
-
155
- ul#bbAdminMenu li#bb-menu-dashboard.bb-menu-current a div.bb-menu-icon,
156
- ul#bbAdminMenu li#bb-menu-dashboard a:hover div.bb-menu-icon {
157
- background-position: -62px -7px;
158
- }
159
-
160
- ul#bbAdminMenu li#bb-menu-forums a div.bb-menu-icon {
161
- background-position: -272px -39px;
162
- }
163
-
164
- ul#bbAdminMenu li#bb-menu-forums.bb-menu-current a div.bb-menu-icon,
165
- ul#bbAdminMenu li#bb-menu-forums a:hover div.bb-menu-icon {
166
- background-position: -272px -7px;
167
- }
168
-
169
- ul#bbAdminMenu li#bb-menu-topics a div.bb-menu-icon {
170
- background-position: -272px -39px;
171
- }
172
-
173
- ul#bbAdminMenu li#bb-menu-topics.bb-menu-current a div.bb-menu-icon,
174
- ul#bbAdminMenu li#bb-menu-topics a:hover div.bb-menu-icon {
175
- background-position: -272px -7px;
176
- }
177
-
178
- ul#bbAdminMenu li#bb-menu-posts a div.bb-menu-icon {
179
- background-position: -272px -39px;
180
- }
181
-
182
- ul#bbAdminMenu li#bb-menu-posts.bb-menu-current a div.bb-menu-icon,
183
- ul#bbAdminMenu li#bb-menu-posts a:hover div.bb-menu-icon {
184
- background-position: -272px -7px;
185
- }
186
-
187
- ul#bbAdminMenu li#bb-menu-appearance a div.bb-menu-icon {
188
- background-position: -1px -39px;
189
- }
190
-
191
- ul#bbAdminMenu li#bb-menu-appearance.bb-menu-current a div.bb-menu-icon,
192
- ul#bbAdminMenu li#bb-menu-appearance a:hover div.bb-menu-icon {
193
- background-position: -1px -7px;
194
- }
195
-
196
- ul#bbAdminMenu li#bb-menu-plugins a div.bb-menu-icon {
197
- background-position: -181px -39px;
198
- }
199
-
200
- ul#bbAdminMenu li#bb-menu-plugins.bb-menu-current a div.bb-menu-icon,
201
- ul#bbAdminMenu li#bb-menu-plugins a:hover div.bb-menu-icon {
202
- background-position: -181px -7px;
203
- }
204
-
205
- ul#bbAdminMenu li#bb-menu-users a div.bb-menu-icon {
206
- background-position: -303px -39px;
207
- }
208
-
209
- ul#bbAdminMenu li#bb-menu-users.bb-menu-current a div.bb-menu-icon,
210
- ul#bbAdminMenu li#bb-menu-users a:hover div.bb-menu-icon {
211
- background-position: -303px -7px;
212
- }
213
-
214
- ul#bbAdminMenu li#bb-menu-tools a div.bb-menu-icon {
215
- background-position: -212px -39px;
216
- }
217
-
218
- ul#bbAdminMenu li#bb-menu-tools.bb-menu-current a div.bb-menu-icon,
219
- ul#bbAdminMenu li#bb-menu-tools a:hover div.bb-menu-icon {
220
- background-position: -212px -7px;
221
- }
222
-
223
- ul#bbAdminMenu li#bb-menu-settings a div.bb-menu-icon {
224
- background-position: -241px -39px;
225
- }
226
-
227
- ul#bbAdminMenu li#bb-menu-settings.bb-menu-current a div.bb-menu-icon,
228
- ul#bbAdminMenu li#bb-menu-settings a:hover div.bb-menu-icon {
229
- background-position: -241px -7px;
230
- }
231
-
232
- ul#bbAdminMenu li.bb-menu.bb-menu-separator a {
233
- background-position: -55px -34px;
234
- cursor: e-resize;
235
- }
236
-
237
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-separator a {
238
- background-position: 0 5px;
239
- cursor: w-resize;
240
- }
241
-
242
- ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap {
243
- border-left-width: 1px;
244
- border-right-width: 0;
245
- }
246
-
247
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap {
248
- left: auto;
249
- right: 36px;
250
- }
251
-
252
- ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap span {
253
- font-family: "Times New Roman", Tahoma;
254
- padding-right: 10px;
255
- padding-left: 5px;
256
- }
257
-
258
- ul#bbAdminMenu li.bb-menu li.bb-menu-sub a {
259
- font-family: Tahoma, "Times New Roman";
260
- padding-right:12px;
261
- padding-left: 5px;
262
- background-image: url('images/menu-bits-rtl.gif');
263
- background-position: 100% -306px;
264
- }
265
-
266
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu li.bb-menu-sub a {
267
- background-image: url('images/menu-bits-rtl.gif');
268
- background-position: 100% -306px;
269
- border-right-width: 0 !important;
270
- border-left-width: 1px !important;
271
- }
272
-
273
- ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub a {
274
- background-image: url('images/menu-dark-rtl.gif');
275
- background-position: 100% -20px !important;
276
- }
277
-
278
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub a {
279
- background-image: url('images/menu-dark-rtl.gif');
280
- background-position: 100% -20px !important;
281
- }
282
-
283
- ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub.bb-menu-sub-current a {
284
- background-position: 100% 0 !important;
285
- }
286
-
287
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub.bb-menu-sub-current a {
288
- background-position: 100% 0 !important;
289
- }
290
-
291
- ul#bbAdminMenu li.bb-menu.bb-menu-open li.bb-menu-sub a {
292
- background-position: 100% -306px;
293
- }
294
-
295
-
296
-
297
- /* Dashboard */
298
-
299
- div.dashboard div.versions p.theme a.button {
300
- float: left;
301
- }
302
-
303
-
304
-
305
- /* Search forms */
306
-
307
- form.search-form fieldset, form.bulk-form fieldset {
308
- clear: right;
309
- float: right;
310
- }
311
-
312
- form.search-form fieldset div {
313
- float: right;
314
- margin-right: 0;
315
- margin-left: 5px;
316
- }
317
-
318
-
319
-
320
- /* Table nav */
321
-
322
- div.tablenav {
323
- float: left;
324
- }
325
-
326
- span.displaying-num {
327
- text-align: left;
328
- }
329
-
330
- span.displaying-pages {
331
- float: left;
332
- }
333
-
334
- span.displaying-pages span,
335
- span.displaying-pages a {
336
- float: right;
337
- }
338
-
339
-
340
-
341
- /* Tabled info */
342
-
343
- table#plugins-list.widefat tr.autoload td.plugin-name {
344
- background-position: 0 0;
345
- padding-right: 7px;
346
- padding-left: 20px;
347
- }
348
-
349
- table.widefat .check-column {
350
- padding-right: 7px;
351
- padding-left: 0;
352
- }
353
-
354
- /* Forums */
355
-
356
- ul#forum-list li ul li {
357
- border-left-width: 0;
358
- border-right: 1px dashed rgb(223, 223, 223);
359
- }
360
-
361
- ul#forum-list li ul.list-block {
362
- padding: 0 30px 0 0;
363
- }
364
-
365
- ul#forum-list li img.sort-handle {
366
- float: right;
367
- margin: 0 -4px 0 3px;
368
- }
369
-
370
- #dragHelper img.sort-handle {
371
- float: right;
372
- margin: 0 0 0 3px;
373
- }
374
-
375
- #dragHelper div.row-description {
376
- margin: 0 4px 0 0;
377
- }
378
-
379
-
380
-
381
- /* Themes */
382
-
383
- table.theme-list td {
384
- border-left: 1px solid rgb(221, 221, 221);
385
- border-right-width: 0;
386
- }
387
-
388
- table.theme-list td.position-3 {
389
- border-left: none;
390
- }
391
-
392
- table.theme-list-active td div.screen-shot {
393
- float: right;
394
- margin-right: 0;
395
- margin-left: 15px;
396
- }
397
-
398
-
399
-
400
- /* Options */
401
-
402
- form.settings div {
403
- margin-right: 0;
404
- margin-left: 10px;
405
- }
406
-
407
- form.settings div label,
408
- form.settings div div.label {
409
- float: right;
410
- }
411
-
412
- form.settings div.disabled label,
413
- form.settings div.disabled div.label {
414
- background-position: 0 0;
415
- padding-right: 0;
416
- padding-left: 20px;
417
- }
418
-
419
- form.settings div div.inputs {
420
- margin: 0 210px 0 0;
421
- }
422
-
423
- form.settings div.table {
424
- margin: 0 220px 0 0;
425
- }
426
-
427
- form.settings div p {
428
- margin: 0 3em 0 0;
429
- border-left-width: 0;
430
- border-right: 1px solid rgb(223, 223, 223);
431
- }
432
-
433
- form.settings a.cancel {
434
- float: right;
435
- margin-right: 0;
436
- margin-left: 6px;
437
- }
438
-
439
- form.settings select#timezone-string option {
440
- margin-left: auto;
441
- margin-right: 1em;
442
- }
443
-
444
-
445
-
446
- /* Footer */
447
-
448
- p#bbShowOff {
449
- margin-right: 0;
450
- margin-left: 8px;
451
- float: left;
452
- font-family: "Times New Roman", Tahoma;
453
- }
454
-
455
- div#bbFoot {
456
- font-family: "Times New Roman", Tahoma;
457
- }
458
-
459
- p#bbThanks {
460
- float: right;
461
- }
462
-
463
- p#bbVersion {
464
- text-align: left;
465
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/style.css DELETED
@@ -1,1932 +0,0 @@
1
- /*
2
- Start with some basic resets
3
- */
4
-
5
- /*
6
- Copyright (c) 2009, Yahoo! Inc. All rights reserved.
7
- Code licensed under the BSD License:
8
- http://developer.yahoo.net/yui/license.txt
9
- version: 2.7.0
10
- */
11
- html{color:#000;background:#FFF;}
12
- body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}
13
- table{border-collapse:collapse;border-spacing:0;}
14
- fieldset,img{border:0;}
15
- address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}
16
- del,ins{text-decoration:none;}
17
- li{list-style:none;}
18
- caption,th{text-align:left;}
19
- h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}
20
- q:before,q:after{content:'';}
21
- abbr,acronym{border:0;font-variant:normal;}
22
- sup{vertical-align:baseline;}
23
- sub{vertical-align:baseline;}
24
- legend{color:#000;}
25
- input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}
26
- input,button,textarea,select{*font-size:100%;}
27
- body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
28
- select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}
29
- table{font-size:inherit;font:100%;}
30
- pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
31
-
32
-
33
- html {
34
- height: 100%;
35
- background-color: rgb(249, 249, 249);
36
- }
37
-
38
- body {
39
- height: 100%;
40
- min-width: 785px;
41
- color: rgb(51, 51, 51);
42
- line-height: 1.4em;
43
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
44
- font-size: 0.8em;
45
- }
46
-
47
- a {
48
- outline: none;
49
- }
50
-
51
- div#bbWrap {
52
- height: auto;
53
- min-height: 100%;
54
- width: 100%;
55
- }
56
-
57
- div#bbContent {
58
- height: 100%;
59
- padding-bottom: 45px;
60
- }
61
-
62
-
63
- pre {
64
- /* http://www.longren.org/2006/09/27/wrapping-text-inside-pre-tags/ */
65
- white-space: pre-wrap; /* css-3 */
66
- white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
67
- white-space: -pre-wrap; /* Opera 4-6 */
68
- white-space: -o-pre-wrap; /* Opera 7 */
69
- word-wrap: break-word; /* Internet Explorer 5.5+ */
70
- }
71
-
72
- /* Header */
73
-
74
- div#bbHead {
75
- position: relative;
76
- background-color: rgb(70, 70, 70);
77
- }
78
-
79
- div#bbHead h1 {
80
- padding: 10px 0 5px 39px;
81
- margin-left: 16px;
82
- min-height: 31px;
83
- background: transparent url('images/admin-header-logo.gif') no-repeat 0 8px;
84
- font: normal normal normal 22px/normal Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
85
- color: white;
86
- }
87
-
88
- div#bbHead h1 a {
89
- text-decoration: none;
90
- }
91
-
92
- div#bbHead h1 a span {
93
- color: rgb(255, 255, 255);
94
- }
95
-
96
- div#bbHead h1 a:hover span {
97
- text-decoration: underline;
98
- }
99
-
100
- div#bbHead h1 a em {
101
- background: rgb(88, 88, 88) url('images/visit-site-button-grad.gif') repeat-x 0 0;
102
- color: rgb(170, 170, 170);
103
- text-shadow: rgb(63, 63, 63) 0px -1px 0px;
104
- -moz-border-radius: 3px;
105
- -khtml-border-radius: 3px;
106
- -webkit-border-radius: 3px;
107
- border-radius: 3px;
108
- cursor: pointer;
109
- display: inline-block;
110
- font-size: 0.5em;
111
- font-style: normal;
112
- line-height: 17px;
113
- margin-left: 5px;
114
- padding: 0px 6px;
115
- vertical-align: middle;
116
- }
117
-
118
- div#bbHead h1 a:hover em {
119
- color: rgb(255, 255, 255);
120
- }
121
-
122
- div#bbHead h1 a:active em {
123
- background-position: 0 -27px;
124
- }
125
-
126
- div#bbUserInfo {
127
- position: absolute;
128
- top: 14px;
129
- right: 15px;
130
- font-size: 0.95em;
131
- color: rgb(153, 153, 153);
132
- }
133
-
134
- div#bbUserInfo a {
135
- color: rgb(204, 204, 204);
136
- text-decoration: none;
137
- }
138
-
139
- div#bbUserInfo a:hover {
140
- color: rgb(255, 255, 255);
141
- text-decoration: underline;
142
- }
143
-
144
-
145
-
146
-
147
- /* Body */
148
-
149
- div#bbBody {
150
- margin-left: 180px;
151
- padding-right: 15px;
152
- }
153
-
154
- body.bb-menu-folded div#bbBody {
155
- margin-left: 65px;
156
- }
157
-
158
- h2 {
159
- display: block;
160
- color: rgb(70, 70, 70);
161
- font: italic normal normal 1.9em/1.45em Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
162
- padding: 14px 15px 3px 0;
163
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
164
- background: transparent none no-repeat 0 0;
165
- margin-left: -5px;
166
- }
167
-
168
- h2 span.subtitle {
169
- font-size: 0.75em;
170
- padding-left: 25px;
171
- }
172
-
173
- body.bb-admin-dashboard h2 {
174
- padding-left: 47px;
175
- background-image: url('images/icons32.png');
176
- background-position: 0 -172px;
177
- }
178
-
179
- body.bb-admin-forums h2 {
180
- padding-left: 47px;
181
- background-image: url('images/icons32.png');
182
- background-position: 0 -981px;
183
- }
184
-
185
- body.bb-admin-topics h2 {
186
- padding-left: 47px;
187
- background-image: url('images/icons32.png');
188
- background-position: 0 -1071px;
189
- }
190
-
191
- body.bb-admin-posts h2 {
192
- padding-left: 47px;
193
- background-image: url('images/icons32.png');
194
- background-position: 0 -1161px;
195
- }
196
-
197
- body.bb-admin-appearance h2 {
198
- padding-left: 47px;
199
- background-image: url('images/icons32.png');
200
- background-position: 0 8px;
201
- }
202
-
203
- body.bb-admin-plugins h2 {
204
- padding-left: 47px;
205
- background-image: url('images/icons32.png');
206
- background-position: 0 -532px;
207
- }
208
-
209
- body.bb-admin-users h2 {
210
- padding-left: 47px;
211
- background-image: url('images/icons32.png');
212
- background-position: 0 -891px;
213
- }
214
-
215
- body.bb-admin-user-manage h2 {
216
- padding-left: 47px;
217
- background-image: url('images/icons32.png');
218
- background-position: 0 -891px;
219
- }
220
-
221
- body.bb-admin-tools h2 {
222
- padding-left: 47px;
223
- background-image: url('images/icons32.png');
224
- background-position: 0 -621px;
225
- }
226
-
227
- body.bb-admin-settings h2 {
228
- padding-left: 47px;
229
- background-image: url('images/icons32.png');
230
- background-position: 0 -712px;
231
- }
232
-
233
-
234
-
235
-
236
-
237
- /* Menu */
238
- ul#bbAdminMenu * {
239
- -webkit-user-select: none;
240
- -moz-user-select: none;
241
- -khtml-user-select: none;
242
- user-select: none;
243
- }
244
-
245
- ul#bbAdminMenu {
246
- float: left;
247
- margin: 15px 5px 15px -165px;
248
- position: relative;
249
- width: 145px;
250
- }
251
-
252
- body.bb-menu-folded ul#bbAdminMenu {
253
- margin-left: -50px;
254
- width: auto;
255
- }
256
-
257
- ul#bbAdminMenu li.bb-menu {
258
-
259
- }
260
-
261
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu {
262
- position: relative;
263
- }
264
-
265
- ul#bbAdminMenu li.bb-menu a {
266
- display: block;
267
- color: rgb(0, 102, 0);
268
- background: rgb(241, 241, 241) url('images/menu-bits.gif') repeat-x 0 -379px;
269
- border: 1px solid rgb(227, 227, 227);
270
- width: 133px;
271
- padding: 5px;
272
- font: normal normal normal 1em/1.4em Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
273
- text-decoration: none;
274
- border-bottom-width: 0;
275
- }
276
-
277
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu a {
278
- height: 17px;
279
- width: 17px;
280
- background-image: none;
281
- }
282
-
283
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu a span {
284
- display: none;
285
- }
286
-
287
- ul#bbAdminMenu li.bb-menu.bb-menu-current a {
288
- background-position: 0 0;
289
- border-color: rgb(109, 109, 109);
290
- color: rgb(255, 255, 255);
291
- text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0px;
292
- }
293
-
294
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current a {
295
- background-color: rgb(230, 230, 230);
296
- background-image: none;
297
- border-color: rgb(227, 227, 227);
298
- }
299
-
300
- ul#bbAdminMenu li.bb-menu.bb-menu-current a:hover {
301
- border-color: rgb(181, 181, 181);
302
- color: rgb(255, 255, 255);
303
- }
304
-
305
- ul#bbAdminMenu li.bb-menu.bb-menu-first a {
306
- -moz-border-radius-topleft: 6px;
307
- -moz-border-radius-topright: 6px;
308
- -khtml-border-top-left-radius: 6px;
309
- -khtml-border-top-right-radius: 6px;
310
- -webkit-border-top-left-radius: 6px;
311
- -webkit-border-top-right-radius: 6px;
312
- border-top-left-radius: 6px;
313
- border-top-right-radius: 6px;
314
- }
315
-
316
- ul#bbAdminMenu li.bb-menu.bb-menu-last a {
317
- -moz-border-radius-bottomleft: 6px;
318
- -moz-border-radius-bottomright: 6px;
319
- -khtml-border-bottom-left-radius: 6px;
320
- -khtml-border-bottom-right-radius: 6px;
321
- -webkit-border-bottom-left-radius: 6px;
322
- -webkit-border-bottom-right-radius: 6px;
323
- border-bottom-left-radius: 6px;
324
- border-bottom-right-radius: 6px;
325
- border-bottom-width: 1px;
326
- }
327
-
328
- ul#bbAdminMenu li.bb-menu.bb-menu-open.bb-menu-has-submenu a,
329
- ul#bbAdminMenu li.bb-menu.bb-menu-open a {
330
- -moz-border-radius-bottomleft: 0;
331
- -moz-border-radius-bottomright: 0;
332
- -khtml-border-bottom-left-radius: 0;
333
- -khtml-border-bottom-right-radius: 0;
334
- -webkit-border-bottom-left-radius: 0;
335
- -webkit-border-bottom-right-radius: 0;
336
- border-bottom-left-radius: 0;
337
- border-bottom-right-radius: 0;
338
- }
339
-
340
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-last a {
341
- -moz-border-radius-bottomleft: 6px;
342
- -moz-border-radius-bottomright: 6px;
343
- -khtml-border-bottom-left-radius: 6px;
344
- -khtml-border-bottom-right-radius: 6px;
345
- -webkit-border-bottom-left-radius: 6px;
346
- -webkit-border-bottom-right-radius: 6px;
347
- border-bottom-left-radius: 6px;
348
- border-bottom-right-radius: 6px;
349
- border-bottom-width: 1px;
350
- }
351
-
352
- ul#bbAdminMenu li.bb-menu.bb-menu-open a {
353
- border-bottom-width: 0;
354
- }
355
-
356
- ul#bbAdminMenu li.bb-menu.bb-menu-current.bb-menu-has-submenu a:hover {
357
- border-color: rgb(109, 109, 109);
358
- }
359
-
360
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current.bb-menu-has-submenu a:hover {
361
- border-color: rgb(227, 227, 227);
362
- }
363
-
364
- ul#bbAdminMenu li.bb-menu div.bb-menu-toggle {
365
- float: right;
366
- height: 27px;
367
- width: 24px;
368
- display: none;
369
- background-image: url('images/menu-bits.gif');
370
- background-repeat: no-repeat;
371
- background-position: 0 -110px;
372
- margin-top: -27px;
373
- }
374
-
375
- ul#bbAdminMenu li.bb-menu.bb-menu-last div.bb-menu-toggle {
376
- margin-top: -28px;
377
- }
378
-
379
- ul#bbAdminMenu li.bb-menu.bb-menu-last.bb-menu-open div.bb-menu-toggle {
380
- margin-top: -27px;
381
- }
382
-
383
- ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu:hover div.bb-menu-toggle,
384
- ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu.bb-menu-open div.bb-menu-toggle {
385
- display: block;
386
- }
387
-
388
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu:hover div.bb-menu-toggle,
389
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu.bb-menu-open div.bb-menu-toggle {
390
- display: none;
391
- }
392
-
393
- ul#bbAdminMenu li.bb-menu.bb-menu-has-submenu.bb-menu-current div.bb-menu-toggle {
394
- background-position: 0 -208px;
395
- }
396
-
397
- ul#bbAdminMenu li.bb-menu a:hover,
398
- ul#bbAdminMenu li.bb-menu a:active,
399
- ul#bbAdminMenu li.bb-menu a:focus {
400
- color: rgb(213, 78, 33);
401
- }
402
-
403
- ul#bbAdminMenu li.bb-menu a div.bb-menu-icon {
404
- height: 22px;
405
- width: 22px;
406
- float: left;
407
- background: transparent url('images/menu.png') no-repeat -337px -39px;
408
- }
409
-
410
- ul#bbAdminMenu li.bb-menu.bb-menu-current a div.bb-menu-icon,
411
- ul#bbAdminMenu li.bb-menu a:hover div.bb-menu-icon {
412
- background-position: -337px -7px;
413
- }
414
-
415
- ul#bbAdminMenu li#bb-menu-dashboard a div.bb-menu-icon {
416
- background-position: -67px -39px;
417
- }
418
-
419
- ul#bbAdminMenu li#bb-menu-dashboard.bb-menu-current a div.bb-menu-icon,
420
- ul#bbAdminMenu li#bb-menu-dashboard a:hover div.bb-menu-icon {
421
- background-position: -67px -7px;
422
- }
423
-
424
- ul#bbAdminMenu li#bb-menu-forums a div.bb-menu-icon {
425
- background-position: -367px -39px;
426
- }
427
-
428
- ul#bbAdminMenu li#bb-menu-forums.bb-menu-current a div.bb-menu-icon,
429
- ul#bbAdminMenu li#bb-menu-forums a:hover div.bb-menu-icon {
430
- background-position: -367px -7px;
431
- }
432
-
433
- ul#bbAdminMenu li#bb-menu-topics a div.bb-menu-icon {
434
- background-position: -397px -39px;
435
- }
436
-
437
- ul#bbAdminMenu li#bb-menu-topics.bb-menu-current a div.bb-menu-icon,
438
- ul#bbAdminMenu li#bb-menu-topics a:hover div.bb-menu-icon {
439
- background-position: -397px -7px;
440
- }
441
-
442
- ul#bbAdminMenu li#bb-menu-posts a div.bb-menu-icon {
443
- background-position: -427px -39px;
444
- }
445
-
446
- ul#bbAdminMenu li#bb-menu-posts.bb-menu-current a div.bb-menu-icon,
447
- ul#bbAdminMenu li#bb-menu-posts a:hover div.bb-menu-icon {
448
- background-position: -427px -7px;
449
- }
450
-
451
- ul#bbAdminMenu li#bb-menu-appearance a div.bb-menu-icon {
452
- background-position: -6px -39px;
453
- }
454
-
455
- ul#bbAdminMenu li#bb-menu-appearance.bb-menu-current a div.bb-menu-icon,
456
- ul#bbAdminMenu li#bb-menu-appearance a:hover div.bb-menu-icon {
457
- background-position: -6px -7px;
458
- }
459
-
460
- ul#bbAdminMenu li#bb-menu-plugins a div.bb-menu-icon {
461
- background-position: -186px -39px;
462
- }
463
-
464
- ul#bbAdminMenu li#bb-menu-plugins.bb-menu-current a div.bb-menu-icon,
465
- ul#bbAdminMenu li#bb-menu-plugins a:hover div.bb-menu-icon {
466
- background-position: -186px -7px;
467
- }
468
-
469
- ul#bbAdminMenu li#bb-menu-users a div.bb-menu-icon {
470
- background-position: -308px -39px;
471
- }
472
-
473
- ul#bbAdminMenu li#bb-menu-users.bb-menu-current a div.bb-menu-icon,
474
- ul#bbAdminMenu li#bb-menu-users a:hover div.bb-menu-icon {
475
- background-position: -308px -7px;
476
- }
477
-
478
- ul#bbAdminMenu li#bb-menu-tools a div.bb-menu-icon {
479
- background-position: -217px -39px;
480
- }
481
-
482
- ul#bbAdminMenu li#bb-menu-tools.bb-menu-current a div.bb-menu-icon,
483
- ul#bbAdminMenu li#bb-menu-tools a:hover div.bb-menu-icon {
484
- background-position: -217px -7px;
485
- }
486
-
487
- ul#bbAdminMenu li#bb-menu-settings a div.bb-menu-icon {
488
- background-position: -246px -39px;
489
- }
490
-
491
- ul#bbAdminMenu li#bb-menu-settings.bb-menu-current a div.bb-menu-icon,
492
- ul#bbAdminMenu li#bb-menu-settings a:hover div.bb-menu-icon {
493
- background-position: -246px -7px;
494
- }
495
-
496
- ul#bbAdminMenu li.bb-menu.bb-menu-separator {
497
-
498
- }
499
-
500
- ul#bbAdminMenu li.bb-menu.bb-menu-separator a {
501
- background: transparent url('images/menu-arrows.gif') no-repeat 0 5px;
502
- border-width: 0;
503
- padding: 0;
504
- height: 21px;
505
- cursor: w-resize;
506
- width: 145px;
507
- }
508
-
509
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-separator a {
510
- background: transparent url('images/menu-arrows.gif') no-repeat -171px -34px;
511
- height: 21px;
512
- cursor: e-resize;
513
- width: 29px;
514
- }
515
-
516
- ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap {
517
- display: none;
518
- border: 1px solid rgb(227, 227, 227);
519
- border-bottom-width: 0;
520
- border-left-width: 0;
521
- }
522
-
523
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap {
524
- display: none;
525
- position: absolute;
526
- left: 36px;
527
- top: 0;
528
- width: 145px;
529
- z-index: 1000;
530
- }
531
-
532
- ul#bbAdminMenu li.bb-menu.bb-menu-current div.bb-menu-sub-wrap {
533
- border-color: rgb(170, 170, 170);
534
- border-bottom-width: 1px;
535
- }
536
-
537
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap {
538
- border-width: 0;
539
- border-color: rgb(227, 227, 227);
540
- border-style: solid;
541
- border-bottom-width: 1px;
542
- }
543
-
544
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current div.bb-menu-sub-wrap {
545
- border-color: rgb(170, 170, 170);
546
- }
547
-
548
- ul#bbAdminMenu li.bb-menu.bb-menu-open div.bb-menu-sub-wrap {
549
- display: block;
550
- }
551
-
552
- ul#bbAdminMenu li.bb-menu.bb-menu-last div.bb-menu-sub-wrap {
553
- border-bottom-width: 1px;
554
- }
555
-
556
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap.bb-menu-sub-open {
557
- display: block;
558
- border-bottom-width: 1px;
559
- }
560
-
561
- ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap span {
562
- display: none;
563
- font: normal normal normal 1em/1.45em Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
564
- background-color: rgb(241, 241, 241);
565
- border: 1px solid rgb(227, 227, 227);
566
- -moz-border-radius-topleft: 6px;
567
- -moz-border-radius-topright: 6px;
568
- -khtml-border-top-left-radius: 6px;
569
- -khtml-border-top-right-radius: 6px;
570
- -webkit-border-top-left-radius: 6px;
571
- -webkit-border-top-right-radius: 6px;
572
- border-top-left-radius: 6px;
573
- border-top-right-radius: 6px;
574
- padding: 5px 5px 4px 10px;
575
- cursor: default;
576
- }
577
-
578
- ul#bbAdminMenu li.bb-menu.bb-menu-current div.bb-menu-sub-wrap span {
579
- background-color: rgb(234, 234, 234);
580
- border-color: rgb(170, 170, 170);
581
- }
582
-
583
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu div.bb-menu-sub-wrap span {
584
- display: block;
585
- }
586
-
587
- ul#bbAdminMenu li.bb-menu li.bb-menu-sub a {
588
- width: 127px !important;
589
- -moz-border-radius: 0 !important;
590
- -khtml-border-radius: 0 !important;
591
- -webkit-border-radius: 0 !important;
592
- border-radius: 0 !important;
593
- border-width: 0 !important;
594
- font: normal normal normal 0.85em/1.7em 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
595
- padding: 1px 5px 3px 12px;
596
- color: rgb(0, 102, 0);
597
- text-shadow: none;
598
- background: rgb(255, 255, 255) url('images/menu-bits.gif') no-repeat 0 -306px;
599
- }
600
-
601
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu li.bb-menu-sub a {
602
- height: auto;
603
- background: rgb(255, 255, 255) url('images/menu-bits.gif') no-repeat 0 -306px;
604
- border-right-width: 1px !important;
605
- }
606
-
607
- ul#bbAdminMenu li.bb-menu li.bb-menu-sub a:hover {
608
- background-color: rgb(222, 236, 225) !important;
609
- color: rgb(51, 51, 51);
610
- }
611
-
612
- ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub a {
613
- background-image: url('images/menu-dark.gif');
614
- background-position: 0 -20px !important;
615
- }
616
-
617
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub a {
618
- background-image: url('images/menu-dark.gif');
619
- background-position: 0 -20px !important;
620
- border-color: rgb(170, 170, 170) !important;
621
- }
622
-
623
- ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub.bb-menu-sub-current a {
624
- color: rgb(51, 51, 51);
625
- font-weight: bold;
626
- background-color: rgb(245, 245, 245) !important;
627
- background-position: 0 0 !important;
628
- }
629
-
630
- body.bb-menu-folded ul#bbAdminMenu li.bb-menu.bb-menu-current li.bb-menu-sub.bb-menu-sub-current a {
631
- background-position: 0 0 !important;
632
- }
633
-
634
- ul#bbAdminMenu li.bb-menu.bb-menu-open li.bb-menu-sub a {
635
- background-position: 0 -306px;
636
- }
637
-
638
- div.wrap {
639
- float: left;
640
- width: 100%;
641
- }
642
-
643
- div#message {
644
- -moz-border-radius: 3px;
645
- -khtml-border-radius: 3px;
646
- -webkit-border-radius: 3px;
647
- border-radius: 3px;
648
- border-style: solid;
649
- border-width: 1px;
650
- margin: 5px 0 2px 0;
651
- padding: 0 0.65em;
652
- font-size: 0.9em;
653
- }
654
-
655
- div#message.updated {
656
- background-color: rgb(255, 251, 204);
657
- border-color: rgb(230, 219, 85);
658
- }
659
-
660
- div#message.error {
661
- background-color: rgb(255, 235, 232);
662
- border-color: rgb(204, 0, 0);
663
- }
664
-
665
- div#message p {
666
- line-height: 1;
667
- margin: 0.6em 0;
668
- padding: 2px;
669
- }
670
-
671
- div#message p strong {
672
- font-weight: bold;
673
- }
674
-
675
- div#message a {
676
- color: rgb(0, 102, 0);
677
- text-decoration: none;
678
- }
679
-
680
- div#message a:hover {
681
- color: rgb(213, 78, 33);
682
- }
683
-
684
- div.plugin-error {
685
- background-color: rgb(255, 235, 232);
686
- border-color: rgb(204, 0, 0);
687
- -moz-border-radius: 3px;
688
- -khtml-border-radius: 3px;
689
- -webkit-border-radius: 3px;
690
- border-radius: 3px;
691
- border-style: solid;
692
- border-width: 1px;
693
- margin: 5px 0 2px 0;
694
- padding: 0;
695
- height: 160px;
696
- }
697
-
698
- div.plugin-error iframe {
699
- -moz-border-radius: 3px;
700
- -khtml-border-radius: 3px;
701
- -webkit-border-radius: 3px;
702
- border-radius: 3px;
703
- display: block;
704
- width: 100%;
705
- height: 100%;
706
- margin: 0;
707
- padding: 0;
708
- border-width: 0;
709
- }
710
-
711
-
712
- /* Dashboard */
713
-
714
- div.dashboard {
715
- background-color: rgb(255, 255, 255);
716
- border: 1px solid rgb(223, 223, 223);
717
- -moz-border-radius: 6px;
718
- -khtml-border-radius: 6px;
719
- -webkit-border-radius: 6px;
720
- border-radius: 6px;
721
- margin: 10px 5px 20px 5px;
722
- }
723
-
724
- div.dashboard a {
725
- color: rgb(0, 102, 0);
726
- }
727
-
728
- div.dashboard a:hover {
729
- color: rgb(213, 78, 33);
730
- }
731
-
732
- div.dashboard h3 {
733
- -moz-border-radius-topleft: 6px;
734
- -moz-border-radius-topright: 6px;
735
- -khtml-border-top-left-radius: 6px;
736
- -khtml-border-top-right-radius: 6px;
737
- -webkit-border-top-left-radius: 6px;
738
- -webkit-border-top-right-radius: 6px;
739
- border-top-left-radius: 6px;
740
- border-top-right-radius: 6px;
741
- background: url('images/gray-grad.png') repeat-x rgb(223, 223, 223);
742
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
743
- color: rgb(70, 70, 70);
744
- font-size: 0.9em;
745
- font-weight: bold;
746
- line-height: 1;
747
- margin: 0px;
748
- padding: 7px 9px;
749
- }
750
-
751
- div.dashboard div.table {
752
- border-bottom: 1px solid rgb(236, 236, 236);
753
- background: rgb(249, 249, 249);
754
- }
755
-
756
- div.dashboard div.table table {
757
- width: 100%;
758
- }
759
-
760
- div.dashboard div.table thead th {
761
- color: rgb(119, 119, 119);
762
- font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
763
- font-size: 1em;
764
- font-style: italic;
765
- padding: 3px 8px 4px;
766
- background: rgb(255, 255, 255);
767
- width: 50%;
768
- }
769
-
770
- div.dashboard div.table tbody td {
771
- border-top: 1px solid rgb(236, 236, 236);
772
- padding: 4px 16px;
773
- white-space: nowrap;
774
- font-size: 0.9em;
775
- color: rgb(70, 70, 70);
776
- }
777
-
778
- div.dashboard div.table tbody td span {
779
- font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
780
- font-size: 1.6em;
781
- padding-right: 6px;
782
- }
783
-
784
- div.dashboard p {
785
- color: rgb(51, 51, 51);
786
- font-size: 0.85em;
787
- margin: 8px;
788
- }
789
-
790
- div.dashboard div.versions p span.b {
791
- font-weight: bold;
792
- }
793
-
794
- div.dashboard div.versions p a {
795
- text-decoration: none;
796
- font-weight: bold;
797
- }
798
-
799
- div.dashboard div.versions p.theme a.button {
800
- display: block;
801
- float: right;
802
- font-weight: normal;
803
- -moz-border-radius: 10px;
804
- -khtml-border-radius: 10px;
805
- -webkit-border-radius: 10px;
806
- border-radius: 10px;
807
- padding: 4px 10px;
808
- background: url('images/white-grad.png') repeat-x scroll rgb(242, 242, 242);
809
- border: 1px solid rgb(187, 187, 187);
810
- color: rgb(70, 70, 70);
811
- cursor: pointer;
812
- font-size: 1em;
813
- line-height: 1.2em;
814
- }
815
-
816
- div.dashboard div.versions p.theme a.button:hover {
817
- border-color: rgb(102, 102, 102);
818
- color: rgb(0, 0, 0);
819
- }
820
-
821
- div.dashboard div.versions p.theme a.button:active {
822
- background: url('images/white-grad-active.png') repeat-x scroll rgb(238, 238, 238);
823
- }
824
-
825
- div.dashboard ul li {
826
- color: rgb(51, 51, 51);
827
- font-size: 0.85em;
828
- margin: 8px;
829
- }
830
-
831
- div.dashboard ul li a {
832
- text-decoration: none;
833
- font-weight: bold;
834
- }
835
-
836
-
837
-
838
- /* Search forms */
839
-
840
- form.search-form fieldset, form.bulk-form fieldset {
841
- margin: 10px 0 0 0;
842
- clear: left;
843
- float: left;
844
- }
845
-
846
- form.search-form fieldset div {
847
- float: left;
848
- margin-right: 5px;
849
- margin-top: 3px;
850
- }
851
-
852
- form.search-form fieldset div div {
853
- float: none;
854
- margin: 0;
855
- }
856
-
857
- form.search-form fieldset div label {
858
- display: block;
859
- line-height: 1;
860
- padding: 0 0 3px 0;
861
- font-size: 0.8em;
862
- color: rgb(70, 70, 70);
863
- }
864
-
865
- form.search-form fieldset div div input.text-input {
866
- width: 100px;
867
- padding: 3px;
868
- -moz-border-radius: 4px;
869
- -khtml-border-radius: 4px;
870
- -webkit-border-radius: 4px;
871
- border-radius: 4px;
872
- border: 1px solid rgb(223, 223, 223);
873
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
874
- font-size: 0.85em;
875
- line-height: 1.3em;
876
- }
877
-
878
- form.search-form fieldset div div input.checkbox-input {
879
- margin: 4px;
880
- }
881
-
882
- form.search-form select, form.bulk-form select {
883
- height: 2.1em;
884
- margin: 0;
885
- padding: 3px;
886
- -moz-border-radius: 4px;
887
- -khtml-border-radius: 4px;
888
- -webkit-border-radius: 4px;
889
- border-radius: 4px;
890
- border: 1px solid rgb(223, 223, 223);
891
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
892
- font-size: 0.85em;
893
- }
894
-
895
- form.search-form fieldset div div option {
896
- padding: 3px;
897
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
898
- font-size: 0.9em;
899
- }
900
-
901
- form.search-form div.submit label {
902
- width: 0;
903
- overflow: hidden;
904
- }
905
-
906
- form.search-form div.submit input.button, form.bulk-form input.button {
907
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
908
- -moz-border-radius: 10px;
909
- -khtml-border-radius: 10px;
910
- -webkit-border-radius: 10px;
911
- border-radius: 10px;
912
- padding: 4px 9px 5px;
913
- background: url('images/white-grad.png') repeat-x scroll rgb(242, 242, 242);
914
- border: 1px solid rgb(187, 187, 187);
915
- color: rgb(70, 70, 70);
916
- cursor: pointer;
917
- line-height: 1.1em;
918
- font-size: 0.85em;
919
- }
920
-
921
- form.search-form div.submit input.button:hover, form.bulk-form input.button:hover {
922
- border-color: rgb(102, 102, 102);
923
- color: rgb(0, 0, 0);
924
- }
925
-
926
- form.search-form div.submit input.button:active, form.bulk-form input.button:active {
927
- background: url('images/white-grad-active.png') repeat-x scroll rgb(238, 238, 238);
928
- }
929
-
930
-
931
-
932
- /* Table nav */
933
-
934
- div.tablenav {
935
- margin-top: -1em;
936
- float: right;
937
- }
938
-
939
- div.bottom {
940
- margin-top: 0;
941
- }
942
-
943
- div.tablenav a {
944
- color: rgb(0, 102, 0);
945
- }
946
-
947
- div.tablenav a:hover {
948
- color: rgb(213, 78, 33);
949
- }
950
-
951
- div.tablenav-pages {
952
- margin: 13px 0 0 0;
953
- }
954
-
955
- div.tablenav.bottom div.tablenav-pages {
956
- margin: 0 0 16px 0;
957
- }
958
-
959
- span.displaying-num {
960
- display: block;
961
- text-align: right;
962
- line-height: 1;
963
- font-size: 0.8em;
964
- color: rgb(70, 70, 70);
965
- padding: 0 0 3px 0;
966
- }
967
-
968
- span.displaying-pages {
969
- display: block;
970
- float: right;
971
- cursor: default;
972
- color: rgb(85, 85, 85);
973
- }
974
-
975
- span.displaying-pages span,
976
- span.displaying-pages a {
977
- display: block;
978
- float: left;
979
- -moz-border-radius: 5px;
980
- -khtml-border-radius: 5px;
981
- -webkit-border-radius: 5px;
982
- border-radius: 5px;
983
- border: 1px solid rgb(211, 211, 211);
984
- padding: 3px 7px;
985
- text-decoration: none;
986
- background-color: rgb(223, 223, 223);
987
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
988
- font-size: 0.85em;
989
- line-height: 1.3em;
990
- margin-left: 3px;
991
- }
992
-
993
- span.displaying-pages span.dots {
994
- border-width: 0;
995
- background-color: transparent;
996
- padding: 4px 0 0 0;
997
- font-weight: bold;
998
- }
999
-
1000
- span.displaying-pages a {
1001
- font-weight: bold;
1002
- background: url('images/menu-bits.gif') repeat-x 0 -379px rgb(238, 238, 238);
1003
- border-color: rgb(227, 227, 227);
1004
- }
1005
-
1006
- span.displaying-pages a:hover {
1007
- border-color: rgb(213, 78, 33);
1008
- }
1009
-
1010
- span.displaying-pages a:active {
1011
- color: rgb(255, 255, 255);
1012
- }
1013
-
1014
- div.table-filter {
1015
- color: rgb(102, 102, 102);
1016
- margin: 8px 0px 5px;
1017
- font-size: 0.85em;
1018
- }
1019
-
1020
- div.table-filter a {
1021
- color: rgb(0, 102, 0);
1022
- text-decoration: none;
1023
- }
1024
-
1025
- div.table-filter a.current {
1026
- color: rgb(0, 0, 0);
1027
- font-weight: bold;
1028
- }
1029
-
1030
- div.table-filter a:hover {
1031
- color: rgb(213, 78, 33);
1032
- }
1033
-
1034
- div.table-filter a span.count {
1035
- color: rgb(153, 153, 153);
1036
- font-weight: normal;
1037
- }
1038
-
1039
-
1040
-
1041
-
1042
- /* Tabled info */
1043
-
1044
- p.no-results {
1045
- margin: 10px 0;
1046
- font-size: 0.85em;
1047
- }
1048
-
1049
- table.widefat {
1050
- width: 100%;
1051
- border: 1px solid rgb(223, 223, 223);
1052
- -moz-border-radius: 4px;
1053
- -khtml-border-radius: 4px;
1054
- -webkit-border-radius: 4px;
1055
- border-radius: 4px;
1056
- border-collapse: separate;
1057
- margin: 10px 0;
1058
- }
1059
-
1060
- table.widefat a {
1061
- color: rgb(0, 102, 0);
1062
- text-decoration: none;
1063
- }
1064
-
1065
- table.widefat a:hover {
1066
- color: rgb(213, 78, 33);
1067
- }
1068
-
1069
- table.widefat tr td {
1070
- width: 18%;
1071
- vertical-align: top;
1072
- padding: 3px 7px;
1073
- font-size: 0.85em;
1074
- border-bottom: 1px solid rgb(223, 223, 223);
1075
- }
1076
-
1077
- table.widefat tr.alt td {
1078
- background-color: rgb(255, 255, 255);
1079
- }
1080
-
1081
- table.widefat tr.deleted td {
1082
- background-color: rgb(245, 224, 224);
1083
- }
1084
-
1085
- table.widefat tr.deleted.alt td {
1086
- background-color: rgb(248, 233, 233);
1087
- }
1088
-
1089
- table.widefat tr.spam td {
1090
- background-color: rgb(238, 218, 204);
1091
- }
1092
-
1093
- table.widefat tr.spam.alt td {
1094
- background-color: rgb(243, 228, 218);
1095
- }
1096
-
1097
- table#plugins-list.widefat tr.inactive td {
1098
- background-color: rgb(238, 238, 238);
1099
- }
1100
-
1101
- table#plugins-list.widefat tr.active td {
1102
- background-color: rgb(255, 255, 255);
1103
- }
1104
-
1105
- table#plugins-list.widefat tr.autoload td {
1106
- background-color: rgb(249, 249, 249);
1107
- }
1108
-
1109
- table#plugins-list.widefat tr.autoload td.plugin-name {
1110
- background-image: url('images/input-lock.png');
1111
- background-repeat: no-repeat;
1112
- background-position: 100% 0;
1113
- padding-right: 20px;
1114
- }
1115
-
1116
- table.widefat tr th {
1117
- background: url('images/gray-grad.png') repeat-x rgb(223, 223, 223);
1118
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
1119
- color: rgb(51, 51, 51);
1120
- font-weight: bold;
1121
- vertical-align: top;
1122
- padding: 7px 7px 8px;
1123
- font-size: 0.85em;
1124
- line-height: 1.3em;
1125
- border-bottom: 1px solid rgb(223, 223, 223);
1126
- }
1127
-
1128
- table.widefat tfoot tr th {
1129
- border-bottom-width: 0;
1130
- }
1131
-
1132
- table.widefat .check-column {
1133
- width: 2.2em;
1134
- padding-right: 0;
1135
- }
1136
-
1137
- table#posts-list.widefat tr td.post {
1138
- width: 46%;
1139
- font-size: 0.9em;
1140
- }
1141
-
1142
- table#topics-list.widefat tr td.topic {
1143
- width: 28%;
1144
- font-size: 0.9em;
1145
- }
1146
-
1147
- table#plugins-list.widefat tr td.plugin-name {
1148
- width: 25%;
1149
- font-size: 0.9em;
1150
- }
1151
-
1152
- table#plugins-list.widefat tr td.plugin-description {
1153
- width: 75%;
1154
- }
1155
-
1156
- table.widefat tr td.author img.avatar {
1157
- vertical-align: top;
1158
- border: 1px solid rgb(223, 223, 223);
1159
- }
1160
-
1161
- table.widefat tr td.post p {
1162
- margin-bottom: 0.4em;
1163
- }
1164
-
1165
- table.widefat tr td.plugin-description p {
1166
- margin-bottom: 0.8em;
1167
- }
1168
-
1169
- table.widefat tr td.plugin-description p.meta {
1170
- margin-bottom: 0;
1171
- }
1172
-
1173
- table.widefat tr td.topic span.row-title,
1174
- table.widefat tr td.user span.row-title {
1175
- margin-bottom: 0.4em;
1176
- display: block;
1177
- font-weight: bold;
1178
- }
1179
-
1180
- table.widefat tr td.user img.avatar {
1181
- display: block;
1182
- float: left;
1183
- margin: 3px 8px 3px -1px;
1184
- border: 1px solid rgb(223, 223, 223);
1185
- }
1186
-
1187
- table.widefat tr td.plugin-name span.row-title {
1188
- margin-bottom: 0.8em;
1189
- display: block;
1190
- font-weight: bold;
1191
- }
1192
-
1193
- table.widefat tr td.post div,
1194
- table.widefat tr td.topic div,
1195
- table.widefat tr td.plugin-name div {
1196
- font-size: 0.85em;
1197
- }
1198
-
1199
- table.widefat tr span.row-actions {
1200
- display: none;
1201
- }
1202
-
1203
- table#plugins-list.widefat tr span.row-actions {
1204
- display: inline;
1205
- }
1206
-
1207
- table.widefat tr:hover span.row-actions {
1208
- display: inline;
1209
- }
1210
-
1211
- table.widefat tr span.row-actions span.note {
1212
- color: rgb(102, 102, 102);
1213
- }
1214
-
1215
- table.widefat tr a.post-undelete-link {
1216
- display: none;
1217
- }
1218
-
1219
- table.widefat tr.deleted a.post-undelete-link {
1220
- display: inline;
1221
- }
1222
-
1223
- table.widefat tr.deleted a.post-delete-link {
1224
- display: none;
1225
- }
1226
-
1227
- table.widefat tr td em {
1228
- font-style: italic;
1229
- }
1230
-
1231
- table.widefat tr td strong {
1232
- font-weight: bold;
1233
- }
1234
-
1235
- table.widefat tr td code,
1236
- table.widefat tr td kbd {
1237
- font-family: Consolas, Monaco, Courier, monospace;
1238
- font-size: 1.2em;
1239
- line-height: 1.4;
1240
- background: rgb(234, 234, 234);
1241
- margin: 0px 1px;
1242
- padding: 1px 3px;
1243
- color: rgb(51, 51, 51);
1244
- }
1245
-
1246
-
1247
-
1248
- /* Forums */
1249
-
1250
- body.sorting {
1251
- overflow-x: hidden;
1252
- }
1253
-
1254
- ul#forum-list {
1255
- xwidth: 100%;
1256
- border: 1px solid rgb(223, 223, 223);
1257
- -moz-border-radius: 4px;
1258
- -khtml-border-radius: 4px;
1259
- -webkit-border-radius: 4px;
1260
- border-radius: 4px;
1261
- margin: 10px 0;
1262
- }
1263
-
1264
- ul#forum-list a {
1265
- color: rgb(0, 102, 0);
1266
- text-decoration: none;
1267
- }
1268
-
1269
- ul#forum-list a:hover {
1270
- color: rgb(213, 78, 33);
1271
- }
1272
-
1273
- ul#forum-list li {
1274
- border-top: 1px solid rgb(223, 223, 223);
1275
- background-color: rgb(249, 249, 249);
1276
- }
1277
-
1278
- ul#forum-list li.alt {
1279
- background-color: rgb(255, 255, 255);
1280
- }
1281
-
1282
- ul#forum-list li ul li {
1283
- border-left: 1px dashed rgb(223, 223, 223);
1284
- }
1285
-
1286
- ul#forum-list li ul.list-block {
1287
- padding: 0 0 0 30px;
1288
- }
1289
-
1290
- ul#forum-list li.list-block {
1291
- padding: 3px 0 0 0;
1292
- }
1293
-
1294
- ul#forum-list li div.list-block {
1295
- padding: 0 7px 3px 7px;
1296
- }
1297
-
1298
- ul#forum-list li.thead {
1299
- background: url('images/gray-grad.png') repeat-x rgb(223, 223, 223);
1300
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
1301
- color: rgb(51, 51, 51);
1302
- font-weight: bold;
1303
- vertical-align: top;
1304
- padding: 7px 7px 8px;
1305
- font-size: 0.85em;
1306
- line-height: 1.3em;
1307
- border-top-width: 0;
1308
- }
1309
-
1310
- ul#forum-list li img.sort-handle {
1311
- float: left;
1312
- margin: 0 3px 0 -4px;
1313
- cursor: move;
1314
- }
1315
-
1316
- ul#forum-list li div.row-title {
1317
- font-size: 0.9em;
1318
- font-weight: bold;
1319
- }
1320
-
1321
- ul#forum-list li p.row-description {
1322
- font-size: 0.85em;
1323
- }
1324
-
1325
- ul#forum-list li div.list-block div.row-actions {
1326
- font-size: 0.8em;
1327
- margin-top: 0.4em;
1328
- }
1329
-
1330
- ul#forum-list li div.list-block div.row-actions span {
1331
- display: none;
1332
- }
1333
-
1334
- ul#forum-list li div.list-block:hover div.row-actions span {
1335
- display: inline;
1336
- }
1337
-
1338
- ul#forum-list.sorting li div.list-block div.row-actions span {
1339
- display: none;
1340
- }
1341
-
1342
- ul#forum-list.sorting li div.list-block div.row-actions span {
1343
- display: none;
1344
- }
1345
-
1346
- .helper {
1347
- background-color: rgb(200, 250, 200);
1348
- outline: 1px dashed #777;
1349
- width: 100% !important;
1350
- padding: 3px 0;
1351
- }
1352
-
1353
- #dragHelper {
1354
- xwidth: auto !important;
1355
- padding: 3px;
1356
- }
1357
-
1358
- #dragHelper img.sort-handle {
1359
- float: left;
1360
- margin: 0 3px 0 0;
1361
- }
1362
-
1363
- #dragHelper div.row-description {
1364
- margin: 0 0 0 4px;
1365
- }
1366
-
1367
- #dragHelper div.row-actions span {
1368
- display: none;
1369
- }
1370
-
1371
-
1372
-
1373
- /* Themes */
1374
-
1375
- h3.themes {
1376
- display: block;
1377
- color: rgb(51, 51, 51);
1378
- font-size: 1.17em;
1379
- font-weight: bold;
1380
- padding: 0 0 1em 0;
1381
- margin-top: 10px;
1382
- }
1383
-
1384
- table.theme-list-active,
1385
- table.theme-list {
1386
- margin: 0 auto 40px;
1387
- width: 100%;
1388
- border-collapse: collapse;
1389
- }
1390
-
1391
- table.theme-list {
1392
- margin-bottom: 20px;
1393
- width: 100%;
1394
- border-top: 1px solid rgb(221, 221, 221);
1395
- border-bottom: 1px solid rgb(221, 221, 221);
1396
- border-collapse: collapse;
1397
- }
1398
-
1399
- table.theme-list td {
1400
- width: 240px;
1401
- padding: 20px;
1402
- border-bottom: 1px solid rgb(221, 221, 221);
1403
- border-right: 1px solid rgb(221, 221, 221);
1404
- vertical-align: top;
1405
- }
1406
-
1407
- table.theme-list td.position-3 {
1408
- border-right: none;
1409
- }
1410
-
1411
- table.theme-list td h3.themes,
1412
- table.theme-list-active td h3.themes {
1413
- margin-top: 0;
1414
- font-size: 1em;
1415
- }
1416
-
1417
- table.theme-list td div.screen-shot {
1418
- border: 1px solid rgb(204, 204, 204);
1419
- width: 240px;
1420
- height: 180px;
1421
- margin-bottom: 10px;
1422
- -moz-border-radius: 4px;
1423
- -khtml-border-radius: 4px;
1424
- -webkit-border-radius: 4px;
1425
- border-radius: 4px;
1426
- }
1427
-
1428
- table.theme-list td div.screen-shot img {
1429
- width: 240px;
1430
- height: 180px;
1431
- -moz-border-radius: 4px;
1432
- -khtml-border-radius: 4px;
1433
- -webkit-border-radius: 4px;
1434
- border-radius: 4px;
1435
- }
1436
-
1437
- table.theme-list-active td div.screen-shot {
1438
- border: 1px solid rgb(153, 153, 153);
1439
- width: 150px;
1440
- height: 112px;
1441
- float: left;
1442
- margin-right: 15px;
1443
- -moz-border-radius: 4px;
1444
- -khtml-border-radius: 4px;
1445
- -webkit-border-radius: 4px;
1446
- border-radius: 4px;
1447
- }
1448
-
1449
- table.theme-list-active td div.screen-shot img {
1450
- width: 150px;
1451
- height: 112px;
1452
- -moz-border-radius: 4px;
1453
- -khtml-border-radius: 4px;
1454
- -webkit-border-radius: 4px;
1455
- border-radius: 4px;
1456
- }
1457
-
1458
- table.theme-list td div.description p,
1459
- table.theme-list-active td div.description p {
1460
- color: rgb(102, 102, 102);
1461
- font-style: italic;
1462
- margin: 0 0 1em 0;
1463
- font-size: 0.9em;
1464
- }
1465
-
1466
- table.theme-list td div.description div.actions {
1467
- margin: 0 0 1em 0;
1468
- font-size: 1em;
1469
- }
1470
-
1471
- table.theme-list td div.description p.location,
1472
- table.theme-list-active td div.description p.location {
1473
- color: inherit;
1474
- font-style: normal;
1475
- margin: 0 0 0 0;
1476
- }
1477
-
1478
- table.theme-list td a,
1479
- table.theme-list-active td a {
1480
- color: rgb(0, 102, 0);
1481
- }
1482
-
1483
- table.theme-list td a:hover,
1484
- table.theme-list-active td a:hover {
1485
- color: rgb(213, 78, 33);
1486
- }
1487
-
1488
-
1489
- /* Users */
1490
-
1491
- .bb-admin-user-manage form {
1492
- width: 550px;
1493
- }
1494
-
1495
- #option-pass-strength-fake-input {
1496
- clear: none;
1497
- width: 200px;
1498
- }
1499
- .bb-admin-user-manage #pass-strength-result {
1500
- clear: left;
1501
- float: left;
1502
- margin-top: -25px;
1503
- }
1504
-
1505
- #pass-strength-result {
1506
- padding: 2px;
1507
- text-align: center;
1508
- width: 280px;
1509
- border: 1px solid #ccc;
1510
- background-color: #e3e3e3;
1511
- -moz-border-radius: 3px;
1512
- -khtml-border-radius: 3px;
1513
- -webkit-border-radius: 3px;
1514
- border-radius: 3px;
1515
- }
1516
-
1517
- #pass-strength-result.bad {
1518
- background-color: #ffeff7;
1519
- border-color: #c69;
1520
- }
1521
-
1522
- #pass-strength-result.good {
1523
- background-color: #effff4;
1524
- border-color: #66cc87;
1525
- }
1526
-
1527
- #pass-strength-result.short {
1528
- background-color: #e3e3e3;
1529
- }
1530
-
1531
- #pass-strength-result.strong {
1532
- background-color: #59ef86;
1533
- border-color: #319f52;
1534
- }
1535
-
1536
-
1537
- /* Options */
1538
-
1539
- form.settings fieldset {
1540
- margin-top: 10px;
1541
- margin-bottom: 20px;
1542
- }
1543
-
1544
- form.settings legend,
1545
- div.settings h3 {
1546
- display: block;
1547
- color: rgb(51, 51, 51);
1548
- font-size: 1.17em;
1549
- font-weight: bold;
1550
- padding: 0 0 1em 0;
1551
- }
1552
-
1553
- div.settings {
1554
- margin-bottom: 20px;
1555
- }
1556
-
1557
- hr.settings {
1558
- height: 1px;
1559
- background-color: rgb(221, 221, 221);
1560
- border-width: 0;
1561
- margin-bottom: 20px;
1562
- }
1563
-
1564
- form.settings p,
1565
- div.settings p {
1566
- float: none;
1567
- display: block;
1568
- color: rgb(51, 51, 51);
1569
- font-size: 0.9em;
1570
- margin: 0 0 1em 0;
1571
- }
1572
-
1573
- form.settings ul,
1574
- div.settings ul {
1575
- float: none;
1576
- display: block;
1577
- color: rgb(51, 51, 51);
1578
- font-size: 0.9em;
1579
- margin: 0 4em 1em 4em;
1580
- }
1581
-
1582
- form.settings ul li,
1583
- div.settings ul li {
1584
- list-style: disc outside none;
1585
- }
1586
-
1587
- form.settings strong,
1588
- div.settings strong {
1589
- font-weight: bold;
1590
- }
1591
-
1592
- form.settings em,
1593
- div.settings em {
1594
- font-style: italic;
1595
- }
1596
-
1597
- form.settings code,
1598
- form.settings kbd {
1599
- font-family: Consolas, Monaco, Courier, monospace;
1600
- font-size: 1.2em;
1601
- background: rgb(234, 234, 234);
1602
- margin: 0px 1px;
1603
- padding: 1px 3px;
1604
- color: rgb(51, 51, 51);
1605
- }
1606
-
1607
- form.settings a {
1608
- color: rgb(0, 102, 0);
1609
- }
1610
-
1611
- form.settings a:hover {
1612
- color: rgb(213, 78, 33);
1613
- }
1614
-
1615
- form.settings div {
1616
- clear: both;
1617
- padding: 10px;
1618
- margin-right: 10px;
1619
- }
1620
-
1621
- form.settings div label {
1622
- float: left;
1623
- display: block;
1624
- padding: 3px;
1625
- width: 200px;
1626
- color: rgb(34, 34, 34);
1627
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
1628
- }
1629
-
1630
- form.settings div div.label {
1631
- float: left;
1632
- display: block;
1633
- padding: 3px;
1634
- width: 190px;
1635
- color: rgb(34, 34, 34);
1636
- text-shadow: rgb(255, 255, 255) 0px 1px 0px;
1637
- }
1638
-
1639
- form.settings div.disabled label,
1640
- form.settings div.disabled div.label {
1641
- background-image: url('images/input-lock.png');
1642
- background-repeat: no-repeat;
1643
- background-position: 100% 0;
1644
- padding-right: 20px;
1645
- width: 180px;
1646
- }
1647
-
1648
- form.settings div.disabled div.label {
1649
- width: 170px;
1650
- }
1651
-
1652
- form.settings div div.inputs {
1653
- clear: none;
1654
- padding: 0;
1655
- margin: 0 0 0 210px;
1656
- }
1657
-
1658
- form.settings div div.inputs label {
1659
- float: none;
1660
- clear: none;
1661
- display: block;
1662
- padding: 0;
1663
- margin: 3px 0 6px 0;
1664
- width: auto;
1665
- color: rgb(51, 51, 51);
1666
- text-shadow: none;
1667
- font-size: 0.85em;
1668
- }
1669
-
1670
- form.settings div.disabled div.inputs label {
1671
- background-image: none;
1672
- }
1673
-
1674
- form.settings div div.inputs label.radios img {
1675
- margin: -2px 0 0 0;
1676
- vertical-align: middle;
1677
- border: 1px solid rgb(223, 223, 223);
1678
- }
1679
-
1680
- form.settings input.text,
1681
- form.settings textarea {
1682
- width: 300px;
1683
- padding: 3px;
1684
- -moz-border-radius: 4px;
1685
- -khtml-border-radius: 4px;
1686
- -webkit-border-radius: 4px;
1687
- border-radius: 4px;
1688
- border: 1px solid rgb(223, 223, 223);
1689
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
1690
- font-size: 1em;
1691
- }
1692
-
1693
- form.settings div.disabled input.text,
1694
- form.settings div.disabled textarea {
1695
- background-color: rgb(221, 221, 221);
1696
- }
1697
-
1698
- form.settings div input.text.short {
1699
- width: 100px;
1700
- }
1701
-
1702
- form.settings div input.text.code {
1703
- font-family: Consolas, Monaco, Courier, monospace;
1704
- font-size: 1.2em;
1705
- }
1706
-
1707
- form.settings input.readonly,
1708
- form.settings textarea.readonly {
1709
- background-color: rgb(221, 221, 221);
1710
- }
1711
-
1712
- form.settings div.table {
1713
- margin: 0 0 0 220px;
1714
- padding: 3px;
1715
- -moz-border-radius: 4px;
1716
- -khtml-border-radius: 4px;
1717
- -webkit-border-radius: 4px;
1718
- border-radius: 4px;
1719
- border: 1px solid rgb(223, 223, 223);
1720
- background-color: rgb(221, 221, 221);
1721
- width: 400px;
1722
- }
1723
-
1724
- form.settings div.table table {
1725
- width: 100%;
1726
- font-family: Consolas, Monaco, Courier, monospace;
1727
- font-size: 1.2em;
1728
- border-collapse: collapse;
1729
- }
1730
-
1731
- form.settings div.table table th {
1732
- border-bottom: 1px dotted rgb(70, 70, 70);
1733
- padding: 6px;
1734
- }
1735
-
1736
- form.settings div.table table td {
1737
- padding: 6px;
1738
- }
1739
-
1740
- form.settings div span.after {
1741
- font-size: 0.85em;
1742
- }
1743
-
1744
- form.settings div p {
1745
- color: rgb(102, 102, 102);
1746
- font-style: italic;
1747
- margin: 0 0 0 3em;
1748
- padding: 0.3em;
1749
- border-left: 1px solid rgb(223, 223, 223);
1750
- }
1751
-
1752
- form.settings input.submit {
1753
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
1754
- -moz-border-radius: 11px;
1755
- -khtml-border-radius: 11px;
1756
- -webkit-border-radius: 11px;
1757
- border-radius: 11px;
1758
- border: 1px solid rgb(63, 163, 50);
1759
- cursor: pointer;
1760
- font-size: 11px;
1761
- line-height: 16px;
1762
- padding: 2px 8px;
1763
- background: url('images/button-grad.png') 0 0 rgb(33, 117, 155);
1764
- color: rgb(255, 255, 255);
1765
- font-weight: bold;
1766
- text-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0;
1767
- }
1768
-
1769
- form.settings input.submit:hover {
1770
- border-color: rgb(0, 102, 0);
1771
- }
1772
-
1773
- form.settings input.submit:active {
1774
- background-position: 0 30px;
1775
- }
1776
-
1777
- form.settings a.cancel {
1778
- display: block;
1779
- float: left;
1780
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
1781
- -moz-border-radius: 11px;
1782
- -khtml-border-radius: 11px;
1783
- -webkit-border-radius: 11px;
1784
- border-radius: 11px;
1785
- border: 1px solid rgb(187, 187, 187);
1786
- cursor: pointer;
1787
- font-size: 11px;
1788
- line-height: 16px;
1789
- padding: 2px 8px;
1790
- background: url('images/white-grad.png') repeat-x scroll rgb(242, 242, 242);
1791
- color: rgb(70, 70, 70);
1792
- cursor: pointer;
1793
- font-weight: bold;
1794
- text-shadow: rgba(255, 255, 255, 0.7) 0 -1px 0;
1795
- margin-right: 6px;
1796
- text-decoration: none;
1797
- }
1798
-
1799
- form.settings a.cancel:hover {
1800
- border-color: rgb(153, 51, 51);
1801
- color: rgb(204, 51, 51);
1802
- }
1803
-
1804
- form.settings a.cancel:active {
1805
- background: url('images/white-grad-active.png') repeat-x scroll rgb(238, 238, 238);
1806
- }
1807
-
1808
- form.settings div#option-mod-rewrite div.inputs label.radios span {
1809
- display: inline-block;
1810
- width: 7em;
1811
- }
1812
-
1813
- form.settings div#option-mod-rewrite div.inputs label.radios code {
1814
- white-space: nowrap;
1815
- }
1816
-
1817
- form.settings textarea#rewrite-rules {
1818
- width: 99%;
1819
- }
1820
-
1821
- form.settings select#timezone-string option {
1822
- margin-left: 1em;
1823
- }
1824
-
1825
-
1826
- /* Footer */
1827
-
1828
- p#bbShowOff {
1829
- margin: 0 8px 8px 0;
1830
- padding: 6px 8px;
1831
- color: rgb(255, 255, 255);
1832
- background-color: rgb(170, 170, 170);
1833
- font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
1834
- font-size: 0.9em;
1835
- font-style: italic;
1836
- -moz-border-radius: 6px;
1837
- -khtml-border-radius: 6px;
1838
- -webkit-border-radius: 6px;
1839
- border-radius: 6px;
1840
- float: right;
1841
- }
1842
-
1843
- div#bbFoot {
1844
- background-color: rgb(70, 70, 70);
1845
- color: rgb(153, 153, 153);
1846
- margin-top: -45px;
1847
- clear: both;
1848
- position: relative;
1849
- width: 100%;
1850
- font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;
1851
- font-size: 0.9em;
1852
- font-style: italic;
1853
- }
1854
-
1855
- div#bbFoot p {
1856
- line-height: 15px;
1857
- padding: 15px;
1858
- }
1859
-
1860
- div#bbFoot p a {
1861
- color: rgb(204, 204, 204);
1862
- text-decoration: none;
1863
- }
1864
-
1865
- p#bbThanks {
1866
- float: left;
1867
- }
1868
-
1869
- p#bbVersion {
1870
- text-align: right;
1871
- }
1872
-
1873
- div.clear {
1874
- clear: both !important;
1875
- height: 0;
1876
- line-height: 0;
1877
- font-size: 0;
1878
- }
1879
-
1880
-
1881
-
1882
-
1883
-
1884
-
1885
-
1886
-
1887
- /* Layout classes */
1888
- /*
1889
- .absleft {
1890
- position: absolute;
1891
- left: 0;
1892
- }
1893
-
1894
- .absright {
1895
- position: absolute;
1896
- right: 0;
1897
- }
1898
-
1899
- .abstop {
1900
- position: absolute;
1901
- top: 0;
1902
- }
1903
-
1904
- .posrel {
1905
- position: relative;
1906
- }
1907
-
1908
- .alignleft {
1909
- float: left;
1910
- }
1911
-
1912
- .alignright {
1913
- float: right;
1914
- }
1915
- */
1916
- /*
1917
- .alternate, .alt {
1918
- background: #f1f1f1;
1919
- }
1920
- */
1921
- /*
1922
- .active {
1923
- background-color: rgb(200, 250, 200);
1924
- }
1925
- */
1926
-
1927
-
1928
-
1929
-
1930
- /* List Blocks */
1931
-
1932
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/tag-destroy.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
-
3
- require( 'admin.php' );
4
-
5
- if ( !bb_current_user_can( 'manage_tags' ) )
6
- bb_die( __( 'You are not allowed to manage tags.' ) );
7
-
8
- $tag_id = (int) $_POST['id' ];
9
-
10
- bb_check_admin_referer( 'destroy-tag_' . $tag_id );
11
-
12
- if ( !$old_tag = bb_get_tag( $tag_id ) )
13
- bb_die( __( 'Tag not found.' ) );
14
-
15
- if ( bb_destroy_tag( $tag_id ) )
16
- bb_die( __( 'That tag was successfully destroyed' ) );
17
- else
18
- bb_die( printf( __( "Something odd happened when attempting to destroy that tag.<br />\n<a href=\"%s\">Try Again?</a>" ), wp_get_referer() ) ) ;
19
-
20
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/tag-merge.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
-
3
- require( 'admin.php' );
4
-
5
- if ( !bb_current_user_can( 'manage_tags' ) )
6
- bb_die( __( 'You are not allowed to manage tags.' ) );
7
-
8
- $old_id = (int) $_POST['id' ];
9
- $tag = $_POST['tag'];
10
-
11
- bb_check_admin_referer( 'merge-tag_' . $old_id );
12
-
13
- if ( ! $tag = bb_get_tag( $tag ) )
14
- bb_die( __( 'The destination tag you specified could not be found.' ) );
15
-
16
- if ( ! bb_get_tag( $old_id ) )
17
- bb_die( __( 'The original tag could not be found.' ) );
18
-
19
- if ( $merged = bb_merge_tags( $old_id, $tag->tag_id ) )
20
- bb_die(
21
- sprintf( __( "Number of topics from which the old tag was removed: %d <br />\n"), $merged['old_count'] ) .
22
- sprintf( __( "Number of topics to which the new tag was added: %d <br />\n"),$merged['diff_count'] ) .
23
- sprintf( __( "Number of rows deleted from tags table:%d <br />\n"),$merged['destroyed']['tags'] ) .
24
- sprintf( __( '<a href="%s">View Results of Merge</a>'), bb_get_tag_link() )
25
- );
26
- else
27
- bb_die( printf( __( "Something odd happened when attempting to merge those tags.<br />\n<a href=\"%s\">Try Again?</a>" ), wp_get_referer() ) );
28
-
29
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/tag-rename.php DELETED
@@ -1,23 +0,0 @@
1
- <?php
2
-
3
- require( 'admin.php' );
4
-
5
- if ( !bb_current_user_can( 'manage_tags' ) )
6
- bb_die( __( 'You are not allowed to manage tags.' ) );
7
-
8
- $tag_id = (int) $_POST['id' ];
9
- $tag = stripslashes( $_POST['tag'] );
10
-
11
- bb_check_admin_referer( 'rename-tag_' . $tag_id );
12
-
13
- if ( !$old_tag = bb_get_tag( $tag_id ) )
14
- bb_die( __( 'Tag not found.' ) );
15
-
16
- if ( $tag = bb_rename_tag( $tag_id, $tag ) )
17
- wp_redirect( bb_get_tag_link() );
18
- else
19
- bb_die( printf( __( 'There already exists a tag by that name or the name is invalid. <a href="%s">Try Again</a>'), wp_get_referer() ) );
20
-
21
- exit;
22
-
23
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/themes.php DELETED
@@ -1,159 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- $themes = bb_get_themes();
5
-
6
- $activetheme = bb_get_option('bb_active_theme');
7
- if (!$activetheme) {
8
- $activetheme = BB_DEFAULT_THEME;
9
- }
10
-
11
- if ( isset($_GET['theme']) ) {
12
- if ( !bb_current_user_can( 'manage_themes' ) ) {
13
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
14
- exit;
15
- }
16
-
17
- bb_check_admin_referer( 'switch-theme' );
18
- do_action( 'bb_deactivate_theme_' . $activetheme );
19
-
20
- $theme = stripslashes($_GET['theme']);
21
- $theme_data = bb_get_theme_data( $theme );
22
- if ($theme_data['Name']) {
23
- $name = $theme_data['Name'];
24
- } else {
25
- $name = preg_replace( '/^([a-z0-9_-]+#)/i', '', $theme);
26
- }
27
- if ($theme == BB_DEFAULT_THEME) {
28
- bb_delete_option( 'bb_active_theme' );
29
- } else {
30
- bb_update_option( 'bb_active_theme', $theme );
31
- }
32
- do_action( 'bb_activate_theme_' . $theme );
33
- wp_redirect( bb_get_uri('bb-admin/themes.php', array('activated' => 1, 'name' => urlencode( $name ) ), BB_URI_CONTEXT_HEADER + BB_URI_CONTEXT_BB_ADMIN ) );
34
- exit;
35
- }
36
-
37
- if ( isset($_GET['activated']) )
38
- $theme_notice = bb_admin_notice( sprintf( __( '<strong>Theme "%s" activated</strong>' ), esc_attr($_GET['name'])) );
39
-
40
- if ( !in_array($activetheme, $themes) ) {
41
- if ($activetheme == BB_DEFAULT_THEME) {
42
- remove_action( 'bb_admin_notices', $theme_notice );
43
- bb_admin_notice( __( '<strong>Default theme is missing.</strong>' ), 'error' );
44
- } else {
45
- bb_delete_option( 'bb_active_theme' );
46
- remove_action( 'bb_admin_notices', $theme_notice );
47
- bb_admin_notice( __( '<strong>Theme not found. Default theme applied.</strong>' ), 'error' );
48
- }
49
- }
50
-
51
- function bb_admin_theme_row( $theme, $position ) {
52
- $theme_directory = bb_get_theme_directory( $theme );
53
- $theme_data = file_exists( $theme_directory . 'style.css' ) ? bb_get_theme_data( $theme ) : false;
54
- $screen_shot = file_exists( $theme_directory . 'screenshot.png' ) ? esc_url( bb_get_theme_uri( $theme ) . 'screenshot.png' ) : false;
55
- $activation_url = bb_get_uri('bb-admin/themes.php', array('theme' => urlencode($theme)), BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN);
56
- $activation_url = esc_url( bb_nonce_url( $activation_url, 'switch-theme' ) );
57
-
58
- if ( 1 === $position || 0 === $position ) {
59
- echo '<tr>';
60
- }
61
- ?>
62
- <td class="position-<?php echo( (int) $position ); ?>">
63
- <div class="screen-shot"><?php if ( $screen_shot ) : ?><a href="<?php echo $activation_url; ?>" title="<?php echo esc_attr( sprintf( __( 'Activate "%s"' ), $theme_data['Title'] ) ); ?>"><img alt="<?php echo esc_attr( $theme_data['Title'] ); ?>" src="<?php echo $screen_shot; ?>" /></a><?php endif; ?></div>
64
- <div class="description">
65
- <h3 class="themes">
66
- <?php
67
- printf(
68
- __( '%1$s %2$s by <cite>%3$s</cite>' ),
69
- $theme_data['Title'],
70
- $theme_data['Version'],
71
- $theme_data['Author']
72
- );
73
- ?>
74
- </h3>
75
-
76
- <?php
77
- if ( $theme_data['Porter'] ) {
78
- ?>
79
- <p>
80
- <?php
81
- printf(
82
- __( 'Ported by <cite>%s</cite>' ),
83
- $theme_data['Porter']
84
- );
85
- ?>
86
- </p>
87
- <?php
88
- }
89
- ?>
90
-
91
- <?php echo $theme_data['Description']; // Description is autop'ed ?>
92
- <?php
93
- if ( 0 !== $position ) {
94
- ?>
95
- <div class="actions">
96
- <a href="<?php echo $activation_url; ?>" title="<?php echo esc_attr( sprintf( __( 'Activate "%s"' ), $theme_data['Title'] ) ); ?>"><?php _e( 'Activate' ); ?></a>
97
- </div>
98
- <?php
99
- }
100
- ?>
101
- <p class="location"><?php printf(__('All of this theme\'s files are located in the "%s" themes directory.'), $theme_data['Location']); ?></p>
102
- </div>
103
- </td>
104
- <?php
105
-
106
- if ( 3 === $position || 0 === $position ) {
107
- echo '</tr>';
108
- }
109
- }
110
-
111
- if ( isset( $bb->safemode ) && $bb->safemode === true ) {
112
- bb_admin_notice( __( '<strong>"Safe mode" is on, the default theme will be used instead of the active theme indicated below.</strong>' ), 'error' );
113
- }
114
-
115
- $bb_admin_body_class = ' bb-admin-appearance';
116
-
117
- bb_get_admin_header();
118
- ?>
119
-
120
- <h2><?php _e('Manage Themes'); ?></h2>
121
- <?php do_action( 'bb_admin_notices' ); ?>
122
-
123
- <h3 class="themes"><?php _e('Current Theme'); ?></h3>
124
- <div>
125
- <table class="theme-list-active">
126
- <?php bb_admin_theme_row( $themes[$activetheme], 0 ); unset($themes[$activetheme] ); ?>
127
- </table>
128
- </div>
129
-
130
- <?php if ( !empty($themes) ) : ?>
131
-
132
- <h3 class="themes"><?php _e('Available Themes'); ?></h3>
133
- <div>
134
- <table class="theme-list">
135
- <?php
136
- $i = 0;
137
- foreach ( $themes as $theme ) {
138
- $position = 1 + ( $i % 3 );
139
-
140
- bb_admin_theme_row( $theme, $position );
141
-
142
- $i++;
143
- }
144
-
145
- switch ( $position ) {
146
- case 1:
147
- echo '<td class="position-2"></td><td class="position-3"></td></tr>';
148
- break;
149
- case 2:
150
- echo '<td class="position-3"></td></tr>';
151
- break;
152
- case 3:
153
- break;
154
- }
155
- ?>
156
- </table>
157
- </div>
158
-
159
- <?php endif; bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/tools-recount.php DELETED
@@ -1,121 +0,0 @@
1
- <?php
2
- require_once( 'admin.php' );
3
- require_once( 'includes/functions.bb-recount.php' );
4
-
5
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
6
- bb_check_admin_referer( 'do-counts' );
7
-
8
- // Stores messages
9
- $messages = array();
10
-
11
- if ( !empty( $_POST['topic-posts'] ) ) {
12
- $message = bb_recount_topic_posts();
13
- $messages[] = $message[1];
14
- }
15
-
16
- if ( !empty( $_POST['topic-voices'] ) ) {
17
- $message = bb_recount_topic_voices();
18
- $messages[] = $message[1];
19
- }
20
-
21
- if ( !empty( $_POST['topic-deleted-posts'] ) ) {
22
- $message = bb_recount_topic_deleted_posts();
23
- $messages[] = $message[1];
24
- }
25
-
26
- if ( !empty( $_POST['forums'] ) ) {
27
- $message = bb_recount_forum_topics();
28
- $messages[] = $message[1];
29
- $message = bb_recount_forum_posts();
30
- $messages[] = $message[1];
31
- }
32
-
33
- if ( !empty( $_POST['topics-replied'] ) ) {
34
- $message = bb_recount_user_topics_replied();
35
- $messages[] = $message[1];
36
- }
37
-
38
- if ( !empty( $_POST['topic-tag-count'] ) ) {
39
- $message = bb_recount_topic_tags();
40
- $messages[] = $message[1];
41
- }
42
-
43
- if ( !empty( $_POST['tags-tag-count'] ) ) {
44
- $message = bb_recount_tag_topics();
45
- $messages[] = $message[1];
46
- }
47
-
48
- if ( !empty( $_POST['tags-delete-empty'] ) ) {
49
- $message = bb_recount_tag_delete_empty();
50
- $messages[] = $message[1];
51
- }
52
-
53
- if ( !empty( $_POST['clean-favorites'] ) ) {
54
- $message = bb_recount_clean_favorites();
55
- $messages[] = $message[1];
56
- }
57
-
58
- bb_recount_list();
59
- foreach ( (array) $recount_list as $item ) {
60
- if ( isset($item[2]) && isset($_POST[$item[0]]) && 1 == $_POST[$item[0]] && is_callable($item[2]) ) {
61
- $message = call_user_func( $item[2] );
62
- if ( is_array( $message ) ) {
63
- $messages[] = $message[1];
64
- } else {
65
- $messages[] = $message;
66
- }
67
- }
68
- }
69
-
70
- wp_cache_flush();
71
-
72
- if ( count( $messages ) ) {
73
- $messages = join( '</p>' . "\n" . '<p>', $messages );
74
- bb_admin_notice( $messages );
75
- }
76
- }
77
-
78
-
79
- $bb_admin_body_class = ' bb-admin-tools';
80
-
81
- bb_get_admin_header();
82
- ?>
83
- <h2><?php _e('Tools') ?></h2>
84
- <?php do_action( 'bb_admin_notices' ); ?>
85
-
86
- <form class="settings" method="post" action="<?php bb_uri('bb-admin/tools-recount.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>">
87
- <fieldset>
88
- <legend><?php _e( 'Re-count' ) ?></legend>
89
- <p><?php _e( 'To minimize database queries, bbPress keeps it\'s own count of various items like posts in each topic and topics in each forum. Occasionally these internal counters may become incorrect, you can manually re-count these items using this form.' ) ?></p>
90
- <p><?php _e( 'You can also clean out some stale items here, like empty tags.' ) ?></p>
91
- <?php
92
- bb_recount_list();
93
- if ( $recount_list ) {
94
- ?>
95
- <div id="option-counts">
96
- <div class="label">
97
- <?php _e( 'Items to re-count' ); ?>
98
- </div>
99
- <div class="inputs">
100
- <?php
101
- foreach ( $recount_list as $item ) {
102
- echo '<label class="checkboxs"><input type="checkbox" class="checkbox" name="' . esc_attr( $item[0] ) . '" id="' . esc_attr( str_replace( '_', '-', $item[0] ) ) . '" value="1" /> ' . esc_html( $item[1] ) . '</label>' . "\n";
103
- }
104
- ?>
105
- </div>
106
- </div>
107
- <?php
108
- } else {
109
- ?>
110
- <p><?php _e( 'There are no re-count tools available.' ) ?></p>
111
- <?php
112
- }
113
- ?>
114
- </fieldset>
115
- <fieldset class="submit">
116
- <?php bb_nonce_field( 'do-counts' ); ?>
117
- <input class="submit" type="submit" name="submit" value="<?php _e('Recount Items') ?>" />
118
- </fieldset>
119
- </form>
120
-
121
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/topic-move.php DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
- require_once('admin-action.php');
3
-
4
- $topic_id = absint( $_POST['topic_id'] );
5
- $forum_id = absint( $_POST['forum_id'] );
6
-
7
- if ( !is_numeric($topic_id) || !is_numeric($forum_id) )
8
- bb_die(__('Invalid topic or forum.'));
9
-
10
- if ( !bb_current_user_can( 'move_topic', $topic_id, $forum_id ) ) {
11
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
12
- exit;
13
- }
14
-
15
- bb_check_admin_referer( 'move-topic_' . $topic_id );
16
-
17
- $topic = get_topic( $topic_id );
18
- $forum = bb_get_forum( $forum_id );
19
-
20
- if ( !$topic || !$forum )
21
- bb_die(__('Your topic or forum caused all manner of confusion'));
22
-
23
- bb_move_topic( $topic_id, $forum_id );
24
-
25
- if ( !$redirect = wp_get_referer() )
26
- $redirect = get_topic_link( $topic_id );
27
-
28
- bb_safe_redirect( $redirect );
29
- exit;
30
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/topic-toggle.php DELETED
@@ -1,33 +0,0 @@
1
- <?php
2
- require('admin-action.php');
3
-
4
- $topic_id = (int) $_GET['id'];
5
- $topic = get_topic ( $topic_id );
6
-
7
- if ( !$topic )
8
- bb_die(__('There is a problem with that topic, pardner.'));
9
-
10
- if ( !bb_current_user_can( 'close_topic', $topic_id ) ) {
11
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
12
- exit;
13
- }
14
-
15
- bb_check_admin_referer( 'close-topic_' . $topic_id );
16
-
17
- if ( topic_is_open( $topic_id ) ) {
18
- bb_close_topic( $topic_id );
19
- $message = 'closed';
20
- } else {
21
- bb_open_topic ( $topic_id );
22
- $message = 'opened';
23
- }
24
-
25
- if ( $sendto = wp_get_referer() ) {
26
- $sendto = remove_query_arg( 'message', $sendto );
27
- $sendto = add_query_arg( 'message', $message, $sendto );
28
- } else {
29
- $sendto = get_topic_link( $topic_id );
30
- }
31
-
32
- bb_safe_redirect( $sendto );
33
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/topics.php DELETED
@@ -1,267 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
5
- bb_check_admin_referer( 'topic-bulk' );
6
-
7
- $topic_ids = array_map( 'absint', $_POST['topic'] );
8
-
9
- $affected = 0;
10
-
11
- $action = trim( $_POST['action'] );
12
-
13
- switch ( $action ) {
14
- case 'close' :
15
- foreach ( $topic_ids as $topic_id ) {
16
- $affected += bb_close_topic( $topic_id );
17
- }
18
- $query_vars = array( 'message' => 'closed', 'count' => $affected );
19
- break;
20
- case 'open' :
21
- foreach ( $topic_ids as $topic_id ) {
22
- $affected += bb_open_topic( $topic_id );
23
- }
24
- $query_vars = array( 'message' => 'opened', 'count' => $affected );
25
- break;
26
- case 'delete' :
27
- foreach ( $topic_ids as $topic_id ) {
28
- $affected += (int) (bool) bb_delete_topic( $topic_id, 1 );
29
- }
30
- $query_vars = array( 'message' => 'deleted', 'count' => $affected );
31
- break;
32
- case 'undelete' :
33
- foreach ( $topic_ids as $topic_id ) {
34
- $affected += (int) (bool) bb_delete_topic( $topic_id, 0 );
35
- }
36
- $query_vars = array( 'message' => 'undeleted', 'count' => $affected );
37
- break;
38
- default :
39
- if ( $action )
40
- $query_vars = apply_filters( "bulk_topic__$action", array(), $topic_ids );
41
- break;
42
- }
43
-
44
- bb_safe_redirect( add_query_arg( $query_vars ) );
45
- exit;
46
- }
47
-
48
- if ( !empty( $_GET['message'] ) ) {
49
- $message_count = isset( $_GET['count'] ) ? (int) $_GET['count'] : 1;
50
-
51
- switch ( (string) $_GET['message'] ) {
52
- case 'undeleted':
53
- bb_admin_notice( sprintf( _n( '<strong>Topic undeleted.</strong>', '<strong>%s topics undeleted.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
54
- break;
55
- case 'deleted':
56
- bb_admin_notice( sprintf( _n( '<strong>Topic deleted.</strong>', '<strong>%s topics deleted.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
57
- break;
58
- case 'opened':
59
- bb_admin_notice( sprintf( _n( '<strong>Topic opened.</strong>', '<strong>%s topics opened.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
60
- break;
61
- case 'closed':
62
- bb_admin_notice( sprintf( _n( '<strong>Topic closed.</strong>', '<strong>%s topics closed.</strong>', $message_count ), bb_number_format_i18n( $message_count ) ) );
63
- break;
64
- }
65
- }
66
-
67
- $bb_admin_body_class = ' bb-admin-topics';
68
-
69
- bb_get_admin_header();
70
-
71
- if ( !bb_current_user_can('browse_deleted') )
72
- die(__("Now how'd you get here? And what did you think you'd being doing?")); //This should never happen.
73
- add_filter( 'topic_link', 'bb_make_link_view_all' );
74
- add_filter( 'topic_last_post_link', 'bb_make_link_view_all' );
75
- $topic_query_vars = array( 'topic_status' => 'normal', 'open' => 'open', 'count' => true, 'per_page' => 20 );
76
- if ( isset($_POST['search']) && $_POST['search'] ) {
77
- $topic_query_vars['post_status'] = 'all';
78
- } elseif ( isset($_GET['search']) && $_GET['search'] ) {
79
- $topic_query_vars['post_status'] = 'all';
80
- }
81
- $topic_query = new BB_Query_Form( 'topic', $topic_query_vars );
82
- $topics = $topic_query->results;
83
- ?>
84
-
85
- <div class="wrap">
86
-
87
- <h2><?php _e( 'Topics' ); ?>
88
- <?php
89
- $h2_search = $topic_query->get( 'search' );
90
- $h2_forum = $topic_query->get( 'forum_id' );
91
- $h2_tag = $topic_query->get( 'tag_id' );
92
- $h2_author = $topic_query->get( 'topic_author_id' );
93
-
94
- $h2_search = $h2_search ? ' ' . sprintf( __('containing &#8220;%s&#8221;'), esc_html( $h2_search ) ) : '';
95
- $h2_forum = $h2_forum ? ' ' . sprintf( __('in &#8220;%s&#8221;') , get_forum_name( $h2_forum ) ) : '';
96
- $h2_tag = $h2_tag ? ' ' . sprintf( __('with tag &#8220;%s&#8221;'), esc_html( bb_get_tag_name( $h2_tag ) ) ) : '';
97
- $h2_author = $h2_author ? ' ' . sprintf( __('by %s') , esc_html( get_user_name( $h2_author ) ) ) : '';
98
-
99
- if ( $h2_search || $h2_forum || $h2_tag || $h2_author ) {
100
- echo '<span class="subtitle">';
101
-
102
- printf( __( '%1$s%2$s%3$s%4$s' ), $h2_search, $h2_forum, $h2_tag, $h2_author );
103
-
104
- echo '</span>';
105
- }
106
- ?>
107
- </h2>
108
- <?php do_action( 'bb_admin_notices' ); ?>
109
-
110
- <?php $topic_query->form( array('tag' => true, 'topic_author' => true, 'topic_status' => true, 'open' => true, 'submit' => __('Filter')) ); ?>
111
-
112
- <div class="clear"></div>
113
-
114
- <?php if ( !$topics ) : ?>
115
-
116
- <p class="no-results"><?php _e('No topics found.'); ?></p>
117
-
118
- <?php
119
-
120
- else :
121
- bb_cache_first_posts( $topics ); bb_cache_last_posts( $topics );
122
-
123
- $bulk_actions = array(
124
- 'delete' => __( 'Delete' ),
125
- 'undelete' => __( 'Undelete' ),
126
- 'open' => __( 'Open' ),
127
- 'close' => __( 'Close' ),
128
- );
129
-
130
- if ( is_numeric( $bulk_action = $topic_query->get( 'topic_status' ) ) )
131
- unset( $bulk_actions[ $bulk_action ? 'delete' : 'undelete' ] );
132
-
133
-
134
- if ( is_numeric( $bulk_action = $topic_query->get( 'open' ) ) )
135
- unset( $bulk_actions[ $bulk_action ? 'open' : 'close' ] );
136
-
137
- unset( $bulk_action );
138
-
139
- do_action_ref_array( 'bulk_topic_actions', array( &$bulk_actions, $topic_query ) );
140
- ?>
141
-
142
- <form class="table-form bulk-form" method="post" action="">
143
- <fieldset>
144
- <select name="action">
145
- <option><?php _e( 'Bulk Actions' ); ?></option>
146
- <?php foreach ( $bulk_actions as $value => $label ) : ?>
147
-
148
- <option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $label ); ?></option>
149
- <?php endforeach; ?>
150
- </select>
151
- <input type="submit" value="<?php esc_attr_e( 'Apply' ); ?>" class="button submit-input" />
152
- <?php bb_nonce_field( 'topic-bulk' ); ?>
153
- </fieldset>
154
-
155
- <div class="tablenav">
156
- <?php if ( $topic_query->found_rows ) : ?>
157
- <div class="tablenav-pages">
158
- <span class="displaying-num"><?php echo $displaying_num = sprintf(
159
- __( '%1$s to %2$s of %3$s' ),
160
- bb_number_format_i18n( ( $page - 1 ) * $topic_query->get( 'per_page' ) + 1 ),
161
- $page * $topic_query->get( 'per_page' ) < $topic_query->found_rows ? bb_number_format_i18n( $page * $topic_query->get( 'per_page' ) ) : '<span class="total-type-count">' . bb_number_format_i18n( $topic_query->found_rows ) . '</span>',
162
- '<span class="total-type-count">' . bb_number_format_i18n( $topic_query->found_rows ) . '</span>'
163
- ); ?></span><span class="displaying-pages">
164
- <?php
165
- $_page_link_args = array(
166
- 'page' => $page,
167
- 'total' => $topic_query->found_rows,
168
- 'per_page' => $topic_query->get( 'per_page' ),
169
- 'mod_rewrite' => false,
170
- 'prev_text' => __( '&laquo;' ),
171
- 'next_text' => __( '&raquo;' )
172
- );
173
- echo $page_number_links = get_page_number_links( $_page_link_args );
174
- ?></span>
175
- <div class="clear"></div>
176
- </div>
177
- <?php endif; ?>
178
- </div>
179
-
180
- <div class="clear"></div>
181
-
182
- <table id="topics-list" class="widefat">
183
- <thead>
184
- <tr>
185
- <th scope="col" class="check-column"><input type="checkbox" /></th>
186
- <th scope="col"><?php _e('Topic') ?></th>
187
- <th scope="col"><?php _e('Author') ?></th>
188
- <th scope="col"><?php _e('Posts') ?></th>
189
- <th scope="col"><?php _e('Date') ?></th>
190
- <th scope="col"><?php _e('Freshness') ?></th>
191
- </tr>
192
- </thead>
193
- <tfoot>
194
- <tr>
195
- <th scope="col" class="check-column"><input type="checkbox" /></th>
196
- <th scope="col"><?php _e('Topic') ?></th>
197
- <th scope="col"><?php _e('Author') ?></th>
198
- <th scope="col"><?php _e('Posts') ?></th>
199
- <th scope="col"><?php _e('Date') ?></th>
200
- <th scope="col"><?php _e('Freshness') ?></th>
201
- </tr>
202
- </thead>
203
-
204
- <tbody>
205
- <?php foreach ( $topics as $topic ) : $first_post = bb_get_first_post( $topic ); ?>
206
- <tr id="topic-<?php echo $topic->topic_id; ?>"<?php topic_class(); ?>>
207
- <td class="check-column"><input type="checkbox" name="topic[]" value="<?php echo $topic->topic_id; ?>" /></td>
208
- <td class="topic">
209
- <span class="row-title"><?php bb_topic_labels(); ?> <a href="<?php topic_link(); ?>"><?php topic_title(); ?></a></span>
210
- <div>
211
- <span class="row-actions">
212
- <a href="<?php topic_link(); ?>"><?php _e( 'View' ); ?></a> |
213
- <?php if ( $first_post ) : post_edit_link( $first_post->post_id ); ?> |
214
- <?php endif; topic_close_link( array( 'id' => $topic->topic_id, 'before' => '', 'after' => '', 'close_text' => __( 'Close' ), 'open_text' => _x( 'Open', 'action' ) ) ); ?> |
215
- <?php topic_delete_link( array( 'id' => $topic->topic_id, 'before' => '', 'after' => '', 'delete_text' => __( 'Delete' ), 'undelete_text' => __( 'Undelete' ) ) ); ?>
216
- </span>&nbsp;
217
- </div>
218
- </td>
219
- <td class="author">
220
- <a class="author-link" href="<?php user_profile_link( $topic->topic_poster ); ?>">
221
- <?php echo bb_get_avatar( $topic->topic_poster, '16' ); ?>
222
- <?php topic_author(); ?>
223
- </a>
224
- </td>
225
- <td class="posts num"><?php topic_posts(); ?></td>
226
- <td class="date num">
227
- <?php
228
- if ( get_topic_start_time( 'U' ) < ( time() - 86400 ) ) {
229
- topic_start_time( 'Y/m/d\<\b\r \/\>H:i:s' );
230
- } else {
231
- printf( __( '%s ago' ), get_topic_start_time( 'since' ) );
232
- }
233
- ?>
234
- </td>
235
- <td class="freshness num"><a href="<?php topic_last_post_link(); ?>" title="<?php echo esc_attr( sprintf( __( 'Last post by %s' ), get_topic_last_poster() ) ); ?>">
236
- <?php
237
- if ( get_topic_time( 'U' ) < ( time() - 86400 ) ) {
238
- topic_time( 'Y/m/d\<\b\r \/\>H:i:s' );
239
- } else {
240
- printf( __( '%s ago' ), get_topic_time( 'since' ) );
241
- }
242
- ?>
243
-
244
- <?php //topic_time( bb_get_datetime_formatstring_i18n() ); ?>
245
-
246
-
247
- </a></td>
248
- </tr>
249
- <?php endforeach; ?>
250
- </tbody>
251
- </table>
252
- </form>
253
- <?php endif; ?>
254
-
255
- <div class="tablenav bottom">
256
- <?php if ( $topic_query->found_rows ) : ?>
257
- <div class="tablenav-pages">
258
- <span class="displaying-pages"><?php echo $page_number_links; ?></span>
259
- <div class="clear"></div>
260
- </div>
261
- <?php endif; ?>
262
- </div>
263
- <div class="clear"></div>
264
-
265
- </div>
266
-
267
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/upgrade.php DELETED
@@ -1,210 +0,0 @@
1
- <?php
2
- // Remove these lines if you want to upgrade and are using safe mode
3
- if ( ini_get('safe_mode') )
4
- die("You're running in safe mode which does not allow this upgrade
5
- script to set a running time limit. Depending on the size of your
6
- database and on which parts of the script you are running, the script
7
- can take quite some time to run (or it could take just a few seconds).
8
- To throw caution to the wind and run the script in safe mode anyway,
9
- remove the first few lines of code in the <code>bb-admin/upgrade.php</code>
10
- file. Backups are always a good idea.");
11
- // Stop removing lines
12
-
13
- // Very old (pre 0.7) installs may need further upgrade utilities.
14
- // Post to http://lists.bbpress.org/mailman/listinfo/bbdev if needed
15
-
16
- require('../bb-load.php');
17
- require( BB_PATH . 'bb-admin/includes/functions.bb-upgrade.php' );
18
-
19
- $step = 'unrequired';
20
-
21
- $forced = false;
22
- if ( isset( $_POST['force'] ) && 1 == $_POST['force'] ) {
23
- $forced = true;
24
- } elseif ( isset( $_GET['force'] ) && 1 == $_GET['force'] ) {
25
- $forced = true;
26
- }
27
-
28
- if ( bb_get_option( 'bb_db_version' ) > bb_get_option_from_db( 'bb_db_version' ) || $forced ) {
29
-
30
- $forced_input = '';
31
- if ( $forced ) {
32
- $forced_input = '<input type="hidden" name="force" value="1" />';
33
- }
34
-
35
- $step = 'required';
36
-
37
- if ( strtolower( $_SERVER['REQUEST_METHOD']) == 'post' ) {
38
-
39
- bb_check_admin_referer( 'bbpress-upgrader' );
40
-
41
- define('BB_UPGRADING', true);
42
-
43
- $bbdb->hide_errors();
44
-
45
- $messages = bb_upgrade_all();
46
-
47
- $bbdb->show_errors();
48
-
49
- $upgrade_log = array(__('Beginning upgrade&hellip;'));
50
- if (is_array($messages['messages'])) {
51
- $upgrade_log = array_merge($upgrade_log, $messages['messages']);
52
- }
53
- $upgrade_log[] = '>>> ' . __('Done');
54
-
55
- $error_log = array();
56
- if (is_array($messages['errors'])) {
57
- $error_log = $messages['errors'];
58
- }
59
-
60
- if ( bb_get_option( 'bb_db_version' ) === bb_get_option_from_db( 'bb_db_version' ) && !count($error_log) ) {
61
- $step = 'complete';
62
- } else {
63
- $step = 'error';
64
- }
65
-
66
- wp_cache_flush();
67
- }
68
-
69
- }
70
-
71
- bb_install_header( __('bbPress database upgrade'), false, true );
72
- ?>
73
- <script type="text/javascript" charset="utf-8">
74
- function toggleAdvanced(toggle, target) {
75
- var toggleObj = document.getElementById(toggle);
76
- var targetObj = document.getElementById(target);
77
- if (toggleObj.checked) {
78
- targetObj.style.display = 'block';
79
- } else {
80
- targetObj.style.display = 'none';
81
- }
82
- }
83
- </script>
84
- <?php
85
- switch ($step) {
86
- case 'unrequired':
87
- ?>
88
- <p class="last">
89
- <?php printf( __('Nothing to upgrade. <a href="%s">Get back to work!</a>'), bb_get_uri('bb-admin/', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN) ); ?>
90
- </p>
91
- <?php
92
- break;
93
-
94
- case 'required'
95
- ?>
96
- <div class="open">
97
- <h2><?php _e('Database upgrade required'); ?></h2>
98
- <div>
99
- <form action="<?php bb_uri('bb-admin/upgrade.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>" method="post">
100
- <p class="error">
101
- <?php _e('It looks like your database is out-of-date. You can upgrade it here.'); ?>
102
- </p>
103
- <fieldset class="buttons">
104
- <?php bb_nonce_field( 'bbpress-upgrader' ); ?>
105
- <?php echo $forced_input; ?>
106
- <label for="upgrade_next" class="forward">
107
- <input class="button" id="upgrade_next" type="submit" value="<?php _e( 'Upgrade database' ); ?>" />
108
- </label>
109
- </fieldset>
110
- </form>
111
- </div>
112
- </div>
113
- <?php
114
- break;
115
-
116
- case 'complete':
117
- ?>
118
- <div class="open">
119
- <h2><?php _e('Database upgrade complete'); ?></h2>
120
- <div>
121
- <form action="<?php bb_uri('bb-admin/', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>" method="get">
122
- <p class="message">
123
- <?php _e('Your database has been successfully upgraded, enjoy!'); ?>
124
- </p>
125
- <fieldset>
126
- <label class="has-label for-toggle" for="upgrade_log_container_toggle">
127
- <span>
128
- <?php _e('Show upgrade messages'); ?>
129
- <input class="checkbox" type="checkbox" id="upgrade_log_container_toggle" value="1" onclick="toggleAdvanced('upgrade_log_container_toggle', 'upgrade_log_container');" />
130
- </span>
131
- <div class="clear"></div>
132
- </label>
133
- </fieldset>
134
- <div class="toggle" id="upgrade_log_container" style="display:none;">
135
- <fieldset>
136
- <label class="has-label for-textarea" for="upgrade_log">
137
- <span><?php _e('Upgrade log'); ?></span>
138
- <textarea id="upgrade_log" class="short"><?php echo(join("\n", $upgrade_log)); ?></textarea>
139
- </label>
140
- </fieldset>
141
- </div>
142
- <fieldset class="buttons">
143
- <label for="upgrade_next" class="back">
144
- <input class="button" id="upgrade_back" type="button" value="<?php _e( '&laquo; Go back to forums' ); ?>" onclick="location.href='<?php echo esc_js( bb_get_uri() ); ?>'; return false;" />
145
- </label>
146
- <label for="upgrade_next" class="forward">
147
- <input class="button" id="upgrade_next" type="submit" value="<?php _e( 'Go to admin' ); ?>" />
148
- </label>
149
- </fieldset>
150
- </form>
151
- </div>
152
- </div>
153
- <?php
154
- break;
155
-
156
- case 'error':
157
- ?>
158
- <div class="open">
159
- <h2><?php _e('Database upgrade failed'); ?></h2>
160
- <div>
161
- <form action="<?php bb_uri('bb-admin/upgrade.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>" method="post">
162
- <p class="error">
163
- <?php _e('The upgrade process seems to have failed. Check the upgrade messages below for more information.<br /><br />Attempting to go to the admin area without resolving the listed errors will return you to this upgrade page.'); ?>
164
- </p>
165
- <fieldset>
166
- <?php bb_nonce_field( 'bbpress-upgrader' ); ?>
167
- <?php echo $forced_input; ?>
168
- <label class="has-label for-toggle" for="upgrade_log_container_toggle" style="margin-bottom: 1.9em;">
169
- <span>
170
- <?php _e('Show upgrade messages'); ?>
171
- <input class="checkbox" type="checkbox" id="upgrade_log_container_toggle" value="1" onclick="toggleAdvanced('upgrade_log_container_toggle', 'upgrade_log_container');" />
172
- </span>
173
- <div class="clear"></div>
174
- </label>
175
- </fieldset>
176
- <div class="toggle" id="upgrade_log_container" style="display:none;">
177
- <fieldset>
178
- <?php
179
- if (count($error_log)) {
180
- ?>
181
- <label class="has-label for-textarea" for="error_log">
182
- <span><?php _e('Error log'); ?></span>
183
- <textarea id="error_log" class="short"><?php echo(join("\n", $error_log)); ?></textarea>
184
- </label>
185
- <?php
186
- }
187
- ?>
188
- <label class="has-label for-textarea" for="upgrade_log">
189
- <span><?php _e('Upgrade log'); ?></span>
190
- <textarea id="upgrade_log" class="short"><?php echo(join("\n", $upgrade_log)); ?></textarea>
191
- </label>
192
- </fieldset>
193
- </div>
194
- <fieldset class="buttons">
195
- <label for="upgrade_next" class="back">
196
- <input class="button" id="upgrade_back" type="button" value="<?php _e( '&laquo; Go back to forums' ); ?>" onclick="location.href='<?php echo esc_js( bb_get_uri() ); ?>'; return false;" />
197
- </label>
198
- <label for="upgrade_next" class="forward">
199
- <input class="button" id="upgrade_next" type="submit" value="<?php _e( 'Try again' ); ?>" />
200
- </label>
201
- </fieldset>
202
- </form>
203
- </div>
204
- </div>
205
- <?php
206
- break;
207
- }
208
-
209
- bb_install_footer();
210
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/user-add-new.php DELETED
@@ -1,49 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- $edit_user = bb_get_user( bb_get_user_id( $_GET['user_id'] ) );
5
- $user_fields = bb_manage_user_fields( $edit_user );
6
-
7
- // Let it rip!
8
-
9
- // Header
10
- $bb_admin_body_class = 'bb-admin-user-manage';
11
- bb_get_admin_header();
12
-
13
- ?>
14
-
15
- <div class="wrap">
16
- <h2><?php _e( 'Add a new user' ); ?></h2>
17
-
18
- <?php do_action( 'bb_admin_notices' ); ?>
19
-
20
- <form class="settings" method="post" action="">
21
- <fieldset>
22
- <?php
23
- foreach ( $user_fields as $field => $args ) {
24
- bb_option_form_element( $field, $args );
25
- }
26
- ?>
27
- <noscript>
28
- <?php _e( 'Disabled (requires JavaScript)' ); ?>
29
- </noscript>
30
- <script type="text/javascript" charset="utf-8">
31
- if (typeof jQuery != 'undefined') {
32
- jQuery('#user-login').attr( 'id', 'user_login' );
33
- var meter = ('<div id="pass-strength-result">' + pwsL10n.short + '</div>');
34
- jQuery('#option-pass-strength-fake-input div.inputs input').before( meter );
35
- } else {
36
- document.writeln('<?php echo str_replace( "'", "\'", __( 'Disabled.' ) ); ?>')
37
- }
38
- </script>
39
- </fieldset>
40
- <fieldset class="submit">
41
- <?php bb_nonce_field( 'user-manage' ); ?>
42
-
43
- <input type="hidden" name="action" value="create" />
44
- <input class="submit" type="submit" name="submit" value="<?php _e( 'Create user' ); ?>" />
45
- </fieldset>
46
- </form>
47
- </div>
48
-
49
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-admin/users.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
- require_once('admin.php');
3
-
4
- // Get all errors and print as notice
5
- if ( isset( $_GET['created'] ) )
6
- bb_admin_notice( __( '<strong>User Created.</strong>' ) );
7
-
8
- if ( isset( $_GET['updated'] ) )
9
- bb_admin_notice( __( '<strong>User Updated.</strong>' ) );
10
-
11
- if ( isset( $_GET['action'] ) || isset( $_GET['user_id'] ) && ( 'edit' == $_GET['action'] || 'create' == $_GET['action'] ) ) {
12
-
13
- $edit_user = bb_get_user( bb_get_user_id( $_GET['user_id'] ) );
14
- $user_fields = bb_manage_user_fields( $edit_user );
15
-
16
- $bb_admin_body_class = 'bb-admin-user-manage';
17
- bb_get_admin_header(); ?>
18
-
19
- <div class="wrap">
20
- <h2><?php _e( 'Edit user' ); ?></h2>
21
-
22
- <?php do_action( 'bb_admin_notices' ); ?>
23
-
24
- <form class="settings" method="post" action="">
25
- <fieldset>
26
- <?php
27
- foreach ( $user_fields as $field => $args ) {
28
- bb_option_form_element( $field, $args );
29
- }
30
- ?>
31
- <noscript>
32
- <?php _e( 'Disabled (requires JavaScript)' ); ?>
33
- </noscript>
34
- <script type="text/javascript" charset="utf-8">
35
- if (typeof jQuery != 'undefined') {
36
- jQuery('#user-login').attr( 'id', 'user_login' );
37
- var meter = ('<div id="pass-strength-result">' + pwsL10n.short + '</div>');
38
- jQuery('#option-pass-strength-fake-input div.inputs input').before( meter );
39
- } else {
40
- document.writeln('<?php echo str_replace( "'", "\'", __( 'Disabled.' ) ); ?>')
41
- }
42
- </script>
43
- </fieldset>
44
- <fieldset class="submit">
45
- <?php bb_nonce_field( 'user-manage' ); ?>
46
-
47
- <input type="hidden" name="action" value="update" />
48
- <input class="submit" type="submit" name="submit" value="<?php _e( 'Update user' ); ?>" />
49
- </fieldset>
50
- </form>
51
- </div>
52
-
53
- <?php } else {
54
- // Query the users
55
- $bb_user_search = new BB_User_Search( @$_GET['usersearch'], @$_GET['page'], @$_GET['userrole'] );
56
-
57
- $bb_admin_body_class = ' bb-admin-users';
58
- bb_get_admin_header(); ?>
59
-
60
- <div class="wrap">
61
-
62
- <?php $bb_user_search->display( true, bb_current_user_can( 'edit_users' ) ); ?>
63
-
64
- </div>
65
-
66
- <?php } ?>
67
-
68
- <?php bb_get_admin_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-config-sample.php DELETED
@@ -1,63 +0,0 @@
1
- <?php
2
- /**
3
- * The base configurations of bbPress.
4
- *
5
- * This file has the following configurations: MySQL settings, Table Prefix,
6
- * Secret Keys and bbPress Language. You can get the MySQL settings from your
7
- * web host.
8
- *
9
- * This file is used by the installer during installation.
10
- *
11
- * @package bbPress
12
- */
13
-
14
- // ** MySQL settings - You can get this info from your web host ** //
15
- /** The name of the database for bbPress */
16
- define( 'BBDB_NAME', 'bbpress' );
17
-
18
- /** MySQL database username */
19
- define( 'BBDB_USER', 'username' );
20
-
21
- /** MySQL database password */
22
- define( 'BBDB_PASSWORD', 'password' );
23
-
24
- /** MySQL hostname */
25
- define( 'BBDB_HOST', 'localhost' );
26
-
27
- /** Database Charset to use in creating database tables. */
28
- define( 'BBDB_CHARSET', 'utf8' );
29
-
30
- /** The Database Collate type. Don't change this if in doubt. */
31
- define( 'BBDB_COLLATE', '' );
32
-
33
- /**#@+
34
- * Authentication Unique Keys.
35
- *
36
- * Change these to different unique phrases!
37
- * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/bbpress/ WordPress.org secret-key service}
38
- *
39
- * @since 1.0
40
- */
41
- define( 'BB_AUTH_KEY', 'put your unique phrase here' );
42
- define( 'BB_SECURE_AUTH_KEY', 'put your unique phrase here' );
43
- define( 'BB_LOGGED_IN_KEY', 'put your unique phrase here' );
44
- define( 'BB_NONCE_KEY', 'put your unique phrase here' );
45
- /**#@-*/
46
-
47
- /**
48
- * bbPress Database Table prefix.
49
- *
50
- * You can have multiple installations in one database if you give each a unique
51
- * prefix. Only numbers, letters, and underscores please!
52
- */
53
- $bb_table_prefix = 'bb_';
54
-
55
- /**
56
- * bbPress Localized Language, defaults to English.
57
- *
58
- * Change this to localize bbPress. A corresponding MO file for the chosen
59
- * language must be installed to a directory called "my-languages" in the root
60
- * directory of bbPress. For example, install de.mo to "my-languages" and set
61
- * BB_LANG to 'de' to enable German language support.
62
- */
63
- define( 'BB_LANG', '' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-cron.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
- /**
3
- * bbPress Cron Implementation for hosts, which do not offer CRON or for which
4
- * the user has not setup a CRON job pointing to this file.
5
- *
6
- * The HTTP request to this file will not slow down the visitor who happens to
7
- * visit when the cron job is needed to run.
8
- *
9
- * @package bbPress
10
- */
11
-
12
- ignore_user_abort( true );
13
-
14
- if ( !empty( $_POST ) || defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) ) {
15
- die();
16
- }
17
-
18
- /**
19
- * Tell bbPress we are doing the CRON task.
20
- *
21
- * @var bool
22
- */
23
- define( 'DOING_CRON', true );
24
-
25
- /** Setup bbPress environment */
26
- require_once( './bb-load.php' );
27
-
28
- if ( false === $crons = _get_cron_array() ) {
29
- die();
30
- }
31
-
32
- $keys = array_keys( $crons );
33
- $local_time = time();
34
-
35
- if ( !is_array( $crons ) || ( isset($keys[0]) && $keys[0] > $local_time ) ) {
36
- die();
37
- }
38
-
39
- foreach ( $crons as $timestamp => $cronhooks ) {
40
- if ( $timestamp > $local_time ) {
41
- break;
42
- }
43
- foreach ( $cronhooks as $hook => $keys ) {
44
- foreach ( $keys as $key => $args ) {
45
- $schedule = $args['schedule'];
46
- if ( $schedule != false ) {
47
- $new_args = array( $timestamp, $schedule, $hook, $args['args'] );
48
- call_user_func_array( 'wp_reschedule_event' , $new_args );
49
- }
50
- wp_unschedule_event( $timestamp, $hook, $args['args'] );
51
- do_action_ref_array( $hook, $args['args'] );
52
- }
53
- }
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-edit.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
- require('./bb-load.php');
3
-
4
- bb_auth('logged_in');
5
-
6
- $post_id = (int) $_POST['post_id'];
7
-
8
- $bb_post = bb_get_post( $post_id );
9
-
10
- if ( !$bb_post ) {
11
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
12
- die();
13
- }
14
-
15
- if ( !bb_current_user_can( 'edit_post', $post_id ) )
16
- bb_die(__('Sorry, post is too old.'));
17
-
18
- bb_check_admin_referer( 'edit-post_' . $post_id );
19
-
20
- if ( 0 != $bb_post->post_status && 'all' == $_GET['view'] ) // We're trying to edit a deleted post
21
- add_filter('bb_is_first_where', 'bb_no_where');
22
-
23
- // Check possible anonymous user data
24
- $post_author = $post_email = $post_url = '';
25
-
26
- if ( !bb_get_user( get_post_author_id( $post_id ) ) ) {
27
- if ( !$post_author = sanitize_user( trim( $_POST['author'] ) ) )
28
- bb_die( __( 'Every post needs an author name!' ) );
29
- elseif ( !$post_email = sanitize_email( trim( $_POST['email'] ) ) )
30
- bb_die( __( 'Every post needs a valid email address!' ) );
31
-
32
- if ( !empty( $_POST['url'] ) )
33
- $post_url = esc_url( trim( $_POST['url'] ) );
34
- }
35
-
36
- // Loop through possible anonymous post data
37
- foreach( array('post_author', 'post_email', 'post_url') as $field ) {
38
- if ( ! empty( $$field ) ) {
39
- $post_data[$field] = $$field;
40
- }
41
- }
42
-
43
- // Setup topic data
44
- if ( bb_is_first( $bb_post->post_id ) && bb_current_user_can( 'edit_topic', $bb_post->topic_id ) ) {
45
-
46
- $post_data['topic_title'] = stripslashes( $_POST['topic'] );
47
- $post_data['topic_id'] = $bb_post->topic_id;
48
-
49
- bb_insert_topic( $post_data );
50
- }
51
-
52
- // Setup post data
53
- $post_data['post_text'] = stripslashes( $_POST['post_content'] );
54
- $post_data['post_id'] = $post_id;
55
-
56
- bb_insert_post( $post_data );
57
-
58
- if ( $post_id ) {
59
- if ( $_REQUEST['view'] === 'all' ) {
60
- add_filter( 'get_post_link', 'bb_make_link_view_all' );
61
- }
62
- $post_link = get_post_link( $post_id );
63
- wp_redirect( $post_link );
64
- } else {
65
- wp_redirect( bb_get_uri(null, null, BB_URI_CONTEXT_HEADER) );
66
- }
67
- exit;
68
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/action.subscribe.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
-
3
- if ( !isset( $_GET['doit'] ) || 'bb-subscribe' != $_GET['doit'] ) // sanity check
4
- bb_die( __( 'What are you trying to do, exactly?' ) );
5
-
6
- if ( !bb_is_subscriptions_active() )
7
- bb_die( __( 'You can not subscribe to topics.' ) );
8
-
9
- if ( !isset( $_GET['topic_id'] ) )
10
- bb_die( __( 'Missing topic ID!' ) );
11
-
12
- bb_auth( 'logged_in' );
13
-
14
- $topic_id = (int) $_GET['topic_id'];
15
-
16
- $topic = get_topic( $topic_id );
17
- if ( !$topic )
18
- bb_die( __( 'Topic not found! What are you subscribing to?' ) );
19
-
20
- bb_check_admin_referer( 'toggle-subscribe_' . $topic_id );
21
-
22
- // Okay, we should be covered now
23
-
24
- if ( in_array( $_GET['and'], array( 'add', 'remove' ) ) )
25
- bb_subscription_management( $topic->topic_id, $_GET['and'] );
26
-
27
- wp_redirect( get_topic_link( $topic_id, 1 ) );
28
-
29
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.bp-log.php DELETED
@@ -1,550 +0,0 @@
1
- <?php
2
-
3
-
4
- /**
5
- * BackPress logging level constants
6
- */
7
- define('BP_LOG_NONE', 0);
8
- define('BP_LOG_FAIL', 1);
9
- define('BP_LOG_ERROR', 2);
10
- define('BP_LOG_WARNING', 4);
11
- define('BP_LOG_NOTICE', 8);
12
- define('BP_LOG_DEBUG', 16);
13
-
14
- /**
15
- * Combination of all errors (excluding none and debug)
16
- */
17
- define('BP_LOG_ALL', BP_LOG_FAIL + BP_LOG_ERROR + BP_LOG_WARNING + BP_LOG_NOTICE);
18
-
19
-
20
-
21
- /**
22
- * Provides easy and abstracted logging facilities
23
- *
24
- * @package BackPress
25
- */
26
- class BP_Log
27
- {
28
- /**
29
- * The logging level
30
- *
31
- * @var integer
32
- */
33
- var $level = BP_LOG_NONE;
34
-
35
- /**
36
- * The type of logging
37
- *
38
- * @var string
39
- */
40
- var $type = 'php';
41
-
42
- /**
43
- * The types of logging available
44
- *
45
- * @var array
46
- */
47
- var $types = array('php', 'file', 'display', 'console');
48
-
49
- /**
50
- * The filename of the file to log messages to when type is "file"
51
- *
52
- * @var string
53
- */
54
- var $filename = '';
55
-
56
- /**
57
- * Whether or not the javascript functions are available
58
- *
59
- * @var boolean
60
- **/
61
- var $console_javascript_loaded = false;
62
-
63
- /**
64
- * Console log messages which are queued up to be displayed on page load
65
- *
66
- * @var array
67
- **/
68
- var $console_javascript_onloads = array();
69
-
70
- /**
71
- * Initialises the logging
72
- *
73
- * @return void
74
- */
75
- function BP_log($level = false, $type = false, $filename = false)
76
- {
77
- $this->set_level($level);
78
- $this->set_type($type);
79
- $this->set_filename($filename);
80
- }
81
-
82
- /**
83
- * Sets the logging level
84
- *
85
- * @return integer|boolean The old level on success or false
86
- * @uses BP_LOG_LEVEL
87
- */
88
- function set_level($level)
89
- {
90
- $old_level = $this->level;
91
-
92
- if (is_integer($level)) {
93
- $this->level = $level;
94
- } elseif (defined('BP_LOG_LEVEL') && is_integer(BP_LOG_LEVEL)) {
95
- $this->level = BP_LOG_LEVEL;
96
- } else {
97
- return false;
98
- }
99
-
100
- return $old_level;
101
- }
102
-
103
- /**
104
- * Sets the logging type
105
- *
106
- * @return string|false The old type on success or false
107
- * @uses BP_LOG_TYPE
108
- */
109
- function set_type($type)
110
- {
111
- $old_type = $this->type;
112
- $type = strtolower($type);
113
-
114
- if (in_array($type, $this->types)) {
115
- $this->type = $type;
116
- } elseif (defined('BP_LOG_TYPE') && in_array(BP_LOG_TYPE, $this->types)) {
117
- $this->type = BP_LOG_TYPE;
118
- } else {
119
- return false;
120
- }
121
-
122
- return $old_type;
123
- }
124
-
125
- /**
126
- * Sets the logging filename
127
- *
128
- * @return string|boolean The old filename on success or false
129
- * @uses BP_LOG_FILENAME
130
- */
131
- function set_filename($filename)
132
- {
133
- $old_filename = $this->filename;
134
-
135
- if (is_string($filename)) {
136
- $_filename = $filename;
137
- } elseif (defined('BP_LOG_FILENAME') && is_string(BP_LOG_FILENAME)) {
138
- $_filename = BP_LOG_FILENAME;
139
- } else {
140
- return false;
141
- }
142
-
143
- if (isset($_filename) && file_exists($_filename) && is_file($_filename) && is_writable($_filename)) {
144
- $this->filename = $_filename;
145
- } else {
146
- return false;
147
- }
148
-
149
- return $old_filename;
150
- }
151
-
152
- /**
153
- * Sends a message to the log
154
- *
155
- * @return boolean True on success, false on failure
156
- */
157
- function send($message = '', $level = BP_LOG_DEBUG, $type = false, $prefix = false)
158
- {
159
- // Make sure the level of this message is set to be logged
160
- if (($level & $this->level) === 0) {
161
- return;
162
- }
163
-
164
- // Format the message into an array of lines to be logged
165
- $lines = $this->format_message($message, $level, $prefix);
166
-
167
- // Do some validation on the type
168
- if ($type && in_array($type, $this->types)) {
169
- $_type = $type;
170
- } else {
171
- $_type = $this->type;
172
- }
173
-
174
- // Get a name for the level
175
- if ($level) {
176
- $_level = $this->get_level_from_integer($level);
177
- }
178
-
179
- // Setup strings to prepend to some of the types
180
- $prepend = $_level . ': ';
181
- if ($prefix) {
182
- $prepend .= $prefix . ': ';
183
- }
184
- $pad = str_repeat(' ', strlen($prepend) - 2) . '| ';
185
-
186
- // Switch over the four types
187
- switch ($_type) {
188
- case 'php':
189
- $php_fail = false;
190
-
191
- // Check that the error_log() function is available
192
- if (function_exists('error_log') && is_callable('error_log')) {
193
- foreach ($lines as $key => $line) {
194
- if ($key === 0) {
195
- $_prepend = $prepend;
196
- } else {
197
- $_prepend = $pad;
198
- }
199
- if (!error_log($_prepend . $line, 0)) {
200
- $php_fail = true;
201
- break;
202
- }
203
- }
204
- } else {
205
- $php_fail = true;
206
- }
207
-
208
- if ($php_fail) {
209
- // The PHP error log process failed, path of least resistance is to write to display
210
- $this->send($message, $level, 'display', $prefix);
211
- return;
212
- }
213
- break;
214
-
215
- case 'file':
216
- $file_fail = false;
217
-
218
- // We've already done the prerequisite checks on the file by now so just write to it
219
- if (!$file_handle = fopen($this->filename, 'a')) {
220
- $file_fail = true;
221
- } else {
222
- // Prepare a string to write
223
- $_lines = array(
224
- '[' . date('c') . ']',
225
- '[client ' . $_SERVER['REMOTE_ADDR'] . ']',
226
- $prepend,
227
- join("\n", $lines)
228
- );
229
- }
230
- if (fwrite($file_handle, join(' ', $_lines) . "\n") === false) {
231
- $file_fail = true;
232
- }
233
- if ($file_handle) {
234
- fclose($file_handle);
235
- }
236
- if ($file_fail) {
237
- // Writing to file failed, output to display
238
- $this->send($message, $level, 'display', $prefix);
239
- return;
240
- }
241
- break;
242
-
243
- case 'display':
244
- $_lines = array();
245
- foreach ($lines as $key => $line) {
246
- if ($key === 0) {
247
- $_lines[] = $prepend . $line;
248
- } else {
249
- $_lines[] = $pad . $line;
250
- }
251
- }
252
- echo '<div class="bplog_message bplog_level_' . strtolower($_level) . '"><pre>' . join("\n", $_lines) . '</pre></div>' . "\n";
253
- break;
254
-
255
- case 'console':
256
- $_lines = array();
257
- foreach ($lines as $key => $line) {
258
- if ($key === 0 && $prefix) {
259
- $_lines[] = $prefix . ': ' . $line;
260
- } else {
261
- $_lines[] = $line;
262
- }
263
- }
264
-
265
- $_lines = $ident . $_level . ' ~\n' . str_replace('\'', '\\\'', join('\n', $_lines));
266
-
267
- if (!$this->console_javascript_loaded) {
268
- // Queue it for logging onload
269
- $this->console_javascript_onloads[] = array('message' => $_lines, 'level' => $level, 'time' => date('c'));
270
- } else {
271
- // Log it now
272
- echo '<script type="text/javascript" charset="utf-8">bp_log_add(\'' . $this->_esc_js_log( $_lines ) . '\', ' . $this->_esc_js_log( $level ) . ', \'' . $this->_esc_js_log( date('c') ) . '\');</script>' . "\n";
273
- }
274
- break;
275
- }
276
-
277
- return true;
278
- }
279
-
280
- /**
281
- * Gets the name of the log level from an integer
282
- *
283
- * @return string The logging level
284
- */
285
- function get_level_from_integer($integer)
286
- {
287
- switch ($integer) {
288
- case BP_LOG_NONE:
289
- return 'BP_LOG_NONE';
290
- break;
291
- case BP_LOG_FAIL:
292
- return 'BP_LOG_FAIL';
293
- break;
294
- case BP_LOG_ERROR:
295
- return 'BP_LOG_ERROR';
296
- break;
297
- case BP_LOG_WARNING:
298
- return 'BP_LOG_WARNING';
299
- break;
300
- case BP_LOG_NOTICE:
301
- return 'BP_LOG_NOTICE';
302
- break;
303
- case BP_LOG_DEBUG:
304
- return 'BP_LOG_DEBUG';
305
- break;
306
- default:
307
- return 'BP_LOG_UNDEFINED';
308
- break;
309
- }
310
- }
311
-
312
- /**
313
- * Formats a message for output to a log file
314
- *
315
- * @return boolean True on success, false on failure
316
- */
317
- function format_message($message, $level = BP_LOG_DEBUG, $prefix = false, $tabs = 0)
318
- {
319
- $lines = array();
320
-
321
- if (is_null($message)) {
322
- $lines[] = 'null (' . var_export($message, true) . ')';
323
- return $lines;
324
- }
325
-
326
- if (is_bool($message)) {
327
- $lines[] = 'bool (' . var_export($message, true) . ')';
328
- return $lines;
329
- }
330
-
331
- if (is_string($message)) {
332
- if ($level === BP_LOG_DEBUG || $message === '') {
333
- $lines[] = 'string(' . strlen($message) . ') ("' . $message . '")';
334
- } else {
335
- $lines[] = $message;
336
- }
337
- return $lines;
338
- }
339
-
340
- if (is_array($message) || is_object($message)) {
341
- if (is_array($message)) {
342
- $lines[] = 'array(' . count($message) . ') (';
343
- } else {
344
- $lines[] = 'object(' . get_class($message) . ') (';
345
- }
346
- $tabs++;
347
- foreach ($message as $key => $value) {
348
- $array = $this->format_message($value, $level, false, $tabs);
349
- if (is_array($array)) {
350
- $array[0] = str_repeat(' ', $tabs) . $key . ' => ' . $array[0];
351
- $lines = array_merge($lines, $array);
352
- } else {
353
- $lines[] = str_repeat(' ', $tabs) . $key . ' => ' . $array;
354
- }
355
- }
356
- $tabs--;
357
- $lines[] = str_repeat(' ', $tabs) . ')';
358
- return $lines;
359
- }
360
-
361
- if (is_int($message)) {
362
- $lines[] = 'int (' . $message . ')';
363
- return $lines;
364
- }
365
-
366
- if (is_float($message)) {
367
- $lines[] = 'float (' . $message . ')';
368
- return $lines;
369
- }
370
-
371
- if (is_resource($message)) {
372
- $lines[] = 'resource (' . get_resource_type($message) . ')';
373
- return $lines;
374
- }
375
-
376
- $lines[] = 'unknown (' . $message . ')';
377
- return $lines;
378
- }
379
-
380
- /**
381
- * Send a debug message
382
- *
383
- * @return boolean True on success, false on failure
384
- */
385
- function debug($message, $prefix = false)
386
- {
387
- $this->send($message, BP_LOG_DEBUG, false, $prefix);
388
- }
389
-
390
- /**
391
- * Send a notice message
392
- *
393
- * If the message is an array, then it sends each index as a separate message
394
- *
395
- * @return boolean True on success, false on failure
396
- */
397
- function notice($message)
398
- {
399
- if (is_array($message)) {
400
- foreach ($message as $value) {
401
- $this->send($value, BP_LOG_NOTICE);
402
- }
403
- } else {
404
- $this->send($message, BP_LOG_NOTICE);
405
- }
406
- }
407
-
408
- /**
409
- * Send a warning message
410
- *
411
- * If the message is an array, then it sends each index as a separate message
412
- *
413
- * @return boolean True on success, false on failure
414
- */
415
- function warning($message)
416
- {
417
- if (is_array($message)) {
418
- foreach ($message as $value) {
419
- $this->send($value, BP_LOG_WARNING);
420
- }
421
- } else {
422
- $this->send($message, BP_LOG_WARNING);
423
- }
424
- }
425
-
426
- /**
427
- * Send an error message
428
- *
429
- * If the message is an array, then it sends each index as a separate message
430
- *
431
- * @return boolean True on success, false on failure
432
- */
433
- function error($message)
434
- {
435
- if (is_array($message)) {
436
- foreach ($message as $value) {
437
- $this->send($value, BP_LOG_ERROR);
438
- }
439
- } else {
440
- $this->send($message, BP_LOG_ERROR);
441
- }
442
- }
443
-
444
- /**
445
- * Send an error message and die
446
- *
447
- * If the message is an array, then it sends each index as a separate message
448
- *
449
- * @return boolean True on success, false on failure
450
- */
451
- function fail($message)
452
- {
453
- if (is_array($message)) {
454
- foreach ($message as $value) {
455
- $this->send($value, BP_LOG_FAIL);
456
- }
457
- } else {
458
- $this->send($message, BP_LOG_FAIL);
459
- }
460
-
461
- die();
462
- }
463
-
464
- /**
465
- * Outputs javascript functions for the head of the html document
466
- *
467
- * Must be included in the head of the debug document somehow when using 'console' type.
468
- *
469
- * @return void
470
- **/
471
- function console_javascript()
472
- {
473
- if ($this->type !== 'console') {
474
- return;
475
- }
476
-
477
- $this->console_javascript_loaded = true;
478
- ?>
479
-
480
- <script type="text/javascript" charset="utf-8">
481
- var BP_LOG_NONE = 0;
482
- var BP_LOG_FAIL = 1;
483
- var BP_LOG_ERROR = 2;
484
- var BP_LOG_WARNING = 4;
485
- var BP_LOG_NOTICE = 8;
486
- var BP_LOG_DEBUG = 16;
487
-
488
- function bp_log_send(message, level, time) {
489
- if (window.console) {
490
- // Works in later Safari and Firefox with Firebug
491
- switch (level) {
492
- case BP_LOG_NONE:
493
- // This shouldn't happen really
494
- break;
495
- case BP_LOG_FAIL:
496
- case BP_LOG_ERROR:
497
- window.console.error("[" + time + "] " + message);
498
- break;
499
- case BP_LOG_WARNING:
500
- window.console.warn("[" + time + "] " + message);
501
- break;
502
- case BP_LOG_NOTICE:
503
- window.console.info("[" + time + "] " + message);
504
- break;
505
- case BP_LOG_DEBUG:
506
- window.console.log("[" + time + "] " + message);
507
- break;
508
- default:
509
- break;
510
- }
511
- }
512
- }
513
-
514
- var bp_log_queue = new Array();
515
-
516
- function bp_log_add(message, level, time) {
517
- bp_log_queue.push(new Array(message, level, time));
518
- }
519
-
520
- function bp_log_process() {
521
- while (item = bp_log_queue.shift()) {
522
- bp_log_send(item[0], item[1], item[2]);
523
- }
524
- }
525
-
526
- function bp_log_onload() {
527
- <?php
528
- foreach ($this->console_javascript_onloads as $onload) {
529
- echo "\t\t\t" . 'bp_log_send(\'' . $this->_esc_js_log( $onload['message'] ) . '\', ' . $this->_esc_js_log( $onload['level'] ) . ', \'' . $this->_esc_js_log( $onload['time'] ) . '\');' . "\n";
530
- }
531
- ?>
532
- bp_log_process();
533
- }
534
-
535
- window.onload = bp_log_onload;
536
- </script>
537
-
538
- <?php
539
- }
540
-
541
- function _esc_js_log( $message )
542
- {
543
- return str_replace(
544
- array( '\'', "\n" ),
545
- array( '\\\'', '\n' ),
546
- $message
547
- );
548
- }
549
-
550
- } // END class BP_Log
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.bp-roles.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
-
3
- class BP_Roles {
4
- var $role_objects = array();
5
- var $role_names = array();
6
-
7
- function __construct() {
8
- do_action_ref_array('init_roles', array(&$this) );
9
- }
10
-
11
- function BP_Roles() {
12
- $this->__construct();
13
- }
14
-
15
- function add_role($role, $display_name, $capabilities = '') {
16
- if ( isset($this->role_objects[$role]) )
17
- return;
18
-
19
- $this->role_objects[$role] = new BP_Role($role, $capabilities, $this);
20
- $this->role_names[$role] = $display_name;
21
- return $this->role_objects[$role];
22
- }
23
-
24
- function remove_role($role) {
25
- if ( ! isset($this->role_objects[$role]) )
26
- return;
27
-
28
- unset($this->role_objects[$role]);
29
- unset($this->role_names[$role]);
30
- }
31
-
32
- function add_cap($role, $cap, $grant = true) {
33
- if ( isset($this->role_objects[$role]) )
34
- $this->role_objects[$role]->add_cap($cap, $grant);
35
- }
36
-
37
- function remove_cap($role, $cap) {
38
- if ( isset($this->role_objects[$role]) )
39
- $this->role_objects[$role]->remove_cap($cap, $grant);
40
- }
41
-
42
- function &get_role($role) {
43
- if ( isset($this->role_objects[$role]) )
44
- return $this->role_objects[$role];
45
- else
46
- return null;
47
- }
48
-
49
- function get_names() {
50
- return $this->role_names;
51
- }
52
-
53
- function is_role($role) {
54
- return isset($this->role_names[$role]);
55
- }
56
-
57
- function map_meta_cap( $cap, $user_id ) {
58
- $args = array_slice(func_get_args(), 2);
59
- return apply_filters( 'map_meta_cap', array( $cap ), $cap, $user_id, $args );
60
- }
61
- }
62
-
63
- class BP_Role {
64
- var $name;
65
- var $capabilities;
66
-
67
- function __construct($role, $capabilities) {
68
- $this->name = $role;
69
- $this->capabilities = $capabilities;
70
- }
71
-
72
- function BP_Role($role, $capabilities) {
73
- $this->__construct($role, $capabilities);
74
- }
75
-
76
- function add_cap($cap, $grant = true) {
77
- $this->capabilities[$cap] = $grant;
78
- }
79
-
80
- function remove_cap($cap) {
81
- unset($this->capabilities[$cap]);
82
- }
83
-
84
- function has_cap($cap) {
85
- $capabilities = apply_filters('role_has_cap', $this->capabilities, $cap, $this->name);
86
- $grant = !empty( $capabilities[$cap] );
87
- return apply_filters("{$this->name}_has_cap", $grant);
88
- }
89
-
90
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.bp-sql-schema-parser.php DELETED
@@ -1,615 +0,0 @@
1
- <?php
2
- /**
3
- * Parses SQL schema statements for comparison to real table structures
4
- *
5
- * @package BackPress
6
- **/
7
- class BP_SQL_Schema_Parser
8
- {
9
- /**
10
- * Builds a column definition as used in CREATE TABLE statements from
11
- * an array such as those returned by DESCRIBE `foo` statements
12
- */
13
- function get_column_definition( $column_data )
14
- {
15
- if ( !is_array( $column_data ) ) {
16
- return $column_data;
17
- }
18
-
19
- $null = '';
20
- if ( $column_data['Null'] != 'YES' ) {
21
- $null = 'NOT NULL';
22
- }
23
-
24
- $default = '';
25
-
26
- // Defaults aren't allowed at all on certain column types
27
- if ( !in_array(
28
- strtolower( $column_data['Type'] ),
29
- array( 'tinytext', 'text', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob' )
30
- ) ) {
31
- if ( $column_data['Null'] == 'YES' && $column_data['Default'] === null ) {
32
- $default = 'default NULL';
33
- } elseif ( preg_match( '@^\d+$@', $column_data['Default'] ) ) {
34
- $default = 'default ' . $column_data['Default'];
35
- } elseif ( is_string( $column_data['Default'] ) || is_float( $column_data['Default'] ) ) {
36
- $default = 'default \'' . $column_data['Default'] . '\'';
37
- }
38
- }
39
-
40
- $column_definition = '`' . $column_data['Field'] . '` ' . $column_data['Type'] . ' ' . $null . ' ' . $column_data['Extra'] . ' ' . $default;
41
- return preg_replace( '@\s+@', ' ', trim( $column_definition ) );
42
- }
43
-
44
- /**
45
- * Builds an index definition as used in CREATE TABLE statements from
46
- * an array similar to those returned by SHOW INDEX FROM `foo` statements
47
- */
48
- function get_index_definition( $index_data )
49
- {
50
- if ( !is_array( $index_data ) ) {
51
- return $index_data;
52
- }
53
-
54
- if ( !count( $index_data ) ) {
55
- return $index_data;
56
- }
57
-
58
- $_name = '`' . $index_data[0]['Key_name'] . '`';
59
-
60
- if ( $index_data[0]['Index_type'] == 'BTREE' && $index_data[0]['Key_name'] == 'PRIMARY' ) {
61
- $_type = 'PRIMARY KEY';
62
- $_name = '';
63
- } elseif ( $index_data[0]['Index_type'] == 'BTREE' && !$index_data[0]['Non_unique'] ) {
64
- $_type = 'UNIQUE KEY';
65
- } elseif ( $index_data[0]['Index_type'] == 'FULLTEXT' ) {
66
- $_type = 'FULLTEXT KEY';
67
- } else {
68
- $_type = 'KEY';
69
- }
70
-
71
- $_columns = array();
72
- foreach ( $index_data as $_index ) {
73
- if ( $_index['Sub_part'] ) {
74
- $_columns[] = '`' . $_index['Column_name'] . '`(' . $_index['Sub_part'] . ')';
75
- } else {
76
- $_columns[] = '`' . $_index['Column_name'] . '`';
77
- }
78
- }
79
- $_columns = join( ', ', $_columns );
80
-
81
- $index_definition = $_type . ' ' . $_name . ' (' . $_columns . ')';
82
- return preg_replace( '@\s+@', ' ', $index_definition );
83
- }
84
-
85
- /**
86
- * Returns a table structure from a raw sql query of the form "CREATE TABLE foo" etc.
87
- * The resulting array contains the original query, the columns as would be returned by DESCRIBE `foo`
88
- * and the indices as would be returned by SHOW INDEX FROM `foo` on a real table
89
- */
90
- function describe_table( $query )
91
- {
92
- // Retrieve the table structure from the query
93
- if ( !preg_match( '@^CREATE\s+TABLE(\s+IF\s+NOT\s+EXISTS)?\s+`?([^\s|`]+)`?\s+\((.*)\)\s*([^\)|;]*)\s*;?@ims', $query, $_matches ) ) {
94
- return $query;
95
- }
96
-
97
- $_if_not_exists = $_matches[1];
98
-
99
- // Tidy up the table name
100
- $_table_name = trim( $_matches[2] );
101
-
102
- // Tidy up the table columns/indices
103
- $_columns_indices = trim( $_matches[3], " \t\n\r\0\x0B," );
104
- // Split by commas not followed by a closing parenthesis ")", using fancy lookaheads
105
- $_columns_indices = preg_split( '@,(?!(?:[^\(]+\)))@ms', $_columns_indices );
106
- $_columns_indices = array_map( 'trim', $_columns_indices );
107
-
108
- // Tidy the table attributes
109
- $_attributes = preg_replace( '@\s+@', ' ', trim( $_matches[4] ) );
110
- unset( $_matches );
111
-
112
- // Initialise some temporary arrays
113
- $_columns = array();
114
- $_indices = array();
115
-
116
- // Loop over the columns/indices
117
- foreach ( $_columns_indices as $_column_index ) {
118
- if ( preg_match( '@^(PRIMARY\s+KEY|UNIQUE\s+(?:KEY|INDEX)|FULLTEXT\s+(?:KEY|INDEX)|KEY|INDEX)\s+(?:`?(\w+)`?\s+)*\((.+?)\)$@im', $_column_index, $_matches ) ) {
119
- // It's an index
120
-
121
- // Tidy the type
122
- $_index_type = strtoupper( preg_replace( '@\s+@', ' ', trim( $_matches[1] ) ) );
123
- $_index_type = str_replace( 'INDEX', 'KEY', $_index_type );
124
- // Set the index name
125
- $_index_name = ( 'PRIMARY KEY' == $_matches[1] ) ? 'PRIMARY' : $_matches[2];
126
- // Split into columns
127
- $_index_columns = array_map( 'trim', explode( ',', $_matches[3] ) );
128
-
129
- foreach ( $_index_columns as $_index_columns_index => $_index_column ) {
130
- preg_match( '@`?(\w+)`?(?:\s*\(\s*(\d+)\s*\))?@i', $_index_column, $_matches_column );
131
-
132
- $_indices[$_index_name][] = array(
133
- 'Table' => $_table_name,
134
- 'Non_unique' => ( 'UNIQUE KEY' == $_index_type || 'PRIMARY' == $_index_name ) ? '0' : '1',
135
- 'Key_name' => $_index_name,
136
- 'Seq_in_index' => (string) ( $_index_columns_index + 1 ),
137
- 'Column_name' => $_matches_column[1],
138
- 'Sub_part' => ( isset( $_matches_column[2] ) && $_matches_column[2] ) ? $_matches_column[2] : null,
139
- 'Index_type' => ( 'FULLTEXT KEY' == $_index_type ) ? 'FULLTEXT' : 'BTREE'
140
- );
141
- }
142
- unset( $_index_type, $_index_name, $_index_columns, $_index_columns_index, $_index_column, $_matches_column );
143
-
144
- } elseif ( preg_match( "@^`?(\w+)`?\s+(?:(\w+)(?:\s*\(\s*(\d+)\s*\))?(?:\s+(unsigned)){0,1})(?:\s+(NOT\s+NULL))?(?:\s+(auto_increment))?(?:\s+(default)\s+(?:(NULL|'[^']*'|\d+)))?@im", $_column_index, $_matches ) ) {
145
- // It's a column
146
-
147
- // Tidy the NOT NULL
148
- $_matches[5] = isset( $_matches[5] ) ? strtoupper( preg_replace( '@\s+@', ' ', trim( $_matches[5] ) ) ) : '';
149
-
150
- $_columns[$_matches[1]] = array(
151
- 'Field' => $_matches[1],
152
- 'Type' => ( is_numeric( $_matches[3] ) ) ? $_matches[2] . '(' . $_matches[3] . ')' . ( ( isset( $_matches[4] ) && strtolower( $_matches[4] ) == 'unsigned' ) ? ' unsigned' : '' ) : $_matches[2],
153
- 'Null' => ( 'NOT NULL' == strtoupper( $_matches[5] ) ) ? 'NO' : 'YES',
154
- 'Default' => ( isset( $_matches[7] ) && 'default' == strtolower( $_matches[7] ) && 'NULL' !== strtoupper( $_matches[8] ) ) ? trim( $_matches[8], "'" ) : null,
155
- 'Extra' => ( isset( $_matches[6] ) && 'auto_increment' == strtolower( $_matches[6] ) ) ? 'auto_increment' : ''
156
- );
157
- }
158
- }
159
- unset( $_matches, $_columns_indices, $_column_index );
160
-
161
- // Tidy up the original query
162
- $_tidy_query = 'CREATE TABLE';
163
- if ( $_if_not_exists ) {
164
- $_tidy_query .= ' IF NOT EXISTS';
165
- }
166
- $_tidy_query .= ' `' . $_table_name . '` (' . "\n";
167
- foreach ( $_columns as $_column ) {
168
- $_tidy_query .= "\t" . BP_SQL_Schema_Parser::get_column_definition( $_column ) . ",\n";
169
- }
170
- unset( $_column );
171
- foreach ( $_indices as $_index ) {
172
- $_tidy_query .= "\t" . BP_SQL_Schema_Parser::get_index_definition( $_index ) . ",\n";
173
- }
174
- $_tidy_query = substr( $_tidy_query, 0, -2 ) . "\n" . ') ' . $_attributes . ';';
175
-
176
- // Add to the query array using the table name as the index
177
- $description = array(
178
- 'query_original' => $query,
179
- 'query_tidy' => $_tidy_query,
180
- 'columns' => $_columns,
181
- 'indices' => $_indices
182
- );
183
- unset( $_table_name, $_columns, $_indices, $_tidy_query );
184
-
185
- return $description;
186
- }
187
-
188
- /**
189
- * Helper function to flatten arrays
190
- */
191
- function _flatten_array( $array, $cut_branch = 0, $keep_child_array_keys = true )
192
- {
193
- if ( !is_array( $array ) ) {
194
- return $array;
195
- }
196
-
197
- if ( empty( $array ) ) {
198
- return null;
199
- }
200
-
201
- $temp = array();
202
- foreach ( $array as $k => $v ) {
203
- if ( $cut_branch && $k == $cut_branch )
204
- continue;
205
- if ( is_array( $v ) ) {
206
- if ( $keep_child_array_keys ) {
207
- $temp[$k] = true;
208
- }
209
- $temp += BP_SQL_Schema_Parser::_flatten_array( $v, $cut_branch, $keep_child_array_keys );
210
- } else {
211
- $temp[$k] = $v;
212
- }
213
- }
214
- return $temp;
215
- }
216
-
217
- /**
218
- * Splits grouped SQL statements into queries within a highly structured array
219
- * Only supports CREATE TABLE, INSERT and UPDATE
220
- */
221
- function parse( $sql )
222
- {
223
- // Only accept strings or arrays
224
- if ( is_string( $sql ) ) {
225
- // Just pop strings into an array to start with
226
- $queries = array( $sql );
227
- } elseif ( is_array( $sql ) ) {
228
- // Flatten the array
229
- $queries = BP_SQL_Schema_Parser::_flatten_array( $sql, 0, false );
230
- // Remove empty nodes
231
- $queries = array_filter( $queries );
232
- } else {
233
- return false;
234
- }
235
-
236
- // Clean up the queries
237
- $_clean_queries = array();
238
- foreach ( $queries as $_query ) {
239
- // Trim space and semi-colons
240
- $_query = trim( $_query, "; \t\n\r\0\x0B" );
241
- // If it exists and isn't a number
242
- if ( $_query && !is_numeric( $_query ) ) {
243
- // Is it more than one query?
244
- if ( strpos( ';', $_query ) !== false ) {
245
- // Explode by semi-colon
246
- foreach ( explode( ';', $_query ) as $_part ) {
247
- $_part = trim( $_part );
248
- if ( $_part && !is_numeric( $_part ) ) {
249
- // Pull out any commented code
250
- // Can't properly deal with /*!4321 FOO `bar` */ version specific inclusion, just includes it regardless of version
251
- $_part = preg_replace( '@/\*![0-9]*([^\*]*)\*/@', '$1', $_part );
252
- $_part = preg_replace( '@/\*[^\*]*\*/@', '', $_part );
253
- $_part = preg_replace( '@[\-\-|#].*$@m', '', $_part );
254
- $_clean_queries[] = trim( $_part ) . ';';
255
- }
256
- }
257
- unset( $_part );
258
- } else {
259
- $_clean_queries[] = $_query . ';';
260
- }
261
- }
262
- }
263
- unset( $_query );
264
- if ( !count( $_clean_queries ) ) {
265
- return false;
266
- }
267
- $queries = $_clean_queries;
268
- unset( $_clean_queries );
269
-
270
- $_queries = array();
271
- foreach ( $queries as $_query ) {
272
- // Only process table creation, inserts and updates, capture the table/database name while we are at it
273
- if ( !preg_match( '@^(CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|INSERT\s+INTO|UPDATE)\s+`?([^\s|`]+)`?@im', $_query, $_matches ) ) {
274
- continue;
275
- }
276
-
277
- // Tidy up the type so we can switch it
278
- $_type = strtoupper( preg_replace( '@\s+@', ' ', trim( $_matches[1] ) ) );
279
- $_table_name = trim( $_matches[2] );
280
- unset( $_matches );
281
-
282
- switch ( $_type ) {
283
- case 'CREATE TABLE':
284
- case 'CREATE TABLE IF NOT EXISTS':
285
- $_description = BP_SQL_Schema_Parser::describe_table( $_query );
286
- if ( is_array( $_description ) ) {
287
- $_queries['tables'][$_table_name] = $_description;
288
- }
289
- break;
290
-
291
- case 'INSERT INTO':
292
- // Just add the query as is for now
293
- $_queries['insert'][$_table_name][] = $_query;
294
- break;
295
-
296
- case 'UPDATE':
297
- // Just add the query as is for now
298
- $_queries['update'][$_table_name][] = $_query;
299
- break;
300
- }
301
- unset( $_type, $_table_name );
302
- }
303
- unset( $_query );
304
-
305
- if ( !count( $_queries ) ) {
306
- return false;
307
- }
308
- return $_queries;
309
- }
310
-
311
- /**
312
- * Evaluates the difference between a given set of SQL queries and real database structure
313
- */
314
- function delta( $db_object, $queries, $ignore = false, $execute = true )
315
- {
316
- if ( !$db_object || !is_object( $db_object ) || !( is_a( $db_object, 'BPDB' ) || is_a( $db_object, 'BPDB_Multi' ) || is_a( $db_object, 'BPDB_Hyper' ) ) ) {
317
- return __( 'Passed variable is not a BackPress database object.' );
318
- }
319
-
320
- if ( !$_queries = BP_SQL_Schema_Parser::parse( $queries ) ) {
321
- return __( 'No schema available.' );
322
- }
323
-
324
- // Set up default elements to ignore
325
- $ignore_defaults = array(
326
- 'tables' => array(), // Just a list of tablenames, including prefix. Does not affect INSERT and UPDATE queries.
327
- 'columns' => array(), // Arrays of column names, keyed with the table names, including prefix.
328
- 'indices' => array() // Arrays of index names, keyed with the table names, including prefix.
329
- );
330
-
331
- // Add the elements to ignore that were passed to the function
332
- if ( !$ignore || !is_array( $ignore ) ) {
333
- $ignore = $ignore_defaults;
334
- } else {
335
- if ( isset( $ignore['tables'] ) && is_array( $ignore['tables'] ) ) {
336
- $ignore['tables'] = array_merge( $ignore_defaults['tables'], $ignore['tables'] );
337
- }
338
- if ( isset( $ignore['columns'] ) && is_array( $ignore['columns'] ) ) {
339
- $ignore['columns'] = array_merge( $ignore_defaults['columns'], $ignore['columns'] );
340
- }
341
- if ( isset( $ignore['indices'] ) && is_array( $ignore['indices'] ) ) {
342
- $ignore['indices'] = array_merge( $ignore_defaults['indices'], $ignore['indices'] );
343
- }
344
- }
345
-
346
- // Build an array of $db_object registered tables and their database identifiers
347
- $_tables = $db_object->tables;
348
- $db_object_tables = array();
349
- foreach ( $_tables as $_table_id => $_table_name ) {
350
- if ( is_array( $_table_name ) && isset( $db_object->db_servers['dbh_' . $_table_name[0]] ) ) {
351
- $db_object_tables[$db_object->$_table_id] = 'dbh_' . $_table_name[0];
352
- } else {
353
- $db_object_tables[$db_object->$_table_id] = 'dbh_global';
354
- }
355
- }
356
- unset( $_tables, $_table_id, $_table_name );
357
-
358
- $alterations = array();
359
-
360
- // Loop through table queries
361
- if ( isset( $_queries['tables'] ) ) {
362
- foreach ( $_queries['tables'] as $_new_table_name => $_new_table_data ) {
363
- if ( in_array( $_new_table_name, $ignore['tables'] ) ) {
364
- continue;
365
- }
366
-
367
- // See if the table is custom and registered in $db_object under a custom database
368
- if (
369
- isset( $db_object_tables[$_new_table_name] ) &&
370
- $db_object_tables[$_new_table_name] != 'dbh_global' &&
371
- isset( $db_object->db_servers[$db_object_tables[$_new_table_name]]['ds'] )
372
- ) {
373
- // Force the database connection
374
- $_dbhname = $db_object->db_servers[$db_object_tables[$_new_table_name]]['ds'];
375
- $db_object->_force_dbhname = $_dbhname;
376
- } else {
377
- $_dbhname = 'dbh_global';
378
- }
379
-
380
- // Fetch the existing table column structure from the database
381
- $db_object->suppress_errors();
382
- if ( !$_existing_table_columns = $db_object->get_results( 'DESCRIBE `' . $_new_table_name . '`;', ARRAY_A ) ) {
383
- $db_object->suppress_errors( false );
384
- // The table doesn't exist, add it and then continue to the next table
385
- $alterations[$_dbhname][$_new_table_name][] = array(
386
- 'action' => 'create_table',
387
- 'message' => __( 'Creating table' ),
388
- 'query' => $_new_table_data['query_tidy']
389
- );
390
- continue;
391
- }
392
- $db_object->suppress_errors( false );
393
-
394
- // Add an index to the existing columns array
395
- $__existing_table_columns = array();
396
- foreach ( $_existing_table_columns as $_existing_table_column ) {
397
- // Remove 'Key' from returned column structure
398
- unset( $_existing_table_column['Key'] );
399
- $__existing_table_columns[$_existing_table_column['Field']] = $_existing_table_column;
400
- }
401
- $_existing_table_columns = $__existing_table_columns;
402
- unset( $__existing_table_columns );
403
-
404
- // Loop over the columns in this table and look for differences
405
- foreach ( $_new_table_data['columns'] as $_new_column_name => $_new_column_data ) {
406
- if ( isset( $ignore['columns'][$_new_table_name] ) && in_array( $_new_column_name, $ignore['columns'][$_new_table_name] ) ) {
407
- continue;
408
- }
409
-
410
- if ( !in_array( $_new_column_data, $_existing_table_columns ) ) {
411
- // There is a difference
412
- if ( !isset( $_existing_table_columns[$_new_column_name] ) ) {
413
- // The column doesn't exist, so add it
414
- $alterations[$_dbhname][$_new_table_name][] = array(
415
- 'action' => 'add_column',
416
- 'message' => sprintf( __( 'Adding column: %s' ), $_new_column_name ),
417
- 'column' => $_new_column_name,
418
- 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD COLUMN ' . BP_SQL_Schema_Parser::get_column_definition( $_new_column_data ) . ';'
419
- );
420
- continue;
421
- }
422
-
423
- // Adjust defaults on columns that allow defaults
424
- if (
425
- $_new_column_data['Default'] !== $_existing_table_columns[$_new_column_name]['Default'] &&
426
- !in_array(
427
- strtolower( $_new_column_data['Type'] ),
428
- array( 'tinytext', 'text', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob' )
429
- )
430
- ) {
431
- // Change the default value for the column
432
- $alterations[$_dbhname][$_new_table_name][] = array(
433
- 'action' => 'set_default',
434
- 'message' => sprintf( __( 'Setting default on column: %s' ), $_new_column_name ),
435
- 'column' => $_new_column_name,
436
- 'query' => 'ALTER TABLE `' . $_new_table_name . '` ALTER COLUMN `' . $_new_column_name . '` SET DEFAULT \'' . $_new_column_data['Default'] . '\';'
437
- );
438
- // Don't continue, overwrite this if the next conditional is met
439
- }
440
-
441
- if (
442
- $_new_column_data['Type'] !== $_existing_table_columns[$_new_column_name]['Type'] ||
443
- ( 'YES' === $_new_column_data['Null'] xor 'YES' === $_existing_table_columns[$_new_column_name]['Null'] ) ||
444
- $_new_column_data['Extra'] !== $_existing_table_columns[$_new_column_name]['Extra']
445
- ) {
446
- // Change the structure for the column
447
- $alterations[$_dbhname][$_new_table_name][] = array(
448
- 'action' => 'change_column',
449
- 'message' => sprintf( __( 'Changing column: %s' ), $_new_column_name ),
450
- 'column' => $_new_column_name,
451
- 'query' => 'ALTER TABLE `' . $_new_table_name . '` CHANGE COLUMN `' . $_new_column_name . '` ' . BP_SQL_Schema_Parser::get_column_definition( $_new_column_data ) . ';'
452
- );
453
- }
454
- }
455
- }
456
- unset( $_existing_table_columns, $_new_column_name, $_new_column_data );
457
-
458
- // Fetch the table index structure from the database
459
- if ( !$_existing_table_indices = $db_object->get_results( 'SHOW INDEX FROM `' . $_new_table_name . '`;', ARRAY_A ) ) {
460
- continue;
461
- }
462
-
463
- // Add an index to the existing columns array and organise by index name
464
- $__existing_table_indices = array();
465
- foreach ( $_existing_table_indices as $_existing_table_index ) {
466
- // Remove unused parts from returned index structure
467
- unset(
468
- $_existing_table_index['Collation'],
469
- $_existing_table_index['Cardinality'],
470
- $_existing_table_index['Packed'],
471
- $_existing_table_index['Null'],
472
- $_existing_table_index['Comment']
473
- );
474
- $__existing_table_indices[$_existing_table_index['Key_name']][] = $_existing_table_index;
475
- }
476
- $_existing_table_indices = $__existing_table_indices;
477
- unset( $__existing_table_indices );
478
-
479
- // Loop over the indices in this table and look for differences
480
- foreach ( $_new_table_data['indices'] as $_new_index_name => $_new_index_data ) {
481
- if ( isset( $ignore['indices'][$_new_table_name] ) && in_array( $_new_index_name, $ignore['indices'][$_new_table_name] ) ) {
482
- continue;
483
- }
484
-
485
- if ( !in_array( $_new_index_data, $_existing_table_indices ) ) {
486
- // There is a difference
487
- if ( !isset( $_existing_table_indices[$_new_index_name] ) ) {
488
- // The index doesn't exist, so add it
489
- $alterations[$_dbhname][$_new_table_name][] = array(
490
- 'action' => 'add_index',
491
- 'message' => sprintf( __( 'Adding index: %s' ), $_new_index_name ),
492
- 'index' => $_new_index_name,
493
- 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD ' . BP_SQL_Schema_Parser::get_index_definition( $_new_index_data ) . ';'
494
- );
495
- continue;
496
- }
497
-
498
- if ( $_new_index_data !== $_existing_table_indices[$_new_index_name] ) {
499
- // The index is incorrect, so drop it and add the new one
500
- if ( $_new_index_name == 'PRIMARY' ) {
501
- $_drop_index_name = 'PRIMARY KEY';
502
- } else {
503
- $_drop_index_name = 'INDEX `' . $_new_index_name . '`';
504
- }
505
- $alterations[$_dbhname][$_new_table_name][] = array(
506
- 'action' => 'drop_index',
507
- 'message' => sprintf( __( 'Dropping index: %s' ), $_new_index_name ),
508
- 'index' => $_new_index_name,
509
- 'query' => 'ALTER TABLE `' . $_new_table_name . '` DROP ' . $_drop_index_name . ';'
510
- );
511
- unset( $_drop_index_name );
512
- $alterations[$_dbhname][$_new_table_name][] = array(
513
- 'action' => 'add_index',
514
- 'message' => sprintf( __( 'Adding index: %s' ), $_new_index_name ),
515
- 'index' => $_new_index_name,
516
- 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD ' . BP_SQL_Schema_Parser::get_index_definition( $_new_index_data ) . ';'
517
- );
518
- }
519
- }
520
- }
521
- unset( $_new_index_name, $_new_index_data );
522
-
523
- // Go back to the default database connection
524
- $db_object->_force_dbhname = false;
525
- }
526
- unset( $_new_table_name, $_new_table_data, $_dbhname );
527
- }
528
-
529
- // Now deal with the sundry INSERT and UPDATE statements (if any)
530
- if ( isset( $_queries['insert'] ) && is_array( $_queries['insert'] ) && count( $_queries['insert'] ) ) {
531
- foreach ( $_queries['insert'] as $_table_name => $_inserts ) {
532
- foreach ( $_inserts as $_insert ) {
533
- $alterations['dbh_global'][$_table_name][] = array(
534
- 'action' => 'insert',
535
- 'message' => __( 'Inserting data' ),
536
- 'query' => $_insert
537
- );
538
- }
539
- unset( $_insert );
540
- }
541
- unset( $_table_name, $_inserts );
542
- }
543
- if ( isset( $_queries['update'] ) && is_array( $_queries['update'] ) && count( $_queries['update'] ) ) {
544
- foreach ( $_queries['update'] as $_table_name => $_updates ) {
545
- foreach ( $_updates as $_update ) {
546
- $alterations['dbh_global'][$_table_name][] = array(
547
- 'action' => 'update',
548
- 'message' => __( 'Updating data' ),
549
- 'query' => $_update
550
- );
551
- }
552
- unset( $_update );
553
- }
554
- unset( $_table_name, $_updates );
555
- }
556
-
557
- // Initialise an array to hold the output messages
558
- $messages = array();
559
- $errors = array();
560
-
561
- foreach ( $alterations as $_dbhname => $_tables ) {
562
- // Force the database connection (this was already checked to be valid in the previous loop)
563
- $db_object->_force_dbhname = $_dbhname;
564
-
565
- // Note the database in the return messages
566
- $messages[] = '>>> ' . sprintf( __( 'Modifying database: %s (%s)' ), $db_object->db_servers[$_dbhname]['name'], $db_object->db_servers[$_dbhname]['host'] );
567
-
568
- foreach ( $_tables as $_table_name => $_alterations ) {
569
- // Note the table in the return messages
570
- $messages[] = '>>>>>> ' . sprintf( __( 'Table: %s' ), $_table_name );
571
-
572
- foreach ( $_alterations as $_alteration ) {
573
- // If there is no query, then skip
574
- if ( !$_alteration['query'] ) {
575
- continue;
576
- }
577
-
578
- // Note the action in the return messages
579
- $messages[] = '>>>>>>>>> ' . $_alteration['message'];
580
-
581
- if ( !$execute ) {
582
- $messages[] = '>>>>>>>>>>>> ' . __( 'Skipped' );
583
- continue;
584
- }
585
-
586
- // Run the query
587
- $_result = $db_object->query( $_alteration['query'] );
588
- $_result_error = $db_object->get_error();
589
-
590
- if ( $_result_error ) {
591
- // There was an error
592
- $_result =& $_result_error;
593
- unset( $_result_error );
594
- $messages[] = '>>>>>>>>>>>> ' . __( 'SQL ERROR! See the error log for more detail' );
595
- $errors[] = __( 'SQL ERROR!' );
596
- $errors[] = '>>> ' . sprintf( __( 'Database: %s (%s)' ), $db_object->db_servers[$_dbhname]['name'], $db_object->db_servers[$_dbhname]['host'] );
597
- $errors[] = '>>>>>> ' . $_result->error_data['db_query']['query'];
598
- $errors[] = '>>>>>> ' . $_result->error_data['db_query']['error'];
599
- } else {
600
- $messages[] = '>>>>>>>>>>>> ' . __( 'Done' );
601
- }
602
- unset( $_result );
603
- }
604
- unset( $_alteration );
605
- }
606
- unset( $_table_name, $_alterations );
607
- }
608
- unset( $_dbhname, $_tables );
609
-
610
- // Reset the database connection
611
- $db_object->_force_dbhname = false;
612
-
613
- return array( 'messages' => $messages, 'errors' => $errors );
614
- }
615
- } // END class BP_SQL_Schema_Parser
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.bp-user.php DELETED
@@ -1,402 +0,0 @@
1
- <?php
2
- // Last sync [WP11537]
3
-
4
- /**
5
- * BackPress User class.
6
- *
7
- * @since 2.0.0
8
- * @package BackPress
9
- * @subpackage User
10
- */
11
- class BP_User {
12
- /**
13
- * User data container.
14
- *
15
- * This will be set as properties of the object.
16
- *
17
- * @since 2.0.0
18
- * @access private
19
- * @var array
20
- */
21
- var $data;
22
-
23
- /**
24
- * The user's ID.
25
- *
26
- * @since 2.1.0
27
- * @access public
28
- * @var int
29
- */
30
- var $ID = 0;
31
-
32
- /**
33
- * The deprecated user's ID.
34
- *
35
- * @since 2.0.0
36
- * @access public
37
- * @deprecated Use BP_User::$ID
38
- * @see BP_User::$ID
39
- * @var int
40
- */
41
- var $id = 0;
42
-
43
- /**
44
- * The individual capabilities the user has been given.
45
- *
46
- * @since 2.0.0
47
- * @access public
48
- * @var array
49
- */
50
- var $caps = array();
51
-
52
- /**
53
- * User metadata option name.
54
- *
55
- * @since 2.0.0
56
- * @access public
57
- * @var string
58
- */
59
- var $cap_key;
60
-
61
- /**
62
- * The roles the user is part of.
63
- *
64
- * @since 2.0.0
65
- * @access public
66
- * @var array
67
- */
68
- var $roles = array();
69
-
70
- /**
71
- * All capabilities the user has, including individual and role based.
72
- *
73
- * @since 2.0.0
74
- * @access public
75
- * @var array
76
- */
77
- var $allcaps = array();
78
-
79
- /**
80
- * First name of the user.
81
- *
82
- * Created to prevent notices.
83
- *
84
- * @since 2.7.0
85
- * @access public
86
- * @var string
87
- */
88
- var $first_name = '';
89
-
90
- /**
91
- * Last name of the user.
92
- *
93
- * Created to prevent notices.
94
- *
95
- * @since 2.7.0
96
- * @access public
97
- * @var string
98
- */
99
- var $last_name = '';
100
-
101
- /**
102
- * PHP4 Constructor - Sets up the object properties.
103
- *
104
- * Retrieves the userdata and then assigns all of the data keys to direct
105
- * properties of the object. Calls {@link BP_User::_init_caps()} after
106
- * setting up the object's user data properties.
107
- *
108
- * @since 2.0.0
109
- * @access public
110
- *
111
- * @param int|string $id User's ID or username
112
- * @param int $name Optional. User's username
113
- * @return BP_User
114
- */
115
- function __construct( $id, $name = '' ) {
116
- global $wp_users_object;
117
-
118
- if ( empty( $id ) && empty( $name ) )
119
- return;
120
-
121
- if ( ! is_numeric( $id ) ) {
122
- $name = $id;
123
- $id = 0;
124
- }
125
-
126
- if ( ! empty( $id ) )
127
- $this->data = $wp_users_object->get_user( $id );
128
- else
129
- $this->data = $wp_users_object->get_user( $name, array( 'by' => 'login' ) );
130
-
131
- if ( empty( $this->data->ID ) )
132
- return;
133
-
134
- foreach ( get_object_vars( $this->data ) as $key => $value ) {
135
- $this->{$key} = $value;
136
- }
137
-
138
- $this->id = $this->ID;
139
- $this->_init_caps();
140
- }
141
-
142
- function BP_User( $id, $name = '' ) {
143
- $this->__construct( $id, $name );
144
- }
145
-
146
- /**
147
- * Setup capability object properties.
148
- *
149
- * Will set the value for the 'cap_key' property to current database table
150
- * prefix, followed by 'capabilities'. Will then check to see if the
151
- * property matching the 'cap_key' exists and is an array. If so, it will be
152
- * used.
153
- *
154
- * @since 2.1.0
155
- * @access protected
156
- */
157
- function _init_caps() {
158
- global $wp_users_object;
159
- $this->cap_key = $wp_users_object->db->prefix . 'capabilities';
160
- $this->caps = &$this->{$this->cap_key};
161
- if ( ! is_array( $this->caps ) )
162
- $this->caps = array();
163
- $this->get_role_caps();
164
- }
165
-
166
- /**
167
- * Retrieve all of the role capabilities and merge with individual capabilities.
168
- *
169
- * All of the capabilities of the roles the user belongs to are merged with
170
- * the users individual roles. This also means that the user can be denied
171
- * specific roles that their role might have, but the specific user isn't
172
- * granted permission to.
173
- *
174
- * @since 2.0.0
175
- * @uses $wp_roles
176
- * @access public
177
- */
178
- function get_role_caps() {
179
- global $wp_roles, $wp_users_object;
180
-
181
- if ( ! isset( $wp_roles ) )
182
- $wp_roles = new BP_Roles( $wp_users_object->db );
183
-
184
- //Filter out caps that are not role names and assign to $this->roles
185
- if ( is_array( $this->caps ) )
186
- $this->roles = array_filter( array_keys( $this->caps ), array( &$wp_roles, 'is_role' ) );
187
-
188
- //Build $allcaps from role caps, overlay user's $caps
189
- $this->allcaps = array();
190
- foreach ( (array) $this->roles as $role ) {
191
- $role = $wp_roles->get_role( $role );
192
- $this->allcaps = array_merge( (array) $this->allcaps, (array) $role->capabilities );
193
- }
194
- $this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );
195
- }
196
-
197
- /**
198
- * Add role to user.
199
- *
200
- * Updates the user's meta data option with capabilities and roles.
201
- *
202
- * @since 2.0.0
203
- * @access public
204
- *
205
- * @param string $role Role name.
206
- */
207
- function add_role( $role ) {
208
- $this->caps[$role] = true;
209
- $this->update_user();
210
- }
211
-
212
- /**
213
- * Remove role from user.
214
- *
215
- * @since 2.0.0
216
- * @access public
217
- *
218
- * @param string $role Role name.
219
- */
220
- function remove_role( $role ) {
221
- if ( empty( $this->caps[$role] ) || ( count( $this->caps ) <= 1 ) )
222
- return;
223
- unset( $this->caps[$role] );
224
- $this->update_user();
225
- }
226
-
227
- /**
228
- * Set the role of the user.
229
- *
230
- * This will remove the previous roles of the user and assign the user the
231
- * new one. You can set the role to an empty string and it will remove all
232
- * of the roles from the user.
233
- *
234
- * @since 2.0.0
235
- * @access public
236
- *
237
- * @param string $role Role name.
238
- */
239
- function set_role( $role ) {
240
- foreach ( (array) $this->roles as $oldrole )
241
- unset( $this->caps[$oldrole] );
242
- if ( !empty( $role ) ) {
243
- $this->caps[$role] = true;
244
- $this->roles = array( $role => true );
245
- } else {
246
- $this->roles = false;
247
- }
248
- $this->update_user();
249
- }
250
-
251
- function update_user() {
252
- global $wp_users_object;
253
- $wp_users_object->update_meta( array( 'id' => $this->ID, 'meta_key' => $this->cap_key, 'meta_value' => $this->caps ) );
254
- $this->get_role_caps();
255
- //$this->update_user_level_from_caps(); // WP
256
- }
257
-
258
- /**
259
- * Choose the maximum level the user has.
260
- *
261
- * Will compare the level from the $item parameter against the $max
262
- * parameter. If the item is incorrect, then just the $max parameter value
263
- * will be returned.
264
- *
265
- * Used to get the max level based on the capabilities the user has. This
266
- * is also based on roles, so if the user is assigned the Administrator role
267
- * then the capability 'level_10' will exist and the user will get that
268
- * value.
269
- *
270
- * @since 2.0.0
271
- * @access public
272
- *
273
- * @param int $max Max level of user.
274
- * @param string $item Level capability name.
275
- * @return int Max Level.
276
- */
277
- /*
278
- function level_reduction( $max, $item ) {
279
- if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) {
280
- $level = intval( $matches[1] );
281
- return max( $max, $level );
282
- } else {
283
- return $max;
284
- }
285
- }
286
- */
287
-
288
- /**
289
- * Update the maximum user level for the user.
290
- *
291
- * Updates the 'user_level' user metadata (includes prefix that is the
292
- * database table prefix) with the maximum user level. Gets the value from
293
- * the all of the capabilities that the user has.
294
- *
295
- * @since 2.0.0
296
- * @access public
297
- */
298
- /*
299
- function update_user_level_from_caps() {
300
- global $wp_users_object;
301
- $this->user_level = array_reduce( array_keys( $this->allcaps ), array( &$this, 'level_reduction' ), 0 );
302
- update_usermeta( $this->ID, $wpdb->prefix.'user_level', $this->user_level );
303
- }
304
- */
305
-
306
- /*
307
- function translate_level_to_cap($level) {
308
- return 'level_' . $level;
309
- }
310
- */
311
-
312
- /**
313
- * Add capability and grant or deny access to capability.
314
- *
315
- * @since 2.0.0
316
- * @access public
317
- *
318
- * @param string $cap Capability name.
319
- * @param bool $grant Whether to grant capability to user.
320
- */
321
- function add_cap( $cap, $grant = true ) {
322
- $this->caps[$cap] = $grant;
323
- $this->update_user();
324
- }
325
-
326
- /**
327
- * Remove capability from user.
328
- *
329
- * @since 2.0.0
330
- * @access public
331
- *
332
- * @param string $cap Capability name.
333
- */
334
- function remove_cap( $cap ) {
335
- if ( empty( $this->caps[$cap] ) ) return;
336
- unset( $this->caps[$cap] );
337
- $this->update_user();
338
- }
339
-
340
- /**
341
- * Remove all of the capabilities of the user.
342
- *
343
- * @since 2.1.0
344
- * @access public
345
- */
346
- function remove_all_caps() {
347
- global $wp_users_object;
348
- $this->caps = array();
349
- $wp_users_object->delete_meta( $this->ID, $this->cap_key );
350
- $this->get_role_caps();
351
- }
352
-
353
- /**
354
- * Whether user has capability or role name.
355
- *
356
- * This is useful for looking up whether the user has a specific role
357
- * assigned to the user. The second optional parameter can also be used to
358
- * check for capabilities against a specfic post.
359
- *
360
- * @since 2.0.0
361
- * @access public
362
- *
363
- * @param string|int $cap Capability or role name to search.
364
- * @param int $post_id Optional. Post ID to check capability against specific post.
365
- * @return bool True, if user has capability; false, if user does not have capability.
366
- */
367
- function has_cap( $cap ) {
368
- global $wp_roles;
369
-
370
- if ( is_numeric( $cap ) )
371
- $cap = $this->translate_level_to_cap( $cap );
372
-
373
- $args = array_slice( func_get_args(), 1 );
374
- $args = array_merge( array( $cap, $this->ID ), $args );
375
- $caps = call_user_func_array( array(&$wp_roles, 'map_meta_cap'), $args );
376
- // Must have ALL requested caps
377
- $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args );
378
- foreach ( (array) $caps as $cap ) {
379
- //echo "Checking cap $cap<br />";
380
- if ( empty( $capabilities[$cap] ) || !$capabilities[$cap] )
381
- return false;
382
- }
383
-
384
- return true;
385
- }
386
-
387
- /**
388
- * Convert numeric level to level capability name.
389
- *
390
- * Prepends 'level_' to level number.
391
- *
392
- * @since 2.0.0
393
- * @access public
394
- *
395
- * @param int $level Level number, 1 to 10.
396
- * @return string
397
- */
398
- function translate_level_to_cap( $level ) {
399
- return 'level_' . $level;
400
- }
401
-
402
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.bpdb-multi.php DELETED
@@ -1,196 +0,0 @@
1
- <?php
2
- // backPress Multi DB Class
3
-
4
- // ORIGINAL CODE FROM:
5
- // Justin Vincent (justin@visunet.ie)
6
- // http://php.justinvincent.com
7
-
8
- require( BACKPRESS_PATH . 'class.bpdb.php' );
9
-
10
- class BPDB_Multi extends BPDB {
11
- /**
12
- * Associative array (dbhname => dbh) for established mysql connections
13
- * @var array
14
- */
15
- var $dbhs = array();
16
-
17
- var $_force_dbhname = false;
18
- var $last_table = '';
19
- var $db_tables = array();
20
- var $db_servers = array();
21
-
22
- // function BPDB_Multi() {} // Not used - rely on PHP4 constructor from BPDB to call BPDB_Multi::__construct
23
-
24
- function __construct() {
25
- $args = func_get_args();
26
- $args = call_user_func_array( array(&$this, '_init'), $args );
27
-
28
- if ( $args['host'] ) {
29
- $this->db_servers['dbh_global'] = $args;
30
- $this->db_connect( '/* */' );
31
- }
32
- }
33
-
34
- /**
35
- * Figure out which database server should handle the query, and connect to it.
36
- * @param string query
37
- * @return resource mysql database connection
38
- */
39
- function &db_connect( $query = '' ) {
40
- $false = false;
41
- if ( empty( $query ) )
42
- return $false;
43
-
44
- $this->last_table = $table = $this->get_table_from_query( $query );
45
-
46
- // We can attempt to force the connection identifier in use
47
- if ( $this->_force_dbhname && isset($this->db_servers[$this->_force_dbhname]) )
48
- $dbhname = $this->_force_dbhname;
49
-
50
- if ( !isset($dbhname) ) {
51
- if ( isset( $this->db_tables[$table] ) )
52
- $dbhname = $this->db_tables[$table];
53
- else
54
- $dbhname = 'dbh_global';
55
- }
56
-
57
- if ( !isset($this->db_servers[$dbhname]) )
58
- return $false;
59
-
60
- if ( isset($this->dbhs[$dbhname]) && is_resource($this->dbhs[$dbhname]) ) // We're already connected!
61
- return $this->dbhs[$dbhname];
62
-
63
- $success = $this->db_connect_host( $this->db_servers[$dbhname] );
64
-
65
- if ( $success && is_resource($this->dbh) ) {
66
- $this->dbhs[$dbhname] =& $this->dbh;
67
- } else {
68
- unset($this->dbhs[$dbhname]);
69
- unset($this->dbh);
70
- return $false;
71
- }
72
-
73
- return $this->dbhs[$dbhname];
74
- }
75
-
76
- /**
77
- * Sets the prefix of the database tables
78
- * @param string prefix
79
- * @param false|array tables (optional: false)
80
- * table identifiers are array keys
81
- * array values
82
- * empty: set prefix: array( 'posts' => false, 'users' => false, ... )
83
- * string: set to that array value: array( 'posts' => 'my_posts', 'users' => 'my_users' )
84
- * array: array[0] is DB identifier, array[1] is table name: array( 'posts' => array( 'global', 'my_posts' ), 'users' => array( 'users', 'my_users' ) )
85
- * OR array values (with numeric keys): array( 'posts', 'users', ... )
86
- *
87
- * @return string the previous prefix (mostly only meaningful if all $table parameter was false)
88
- */
89
- function set_prefix( $prefix, $tables = false ) {
90
- $old_prefix = parent::set_prefix( $prefix, $tables );
91
- if ( !$old_prefix || is_wp_error($old_prefix) ) {
92
- return $old_prefix;
93
- }
94
-
95
- if ( $tables && is_array($tables) ) {
96
- $_tables = $tables;
97
- } else {
98
- $_tables = $this->tables;
99
- }
100
-
101
- foreach ( $_tables as $key => $value ) {
102
- // array( 'posts' => array( 'global', 'my_posts' ), 'users' => array( 'users', 'my_users' ) )
103
- if ( is_array($value) && isset($this->db_servers['dbh_' . $value[0]]) ) {
104
- $this->add_db_table( $value[0], $value[1] );
105
- $this->$key = $value[1];
106
- }
107
- }
108
-
109
- return $old_prefix;
110
- }
111
-
112
- /**
113
- * Find the first table name referenced in a query
114
- * @param string query
115
- * @return string table
116
- */
117
- function get_table_from_query ( $q ) {
118
- // Remove characters that can legally trail the table name
119
- rtrim($q, ';/-#');
120
-
121
- // Quickly match most common queries
122
- if ( preg_match('/^\s*(?:'
123
- . 'SELECT.*?\s+FROM'
124
- . '|INSERT(?:\s+IGNORE)?(?:\s+INTO)?'
125
- . '|REPLACE(?:\s+INTO)?'
126
- . '|UPDATE(?:\s+IGNORE)?'
127
- . '|DELETE(?:\s+IGNORE)?(?:\s+FROM)?'
128
- . ')\s+`?(\w+)`?/is', $q, $maybe) )
129
- return $maybe[1];
130
-
131
- // Refer to the previous query
132
- if ( preg_match('/^\s*SELECT.*?\s+FOUND_ROWS\(\)/is', $q) )
133
- return $this->last_table;
134
-
135
- // Big pattern for the rest of the table-related queries in MySQL 5.0
136
- if ( preg_match('/^\s*(?:'
137
- . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
138
- . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
139
- . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
140
- . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
141
- . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:\s+FROM)?'
142
- . '|DESCRIBE|DESC|EXPLAIN|HANDLER'
143
- . '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?'
144
- . '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|OPTIMIZE|REPAIR).*\s+TABLE'
145
- . '|TRUNCATE(?:\s+TABLE)?'
146
- . '|CREATE(?:\s+TEMPORARY)?\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?'
147
- . '|ALTER(?:\s+IGNORE)?'
148
- . '|DROP\s+TABLE(?:\s+IF\s+EXISTS)?'
149
- . '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
150
- . '|DROP\s+INDEX.*\s+ON'
151
- . '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
152
- . '|(?:GRANT|REVOKE).*ON\s+TABLE'
153
- . '|SHOW\s+(?:.*FROM|.*TABLE)'
154
- . ')\s+`?(\w+)`?/is', $q, $maybe) )
155
- return $maybe[1];
156
-
157
- // All unmatched queries automatically fall to the global master
158
- return '';
159
- }
160
-
161
- /**
162
- * Add a database server's information. Does not automatically connect.
163
- * @param string $ds Dataset: the name of the dataset.
164
- * @param array $args
165
- * name => string DB name (required)
166
- * user => string DB user (optional: false)
167
- * password => string DB user password (optional: false)
168
- * host => string DB hostname (optional: 'localhost')
169
- * charset => string DB default charset. Used in a SET NAMES query. (optional)
170
- * collate => string DB default collation. If charset supplied, optionally added to the SET NAMES query (optional)
171
- */
172
- function add_db_server( $ds, $args = null ) {
173
- $defaults = array(
174
- 'user' => false,
175
- 'password' => false,
176
- 'name' => false,
177
- 'host' => 'localhost',
178
- 'charset' => false,
179
- 'collate' => false
180
- );
181
-
182
- $args = wp_parse_args( $args, $defaults );
183
- $args['ds'] = 'dbh_' . $ds;
184
-
185
- $this->db_servers['dbh_' . $ds] = $args;
186
- }
187
-
188
- /**
189
- * Maps a table to a dataset.
190
- * @param string $ds Dataset: the name of the dataset.
191
- * @param string $table
192
- */
193
- function add_db_table( $ds, $table ) {
194
- $this->db_tables[$table] = 'dbh_' . $ds;
195
- }
196
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.bpdb.php DELETED
@@ -1,1164 +0,0 @@
1
- <?php
2
- // backPress DB Class
3
-
4
- // ORIGINAL CODE FROM:
5
- // Justin Vincent (justin@visunet.ie)
6
- // http://php.justinvincent.com
7
-
8
- define( 'EZSQL_VERSION', 'BP1.25' );
9
- define( 'OBJECT', 'OBJECT', true );
10
- define( 'OBJECT_K', 'OBJECT_K', false );
11
- define( 'ARRAY_A', 'ARRAY_A', false );
12
- define( 'ARRAY_K', 'ARRAY_K', false );
13
- define( 'ARRAY_N', 'ARRAY_N', false );
14
-
15
- if ( !defined( 'SAVEQUERIES' ) ) {
16
- define( 'SAVEQUERIES', false );
17
- }
18
-
19
- if ( !defined( 'BPDB__ERROR_STRING' ) ) {
20
- define( 'BPDB__ERROR_STRING', 'DB Error: %s, %s: %s' );
21
- }
22
- if ( !defined( 'BPDB__ERROR_HTML' ) ) {
23
- define( 'BPDB__ERROR_HTML', '<div class="error"><p><strong>DB Error in %3$s:</strong> %1$s</p><pre>%2$s</pre></div>' );
24
- }
25
- if ( !defined( 'BPDB__CONNECT_ERROR_MESSAGE' ) ) {
26
- define( 'BPDB__CONNECT_ERROR_MESSAGE', 'DB Error: cannot connect' );
27
- }
28
- if ( !defined( 'BPDB__SELECT_ERROR_MESSAGE' ) ) {
29
- define( 'BPDB__SELECT_ERROR_MESSAGE', 'DB Error: cannot select' );
30
- }
31
- if ( !defined( 'BPDB__DB_VERSION_ERROR' ) ) {
32
- define( 'BPDB__DB_VERSION_ERROR', 'DB Requires MySQL version 4.0 or higher' );
33
- }
34
- if ( !defined( 'BPDB__PHP_EXTENSION_MISSING' ) ) {
35
- define( 'BPDB__PHP_EXTENSION_MISSING', 'DB Requires The MySQL PHP extension' );
36
- }
37
-
38
- class BPDB
39
- {
40
- /**
41
- * Whether to show SQL/DB errors
42
- *
43
- * @since 1.0
44
- * @access private
45
- * @var bool
46
- */
47
- var $show_errors = false;
48
-
49
- /**
50
- * Whether to suppress errors during the DB bootstrapping.
51
- *
52
- * @access private
53
- * @since 1.0
54
- * @var bool
55
- */
56
- var $suppress_errors = false;
57
-
58
- /**
59
- * The last error during query.
60
- *
61
- * @since 1.0
62
- * @var string
63
- */
64
- var $last_error = '';
65
-
66
- /**
67
- * Amount of queries made
68
- *
69
- * @since 1.0
70
- * @access private
71
- * @var int
72
- */
73
- var $num_queries = 0;
74
-
75
- /**
76
- * The last query made
77
- *
78
- * @since 1.0
79
- * @access private
80
- * @var string
81
- */
82
- var $last_query = null;
83
-
84
- /**
85
- * Saved info on the table column
86
- *
87
- * @since 1.0
88
- * @access private
89
- * @var array
90
- */
91
- var $col_info = array();
92
-
93
- /**
94
- * Saved queries that were executed
95
- *
96
- * @since 1.0
97
- * @access private
98
- * @var array
99
- */
100
- var $queries = array();
101
-
102
- /**
103
- * Whether to use the query log
104
- *
105
- * @since 1.0
106
- * @access private
107
- * @var bool
108
- */
109
- var $save_queries = false;
110
-
111
- /**
112
- * Table prefix
113
- *
114
- * You can set this to have multiple installations
115
- * in a single database. The second reason is for possible
116
- * security precautions.
117
- *
118
- * @since 1.0
119
- * @access private
120
- * @var string
121
- */
122
- var $prefix = '';
123
-
124
- /**
125
- * Whether the database queries are ready to start executing.
126
- *
127
- * @since 1.0
128
- * @access private
129
- * @var bool
130
- */
131
- var $ready = false;
132
-
133
- /**
134
- * The currently connected MySQL connection resource.
135
- *
136
- * @since 1.0
137
- * @access private
138
- * @var bool|resource
139
- */
140
- var $dbh = false;
141
-
142
- /**
143
- * List of tables
144
- *
145
- * @since 1.0
146
- * @access private
147
- * @var array
148
- */
149
- var $tables = array();
150
-
151
- /**
152
- * Whether to use mysql_real_escape_string
153
- *
154
- * @since 1.0
155
- * @access public
156
- * @var bool
157
- */
158
- var $real_escape = false;
159
-
160
- /**
161
- * PHP4 style constructor
162
- *
163
- * @since 1.0
164
- *
165
- * @return unknown Returns the result of bpdb::__construct()
166
- */
167
- function BPDB()
168
- {
169
- $args = func_get_args();
170
- register_shutdown_function( array( &$this, '__destruct' ) );
171
- return call_user_func_array( array( &$this, '__construct' ), $args );
172
- }
173
-
174
- /**
175
- * PHP5 style constructor
176
- *
177
- * Grabs the arguments, calls bpdb::_init() and then connects to the database
178
- *
179
- * @since 1.0
180
- *
181
- * @return void
182
- */
183
- function __construct()
184
- {
185
- $args = func_get_args();
186
- $args = call_user_func_array( array( &$this, '_init' ), $args );
187
-
188
- $this->db_connect_host( $args );
189
- }
190
-
191
- /**
192
- * Initialises the class variables based on provided arguments
193
- *
194
- * @since 1.0
195
- *
196
- * @param array $args The provided connection settings
197
- * @return array The current connection settings after processing by init
198
- */
199
- function _init( $args )
200
- {
201
- if ( !extension_loaded( 'mysql' ) ) {
202
- $this->show_errors();
203
- $this->bail( BPDB__PHP_EXTENSION_MISSING );
204
- return;
205
- }
206
-
207
- if ( 4 == func_num_args() ) {
208
- $args = array(
209
- 'user' => $args,
210
- 'password' => func_get_arg( 1 ),
211
- 'name' => func_get_arg( 2 ),
212
- 'host' => func_get_arg( 3 )
213
- );
214
- }
215
-
216
- $defaults = array(
217
- 'user' => false,
218
- 'password' => false,
219
- 'name' => false,
220
- 'host' => 'localhost',
221
- 'charset' => false,
222
- 'collate' => false,
223
- 'errors' => false
224
- );
225
-
226
- $args = wp_parse_args( $args, $defaults );
227
-
228
- switch ( $args['errors'] ) {
229
- case 'show' :
230
- $this->show_errors( true );
231
- break;
232
- case 'suppress' :
233
- $this->suppress_errors( true );
234
- break;
235
- }
236
-
237
- return $args;
238
- }
239
-
240
- /**
241
- * PHP5 style destructor, registered as shutdown function in PHP4
242
- *
243
- * @since 1.0
244
- *
245
- * @return bool Always returns true
246
- */
247
- function __destruct()
248
- {
249
- return true;
250
- }
251
-
252
- /**
253
- * Figure out which database server should handle the query, and connect to it.
254
- *
255
- * @since 1.0
256
- *
257
- * @param string query
258
- * @return resource mysql database connection
259
- */
260
- function &db_connect( $query = '' )
261
- {
262
- $false = false;
263
- if ( empty( $query ) ) {
264
- return $false;
265
- }
266
- return $this->dbh;
267
- }
268
-
269
- /**
270
- * Connects to the database server and selects a database
271
- *
272
- * @since 1.0
273
- *
274
- * @param array args
275
- * name => string DB name (required)
276
- * user => string DB user (optional: false)
277
- * password => string DB user password (optional: false)
278
- * host => string DB hostname (optional: 'localhost')
279
- * charset => string DB default charset. Used in a SET NAMES query. (optional)
280
- * collate => string DB default collation. If charset supplied, optionally added to the SET NAMES query (optional)
281
- * @return void|bool void if cannot connect, false if cannot select, true if success
282
- */
283
- function db_connect_host( $args )
284
- {
285
- extract( $args, EXTR_SKIP );
286
-
287
- unset( $this->dbh ); // De-reference before re-assigning
288
- $this->dbh = @mysql_connect( $host, $user, $password, true );
289
-
290
- if ( !$this->dbh ) {
291
- if ( !$this->suppress_errors ) {
292
- $this->show_errors();
293
- }
294
- $this->bail( BPDB__CONNECT_ERROR_MESSAGE );
295
- return;
296
- }
297
-
298
- $this->ready = true;
299
-
300
- if ( $this->has_cap( 'collation' ) ) {
301
- if ( !empty( $charset ) ) {
302
- if ( function_exists( 'mysql_set_charset' ) ) {
303
- mysql_set_charset( $charset, $this->dbh );
304
- $this->real_escape = true;
305
- } else {
306
- $collation_query = "SET NAMES '{$charset}'";
307
- if ( !empty( $collate ) ) {
308
- $collation_query .= " COLLATE '{$collate}'";
309
- }
310
- $this->query( $collation_query, true );
311
- }
312
- }
313
- }
314
-
315
- return $this->select( $name, $this->dbh );
316
- }
317
-
318
- /**
319
- * Sets the table prefix for the WordPress tables.
320
- *
321
- * @since 1.0
322
- *
323
- * @param string prefix
324
- * @param false|array tables (optional: false)
325
- * table identifiers are array keys
326
- * array values
327
- * empty: set prefix: array( 'posts' => false, 'users' => false, ... )
328
- * string: set to that array value: array( 'posts' => 'my_posts', 'users' => 'my_users' )
329
- * OR array values (with numeric keys): array( 'posts', 'users', ... )
330
- *
331
- * @return string the previous prefix (mostly only meaningful if all $table parameter was false)
332
- */
333
- function set_prefix( $prefix, $tables = false )
334
- {
335
- if ( !$prefix ) {
336
- return false;
337
- }
338
- if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) {
339
- return new WP_Error( 'invalid_db_prefix', 'Invalid database prefix' ); // No gettext here
340
- }
341
-
342
- $old_prefix = $this->prefix;
343
-
344
- if ( $tables && is_array( $tables ) ) {
345
- $_tables =& $tables;
346
- } else {
347
- $_tables =& $this->tables;
348
- $this->prefix = $prefix;
349
- }
350
-
351
- foreach ( $_tables as $key => $value ) {
352
- if ( is_numeric( $key ) ) { // array( 'posts', 'users', ... )
353
- $this->$value = $prefix . $value;
354
- } elseif ( !$value ) {
355
- $this->$key = $prefix . $key; // array( 'posts' => false, 'users' => false, ... )
356
- } elseif ( is_string( $value ) ) { // array( 'posts' => 'my_posts', 'users' => 'my_users' )
357
- $this->$key = $value;
358
- }
359
- }
360
-
361
- return $old_prefix;
362
- }
363
-
364
- /**
365
- * Selects a database using the current database connection.
366
- *
367
- * The database name will be changed based on the current database
368
- * connection. On failure, the execution will bail and display an DB error.
369
- *
370
- * @since 1.0
371
- *
372
- * @param string $db MySQL database name
373
- * @return bool True on success, false on failure.
374
- */
375
- function select( $db, &$dbh )
376
- {
377
- if ( !@mysql_select_db( $db, $dbh ) ) {
378
- $this->ready = false;
379
- $this->show_errors();
380
- $this->bail( BPDB__SELECT_ERROR_MESSAGE );
381
- return false;
382
- }
383
- return true;
384
- }
385
-
386
- function _weak_escape( $string )
387
- {
388
- return addslashes( $string );
389
- }
390
-
391
- function _real_escape( $string )
392
- {
393
- if ( $this->dbh && $this->real_escape ) {
394
- return mysql_real_escape_string( $string, $this->dbh );
395
- } else {
396
- return addslashes( $string );
397
- }
398
- }
399
-
400
- function _escape( $data )
401
- {
402
- if ( is_array( $data ) ) {
403
- foreach ( (array) $data as $k => $v ) {
404
- if ( is_array( $v ) ) {
405
- $data[$k] = $this->_escape( $v );
406
- } else {
407
- $data[$k] = $this->_real_escape( $v );
408
- }
409
- }
410
- } else {
411
- $data = $this->_real_escape( $data );
412
- }
413
-
414
- return $data;
415
- }
416
-
417
- /**
418
- * Escapes content for insertion into the database using addslashes(), for security
419
- *
420
- * @since 1.0
421
- *
422
- * @param string|array $data
423
- * @return string query safe string
424
- */
425
- function escape( $data )
426
- {
427
- if ( is_array( $data ) ) {
428
- foreach ( (array) $data as $k => $v ) {
429
- if ( is_array( $v ) ) {
430
- $data[$k] = $this->escape( $v );
431
- } else {
432
- $data[$k] = $this->_weak_escape( $v );
433
- }
434
- }
435
- } else {
436
- $data = $this->_weak_escape( $data );
437
- }
438
-
439
- return $data;
440
- }
441
-
442
- /**
443
- * Escapes content by reference for insertion into the database, for security
444
- *
445
- * @since 1.0
446
- *
447
- * @param string $s
448
- */
449
- function escape_by_ref( &$string )
450
- {
451
- $string = $this->_real_escape( $string );
452
- }
453
-
454
- /**
455
- * Escapes array recursively for insertion into the database, for security
456
- * @param array $array
457
- */
458
- function escape_deep( $array )
459
- {
460
- return $this->_escape( $array );
461
- }
462
-
463
- /**
464
- * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
465
- *
466
- * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string).
467
- * Does not support sign, padding, alignment, width or precision specifiers.
468
- * Does not support argument numbering/swapping.
469
- *
470
- * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
471
- *
472
- * Both %d and %s should be left unquoted in the query string.
473
- *
474
- * <code>
475
- * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 )
476
- * </code>
477
- *
478
- * @link http://php.net/sprintf Description of syntax.
479
- * @since 1.0
480
- *
481
- * @param string $query Query statement with sprintf()-like placeholders
482
- * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
483
- * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
484
- * @return null|string Sanitized query string
485
- */
486
- function prepare( $query = null ) // ( $query, *$args )
487
- {
488
- if ( is_null( $query ) ) {
489
- return;
490
- }
491
- $args = func_get_args();
492
- array_shift( $args );
493
- // If args were passed as an array (as in vsprintf), move them up
494
- if ( isset( $args[0] ) && is_array( $args[0] ) ) {
495
- $args = $args[0];
496
- }
497
- $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
498
- $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
499
- $query = str_replace( '%s', "'%s'", $query ); // quote the strings
500
- array_walk( $args, array( &$this, 'escape_by_ref' ) );
501
- return @vsprintf( $query, $args );
502
- }
503
-
504
- /**
505
- * Get SQL/DB error
506
- *
507
- * @since 1.0
508
- *
509
- * @param string $str Error string
510
- */
511
- function get_error( $str = '' )
512
- {
513
- if ( empty( $str ) ) {
514
- if ( $this->last_error ) {
515
- $str = $this->last_error;
516
- } else {
517
- return false;
518
- }
519
- }
520
-
521
- $caller = $this->get_caller();
522
- $error_str = sprintf( BPDB__ERROR_STRING, $str, $this->last_query, $caller );
523
-
524
- if ( class_exists( 'WP_Error' ) ) {
525
- return new WP_Error( 'db_query', $error_str, array( 'query' => $this->last_query, 'error' => $str, 'caller' => $caller ) );
526
- } else {
527
- return array( 'query' => $this->last_query, 'error' => $str, 'caller' => $caller, 'error_str' => $error_str );
528
- }
529
- }
530
-
531
- /**
532
- * Print SQL/DB error.
533
- *
534
- * @since 1.0
535
- *
536
- * @param string $str The error to display
537
- * @return bool False if the showing of errors is disabled.
538
- */
539
- function print_error( $str = '' )
540
- {
541
- if ( $this->suppress_errors ) {
542
- return false;
543
- }
544
-
545
- $error = $this->get_error( $str );
546
- if ( is_object( $error ) && is_a( $error, 'WP_Error' ) ) {
547
- $err = $error->get_error_data();
548
- $err['error_str'] = $error->get_error_message();
549
- } else {
550
- $err =& $error;
551
- }
552
-
553
- $log_file = ini_get( 'error_log' );
554
- if ( !empty( $log_file ) && ( 'syslog' != $log_file ) && is_writable( $log_file ) && function_exists( 'error_log' ) ) {
555
- error_log($err['error_str'], 0);
556
- }
557
-
558
- // Is error output turned on or not
559
- if ( !$this->show_errors ) {
560
- return false;
561
- }
562
-
563
- $str = htmlspecialchars( $err['error'], ENT_QUOTES );
564
- $query = htmlspecialchars( $err['query'], ENT_QUOTES );
565
- $caller = htmlspecialchars( $err['caller'], ENT_QUOTES );
566
-
567
- // If there is an error then take note of it
568
-
569
- printf( BPDB__ERROR_HTML, $str, $query, $caller );
570
- }
571
-
572
- /**
573
- * Enables showing of database errors.
574
- *
575
- * This function should be used only to enable showing of errors.
576
- * bpdb::hide_errors() should be used instead for hiding of errors. However,
577
- * this function can be used to enable and disable showing of database
578
- * errors.
579
- *
580
- * @since 1.0
581
- *
582
- * @param bool $show Whether to show or hide errors
583
- * @return bool Old value for showing errors.
584
- */
585
- function show_errors( $show = true )
586
- {
587
- $errors = $this->show_errors;
588
- $this->show_errors = $show;
589
- return $errors;
590
- }
591
-
592
- /**
593
- * Disables showing of database errors.
594
- *
595
- * @since 1.0
596
- *
597
- * @return bool Whether showing of errors was active or not
598
- */
599
- function hide_errors()
600
- {
601
- return $this->show_errors( false );
602
- }
603
-
604
- /**
605
- * Whether to suppress database errors.
606
- *
607
- * @since 1.0
608
- *
609
- * @param bool $suppress
610
- * @return bool previous setting
611
- */
612
- function suppress_errors( $suppress = true )
613
- {
614
- $errors = $this->suppress_errors;
615
- $this->suppress_errors = $suppress;
616
- return $errors;
617
- }
618
-
619
- /**
620
- * Kill cached query results.
621
- *
622
- * @since 1.0
623
- */
624
- function flush()
625
- {
626
- $this->last_result = array();
627
- $this->col_info = array();
628
- $this->last_query = null;
629
- $this->last_error = '';
630
- $this->num_rows = 0;
631
- }
632
-
633
- /**
634
- * Perform a MySQL database query, using current database connection.
635
- *
636
- * More information can be found on the codex page.
637
- *
638
- * @since 1.0
639
- *
640
- * @param string $query
641
- * @return int|false Number of rows affected/selected or false on error
642
- */
643
- function query( $query, $use_current = false )
644
- {
645
- if ( !$this->ready ) {
646
- return false;
647
- }
648
-
649
- // filter the query, if filters are available
650
- // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
651
- if ( function_exists( 'apply_filters' ) ) {
652
- $query = apply_filters( 'query', $query );
653
- }
654
-
655
- // initialise return
656
- $return_val = 0;
657
- $this->flush();
658
-
659
- // Log how the function was called
660
- $this->func_call = "\$db->query(\"$query\")";
661
-
662
- // Keep track of the last query for debug..
663
- $this->last_query = $query;
664
-
665
- // Perform the query via std mysql_query function..
666
- if ( SAVEQUERIES ) {
667
- $this->timer_start();
668
- }
669
-
670
- if ( $use_current ) {
671
- $dbh =& $this->dbh;
672
- } else {
673
- $dbh = $this->db_connect( $query );
674
- }
675
-
676
- $this->result = @mysql_query( $query, $dbh );
677
- ++$this->num_queries;
678
-
679
- if ( SAVEQUERIES ) {
680
- $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
681
- }
682
-
683
- // If there is an error then take note of it..
684
- if ( $this->last_error = mysql_error( $dbh ) ) {
685
- return $this->print_error( $this->last_error );
686
- }
687
-
688
- if ( preg_match( "/^\\s*(insert|delete|update|replace|alter) /i", $query ) ) {
689
- $this->rows_affected = mysql_affected_rows( $dbh );
690
- // Take note of the insert_id
691
- if ( preg_match( "/^\\s*(insert|replace) /i", $query ) ) {
692
- $this->insert_id = mysql_insert_id( $dbh );
693
- }
694
- // Return number of rows affected
695
- $return_val = $this->rows_affected;
696
- } else {
697
- $i = 0;
698
- while ( $i < @mysql_num_fields( $this->result ) ) {
699
- $this->col_info[$i] = @mysql_fetch_field( $this->result );
700
- $i++;
701
- }
702
- $num_rows = 0;
703
- while ( $row = @mysql_fetch_object( $this->result ) ) {
704
- $this->last_result[$num_rows] = $row;
705
- $num_rows++;
706
- }
707
-
708
- @mysql_free_result( $this->result );
709
-
710
- // Log number of rows the query returned
711
- $this->num_rows = $num_rows;
712
-
713
- // Return number of rows selected
714
- $return_val = $this->num_rows;
715
- }
716
-
717
- return $return_val;
718
- }
719
-
720
- /**
721
- * Insert a row into a table.
722
- *
723
- * <code>
724
- * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
725
- * </code>
726
- *
727
- * @since 1.0
728
- * @see bpdb::prepare()
729
- *
730
- * @param string $table table name
731
- * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
732
- * @param array|string $format (optional) An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $data will be treated as strings.
733
- * @return int|false The number of rows inserted, or false on error.
734
- */
735
- function insert( $table, $data, $format = null )
736
- {
737
- $formats = $format = (array) $format;
738
- $fields = array_keys( $data );
739
- $formatted_fields = array();
740
- foreach ( $fields as $field ) {
741
- if ( !empty( $format ) ) {
742
- $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
743
- } elseif ( isset( $this->field_types[$field] ) ) {
744
- $form = $this->field_types[$field];
745
- } elseif ( is_null( $data[$field] ) ) {
746
- $form = 'NULL';
747
- unset( $data[$field] );
748
- } else {
749
- $form = '%s';
750
- }
751
- $formatted_fields[] = $form;
752
- }
753
- $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")";
754
- return $this->query( $this->prepare( $sql, $data ) );
755
- }
756
-
757
- /**
758
- * Update a row in the table
759
- *
760
- * <code>
761
- * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
762
- * </code>
763
- *
764
- * @since 1.0
765
- * @see bpdb::prepare()
766
- *
767
- * @param string $table table name
768
- * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
769
- * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw".
770
- * @param array|string $format (optional) An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $data will be treated as strings.
771
- * @param array|string $format_where (optional) An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $where will be treated as strings.
772
- * @return int|false The number of rows updated, or false on error.
773
- */
774
- function update( $table, $data, $where, $format = null, $where_format = null )
775
- {
776
- if ( !is_array( $where ) ) {
777
- return false;
778
- }
779
-
780
- $formats = $format = (array) $format;
781
- $bits = $wheres = array();
782
- foreach ( (array) array_keys( $data ) as $field ) {
783
- if ( !empty( $format ) ) {
784
- $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
785
- } elseif ( isset( $this->field_types[$field] ) ) {
786
- $form = $this->field_types[$field];
787
- } elseif ( is_null( $data[$field] ) ) {
788
- $form = 'NULL';
789
- unset( $data[$field] );
790
- } else {
791
- $form = '%s';
792
- }
793
- $bits[] = "`$field` = {$form}";
794
- }
795
-
796
- $where_formats = $where_format = (array) $where_format;
797
- foreach ( (array) array_keys( $where ) as $field ) {
798
- if ( !empty( $where_format ) ) {
799
- $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
800
- } elseif ( isset( $this->field_types[$field] ) ) {
801
- $form = $this->field_types[$field];
802
- } elseif ( is_null( $where[$field] ) ) {
803
- unset( $where[$field] );
804
- $wheres[] = "`$field` IS NULL";
805
- continue;
806
- } else {
807
- $form = '%s';
808
- }
809
- $wheres[] = "`$field` = {$form}";
810
- }
811
-
812
- $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
813
- return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) );
814
- }
815
-
816
- /**
817
- * Retrieve one variable from the database.
818
- *
819
- * Executes a SQL query and returns the value from the SQL result.
820
- * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified.
821
- * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
822
- *
823
- * @since 1.0
824
- *
825
- * @param string|null $query SQL query. If null, use the result from the previous query.
826
- * @param int $x (optional) Column of value to return. Indexed from 0.
827
- * @param int $y (optional) Row of value to return. Indexed from 0.
828
- * @return string Database query result
829
- */
830
- function get_var( $query=null, $x = 0, $y = 0 )
831
- {
832
- $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
833
- if ( $query ) {
834
- $this->query( $query );
835
- }
836
-
837
- // Extract var out of cached results based x,y vals
838
- if ( !empty( $this->last_result[$y] ) ) {
839
- $values = array_values( get_object_vars( $this->last_result[$y] ) );
840
- }
841
-
842
- // If there is a value return it else return null
843
- return ( isset($values[$x]) && $values[$x]!=='' ) ? $values[$x] : null;
844
- }
845
-
846
- /**
847
- * Retrieve one row from the database.
848
- *
849
- * Executes a SQL query and returns the row from the SQL result.
850
- *
851
- * @since 1.0
852
- *
853
- * @param string|null $query SQL query.
854
- * @param string $output (optional) one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...), a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively.
855
- * @param int $y (optional) Row to return. Indexed from 0.
856
- * @return mixed Database query result in format specifed by $output
857
- */
858
- function get_row( $query = null, $output = OBJECT, $y = 0 )
859
- {
860
- $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
861
- if ( $query ) {
862
- $this->query( $query );
863
- } else {
864
- return null;
865
- }
866
-
867
- if ( !isset( $this->last_result[$y] ) ) {
868
- return null;
869
- }
870
-
871
- if ( $output == OBJECT ) {
872
- return $this->last_result[$y] ? $this->last_result[$y] : null;
873
- } elseif ( $output == ARRAY_A ) {
874
- return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
875
- } elseif ( $output == ARRAY_N ) {
876
- return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
877
- } else {
878
- $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" );
879
- }
880
- }
881
-
882
- /**
883
- * Retrieve one column from the database.
884
- *
885
- * Executes a SQL query and returns the column from the SQL result.
886
- * If the SQL result contains more than one column, this function returns the column specified.
887
- * If $query is null, this function returns the specified column from the previous SQL result.
888
- *
889
- * @since 1.0
890
- *
891
- * @param string|null $query SQL query. If null, use the result from the previous query.
892
- * @param int $x Column to return. Indexed from 0.
893
- * @return array Database query result. Array indexed from 0 by SQL result row number.
894
- */
895
- function get_col( $query = null , $x = 0 )
896
- {
897
- if ( $query ) {
898
- $this->query( $query );
899
- }
900
-
901
- $new_array = array();
902
- // Extract the column values
903
- for ( $i=0; $i < count( $this->last_result ); $i++ ) {
904
- $new_array[$i] = $this->get_var( null, $x, $i );
905
- }
906
- return $new_array;
907
- }
908
-
909
- /**
910
- * Retrieve an entire SQL result set from the database (i.e., many rows)
911
- *
912
- * Executes a SQL query and returns the entire SQL result.
913
- *
914
- * @since 1.0
915
- *
916
- * @param string $query SQL query.
917
- * @param string $output (optional) ane of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K | ARRAY_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number. Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. With OBJECT_K and ARRAY_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded.
918
- * @return mixed Database query results
919
- */
920
- function get_results( $query = null, $output = OBJECT )
921
- {
922
- $this->func_call = "\$db->get_results(\"$query\", $output)";
923
-
924
- if ( $query ) {
925
- $this->query($query);
926
- } else {
927
- return null;
928
- }
929
-
930
- if ( $output == OBJECT ) {
931
- // Return an integer-keyed array of row objects
932
- return $this->last_result;
933
- } elseif ( $output == OBJECT_K || $output == ARRAY_K ) {
934
- // Return an array of row objects with keys from column 1
935
- // (Duplicates are discarded)
936
- $key = $this->col_info[0]->name;
937
- foreach ( $this->last_result as $row ) {
938
- if ( !isset( $new_array[ $row->$key ] ) ) {
939
- $new_array[ $row->$key ] = $row;
940
- }
941
- }
942
- if ( $output == ARRAY_K ) {
943
- return array_map( 'get_object_vars', $new_array );
944
- }
945
- return $new_array;
946
- } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
947
- // Return an integer-keyed array of...
948
- if ( $this->last_result ) {
949
- $i = 0;
950
- foreach( $this->last_result as $row ) {
951
- if ( $output == ARRAY_N ) {
952
- // ...integer-keyed row arrays
953
- $new_array[$i] = array_values( get_object_vars( $row ) );
954
- } else {
955
- // ...column name-keyed row arrays
956
- $new_array[$i] = get_object_vars( $row );
957
- }
958
- ++$i;
959
- }
960
- return $new_array;
961
- }
962
- }
963
- }
964
-
965
- /**
966
- * Retrieve column metadata from the last query.
967
- *
968
- * @since 1.0
969
- *
970
- * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
971
- * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
972
- * @return mixed Column Results
973
- */
974
- function get_col_info( $info_type = 'name', $col_offset = -1 )
975
- {
976
- if ( $this->col_info ) {
977
- if ( $col_offset == -1 ) {
978
- $i = 0;
979
- foreach( (array) $this->col_info as $col ) {
980
- $new_array[$i] = $col->{$info_type};
981
- $i++;
982
- }
983
- return $new_array;
984
- } else {
985
- return $this->col_info[$col_offset]->{$info_type};
986
- }
987
- }
988
- }
989
-
990
- /**
991
- * Starts the timer, for debugging purposes.
992
- *
993
- * @since 1.0
994
- *
995
- * @return true
996
- */
997
- function timer_start()
998
- {
999
- $mtime = microtime();
1000
- $mtime = explode( ' ', $mtime );
1001
- $this->time_start = $mtime[1] + $mtime[0];
1002
- return true;
1003
- }
1004
-
1005
- /**
1006
- * Stops the debugging timer.
1007
- *
1008
- * @since 1.0
1009
- *
1010
- * @return int Total time spent on the query, in milliseconds
1011
- */
1012
- function timer_stop()
1013
- {
1014
- $mtime = microtime();
1015
- $mtime = explode( ' ', $mtime );
1016
- $time_end = $mtime[1] + $mtime[0];
1017
- $time_total = $time_end - $this->time_start;
1018
- return $time_total;
1019
- }
1020
-
1021
- /**
1022
- * Wraps errors in a nice header and footer and dies.
1023
- *
1024
- * Will not die if bpdb::$show_errors is true
1025
- *
1026
- * @since 1.0
1027
- *
1028
- * @param string $message
1029
- * @return false|void
1030
- */
1031
- function bail( $message )
1032
- {
1033
- if ( !$this->show_errors ) {
1034
- if ( class_exists( 'WP_Error' ) )
1035
- $this->error = new WP_Error( '500', $message );
1036
- else
1037
- $this->error = $message;
1038
- return false;
1039
- }
1040
- backpress_die( $message );
1041
- }
1042
-
1043
- /**
1044
- * Whether or not MySQL database is at least the required minimum version.
1045
- *
1046
- * @since 1.0
1047
- *
1048
- * @return WP_Error
1049
- */
1050
- function check_database_version( $dbh_or_table = false )
1051
- {
1052
- // Make sure the server has MySQL 4.0
1053
- if ( version_compare( $this->db_version( $dbh_or_table ), '4.0.0', '<' ) ) {
1054
- return new WP_Error( 'database_version', BPDB__DB_VERSION_ERROR );
1055
- }
1056
- }
1057
-
1058
- /**
1059
- * Whether of not the database supports collation.
1060
- *
1061
- * Called when BackPress is generating the table scheme.
1062
- *
1063
- * @since 1.0
1064
- *
1065
- * @return bool True if collation is supported, false if version does not
1066
- */
1067
- function supports_collation()
1068
- {
1069
- return $this->has_cap( 'collation' );
1070
- }
1071
-
1072
- /**
1073
- * Generic function to determine if a database supports a particular feature
1074
- *
1075
- * @since 1.0
1076
- *
1077
- * @param string $db_cap the feature
1078
- * @param false|string|resource $dbh_or_table Which database to test. False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
1079
- * @return bool
1080
- */
1081
- function has_cap( $db_cap, $dbh_or_table = false )
1082
- {
1083
- $version = $this->db_version( $dbh_or_table );
1084
-
1085
- switch ( strtolower( $db_cap ) ) {
1086
- case 'collation' :
1087
- case 'group_concat' :
1088
- case 'subqueries' :
1089
- return version_compare( $version, '4.1', '>=' );
1090
- break;
1091
-
1092
- case 'index_hint_for_join' :
1093
- return version_compare( $version, '5.0', '>=' );
1094
- break;
1095
-
1096
- case 'index_hint_lists' :
1097
- case 'index_hint_for_any' :
1098
- return version_compare( $version, '5.1', '>=' );
1099
- break;
1100
- }
1101
-
1102
- return false;
1103
- }
1104
-
1105
- /**
1106
- * The database version number
1107
- *
1108
- * @since 1.0
1109
- *
1110
- * @param false|string|resource $dbh_or_table Which database to test. False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
1111
- * @return false|string false on failure, version number on success
1112
- */
1113
- function db_version( $dbh_or_table = false )
1114
- {
1115
- if ( !$dbh_or_table ) {
1116
- $dbh =& $this->dbh;
1117
- } elseif ( is_resource( $dbh_or_table ) ) {
1118
- $dbh =& $dbh_or_table;
1119
- } else {
1120
- $dbh = $this->db_connect( "DESCRIBE $dbh_or_table" );
1121
- }
1122
-
1123
- if ( $dbh ) {
1124
- return preg_replace( '|[^0-9\.]|', '', mysql_get_server_info( $dbh ) );
1125
- }
1126
- return false;
1127
- }
1128
-
1129
- /**
1130
- * Retrieve the name of the function that called bpdb.
1131
- *
1132
- * Requires PHP 4.3 and searches up the list of functions until it reaches
1133
- * the one that would most logically had called this method.
1134
- *
1135
- * @since 1.0
1136
- *
1137
- * @return string The name of the calling function
1138
- */
1139
- function get_caller()
1140
- {
1141
- // requires PHP 4.3+
1142
- if ( !is_callable( 'debug_backtrace' ) ) {
1143
- return '';
1144
- }
1145
-
1146
- $bt = debug_backtrace();
1147
- $caller = array();
1148
-
1149
- $bt = array_reverse( $bt );
1150
- foreach ( (array) $bt as $call ) {
1151
- if ( @$call['class'] == __CLASS__ ) {
1152
- continue;
1153
- }
1154
- $function = $call['function'];
1155
- if ( isset( $call['class'] ) ) {
1156
- $function = $call['class'] . "->$function";
1157
- }
1158
- $caller[] = $function;
1159
- }
1160
- $caller = join( ', ', $caller );
1161
-
1162
- return $caller;
1163
- }
1164
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.ixr.php DELETED
@@ -1,1115 +0,0 @@
1
- <?php
2
- // Last sync [WP16063]
3
- /**
4
- * IXR - The Incutio XML-RPC Library
5
- *
6
- * Copyright (c) 2010, Incutio Ltd.
7
- * All rights reserved.
8
- *
9
- * Redistribution and use in source and binary forms, with or without
10
- * modification, are permitted provided that the following conditions are met:
11
- *
12
- * - Redistributions of source code must retain the above copyright notice,
13
- * this list of conditions and the following disclaimer.
14
- * - Redistributions in binary form must reproduce the above copyright
15
- * notice, this list of conditions and the following disclaimer in the
16
- * documentation and/or other materials provided with the distribution.
17
- * - Neither the name of Incutio Ltd. nor the names of its contributors
18
- * may be used to endorse or promote products derived from this software
19
- * without specific prior written permission.
20
- *
21
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
- *
33
- * @package IXR
34
- * @since 1.5
35
- *
36
- * @copyright Incutio Ltd 2010 (http://www.incutio.com)
37
- * @version 1.7.4 7th September 2010
38
- * @author Simon Willison
39
- * @link http://scripts.incutio.com/xmlrpc/ Site/manual
40
- * @license http://www.opensource.org/licenses/bsd-license.php BSD
41
- */
42
-
43
- /**
44
- * IXR_Value
45
- *
46
- * @package IXR
47
- * @since 1.5
48
- */
49
- class IXR_Value {
50
- var $data;
51
- var $type;
52
-
53
- function __construct($data, $type = false)
54
- {
55
- $this->data = $data;
56
- if (!$type) {
57
- $type = $this->calculateType();
58
- }
59
- $this->type = $type;
60
- if ($type == 'struct') {
61
- // Turn all the values in the array in to new IXR_Value objects
62
- foreach ($this->data as $key => $value) {
63
- $this->data[$key] = new IXR_Value($value);
64
- }
65
- }
66
- if ($type == 'array') {
67
- for ($i = 0, $j = count($this->data); $i < $j; $i++) {
68
- $this->data[$i] = new IXR_Value($this->data[$i]);
69
- }
70
- }
71
- }
72
-
73
- function IXR_Value($data, $type = false)
74
- {
75
- $this->__construct($data, $type);
76
- }
77
-
78
- function calculateType()
79
- {
80
- if ($this->data === true || $this->data === false) {
81
- return 'boolean';
82
- }
83
- if (is_integer($this->data)) {
84
- return 'int';
85
- }
86
- if (is_double($this->data)) {
87
- return 'double';
88
- }
89
-
90
- // Deal with IXR object types base64 and date
91
- if (is_object($this->data) && is_a($this->data, 'IXR_Date')) {
92
- return 'date';
93
- }
94
- if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) {
95
- return 'base64';
96
- }
97
-
98
- // If it is a normal PHP object convert it in to a struct
99
- if (is_object($this->data)) {
100
- $this->data = get_object_vars($this->data);
101
- return 'struct';
102
- }
103
- if (!is_array($this->data)) {
104
- return 'string';
105
- }
106
-
107
- // We have an array - is it an array or a struct?
108
- if ($this->isStruct($this->data)) {
109
- return 'struct';
110
- } else {
111
- return 'array';
112
- }
113
- }
114
-
115
- function getXml()
116
- {
117
- // Return XML for this value
118
- switch ($this->type) {
119
- case 'boolean':
120
- return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
121
- break;
122
- case 'int':
123
- return '<int>'.$this->data.'</int>';
124
- break;
125
- case 'double':
126
- return '<double>'.$this->data.'</double>';
127
- break;
128
- case 'string':
129
- return '<string>'.htmlspecialchars($this->data).'</string>';
130
- break;
131
- case 'array':
132
- $return = '<array><data>'."\n";
133
- foreach ($this->data as $item) {
134
- $return .= ' <value>'.$item->getXml()."</value>\n";
135
- }
136
- $return .= '</data></array>';
137
- return $return;
138
- break;
139
- case 'struct':
140
- $return = '<struct>'."\n";
141
- foreach ($this->data as $name => $value) {
142
- $name = htmlspecialchars($name);
143
- $return .= " <member><name>$name</name><value>";
144
- $return .= $value->getXml()."</value></member>\n";
145
- }
146
- $return .= '</struct>';
147
- return $return;
148
- break;
149
- case 'date':
150
- case 'base64':
151
- return $this->data->getXml();
152
- break;
153
- }
154
- return false;
155
- }
156
-
157
- /**
158
- * Checks whether or not the supplied array is a struct or not
159
- *
160
- * @param unknown_type $array
161
- * @return boolean
162
- */
163
- function isStruct($array)
164
- {
165
- $expected = 0;
166
- foreach ($array as $key => $value) {
167
- if ((string)$key != (string)$expected) {
168
- return true;
169
- }
170
- $expected++;
171
- }
172
- return false;
173
- }
174
- }
175
-
176
- /**
177
- * IXR_MESSAGE
178
- *
179
- * @package IXR
180
- * @since 1.5
181
- *
182
- */
183
- class IXR_Message
184
- {
185
- var $message;
186
- var $messageType; // methodCall / methodResponse / fault
187
- var $faultCode;
188
- var $faultString;
189
- var $methodName;
190
- var $params;
191
-
192
- // Current variable stacks
193
- var $_arraystructs = array(); // The stack used to keep track of the current array/struct
194
- var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
195
- var $_currentStructName = array(); // A stack as well
196
- var $_param;
197
- var $_value;
198
- var $_currentTag;
199
- var $_currentTagContents;
200
- // The XML parser
201
- var $_parser;
202
-
203
- function __construct($message)
204
- {
205
- $this->message =& $message;
206
- }
207
-
208
- function IXR_Message($message)
209
- {
210
- $this->__construct($message);
211
- }
212
-
213
- function parse()
214
- {
215
- // first remove the XML declaration
216
- // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages
217
- $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr($this->message, 0, 100), 1);
218
- $this->message = substr_replace($this->message, $header, 0, 100);
219
- if (trim($this->message) == '') {
220
- return false;
221
- }
222
- $this->_parser = xml_parser_create();
223
- // Set XML parser to take the case of tags in to account
224
- xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
225
- // Set XML parser callback functions
226
- xml_set_object($this->_parser, $this);
227
- xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
228
- xml_set_character_data_handler($this->_parser, 'cdata');
229
- $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages
230
- do {
231
- if (strlen($this->message) <= $chunk_size) {
232
- $final = true;
233
- }
234
- $part = substr($this->message, 0, $chunk_size);
235
- $this->message = substr($this->message, $chunk_size);
236
- if (!xml_parse($this->_parser, $part, $final)) {
237
- return false;
238
- }
239
- if ($final) {
240
- break;
241
- }
242
- } while (true);
243
- xml_parser_free($this->_parser);
244
-
245
- // Grab the error messages, if any
246
- if ($this->messageType == 'fault') {
247
- $this->faultCode = $this->params[0]['faultCode'];
248
- $this->faultString = $this->params[0]['faultString'];
249
- }
250
- return true;
251
- }
252
-
253
- function tag_open($parser, $tag, $attr)
254
- {
255
- $this->_currentTagContents = '';
256
- $this->currentTag = $tag;
257
- switch($tag) {
258
- case 'methodCall':
259
- case 'methodResponse':
260
- case 'fault':
261
- $this->messageType = $tag;
262
- break;
263
- /* Deal with stacks of arrays and structs */
264
- case 'data': // data is to all intents and puposes more interesting than array
265
- $this->_arraystructstypes[] = 'array';
266
- $this->_arraystructs[] = array();
267
- break;
268
- case 'struct':
269
- $this->_arraystructstypes[] = 'struct';
270
- $this->_arraystructs[] = array();
271
- break;
272
- }
273
- }
274
-
275
- function cdata($parser, $cdata)
276
- {
277
- $this->_currentTagContents .= $cdata;
278
- }
279
-
280
- function tag_close($parser, $tag)
281
- {
282
- $valueFlag = false;
283
- switch($tag) {
284
- case 'int':
285
- case 'i4':
286
- $value = (int)trim($this->_currentTagContents);
287
- $valueFlag = true;
288
- break;
289
- case 'double':
290
- $value = (double)trim($this->_currentTagContents);
291
- $valueFlag = true;
292
- break;
293
- case 'string':
294
- $value = (string)trim($this->_currentTagContents);
295
- $valueFlag = true;
296
- break;
297
- case 'dateTime.iso8601':
298
- $value = new IXR_Date(trim($this->_currentTagContents));
299
- $valueFlag = true;
300
- break;
301
- case 'value':
302
- // "If no type is indicated, the type is string."
303
- if (trim($this->_currentTagContents) != '') {
304
- $value = (string)$this->_currentTagContents;
305
- $valueFlag = true;
306
- }
307
- break;
308
- case 'boolean':
309
- $value = (boolean)trim($this->_currentTagContents);
310
- $valueFlag = true;
311
- break;
312
- case 'base64':
313
- $value = base64_decode($this->_currentTagContents);
314
- $valueFlag = true;
315
- break;
316
- /* Deal with stacks of arrays and structs */
317
- case 'data':
318
- case 'struct':
319
- $value = array_pop($this->_arraystructs);
320
- array_pop($this->_arraystructstypes);
321
- $valueFlag = true;
322
- break;
323
- case 'member':
324
- array_pop($this->_currentStructName);
325
- break;
326
- case 'name':
327
- $this->_currentStructName[] = trim($this->_currentTagContents);
328
- break;
329
- case 'methodName':
330
- $this->methodName = trim($this->_currentTagContents);
331
- break;
332
- }
333
-
334
- if ($valueFlag) {
335
- if (count($this->_arraystructs) > 0) {
336
- // Add value to struct or array
337
- if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
338
- // Add to struct
339
- $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
340
- } else {
341
- // Add to array
342
- $this->_arraystructs[count($this->_arraystructs)-1][] = $value;
343
- }
344
- } else {
345
- // Just add as a paramater
346
- $this->params[] = $value;
347
- }
348
- }
349
- $this->_currentTagContents = '';
350
- }
351
- }
352
-
353
- /**
354
- * IXR_Server
355
- *
356
- * @package IXR
357
- * @since 1.5
358
- */
359
- class IXR_Server
360
- {
361
- var $data;
362
- var $callbacks = array();
363
- var $message;
364
- var $capabilities;
365
-
366
- function __construct($callbacks = false, $data = false, $wait = false)
367
- {
368
- $this->setCapabilities();
369
- if ($callbacks) {
370
- $this->callbacks = $callbacks;
371
- }
372
- $this->setCallbacks();
373
- if (!$wait) {
374
- $this->serve($data);
375
- }
376
- }
377
-
378
- function IXR_Server($callbacks = false, $data = false, $wait = false)
379
- {
380
- $this->__construct($callbacks, $data, $wait);
381
- }
382
-
383
- function serve($data = false)
384
- {
385
- if (!$data) {
386
- if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') {
387
- header('Content-Type: text/plain'); // merged from WP #9093
388
- die('XML-RPC server accepts POST requests only.');
389
- }
390
-
391
- global $HTTP_RAW_POST_DATA;
392
- if (empty($HTTP_RAW_POST_DATA)) {
393
- // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293
394
- $data = file_get_contents('php://input');
395
- } else {
396
- $data =& $HTTP_RAW_POST_DATA;
397
- }
398
- }
399
- $this->message = new IXR_Message($data);
400
- if (!$this->message->parse()) {
401
- $this->error(-32700, 'parse error. not well formed');
402
- }
403
- if ($this->message->messageType != 'methodCall') {
404
- $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
405
- }
406
- $result = $this->call($this->message->methodName, $this->message->params);
407
-
408
- // Is the result an error?
409
- if (is_a($result, 'IXR_Error')) {
410
- $this->error($result);
411
- }
412
-
413
- // Encode the result
414
- $r = new IXR_Value($result);
415
- $resultxml = $r->getXml();
416
-
417
- // Create the XML
418
- $xml = <<<EOD
419
- <methodResponse>
420
- <params>
421
- <param>
422
- <value>
423
- $resultxml
424
- </value>
425
- </param>
426
- </params>
427
- </methodResponse>
428
-
429
- EOD;
430
- // Send it
431
- $this->output($xml);
432
- }
433
-
434
- function call($methodname, $args)
435
- {
436
- if (!$this->hasMethod($methodname)) {
437
- return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
438
- }
439
- $method = $this->callbacks[$methodname];
440
-
441
- // Perform the callback and send the response
442
- if (count($args) == 1) {
443
- // If only one paramater just send that instead of the whole array
444
- $args = $args[0];
445
- }
446
-
447
- // Are we dealing with a function or a method?
448
- if (is_string($method) && substr($method, 0, 5) == 'this:') {
449
- // It's a class method - check it exists
450
- $method = substr($method, 5);
451
- if (!method_exists($this, $method)) {
452
- return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
453
- }
454
-
455
- //Call the method
456
- $result = $this->$method($args);
457
- } else {
458
- // It's a function - does it exist?
459
- if (is_array($method)) {
460
- if (!method_exists($method[0], $method[1])) {
461
- return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.');
462
- }
463
- } else if (!function_exists($method)) {
464
- return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
465
- }
466
-
467
- // Call the function
468
- $result = call_user_func($method, $args);
469
- }
470
- return $result;
471
- }
472
-
473
- function error($error, $message = false)
474
- {
475
- // Accepts either an error object or an error code and message
476
- if ($message && !is_object($error)) {
477
- $error = new IXR_Error($error, $message);
478
- }
479
- $this->output($error->getXml());
480
- }
481
-
482
- function output($xml)
483
- {
484
- $xml = '<?xml version="1.0"?>'."\n".$xml;
485
- $length = strlen($xml);
486
- header('Connection: close');
487
- header('Content-Length: '.$length);
488
- header('Content-Type: text/xml');
489
- header('Date: '.date('r'));
490
- echo $xml;
491
- exit;
492
- }
493
-
494
- function hasMethod($method)
495
- {
496
- return in_array($method, array_keys($this->callbacks));
497
- }
498
-
499
- function setCapabilities()
500
- {
501
- // Initialises capabilities array
502
- $this->capabilities = array(
503
- 'xmlrpc' => array(
504
- 'specUrl' => 'http://www.xmlrpc.com/spec',
505
- 'specVersion' => 1
506
- ),
507
- 'faults_interop' => array(
508
- 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
509
- 'specVersion' => 20010516
510
- ),
511
- 'system.multicall' => array(
512
- 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
513
- 'specVersion' => 1
514
- ),
515
- );
516
- }
517
-
518
- function getCapabilities($args)
519
- {
520
- return $this->capabilities;
521
- }
522
-
523
- function setCallbacks()
524
- {
525
- $this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
526
- $this->callbacks['system.listMethods'] = 'this:listMethods';
527
- $this->callbacks['system.multicall'] = 'this:multiCall';
528
- }
529
-
530
- function listMethods($args)
531
- {
532
- // Returns a list of methods - uses array_reverse to ensure user defined
533
- // methods are listed before server defined methods
534
- return array_reverse(array_keys($this->callbacks));
535
- }
536
-
537
- function multiCall($methodcalls)
538
- {
539
- // See http://www.xmlrpc.com/discuss/msgReader$1208
540
- $return = array();
541
- foreach ($methodcalls as $call) {
542
- $method = $call['methodName'];
543
- $params = $call['params'];
544
- if ($method == 'system.multicall') {
545
- $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
546
- } else {
547
- $result = $this->call($method, $params);
548
- }
549
- if (is_a($result, 'IXR_Error')) {
550
- $return[] = array(
551
- 'faultCode' => $result->code,
552
- 'faultString' => $result->message
553
- );
554
- } else {
555
- $return[] = array($result);
556
- }
557
- }
558
- return $return;
559
- }
560
- }
561
-
562
- /**
563
- * IXR_Request
564
- *
565
- * @package IXR
566
- * @since 1.5
567
- */
568
- class IXR_Request
569
- {
570
- var $method;
571
- var $args;
572
- var $xml;
573
-
574
- function __construct($method, $args)
575
- {
576
- $this->method = $method;
577
- $this->args = $args;
578
- $this->xml = <<<EOD
579
- <?xml version="1.0"?>
580
- <methodCall>
581
- <methodName>{$this->method}</methodName>
582
- <params>
583
-
584
- EOD;
585
- foreach ($this->args as $arg) {
586
- $this->xml .= '<param><value>';
587
- $v = new IXR_Value($arg);
588
- $this->xml .= $v->getXml();
589
- $this->xml .= "</value></param>\n";
590
- }
591
- $this->xml .= '</params></methodCall>';
592
- }
593
-
594
- function IXR_Request($method, $args)
595
- {
596
- $this->__construct($method, $args);
597
- }
598
-
599
- function getLength()
600
- {
601
- return strlen($this->xml);
602
- }
603
-
604
- function getXml()
605
- {
606
- return $this->xml;
607
- }
608
- }
609
-
610
- /**
611
- * IXR_Client
612
- *
613
- * @package IXR
614
- * @since 1.5
615
- *
616
- */
617
- class IXR_Client
618
- {
619
- var $server;
620
- var $port;
621
- var $path;
622
- var $useragent;
623
- var $response;
624
- var $message = false;
625
- var $debug = false;
626
- var $timeout;
627
- var $headers = array();
628
-
629
- // Storage place for an error message
630
- var $error = false;
631
-
632
- function __construct($server, $path = false, $port = 80, $timeout = 15)
633
- {
634
- if (!$path) {
635
- // Assume we have been given a URL instead
636
- $bits = parse_url($server);
637
- $this->server = $bits['host'];
638
- $this->port = isset($bits['port']) ? $bits['port'] : 80;
639
- $this->path = isset($bits['path']) ? $bits['path'] : '/';
640
-
641
- // Make absolutely sure we have a path
642
- if (!$this->path) {
643
- $this->path = '/';
644
- }
645
- } else {
646
- $this->server = $server;
647
- $this->path = $path;
648
- $this->port = $port;
649
- }
650
- $this->useragent = 'The Incutio XML-RPC PHP Library';
651
- $this->timeout = $timeout;
652
- }
653
-
654
- function IXR_Client($server, $path = false, $port = 80, $timeout = 15)
655
- {
656
- $this->__construct($server, $path, $port, $timeout);
657
- }
658
-
659
- function query()
660
- {
661
- $args = func_get_args();
662
- $method = array_shift($args);
663
- $request = new IXR_Request($method, $args);
664
- $length = $request->getLength();
665
- $xml = $request->getXml();
666
- $r = "\r\n";
667
- $request = "POST {$this->path} HTTP/1.0$r";
668
-
669
- // Merged from WP #8145 - allow custom headers
670
- $this->headers['Host'] = $this->server;
671
- $this->headers['Content-Type'] = 'text/xml';
672
- $this->headers['User-Agent'] = $this->useragent;
673
- $this->headers['Content-Length']= $length;
674
-
675
- foreach( $this->headers as $header => $value ) {
676
- $request .= "{$header}: {$value}{$r}";
677
- }
678
- $request .= $r;
679
-
680
- $request .= $xml;
681
-
682
- // Now send the request
683
- if ($this->debug) {
684
- echo '<pre class="ixr_request">'.htmlspecialchars($request)."\n</pre>\n\n";
685
- }
686
-
687
- if ($this->timeout) {
688
- $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
689
- } else {
690
- $fp = @fsockopen($this->server, $this->port, $errno, $errstr);
691
- }
692
- if (!$fp) {
693
- $this->error = new IXR_Error(-32300, 'transport error - could not open socket');
694
- return false;
695
- }
696
- fputs($fp, $request);
697
- $contents = '';
698
- $debugContents = '';
699
- $gotFirstLine = false;
700
- $gettingHeaders = true;
701
- while (!feof($fp)) {
702
- $line = fgets($fp, 4096);
703
- if (!$gotFirstLine) {
704
- // Check line for '200'
705
- if (strstr($line, '200') === false) {
706
- $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200');
707
- return false;
708
- }
709
- $gotFirstLine = true;
710
- }
711
- if (trim($line) == '') {
712
- $gettingHeaders = false;
713
- }
714
- if (!$gettingHeaders) {
715
- // merged from WP #12559 - remove trim
716
- $contents .= $line;
717
- }
718
- if ($this->debug) {
719
- $debugContents .= $line;
720
- }
721
- }
722
- if ($this->debug) {
723
- echo '<pre class="ixr_response">'.htmlspecialchars($debugContents)."\n</pre>\n\n";
724
- }
725
-
726
- // Now parse what we've got back
727
- $this->message = new IXR_Message($contents);
728
- if (!$this->message->parse()) {
729
- // XML error
730
- $this->error = new IXR_Error(-32700, 'parse error. not well formed');
731
- return false;
732
- }
733
-
734
- // Is the message a fault?
735
- if ($this->message->messageType == 'fault') {
736
- $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
737
- return false;
738
- }
739
-
740
- // Message must be OK
741
- return true;
742
- }
743
-
744
- function getResponse()
745
- {
746
- // methodResponses can only have one param - return that
747
- return $this->message->params[0];
748
- }
749
-
750
- function isError()
751
- {
752
- return (is_object($this->error));
753
- }
754
-
755
- function getErrorCode()
756
- {
757
- return $this->error->code;
758
- }
759
-
760
- function getErrorMessage()
761
- {
762
- return $this->error->message;
763
- }
764
- }
765
-
766
-
767
- /**
768
- * IXR_Error
769
- *
770
- * @package IXR
771
- * @since 1.5
772
- */
773
- class IXR_Error
774
- {
775
- var $code;
776
- var $message;
777
-
778
- function __construct($code, $message)
779
- {
780
- $this->code = $code;
781
- $this->message = htmlspecialchars($message);
782
- }
783
-
784
- function IXR_Error($code, $message)
785
- {
786
- $this->__construct($code, $message);
787
- }
788
-
789
- function getXml()
790
- {
791
- $xml = <<<EOD
792
- <methodResponse>
793
- <fault>
794
- <value>
795
- <struct>
796
- <member>
797
- <name>faultCode</name>
798
- <value><int>{$this->code}</int></value>
799
- </member>
800
- <member>
801
- <name>faultString</name>
802
- <value><string>{$this->message}</string></value>
803
- </member>
804
- </struct>
805
- </value>
806
- </fault>
807
- </methodResponse>
808
-
809
- EOD;
810
- return $xml;
811
- }
812
- }
813
-
814
- /**
815
- * IXR_Date
816
- *
817
- * @package IXR
818
- * @since 1.5
819
- */
820
- class IXR_Date {
821
- var $year;
822
- var $month;
823
- var $day;
824
- var $hour;
825
- var $minute;
826
- var $second;
827
- var $timezone;
828
-
829
- function __construct($time)
830
- {
831
- // $time can be a PHP timestamp or an ISO one
832
- if (is_numeric($time)) {
833
- $this->parseTimestamp($time);
834
- } else {
835
- $this->parseIso($time);
836
- }
837
- }
838
-
839
- function IXR_Date($time)
840
- {
841
- $this->__construct($time);
842
- }
843
-
844
- function parseTimestamp($timestamp)
845
- {
846
- $this->year = date('Y', $timestamp);
847
- $this->month = date('m', $timestamp);
848
- $this->day = date('d', $timestamp);
849
- $this->hour = date('H', $timestamp);
850
- $this->minute = date('i', $timestamp);
851
- $this->second = date('s', $timestamp);
852
- $this->timezone = '';
853
- }
854
-
855
- function parseIso($iso)
856
- {
857
- $this->year = substr($iso, 0, 4);
858
- $this->month = substr($iso, 4, 2);
859
- $this->day = substr($iso, 6, 2);
860
- $this->hour = substr($iso, 9, 2);
861
- $this->minute = substr($iso, 12, 2);
862
- $this->second = substr($iso, 15, 2);
863
- $this->timezone = substr($iso, 17);
864
- }
865
-
866
- function getIso()
867
- {
868
- return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone;
869
- }
870
-
871
- function getXml()
872
- {
873
- return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
874
- }
875
-
876
- function getTimestamp()
877
- {
878
- return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
879
- }
880
- }
881
-
882
- /**
883
- * IXR_Base64
884
- *
885
- * @package IXR
886
- * @since 1.5
887
- */
888
- class IXR_Base64
889
- {
890
- var $data;
891
-
892
- function __construct($data)
893
- {
894
- $this->data = $data;
895
- }
896
-
897
- function IXR_Base64($data)
898
- {
899
- $this->__construct($data);
900
- }
901
-
902
- function getXml()
903
- {
904
- return '<base64>'.base64_encode($this->data).'</base64>';
905
- }
906
- }
907
-
908
- /**
909
- * IXR_IntrospectionServer
910
- *
911
- * @package IXR
912
- * @since 1.5
913
- */
914
- class IXR_IntrospectionServer extends IXR_Server
915
- {
916
- var $signatures;
917
- var $help;
918
-
919
- function __construct()
920
- {
921
- $this->setCallbacks();
922
- $this->setCapabilities();
923
- $this->capabilities['introspection'] = array(
924
- 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html',
925
- 'specVersion' => 1
926
- );
927
- $this->addCallback(
928
- 'system.methodSignature',
929
- 'this:methodSignature',
930
- array('array', 'string'),
931
- 'Returns an array describing the return type and required parameters of a method'
932
- );
933
- $this->addCallback(
934
- 'system.getCapabilities',
935
- 'this:getCapabilities',
936
- array('struct'),
937
- 'Returns a struct describing the XML-RPC specifications supported by this server'
938
- );
939
- $this->addCallback(
940
- 'system.listMethods',
941
- 'this:listMethods',
942
- array('array'),
943
- 'Returns an array of available methods on this server'
944
- );
945
- $this->addCallback(
946
- 'system.methodHelp',
947
- 'this:methodHelp',
948
- array('string', 'string'),
949
- 'Returns a documentation string for the specified method'
950
- );
951
- }
952
-
953
- function IXR_IntrospectionServer()
954
- {
955
- $this->__construct();
956
- }
957
-
958
- function addCallback($method, $callback, $args, $help)
959
- {
960
- $this->callbacks[$method] = $callback;
961
- $this->signatures[$method] = $args;
962
- $this->help[$method] = $help;
963
- }
964
-
965
- function call($methodname, $args)
966
- {
967
- // Make sure it's in an array
968
- if ($args && !is_array($args)) {
969
- $args = array($args);
970
- }
971
-
972
- // Over-rides default call method, adds signature check
973
- if (!$this->hasMethod($methodname)) {
974
- return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
975
- }
976
- $method = $this->callbacks[$methodname];
977
- $signature = $this->signatures[$methodname];
978
- $returnType = array_shift($signature);
979
-
980
- // Check the number of arguments
981
- if (count($args) != count($signature)) {
982
- return new IXR_Error(-32602, 'server error. wrong number of method parameters');
983
- }
984
-
985
- // Check the argument types
986
- $ok = true;
987
- $argsbackup = $args;
988
- for ($i = 0, $j = count($args); $i < $j; $i++) {
989
- $arg = array_shift($args);
990
- $type = array_shift($signature);
991
- switch ($type) {
992
- case 'int':
993
- case 'i4':
994
- if (is_array($arg) || !is_int($arg)) {
995
- $ok = false;
996
- }
997
- break;
998
- case 'base64':
999
- case 'string':
1000
- if (!is_string($arg)) {
1001
- $ok = false;
1002
- }
1003
- break;
1004
- case 'boolean':
1005
- if ($arg !== false && $arg !== true) {
1006
- $ok = false;
1007
- }
1008
- break;
1009
- case 'float':
1010
- case 'double':
1011
- if (!is_float($arg)) {
1012
- $ok = false;
1013
- }
1014
- break;
1015
- case 'date':
1016
- case 'dateTime.iso8601':
1017
- if (!is_a($arg, 'IXR_Date')) {
1018
- $ok = false;
1019
- }
1020
- break;
1021
- }
1022
- if (!$ok) {
1023
- return new IXR_Error(-32602, 'server error. invalid method parameters');
1024
- }
1025
- }
1026
- // It passed the test - run the "real" method call
1027
- return parent::call($methodname, $argsbackup);
1028
- }
1029
-
1030
- function methodSignature($method)
1031
- {
1032
- if (!$this->hasMethod($method)) {
1033
- return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
1034
- }
1035
- // We should be returning an array of types
1036
- $types = $this->signatures[$method];
1037
- $return = array();
1038
- foreach ($types as $type) {
1039
- switch ($type) {
1040
- case 'string':
1041
- $return[] = 'string';
1042
- break;
1043
- case 'int':
1044
- case 'i4':
1045
- $return[] = 42;
1046
- break;
1047
- case 'double':
1048
- $return[] = 3.1415;
1049
- break;
1050
- case 'dateTime.iso8601':
1051
- $return[] = new IXR_Date(time());
1052
- break;
1053
- case 'boolean':
1054
- $return[] = true;
1055
- break;
1056
- case 'base64':
1057
- $return[] = new IXR_Base64('base64');
1058
- break;
1059
- case 'array':
1060
- $return[] = array('array');
1061
- break;
1062
- case 'struct':
1063
- $return[] = array('struct' => 'struct');
1064
- break;
1065
- }
1066
- }
1067
- return $return;
1068
- }
1069
-
1070
- function methodHelp($method)
1071
- {
1072
- return $this->help[$method];
1073
- }
1074
- }
1075
-
1076
- /**
1077
- * IXR_ClientMulticall
1078
- *
1079
- * @package IXR
1080
- * @since 1.5
1081
- */
1082
- class IXR_ClientMulticall extends IXR_Client
1083
- {
1084
- var $calls = array();
1085
-
1086
- function __construct($server, $path = false, $port = 80)
1087
- {
1088
- parent::__construct($server, $path, $port);
1089
- $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
1090
- }
1091
-
1092
- function IXR_ClientMulticall($server, $path = false, $port = 80)
1093
- {
1094
- $this->__construct($server, $path, $port);
1095
- }
1096
-
1097
- function addCall()
1098
- {
1099
- $args = func_get_args();
1100
- $methodName = array_shift($args);
1101
- $struct = array(
1102
- 'methodName' => $methodName,
1103
- 'params' => $args
1104
- );
1105
- $this->calls[] = $struct;
1106
- }
1107
-
1108
- function query()
1109
- {
1110
- // Prepare multicall, then call the parent::query() method
1111
- return parent::query('system.multicall', $this->calls);
1112
- }
1113
- }
1114
-
1115
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bp-forums/bbpress/bb-includes/backpress/class.mailer-smtp.php DELETED
@@ -1,1065 +0,0 @@
1
- <?php
2
- // Last sync [WP13425]
3
-
4
- /*~ class.smtp.php
5
- .---------------------------------------------------------------------------.
6
- | Software: PHPMailer - PHP email class |
7
- | Version: 2.0.4 |
8
- | Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
9
- | Info: http://phpmailer.sourceforge.net |
10
- | Support: http://sourceforge.net/projects/phpmailer/ |
11
- | ------------------------------------------------------------------------- |
12
- | Author: Andy Prevost (project admininistrator) |
13
- | Author: Brent R. Matzelle (original founder) |
14
- | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. |
15
- | Copyright (c) 2001-2003, Brent R. Matzelle |
16
- | ------------------------------------------------------------------------- |
17
- | License: Distributed under the Lesser General Public License (LGPL) |
18
- | http://www.gnu.org/copyleft/lesser.html |
19
- | This program is distributed in the hope that it will be useful - WITHOUT |
20
- | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21
- | FITNESS FOR A PARTICULAR PURPOSE. |
22
- | ------------------------------------------------------------------------- |
23
- | We offer a number of paid services (www.codeworxtech.com): |
24
- | - Web Hosting on highly optimized fast and secure servers |
25
- | - Technology Consulting |
26
- | - Oursourcing (highly qualified programmers and graphic designers) |
27
- '---------------------------------------------------------------------------'
28
- */
29
- /**
30
- * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
31
- * commands except TURN which will always return a not implemented
32
- * error. SMTP also provides some utility methods for sending mail
33
- * to an SMTP server.
34
- * @package PHPMailer
35
- * @author Chris Ryan
36
- */
37
-
38
- class SMTP
39
- {
40
- /**
41
- * SMTP server port
42
- * @var int
43
- */
44
- var $SMTP_PORT = 25;
45
-
46
- /**
47
- * SMTP reply line ending
48
- * @var string
49
- */
50
- var $CRLF = "\r\n";
51
-
52
- /**
53
- * Sets whether debugging is turned on
54
- * @var bool
55
- */
56
- var $do_debug; # the level of debug to perform
57
-
58
- /**
59
- * Sets VERP use on/off (default is off)
60
- * @var bool
61
- */
62
- var $do_verp = false;
63
-
64
- /**#@+
65
- * @access private
66
- */
67
- var $smtp_conn; # the socket to the server
68
- var $error; # error if any on the last call
69
- var $helo_rply; # the reply the server sent to us for HELO
70
- /**#@-*/
71
-
72
- /**
73
- * Initialize the class so that the data is in a known state.
74
- * @access public
75
- * @return void
76
- */
77
- function __construct() {
78
- $this->smtp_conn = 0;
79
- $this->error = null;
80
- $this->helo_rply = null;
81
-
82
- $this->do_debug = 0;
83
- }
84
-
85
- function SMTP() {
86
- $this->__construct();
87
- }
88
-
89
- /*************************************************************
90
- * CONNECTION FUNCTIONS *
91
- ***********************************************************/
92
-
93
- /**
94
- * Connect to the server specified on the port specified.
95
- * If the port is not specified use the default SMTP_PORT.
96
- * If tval is specified then a connection will try and be
97
- * established with the server for that number of seconds.
98
- * If tval is not specified the default is 30 seconds to
99
- * try on the connection.
100
- *
101
- * SMTP CODE SUCCESS: 220
102
- * SMTP CODE FAILURE: 421
103
- * @access public
104
- * @return bool
105
- */
106
- function Connect($host,$port=0,$tval=30) {
107
- # set the error val to null so there is no confusion
108
- $this->error = null;
109
-
110
- # make sure we are __not__ connected
111
- if($this->connected()) {
112
- # ok we are connected! what should we do?
113
- # for now we will just give an error saying we
114
- # are already connected
115
- $this->error = array("error" => "Already connected to a server");
116
- return false;
117
- }
118
-
119
- if(empty($port)) {
120
- $port = $this->SMTP_PORT;
121
- }
122
-
123
- #connect to the smtp server
124
- $this->smtp_conn = fsockopen($host, # the host of the server
125
- $port, # the port to use
126
- $errno, # error number if any
127
- $errstr, # error message if any
128
- $tval); # give up after ? secs
129
- # verify we connected properly
130
- if(empty($this->smtp_conn)) {
131
- $this->error = array("error" => "Failed to connect to server",
132
- "errno" => $errno,
133
- "errstr" => $errstr);
134
- if($this->do_debug >= 1) {
135
- echo "SMTP -> ERROR: " . $this->error["error"] .
136
- ": $errstr ($errno)" . $this->CRLF;
137
- }
138
- return false;
139
- }
140
-
141
- # sometimes the SMTP server takes a little longer to respond
142
- # so we will give it a longer timeout for the first read
143
- // Windows still does not have support for this timeout function
144
- if(substr(PHP_OS, 0, 3) != "WIN")
145
- socket_set_timeout($this->smtp_conn, $tval, 0);
146
-
147
- # get any announcement stuff
148
- $announce = $this->get_lines();
149
-
150
- # set the timeout of any socket functions at 1/10 of a second
151
- //if(function_exists("socket_set_timeout"))
152
- // socket_set_timeout($this->smtp_conn, 0, 100000);
153
-
154
- if($this->do_debug >= 2) {
155
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
156
- }
157
-
158
- return true;
159
- }
160
-
161
- /**
162
- * Performs SMTP authentication. Must be run after running the
163
- * Hello() method. Returns true if successfully authenticated.
164
- * @access public
165
- * @return bool
166
- */
167
- function Authenticate($username, $password) {
168
- // Start authentication
169
- fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
170
-
171
- $rply = $this->get_lines();
172
- $code = substr($rply,0,3);
173
-
174
- if($code != 334) {
175
- $this->error =
176
- array("error" => "AUTH not accepted from server",
177
- "smtp_code" => $code,
178
- "smtp_msg" => substr($rply,4));
179
- if($this->do_debug >= 1) {
180
- echo "SMTP -> ERROR: " . $this->error["error"] .
181
- ": " . $rply . $this->CRLF;
182
- }
183
- return false;
184
- }
185
-
186
- // Send encoded username
187
- fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
188
-
189
- $rply = $this->get_lines();
190
- $code = substr($rply,0,3);
191
-
192
- if($code != 334) {
193
- $this->error =
194
- array("error" => "Username not accepted from server",
195
- "smtp_code" => $code,
196
- "smtp_msg" => substr($rply,4));
197
- if($this->do_debug >= 1) {
198
- echo "SMTP -> ERROR: " . $this->error["error"] .
199
- ": " . $rply . $this->CRLF;
200
- }
201
- return false;
202
- }
203
-
204
- // Send encoded password
205
- fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
206
-
207
- $rply = $this->get_lines();
208
- $code = substr($rply,0,3);
209
-
210
- if($code != 235) {
211
- $this->error =
212
- array("error" => "Password not accepted from server",
213
- "smtp_code" => $code,
214
- "smtp_msg" => substr($rply,4));
215
- if($this->do_debug >= 1) {
216
- echo "SMTP -> ERROR: " . $this->error["error"] .
217
- ": " . $rply . $this->CRLF;
218
- }
219
- return false;
220
- }
221
-
222
- return true;
223
- }
224
-
225
- /**
226
- * Returns true if connected to a server otherwise false
227
- * @access private
228
- * @return bool
229
- */
230
- function Connected() {
231
- if(!empty($this->smtp_conn)) {
232
- $sock_status = socket_get_status($this->smtp_conn);
233
- if($sock_status["eof"]) {
234
- # hmm this is an odd situation... the socket is
235
- # valid but we are not connected anymore
236
- if($this->do_debug >= 1) {
237
- echo "SMTP -> NOTICE:" . $this->CRLF .
238
- "EOF caught while checking if connected";
239
- }
240
- $this->Close();
241
- return false;
242
- }
243
- return true; # everything looks good
244
- }
245
- return false;
246
- }
247
-
248
- /**
249
- * Closes the socket and cleans up the state of the class.
250
- * It is not considered good to use this function without
251
- * first trying to use QUIT.
252
- * @access public
253
- * @return void
254
- */
255
- function Close() {
256
- $this->error = null; # so there is no confusion
257
- $this->helo_rply = null;
258
- if(!empty($this->smtp_conn)) {
259
- # close the connection and cleanup
260
- fclose($this->smtp_conn);
261
- $this->smtp_conn = 0;
262
- }
263
- }
264
-
265
- /***************************************************************
266
- * SMTP COMMANDS *
267
- *************************************************************/
268
-
269
- /**
270
- * Issues a data command and sends the msg_data to the server
271
- * finializing the mail transaction. $msg_data is the message
272
- * that is to be send with the headers. Each header needs to be
273
- * on a single line followed by a <CRLF> with the message headers
274
- * and the message body being separated by and additional <CRLF>.
275
- *
276
- * Implements rfc 821: DATA <CRLF>
277
- *
278
- * SMTP CODE INTERMEDIATE: 354
279
- * [data]
280
- * <CRLF>.<CRLF>
281
- * SMTP CODE SUCCESS: 250
282
- * SMTP CODE FAILURE: 552,554,451,452
283
- * SMTP CODE FAILURE: 451,554
284
- * SMTP CODE ERROR : 500,501,503,421
285
- * @access public
286
- * @return bool
287
- */
288
- function Data($msg_data) {
289
- $this->error = null; # so no confusion is caused
290
-
291
- if(!$this->connected()) {
292
- $this->error = array(
293
- "error" => "Called Data() without being connected");
294
- return false;
295
- }
296
-
297
- fputs($this->smtp_conn,"DATA" . $this->CRLF);
298
-
299
- $rply = $this->get_lines();
300
- $code = substr($rply,0,3);
301
-
302
- if($this->do_debug >= 2) {
303
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
304
- }
305
-
306
- if($code != 354) {
307
- $this->error =
308
- array("error" => "DATA command not accepted from server",
309
- "smtp_code" => $code,
310
- "smtp_msg" => substr($rply,4));
311
- if($this->do_debug >= 1) {
312
- echo "SMTP -> ERROR: " . $this->error["error"] .
313
- ": " . $rply . $this->CRLF;
314
- }
315
- return false;
316
- }
317
-
318
- # the server is ready to accept data!
319
- # according to rfc 821 we should not send more than 1000
320
- # including the CRLF
321
- # characters on a single line so we will break the data up
322
- # into lines by \r and/or \n then if needed we will break
323
- # each of those into smaller lines to fit within the limit.
324
- # in addition we will be looking for lines that start with
325
- # a period '.' and append and additional period '.' to that
326
- # line. NOTE: this does not count towards are limit.
327
-
328
- # normalize the line breaks so we know the explode works
329
- $msg_data = str_replace("\r\n","\n",$msg_data);
330
- $msg_data = str_replace("\r","\n",$msg_data);
331
- $lines = explode("\n",$msg_data);
332
-
333
- # we need to find a good way to determine is headers are
334
- # in the msg_data or if it is a straight msg body
335
- # currently I am assuming rfc 822 definitions of msg headers
336
- # and if the first field of the first line (':' sperated)
337
- # does not contain a space then it _should_ be a header
338
- # and we can process all lines before a blank "" line as
339
- # headers.
340
- $field = substr($lines[0],0,strpos($lines[0],":"));
341
- $in_headers = false;
342
- if(!empty($field) && !strstr($field," ")) {
343
- $in_headers = true;
344
- }
345
-
346
- $max_line_length = 998; # used below; set here for ease in change
347
-
348
- while(list(,$line) = @each($lines)) {
349
- $lines_out = null;
350
- if($line == "" && $in_headers) {
351
- $in_headers = false;
352
- }
353
- # ok we need to break this line up into several
354
- # smaller lines
355
- while(strlen($line) > $max_line_length) {
356
- $pos = strrpos(substr($line,0,$max_line_length)," ");
357
-
358
- # Patch to fix DOS attack
359
- if(!$pos) {
360
- $pos = $max_line_length - 1;
361
- }
362
-
363
- $lines_out[] = substr($line,0,$pos);
364
- $line = substr($line,$pos + 1);
365
- # if we are processing headers we need to
366
- # add a LWSP-char to the front of the new line
367
- # rfc 822 on long msg headers
368
- if($in_headers) {
369
- $line = "\t" . $line;
370
- }
371
- }
372
- $lines_out[] = $line;
373
-
374
- # now send the lines to the server
375
- while(list(,$line_out) = @each($lines_out)) {
376
- if(strlen($line_out) > 0)
377
- {
378
- if(substr($line_out, 0, 1) == ".") {
379
- $line_out = "." . $line_out;
380
- }
381
- }
382
- fputs($this->smtp_conn,$line_out . $this->CRLF);
383
- }
384
- }
385
-
386
- # ok all the message data has been sent so lets get this
387
- # over with aleady
388
- fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
389
-
390
- $rply = $this->get_lines();
391
- $code = substr($rply,0,3);
392
-
393
- if($this->do_debug >= 2) {
394
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
395
- }
396
-
397
- if($code != 250) {
398
- $this->error =
399
- array("error" => "DATA not accepted from server",
400
- "smtp_code" => $code,
401
- "smtp_msg" => substr($rply,4));
402
- if($this->do_debug >= 1) {
403
- echo "SMTP -> ERROR: " . $this->error["error"] .
404
- ": " . $rply . $this->CRLF;
405
- }
406
- return false;
407
- }
408
- return true;
409
- }
410
-
411
- /**
412
- * Expand takes the name and asks the server to list all the
413
- * people who are members of the _list_. Expand will return
414
- * back and array of the result or false if an error occurs.
415
- * Each value in the array returned has the format of:
416
- * [ <full-name> <sp> ] <path>
417
- * The definition of <path> is defined in rfc 821
418
- *
419
- * Implements rfc 821: EXPN <SP> <string> <CRLF>
420
- *
421
- * SMTP CODE SUCCESS: 250
422
- * SMTP CODE FAILURE: 550
423
- * SMTP CODE ERROR : 500,501,502,504,421
424
- * @access public
425
- * @return string array
426
- */
427
- function Expand($name) {
428
- $this->error = null; # so no confusion is caused
429
-
430
- if(!$this->connected()) {
431
- $this->error = array(
432
- "error" => "Called Expand() without being connected");
433
- return false;
434
- }
435
-
436
- fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
437
-
438
- $rply = $this->get_lines();
439
- $code = substr($rply,0,3);
440
-
441
- if($this->do_debug >= 2) {
442
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
443
- }
444
-
445
- if($code != 250) {
446
- $this->error =
447
- array("error" => "EXPN not accepted from server",
448
- "smtp_code" => $code,
449
- "smtp_msg" => substr($rply,4));
450
- if($this->do_debug >= 1) {
451
- echo "SMTP -> ERROR: " . $this->error["error"] .
452
- ": " . $rply . $this->CRLF;
453
- }
454
- return false;
455
- }
456
-
457
- # parse the reply and place in our array to return to user
458
- $entries = explode($this->CRLF,$rply);
459
- while(list(,$l) = @each($entries)) {
460
- $list[] = substr($l,4);
461
- }
462
-
463
- return $list;
464
- }
465
-
466
- /**
467
- * Sends the HELO command to the smtp server.
468
- * This makes sure that we and the server are in
469
- * the same known state.
470
- *
471
- * Implements from rfc 821: HELO <SP> <domain> <CRLF>
472
- *
473
- * SMTP CODE SUCCESS: 250
474
- * SMTP CODE ERROR : 500, 501, 504, 421
475
- * @access public
476
- * @return bool
477
- */
478
- function Hello($host="") {
479
- $this->error = null; # so no confusion is caused
480
-
481
- if(!$this->connected()) {
482
- $this->error = array(
483
- "error" => "Called Hello() without being connected");
484
- return false;
485
- }
486
-
487
- # if a hostname for the HELO was not specified determine
488
- # a suitable one to send
489
- if(empty($host)) {
490
- # we need to determine some sort of appopiate default
491
- # to send to the server
492
- $host = "localhost";
493
- }
494
-
495
- // Send extended hello first (RFC 2821)
496
- if(!$this->SendHello("EHLO", $host))
497
- {
498
- if(!$this->SendHello("HELO", $host))
499
- return false;
500
- }
501
-
502
- return true;
503
- }
504
-
505
- /**
506
- * Sends a HELO/EHLO command.
507
- * @access private
508
- * @return bool
509
- */
510
- function SendHello($hello, $host) {
511
- fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
512
-
513
- $rply = $this->get_lines();
514
- $code = substr($rply,0,3);
515
-
516
- if($this->do_debug >= 2) {
517
- echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
518
- }
519
-
520
- if($code != 250) {
521
- $this->error =
522
- array("error" => $hello . " not accepted from server",
523
- "smtp_code" => $code,
524
- "smtp_msg" => substr($rply,4));
525
- if($this->do_debug >= 1) {
526
- echo "SMTP -> ERROR: " . $this->error["error"] .
527
- ": " . $rply . $this->CRLF;
528
- }
529
- return false;
530
- }
531
-
532
- $this->helo_rply = $rply;
533
-
534
- return true;
535
- }
536
-
537
- /**
538
- * Gets help information on the keyword specified. If the keyword
539
- * is not specified then returns generic help, ussually contianing
540
- * A list of keywords that help is available on. This function
541
- * returns the results back to the user. It is up to the user to
542
- * handle the returned data. If an error occurs then false is
543
- * returned with $this->error set appropiately.
544
- *
545
- * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
546
- *
547
- * SMTP CODE SUCCESS: 211,214
548
- * SMTP CODE ERROR : 500,501,502,504,421
549
- * @access public
550
- * @return string
551
- */
552
- function Help($keyword="") {
553
- $this->error = null; # to avoid confusion
554
-
555
- if(!$this->connected()) {
556
- $this->error = array(
557
- "error" => "Called Help() without being connected");
558
- return false;
559
- }
560
-
561
- $extra = "";
562
- if(!empty($keyword)) {
563
- $extra = " " . $keyword;
564
- }
565
-
566
- fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
567
-
568
- $rply = $this->get_lines();
569
- $code = substr($rply,0,3);
570
-
571
- if($this->do_debug >= 2) {
572
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
573
- }
574
-
575
- if($code != 211 && $code != 214) {
576
- $this->error =
577
- array("error" => "HELP not accepted from server",
578
- "smtp_code" => $code,
579
- "smtp_msg" => substr($rply,4));
580
- if