PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.5.1
Forumax – AI Powered Advanced Community Forum Plugin v2.5.1
2.5.1 2.5.0 2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 All 31 releases
← All changes | includes/features/bbp_solved_topic.php +461 -418 1.3.0 → 2.5.1 View file →
@@ -1,419 +1,462 @@
1 -<?php
2 -namespace features;
3 -
4 -class bbp_solved_topic {
5 -
6 - /**
7 - * The capability required to view private posts.
8 - *
9 - * @since 1.0
10 - *
11 - * @var string $capability
12 - */
13 - public $capability = 'moderate';
14 -
15 - /*
16 - --------------------------------------------*
17 - * Constructor
18 - *--------------------------------------------*/
19 -
20 - /**
21 - * Initializes the plugin by setting filters, and administration functions.
22 - */
23 - function __construct() {
24 - add_action( 'plugins_loaded', [ $this, 'filter_capability' ] );
25 -
26 - // show the checkboxes
27 - add_action( 'bbp_theme_before_reply_form_submit_wrapper', [ $this, 'reply_checkbox' ] );
28 - add_action( 'bbp_theme_before_topic_form_submit_wrapper', [ $this, 'topic_checkbox' ] );
29 -
30 - // save the reply state
31 - add_action( 'bbp_new_reply', [ $this, 'update_reply' ], 0, 6 );
32 - add_action( 'bbp_edit_reply', [ $this, 'update_reply' ], 0, 6 );
33 -
34 - // save the topic state
35 - add_action( 'bbp_new_topic', [ $this, 'update_topic' ], 0, 6 );
36 - add_action( 'bbp_edit_topic', [ $this, 'update_topic' ], 0, 6 );
37 -
38 - // reply content filter
39 - add_filter( 'bbp_get_reply_excerpt', [ $this, 'reply_content_filter' ], 999, 2 );
40 - add_filter( 'bbp_get_reply_content', [ $this, 'reply_content_filter' ], 999, 2 );
41 -
42 - add_filter( 'bbp_theme_before_topic_title', [ $this, 'solved_badge' ], 999, 2 );
43 - add_filter( 'bbp_topic_admin_links', [ $this, 'add_topic_admin_link' ], 10, 2 );
44 -
45 - // add a class name indicating the read status
46 - add_filter( 'post_class', [ $this, 'reply_post_class' ] );
47 - }
48 -
49 - /**
50 - * Admin links
51 - */
52 - public function add_topic_admin_link( $links, $topic_id ) {
53 -
54 - $topic_author = bbp_get_topic_author_id( bbp_get_topic_id() );
55 - if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
56 - if ( isset( $_GET['unsolve_topic'] ) ) {
57 - $this->unsolve_topic( bbp_get_topic_id() );
58 - $links['solved'] = '<a href="' . bbp_get_topic_permalink() . '?solve_topic">' . esc_html__( 'Mark as solved', 'ama-core' ) . '</a>';
59 - } elseif ( isset( $_GET['solve_topic'] ) ) {
60 - $this->solve_topic( bbp_get_topic_id() );
61 - $links['unsolved'] = '<a href="' . bbp_get_topic_permalink() . '?unsolve_topic">' . esc_html__( 'Mark as unsolved', 'ama-core' ) . '</a>';
62 - } else {
63 - if ( $this->is_solved( bbp_get_topic_id() ) ) {
64 - $links['unsolved'] = '<a href="' . bbp_get_topic_permalink() . '?unsolve_topic">' . esc_html__( 'Mark as unsolved', 'ama-core' ) . '</a>';
65 - } else {
66 - $links['solved'] = '<a href="' . bbp_get_topic_permalink() . '?solve_topic">' . esc_html__( 'Mark as solved', 'ama-core' ) . '</a>';
67 - }
68 - }
69 - }
70 - return $links;
71 - }
72 -
73 - public function solve_topic( $topic_id = 0 ) {
74 - $topic_author = bbp_get_topic_author_id( $topic_id );
75 - if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
76 - update_post_meta( $topic_id, '_bbp_topic_is_solved', '1' );
77 - $redirect = remove_query_arg( [ 'solve_topic' ] );
78 - wp_safe_redirect( $redirect );
79 - } else {
80 - wp_die( esc_html__( 'You do not have the permission to do that!', 'ama-core' ) );
81 - }
82 -
83 - }
84 -
85 - public function unsolve_topic( $topic_id = 0 ) {
86 - $topic_author = bbp_get_topic_author_id( $topic_id );
87 - if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
88 - delete_post_meta( $topic_id, '_bbp_topic_is_solved' );
89 - $redirect = remove_query_arg( [ 'unsolve_topic' ] );
90 - wp_safe_redirect( $redirect );
91 - } else {
92 - wp_die( esc_html__( 'You do not have the permission to do that!', 'ama-core' ) );
93 - }
94 - }
95 -
96 - /**
97 - * Called during the plugins_loaded action to filter the capability
98 - * required to view solved topics.
99 - *
100 - * @since 1.0
101 - *
102 - * @return void
103 - */
104 - public function filter_capability() {
105 - $this->capability = apply_filters( 'bbp_solved_topic_capability', $this->capability );
106 - }
107 -
108 - /**
109 - * Solved topic badge
110 - *
111 - * @since 1.0
112 - *
113 - * @return void
114 - */
115 - public function solved_badge() {
116 - $topic_id = bbp_get_topic_id();
117 - if ( $this->is_solved( $topic_id ) ) {
118 - echo '<i class="fa fa-check-circle text-success"></i>';
119 - }
120 - }
121 -
122 - /**
123 - * Outputs the reply checkbox
124 - *
125 - * @since 1.0
126 - *
127 - * @return void
128 - */
129 - public function reply_checkbox() {
130 - $has_best_answer = $this->has_best_answer( bbp_get_topic_id() );
131 - $is_best_answer = $this->is_best_answer( bbp_get_reply_id() );
132 - if ( bbp_is_reply_edit() && ( current_user_can( $this->capability ) ) ) {
133 - if ( ( ! $has_best_answer ) || ( $is_best_answer ) ) {
134 - ?>
135 - <p>
136 - <input name="bbp_best_answer" id="bbp_best_answer" type="checkbox"<?php checked( '1', $is_best_answer ); ?> value="1" tabindex="<?php bbp_tab_index(); ?>" />
137 - <label for="bbp_best_answer"><?php esc_html_e( 'Set this reply as Best Answer.', 'ama-core' ); ?></label>
138 - </p>
139 - <?php
140 - }
141 - }
142 - }
143 -
144 - /**
145 - * Outputs the topic checkbox
146 - *
147 - * @since 1.0
148 - *
149 - * @return void
150 - */
151 - public function topic_checkbox() {
152 - $topic_author = bbp_get_topic_author_id( bbp_get_topic_id() );
153 - if ( bbp_is_topic_edit() && ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) ) {
154 - ?>
155 - <p>
156 - <input name="bbp_solved_topic" id="bbp_solved_topic" type="checkbox"<?php checked( '1', $this->is_solved( bbp_get_topic_id() ) ); ?> value="1" tabindex="<?php bbp_tab_index(); ?>" />
157 - <label for="bbp_solved_topic"><?php esc_html_e( 'Set this post as solved.', 'ama-core' ); ?></label>
158 - </p>
159 - <?php
160 - }
161 -
162 - }
163 -
164 - /**
165 - * Stores the private state on reply creation and edit
166 - *
167 - * @since 1.0
168 - *
169 - * @param $reply_id int The ID of the reply
170 - * @param $topic_id int The ID of the topic the reply belongs to
171 - * @param $forum_id int The ID of the forum the topic belongs to
172 - * @param $anonymous_data bool Are we posting as an anonymous user?
173 - * @param $author_id int The ID of user creating the reply, or the ID of the replie's author during edit
174 - * @param $is_edit bool Are we editing a reply?
175 - *
176 - * @return void
177 - */
178 - public function update_reply( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
179 -
180 - if ( isset( $_POST['bbp_best_answer'] ) ) {
181 - $get_topic_meta = get_post_meta( $topic_id, '_bbp_topic_has_best_answer', true );
182 - if ( ! $get_topic_meta ) {
183 - update_post_meta( $topic_id, '_bbp_topic_has_best_answer', '1' );
184 - }
185 - update_post_meta( $reply_id, '_bbp_reply_is_best_answer', '1' );
186 - } else {
187 - delete_post_meta( $reply_id, '_bbp_reply_is_best_answer' );
188 - delete_post_meta( $topic_id, '_bbp_topic_has_best_answer' );
189 - }
190 -
191 - }
192 -
193 - /**
194 - * Stores the private state on topic creation and edit
195 - *
196 - * @since 1.0
197 - *
198 - * @param $topic_id int The ID of the topic
199 - * @param $is_edit bool Are we editing a topic?
200 - *
201 - * @return void
202 - */
203 - public function update_topic( $topic_id = 0, $is_edit = false ) {
204 -
205 - if ( isset( $_POST['bbp_solved_topic'] ) ) {
206 - update_post_meta( $topic_id, '_bbp_topic_is_solved', '1' );
207 - } else {
208 - delete_post_meta( $topic_id, '_bbp_topic_is_solved' );
209 - }
210 -
211 - }
212 -
213 -
214 - /**
215 - * Determines if a reply is marked as solved
216 - *
217 - * @since 1.0
218 - *
219 - * @param $reply_id int The ID of the reply
220 - *
221 - * @return bool
222 - */
223 - public function is_best_answer( $reply_id = 0 ) {
224 -
225 - $retval = false;
226 -
227 - // Checking a specific reply id
228 - if ( ! empty( $reply_id ) ) {
229 - $reply = bbp_get_reply( $reply_id );
230 - $reply_id = ! empty( $reply ) ? $reply->ID : 0;
231 -
232 - // Using the global reply id
233 - } elseif ( bbp_get_reply_id() ) {
234 - $reply_id = bbp_get_reply_id();
235 -
236 - // Use the current post id
237 - } elseif ( ! bbp_get_reply_id() ) {
238 - $reply_id = get_the_ID();
239 - }
240 -
241 - if ( ! empty( $reply_id ) ) {
242 - $retval = get_post_meta( $reply_id, '_bbp_reply_is_best_answer', true );
243 - }
244 -
245 - return (bool) apply_filters( 'bbp_reply_is_best_answer', (bool) $retval, $reply_id );
246 - }
247 -
248 - /**
249 - * Determines if a reply is marked as solved
250 - *
251 - * @since 1.0
252 - *
253 - * @param $reply_id int The ID of the reply
254 - *
255 - * @return bool
256 - */
257 - public function is_solved( $topic_id = 0 ) {
258 -
259 - $retval = false;
260 -
261 - // Checking a specific reply id.
262 - if ( ! empty( $topic_id ) ) {
263 - $topic = bbp_get_topic( $topic_id );
264 - $topic_id = ! empty( $topic ) ? $topic->ID : 0;
265 -
266 - // Using the global reply id.
267 - } elseif ( bbp_get_topic_id() ) {
268 - $topic_id = bbp_get_topic_id();
269 -
270 - // Use the current post id.
271 - } elseif ( ! bbp_get_topic_id() ) {
272 - $topic_id = get_the_ID();
273 - }
274 -
275 - if ( ! empty( $topic_id ) ) {
276 - $retval = get_post_meta( $topic_id, '_bbp_topic_is_solved', true );
277 - }
278 -
279 - return (bool) apply_filters( 'bbp_topic_is_solved', (bool) $retval, $topic_id );
280 - }
281 -
282 - /**
283 - * Determines if a reply is marked as solved
284 - *
285 - * @since 1.0
286 - *
287 - * @param $reply_id int The ID of the reply
288 - *
289 - * @return bool
290 - */
291 - public function has_best_answer( $topic_id = 0 ) {
292 -
293 - // if bbpress is not active, return the classes
294 -
295 - if ( ! function_exists( 'bbp_get_topic_id' ) ) {
296 - return false;
297 - }
298 -
299 - $retval = false;
300 -
301 - // Checking a specific reply id.
302 - if ( ! empty( $topic_id ) ) {
303 - $topic = bbp_get_topic( $topic_id );
304 - $topic_id = ! empty( $topic ) ? $topic->ID : 0;
305 -
306 - // Using the global reply id.
307 - } elseif ( bbp_get_topic_id() ) {
308 - $topic_id = bbp_get_topic_id();
309 -
310 - // Use the current post id.
311 - } elseif ( ! bbp_get_topic_id() ) {
312 - $topic_id = get_the_ID();
313 - }
314 -
315 - if ( ! empty( $topic_id ) ) {
316 - $retval = get_post_meta( $topic_id, '_bbp_topic_has_best_answer', true );
317 - }
318 -
319 - return (bool) apply_filters( 'bbp_topic_has_best_answer', (bool) $retval, $topic_id );
320 - }
321 -
322 -
323 - /**
324 - * Reply content filter
325 - *
326 - * @since 1.0
327 - *
328 - * @param $content string The content of the reply
329 - * @param $reply_id int The ID of the reply
330 - *
331 - * @return string
332 - */
333 - public function reply_content_filter( $content = '', $reply_id = 0 ) {
334 -
335 - if ( empty( $reply_id ) ) {
336 - $reply_id = bbp_get_reply_id( $reply_id );
337 - }
338 -
339 - $topic_id = bbp_get_topic_id();
340 -
341 - if ( $this->is_best_answer( $reply_id ) ) {
342 - $content = '<div class="solved-topic-bar" id="best-answer"><span class="badge"><i class="icon_check"></i> ' . esc_html__( 'Best Answer', 'ama-core' ) . '</span></div>' . $content;
343 - }
344 -
345 - return $content;
346 - }
347 -
348 - /**
349 - * Topic content filter
350 - *
351 - * @since 1.0
352 - *
353 - * @param $content string The content of the topic
354 - * @param $topic_id int The ID of the reply
355 - *
356 - * @return string
357 - */
358 - public function topic_content_filter( $content = '', $topic_id = 0 ) {
359 -
360 - if ( empty( $topic_id ) ) {
361 - $topic_id = bbp_get_topic_id( $topic_id );
362 - }
363 -
364 - $open = '';
365 - $close = '';
366 - $resolved = '';
367 - $has_best_answer = '';
368 -
369 - if ( $this->is_solved( $topic_id ) || $this->has_best_answer( $topic_id ) ) {
370 - $open = '<div class="solved-topic-bar">';
371 - $close = '</div>';
372 - }
373 -
374 - if ( $this->is_solved( $topic_id ) ) {
375 - $resolved = '<span class="accepted-ans-mark"><i class="icon_check_alt"></i> ' . esc_html__( 'Resolved', 'ama-core' ) . '</span>';
376 - }
377 -
378 - $content = $content . $open . $resolved . $has_best_answer . $close;
379 -
380 - return $content;
381 - }
382 -
383 - /**
384 - * Adds a new class to replies that are marked as solved
385 - *
386 - * @since 1.0
387 - *
388 - * @param $classes array An array of current class names
389 - *
390 - * @return bool
391 - */
392 - public function reply_post_class( $classes ) {
393 -
394 - // if bbpress is not active, return the classes
395 - if ( ! function_exists( 'bbp_get_reply_id' ) ) {
396 - return $classes;
397 - }
398 -
399 - $reply_id = bbp_get_reply_id();
400 -
401 - // Only apply the class to replies.
402 - if ( bbp_get_reply_post_type() != get_post_type( $reply_id ) ) {
403 - return $classes;
404 - }
405 -
406 - if ( $this->is_best_answer( $reply_id ) ) {
407 - $classes[] = 'best-answer';
408 - }
409 -
410 - return $classes;
411 - }
412 -}
413 -
414 -// Instantiate the class.
415 -$GLOBALS['bbp_solved_topic'] = new bbp_solved_topic();
416 -
417 -function bbp_solved_topic(): bbp_solved_topic {
418 - return new bbp_solved_topic();
1 +<?php
2 +namespace features;
3 +
4 +class forumax_solve_topic {
5 +
6 + /**
7 + * The capability required to view private posts.
8 + *
9 + * @since 1.0
10 + *
11 + * @var string $capability
12 + */
13 + public $capability = 'moderate';
14 +
15 + /*
16 + --------------------------------------------*
17 + * Constructor
18 + *--------------------------------------------*/
19 +
20 + /**
21 + * Initializes the plugin by setting filters, and administration functions.
22 + */
23 + function __construct() {
24 + add_action( 'plugins_loaded', [ $this, 'filter_capability' ] );
25 +
26 + // show the checkboxes
27 + add_action( 'bbp_theme_before_reply_form_submit_wrapper', [ $this, 'reply_checkbox' ] );
28 + add_action( 'bbp_theme_before_topic_form_submit_wrapper', [ $this, 'topic_checkbox' ] );
29 +
30 + // save the reply state
31 + add_action( 'bbp_new_reply', [ $this, 'update_reply' ], 0, 6 );
32 + add_action( 'bbp_edit_reply', [ $this, 'update_reply' ], 0, 6 );
33 +
34 + // save the topic state
35 + add_action( 'bbp_new_topic', [ $this, 'update_topic' ], 0, 6 );
36 + add_action( 'bbp_edit_topic', [ $this, 'update_topic' ], 0, 6 );
37 +
38 + // reply content filter
39 + add_filter( 'bbp_get_reply_excerpt', [ $this, 'reply_content_filter' ], 999, 2 );
40 + add_filter( 'bbp_get_reply_content', [ $this, 'reply_content_filter' ], 999, 2 );
41 +
42 + add_filter( 'bbp_theme_before_topic_title', [ $this, 'solved_badge' ], 999, 2 );
43 + add_filter( 'bbp_topic_admin_links', [ $this, 'add_topic_admin_link' ], 10, 2 );
44 +
45 + add_action( 'template_redirect', [ $this, 'handle_solve_action' ] );
46 +
47 + // add a class name indicating the read status
48 + add_filter( 'post_class', [ $this, 'reply_post_class' ] );
49 + }
50 +
51 + /**
52 + * Handle the solve/unsolve action via GET request
53 + *
54 + * @since 2.2.0
55 + */
56 + public function handle_solve_action() {
57 + if ( ! isset( $_GET['solve_topic'] ) && ! isset( $_GET['unsolve_topic'] ) ) {
58 + return;
59 + }
60 +
61 + $topic_id = bbp_get_topic_id();
62 + $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
63 +
64 + if ( isset( $_GET['solve_topic'] ) ) {
65 + // Verify nonce
66 + if ( ! wp_verify_nonce( $nonce, 'forumax_solve_topic_' . $topic_id ) ) {
67 + wp_die( esc_html__( 'Security check failed.', 'forumax' ) );
68 + }
69 + $this->solve_topic( $topic_id );
70 + } elseif ( isset( $_GET['unsolve_topic'] ) ) {
71 + if ( ! wp_verify_nonce( $nonce, 'forumax_unsolve_topic_' . $topic_id ) ) {
72 + wp_die( esc_html__( 'Security check failed.', 'forumax' ) );
73 + }
74 + $this->unsolve_topic( $topic_id );
75 + }
76 + }
77 +
78 + /**
79 + * Admin links
80 + */
81 + public function add_topic_admin_link( $links, $topic_id ) {
82 +
83 + $topic_author = bbp_get_topic_author_id( bbp_get_topic_id() );
84 + if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
85 + if ( $this->is_solved( bbp_get_topic_id() ) ) {
86 + $links['unsolved'] = '<a href="' . wp_nonce_url(
87 + add_query_arg( 'unsolve_topic', '1', bbp_get_topic_permalink() ),
88 + 'forumax_unsolve_topic_' . bbp_get_topic_id()
89 + ) . '">' . esc_html__( 'Mark as unsolved', 'forumax' ) . '</a>';
90 + } else {
91 + $links['solved'] = '<a href="' . wp_nonce_url(
92 + add_query_arg( 'solve_topic', '1', bbp_get_topic_permalink() ),
93 + 'forumax_solve_topic_' . bbp_get_topic_id()
94 + ) . '">' . esc_html__( 'Mark as solved', 'forumax' ) . '</a>';
95 + }
96 + }
97 + return $links;
98 + }
99 +
100 + public function solve_topic( $topic_id = 0 ) {
101 + $topic_author = bbp_get_topic_author_id( $topic_id );
102 + if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
103 + update_post_meta( $topic_id, '_bbp_topic_is_solved', '1' );
104 + $redirect = remove_query_arg( [ 'solve_topic', '_wpnonce' ] );
105 + wp_safe_redirect( $redirect );
106 + exit;
107 + } else {
108 + wp_die( esc_html__( 'You do not have the permission to do that!', 'forumax' ) );
109 + }
110 +
111 + }
112 +
113 + public function unsolve_topic( $topic_id = 0 ) {
114 + $topic_author = bbp_get_topic_author_id( $topic_id );
115 + if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
116 + delete_post_meta( $topic_id, '_bbp_topic_is_solved' );
117 + $redirect = remove_query_arg( [ 'unsolve_topic', '_wpnonce' ] );
118 + wp_safe_redirect( $redirect );
119 + exit;
120 + } else {
121 + wp_die( esc_html__( 'You do not have the permission to do that!', 'forumax' ) );
122 + }
123 + }
124 +
125 + /**
126 + * Called during the plugins_loaded action to filter the capability
127 + * required to view solved topics.
128 + *
129 + * @since 1.0
130 + *
131 + * @return void
132 + */
133 + public function filter_capability() {
134 + $this->capability = apply_filters( 'forumax_solve_topic_capability', $this->capability );
135 + }
136 +
137 + /**
138 + * Solved topic badge
139 + *
140 + * @since 1.0
141 + *
142 + * @return void
143 + */
144 + public function solved_badge() {
145 + $topic_id = bbp_get_topic_id();
146 + if ( $this->is_solved( $topic_id ) ) {
147 + echo '<i class="fa fa-check-circle text-success"></i>';
148 + }
149 + }
150 +
151 + /**
152 + * Outputs the reply checkbox
153 + *
154 + * @since 1.0
155 + *
156 + * @return void
157 + */
158 + public function reply_checkbox() {
159 + $has_best_answer = $this->has_best_answer( bbp_get_topic_id() );
160 + $is_best_answer = $this->is_best_answer( bbp_get_reply_id() );
161 + if ( bbp_is_reply_edit() && ( current_user_can( $this->capability ) ) ) {
162 + if ( ( ! $has_best_answer ) || ( $is_best_answer ) ) {
163 + ?>
164 + <p>
165 + <input name="bbp_best_answer" id="bbp_best_answer" type="checkbox"<?php checked( '1', $is_best_answer ); ?> value="1" tabindex="<?php bbp_tab_index(); ?>" />
166 + <label for="bbp_best_answer"><?php esc_html_e( 'Set this reply as Best Answer.', 'forumax' ); ?></label>
167 + </p>
168 + <?php
169 + }
170 + }
171 + }
172 +
173 + /**
174 + * Outputs the topic checkbox
175 + *
176 + * @since 1.0
177 + *
178 + * @return void
179 + */
180 + public function topic_checkbox() {
181 + $topic_author = bbp_get_topic_author_id( bbp_get_topic_id() );
182 + if ( bbp_is_topic_edit() && ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) ) {
183 + ?>
184 + <p>
185 + <input name="forumax_solve_topic" id="forumax_solve_topic" type="checkbox"<?php checked( '1', $this->is_solved( bbp_get_topic_id() ) ); ?> value="1" tabindex="<?php bbp_tab_index(); ?>" />
186 + <label for="forumax_solve_topic"><?php esc_html_e( 'Set this post as solved.', 'forumax' ); ?></label>
187 + </p>
188 + <?php
189 + }
190 +
191 + }
192 +
193 + /**
194 + * Stores the private state on reply creation and edit
195 + *
196 + * @since 1.0
197 + *
198 + * @param $reply_id int The ID of the reply
199 + * @param $topic_id int The ID of the topic the reply belongs to
200 + * @param $forum_id int The ID of the forum the topic belongs to
201 + * @param $anonymous_data bool Are we posting as an anonymous user?
202 + * @param $author_id int The ID of user creating the reply, or the ID of the replie's author during edit
203 + * @param $is_edit bool Are we editing a reply?
204 + *
205 + * @return void
206 + */
207 + public function update_reply( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
208 +
209 + if ( isset( $_POST['bbp_best_answer'] ) ) {
210 + $get_topic_meta = get_post_meta( $topic_id, '_bbp_topic_has_best_answer', true );
211 + if ( ! $get_topic_meta ) {
212 + update_post_meta( $topic_id, '_bbp_topic_has_best_answer', '1' );
213 + }
214 + update_post_meta( $reply_id, '_bbp_reply_is_best_answer', '1' );
215 + } elseif ( get_post_meta( $reply_id, '_bbp_reply_is_best_answer', true ) ) {
216 + // Only clear the topic flag when this reply was the best answer;
217 + // saving any other reply must not wipe it.
218 + delete_post_meta( $reply_id, '_bbp_reply_is_best_answer' );
219 + delete_post_meta( $topic_id, '_bbp_topic_has_best_answer' );
220 + }
221 +
222 + }
223 +
224 + /**
225 + * Stores the private state on topic creation and edit
226 + *
227 + * @since 1.0
228 + *
229 + * @param $topic_id int The ID of the topic
230 + * @param $is_edit bool Are we editing a topic?
231 + *
232 + * @return void
233 + */
234 + public function update_topic( $topic_id = 0, $is_edit = false ) {
235 +
236 + if ( isset( $_POST['forumax_solve_topic'] ) ) {
237 + update_post_meta( $topic_id, '_bbp_topic_is_solved', '1' );
238 + } else {
239 + delete_post_meta( $topic_id, '_bbp_topic_is_solved' );
240 + }
241 +
242 + }
243 +
244 +
245 + /**
246 + * Determines if a reply is marked as solved
247 + *
248 + * @since 1.0
249 + *
250 + * @param $reply_id int The ID of the reply
251 + *
252 + * @return bool
253 + */
254 + public function is_best_answer( $reply_id = 0 ) {
255 +
256 + $retval = false;
257 +
258 + // Checking a specific reply id
259 + if ( ! empty( $reply_id ) ) {
260 + $reply = bbp_get_reply( $reply_id );
261 + $reply_id = ! empty( $reply ) ? $reply->ID : 0;
262 +
263 + // Using the global reply id
264 + } elseif ( bbp_get_reply_id() ) {
265 + $reply_id = bbp_get_reply_id();
266 +
267 + // Use the current post id
268 + } elseif ( ! bbp_get_reply_id() ) {
269 + $reply_id = get_the_ID();
270 + }
271 +
272 + if ( ! empty( $reply_id ) ) {
273 + $retval = get_post_meta( $reply_id, '_bbp_reply_is_best_answer', true );
274 + }
275 +
276 + return (bool) apply_filters( 'bbp_reply_is_best_answer', (bool) $retval, $reply_id );
277 + }
278 +
279 + /**
280 + * Determines if a reply is marked as solved
281 + *
282 + * @since 1.0
283 + *
284 + * @param $reply_id int The ID of the reply
285 + *
286 + * @return bool
287 + */
288 + public function is_solved( $topic_id = 0 ) {
289 +
290 + $retval = false;
291 +
292 + // Checking a specific reply id.
293 + if ( ! empty( $topic_id ) ) {
294 + $topic = bbp_get_topic( $topic_id );
295 + $topic_id = ! empty( $topic ) ? $topic->ID : 0;
296 +
297 + // Using the global reply id.
298 + } elseif ( bbp_get_topic_id() ) {
299 + $topic_id = bbp_get_topic_id();
300 +
301 + // Use the current post id.
302 + } elseif ( ! bbp_get_topic_id() ) {
303 + $topic_id = get_the_ID();
304 + }
305 +
306 + if ( ! empty( $topic_id ) ) {
307 + $retval = get_post_meta( $topic_id, '_bbp_topic_is_solved', true );
308 + }
309 +
310 + return (bool) apply_filters( 'bbp_topic_is_solved', (bool) $retval, $topic_id );
311 + }
312 +
313 + /**
314 + * Determines if a reply is marked as solved
315 + *
316 + * @since 1.0
317 + *
318 + * @param $reply_id int The ID of the reply
319 + *
320 + * @return bool
321 + */
322 + public function has_best_answer( $topic_id = 0 ) {
323 +
324 + // if bbpress is not active, return the classes
325 +
326 + if ( ! function_exists( 'bbp_get_topic_id' ) ) {
327 + return false;
328 + }
329 +
330 + $retval = false;
331 +
332 + // Checking a specific reply id.
333 + if ( ! empty( $topic_id ) ) {
334 + $topic = bbp_get_topic( $topic_id );
335 + $topic_id = ! empty( $topic ) ? $topic->ID : 0;
336 +
337 + // Using the global reply id.
338 + } elseif ( bbp_get_topic_id() ) {
339 + $topic_id = bbp_get_topic_id();
340 +
341 + // Use the current post id.
342 + } elseif ( ! bbp_get_topic_id() ) {
343 + $topic_id = get_the_ID();
344 + }
345 +
346 + if ( ! empty( $topic_id ) ) {
347 + $retval = get_post_meta( $topic_id, '_bbp_topic_has_best_answer', true );
348 + }
349 +
350 + return (bool) apply_filters( 'bbp_topic_has_best_answer', (bool) $retval, $topic_id );
351 + }
352 +
353 +
354 + /**
355 + * Reply content filter
356 + *
357 + * @since 1.0
358 + *
359 + * @param $content string The content of the reply
360 + * @param $reply_id int The ID of the reply
361 + *
362 + * @return string
363 + */
364 + public function reply_content_filter( $content = '', $reply_id = 0 ) {
365 +
366 + if ( empty( $reply_id ) ) {
367 + $reply_id = bbp_get_reply_id( $reply_id );
368 + }
369 +
370 + $topic_id = bbp_get_topic_id();
371 +
372 + if ( $this->is_best_answer( $reply_id ) ) {
373 + $content = '<div class="solved-topic-bar" id="best-answer"><span class="badge"><i class="icon_check"></i> ' . esc_html__( 'Best Answer', 'forumax' ) . '</span></div>' . $content;
374 + }
375 +
376 + return $content;
377 + }
378 +
379 + /**
380 + * Topic content filter
381 + *
382 + * @since 1.0
383 + *
384 + * @param $content string The content of the topic
385 + * @param $topic_id int The ID of the reply
386 + *
387 + * @return string
388 + */
389 + public function topic_content_filter( $content = '', $topic_id = 0 ) {
390 +
391 + if ( empty( $topic_id ) ) {
392 + $topic_id = bbp_get_topic_id( $topic_id );
393 + }
394 +
395 + $open = '';
396 + $close = '';
397 + $resolved = '';
398 + $has_best_answer = '';
399 +
400 + if ( $this->is_solved( $topic_id ) || $this->has_best_answer( $topic_id ) ) {
401 + $open = '<div class="solved-topic-bar">';
402 + $close = '</div>';
403 + }
404 +
405 + if ( $this->is_solved( $topic_id ) ) {
406 + $resolved = '<span class="accepted-ans-mark badge"><i class="icon_check_alt"></i> ' . esc_html__( 'Resolved', 'forumax' ) . '</span>';
407 + }
408 +
409 + $content = $content . $open . $resolved . $has_best_answer . $close;
410 +
411 + return $content;
412 + }
413 +
414 + /**
415 + * Adds a new class to replies that are marked as solved
416 + *
417 + * @since 1.0
418 + *
419 + * @param $classes array An array of current class names
420 + *
421 + * @return bool
422 + */
423 + public function reply_post_class( $classes ) {
424 +
425 + // if bbpress is not active, return the classes
426 + if ( ! function_exists( 'bbp_get_reply_id' ) ) {
427 + return $classes;
428 + }
429 +
430 + $reply_id = bbp_get_reply_id();
431 +
432 + // Only apply the class to replies.
433 + if ( bbp_get_reply_post_type() != get_post_type( $reply_id ) ) {
434 + return $classes;
435 + }
436 +
437 + if ( $this->is_best_answer( $reply_id ) ) {
438 + $classes[] = 'best-answer';
439 + }
440 +
441 + return $classes;
442 + }
443 +}
444 +
445 +// Instantiate the class.
446 +$GLOBALS['forumax_solve_topic'] = new forumax_solve_topic();
447 +
448 +/**
449 + * Shared solved-topic instance.
450 + *
451 + * Constructing a new instance re-registers every hook, so repeated calls
452 + * (once per topic in a loop) duplicated badges and filters.
453 + *
454 + * @return forumax_solve_topic
455 + */
456 +function forumax_solve_topic(): forumax_solve_topic {
457 + if ( ! ( $GLOBALS['forumax_solve_topic'] ?? null ) instanceof forumax_solve_topic ) {
458 + $GLOBALS['forumax_solve_topic'] = new forumax_solve_topic();
459 + }
460 +
461 + return $GLOBALS['forumax_solve_topic'];
419 462 }