PluginProbe
bbPress / 2.6.17
bbPress v2.6.17
2.6.17 trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 2.2 2.2.1 All 72 releases
← All changes | includes/admin/topics.php +879 -570 2.2.12.6.17 View file →
@@ -7,17 +7,17 @@
7 7 * @subpackage Administration
8 8 */
9 9
10 10 // Exit if accessed directly
11 -if ( !defined( 'ABSPATH' ) ) exit;
11 +defined( 'ABSPATH' ) || exit;
12 12
13 -if ( !class_exists( 'BBP_Topics_Admin' ) ) :
13 +if ( ! class_exists( 'BBP_Topics_Admin' ) ) :
14 14 /**
15 15 * Loads bbPress topics admin area
16 16 *
17 17 * @package bbPress
18 18 * @subpackage Administration
19 - * @since bbPress (r2464)
19 + * @since 2.0.0 bbPress (r2464)
20 20 */
21 21 class BBP_Topics_Admin {
22 22
23 23 /** Variables *************************************************************/
@@ -31,13 +31,9 @@
31 31
32 32 /**
33 33 * The main bbPress topics admin loader
34 34 *
35 - * @since bbPress (r2515)
36 - *
37 - * @uses BBP_Topics_Admin::setup_globals() Setup the globals needed
38 - * @uses BBP_Topics_Admin::setup_actions() Setup the hooks and actions
39 - * @uses BBP_Topics_Admin::setup_help() Setup the help text
35 + * @since 2.0.0 bbPress (r2515)
40 36 */
41 37 public function __construct() {
42 38 $this->setup_globals();
43 39 $this->setup_actions();
@@ -45,70 +41,64 @@
45 41
46 42 /**
47 43 * Setup the admin hooks, actions and filters
48 44 *
49 - * @since bbPress (r2646)
45 + * @since 2.0.0 bbPress (r2646)
46 + * @since 2.6.0 bbPress (r6101) Added bulk actions
47 + *
50 48 * @access private
51 - *
52 - * @uses add_action() To add various actions
53 - * @uses add_filter() To add various filters
54 - * @uses bbp_get_forum_post_type() To get the forum post type
55 - * @uses bbp_get_topic_post_type() To get the topic post type
56 - * @uses bbp_get_reply_post_type() To get the reply post type
57 49 */
58 50 private function setup_actions() {
59 51
60 - // Add some general styling to the admin area
61 - add_action( 'bbp_admin_head', array( $this, 'admin_head' ) );
62 -
63 52 // Messages
64 53 add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
65 54
55 + // Topic bulk actions, added in WordPress 4.7, see #WP16031.
56 + if ( bbp_get_major_wp_version() >= 4.7 ) {
57 + add_filter( 'bulk_actions-edit-topic', array( $this, 'bulk_actions' ) );
58 + add_filter( 'handle_bulk_actions-edit-topic', array( $this, 'handle_bulk_actions' ), 10, 3 );
59 + add_filter( 'bulk_post_updated_messages', array( $this, 'bulk_post_updated_messages' ), 10, 2 );
60 + }
61 +
66 62 // Topic column headers.
67 - add_filter( 'manage_' . $this->post_type . '_posts_columns', array( $this, 'topics_column_headers' ) );
63 + add_filter( 'manage_' . $this->post_type . '_posts_columns', array( $this, 'column_headers' ) );
68 64
69 65 // Topic columns (in post row)
70 - add_action( 'manage_' . $this->post_type . '_posts_custom_column', array( $this, 'topics_column_data' ), 10, 2 );
71 - add_filter( 'post_row_actions', array( $this, 'topics_row_actions' ), 10, 2 );
66 + add_action( 'manage_' . $this->post_type . '_posts_custom_column', array( $this, 'column_data' ), 10, 2 );
67 + add_filter( 'post_row_actions', array( $this, 'row_actions' ), 10, 2 );
72 68
73 - // Topic metabox actions
74 - add_action( 'add_meta_boxes', array( $this, 'attributes_metabox' ) );
75 - add_action( 'save_post', array( $this, 'attributes_metabox_save' ) );
69 + // Topic meta-box actions
70 + add_action( 'add_meta_boxes', array( $this, 'attributes_metabox' ) );
71 + add_action( 'add_meta_boxes', array( $this, 'author_metabox' ) );
72 + add_action( 'add_meta_boxes', array( $this, 'replies_metabox' ) );
73 + add_action( 'add_meta_boxes', array( $this, 'engagements_metabox' ) );
74 + add_action( 'add_meta_boxes', array( $this, 'favorites_metabox' ) );
75 + add_action( 'add_meta_boxes', array( $this, 'subscriptions_metabox' ) );
76 + add_action( 'add_meta_boxes', array( $this, 'comments_metabox' ) );
77 + add_action( 'save_post', array( $this, 'save_meta_boxes' ) );
76 78
77 79 // Check if there are any bbp_toggle_topic_* requests on admin_init, also have a message displayed
78 80 add_action( 'load-edit.php', array( $this, 'toggle_topic' ) );
79 - add_action( 'admin_notices', array( $this, 'toggle_topic_notice' ) );
81 + add_action( 'load-edit.php', array( $this, 'toggle_topic_notice' ) );
80 82
81 - // Anonymous metabox actions
82 - add_action( 'add_meta_boxes', array( $this, 'author_metabox' ) );
83 - add_action( 'save_post', array( $this, 'author_metabox_save' ) );
84 -
85 83 // Add ability to filter topics and replies per forum
86 84 add_filter( 'restrict_manage_posts', array( $this, 'filter_dropdown' ) );
87 85 add_filter( 'bbp_request', array( $this, 'filter_post_rows' ) );
88 86
87 + // Empty spam
88 + add_filter( 'manage_posts_extra_tablenav', array( $this, 'filter_empty_spam' ) );
89 +
89 90 // Contextual Help
90 91 add_action( 'load-edit.php', array( $this, 'edit_help' ) );
92 + add_action( 'load-post.php', array( $this, 'new_help' ) );
91 93 add_action( 'load-post-new.php', array( $this, 'new_help' ) );
92 94 }
93 95
94 96 /**
95 - * Should we bail out of this method?
97 + * Admin globals
96 98 *
97 - * @since bbPress (r4067)
98 - * @return boolean
99 - */
100 - private function bail() {
101 - if ( !isset( get_current_screen()->post_type ) || ( $this->post_type != get_current_screen()->post_type ) )
102 - return true;
103 -
104 - return false;
105 - }
106 -
107 - /**
108 - * Admin globals
99 + * @since 2.0.0 bbPress (r2646)
109 100 *
110 - * @since bbPress (r2646)
111 101 * @access private
112 102 */
113 103 private function setup_globals() {
114 104 $this->post_type = bbp_get_topic_post_type();
@@ -118,67 +108,74 @@
118 108
119 109 /**
120 110 * Contextual help for bbPress topic edit page
121 111 *
122 - * @since bbPress (r3119)
123 - * @uses get_current_screen()
112 + * @since 2.0.0 bbPress (r3119)
124 113 */
125 114 public function edit_help() {
126 115
127 - if ( $this->bail() ) return;
128 -
129 116 // Overview
130 - get_current_screen()->add_help_tab( array(
131 - 'id' => 'overview',
132 - 'title' => __( 'Overview', 'bbpress' ),
133 - 'content' =>
134 - '<p>' . __( 'This screen displays the individual topics on your site. You can customize the display of this screen to suit your workflow.', 'bbpress' ) . '</p>'
135 - ) );
117 + get_current_screen()->add_help_tab(
118 + array(
119 + 'id' => 'overview',
120 + 'title' => __( 'Overview', 'bbpress' ),
121 + 'content' =>
122 + '<p>' . __( 'This screen displays the individual topics on your site. You can customize the display of this screen to suit your workflow.', 'bbpress' ) . '</p>'
123 + )
124 + );
136 125
137 126 // Screen Content
138 - get_current_screen()->add_help_tab( array(
139 - 'id' => 'screen-content',
140 - 'title' => __( 'Screen Content', 'bbpress' ),
141 - 'content' =>
142 - '<p>' . __( 'You can customize the display of this screen&#8217;s contents in a number of ways:', 'bbpress' ) . '</p>' .
143 - '<ul>' .
144 - '<li>' . __( 'You can hide/display columns based on your needs and decide how many topics to list per screen using the Screen Options tab.', 'bbpress' ) . '</li>' .
145 - '<li>' . __( 'You can filter the list of topics by topic status using the text links in the upper left to show All, Published, or Trashed topics. The default view is to show all topics.', 'bbpress' ) . '</li>' .
146 - '<li>' . __( 'You can refine the list to show only topics from a specific month by using the dropdown menus above the topics list. Click the Filter button after making your selection. You also can refine the list by clicking on the topic creator in the topics list.', 'bbpress' ) . '</li>' .
147 - '</ul>'
148 - ) );
127 + get_current_screen()->add_help_tab(
128 + array(
129 + 'id' => 'screen-content',
130 + 'title' => __( 'Screen Content', 'bbpress' ),
131 + 'content' =>
132 + '<p>' . __( 'You can customize the display of this screen&#8217;s contents in a number of ways:', 'bbpress' ) . '</p>' .
133 + '<ul>' .
134 + '<li>' . __( 'You can hide/display columns based on your needs and decide how many topics to list per screen using the Screen Options tab.', 'bbpress' ) . '</li>' .
135 + '<li>' . __( 'You can filter the list of topics by topic status using the text links in the upper left to show All, Published, Draft, Pending, Trashed, Closed, or Spam topics. The default view is to show all topics.', 'bbpress' ) . '</li>' .
136 + '<li>' . __( 'You can view topics in a simple title list or with an excerpt. Choose the view you prefer by clicking on the icons at the top of the list on the right.', 'bbpress' ) . '</li>' .
137 + '<li>' . __( 'You can refine the list to show only topics in a specific forum or from a specific month by using the dropdown menus above the topics list. Click the Filter button after making your selection.', 'bbpress' ) . '</li>' .
138 + '</ul>'
139 + )
140 + );
149 141
150 142 // Available Actions
151 - get_current_screen()->add_help_tab( array(
152 - 'id' => 'action-links',
153 - 'title' => __( 'Available Actions', 'bbpress' ),
154 - 'content' =>
155 - '<p>' . __( 'Hovering over a row in the topics list will display action links that allow you to manage your topic. You can perform the following actions:', 'bbpress' ) . '</p>' .
156 - '<ul>' .
157 - '<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that topic. You can also reach that screen by clicking on the topic title.', 'bbpress' ) . '</li>' .
158 - '<li>' . __( '<strong>Trash</strong> removes your topic from this list and places it in the trash, from which you can permanently delete it.', 'bbpress' ) . '</li>' .
159 - '<li>' . __( '<strong>Spam</strong> removes your topic from this list and places it in the spam queue, from which you can permanently delete it.', 'bbpress' ) . '</li>' .
160 - '<li>' . __( '<strong>Preview</strong> will show you what your draft topic will look like if you publish it. View will take you to your live site to view the topic. Which link is available depends on your topic&#8217;s status.', 'bbpress' ) . '</li>' .
161 - '<li>' . __( '<strong>Close</strong> will mark the selected topic as &#8217;closed&#8217; and disable the option to post new replies to the topic.', 'bbpress' ) . '</li>' .
162 - '<li>' . __( '<strong>Stick</strong> will keep the selected topic &#8217;pinned&#8217; to the top the parent forum topic list.', 'bbpress' ) . '</li>' .
163 - '<li>' . __( '<strong>Stick <em>(to front)</em></strong> will keep the selected topic &#8217;pinned&#8217; to the top of ALL forums and be visable in any forums topics list.', 'bbpress' ) . '</li>' .
164 - '</ul>'
165 - ) );
143 + get_current_screen()->add_help_tab(
144 + array(
145 + 'id' => 'action-links',
146 + 'title' => __( 'Available Actions', 'bbpress' ),
147 + 'content' =>
148 + '<p>' . __( 'Hovering over a row in the topics list will display action links that allow you to manage your topic. You can perform the following actions:', 'bbpress' ) . '</p>' .
149 + '<ul>' .
150 + '<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that topic. You can also reach that screen by clicking on the topic title.', 'bbpress' ) . '</li>' .
151 + '<li>' . __( '<strong>Stick</strong> will keep the selected topic &#8217;pinned&#8217; to the top the parent forum topic list.', 'bbpress' ) . '</li>' .
152 + '<li>' . __( '<strong>Stick <em>(to front)</em></strong> will keep the selected topic &#8217;pinned&#8217; to the top of ALL forums and be visable in any forums topics list.', 'bbpress' ) . '</li>' .
153 + '<li>' . __( '<strong>Approve</strong> will change the status from pending to publish.', 'bbpress' ) . '</li>' .
154 + '<li>' . __( '<strong>Close</strong> will mark the selected topic as &#8217;closed&#8217; and disable the ability to post new replies to it.', 'bbpress' ) . '</li>' .
155 + '<li>' . __( '<strong>Spam</strong> removes your topic from this list and places it in the spam queue, from which you can permanently delete it.', 'bbpress' ) . '</li>' .
156 + '<li>' . __( '<strong>Trash</strong> removes your topic from this list and places it in the trash, from which you can permanently delete it.', 'bbpress' ) . '</li>' .
157 + '<li>' . __( '<strong>View</strong> will take you to your live site to view the topic.', 'bbpress' ) . '</li>' .
158 + '</ul>'
159 + )
160 + );
166 161
167 162 // Bulk Actions
168 - get_current_screen()->add_help_tab( array(
169 - 'id' => 'bulk-actions',
170 - 'title' => __( 'Bulk Actions', 'bbpress' ),
171 - 'content' =>
172 - '<p>' . __( 'You can also edit or move multiple topics to the trash at once. Select the topics you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply.', 'bbpress' ) . '</p>' .
173 - '<p>' . __( 'When using Bulk Edit, you can change the metadata (categories, author, etc.) for all selected topics at once. To remove a topic from the grouping, just click the x next to its name in the Bulk Edit area that appears.', 'bbpress' ) . '</p>'
174 - ) );
163 + get_current_screen()->add_help_tab(
164 + array(
165 + 'id' => 'bulk-actions',
166 + 'title' => __( 'Bulk Actions', 'bbpress' ),
167 + 'content' =>
168 + '<p>' . __( 'You can also edit, spam, or move multiple topics to the trash at once. Select the topics you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply.', 'bbpress' ) . '</p>' .
169 + '<p>' . __( 'When using Bulk Edit, you can change the metadata (categories, author, etc.) for all selected topics at once. To remove a topic from the grouping, just click the x next to its name in the Bulk Edit area that appears.', 'bbpress' ) . '</p>'
170 + )
171 + );
175 172
176 173 // Help Sidebar
177 174 get_current_screen()->set_help_sidebar(
178 175 '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' .
179 - '<p>' . __( '<a href="http://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' .
180 - '<p>' . __( '<a href="http://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>'
176 + '<p>' . __( '<a href="https://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' .
177 + '<p>' . __( '<a href="https://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>'
181 178 );
182 179 }
183 180
184 181 /**
@@ -183,314 +180,399 @@
183 180
184 181 /**
185 182 * Contextual help for bbPress topic edit page
186 183 *
187 - * @since bbPress (r3119)
188 - * @uses get_current_screen()
184 + * @since 2.0.0 bbPress (r3119)
189 185 */
190 186 public function new_help() {
191 187
192 - if ( $this->bail() ) return;
193 -
194 188 $customize_display = '<p>' . __( 'The title field and the big topic editing Area are fixed in place, but you can reposition all the other boxes using drag and drop, and can minimize or expand them by clicking the title bar of each box. Use the Screen Options tab to unhide more boxes (Excerpt, Send Trackbacks, Custom Fields, Discussion, Slug, Author) or to choose a 1- or 2-column layout for this screen.', 'bbpress' ) . '</p>';
195 189
196 - get_current_screen()->add_help_tab( array(
197 - 'id' => 'customize-display',
198 - 'title' => __( 'Customizing This Display', 'bbpress' ),
199 - 'content' => $customize_display,
200 - ) );
190 + get_current_screen()->add_help_tab(
191 + array(
192 + 'id' => 'customize-display',
193 + 'title' => __( 'Customizing This Display', 'bbpress' ),
194 + 'content' => $customize_display,
195 + )
196 + );
201 197
202 - get_current_screen()->add_help_tab( array(
203 - 'id' => 'title-topic-editor',
204 - 'title' => __( 'Title and Topic Editor', 'bbpress' ),
205 - 'content' =>
206 - '<p>' . __( '<strong>Title</strong> - Enter a title for your topic. After you enter a title, you&#8217;ll see the permalink below, which you can edit.', 'bbpress' ) . '</p>' .
207 - '<p>' . __( '<strong>Topic Editor</strong> - Enter the text for your topic. There are two modes of editing: Visual and HTML. Choose the mode by clicking on the appropriate tab. Visual mode gives you a WYSIWYG editor. Click the last icon in the row to get a second row of controls. The HTML mode allows you to enter raw HTML along with your topic text. You can insert media files by clicking the icons above the topic editor and following the directions. You can go to the distraction-free writing screen via the Fullscreen icon in Visual mode (second to last in the top row) or the Fullscreen button in HTML mode (last in the row). Once there, you can make buttons visible by hovering over the top area. Exit Fullscreen back to the regular topic editor.', 'bbpress' ) . '</p>'
208 - ) );
198 + get_current_screen()->add_help_tab(
199 + array(
200 + 'id' => 'title-topic-editor',
201 + 'title' => __( 'Title and Topic Editor', 'bbpress' ),
202 + 'content' =>
203 + '<p>' . __( '<strong>Title</strong> - Enter a title for your topic. After you enter a title, you&#8217;ll see the permalink below, which you can edit.', 'bbpress' ) . '</p>' .
204 + '<p>' . __( '<strong>Topic Editor</strong> - Enter the text for your topic. There are two modes of editing: Visual and HTML. Choose the mode by clicking on the appropriate tab. Visual mode gives you a WYSIWYG editor. Click the last icon in the row to get a second row of controls. The HTML mode allows you to enter raw HTML along with your topic text. You can insert media files by clicking the icons above the topic editor and following the directions. You can go to the distraction-free writing screen via the Fullscreen icon in Visual mode (second to last in the top row) or the Fullscreen button in HTML mode (last in the row). Once there, you can make buttons visible by hovering over the top area. Exit Fullscreen back to the regular topic editor.', 'bbpress' ) . '</p>'
205 + )
206 + );
209 207
210 208 $publish_box = '<p>' . __( '<strong>Publish</strong> - You can set the terms of publishing your topic in the Publish box. For Status, Visibility, and Publish (immediately), click on the Edit link to reveal more options. Visibility includes options for password-protecting a topic or making it stay at the top of your blog indefinitely (sticky). Publish (immediately) allows you to set a future or past date and time, so you can schedule a topic to be published in the future or backdate a topic.', 'bbpress' ) . '</p>';
211 209
212 - if ( current_theme_supports( 'topic-formats' ) && topic_type_supports( 'topic', 'topic-formats' ) ) {
213 - $publish_box .= '<p>' . __( '<strong>topic Format</strong> - This designates how your theme will display a specific topic. For example, you could have a <em>standard</em> blog topic with a title and paragraphs, or a short <em>aside</em> that omits the title and contains a short text blurb. Please refer to the Codex for <a href="http://codex.wordpress.org/Post_Formats#Supported_Formats">descriptions of each topic format</a>. Your theme could enable all or some of 10 possible formats.', 'bbpress' ) . '</p>';
214 - }
215 -
216 - if ( current_theme_supports( 'topic-thumbnails' ) && topic_type_supports( 'topic', 'thumbnail' ) ) {
210 + if ( current_theme_supports( 'topic-thumbnails' ) && post_type_supports( bbp_get_topic_post_type(), 'thumbnail' ) ) {
217 211 $publish_box .= '<p>' . __( '<strong>Featured Image</strong> - This allows you to associate an image with your topic without inserting it. This is usually useful only if your theme makes use of the featured image as a topic thumbnail on the home page, a custom header, etc.', 'bbpress' ) . '</p>';
218 212 }
219 213
220 - get_current_screen()->add_help_tab( array(
221 - 'id' => 'topic-attributes',
222 - 'title' => __( 'Topic Attributes', 'bbpress' ),
223 - 'content' =>
224 - '<p>' . __( 'Select the attributes that your topic should have:', 'bbpress' ) . '</p>' .
225 - '<ul>' .
226 - '<li>' . __( '<strong>Forum</strong> dropdown determines the parent forum that the topic belongs to. Select the forum or category from the dropdown, or leave the default (No Forum) to post the topic without an assigned forum.', 'bbpress' ) . '</li>' .
227 - '<li>' . __( '<strong>Topic Type</strong> dropdown indicates the sticky status of the topic. Selecting the super sticky option would stick the topic to the front of your forums, i.e. the topic index, sticky option would stick the topic to its respective forum. Selecting normal would not stick the topic anywhere.', 'bbpress' ) . '</li>' .
228 - '</ul>'
229 - ) );
214 + get_current_screen()->add_help_tab(
215 + array(
216 + 'id' => 'topic-attributes',
217 + 'title' => __( 'Topic Attributes', 'bbpress' ),
218 + 'content' =>
219 + '<p>' . __( 'Select the attributes that your topic should have:', 'bbpress' ) . '</p>' .
220 + '<ul>' .
221 + '<li>' . __( '<strong>Forum</strong> dropdown determines the parent forum that the topic belongs to. Select the forum or category from the dropdown, or leave the default "No forum" to post the topic without an assigned forum.', 'bbpress' ) . '</li>' .
222 + '<li>' . __( '<strong>Topic Type</strong> dropdown indicates the sticky status of the topic. Selecting the super sticky option would stick the topic to the front of your forums, i.e. the topic index, sticky option would stick the topic to its respective forum. Selecting normal would not stick the topic anywhere.', 'bbpress' ) . '</li>' .
223 + '</ul>'
224 + )
225 + );
230 226
231 - get_current_screen()->add_help_tab( array(
232 - 'id' => 'publish-box',
233 - 'title' => __( 'Publish Box', 'bbpress' ),
234 - 'content' => $publish_box,
235 - ) );
227 + get_current_screen()->add_help_tab(
228 + array(
229 + 'id' => 'publish-box',
230 + 'title' => __( 'Publish Box', 'bbpress' ),
231 + 'content' => $publish_box,
232 + )
233 + );
236 234
237 - get_current_screen()->add_help_tab( array(
238 - 'id' => 'discussion-settings',
239 - 'title' => __( 'Discussion Settings', 'bbpress' ),
240 - 'content' =>
241 - '<p>' . __( '<strong>Send Trackbacks</strong> - Trackbacks are a way to notify legacy blog systems that you&#8217;ve linked to them. Enter the URL(s) you want to send trackbacks. If you link to other WordPress sites they&#8217;ll be notified automatically using pingbacks, and this field is unnecessary.', 'bbpress' ) . '</p>' .
242 - '<p>' . __( '<strong>Discussion</strong> - You can turn comments and pings on or off, and if there are comments on the topic, you can see them here and moderate them.', 'bbpress' ) . '</p>'
243 - ) );
244 -
245 235 get_current_screen()->set_help_sidebar(
246 236 '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' .
247 - '<p>' . __( '<a href="http://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' .
248 - '<p>' . __( '<a href="http://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>'
237 + '<p>' . __( '<a href="https://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' .
238 + '<p>' . __( '<a href="https://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>'
249 239 );
250 240 }
251 241
252 242 /**
253 - * Add the topic attributes metabox
243 + * Add spam/unspam bulk actions to the bulk action dropdown.
254 244 *
255 - * @since bbPress (r2744)
245 + * @since 2.6.0 bbPress (r6101)
256 246 *
257 - * @uses bbp_get_topic_post_type() To get the topic post type
258 - * @uses add_meta_box() To add the metabox
259 - * @uses do_action() Calls 'bbp_topic_attributes_metabox'
247 + * @param array $actions The list of bulk actions.
248 + * @return array The filtered list of bulk actions.
260 249 */
261 - public function attributes_metabox() {
250 + public function bulk_actions( $actions ) {
262 251
263 - if ( $this->bail() ) return;
252 + if ( current_user_can( 'moderate' ) ) {
253 + if ( bbp_get_spam_status_id() === get_query_var( 'post_status' ) ) {
254 + $actions['unspam'] = esc_html__( 'Unspam', 'bbpress' );
255 + } else {
256 + $actions['spam'] = esc_html__( 'Spam', 'bbpress' );
257 + }
258 + }
264 259
265 - add_meta_box (
266 - 'bbp_topic_attributes',
267 - __( 'Topic Attributes', 'bbpress' ),
268 - 'bbp_topic_metabox',
269 - $this->post_type,
270 - 'side',
271 - 'high'
272 - );
260 + return $actions;
261 + }
273 262
274 - do_action( 'bbp_topic_attributes_metabox' );
263 + /**
264 + * Add custom bulk action updated messages for topics.
265 + *
266 + * @since 2.6.0 bbPress (r6101)
267 + *
268 + * @param array $bulk_messages Arrays of messages, each keyed by the corresponding post type.
269 + * @param array $bulk_counts Array of item counts for each message, used to build internationalized strings.
270 + */
271 + public function bulk_post_updated_messages( $bulk_messages, $bulk_counts ) {
272 + /* translators: %s: Number of topics */
273 + $bulk_messages['topic']['updated'] = _n( '%s topic updated.', '%s topics updated.', $bulk_counts['updated'], 'bbpress' );
274 + $bulk_messages['topic']['locked'] = ( 1 === $bulk_counts['locked'] )
275 + ? __( '1 topic not updated, somebody is editing it.', 'bbpress' )
276 + /* translators: %s: Number of topics */
277 + : _n( '%s topic not updated, somebody is editing it.', '%s topics not updated, somebody is editing them.', $bulk_counts['locked'], 'bbpress' );
278 +
279 + return $bulk_messages;
275 280 }
276 281
277 282 /**
278 - * Pass the topic attributes for processing
283 + * Handle spam/unspam bulk actions.
279 284 *
280 - * @since bbPress (r2746)
285 + * @since 2.6.0 bbPress (r6101)
281 286 *
282 - * @param int $topic_id Topic id
283 - * @uses current_user_can() To check if the current user is capable of
284 - * editing the topic
285 - * @uses do_action() Calls 'bbp_topic_attributes_metabox_save' with the
286 - * topic id and parent id
287 - * @return int Parent id
287 + * @param string $sendback The sendback URL.
288 + * @param string $doaction The action to be taken.
289 + * @param array $post_ids The post IDS to take the action on.
290 + * @return string The sendback URL.
288 291 */
289 - public function attributes_metabox_save( $topic_id ) {
292 + public function handle_bulk_actions( $sendback, $doaction, $post_ids ) {
290 293
291 - if ( $this->bail() ) return $topic_id;
294 + $sendback = remove_query_arg( array( 'spam', 'unspam' ), $sendback );
295 + $updated = $locked = 0;
292 296
293 - // Bail if doing an autosave
294 - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
295 - return $topic_id;
297 + if ( 'spam' === $doaction ) {
296 298
297 - // Bail if not a post request
298 - if ( 'POST' != strtoupper( $_SERVER['REQUEST_METHOD'] ) )
299 - return $topic_id;
299 + foreach ( (array) $post_ids as $post_id ) {
300 + if ( ! current_user_can( 'moderate', $post_id ) ) {
301 + wp_die( esc_html__( 'Sorry, you are not allowed to spam this item.', 'bbpress' ) );
302 + }
300 303
301 - // Nonce check
302 - if ( empty( $_POST['bbp_topic_metabox'] ) || !wp_verify_nonce( $_POST['bbp_topic_metabox'], 'bbp_topic_metabox_save' ) )
303 - return $topic_id;
304 + if ( wp_check_post_lock( $post_id ) ) {
305 + $locked++;
306 + continue;
307 + }
304 308
305 - // Bail if current user cannot edit this topic
306 - if ( !current_user_can( 'edit_topic', $topic_id ) )
307 - return $topic_id;
309 + if ( ! bbp_spam_topic( $post_id ) ) {
310 + wp_die( esc_html__( 'Error in spamming topic.', 'bbpress' ) );
311 + }
308 312
309 - // Get the forum ID
310 - $forum_id = !empty( $_POST['parent_id'] ) ? (int) $_POST['parent_id'] : 0;
313 + ++$updated;
314 + }
311 315
312 - // Formally update the topic
313 - bbp_update_topic( $topic_id, $forum_id );
316 + $sendback = add_query_arg(
317 + array(
318 + 'updated' => $updated,
319 + 'ids' => implode( ',', $post_ids ),
320 + 'locked' => $locked
321 + ),
322 + $sendback
323 + );
314 324
315 - // Stickies
316 - if ( !empty( $_POST['bbp_stick_topic'] ) && in_array( $_POST['bbp_stick_topic'], array( 'stick', 'super', 'unstick' ) ) ) {
325 + } elseif ( 'unspam' === $doaction ) {
317 326
318 - // What's the haps?
319 - switch ( $_POST['bbp_stick_topic'] ) {
327 + foreach ( (array) $post_ids as $post_id ) {
328 + if ( ! current_user_can( 'moderate', $post_id ) ) {
329 + wp_die( esc_html__( 'Sorry, you are not allowed to unspam this topic.', 'bbpress' ) );
330 + }
320 331
321 - // Sticky in this forum
322 - case 'stick' :
323 - bbp_stick_topic( $topic_id );
324 - break;
332 + if ( wp_check_post_lock( $post_id ) ) {
333 + $locked++;
334 + continue;
335 + }
325 336
326 - // Super sticky in all forums
327 - case 'super' :
328 - bbp_stick_topic( $topic_id, true );
329 - break;
337 + if ( ! bbp_unspam_topic( $post_id ) ) {
338 + wp_die( esc_html__( 'Error in unspamming topic.', 'bbpress' ) );
339 + }
330 340
331 - // Normal
332 - case 'unstick' :
333 - default :
334 - bbp_unstick_topic( $topic_id );
335 - break;
341 + ++$updated;
336 342 }
343 +
344 + $sendback = add_query_arg(
345 + array(
346 + 'updated' => $updated,
347 + 'ids' => implode( ',', $post_ids ),
348 + 'locked' => $locked
349 + ),
350 + $sendback
351 + );
337 352 }
338 353
339 - // Allow other fun things to happen
340 - do_action( 'bbp_topic_attributes_metabox_save', $topic_id, $forum_id );
354 + return $sendback;
355 + }
341 356
342 - return $topic_id;
357 + /**
358 + * Add the topic attributes meta-box
359 + *
360 + * @since 2.0.0 bbPress (r2744)
361 + */
362 + public function attributes_metabox() {
363 + add_meta_box(
364 + 'bbp_topic_attributes',
365 + esc_html__( 'Topic Attributes', 'bbpress' ),
366 + 'bbp_topic_metabox',
367 + $this->post_type,
368 + 'side',
369 + 'high'
370 + );
343 371 }
344 372
345 373 /**
346 - * Add the author info metabox
374 + * Add the author info meta-box
347 375 *
348 - * @since bbPress (r2828)
349 - *
350 - * @uses bbp_get_topic() To get the topic
351 - * @uses bbp_get_reply() To get the reply
352 - * @uses bbp_get_topic_post_type() To get the topic post type
353 - * @uses bbp_get_reply_post_type() To get the reply post type
354 - * @uses add_meta_box() To add the metabox
355 - * @uses do_action() Calls 'bbp_author_metabox' with the topic/reply
356 - * id
376 + * @since 2.0.0 bbPress (r2828)
357 377 */
358 378 public function author_metabox() {
359 379
360 - if ( $this->bail() ) return;
361 -
362 380 // Bail if post_type is not a topic
363 - if ( empty( $_GET['action'] ) || ( 'edit' != $_GET['action'] ) )
381 + if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
364 382 return;
383 + }
365 384
366 - // Add the metabox
385 + // Add the meta-box
367 386 add_meta_box(
368 387 'bbp_author_metabox',
369 - __( 'Author Information', 'bbpress' ),
388 + esc_html__( 'Author Information', 'bbpress' ),
370 389 'bbp_author_metabox',
371 390 $this->post_type,
372 391 'side',
373 392 'high'
374 393 );
375 -
376 - do_action( 'bbp_author_metabox', get_the_ID() );
377 394 }
378 395
379 396 /**
380 - * Save the author information for the topic
397 + * Add the replies meta-box
381 398 *
382 - * @since bbPress (r2828)
399 + * Allows viewing & moderating of replies to a topic, based on the way
400 + * comments are visible on a blog post.
383 401 *
384 - * @param int $post_id Topic or reply id
385 - * @uses bbp_get_topic() To get the topic
386 - * @uses bbp_get_reply() To get the reply
387 - * @uses current_user_can() To check if the current user can edit the
388 - * topic or reply
389 - * @uses bbp_filter_author_post_data() To filter the author data
390 - * @uses update_post_meta() To update the anonymous user data
391 - * @uses do_action() Calls 'bbp_author_metabox_save' with the topic id and
392 - * anonymous data
393 - * @return int Topic or reply id
402 + * @since 2.6.0 bbPress (r5886)
394 403 */
395 - public function author_metabox_save( $post_id ) {
404 + public function replies_metabox() {
396 405
397 - if ( $this->bail() ) return $post_id;
406 + // Bail if post_type is not a reply
407 + if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
408 + return;
409 + }
398 410
399 - // Bail if no post_id
400 - if ( empty( $post_id ) )
401 - return $post_id;
411 + // Add the meta-box
412 + add_meta_box(
413 + 'bbp_topic_replies_metabox',
414 + esc_html__( 'Replies', 'bbpress' ),
415 + 'bbp_topic_replies_metabox',
416 + $this->post_type,
417 + 'normal',
418 + 'high'
419 + );
420 + }
402 421
403 - // Bail if doing an autosave
404 - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
405 - return $post_id;
422 + /**
423 + * Add the engagements meta-box
424 + *
425 + * Allows viewing of users who have engaged in a topic.
426 + *
427 + * @since 2.6.0 bbPress (r6333)
428 + */
429 + public function engagements_metabox() {
406 430
407 - // Bail if not a post request
408 - if ( 'POST' != strtoupper( $_SERVER['REQUEST_METHOD'] ) )
409 - return $post_id;
431 + // Bail when creating a new topic
432 + if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
433 + return;
434 + }
410 435
411 - // Bail if user cannot edit topics
412 - if ( !current_user_can( 'edit_topic', $post_id ) )
413 - return $post_id;
436 + // Bail if no engagements
437 + if ( ! bbp_is_engagements_active() ) {
438 + return;
439 + }
414 440
415 - $anonymous_data = bbp_filter_anonymous_post_data();
441 + // Add the meta-box
442 + add_meta_box(
443 + 'bbp_topic_engagements_metabox',
444 + esc_html__( 'Engagements', 'bbpress' ),
445 + 'bbp_topic_engagements_metabox',
446 + $this->post_type,
447 + 'side',
448 + 'low'
449 + );
450 + }
416 451
417 - update_post_meta( $post_id, '_bbp_anonymous_name', $anonymous_data['bbp_anonymous_name'] );
418 - update_post_meta( $post_id, '_bbp_anonymous_email', $anonymous_data['bbp_anonymous_email'] );
419 - update_post_meta( $post_id, '_bbp_anonymous_website', $anonymous_data['bbp_anonymous_website'] );
452 + /**
453 + * Add the favorites meta-box
454 + *
455 + * Allows viewing of users who have favorited a topic.
456 + *
457 + * @since 2.6.0 bbPress (r6197)
458 + */
459 + public function favorites_metabox() {
420 460
421 - do_action( 'bbp_author_metabox_save', $post_id, $anonymous_data );
461 + // Bail if post_type is not a reply
462 + if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
463 + return;
464 + }
422 465
423 - return $post_id;
466 + // Bail if no favorites
467 + if ( ! bbp_is_favorites_active() ) {
468 + return;
469 + }
470 +
471 + // Add the meta-box
472 + add_meta_box(
473 + 'bbp_topic_favorites_metabox',
474 + esc_html__( 'Favorites', 'bbpress' ),
475 + 'bbp_topic_favorites_metabox',
476 + $this->post_type,
477 + 'normal',
478 + 'high'
479 + );
424 480 }
425 481
426 482 /**
427 - * Add some general styling to the admin area
483 + * Add the subscriptions meta-box
428 484 *
429 - * @since bbPress (r2464)
485 + * Allows viewing of users who have subscribed to a topic.
430 486 *
431 - * @uses bbp_get_forum_post_type() To get the forum post type
432 - * @uses bbp_get_topic_post_type() To get the topic post type
433 - * @uses bbp_get_reply_post_type() To get the reply post type
434 - * @uses sanitize_html_class() To sanitize the classes
435 - * @uses do_action() Calls 'bbp_admin_head'
487 + * @since 2.6.0 bbPress (r6197)
436 488 */
437 - public function admin_head() {
489 + public function subscriptions_metabox() {
438 490
439 - if ( $this->bail() ) return;
491 + // Bail if post_type is not a reply
492 + if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
493 + return;
494 + }
440 495
441 - ?>
496 + // Bail if no subscriptions
497 + if ( ! bbp_is_subscriptions_active() ) {
498 + return;
499 + }
442 500
443 - <style type="text/css" media="screen">
444 - /*<![CDATA[*/
501 + // Add the meta-box
502 + add_meta_box(
503 + 'bbp_topic_subscriptions_metabox',
504 + esc_html__( 'Subscriptions', 'bbpress' ),
505 + 'bbp_topic_subscriptions_metabox',
506 + $this->post_type,
507 + 'normal',
508 + 'high'
509 + );
510 + }
445 511
446 - strong.label {
447 - display: inline-block;
448 - width: 60px;
449 - }
512 + /**
513 + * Remove comments & discussion meta-boxes if comments are not supported
514 + *
515 + * @since 2.6.0 bbPress (r6186)
516 + */
517 + public function comments_metabox() {
518 + if ( ! post_type_supports( $this->post_type, 'comments' ) ) {
519 + remove_meta_box( 'commentstatusdiv', $this->post_type, 'normal' );
520 + remove_meta_box( 'commentsdiv', $this->post_type, 'normal' );
521 + }
522 + }
450 523
451 - .column-bbp_forum_topic_count,
452 - .column-bbp_forum_reply_count,
453 - .column-bbp_topic_reply_count,
454 - .column-bbp_topic_voice_count {
455 - width: 8% !important;
456 - }
524 + /**
525 + * Pass the topic attributes for processing
526 + *
527 + * @since 2.0.0 bbPress (r2746)
528 + *
529 + * @param int $topic_id Topic id
530 + * @return int Parent id
531 + */
532 + public function save_meta_boxes( $topic_id ) {
457 533
458 - .column-author,
459 - .column-bbp_reply_author,
460 - .column-bbp_topic_author {
461 - width: 10% !important;
462 - }
534 + // Bail if doing an autosave
535 + if ( bbp_doing_autosave() ) {
536 + return $topic_id;
537 + }
463 538
464 - .column-bbp_topic_forum,
465 - .column-bbp_reply_forum,
466 - .column-bbp_reply_topic {
467 - width: 10% !important;
468 - }
539 + // Bail if not a post request
540 + if ( ! bbp_is_post_request() ) {
541 + return $topic_id;
542 + }
469 543
470 - .column-bbp_forum_freshness,
471 - .column-bbp_topic_freshness {
472 - width: 10% !important;
473 - }
544 + // Check action exists
545 + if ( empty( $_POST['action'] ) ) {
546 + return $topic_id;
547 + }
474 548
475 - .column-bbp_forum_created,
476 - .column-bbp_topic_created,
477 - .column-bbp_reply_created {
478 - width: 15% !important;
479 - }
549 + // Nonce check
550 + if ( empty( $_POST['bbp_topic_metabox'] ) || ! wp_verify_nonce( $_POST['bbp_topic_metabox'], 'bbp_topic_metabox_save' ) ) {
551 + return $topic_id;
552 + }
480 553
481 - .status-closed {
482 - background-color: #eaeaea;
483 - }
554 + // Bail if current user cannot edit this topic
555 + if ( ! current_user_can( 'edit_topic', $topic_id ) ) {
556 + return $topic_id;
557 + }
484 558
485 - .status-spam {
486 - background-color: #faeaea;
487 - }
559 + // Get the forum ID
560 + $forum_id = ! empty( $_POST['parent_id'] ) ? (int) $_POST['parent_id'] : 0;
488 561
489 - /*]]>*/
490 - </style>
562 + // Get topic author data
563 + $anonymous_data = bbp_filter_anonymous_post_data();
564 + $author_id = bbp_get_topic_author_id( $topic_id );
565 + $is_edit = ( isset( $_POST['hidden_post_status'] ) && ( 'draft' !== $_POST['hidden_post_status'] ) );
491 566
492 - <?php
567 + // Formally update the topic
568 + bbp_update_topic( $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit );
569 +
570 + // Allow other fun things to happen
571 + do_action( 'bbp_topic_attributes_metabox_save', $topic_id, $forum_id );
572 + do_action( 'bbp_author_metabox_save', $topic_id, $anonymous_data );
573 +
574 + return $topic_id;
493 575 }
494 576
495 577 /**
496 578 * Toggle topic
@@ -497,96 +579,119 @@
497 579 *
498 580 * Handles the admin-side opening/closing, sticking/unsticking and
499 581 * spamming/unspamming of topics
500 582 *
501 - * @since bbPress (r2727)
502 - *
503 - * @uses bbp_get_topic() To get the topic
504 - * @uses current_user_can() To check if the user is capable of editing
505 - * the topic
506 - * @uses wp_die() To die if the user isn't capable or the post wasn't
507 - * found
508 - * @uses check_admin_referer() To verify the nonce and check referer
509 - * @uses bbp_is_topic_open() To check if the topic is open
510 - * @uses bbp_close_topic() To close the topic
511 - * @uses bbp_open_topic() To open the topic
512 - * @uses bbp_is_topic_sticky() To check if the topic is a sticky or
513 - * super sticky
514 - * @uses bbp_unstick_topic() To unstick the topic
515 - * @uses bbp_stick_topic() To stick the topic
516 - * @uses bbp_is_topic_spam() To check if the topic is marked as spam
517 - * @uses bbp_unspam_topic() To unmark the topic as spam
518 - * @uses bbp_spam_topic() To mark the topic as spam
519 - * @uses do_action() Calls 'bbp_toggle_topic_admin' with success, post
520 - * data, action and message
521 - * @uses add_query_arg() To add custom args to the url
522 - * @uses wp_safe_redirect() Redirect the page to custom url
583 + * @since 2.0.0 bbPress (r2727)
523 584 */
524 585 public function toggle_topic() {
525 586
526 - if ( $this->bail() ) return;
587 + // Bail if not a topic toggle action
588 + if ( ! bbp_is_get_request() || empty( $_GET['action'] ) || empty( $_GET['topic_id'] ) ) {
589 + return;
590 + }
527 591
528 - // Only proceed if GET is a topic toggle action
529 - if ( 'GET' == $_SERVER['REQUEST_METHOD'] && !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_topic_close', 'bbp_toggle_topic_stick', 'bbp_toggle_topic_spam' ) ) && !empty( $_GET['topic_id'] ) ) {
530 - $action = $_GET['action']; // What action is taking place?
531 - $topic_id = (int) $_GET['topic_id']; // What's the topic id?
532 - $success = false; // Flag
533 - $post_data = array( 'ID' => $topic_id ); // Prelim array
534 - $topic = bbp_get_topic( $topic_id );
592 + // Bail if not an allowed action
593 + $action = sanitize_key( $_GET['action'] );
594 + if ( empty( $action ) || ! in_array( $action, $this->get_allowed_action_toggles(), true ) ) {
595 + return;
596 + }
535 597
536 - // Bail if topic is missing
537 - if ( empty( $topic ) )
538 - wp_die( __( 'The topic was not found!', 'bbpress' ) );
598 + // Bail if topic is missing
599 + $topic_id = bbp_get_topic_id( $_GET['topic_id'] );
600 + if ( ! bbp_get_topic( $topic_id ) ) {
601 + wp_die( esc_html__( 'The topic was not found.', 'bbpress' ) );
602 + }
539 603
540 - if ( !current_user_can( 'moderate', $topic->ID ) ) // What is the user doing here?
541 - wp_die( __( 'You do not have the permission to do that!', 'bbpress' ) );
604 + // What is the user doing here?
605 + if ( ! current_user_can( 'moderate', $topic_id ) ) {
606 + wp_die( esc_html__( 'You do not have permission to do that.', 'bbpress' ) );
607 + }
542 608
543 - switch ( $action ) {
544 - case 'bbp_toggle_topic_close' :
545 - check_admin_referer( 'close-topic_' . $topic_id );
609 + // Defaults
610 + $post_data = array( 'ID' => $topic_id );
611 + $message = '';
612 + $success = false;
546 613
547 - $is_open = bbp_is_topic_open( $topic_id );
548 - $message = true == $is_open ? 'closed' : 'opened';
549 - $success = true == $is_open ? bbp_close_topic( $topic_id ) : bbp_open_topic( $topic_id );
614 + switch ( $action ) {
615 + case 'bbp_toggle_topic_approve' :
616 + check_admin_referer( 'approve-topic_' . $topic_id );
550 617
551 - break;
618 + $is_approve = bbp_is_topic_public( $topic_id );
619 + $message = ( true === $is_approve )
620 + ? 'unapproved'
621 + : 'approved';
622 + $success = ( true === $is_approve )
623 + ? bbp_unapprove_topic( $topic_id )
624 + : bbp_approve_topic( $topic_id );
552 625
553 - case 'bbp_toggle_topic_stick' :
554 - check_admin_referer( 'stick-topic_' . $topic_id );
626 + break;
555 627
556 - $is_sticky = bbp_is_topic_sticky( $topic_id );
557 - $is_super = ( empty( $is_sticky ) && !empty( $_GET['super'] ) && 1 == (int) $_GET['super'] ) ? true : false;
558 - $message = true == $is_sticky ? 'unsticked' : 'sticked';
559 - $message = true == $is_super ? 'super_sticked' : $message;
560 - $success = true == $is_sticky ? bbp_unstick_topic( $topic_id ) : bbp_stick_topic( $topic_id, $is_super );
628 + case 'bbp_toggle_topic_close' :
629 + check_admin_referer( 'close-topic_' . $topic_id );
561 630
562 - break;
631 + $is_open = bbp_is_topic_open( $topic_id );
632 + $message = ( true === $is_open )
633 + ? 'closed'
634 + : 'opened';
635 + $success = ( true === $is_open )
636 + ? bbp_close_topic( $topic_id )
637 + : bbp_open_topic( $topic_id );
563 638
564 - case 'bbp_toggle_topic_spam' :
565 - check_admin_referer( 'spam-topic_' . $topic_id );
639 + break;
566 640
567 - $is_spam = bbp_is_topic_spam( $topic_id );
568 - $message = true == $is_spam ? 'unspammed' : 'spammed';
569 - $success = true == $is_spam ? bbp_unspam_topic( $topic_id ) : bbp_spam_topic( $topic_id );
641 + case 'bbp_toggle_topic_stick' :
642 + check_admin_referer( 'stick-topic_' . $topic_id );
570 643
571 - break;
572 - }
644 + $is_sticky = bbp_is_topic_sticky( $topic_id );
645 + $is_super = ( false === $is_sticky ) && ! empty( $_GET['super'] ) && ( '1' === $_GET['super'] )
646 + ? true
647 + : false;
648 + $message = ( true === $is_sticky )
649 + ? 'unstuck'
650 + : 'stuck';
651 + $message = ( true === $is_super )
652 + ? 'super_sticky'
653 + : $message;
654 + $success = ( true === $is_sticky )
655 + ? bbp_unstick_topic( $topic_id )
656 + : bbp_stick_topic( $topic_id, $is_super );
573 657
574 - $message = array( 'bbp_topic_toggle_notice' => $message, 'topic_id' => $topic->ID );
658 + break;
575 659
576 - if ( false == $success || is_wp_error( $success ) )
577 - $message['failed'] = '1';
660 + case 'bbp_toggle_topic_spam' :
661 + check_admin_referer( 'spam-topic_' . $topic_id );
578 662
579 - // Do additional topic toggle actions (admin side)
580 - do_action( 'bbp_toggle_topic_admin', $success, $post_data, $action, $message );
663 + $is_spam = bbp_is_topic_spam( $topic_id );
664 + $message = ( true === $is_spam )
665 + ? 'unspammed'
666 + : 'spammed';
667 + $success = ( true === $is_spam )
668 + ? bbp_unspam_topic( $topic_id )
669 + : bbp_spam_topic( $topic_id );
581 670
582 - // Redirect back to the topic
583 - $redirect = add_query_arg( $message, remove_query_arg( array( 'action', 'topic_id' ) ) );
584 - wp_safe_redirect( $redirect );
671 + break;
672 + }
585 673
586 - // For good measure
587 - exit();
674 + // Setup the message
675 + $retval = array(
676 + 'bbp_topic_toggle_notice' => $message,
677 + 'topic_id' => $topic_id
678 + );
679 +
680 + // Prepare for failure
681 + if ( ( false === $success ) || is_wp_error( $success ) ) {
682 + $retval['failed'] = '1';
588 683 }
684 +
685 + // Filter all message args
686 + $retval = apply_filters( 'bbp_toggle_topic_action_admin', $retval, $topic_id, $action );
687 +
688 + // Do additional topic toggle actions (admin side)
689 + do_action( 'bbp_toggle_topic_admin', $success, $post_data, $action, $retval );
690 +
691 + // Redirect back to the topic
692 + $redirect = add_query_arg( $retval, remove_query_arg( array( 'action', 'topic_id' ) ) );
693 + bbp_redirect( $redirect );
589 694 }
590 695
591 696 /**
592 697 * Toggle topic notices
@@ -593,137 +698,234 @@
593 698 *
594 699 * Display the success/error notices from
595 700 * {@link BBP_Admin::toggle_topic()}
596 701 *
597 - * @since bbPress (r2727)
598 - *
599 - * @uses bbp_get_topic() To get the topic
600 - * @uses bbp_get_topic_title() To get the topic title of the topic
601 - * @uses esc_html() To sanitize the topic title
602 - * @uses apply_filters() Calls 'bbp_toggle_topic_notice_admin' with
603 - * message, topic id, notice and is it a failure
702 + * @since 2.0.0 bbPress (r2727)
604 703 */
605 704 public function toggle_topic_notice() {
606 705
607 - if ( $this->bail() ) return;
706 + // Bail if missing topic toggle action
707 + if ( ! bbp_is_get_request() || empty( $_GET['topic_id'] ) || empty( $_GET['bbp_topic_toggle_notice'] ) ) {
708 + return;
709 + }
608 710
609 - // Only proceed if GET is a topic toggle action
610 - if ( 'GET' == $_SERVER['REQUEST_METHOD'] && !empty( $_GET['bbp_topic_toggle_notice'] ) && in_array( $_GET['bbp_topic_toggle_notice'], array( 'opened', 'closed', 'super_sticked', 'sticked', 'unsticked', 'spammed', 'unspammed' ) ) && !empty( $_GET['topic_id'] ) ) {
611 - $notice = $_GET['bbp_topic_toggle_notice']; // Which notice?
612 - $topic_id = (int) $_GET['topic_id']; // What's the topic id?
613 - $is_failure = !empty( $_GET['failed'] ) ? true : false; // Was that a failure?
711 + // Bail if not an allowed notice
712 + $notice = sanitize_key( $_GET['bbp_topic_toggle_notice'] );
713 + if ( empty( $notice ) || ! in_array( $notice, $this->get_allowed_notice_toggles(), true ) ) {
714 + return;
715 + }
614 716
615 - // Bais if no topic_id or notice
616 - if ( empty( $notice ) || empty( $topic_id ) )
617 - return;
717 + // Bail if no topic_id or notice
718 + $topic_id = bbp_get_topic_id( $_GET['topic_id'] );
719 + if ( empty( $topic_id ) ) {
720 + return;
721 + }
618 722
619 - // Bail if topic is missing
620 - $topic = bbp_get_topic( $topic_id );
621 - if ( empty( $topic ) )
622 - return;
723 + // Bail if topic is missing
724 + if ( ! bbp_get_topic( $topic_id ) ) {
725 + return;
726 + }
623 727
624 - $topic_title = esc_html( bbp_get_topic_title( $topic->ID ) );
728 + // Use the title in the responses
729 + $topic_title = bbp_get_topic_title( $topic_id );
730 + $is_failure = ! empty( $_GET['failed'] );
731 + $message = '';
625 732
626 - switch ( $notice ) {
627 - case 'opened' :
628 - $message = $is_failure == true ? sprintf( __( 'There was a problem opening the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully opened.', 'bbpress' ), $topic_title );
629 - break;
733 + // Which notice?
734 + switch ( $notice ) {
735 + case 'opened' :
736 + $message = ( true === $is_failure )
737 + /* translators: %1$s: Topic title */
738 + ? sprintf( esc_html__( 'There was a problem opening the topic "%1$s".', 'bbpress' ), $topic_title )
739 + /* translators: %1$s: Topic title */
740 + : sprintf( esc_html__( 'Topic "%1$s" successfully opened.', 'bbpress' ), $topic_title );
741 + break;
630 742
631 - case 'closed' :
632 - $message = $is_failure == true ? sprintf( __( 'There was a problem closing the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully closed.', 'bbpress' ), $topic_title );
633 - break;
743 + case 'closed' :
744 + $message = ( true === $is_failure )
745 + /* translators: %1$s: Topic title */
746 + ? sprintf( esc_html__( 'There was a problem closing the topic "%1$s".', 'bbpress' ), $topic_title )
747 + /* translators: %1$s: Topic title */
748 + : sprintf( esc_html__( 'Topic "%1$s" successfully closed.', 'bbpress' ), $topic_title );
749 + break;
634 750
635 - case 'super_sticked' :
636 - $message = $is_failure == true ? sprintf( __( 'There was a problem sticking the topic "%1$s" to front.', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully sticked to front.', 'bbpress' ), $topic_title );
637 - break;
751 + case 'super_sticky' :
752 + $message = ( true === $is_failure )
753 + /* translators: %1$s: Topic title */
754 + ? sprintf( esc_html__( 'There was a problem sticking the topic "%1$s" to front.', 'bbpress' ), $topic_title )
755 + /* translators: %1$s: Topic title */
756 + : sprintf( esc_html__( 'Topic "%1$s" successfully stuck to front.', 'bbpress' ), $topic_title );
757 + break;
638 758
639 - case 'sticked' :
640 - $message = $is_failure == true ? sprintf( __( 'There was a problem sticking the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully sticked.', 'bbpress' ), $topic_title );
641 - break;
759 + case 'stuck' :
760 + $message = ( true === $is_failure )
761 + /* translators: %1$s: Topic title */
762 + ? sprintf( esc_html__( 'There was a problem sticking the topic "%1$s".', 'bbpress' ), $topic_title )
763 + /* translators: %1$s: Topic title */
764 + : sprintf( esc_html__( 'Topic "%1$s" successfully stuck.', 'bbpress' ), $topic_title );
765 + break;
642 766
643 - case 'unsticked' :
644 - $message = $is_failure == true ? sprintf( __( 'There was a problem unsticking the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully unsticked.', 'bbpress' ), $topic_title );
645 - break;
767 + case 'unstuck' :
768 + $message = ( true === $is_failure )
769 + /* translators: %1$s: Topic title */
770 + ? sprintf( esc_html__( 'There was a problem unsticking the topic "%1$s".', 'bbpress' ), $topic_title )
771 + /* translators: %1$s: Topic title */
772 + : sprintf( esc_html__( 'Topic "%1$s" successfully unstuck.', 'bbpress' ), $topic_title );
773 + break;
646 774
647 - case 'spammed' :
648 - $message = $is_failure == true ? sprintf( __( 'There was a problem marking the topic "%1$s" as spam.', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully marked as spam.', 'bbpress' ), $topic_title );
649 - break;
775 + case 'spammed' :
776 + $message = ( true === $is_failure )
777 + /* translators: %1$s: Topic title */
778 + ? sprintf( esc_html__( 'There was a problem marking the topic "%1$s" as spam.', 'bbpress' ), $topic_title )
779 + /* translators: %1$s: Topic title */
780 + : sprintf( esc_html__( 'Topic "%1$s" successfully marked as spam.', 'bbpress' ), $topic_title );
781 + break;
650 782
651 - case 'unspammed' :
652 - $message = $is_failure == true ? sprintf( __( 'There was a problem unmarking the topic "%1$s" as spam.', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully unmarked as spam.', 'bbpress' ), $topic_title );
653 - break;
654 - }
783 + case 'unspammed' :
784 + $message = ( true === $is_failure )
785 + /* translators: %1$s: Topic title */
786 + ? sprintf( esc_html__( 'There was a problem unmarking the topic "%1$s" as spam.', 'bbpress' ), $topic_title )
787 + /* translators: %1$s: Topic title */
788 + : sprintf( esc_html__( 'Topic "%1$s" successfully unmarked as spam.', 'bbpress' ), $topic_title );
789 + break;
655 790
656 - // Do additional topic toggle notice filters (admin side)
657 - $message = apply_filters( 'bbp_toggle_topic_notice_admin', $message, $topic->ID, $notice, $is_failure );
791 + case 'approved' :
792 + $message = ( true === $is_failure )
793 + /* translators: %1$s: Topic title */
794 + ? sprintf( esc_html__( 'There was a problem approving the topic "%1$s".', 'bbpress' ), $topic_title )
795 + /* translators: %1$s: Topic title */
796 + : sprintf( esc_html__( 'Topic "%1$s" successfully approved.', 'bbpress' ), $topic_title );
797 + break;
658 798
659 - ?>
799 + case 'unapproved' :
800 + $message = ( true === $is_failure )
801 + /* translators: %1$s: Topic title */
802 + ? sprintf( esc_html__( 'There was a problem unapproving the topic "%1$s".', 'bbpress' ), $topic_title )
803 + /* translators: %1$s: Topic title */
804 + : sprintf( esc_html__( 'Topic "%1$s" successfully unapproved.', 'bbpress' ), $topic_title );
805 + break;
806 + }
660 807
661 - <div id="message" class="<?php echo $is_failure == true ? 'error' : 'updated'; ?> fade">
662 - <p style="line-height: 150%"><?php echo $message; ?></p>
663 - </div>
808 + // Do additional topic toggle notice filters (admin side)
809 + $message = apply_filters( 'bbp_toggle_topic_notice_admin', $message, $topic_id, $notice, $is_failure );
810 + $class = ( true === $is_failure )
811 + ? 'error'
812 + : 'updated';
664 813
665 - <?php
666 - }
814 + // Add the notice
815 + bbp_admin()->add_notice( $message, $class, true );
667 816 }
668 817
669 818 /**
819 + * Returns an array of keys used to sort row actions
820 + *
821 + * @since 2.6.0 bbPress (r6771)
822 + *
823 + * @return array
824 + */
825 + private function get_row_action_sort_order() {
826 +
827 + // Filter & return
828 + return (array) apply_filters(
829 + 'bbp_admin_topics_row_action_sort_order',
830 + array(
831 + 'edit',
832 + 'stick',
833 + 'approved',
834 + 'unapproved',
835 + 'closed',
836 + 'spam',
837 + 'unspam',
838 + 'trash',
839 + 'untrash',
840 + 'delete',
841 + 'view'
842 + )
843 + );
844 + }
845 +
846 + /**
847 + * Returns an array of notice toggles
848 + *
849 + * @since 2.6.0 bbPress (r6396)
850 + *
851 + * @return array
852 + */
853 + private function get_allowed_notice_toggles() {
854 +
855 + // Filter & return
856 + return (array) apply_filters(
857 + 'bbp_admin_topics_allowed_notice_toggles',
858 + array(
859 + 'opened',
860 + 'closed',
861 + 'super_sticky',
862 + 'stuck',
863 + 'unstuck',
864 + 'spammed',
865 + 'unspammed',
866 + 'approved',
867 + 'unapproved'
868 + )
869 + );
870 + }
871 +
872 + /**
873 + * Returns an array of notice toggles
874 + *
875 + * @since 2.6.0 bbPress (r6396)
876 + *
877 + * @return array
878 + */
879 + private function get_allowed_action_toggles() {
880 +
881 + // Filter & return
882 + return (array) apply_filters(
883 + 'bbp_admin_topics_allowed_action_toggles',
884 + array(
885 + 'bbp_toggle_topic_close',
886 + 'bbp_toggle_topic_stick',
887 + 'bbp_toggle_topic_spam',
888 + 'bbp_toggle_topic_approve'
889 + )
890 + );
891 + }
892 +
893 + /**
670 894 * Manage the column headers for the topics page
671 895 *
672 - * @since bbPress (r2485)
896 + * @since 2.0.0 bbPress (r2485)
673 897 *
674 898 * @param array $columns The columns
675 - * @uses apply_filters() Calls 'bbp_admin_topics_column_headers' with
676 - * the columns
899 + *
677 900 * @return array $columns bbPress topic columns
678 901 */
679 - public function topics_column_headers( $columns ) {
680 -
681 - if ( $this->bail() ) return $columns;
682 -
902 + public function column_headers( $columns ) {
683 903 $columns = array(
684 904 'cb' => '<input type="checkbox" />',
685 - 'title' => __( 'Topics', 'bbpress' ),
686 - 'bbp_topic_forum' => __( 'Forum', 'bbpress' ),
687 - 'bbp_topic_reply_count' => __( 'Replies', 'bbpress' ),
688 - 'bbp_topic_voice_count' => __( 'Voices', 'bbpress' ),
689 - 'bbp_topic_author' => __( 'Author', 'bbpress' ),
690 - 'bbp_topic_created' => __( 'Created', 'bbpress' ),
691 - 'bbp_topic_freshness' => __( 'Freshness', 'bbpress' )
905 + 'title' => esc_html__( 'Topics', 'bbpress' ),
906 + 'bbp_topic_forum' => esc_html__( 'Forum', 'bbpress' ),
907 + 'bbp_topic_reply_count' => esc_html__( 'Replies', 'bbpress' ),
908 + 'bbp_topic_voice_count' => esc_html__( 'Voices', 'bbpress' ),
909 + 'bbp_topic_author' => esc_html__( 'Author', 'bbpress' ),
910 + 'bbp_topic_created' => esc_html__( 'Created', 'bbpress' ),
911 + 'bbp_topic_freshness' => esc_html__( 'Last Post', 'bbpress' )
692 912 );
693 913
694 - return apply_filters( 'bbp_admin_topics_column_headers', $columns );
914 + // Filter & return
915 + return (array) apply_filters( 'bbp_admin_topics_column_headers', $columns );
695 916 }
696 917
697 918 /**
698 919 * Print extra columns for the topics page
699 920 *
700 - * @since bbPress (r2485)
921 + * @since 2.0.0 bbPress (r2485)
701 922 *
702 923 * @param string $column Column
703 924 * @param int $topic_id Topic id
704 - * @uses bbp_get_topic_forum_id() To get the forum id of the topic
705 - * @uses bbp_forum_title() To output the topic's forum title
706 - * @uses apply_filters() Calls 'topic_forum_row_actions' with an array
707 - * of topic forum actions
708 - * @uses bbp_get_forum_permalink() To get the forum permalink
709 - * @uses admin_url() To get the admin url of post.php
710 - * @uses add_query_arg() To add custom args to the url
711 - * @uses bbp_topic_reply_count() To output the topic reply count
712 - * @uses bbp_topic_voice_count() To output the topic voice count
713 - * @uses bbp_topic_author_display_name() To output the topic author name
714 - * @uses get_the_date() Get the topic creation date
715 - * @uses get_the_time() Get the topic creation time
716 - * @uses esc_attr() To sanitize the topic creation time
717 - * @uses bbp_get_topic_last_active_time() To get the time when the topic was
718 - * last active
719 - * @uses do_action() Calls 'bbp_admin_topics_column_data' with the
720 - * column and topic id
721 925 */
722 - function topics_column_data( $column, $topic_id ) {
926 + public function column_data( $column, $topic_id ) {
723 927
724 - if ( $this->bail() ) return;
725 -
726 928 // Get topic forum ID
727 929 $forum_id = bbp_get_topic_forum_id( $topic_id );
728 930
729 931 // Populate column data
@@ -731,22 +933,23 @@
731 933
732 934 // Forum
733 935 case 'bbp_topic_forum' :
734 936
937 + // Get title
938 + $forum_title = ! empty( $forum_id )
939 + ? bbp_get_forum_title( $forum_id )
940 + : '';
941 +
735 942 // Output forum name
736 - if ( !empty( $forum_id ) ) {
737 -
738 - // Forum Title
739 - $forum_title = bbp_get_forum_title( $forum_id );
740 - if ( empty( $forum_title ) ) {
741 - $forum_title = __( 'No Forum', 'bbpress' );
742 - }
743 -
744 - // Output the title
943 + if ( ! empty( $forum_title ) ) {
745 944 echo $forum_title;
746 945
946 + // Output dash
747 947 } else {
748 - _e( '(No Forum)', 'bbpress' );
948 + ?>
949 + <span aria-hidden="true">&mdash;</span>
950 + <span class="screen-reader-text"><?php esc_html_e( 'No forum', 'bbpress' ); ?></span>
951 + <?php
749 952 }
750 953
751 954 break;
752 955
@@ -766,9 +969,9 @@
766 969 break;
767 970
768 971 // Freshness
769 972 case 'bbp_topic_created':
770 - printf( __( '%1$s <br /> %2$s', 'bbpress' ),
973 + printf( '%1$s <br /> %2$s',
771 974 get_the_date(),
772 975 esc_attr( get_the_time() )
773 976 );
774 977
@@ -776,12 +979,12 @@
776 979
777 980 // Freshness
778 981 case 'bbp_topic_freshness' :
779 982 $last_active = bbp_get_topic_last_active_time( $topic_id, false );
780 - if ( !empty( $last_active ) ) {
781 - echo $last_active;
983 + if ( ! empty( $last_active ) ) {
984 + echo esc_html( $last_active );
782 985 } else {
783 - _e( 'No Replies', 'bbpress' ); // This should never happen
986 + esc_html_e( 'No Replies', 'bbpress' ); // This should never happen
784 987 }
785 988
786 989 break;
787 990
@@ -797,143 +1000,222 @@
797 1000 *
798 1001 * Remove the quick-edit action link under the topic title and add the
799 1002 * content and close/stick/spam links
800 1003 *
801 - * @since bbPress (r2485)
1004 + * @since 2.0.0 bbPress (r2485)
802 1005 *
803 - * @param array $actions Actions
804 - * @param array $topic Topic object
805 - * @uses bbp_get_topic_post_type() To get the topic post type
806 - * @uses bbp_topic_content() To output topic content
807 - * @uses bbp_get_topic_permalink() To get the topic link
808 - * @uses bbp_get_topic_title() To get the topic title
809 - * @uses current_user_can() To check if the current user can edit or
810 - * delete the topic
811 - * @uses bbp_is_topic_open() To check if the topic is open
812 - * @uses bbp_is_topic_spam() To check if the topic is marked as spam
813 - * @uses bbp_is_topic_sticky() To check if the topic is a sticky or a
814 - * super sticky
815 - * @uses get_post_type_object() To get the topic post type object
816 - * @uses add_query_arg() To add custom args to the url
817 - * @uses remove_query_arg() To remove custom args from the url
818 - * @uses wp_nonce_url() To nonce the url
819 - * @uses get_delete_post_link() To get the delete post link of the topic
1006 + * @param array $actions Actions
1007 + * @param object $topic Topic object
1008 + *
820 1009 * @return array $actions Actions
821 1010 */
822 - public function topics_row_actions( $actions, $topic ) {
1011 + public function row_actions( $actions = array(), $topic = false ) {
823 1012
824 - if ( $this->bail() ) return $actions;
1013 + // Disable quick edit (too much to do here)
1014 + unset( $actions['inline hide-if-no-js'] );
825 1015
826 - unset( $actions['inline hide-if-no-js'] );
1016 + // View link
1017 + $view_link = bbp_get_topic_permalink( $topic->ID );
827 1018
1019 + // Maybe add view=all
1020 + if ( ! in_array( $topic->post_status, array( bbp_get_closed_status_id(), bbp_get_public_status_id() ), true ) ) {
1021 + $view_link = bbp_add_view_all( $view_link, true );
1022 + }
1023 +
828 1024 // Show view link if it's not set, the topic is trashed and the user can view trashed topics
829 - if ( empty( $actions['view'] ) && ( bbp_get_trash_status_id() == $topic->post_status ) && current_user_can( 'view_trash' ) )
830 - $actions['view'] = '<a href="' . bbp_get_topic_permalink( $topic->ID ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'bbpress' ), bbp_get_topic_title( $topic->ID ) ) ) . '" rel="permalink">' . __( 'View', 'bbpress' ) . '</a>';
1025 + if ( empty( $actions['view'] ) && ( bbp_get_trash_status_id() === $topic->post_status ) && current_user_can( 'view_trash' ) ) {
1026 + /* translators: %s: Topic title */
1027 + $actions['view'] = '<a href="' . esc_url( $view_link ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'bbpress' ), bbp_get_topic_title( $topic->ID ) ) ) . '" rel="permalink">' . esc_html__( 'View', 'bbpress' ) . '</a>';
1028 + }
831 1029
832 1030 // Only show the actions if the user is capable of viewing them :)
833 1031 if ( current_user_can( 'moderate', $topic->ID ) ) {
834 1032
1033 + // Pending
1034 + // Show the 'approve' and 'view' link on pending posts only and 'unapprove' on published posts only
1035 + $args = array(
1036 + 'topic_id' => $topic->ID,
1037 + 'action' => 'bbp_toggle_topic_approve'
1038 + );
1039 + $approve_uri = wp_nonce_url( add_query_arg( $args, remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'approve-topic_' . $topic->ID );
1040 + if ( bbp_is_topic_public( $topic->ID ) ) {
1041 + $actions['unapproved'] = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Unapprove this topic', 'bbpress' ) . '">' . _x( 'Unapprove', 'Unapprove Topic', 'bbpress' ) . '</a>';
1042 + } else {
1043 +
1044 + // Do not show 'approve' if already public
1045 + if ( ! bbp_is_topic_public( $topic->ID ) ) {
1046 + $actions['approved'] = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Approve this topic', 'bbpress' ) . '">' . _x( 'Approve', 'Approve Topic', 'bbpress' ) . '</a>';
1047 + }
1048 +
1049 + // Modify the view link
1050 + /* translators: %s: Topic title */
1051 + $actions['view'] = '<a href="' . esc_url( $view_link ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'bbpress' ), bbp_get_topic_title( $topic->ID ) ) ) . '" rel="permalink">' . esc_html__( 'View', 'bbpress' ) . '</a>';
1052 + }
1053 +
835 1054 // Close
836 1055 // Show the 'close' and 'open' link on published and closed posts only
837 - if ( in_array( $topic->post_status, array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ) ) {
838 - $close_uri = esc_url( wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_close' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'close-topic_' . $topic->ID ) );
839 - if ( bbp_is_topic_open( $topic->ID ) )
840 - $actions['closed'] = '<a href="' . $close_uri . '" title="' . esc_attr__( 'Close this topic', 'bbpress' ) . '">' . _x( 'Close', 'Close a Topic', 'bbpress' ) . '</a>';
841 - else
842 - $actions['closed'] = '<a href="' . $close_uri . '" title="' . esc_attr__( 'Open this topic', 'bbpress' ) . '">' . _x( 'Open', 'Open a Topic', 'bbpress' ) . '</a>';
1056 + if ( bbp_is_topic_public( $topic->ID ) ) {
1057 + $args = array(
1058 + 'topic_id' => $topic->ID,
1059 + 'action' => 'bbp_toggle_topic_close'
1060 + );
1061 + $close_uri = wp_nonce_url( add_query_arg( $args, remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'close-topic_' . $topic->ID );
1062 + if ( bbp_is_topic_open( $topic->ID ) ) {
1063 + $actions['closed'] = '<a href="' . esc_url( $close_uri ) . '" title="' . esc_attr__( 'Close this topic', 'bbpress' ) . '">' . _x( 'Close', 'Close a Topic', 'bbpress' ) . '</a>';
1064 + } else {
1065 + $actions['closed'] = '<a href="' . esc_url( $close_uri ) . '" title="' . esc_attr__( 'Open this topic', 'bbpress' ) . '">' . _x( 'Open', 'Open a Topic', 'bbpress' ) . '</a>';
1066 + }
843 1067 }
844 1068
845 - // Dont show sticky if topic links is spam or trash
846 - if ( !bbp_is_topic_spam( $topic->ID ) && !bbp_is_topic_trash( $topic->ID ) ) {
847 -
848 - // Sticky
849 - $stick_uri = esc_url( wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_stick' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_' . $topic->ID ) );
1069 + // Sticky
1070 + // Dont show sticky if topic is spam, trash or pending
1071 + if ( ! bbp_is_topic_spam( $topic->ID ) && ! bbp_is_topic_trash( $topic->ID ) && ! bbp_is_topic_pending( $topic->ID ) ) {
1072 + $args = array(
1073 + 'topic_id' => $topic->ID,
1074 + 'action' => 'bbp_toggle_topic_stick'
1075 + );
1076 + $stick_uri = wp_nonce_url( add_query_arg( $args, remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_' . $topic->ID );
850 1077 if ( bbp_is_topic_sticky( $topic->ID ) ) {
851 - $actions['stick'] = '<a href="' . $stick_uri . '" title="' . esc_attr__( 'Unstick this topic', 'bbpress' ) . '">' . __( 'Unstick', 'bbpress' ) . '</a>';
1078 + $actions['stick'] = '<a href="' . esc_url( $stick_uri ) . '" title="' . esc_attr__( 'Unstick this topic', 'bbpress' ) . '">' . esc_html__( 'Unstick', 'bbpress' ) . '</a>';
852 1079 } else {
853 - $super_uri = esc_url( wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_stick', 'super' => '1' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_' . $topic->ID ) );
854 - $actions['stick'] = '<a href="' . $stick_uri . '" title="' . esc_attr__( 'Stick this topic to its forum', 'bbpress' ) . '">' . __( 'Stick', 'bbpress' ) . '</a> (<a href="' . $super_uri . '" title="' . esc_attr__( 'Stick this topic to front', 'bbpress' ) . '">' . __( 'to front', 'bbpress' ) . '</a>)';
1080 + $args = array(
1081 + 'topic_id' => $topic->ID,
1082 + 'action' => 'bbp_toggle_topic_stick',
1083 + 'super' => '1'
1084 + );
1085 + $super_uri = wp_nonce_url( add_query_arg( $args, remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_' . $topic->ID );
1086 + $actions['stick'] = '<a href="' . esc_url( $stick_uri ) . '" title="' . esc_attr__( 'Stick this topic to its forum', 'bbpress' ) . '">' . esc_html__( 'Stick', 'bbpress' ) . '</a> <a href="' . esc_url( $super_uri ) . '" title="' . esc_attr__( 'Stick this topic to front', 'bbpress' ) . '">' . esc_html__( '(to front)', 'bbpress' ) . '</a>';
855 1087 }
856 1088 }
857 1089
858 1090 // Spam
859 - $spam_uri = esc_url( wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_spam' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'spam-topic_' . $topic->ID ) );
860 - if ( bbp_is_topic_spam( $topic->ID ) )
861 - $actions['spam'] = '<a href="' . $spam_uri . '" title="' . esc_attr__( 'Mark the topic as not spam', 'bbpress' ) . '">' . __( 'Not spam', 'bbpress' ) . '</a>';
862 - else
863 - $actions['spam'] = '<a href="' . $spam_uri . '" title="' . esc_attr__( 'Mark this topic as spam', 'bbpress' ) . '">' . __( 'Spam', 'bbpress' ) . '</a>';
864 -
1091 + $args = array(
1092 + 'topic_id' => $topic->ID,
1093 + 'action' => 'bbp_toggle_topic_spam'
1094 + );
1095 + $spam_uri = wp_nonce_url( add_query_arg( $args, remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'spam-topic_' . $topic->ID );
1096 + if ( ! bbp_is_topic_spam( $topic->ID ) ) {
1097 + $actions['spam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark this topic as spam', 'bbpress' ) . '">' . esc_html__( 'Spam', 'bbpress' ) . '</a>';
1098 + } else {
1099 + $actions['unspam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark the topic as not spam', 'bbpress' ) . '">' . esc_html__( 'Not Spam', 'bbpress' ) . '</a>';
1100 + }
865 1101 }
866 1102
867 1103 // Do not show trash links for spam topics, or spam links for trashed topics
868 1104 if ( current_user_can( 'delete_topic', $topic->ID ) ) {
869 - if ( bbp_get_trash_status_id() == $topic->post_status ) {
1105 + $trash_days = bbp_get_trash_days( bbp_get_topic_post_type() );
1106 +
1107 + if ( bbp_get_trash_status_id() === $topic->post_status ) {
870 1108 $post_type_object = get_post_type_object( bbp_get_topic_post_type() );
871 - $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . "' href='" . wp_nonce_url( add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_topic_post_type() ), admin_url( 'edit.php' ) ) ), admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $topic->ID ) ) ), 'untrash-' . $topic->post_type . '_' . $topic->ID ) . "'>" . __( 'Restore', 'bbpress' ) . "</a>";
872 - } elseif ( EMPTY_TRASH_DAYS ) {
873 - $actions['trash'] = "<a class='submitdelete' title='" . esc_attr__( 'Move this item to the Trash', 'bbpress' ) . "' href='" . add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_topic_post_type() ), admin_url( 'edit.php' ) ) ), get_delete_post_link( $topic->ID ) ) . "'>" . __( 'Trash', 'bbpress' ) . "</a>";
1109 + $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . "' href='" . esc_url( wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $topic->ID ) ), 'untrash-post_' . $topic->ID ) ) . "'>" . esc_html__( 'Restore', 'bbpress' ) . '</a>';
1110 + } elseif ( ! empty( $trash_days ) ) {
1111 + $actions['trash'] = "<a class='submitdelete' title='" . esc_attr__( 'Move this item to the Trash', 'bbpress' ) . "' href='" . esc_url( get_delete_post_link( $topic->ID ) ) . "'>" . esc_html__( 'Trash', 'bbpress' ) . '</a>';
874 1112 }
875 1113
876 - if ( bbp_get_trash_status_id() == $topic->post_status || !EMPTY_TRASH_DAYS ) {
877 - $actions['delete'] = "<a class='submitdelete' title='" . esc_attr__( 'Delete this item permanently', 'bbpress' ) . "' href='" . add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_topic_post_type() ), admin_url( 'edit.php' ) ) ), get_delete_post_link( $topic->ID, '', true ) ) . "'>" . __( 'Delete Permanently', 'bbpress' ) . "</a>";
878 - } elseif ( bbp_get_spam_status_id() == $topic->post_status ) {
879 - unset( $actions['trash'] );
1114 + if ( ( bbp_get_trash_status_id() === $topic->post_status ) || empty( $trash_days ) ) {
1115 + $actions['delete'] = "<a class='submitdelete' title='" . esc_attr__( 'Delete this item permanently', 'bbpress' ) . "' href='" . esc_url( get_delete_post_link( $topic->ID, '', true ) ) . "'>" . esc_html__( 'Delete Permanently', 'bbpress' ) . '</a>';
880 1116 }
881 1117 }
882 1118
883 - return $actions;
1119 + // Sort & return
1120 + return $this->sort_row_actions( $actions );
884 1121 }
885 1122
886 1123 /**
1124 + * Sort row actions by key
1125 + *
1126 + * @since 2.6.0
1127 + *
1128 + * @param array $actions
1129 + *
1130 + * @return array
1131 + */
1132 + private function sort_row_actions( $actions = array() ) {
1133 +
1134 + // Return value
1135 + $retval = array();
1136 +
1137 + // Known row actions, in sort order
1138 + $known_actions = $this->get_row_action_sort_order();
1139 +
1140 + // Sort known actions, and keep any unknown ones
1141 + foreach ( $known_actions as $key ) {
1142 + if ( isset( $actions[ $key ] ) ) {
1143 + $retval[ $key ] = $actions[ $key ];
1144 + unset( $actions[ $key ] );
1145 + }
1146 + }
1147 +
1148 + // Combine & return
1149 + return $retval + $actions;
1150 + }
1151 +
1152 + /**
887 1153 * Add forum dropdown to topic and reply list table filters
888 1154 *
889 - * @since bbPress (r2991)
1155 + * @since 2.0.0 bbPress (r2991)
890 1156 *
891 - * @uses bbp_get_reply_post_type() To get the reply post type
892 - * @uses bbp_get_topic_post_type() To get the topic post type
893 - * @uses bbp_dropdown() To generate a forum dropdown
894 1157 * @return bool False. If post type is not topic or reply
895 1158 */
896 1159 public function filter_dropdown() {
897 1160
898 - if ( $this->bail() ) return;
1161 + // Get which forum is selected
1162 + $selected = ! empty( $_GET['bbp_forum_id'] )
1163 + ? (int) $_GET['bbp_forum_id']
1164 + : 0;
899 1165
900 - // Add Empty Spam button
901 - if ( !empty( $_GET['post_status'] ) && ( bbp_get_spam_status_id() == $_GET['post_status'] ) && current_user_can( 'moderate' ) ) {
902 - wp_nonce_field( 'bulk-destroy', '_destroy_nonce' );
903 - $title = esc_attr__( 'Empty Spam', 'bbpress' );
904 - submit_button( $title, 'button-secondary apply', 'delete_all', false );
1166 + // Show the forums dropdown
1167 + bbp_dropdown(
1168 + array(
1169 + 'selected' => $selected,
1170 + 'show_none' => esc_html__( 'In all forums', 'bbpress' )
1171 + )
1172 + );
1173 + }
1174 +
1175 + /**
1176 + * Add "Empty Spam" button for moderators
1177 + *
1178 + * @since 2.6.0 bbPress (r6791)
1179 + */
1180 + public function filter_empty_spam() {
1181 +
1182 + // Bail if not viewing spam
1183 + if ( empty( $_GET['post_status'] ) || ( bbp_get_spam_status_id() !== $_GET['post_status'] ) && current_user_can( 'moderate' ) ) {
1184 + return;
905 1185 }
906 1186
907 - // Get which forum is selected
908 - $selected = !empty( $_GET['bbp_forum_id'] ) ? $_GET['bbp_forum_id'] : '';
1187 + ?>
909 1188
910 - // Show the forums dropdown
911 - bbp_dropdown( array(
912 - 'selected' => $selected,
913 - 'show_none' => __( 'In all forums', 'bbpress' )
914 - ) );
1189 + <div class="alignleft actions"><?php
1190 +
1191 + // Output the nonce & button
1192 + wp_nonce_field( 'bulk-destroy', '_destroy_nonce' );
1193 + submit_button(
1194 + esc_attr__( 'Empty Spam', 'bbpress' ),
1195 + 'button-secondary apply',
1196 + 'delete_all',
1197 + false
1198 + );
1199 +
1200 + ?></div><?php
915 1201 }
916 1202
917 1203 /**
918 1204 * Adjust the request query and include the forum id
919 1205 *
920 - * @since bbPress (r2991)
1206 + * @since 2.0.0 bbPress (r2991)
921 1207 *
922 1208 * @param array $query_vars Query variables from {@link WP_Query}
923 - * @uses is_admin() To check if it's the admin section
924 - * @uses bbp_get_topic_post_type() To get the topic post type
925 - * @uses bbp_get_reply_post_type() To get the reply post type
926 1209 * @return array Processed Query Vars
927 1210 */
928 - function filter_post_rows( $query_vars ) {
1211 + public function filter_post_rows( $query_vars ) {
929 1212
930 - if ( $this->bail() ) return $query_vars;
931 -
932 1213 // Add post_parent query_var if one is present
933 - if ( !empty( $_GET['bbp_forum_id'] ) ) {
1214 + if ( ! empty( $_GET['bbp_forum_id'] ) ) {
934 1215 $query_vars['meta_key'] = '_bbp_forum_id';
935 - $query_vars['meta_value'] = $_GET['bbp_forum_id'];
1216 + $query_vars['meta_type'] = 'NUMERIC';
1217 + $query_vars['meta_value'] = (int) $_GET['bbp_forum_id'];
936 1218 }
937 1219
938 1220 // Return manipulated query_vars
939 1221 return $query_vars;
@@ -941,15 +1223,11 @@
941 1223
942 1224 /**
943 1225 * Custom user feedback messages for topic post type
944 1226 *
945 - * @since bbPress (r3080)
1227 + * @since 2.0.0 bbPress (r3080)
946 1228 *
947 1229 * @global int $post_ID
948 - * @uses bbp_get_topic_permalink()
949 - * @uses wp_post_revision_title()
950 - * @uses esc_url()
951 - * @uses add_query_arg()
952 1230 *
953 1231 * @param array $messages
954 1232 *
955 1233 * @return array
@@ -956,10 +1234,8 @@
956 1234 */
957 1235 public function updated_messages( $messages ) {
958 1236 global $post_ID;
959 1237
960 - if ( $this->bail() ) return $messages;
961 -
962 1238 // URL for the current topic
963 1239 $topic_url = bbp_get_topic_permalink( $post_ID );
964 1240
965 1241 // Current topic's post_date
@@ -965,47 +1241,73 @@
965 1241 // Current topic's post_date
966 1242 $post_date = bbp_get_global_post_field( 'post_date', 'raw' );
967 1243
968 1244 // Messages array
969 - $messages[$this->post_type] = array(
970 - 0 => '', // Left empty on purpose
1245 + $messages[ $this->post_type ] = array(
1246 + 0 => '', // Left empty on purpose
971 1247
972 1248 // Updated
973 - 1 => sprintf( __( 'Topic updated. <a href="%s">View topic</a>', 'bbpress' ), $topic_url ),
1249 + 1 => sprintf(
1250 + '%1$s <a href="%2$s">%3$s</a>',
1251 + esc_html__( 'Topic updated.', 'bbpress' ),
1252 + $topic_url,
1253 + esc_html__( 'View topic', 'bbpress' )
1254 + ),
974 1255
975 1256 // Custom field updated
976 - 2 => __( 'Custom field updated.', 'bbpress' ),
1257 + 2 => esc_html__( 'Custom field updated.', 'bbpress' ),
977 1258
978 1259 // Custom field deleted
979 - 3 => __( 'Custom field deleted.', 'bbpress' ),
1260 + 3 => esc_html__( 'Custom field deleted.', 'bbpress' ),
980 1261
981 1262 // Topic updated
982 - 4 => __( 'Topic updated.', 'bbpress' ),
1263 + 4 => esc_html__( 'Topic updated.', 'bbpress' ),
983 1264
984 1265 // Restored from revision
985 - // translators: %s: date and time of the revision
1266 + /* translators: %s: date and time of the revision */
986 1267 5 => isset( $_GET['revision'] )
987 - ? sprintf( __( 'Topic restored to revision from %s', 'bbpress' ), wp_post_revision_title( (int) $_GET['revision'], false ) )
1268 + /* translators: %s: Date and time of the revision */
1269 + ? sprintf( esc_html__( 'Topic restored to revision from %s', 'bbpress' ), wp_post_revision_title( (int) $_GET['revision'], false ) )
988 1270 : false,
989 1271
990 1272 // Topic created
991 - 6 => sprintf( __( 'Topic created. <a href="%s">View topic</a>', 'bbpress' ), $topic_url ),
1273 + 6 => sprintf(
1274 + '%1$s <a href="%2$s">%3$s</a>',
1275 + esc_html__( 'Topic created.', 'bbpress' ),
1276 + $topic_url,
1277 + esc_html__( 'View topic', 'bbpress' )
1278 + ),
992 1279
993 1280 // Topic saved
994 - 7 => __( 'Topic saved.', 'bbpress' ),
1281 + 7 => esc_html__( 'Topic saved.', 'bbpress' ),
995 1282
996 1283 // Topic submitted
997 - 8 => sprintf( __( 'Topic submitted. <a target="_blank" href="%s">Preview topic</a>', 'bbpress' ), esc_url( add_query_arg( 'preview', 'true', $topic_url ) ) ),
1284 + 8 => sprintf(
1285 + '%1$s <a href="%2$s" target="_blank">%3$s</a>',
1286 + esc_html__( 'Topic submitted.', 'bbpress' ),
1287 + esc_url( add_query_arg( 'preview', 'true', $topic_url ) ),
1288 + esc_html__( 'Preview topic', 'bbpress' )
1289 + ),
998 1290
999 1291 // Topic scheduled
1000 - 9 => sprintf( __( 'Topic scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview topic</a>', 'bbpress' ),
1001 - // translators: Publish box date format, see http://php.net/date
1002 - date_i18n( __( 'M j, Y @ G:i', 'bbpress' ),
1003 - strtotime( $post_date ) ),
1004 - $topic_url ),
1292 + 9 => sprintf(
1293 + '%1$s <a target="_blank" href="%2$s">%3$s</a>',
1294 + sprintf(
1295 + /* translators: Publish box date format, see http://php.net/date */
1296 + esc_html__( 'Topic scheduled for: %s.', 'bbpress' ),
1297 + '<strong>' . date_i18n( __( 'M j, Y @ G:i', 'bbpress' ), strtotime( $post_date ) ) . '</strong>'
1298 + ),
1299 + $topic_url,
1300 + esc_html__( 'Preview topic', 'bbpress' )
1301 + ),
1005 1302
1006 1303 // Topic draft updated
1007 - 10 => sprintf( __( 'Topic draft updated. <a target="_blank" href="%s">Preview topic</a>', 'bbpress' ), esc_url( add_query_arg( 'preview', 'true', $topic_url ) ) ),
1304 + 10 => sprintf(
1305 + '%1$s <a href="%2$s" target="_blank">%3$s</a>',
1306 + esc_html__( 'Topic draft updated.', 'bbpress' ),
1307 + esc_url( add_query_arg( 'preview', 'true', $topic_url ) ),
1308 + esc_html__( 'Preview topic', 'bbpress' )
1309 + ),
1008 1310 );
1009 1311
1010 1312 return $messages;
1011 1313 }
@@ -1017,11 +1319,18 @@
1017 1319 *
1018 1320 * This is currently here to make hooking and unhooking of the admin UI easy.
1019 1321 * It could use dependency injection in the future, but for now this is easier.
1020 1322 *
1021 - * @since bbPress (r2596)
1323 + * @since 2.0.0 bbPress (r2596)
1022 1324 *
1023 - * @uses BBP_Forums_Admin
1325 + * @param WP_Screen $current_screen Current screen object
1024 1326 */
1025 -function bbp_admin_topics() {
1026 - bbpress()->admin->topics = new BBP_Topics_Admin();
1327 +function bbp_admin_topics( $current_screen ) {
1328 +
1329 + // Bail if not a forum screen
1330 + if ( empty( $current_screen->post_type ) || ( bbp_get_topic_post_type() !== $current_screen->post_type ) ) {
1331 + return;
1332 + }
1333 +
1334 + // Init the topics admin
1335 + bbp_admin()->topics = new BBP_Topics_Admin();
1027 1336 }