PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.2.0
Forumax – AI Powered Advanced Community Forum Plugin v2.2.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 2.0.0 2.1.0 All 29 releases
bbp-core / includes / features / bbp_solved_topic.php

bbp_solved_topic.php in Forumax – AI Powered Advanced Community Forum Plugin 2.2.0, at includes/features/bbp_solved_topic.php

443 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 $topic_id = bbp_get_topic_id();
58
59 if ( isset( $_GET['solve_topic'] ) ) {
60 // Verify nonce
61 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'forumax_solve_topic_' . $topic_id ) ) {
62 wp_die( esc_html__( 'Security check failed.', 'forumax' ) );
63 }
64 $this->solve_topic( $topic_id );
65 } elseif ( isset( $_GET['unsolve_topic'] ) ) {
66 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'forumax_unsolve_topic_' . $topic_id ) ) {
67 wp_die( esc_html__( 'Security check failed.', 'forumax' ) );
68 }
69 $this->unsolve_topic( $topic_id );
70 }
71 }
72
73 /**
74 * Admin links
75 */
76 public function add_topic_admin_link( $links, $topic_id ) {
77
78 $topic_author = bbp_get_topic_author_id( bbp_get_topic_id() );
79 if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
80 if ( $this->is_solved( bbp_get_topic_id() ) ) {
81 $links['unsolved'] = '<a href="' . wp_nonce_url(
82 add_query_arg( 'unsolve_topic', '1', bbp_get_topic_permalink() ),
83 'forumax_unsolve_topic_' . bbp_get_topic_id()
84 ) . '">' . esc_html__( 'Mark as unsolved', 'forumax' ) . '</a>';
85 } else {
86 $links['solved'] = '<a href="' . wp_nonce_url(
87 add_query_arg( 'solve_topic', '1', bbp_get_topic_permalink() ),
88 'forumax_solve_topic_' . bbp_get_topic_id()
89 ) . '">' . esc_html__( 'Mark as solved', 'forumax' ) . '</a>';
90 }
91 }
92 return $links;
93 }
94
95 public function solve_topic( $topic_id = 0 ) {
96 $topic_author = bbp_get_topic_author_id( $topic_id );
97 if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
98 update_post_meta( $topic_id, '_bbp_topic_is_solved', '1' );
99 $redirect = remove_query_arg( [ 'solve_topic', '_wpnonce' ] );
100 wp_safe_redirect( $redirect );
101 exit;
102 } else {
103 wp_die( esc_html__( 'You do not have the permission to do that!', 'forumax' ) );
104 }
105
106 }
107
108 public function unsolve_topic( $topic_id = 0 ) {
109 $topic_author = bbp_get_topic_author_id( $topic_id );
110 if ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) {
111 delete_post_meta( $topic_id, '_bbp_topic_is_solved' );
112 $redirect = remove_query_arg( [ 'unsolve_topic', '_wpnonce' ] );
113 wp_safe_redirect( $redirect );
114 exit;
115 } else {
116 wp_die( esc_html__( 'You do not have the permission to do that!', 'forumax' ) );
117 }
118 }
119
120 /**
121 * Called during the plugins_loaded action to filter the capability
122 * required to view solved topics.
123 *
124 * @since 1.0
125 *
126 * @return void
127 */
128 public function filter_capability() {
129 $this->capability = apply_filters( 'forumax_solve_topic_capability', $this->capability );
130 }
131
132 /**
133 * Solved topic badge
134 *
135 * @since 1.0
136 *
137 * @return void
138 */
139 public function solved_badge() {
140 $topic_id = bbp_get_topic_id();
141 if ( $this->is_solved( $topic_id ) ) {
142 echo '<i class="fa fa-check-circle text-success"></i>';
143 }
144 }
145
146 /**
147 * Outputs the reply checkbox
148 *
149 * @since 1.0
150 *
151 * @return void
152 */
153 public function reply_checkbox() {
154 $has_best_answer = $this->has_best_answer( bbp_get_topic_id() );
155 $is_best_answer = $this->is_best_answer( bbp_get_reply_id() );
156 if ( bbp_is_reply_edit() && ( current_user_can( $this->capability ) ) ) {
157 if ( ( ! $has_best_answer ) || ( $is_best_answer ) ) {
158 ?>
159 <p>
160 <input name="bbp_best_answer" id="bbp_best_answer" type="checkbox"<?php checked( '1', $is_best_answer ); ?> value="1" tabindex="<?php bbp_tab_index(); ?>" />
161 <label for="bbp_best_answer"><?php esc_html_e( 'Set this reply as Best Answer.', 'forumax' ); ?></label>
162 </p>
163 <?php
164 }
165 }
166 }
167
168 /**
169 * Outputs the topic checkbox
170 *
171 * @since 1.0
172 *
173 * @return void
174 */
175 public function topic_checkbox() {
176 $topic_author = bbp_get_topic_author_id( bbp_get_topic_id() );
177 if ( bbp_is_topic_edit() && ( ( current_user_can( $this->capability ) ) || ( $topic_author == get_current_user_id() ) ) ) {
178 ?>
179 <p>
180 <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(); ?>" />
181 <label for="forumax_solve_topic"><?php esc_html_e( 'Set this post as solved.', 'forumax' ); ?></label>
182 </p>
183 <?php
184 }
185
186 }
187
188 /**
189 * Stores the private state on reply creation and edit
190 *
191 * @since 1.0
192 *
193 * @param $reply_id int The ID of the reply
194 * @param $topic_id int The ID of the topic the reply belongs to
195 * @param $forum_id int The ID of the forum the topic belongs to
196 * @param $anonymous_data bool Are we posting as an anonymous user?
197 * @param $author_id int The ID of user creating the reply, or the ID of the replie's author during edit
198 * @param $is_edit bool Are we editing a reply?
199 *
200 * @return void
201 */
202 public function update_reply( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
203
204 if ( isset( $_POST['bbp_best_answer'] ) ) {
205 $get_topic_meta = get_post_meta( $topic_id, '_bbp_topic_has_best_answer', true );
206 if ( ! $get_topic_meta ) {
207 update_post_meta( $topic_id, '_bbp_topic_has_best_answer', '1' );
208 }
209 update_post_meta( $reply_id, '_bbp_reply_is_best_answer', '1' );
210 } else {
211 delete_post_meta( $reply_id, '_bbp_reply_is_best_answer' );
212 delete_post_meta( $topic_id, '_bbp_topic_has_best_answer' );
213 }
214
215 }
216
217 /**
218 * Stores the private state on topic creation and edit
219 *
220 * @since 1.0
221 *
222 * @param $topic_id int The ID of the topic
223 * @param $is_edit bool Are we editing a topic?
224 *
225 * @return void
226 */
227 public function update_topic( $topic_id = 0, $is_edit = false ) {
228
229 if ( isset( $_POST['forumax_solve_topic'] ) ) {
230 update_post_meta( $topic_id, '_bbp_topic_is_solved', '1' );
231 } else {
232 delete_post_meta( $topic_id, '_bbp_topic_is_solved' );
233 }
234
235 }
236
237
238 /**
239 * Determines if a reply is marked as solved
240 *
241 * @since 1.0
242 *
243 * @param $reply_id int The ID of the reply
244 *
245 * @return bool
246 */
247 public function is_best_answer( $reply_id = 0 ) {
248
249 $retval = false;
250
251 // Checking a specific reply id
252 if ( ! empty( $reply_id ) ) {
253 $reply = bbp_get_reply( $reply_id );
254 $reply_id = ! empty( $reply ) ? $reply->ID : 0;
255
256 // Using the global reply id
257 } elseif ( bbp_get_reply_id() ) {
258 $reply_id = bbp_get_reply_id();
259
260 // Use the current post id
261 } elseif ( ! bbp_get_reply_id() ) {
262 $reply_id = get_the_ID();
263 }
264
265 if ( ! empty( $reply_id ) ) {
266 $retval = get_post_meta( $reply_id, '_bbp_reply_is_best_answer', true );
267 }
268
269 return (bool) apply_filters( 'bbp_reply_is_best_answer', (bool) $retval, $reply_id );
270 }
271
272 /**
273 * Determines if a reply is marked as solved
274 *
275 * @since 1.0
276 *
277 * @param $reply_id int The ID of the reply
278 *
279 * @return bool
280 */
281 public function is_solved( $topic_id = 0 ) {
282
283 $retval = false;
284
285 // Checking a specific reply id.
286 if ( ! empty( $topic_id ) ) {
287 $topic = bbp_get_topic( $topic_id );
288 $topic_id = ! empty( $topic ) ? $topic->ID : 0;
289
290 // Using the global reply id.
291 } elseif ( bbp_get_topic_id() ) {
292 $topic_id = bbp_get_topic_id();
293
294 // Use the current post id.
295 } elseif ( ! bbp_get_topic_id() ) {
296 $topic_id = get_the_ID();
297 }
298
299 if ( ! empty( $topic_id ) ) {
300 $retval = get_post_meta( $topic_id, '_bbp_topic_is_solved', true );
301 }
302
303 return (bool) apply_filters( 'bbp_topic_is_solved', (bool) $retval, $topic_id );
304 }
305
306 /**
307 * Determines if a reply is marked as solved
308 *
309 * @since 1.0
310 *
311 * @param $reply_id int The ID of the reply
312 *
313 * @return bool
314 */
315 public function has_best_answer( $topic_id = 0 ) {
316
317 // if bbpress is not active, return the classes
318
319 if ( ! function_exists( 'bbp_get_topic_id' ) ) {
320 return false;
321 }
322
323 $retval = false;
324
325 // Checking a specific reply id.
326 if ( ! empty( $topic_id ) ) {
327 $topic = bbp_get_topic( $topic_id );
328 $topic_id = ! empty( $topic ) ? $topic->ID : 0;
329
330 // Using the global reply id.
331 } elseif ( bbp_get_topic_id() ) {
332 $topic_id = bbp_get_topic_id();
333
334 // Use the current post id.
335 } elseif ( ! bbp_get_topic_id() ) {
336 $topic_id = get_the_ID();
337 }
338
339 if ( ! empty( $topic_id ) ) {
340 $retval = get_post_meta( $topic_id, '_bbp_topic_has_best_answer', true );
341 }
342
343 return (bool) apply_filters( 'bbp_topic_has_best_answer', (bool) $retval, $topic_id );
344 }
345
346
347 /**
348 * Reply content filter
349 *
350 * @since 1.0
351 *
352 * @param $content string The content of the reply
353 * @param $reply_id int The ID of the reply
354 *
355 * @return string
356 */
357 public function reply_content_filter( $content = '', $reply_id = 0 ) {
358
359 if ( empty( $reply_id ) ) {
360 $reply_id = bbp_get_reply_id( $reply_id );
361 }
362
363 $topic_id = bbp_get_topic_id();
364
365 if ( $this->is_best_answer( $reply_id ) ) {
366 $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;
367 }
368
369 return $content;
370 }
371
372 /**
373 * Topic content filter
374 *
375 * @since 1.0
376 *
377 * @param $content string The content of the topic
378 * @param $topic_id int The ID of the reply
379 *
380 * @return string
381 */
382 public function topic_content_filter( $content = '', $topic_id = 0 ) {
383
384 if ( empty( $topic_id ) ) {
385 $topic_id = bbp_get_topic_id( $topic_id );
386 }
387
388 $open = '';
389 $close = '';
390 $resolved = '';
391 $has_best_answer = '';
392
393 if ( $this->is_solved( $topic_id ) || $this->has_best_answer( $topic_id ) ) {
394 $open = '<div class="solved-topic-bar">';
395 $close = '</div>';
396 }
397
398 if ( $this->is_solved( $topic_id ) ) {
399 $resolved = '<span class="accepted-ans-mark badge"><i class="icon_check_alt"></i> ' . esc_html__( 'Resolved', 'forumax' ) . '</span>';
400 }
401
402 $content = $content . $open . $resolved . $has_best_answer . $close;
403
404 return $content;
405 }
406
407 /**
408 * Adds a new class to replies that are marked as solved
409 *
410 * @since 1.0
411 *
412 * @param $classes array An array of current class names
413 *
414 * @return bool
415 */
416 public function reply_post_class( $classes ) {
417
418 // if bbpress is not active, return the classes
419 if ( ! function_exists( 'bbp_get_reply_id' ) ) {
420 return $classes;
421 }
422
423 $reply_id = bbp_get_reply_id();
424
425 // Only apply the class to replies.
426 if ( bbp_get_reply_post_type() != get_post_type( $reply_id ) ) {
427 return $classes;
428 }
429
430 if ( $this->is_best_answer( $reply_id ) ) {
431 $classes[] = 'best-answer';
432 }
433
434 return $classes;
435 }
436 }
437
438 // Instantiate the class.
439 $GLOBALS['forumax_solve_topic'] = new forumax_solve_topic();
440
441 function forumax_solve_topic(): forumax_solve_topic {
442 return new forumax_solve_topic();
443 }