PluginProbe
wpForo Forum / 2.2.9
wpForo Forum v2.2.9
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / classes / Template.php

Template.php in wpForo Forum 2.2.9, at classes/Template.php

2,949 lines 149.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 use stdClass;
6
7 // Exit if accessed directly
8 if( ! defined( 'ABSPATH' ) ) exit;
9
10 define( 'WPFORO_THEME_DIR', WPFORO_DIR . DIRECTORY_SEPARATOR . 'themes' );
11 define( 'WPFORO_THEME_URL', WPFORO_URL . '/themes' );
12
13 class Template {
14 public $default;
15 public $theme = '2022';
16 public $theme_info;
17 public $template_dir;
18 public $template_url;
19 public $paths = [];
20 public $base_templates = [];
21 public $member_templates = [];
22 public $templates = [];
23 public $menu = [];
24
25 public function __construct() {
26 $this->init_defaults();
27 $this->init_base_templates();
28 add_action( 'wpforo_core_inited', function(){
29 $this->init_member_templates();
30 $this->init_templates();
31 },
32 999
33 );
34 $this->init_current_theme( wpforo_setting( 'general', 'current_theme' ) );
35 add_action( 'wpforo_after_init', function() {
36 $this->init_hooks();
37 $this->init_nav_menu();
38 } );
39 }
40
41 private function init_hooks() {
42 if( is_wpforo_page() ) {
43 add_filter( "mce_external_plugins", [ $this, 'add_mce_external_plugins' ], 15 );
44 add_filter( "tiny_mce_plugins", [ $this, 'filter_tinymce_plugins' ], 15 );
45 add_filter( "wp_mce_translation", [ $this, 'add_tinymce_translations' ] );
46 add_filter( "wpforo_editor_settings", [ $this, 'editor_settings_required_params' ], 999 );
47
48 add_action( 'wpforo_topic_form_extra_fields_after', [ $this, 'add_default_attach_input' ] );
49 add_action( 'wpforo_reply_form_extra_fields_after', [ $this, 'add_default_attach_input' ], 10, 1 );
50 add_action( 'wpforo_portable_form_extra_fields_after', [ $this, 'add_default_attach_input' ] );
51
52 add_filter( 'is_wpforo_attach_page_templates', function( $templates ) {
53 $templates[] = 'add-topic';
54
55 return $templates;
56 } );
57 add_filter( 'wpforo_emoticons_loading_template', function( $templates ) {
58 $templates[] = 'add-topic';
59
60 return $templates;
61 } );
62
63 add_action( 'wp_footer', [ $this, 'add_footer_html' ], 999999 );
64
65 add_action( 'wpforo_profile_head_right', function( $user ){
66 echo $this->change_cover_button( $user );
67 } );
68
69 //ajax actions hooks
70 add_action( 'wp_ajax_wpforo_active_tab_content_ajax', [ $this, 'ajx_active_tab_content' ] );
71 }
72 add_filter( 'wpforo_content_after', [ $this, 'do_spoilers' ] );
73 add_filter( 'wpforo_content_after', [ $this, 'apply_quotes' ] );
74 add_action( 'wpforo_register_form_end', function() {
75 echo '<input type="hidden" name="wpfaction" value="registration">';
76 } );
77 add_action( 'wpforo_login_form_end', function() {
78 wp_nonce_field( 'login', '_wpfnonce', false );
79 echo '<input type="hidden" name="wpfaction" value="login">';
80 } );
81 add_action( 'wpforo_profile_account_bottom', function() {
82 echo '<input type="hidden" name="wpfaction" value="profile_update">';
83 } );
84 }
85
86 private function init_defaults() {
87 $this->default = new stdClass;
88
89 $this->default->editor_settings = [
90 'media_buttons' => false,
91 'textarea_name' => '',
92 'textarea_rows' => 15,
93 'tabindex' => '',
94 'editor_height' => 130,
95 'editor_css' => '',
96 'editor_class' => '',
97 'teeny' => false,
98 'dfw' => false,
99 'plugins' => 'hr,lists,textcolor,paste,wpautoresize,fullscreen',
100 'external_plugins' => [
101 'wpforo_pre_button' => WPFORO_URL . '/assets/js/tinymce-pre.js',
102 'wpforo_link_button' => WPFORO_URL . '/assets/js/tinymce-link.js',
103 'wpforo_spoiler_button' => WPFORO_URL . '/assets/js/tinymce-spoiler.js',
104 'wpforo_source_code_button' => WPFORO_URL . '/assets/js/tinymce-code.js',
105 'emoticons' => WPFORO_URL . '/assets/js/tinymce-emoji.js',
106 ],
107 'tinymce' => [
108 'toolbar1' => 'fontsizeselect,bold,italic,underline,strikethrough,forecolor,bullist,numlist,hr,alignleft,aligncenter,alignright,alignjustify,link,unlink,blockquote,pre,wpf_spoil,undo,redo,pastetext,source_code,emoticons,fullscreen',
109 'toolbar2' => '',
110 'toolbar3' => '',
111 'toolbar4' => '',
112 'content_style' => 'blockquote{border: #cccccc 1px dotted; background: #F7F7F7; padding:10px;font-size:12px; font-style:italic; margin: 20px 10px;} pre{border-left: 3px solid #ccc; outline: none !important; background: #fafcff;padding: 10px;font-size: 14px;margin: 20px 0 0 10px;display: block;width: 100%;} img.emoji{width: 20px;}',
113 'object_resizing' => false,
114 'autoresize_on_init' => true,
115 'wp_autoresize_on' => true,
116 'wp_keep_scroll_position' => true,
117 'indent' => true,
118 'add_unload_trigger' => false,
119 'wpautop' => false,
120 'setup' => 'wpforo_tinymce_setup',
121 'content_css' => '',
122 'extended_valid_elements' => 'i[class|style],span[class|style]',
123 'custom_elements' => '',
124 ],
125 'quicktags' => false,
126 'default_editor' => 'tinymce',
127 ];
128
129 $this->default->template = [
130 'type' => 'html',
131 'key' => '',
132 'slug' => '',
133 'menu_shortcode' => '',
134 'callback_for_can_view_menu' => null,
135 'ico' => '',
136 'title' => '',
137 'callback_for_page' => null,
138 'callback_for_get_url' => null,
139 'value' => '',
140 'status' => 1,
141 'is_default' => 0,
142 'callback_for_can' => null,
143 'can' => '',
144 'callback_for_can_view_member_menu' => null,
145 'add_in_member_menu' => 1,
146 'add_in_member_buttons' => 0,
147 ];
148
149 $this->default->base_templates = [
150 'members' => [
151 'type' => 'callback',
152 'key' => 'members',
153 'slug' => 'participants',
154 'title' => 'Members',
155 'callback_for_get_url' => function() {
156 return wpforo_members_url();
157 },
158 'is_default' => 1,
159 'can' => 'vmem',
160 'callback_for_page' => function(){
161 require wpftpl( 'members.php' );
162 }
163 ],
164 'register' => [
165 'type' => 'callback',
166 'key' => 'register',
167 'slug' => 'sign-up',
168 'title' => 'Register',
169 'callback_for_get_url' => function() {
170 return wpforo_register_url();
171 },
172 'callback_for_can_view_menu' => function() {
173 return ( ! wpforo_is_bot() && ! WPF()->current_userid && ( wpforo_setting( 'authorization', 'user_register' ) || wpforo_setting( 'authorization', 'register_url' ) ) );
174 },
175 'is_default' => 1,
176 'callback_for_page' => function(){
177 require wpftpl( 'register.php' );
178 }
179 ],
180 'login' => [
181 'type' => 'callback',
182 'key' => 'login',
183 'slug' => 'sign-in',
184 'title' => 'Login',
185 'callback_for_get_url' => function() {
186 return wpforo_login_url();
187 },
188 'callback_for_can_view_menu' => function() {
189 return ! wpforo_is_bot() && ! WPF()->current_userid;
190 },
191 'is_default' => 1,
192 'callback_for_page' => function(){
193 require wpftpl( 'login.php' );
194 },
195 'callback_for_can' => function(){
196 return ! wpforo_is_bot() && ! WPF()->current_userid;
197 },
198 ],
199 'lostpassword' => [
200 'type' => 'callback',
201 'key' => 'lostpassword',
202 'slug' => 'change-password',
203 'title' => 'Lost your password',
204 'callback_for_get_url' => function() {
205 return wpforo_lostpassword_url();
206 },
207 'callback_for_can_view_menu' => function() {
208 return ! wpforo_is_bot() && ! WPF()->current_userid;
209 },
210 'is_default' => 1,
211 'callback_for_page' => function(){
212 if( wpfval( WPF()->GET, 'wpfaction' ) === 'resetpassword_form' ){
213 echo do_shortcode( '[wpforo-resetpassword]' );
214 }else{
215 echo do_shortcode( '[wpforo-lostpassword]' );
216 }
217 }
218 ],
219 'logout' => [
220 'type' => 'callback',
221 'key' => 'logout',
222 'slug' => 'sign-out',
223 'title' => 'Logout',
224 'callback_for_get_url' => function() {
225 return wpforo_logout_url();
226 },
227 'callback_for_can_view_menu' => function() {
228 return ! wpforo_is_bot() && WPF()->current_userid;
229 },
230 'is_default' => 1,
231 'callback_for_can' => function(){
232 return ! wpforo_is_bot() && WPF()->current_userid;
233 }
234 ],
235 'member' => [
236 'type' => 'callback',
237 'key' => 'member',
238 'slug' => 'participant',
239 'ico' => '<i class="fas fa-user"></i>',
240 'title' => 'Profile',
241 'is_default' => 1,
242 'can' => 'vprf',
243 'callback_for_page' => function(){
244 require wpftpl( 'profile.php' );
245 }
246 ],
247 'cantlogin' => [
248 'type' => 'callback',
249 'key' => 'cantlogin',
250 'slug' => 'login-message',
251 'title' => 'Can\'t Login',
252 'is_default' => 1,
253 'callback_for_can' => function() {
254 return (bool) WPF()->ram_cache->get( 'USER_LOGIN_REFERER' );
255 },
256 'callback_for_page' => function() {
257 echo $this->cantlogin_page();
258 },
259 'callback_for_can_view_menu' => '__return_false',
260 'add_in_member_menu' => 0,
261 'add_in_member_buttons' => 0,
262 ],
263 ];
264
265 $this->default->member_templates = [
266 'profile' => [
267 'type' => 'callback',
268 'key' => 'profile',
269 'menu_shortcode' => 'wpforo-profile-home',
270 'ico' => '<i class="fas fa-user"></i>',
271 'title' => 'Profile',
272 'is_default' => 1,
273 'can' => 'vprf',
274 'add_in_member_menu' => 1,
275 'add_in_member_buttons' => 1,
276 'callback_for_page' => function(){
277 require wpftpl( 'profile-home.php' );
278 },
279 ],
280 'account' => [
281 'type' => 'callback',
282 'key' => 'account',
283 'menu_shortcode' => 'wpforo-profile-account',
284 'ico' => '<i class="fas fa-cog"></i>',
285 'title' => 'Account',
286 'is_default' => 1,
287 'can' => 'em',
288 'add_in_member_menu' => 0,
289 'add_in_member_buttons' => 1,
290 'callback_for_page' => function(){
291 if( WPF()->perm->user_can_edit_account() ) {
292 require wpftpl( 'profile-account.php' );
293 }else{
294 printf(
295 '<p class="wpf-p-error">%1$s</p>',
296 wpforo_phrase( 'You should have minimum number of approved posts to be able edit your profile information', false )
297 );
298 }
299 },
300 ],
301 'activity' => [
302 'type' => 'callback',
303 'key' => 'activity',
304 'menu_shortcode' => 'wpforo-profile-activity',
305 'ico' => '<i class="fas fa-comments"></i>',
306 'title' => 'Activity',
307 'is_default' => 1,
308 'can' => 'vpra',
309 'add_in_member_menu' => 1,
310 'add_in_member_buttons' => 1,
311 'callback_for_page' => function(){
312 require wpftpl( 'profile-activity.php' );
313 },
314 ],
315 'favored' => [
316 'type' => 'callback',
317 'key' => 'favored',
318 'menu_shortcode' => 'wpforo-profile-favored',
319 'ico' => '<i class="fas fa-bookmark"></i>',
320 'title' => 'Favored',
321 'is_default' => 1,
322 'can' => 'l',
323 'add_in_member_menu' => 1,
324 'add_in_member_buttons' => 1,
325 'callback_for_page' => function(){
326 require wpftpl( 'profile-favored.php' );
327 },
328 ],
329 ];
330
331 $this->default->templates = [
332 'add-topic' => [
333 'type' => 'callback',
334 'key' => 'add-topic',
335 'title' => 'Add New Topic',
336 'is_default' => 1,
337 'callback_for_page' => function() {
338 echo '<div class="wpf-add-topic-wrap">';
339 printf( '<h2 class="wpf-add-topic-title">%1$s</h2>', wpforo_phrase( 'Add New Topic', false ) );
340 $forumid = (int) wpfval( WPF()->current_object['qvars'], 0 );
341 $this->portable_topic_form( $forumid );
342 echo '</div>';
343 },
344 'can' => 'vt_add_topic',
345 ],
346 'recent' => [
347 'type' => 'callback',
348 'key' => 'recent',
349 'title' => 'Recent Posts',
350 'is_default' => 1,
351 'callback_for_page' => function() {
352 require wpftpl( 'recent.php' );
353 },
354 ],
355 'tags' => [
356 'type' => 'callback',
357 'key' => 'tags',
358 'title' => 'Tags',
359 'is_default' => 1,
360 'callback_for_page' => function() {
361 require wpftpl( 'tags.php' );
362 },
363 ],
364 ];
365 }
366
367 /**
368 * initialize base templates
369 */
370 private function init_base_templates() {
371 $this->base_templates = $this->default->base_templates;
372 $this->base_templates = (array) apply_filters( 'wpforo_init_base_templates', $this->base_templates );
373 do_action( 'wpforo_after_init_base_templates', $this->base_templates );
374 }
375
376 /**
377 * initialize templates
378 */
379 private function init_member_templates() {
380 $this->member_templates = $this->default->member_templates;
381 $this->member_templates = (array) apply_filters( 'wpforo_init_member_templates', $this->member_templates );
382 do_action( 'wpforo_after_init_member_templates', $this->member_templates );
383 }
384
385 /**
386 * initialize templates
387 */
388 private function init_templates() {
389 $this->templates = $this->default->templates;
390 $this->templates = (array) apply_filters( 'wpforo_init_templates', $this->templates );
391 do_action( 'wpforo_after_init_templates', $this->templates );
392 }
393
394 /**
395 * initialize templates paths
396 */
397 private function init_paths() {
398 if( ! $this->paths && function_exists( 'wpftpl' ) ) {
399 $this->paths = [
400 '404' => wpftpl( '404.php' ),
401 'search' => wpftpl( 'search.php' ),
402 'forum' => wpftpl( 'forum.php' ),
403 'topic' => wpftpl( 'topic.php' ),
404 'post' => wpftpl( 'post.php' ),
405 ];
406 $this->paths = apply_filters( 'wpforo_init_template_paths', $this->paths );
407 }
408 }
409
410 /**
411 * @param array|string $template
412 *
413 * @return array
414 */
415 private function fix_template( $template ) {
416 if( is_string( $template ) ) {
417 $t = $this->default->template;
418 $t['key'] = $template;
419 $t['menu_shortcode'] = $template;
420 $t['title'] = ucfirst( (string) $template );
421
422 return $t;
423 } else {
424 $template = wpforo_settype( $template, 'array' );
425 if( is_array( $template ) ) {
426 $template = array_merge( $this->default->template, $template );
427 if( ! $template['ico'] = trim( (string) $template['ico'] ) ) $template['ico'] = '<i class="fas fa-user"></i>';
428
429 return $template;
430 }
431 }
432
433 return $this->default->template;
434 }
435
436 /**
437 * @param array $template
438 *
439 * @return bool
440 */
441 private function is_template( &$template ) {
442 $key = wpfval( $template, 'key' );
443 if( wpfval( $template, 'type' ) && $key && is_string( $key ) ) {
444 $template = $this->fix_template( $template );
445
446 return true;
447 }
448
449 return false;
450 }
451
452 /**
453 * @param array|string $template
454 * @param array $member
455 * @param bool $default
456 *
457 * @return bool
458 */
459 public function can_view_template( $template, $member = [], $default = false ) {
460 if( $template = $this->get_template( $template ) ) {
461 if( (int) $template['status'] ) {
462 if( ! is_callable( $template['callback_for_can'] ) ) {
463 if( $template['can'] ) {
464 $userid = wpforo_bigintval( wpfval( $member, 'userid' ) );
465 if( $userid && $userid === WPF()->current_userid && wpforo_is_member_template( $template ) ) {
466 return true;
467 } else {
468 return (bool) WPF()->usergroup->can( $template['can'] );
469 }
470 } else {
471 return true;
472 }
473 } else {
474 return (bool) call_user_func( $template['callback_for_can'], $template, $member, $default );
475 }
476 }
477 }
478
479 return $default;
480 }
481
482 /**
483 * @param array|string $template
484 *
485 * @return string
486 */
487 public function get_key( $template = null ) {
488 if( ! $template ) $template = WPF()->current_object['template'];
489
490 return is_string( $template ) ? $template : (string) wpfval( $template, 'key' );
491 }
492
493 /**
494 * @param array|string $template
495 *
496 * @return string
497 */
498 private function get_menu_shortcode( $template ) {
499 $menu_shortcode = '';
500 if( $template = $this->get_template( $template ) ) {
501 $menu_shortcode = sanitize_title( trim( (string) $template['menu_shortcode'], '%/' ) );
502 if( ! $menu_shortcode ) $menu_shortcode = $template['key'];
503 if( strpos( (string) $menu_shortcode, 'wpforo-' ) !== 0 ) $menu_shortcode = 'wpforo-' . $menu_shortcode;
504 }
505
506 return $menu_shortcode;
507 }
508
509 /**
510 * @param array|string $template
511 * @param array $args
512 * @param string $default
513 *
514 * @return string
515 */
516 private function get_url( $template, $args = [], $default = '' ) {
517 $return = $default ?: '#';
518 if( $template = $this->get_template( $template ) ) {
519 if( is_callable( $template['callback_for_get_url'] ) ) {
520 $return = call_user_func( $template['callback_for_get_url'], $template, $args, $default );
521 } elseif( wpfval( $args, 'userid' ) && wpfval( $args, 'user_nicename' ) && wpforo_is_member_template( $template ) ) {
522 $return = WPF()->member->get_profile_url( $args, $template['key'] );
523 } elseif( ! $default && $slug = wpforo_settings_get_slug( $template['key'] ) ) {
524 $return = wpforo_home_url( $slug );
525 }
526 }
527
528 return $return;
529 }
530
531 /**
532 * @param array|string $template
533 *
534 * @return string
535 */
536 public function get_template_path( $template ) {
537 $this->init_paths();
538 $path = (string) wpfval( $this->paths, $this->get_key( $template ) );
539
540 return apply_filters( 'wpforo_get_template_path', $path, $template );
541 }
542
543 /**
544 * @param bool $only_enableds
545 * @param bool $only_defaults
546 * @param array $__templates
547 *
548 * @return array
549 */
550 public function get_templates( $only_enableds = true, $only_defaults = false, $__templates = [] ) {
551 $templates = [];
552 if( ! $__templates ) $__templates = array_merge( (array) $this->base_templates, (array) $this->member_templates, (array) $this->templates );
553 foreach( $__templates as $key => $template ) {
554 if( $this->is_template( $template ) && ( ! $only_enableds || $template['status'] ) && ( ! $only_defaults || $template['is_default'] ) ) {
555 $templates[ $key ] = $template;
556 }
557 }
558
559 return $templates;
560 }
561
562 /**
563 * @param bool $only_enableds
564 * @param bool $only_defaults
565 *
566 * @return array
567 */
568 public function get_member_templates( $only_enableds = true, $only_defaults = false ) {
569 return $this->get_templates( $only_enableds, $only_defaults, $this->member_templates );
570 }
571
572 /**
573 * @param bool $only_enableds
574 * @param bool $only_defaults
575 *
576 * @return array
577 */
578 public function get_templates_list( $only_enableds = true, $only_defaults = false ) {
579 return array_keys( $this->get_templates( $only_enableds, $only_defaults ) );
580 }
581
582 /**
583 * @param bool $only_enableds
584 * @param bool $only_defaults
585 *
586 * @return array
587 */
588 public function get_member_templates_list( $only_enableds = true, $only_defaults = false ) {
589 return array_keys( $this->get_member_templates( $only_enableds, $only_defaults ) );
590 }
591
592 /**
593 * @param array|string $template
594 *
595 * @return array
596 */
597 public function get_template( $template = null ) {
598 $return = [];
599 if( ! $template ) $template = WPF()->current_object['template'];
600 if( is_string( $template ) ) {
601 $templates = $this->get_templates();
602 if( $t = (array) wpfval( $templates, $template ) ) {
603 $return = $t;
604 } else {
605 $return = $this->fix_template( $template );
606 }
607 } elseif( is_array( $template ) ) {
608 $return = $this->fix_template( $template );
609 }
610
611 return ( $this->is_template( $return ) ? $return : [] );
612 }
613
614 /**
615 * show given template
616 *
617 * @param array|string $template
618 */
619 public function show_template( $template = null ) {
620 if( $template = $this->get_template( $template ) ) {
621 if( $template['type'] === 'callback' && is_callable( $template['callback_for_page'] ) ) { ?>
622 <?php if( $template['key'] === 'add-topic' ): ?>
623 <?php echo call_user_func( $template['callback_for_page'], $template ); ?>
624 <?php else: ?>
625 <div class="wpforo-profile-content <?php echo esc_attr('wpf-pt-' . wpfval(WPF()->current_object ,'template')) ?>">
626 <div class="wpf-profile-section wpf-mi-section">
627 <div class="wpf-profile-body">
628 <?php echo call_user_func( $template['callback_for_page'], $template ); ?>
629 </div>
630 </div>
631 </div>
632 <?php endif; ?>
633 <?php
634 } elseif( $template['type'] === 'html' && is_string( $template['value'] ) && $template['value'] ) { ?>
635 <div class="wpforo-profile-content <?php echo esc_attr('wpf-pt-' . wpfval(WPF()->current_object ,'template')) ?>">
636 <div class="wpf-profile-section wpf-mi-section">
637 <?php echo wpautop( do_shortcode( wpforo_apply_ucf_shortcode( $template['value'] ) ) ); ?>
638 </div>
639 </div>
640 <?php
641 } elseif( $template['type'] === 'builder' && $fields = $template['value'] ) {
642 if( $fields = maybe_unserialize( $fields ) ) : ?>
643 <div class="wpforo-profile-content <?php echo esc_attr('wpf-pt-' . wpfval(WPF()->current_object ,'template')) ?>">
644 <div class="wpf-profile-section wpf-mi-section">
645 <div class="wpf-table">
646 <?php wpforo_fields( $fields ) ?>
647 </div>
648 </div>
649 </div>
650 <?php
651 endif;
652 }
653 } else {
654 $this->show_msg( wpforo_phrase( 'Your template is not found', false ) );
655 }
656 }
657
658 public function member_menu() {
659 if( $templates = $this->get_member_templates() ) {
660 foreach( $templates as $key => $template ) {
661 if( is_callable( $template['callback_for_can_view_member_menu'] ) ){
662 $can_view = call_user_func( $template['callback_for_can_view_member_menu'] );
663 }else{
664 $can_view = (bool) $template['add_in_member_menu'];
665 }
666 if( $can_view && $this->can_view_template( $template, WPF()->current_object['user'] ) ) {
667 printf(
668 '<a class="wpf-profile-menu %1$s" href="%2$s">%3$s <span class="wpf-profile-menu-label">%4$s</span></a>',
669 WPF()->current_object['template'] === $key ? 'wpforo-active' : '',
670 esc_url( $this->get_url( $template, WPF()->current_object['user'], WPF()->member->get_profile_url( WPF()->current_object['user'], $key ) ) ),
671 $template['ico'],
672 wpforo_phrase( $template['title'], false )
673 );
674 }
675 }
676 }
677 }
678
679 public function member_buttons( $member, $called_from = '' ) {
680 if( wpforo_bigintval( wpfval( $member, 'userid' ) ) && WPF()->usergroup->can( 'vprf' ) ) {
681 if( $templates = $this->get_member_templates() ) {
682 foreach( $templates as $template ) {
683 if( $template['add_in_member_buttons'] && $this->can_view_template( $template, $member ) ) {
684 printf(
685 '<a class="wpf-member-profile-button" title="%1$s" href="%2$s" %3$s>%4$s</a>',
686 wpforo_phrase( $template['title'], false ),
687 esc_url( $this->get_url( $template, $member, WPF()->member->get_profile_url( $member, $template['key'] ) ) ),
688 ( ($button_attrs = wpfval( $template, 'button_attrs' )) ? implode( ' ', array_map( function( $attr, $attrval ) use( $called_from ){
689 return sprintf('%1$s="%2$s"', $attr, ( is_callable($attrval) ? call_user_func( $attrval, $called_from ) : $attrval ));
690 }, array_keys($button_attrs), $button_attrs ) ) : '' ),
691 $template['ico']
692 );
693 }
694 }
695 }
696 do_action( 'wpforo_member_info_buttons', $member );
697 }
698 }
699
700 public function get_member_actions_html( $user ) {
701 $html = '';
702 foreach( WPF()->member->get_actions( $user ) as $key => $action ){
703 $data = [];
704 if( $action['data'] ) foreach( $action['data'] as $k => $v ) $data[] = "data-$k=\"$v\"";
705 $_html = sprintf(
706 '<span class="wpf-ab-%1$s" wpf-tooltip="%2$s" wpf-tooltip-position="top" wpf-tooltip-size="medium" %3$s %4$s>%5$s</span>',
707 $key,
708 $action['label'],
709 implode( ' ', $data ),
710 ( $action['confirm_msg'] ? 'onclick="return wpforo_confirm(\'' . $action['confirm_msg'] . '\', event)"' : '' ),
711 $action['ico']
712 );
713 $url = ( is_callable( $action['callback_for_get_url'] ) ? call_user_func( $action['callback_for_get_url'] ) : '' );
714 $html .= ($url ? sprintf( '<a href="%1$s">%2$s</a>', $url, $_html ) : $_html);
715 }
716 return $html ? sprintf( '<div class="wpforo-user-tools">%1$s</div>', $html ) : '';
717 }
718
719 public function member_template( $template = null ) {
720 if( $template = $this->get_template( $template ) ) {
721 if( $this->can_view_template( $template, WPF()->current_object['user'] ) ) {
722 $this->show_template( $template );
723 } else {
724 $this->show_msg( wpforo_phrase( 'You do not have permission to view this page', false ) );
725 }
726 } else {
727 $this->show_msg( wpforo_phrase( 'Your template has not found', false ) );
728 }
729 }
730
731 public function show_msg( $msg ) {
732 ?>
733 <div class="wpfbg-7 wpf-page-message-wrap">
734 <div class="wpf-page-message-text"><?php echo $msg ?></div></div><?php
735 }
736
737 /**
738 * @param array|string $template
739 * @param bool $default
740 *
741 * @return bool
742 */
743 public function can_view_nav_menu( $template, $default = false ) {
744 $can_view = $default;
745 if( $template = $this->get_template( $template ) ) {
746 if( $this->can_view_template( $template, WPF()->current_user ) ) {
747 if( ! is_callable( $template['callback_for_can_view_menu'] ) ) {
748 if( wpforo_is_member_template( $template ) ) {
749 $can_view = (bool) WPF()->current_userid;
750 } else {
751 $can_view = true;
752 }
753 } else {
754 $can_view = (bool) call_user_func( $template['callback_for_can_view_menu'], $template, $default );
755 }
756 }
757 }
758
759 return $can_view;
760 }
761
762 function init_nav_menu() {
763 $actives = [];
764
765 $is_active = in_array( WPF()->current_object['template'], [ 'forum', 'topic', 'post' ] );
766 $this->menu['wpforo-home'] = [
767 'href' => wpforo_home_url(),
768 'label' => wpforo_phrase( 'forums', false ),
769 'is_active' => $is_active && ! in_array( true, $actives ),
770 ];
771 $actives['wpforo-home'] = $is_active;
772
773 $is_active = WPF()->current_object['template'] === 'recent' && wpfval( WPF()->GET, 'view' ) === 'prefix';
774 $this->menu['wpforo-unread'] = [
775 'href' => wpforo_home_url( wpforo_settings_get_slug( 'recent' ) . '?view=unread' ),
776 'label' => wpforo_phrase( 'Unread Posts', false ),
777 'is_active' => $is_active && ! in_array( true, $actives ),
778 ];
779 $actives['wpforo-unread'] = $is_active;
780
781 if( $templates = $this->get_templates() ) {
782 $cot_is_member_template = wpforo_is_member_template();
783 foreach( $templates as $key => $template ) {
784 if( $this->can_view_nav_menu( $template ) ) {
785 $is_active = ( $key === WPF()->current_object['template'] && ( ! $cot_is_member_template || WPF()->current_object['user_is_same_current_user'] ) ) || ( $key === 'profile' && $cot_is_member_template && WPF()->current_object['user_is_same_current_user'] );
786 $default_url = wpforo_is_member_template( $template ) ? WPF()->member->get_profile_url( WPF()->current_user, $key ) : '';
787 $shortcode = $this->get_menu_shortcode( $template );
788 $this->menu[ $shortcode ] = [
789 'href' => $this->get_url( $template, WPF()->current_user, $default_url ),
790 'label' => wpforo_phrase( $template['title'], false ),
791 'is_active' => $is_active && ! in_array( true, $actives ),
792 ];
793 if( $key !== 'profile' ) $actives[ $shortcode ] = $is_active;
794 }
795 }
796 }
797
798 $this->menu = apply_filters( 'wpforo_menu_array_filter', $this->menu );
799 }
800
801 function has_menu() {
802 return has_nav_menu( 'wpforo-menu' );
803 }
804
805 function nav_menu() {
806 $location = wpforo_prefix_slug( 'menu' );
807 if( has_nav_menu( $location ) ) {
808 $defaults = [
809 'theme_location' => $location,
810 'menu' => '',
811 'container' => '',
812 'container_class' => '',
813 'container_id' => '',
814 'menu_class' => 'wpf-menu',
815 'menu_id' => 'wpf-menu',
816 'echo' => true,
817 'fallback_cb' => 'wp_page_menu',
818 'before' => '',
819 'after' => '',
820 'link_before' => '',
821 'link_after' => '',
822 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
823 'depth' => 0,
824 'walker' => '',
825 ];
826 wp_nav_menu( $defaults );
827 }
828 }
829
830 private function init_current_theme( $theme ) {
831 if( ! $this->theme_exists( $theme ) ) $theme = '2022';
832 $this->theme = $theme;
833 $this->theme_info = $this->find_theme( $this->theme );
834 $this->template_dir = wpforo_fix_dir_sep( WPFORO_THEME_DIR . '/' . $this->theme );
835 $this->template_url = WPFORO_THEME_URL . '/' . $this->theme;
836 }
837
838 function add_mce_external_plugins() {
839 $plugin_array = [];
840 $plugin_array['wpforo_pre_button'] = WPFORO_URL . '/assets/js/tinymce-pre.js';
841 $plugin_array['wpforo_link_button'] = WPFORO_URL . '/assets/js/tinymce-link.js';
842 $plugin_array['wpforo_spoiler_button'] = WPFORO_URL . '/assets/js/tinymce-spoiler.js';
843 $plugin_array['wpforo_source_code_button'] = WPFORO_URL . '/assets/js/tinymce-code.js';
844 $plugin_array['emoticons'] = WPFORO_URL . '/assets/js/tinymce-emoji.js';
845
846 return $plugin_array;
847 }
848
849 function filter_tinymce_plugins() {
850 return [ 'hr', 'lists', 'textcolor', 'paste', 'wpautoresize', 'fullscreen' ];
851 }
852
853 function add_tinymce_translations( $mce_translation ) {
854 $mce_translation['Insert link'] = __( 'Insert link' );
855 $mce_translation['Link Text'] = __( 'Link Text' );
856 $mce_translation['Open link in a new tab'] = __( 'Open link in a new tab' );
857 $mce_translation['Insert Spoiler'] = __( 'Insert Spoiler', 'wpforo' );
858 $mce_translation['Spoiler'] = __( 'Spoiler', 'wpforo' );
859
860 return $mce_translation;
861 }
862
863 public function add_default_attach_input( $forumid = null ) {
864 if( WPF()->perm->can_attach( $forumid ) ) { ?>
865 <div class="wpf-default-attachment">
866 <label for="wpf_file"><?php wpforo_phrase( 'Attach file:' ) ?> </label> <input id="wpf_file" type="file" name="attachfile"/>
867 <p><?php wpforo_phrase( 'Maximum allowed file size is' );
868 echo ' ' . wpforo_print_size( wpforo_setting( 'posting', 'max_upload_size' ) ); ?></p>
869 <div class="wpf-clear"></div>
870 </div>
871 <?php
872 }
873 }
874
875 public function topic_form_forums_selectbox( $forumid = null ) {
876 if( wpforo_forum_list_need_add_topic_button( $forumid ) && WPF()->perm->forum_can( 'ct', $forumid ) ) {
877 $this->portable_topic_form( null, $forumid );
878 }
879 }
880
881 public function portable_topic_form( $forumid = null, $parent_forumid = null ) {
882 WPF()->current_object['load_tinymce'] = true;
883 $uniqid = uniqid();
884 ?>
885 <div class="wpf-topic-form-extra-wrap">
886 <div class="wpf-topic-forum-field" style="padding: 0 10px 15px; text-align: center; margin: 0 auto 10px;">
887 <label for="wpf-choose-forum-<?php echo $uniqid ?>" class="wpf-choose-forum" style="font-size: 15px; padding-bottom: 5px;">
888 <?php wpforo_phrase( 'Select Forum' ) ?>
889 </label>
890 <div class="wpf-topic-forum-wrap" style="width: 70%; margin: 0 auto; padding-bottom: 15px; min-width: 222px; border-bottom: 1px dashed #cccccc;">
891 <select id="wpf-choose-forum-<?php echo $uniqid ?>" class="wpf-topic-form-forumid" style="width: 100%; max-width: 100%;">
892 <option class="wpf-topic-form-no-selected-forum" value="0">-- <?php wpforo_phrase( 'No forum selected' ); ?> --</option>
893 <?php WPF()->forum->tree( 'select_box', false, (array) $forumid, true, [], $parent_forumid ); ?>
894 </select>
895 </div>
896 </div>
897 <div class="wpf-topic-form-ajax-wrap"><?php if( (int) $forumid ) $this->topic_form( $forumid ); ?></div>
898 </div>
899 <?php
900 }
901
902 /**
903 * @param array|int $forum
904 * @param array $values
905 */
906 function topic_form( $forum = [], $values = [] ) {
907 if( ! $forum ) $forum = WPF()->current_object['forum'];
908 if( is_scalar( $forum ) ) $forum = WPF()->forum->get_forum( (int) $forum );
909 if( ! $forum ) return;
910 $forumid = intval( $forum['forumid'] );
911 $layout = WPF()->forum->get_layout( $forum );
912 $uniqid = uniqid();
913 WPF()->form->current['varname'] = 'thread';
914 ?>
915 <div class="wpf-form-wrapper wpf-topic-create" data-suggestion="<?php echo (apply_filters( 'wpforo_topic_suggestion', true ) ? 'true' : 'false') ?>">
916 <form enctype="multipart/form-data" method="POST" class="wpforoeditor" data-bodyminlength="<?php echo wpforo_setting( 'posting', 'topic_body_min_length' ) ?>" data-bodymaxlength="<?php echo wpforo_setting( 'posting', 'topic_body_max_length' ) ?>">
917 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
918 <input type="hidden" name="wpfaction" value="<?php echo ! $values ? 'topic_add' : 'topic_edit' ?>">
919 <input type="hidden" name="thread[forumid]" value="<?php echo $forumid ?>">
920 <?php if( $values ) : ?>
921 <input type="hidden" name="thread[topicid]" value="<?php echo wpforo_bigintval( wpfval( $values, 'topicid' ) ) ?>">
922 <input type="hidden" name="thread[postid]" value="<?php echo wpforo_bigintval( wpfval( $values, 'postid' ) ) ?>">
923 <?php endif ?>
924
925 <div class="wpf-topic-form-wrap">
926 <?php wpforo_fields( WPF()->post->get_topic_fields( $forum, $values, ! WPF()->current_userid ) ) ?>
927 <div class="wpf-extra-fields">
928 <?php do_action( 'wpforo_topic_form_extra_before', $forumid, $values ) ?>
929 <div class="wpf-main-fields">
930 <?php if( ! $values ) : ?>
931 <?php if( WPF()->perm->forum_can( 's', $forumid ) ) : ?>
932 <input id="wpf_t_sticky_<?php echo $uniqid ?>" name="thread[type]" type="checkbox" value="1">&nbsp;&nbsp;
933 <i class="fas fa-exclamation wpfsx"></i>&nbsp;&nbsp;
934 <label for="wpf_t_sticky_<?php echo $uniqid ?>" style="padding-bottom:2px; cursor: pointer;"><?php wpforo_phrase( 'Set Topic Sticky' ); ?>&nbsp;</label>
935 <span class="wpfbs">&nbsp;&nbsp;|&nbsp;&nbsp;</span>
936 <?php endif; ?>
937 <?php if( WPF()->perm->forum_can( 'p', $forumid ) || WPF()->perm->forum_can( 'op', $forumid ) ) : ?>
938 <input id="wpf_t_private_<?php echo $uniqid ?>" name="thread[private]" type="checkbox" value="1">&nbsp;&nbsp;
939 <i class="fas fa-eye-slash wpfsx"></i>&nbsp;&nbsp;
940 <label for="wpf_t_private_<?php echo $uniqid ?>" style="padding-bottom:2px; cursor: pointer;" title="<?php wpforo_phrase( 'Only Admins and Moderators can see your private topics.' ); ?>"><?php wpforo_phrase( 'Private Topic' ); ?>&nbsp;</label>
941 <?php endif; ?>
942 <?php endif ?>
943 <?php do_action( 'wpforo_topic_buttons_hook', $forumid, $values ); ?>
944 </div>
945 <?php do_action( 'wpforo_topic_form_extra_after', $forumid, $values ) ?>
946 </div>
947 <?php if( wpforo_is_module_enabled( 'tags' ) && WPF()->perm->forum_can( 'tag', $forumid ) ) : ?>
948 <div class="wpf-topic-tags">
949 <p class="wpf-topic-tags-label">
950 <label for="wpf_tags_<?php echo $uniqid ?>">
951 <i class="fas fa-tag"></i>
952 <?php $layout == 3 ? wpforo_phrase( 'Question Tags' ) : wpforo_phrase( 'Topic Tags' ) ?>
953 <span>(<?php wpforo_phrase( 'Separate tags using a comma' ) ?>)</span>
954 </label>
955 </p>
956 <input id="wpf_tags_<?php echo $uniqid ?>" class="wpf-tags" placeholder="<?php echo sprintf( wpforo_phrase( 'Start typing tags here (maximum %d tags are allowed)...', false ), wpforo_setting( 'tags', 'max_per_topic' ) ) ?>" name="thread[tags]" autocomplete="off" value="<?php echo wpfval( $values, 'tags' ) ?>" type="text">
957 </div>
958 <?php endif; ?>
959 <?php do_action( 'wpforo_editor_topic_submit_before', $forum, $values ) ?>
960 <div class="wpf-buttons-wrap">
961 <?php if( $values ) : ?>
962 <input type="button" class="wpf-button wpf-button-secondary wpf-edit-post-cancel" value="<?php wpforo_phrase( 'Cancel' ) ?>">
963 <input type="submit" class="wpf-button" value="<?php wpforo_phrase( 'Save' ) ?>" title="Ctrl+Enter">
964 <?php else : ?>
965 <input type="submit" class="wpf-button" value="<?php $layout == 3 ? wpforo_phrase( 'Ask a question' ) : wpforo_phrase( 'Add topic' ) ?>" title="Ctrl+Enter">
966 <?php endif ?>
967 </div>
968 <?php do_action( 'wpforo_editor_topic_submit_after', $forumid, $values ) ?>
969 <div class="wpf-clear"></div>
970 </div>
971 </form>
972 </div>
973
974 <?php
975 }
976
977 /**
978 * @param array|int $topic
979 * @param array $values post object edit values
980 */
981 function reply_form( $topic = [], $values = [] ) {
982 if( ! $topic ) $topic = WPF()->current_object['topic'];
983 if( is_scalar( $topic ) ) $topic = wpforo_topic( $topic );
984 $forum = WPF()->forum->get_forum( wpfval( $topic, 'forumid' ) );
985 if( wpfval( $topic, 'closed' ) ) return;
986 $layout = $topic['layout'] = WPF()->forum->get_layout( $forum );
987
988 WPF()->form->current['varname'] = 'post';
989
990 $style = ( $layout === 3 && ! wpforo_setting( 'posting', 'qa_display_answer_editor' ) ) ? 'style="display: none;"' : '';
991 $parentid = ( $layout === 3 && ! WPF()->topic->can_answer( $topic['topicid'] ) ) ? wpforo_bigintval( wpfval( $topic, 'first_postid' ) ) : 0;
992 $v = $values;
993 if( ! trim( (string) wpfval( $v, 'title' ) ) ) $v['title'] = $topic['title'];
994 ?>
995 <div class="wpf-form-wrapper wpfel-<?php echo $layout ?>" <?php echo $style ?>>
996 <?php if( ! $values ): ?>
997 <p class="wpf-reply-form-title"><?php echo apply_filters( 'wpforo_reply_form_head', wpforo_phrase( 'Leave a reply', false ), $topic ) ?></p>
998 <?php endif ?>
999 <div class="wpf-post-create">
1000 <form enctype="multipart/form-data" method="POST" class="wpforoeditor <?php echo( ! $values ? 'wpforo-main-form' : '' ) ?>" data-bodyminlength="<?php echo wpforo_setting( 'posting', 'post_body_min_length' ) ?>" data-bodymaxlength="<?php echo wpforo_setting( 'posting', 'post_body_max_length' ) ?>">
1001 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1002 <input type="hidden" name="wpfaction" value="<?php echo ! $values ? 'post_add' : 'post_edit' ?>">
1003 <input type="hidden" class="wpf-form-forumid" name="post[forumid]" value="<?php echo intval( $topic['forumid'] ) ?>">
1004 <input type="hidden" class="wpf-form-topicid" name="post[topicid]" value="<?php echo intval( $topic['topicid'] ) ?>">
1005 <input type="hidden" class="wpf-form-post-parentid" name="post[parentid]" value="<?php echo $parentid ?>">
1006 <input type="hidden" class="wpf-form-postid" name="post[postid]" value="<?php echo wpforo_bigintval( wpfval( $values, 'postid' ) ) ?>">
1007 <?php wpforo_fields( WPF()->post->get_post_fields( $forum, $topic, $v, ! WPF()->current_userid ) ); ?>
1008 <div class="wpf-extra-fields">
1009 <?php do_action( 'wpforo_reply_form_extra_before', $topic, $values, $forum ) ?>
1010 <?php do_action( 'wpforo_reply_buttons_hook', $topic, $values, $forum ); ?>
1011 <?php do_action( 'wpforo_reply_form_extra_after', $topic, $values, $forum ) ?>
1012 </div>
1013 <?php do_action( 'wpforo_editor_post_submit_before', $topic, $values, $forum ) ?>
1014 <div class="wpf-buttons-wrap">
1015 <?php if( $values ) : ?>
1016 <input type="button" class="wpf-button wpf-button-secondary wpf-edit-post-cancel" value="<?php wpforo_phrase( 'Cancel' ) ?>">
1017 <input type="submit" class="wpf-button" value="<?php wpforo_phrase( 'Save' ) ?>" title="Ctrl+Enter">
1018 <?php else : ?>
1019 <input type="submit" class="wpf-button" value="<?php $layout === 3 ? wpforo_phrase( 'Answer' ) : wpforo_phrase( 'Add Reply' ) ?>" title="Ctrl+Enter">
1020 <?php endif ?>
1021 </div>
1022 <?php do_action( 'wpforo_editor_post_submit_after', $topic, $values, $forum ) ?>
1023 <div class="wpf-clear"></div>
1024 </form>
1025 </div>
1026 </div>
1027 <?php
1028 if( ! $values && in_array( $layout, [ 3, 4 ], true ) ) {
1029 $is_rich_editor = ( $layout === 3 ? wpforo_setting( 'posting', 'qa_comments_rich_editor' ) : wpforo_setting( 'posting', 'threaded_reply_rich_editor' ) );
1030 if( $is_rich_editor ) {
1031 $this->post_form();
1032 } else {
1033 $this->post_form_simple();
1034 }
1035 }
1036 }
1037
1038 public function post_form_simple() {
1039 if( wpfval( WPF()->current_object, 'topic', 'closed' ) ) return;
1040 $textareaid = uniqid( 'wpf_post_body_' );
1041 $topicid = wpforo_bigintval( wpfval( WPF()->current_object, 'topicid' ) );
1042 $topic = WPF()->current_object['topic'];
1043 $forum = WPF()->current_object['forum'];
1044 $layout = WPF()->forum->get_layout();
1045 $bodyminlength = ( $layout == 3 ? wpforo_setting( 'posting', 'comment_body_min_length' ) : wpforo_setting( 'posting', 'post_body_min_length' ) );
1046 $bodymaxlength = ( $layout == 3 ? wpforo_setting( 'posting', 'comment_body_max_length' ) : wpforo_setting( 'posting', 'post_body_max_length' ) );
1047 $submit_ico = ( $layout == 3 ? '<i class="far fa-comment"></i>' : '<i class="fas fa-reply"></i>' );
1048 $submit_value = ( $layout == 3 ? wpforo_phrase( 'Add a comment', false ) : wpforo_phrase( 'Reply', false ) );
1049 $uniqid = uniqid();
1050 ?>
1051 <form enctype="multipart/form-data" method="POST" class="wpforo-post-form" style="display: none;" data-textareaid="<?php echo $textareaid ?>" data-bodyminlength="<?php echo $bodyminlength ?>" data-bodymaxlength="<?php echo $bodymaxlength ?>">
1052 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1053 <input type="hidden" name="wpfaction" value="post_add">
1054 <input type="hidden" class="wpf_post_forumid" name="post[forumid]" value="<?php echo wpforo_bigintval( wpfval( WPF()->current_object, 'forumid' ) ) ?>">
1055 <input type="hidden" class="wpf_post_topicid" name="post[topicid]" value="<?php echo wpforo_bigintval( wpfval( WPF()->current_object, 'topicid' ) ) ?>">
1056 <input type="hidden" class="wpf_post_parentid" name="post[parentid]" value="0">
1057 <?php if( ! is_user_logged_in() ): ?>
1058 <?php $guest = WPF()->member->get_guest_cookies(); ?>
1059 <div class="wpf-post-guest-fields" style="display: table;">
1060 <div class="wpf-post-guest-name" style="display: table-row;">
1061 <label for="wpf-name-<?php echo $uniqid ?>" style="padding-left:8px; display: table-cell;"> <?php wpforo_phrase( 'Author Name' ) ?> * </label>
1062 <input id="wpf-name-<?php echo $uniqid ?>" class="wpf_user_name" style="display: table-cell;" type="text" placeholder="<?php esc_attr( wpforo_phrase( 'Your name' ) ) ?>" name="post[name]" value="<?php echo esc_attr( $guest['name'] ) ?>" required>
1063 </div>
1064 <div class="wpf-post-guest-email" style="display: table-row;">
1065 <label for="wpf-email-<?php echo $uniqid ?>" style="padding-left:8px; display: table-cell;"> <?php wpforo_phrase( 'Author Email' ) ?> * </label>
1066 <input id="wpf-email-<?php echo $uniqid ?>" class="wpf_user_email" style="display: table-cell;" type="text" placeholder="<?php esc_attr( wpforo_phrase( 'Your email' ) ) ?>" name="post[email]" value="<?php echo esc_attr( $guest['email'] ) ?>" required>
1067 </div>
1068 <div class="wpf-clear"></div>
1069 </div>
1070 <?php endif; ?>
1071 <div class="wpf_post_form_textarea_wrap" data-textareatype="simple_editor">
1072 <label for="<?php echo $textareaid ?>"></label><textarea id="<?php echo $textareaid ?>" required class="wpf_post_body" name="post[body]" placeholder="<?php wpforo_phrase( 'Write here . . .' ) ?>"></textarea>
1073 </div>
1074 <div class="wpf-extra-fields">
1075 <?php do_action( 'wpforo_portable_form_extra_fields_before', $topic, [], $forum ) ?>
1076 <?php do_action( 'wpforo_portable_form_buttons_hook', $topic, [], $forum ); ?>
1077 <?php do_action( 'wpforo_portable_form_extra_fields_after', $topic, [], $forum ) ?>
1078 </div>
1079 <?php do_action( 'wpforo_portable_editor_post_submit_before', $topic, [], $forum ) ?>
1080 <button type="submit" name="post[save]" class="wpf-button" title="Ctrl+Enter">
1081 <?php echo $submit_ico ?>
1082 <?php echo $submit_value ?>
1083 </button>
1084 <button type="reset" class="wpf-button-secondary wpf-button-close-form">
1085 <i class="fas fa-times"></i>
1086 <span class="wpf-button-text"><?php wpforo_phrase( 'Cancel' ) ?></span>
1087 </button>
1088 <div class="wpf-clear"></div>
1089 <?php do_action( 'wpforo_portable_editor_post_submit_after', $topic, [], $forum ) ?>
1090 </form>
1091 <?php
1092 }
1093
1094 public function post_form() {
1095 if( wpfval( WPF()->current_object, 'topic', 'closed' ) ) return;
1096 $textareaid = uniqid( 'wpf_post_body_' );
1097 $topicid = wpforo_bigintval( wpfval( WPF()->current_object, 'topicid' ) );
1098 $topic = WPF()->current_object['topic'];
1099 $forum = WPF()->current_object['forum'];
1100 $layout = WPF()->forum->get_layout();
1101 $bodyminlength = ( $layout == 3 ? wpforo_setting( 'posting', 'comment_body_min_length' ) : wpforo_setting( 'posting', 'post_body_min_length' ) );
1102 $bodymaxlength = ( $layout == 3 ? wpforo_setting( 'posting', 'comment_body_max_length' ) : wpforo_setting( 'posting', 'post_body_max_length' ) );
1103 $submit_ico = ( $layout == 3 ? '<i class="far fa-comment"></i>' : '<i class="fas fa-reply"></i>' );
1104 $submit_value = ( $layout == 3 ? wpforo_phrase( 'Add a comment', false ) : wpforo_phrase( 'Reply', false ) );
1105 $uniqid = uniqid();
1106 ?>
1107 <form enctype="multipart/form-data" method="POST" class="wpforo-post-form" style="display: none;" data-textareaid="<?php echo $textareaid ?>" data-bodyminlength="<?php echo $bodyminlength ?>" data-bodymaxlength="<?php echo $bodymaxlength ?>">
1108 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1109 <input type="hidden" name="wpfaction" value="post_add">
1110 <input type="hidden" class="wpf_post_forumid" name="post[forumid]" value="<?php echo wpforo_bigintval( wpfval( WPF()->current_object, 'forumid' ) ) ?>">
1111 <input type="hidden" class="wpf_post_topicid" name="post[topicid]" value="<?php echo $topicid ?>">
1112 <input type="hidden" class="wpf_post_parentid" name="post[parentid]" value="0">
1113 <?php if( ! is_user_logged_in() ): ?>
1114 <?php $guest = WPF()->member->get_guest_cookies(); ?>
1115 <div class="wpf-post-guest-fields" style="display: table;">
1116 <div class="wpf-post-guest-name" style="display: table-row;">
1117 <label for="wpf-name-<?php echo $uniqid ?>" style="padding-left:8px; display: table-cell;"> <?php wpforo_phrase( 'Author Name' ) ?> * </label>
1118 <input id="wpf-name-<?php echo $uniqid ?>" class="wpf_user_name" style="display: table-cell;" type="text" placeholder="<?php esc_attr( wpforo_phrase( 'Your name' ) ) ?>" name="post[name]" value="<?php echo esc_attr( $guest['name'] ) ?>" required>
1119 </div>
1120 <div class="wpf-post-guest-email" style="display: table-row;">
1121 <label for="wpf-email-<?php echo $uniqid ?>" style="padding-left:8px; display: table-cell;"> <?php wpforo_phrase( 'Author Email' ) ?> * </label>
1122 <input id="wpf-email-<?php echo $uniqid ?>" class="wpf_user_email" style="display: table-cell;" type="text" placeholder="<?php esc_attr( wpforo_phrase( 'Your email' ) ) ?>" name="post[email]" value="<?php echo esc_attr( $guest['email'] ) ?>" required>
1123 </div>
1124 <div class="wpf-clear"></div>
1125 </div>
1126 <?php endif; ?>
1127 <div class="wpf_post_form_textarea_wrap wpf-post-create" data-textareatype="rich_editor">
1128 <textarea id="<?php echo $textareaid ?>" class="wpf_post_body" name="post[body]"></textarea>
1129 </div>
1130 <div class="wpf-extra-fields">
1131 <?php do_action( 'wpforo_portable_form_extra_fields_before', $topic, [], $forum ) ?>
1132 <?php do_action( 'wpforo_portable_form_buttons_hook', $topic, [], $forum ); ?>
1133 <?php do_action( 'wpforo_portable_form_extra_fields_after', $topic, [], $forum ) ?>
1134 </div>
1135 <?php do_action( 'wpforo_portable_editor_post_submit_before', $topic, [], $forum ) ?>
1136 <button type="submit" name="post[save]" class="wpf-button" title="Ctrl+Enter">
1137 <?php echo $submit_ico ?>
1138 <?php echo $submit_value ?>
1139 </button>
1140 <button type="reset" class="wpf-button-secondary wpf-button-close-form">
1141 <i class="fas fa-times"></i>
1142 <span class="wpf-button-text"><?php wpforo_phrase( 'Cancel' ) ?></span>
1143 </button>
1144 <div class="wpf-clear"></div>
1145 <?php do_action( 'wpforo_portable_editor_post_submit_after', $topic, [], $forum ) ?>
1146 <div class="wpf-clear"></div>
1147 </form>
1148 <?php
1149 }
1150
1151 public function topic_moderation_tabs( $tabs = [] ) {
1152 $tabs = apply_filters( 'wpforo_topic_moderation_tabs', $tabs );
1153 if( ! $tabs ) return;
1154 $default_tab = [ 'title' => '', 'id' => '', 'class' => '', 'icon' => '', 'active' => false ];
1155 ?>
1156 <div class="wpf-tool-tabs">
1157 <?php foreach( $tabs as $tab ) : $tab = wpforo_parse_args( $tab, $default_tab ); ?>
1158 <div id="<?php echo esc_attr( $tab['id'] ) ?>" class="wpf-tool-tab <?php echo $tab['class'];
1159 echo( $tab['active'] ? ' wpf-tt-active' : '' ); ?>">
1160 <i class="<?php echo $tab['icon'] ?>"></i>&nbsp;
1161 <?php echo $tab['title'] ?>
1162 </div>
1163 <?php endforeach; ?>
1164 </div>
1165 <div id="wpf_tool_tab_content_wrap">
1166 <i class="fas fa-spinner fa-spin wpf-icon-spinner"></i>
1167 </div>
1168 <?php
1169 }
1170
1171 private function topic_merge_form() {
1172 ?>
1173 <div class="wpf-tool wpf-tool-merge">
1174 <h3><i class="fas fa-code-branch"></i></h3>
1175 <div class="wpf-cl"></div>
1176 <form method="post" enctype="multipart/form-data" action="">
1177 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1178 <input type="hidden" name="wpfaction" value="topic_merge">
1179 <ul>
1180 <li class="wpf-target-topic">
1181 <label for="target-topic" class="wpf-input-label"><?php wpforo_phrase( 'Target Topic URL' ) ?> <sup>*</sup></label>
1182 <div class="wpf-tool-desc">
1183 <?php wpforo_phrase( 'Please copy the target topic URL from browser address bar and paste in the field below.' ) ?><br/>
1184 </div>
1185 <input id="target-topic" type="text" required name="wpforo[target_topic_url]" value="" placeholder="https://example.com/community/main-forum/target-topic/"/>
1186 <div class="wpf-tool-desc" style="margin: 15px 1px 0 1px;">
1187 <?php wpforo_phrase( 'All posts will be merged and displayed (ordered) in target topic according to posts dates. If you want to append merged posts to the end of the target topic you should allow to update posts dates to current date by check the option below.' ) ?>
1188 </div>
1189 </li>
1190 <li class="wpf-update-date-and-append"><input id="update-date-and-append" type="checkbox" name="wpforo[update_date_and_append]" value="1"/> <label for="update-date-and-append"><?php wpforo_phrase( 'Update post dates (current date) to allow append posts to the end of the target topic.' ) ?></label></li>
1191 <li class="wpf-update-to-target-title"><input id="update-to-target-title" type="checkbox" name="wpforo[to_target_title]" value="1" checked/> <label for="update-to-target-title"><?php wpforo_phrase( 'Update post titles with target topic title.' ) ?></label></li>
1192 <li><i class="fas fa-info-circle wpfcl-5" style="font-size: 16px;"></i> &nbsp;<?php wpforo_phrase( 'Topics once merged cannot be unmerged. This topic URL will no longer be available.' ) ?></li>
1193 <li class="wpf-submit"><input type="submit" name="wpforo[topic_merge]" value="<?php wpforo_phrase( 'Merge' ) ?>"></li>
1194 </ul>
1195 </form>
1196 </div>
1197 <?php
1198 }
1199
1200 private function reply_move_form() {
1201 if( ! $posts = WPF()->post->get_posts( [ 'topicid' => WPF()->current_object['topicid'] ] ) ) return;
1202 if( count( $posts ) < 2 ) return;
1203 ?>
1204 <div class="wpf-tool wpf-tool-split">
1205 <h3><i class="far fa-share-square"></i></h3>
1206 <div class="wpf-cl"></div>
1207 <form id="wpforo_split_form" method="post" enctype="multipart/form-data" action="">
1208 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1209 <input type="hidden" name="wpfaction" value="topic_split">
1210 <ul>
1211 <li id="wpf_split_target_url" class="wpf-target-topic">
1212 <label for="spl-target-url" class="wpf-input-label"><?php wpforo_phrase( 'Target Topic URL' ) ?> <sup>*</sup></label>
1213 <div class="wpf-tool-desc">
1214 <?php wpforo_phrase( 'Please copy the target topic URL from browser address bar and paste in the field below.' ) ?><br/>
1215 </div>
1216 <input id="spl-target-url" type="text" name="wpforo[target_topic_url]" required placeholder="https://example.com/community/main-forum/target-topic/"/>
1217 <div class="wpf-tool-desc" style="margin: 15px 1px 0 1px;">
1218 <?php wpforo_phrase( 'All posts will be merged and displayed (ordered) in target topic according to posts dates. If you want to append merged posts to the end of the target topic you should allow to update posts dates to current date by check the option below.' ) ?>
1219 </div>
1220 </li>
1221 <li id="wpf_split_append">
1222 <input id="spl-update-date-and-append" type="checkbox" name="wpforo[update_date_and_append]" value="1"/>
1223 <label for="spl-update-date-and-append"><?php wpforo_phrase( 'Update post dates (current date) to allow append posts to the end of the target topic.' ) ?></label>
1224 </li>
1225 <li>
1226 <input id="split-update-to-target-title" type="checkbox" name="wpforo[to_target_title]" value="1" checked/>
1227 <label for="split-update-to-target-title"><?php wpforo_phrase( 'Update post titles with target topic title.' ) ?></label>
1228 </li>
1229 <li>
1230 <label class="wpf-input-label"><?php wpforo_phrase( 'Select Posts to Split' ) ?> <sup>*</sup></label>
1231 <div class="wpf-split-posts">
1232 <ul>
1233 <?php foreach( $posts as $post ) :
1234 if( $title = wpforo_text( $post['body'], 200, false ) ) {
1235 $value = wpforo_text( $post['body'], 100, false );
1236 } else {
1237 $title = wpforo_text( $post['title'], 200, false );
1238 $value = wpforo_text( $post['title'], 100, false );
1239 }
1240 ?>
1241 <li>
1242 <label title="<?php echo $title ?>">
1243 <input type="checkbox" name="wpforo[posts][]" value="<?php echo $post['postid'] ?>">
1244 <?php echo $value ?>
1245 </label>
1246 </li>
1247 <?php endforeach; ?>
1248 </ul>
1249 </div>
1250 </li>
1251 <li style="padding-top: 10px;"><i class="fas fa-info-circle wpfcl-5" style="font-size: 16px;"></i> &nbsp;<?php wpforo_phrase( 'Topic once split cannot be unsplit. The first post of new topic becomes the earliest reply.' ) ?></li>
1252 <li class="wpf-submit"><input type="submit" name="wpforo[topic_split]" value="<?php wpforo_phrase( 'Move' ) ?>"></li>
1253 </ul>
1254 </form>
1255 </div>
1256 <?php
1257 }
1258
1259 private function topic_split_form() {
1260 if( ! $posts = WPF()->post->get_posts( [ 'topicid' => WPF()->current_object['topicid'] ] ) ) return;
1261 if( count( $posts ) < 2 ) return;
1262 ?>
1263 <div class="wpf-tool wpf-tool-split">
1264 <h3><i class="fas fa-cut"></i></h3>
1265 <div class="wpf-cl"></div>
1266 <form id="wpforo_split_form" method="post" enctype="multipart/form-data" action="">
1267 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1268 <input type="hidden" name="wpfaction" value="topic_split">
1269 <ul>
1270 <li>
1271 <input id="wpf_split_create_new" type="checkbox" name="wpforo[create_new]" value="1" checked>
1272 <label for="wpf_split_create_new" class="wpf-input-label" style="display: inline-block;"><?php wpforo_phrase( 'Create New Topic' ) ?></label>
1273 <div class="wpf-tool-desc">
1274 <?php wpforo_phrase( 'Create new topic with split posts. The first post of new topic becomes the earliest reply.' ) ?><br/>
1275 </div>
1276 </li>
1277 <li id="wpf_split_target_url" class="wpf-target-topic" style="display: none;">
1278 <label for="spl-target-url" class="wpf-input-label"><?php wpforo_phrase( 'Target Topic URL' ) ?> <sup>*</sup></label>
1279 <div class="wpf-tool-desc">
1280 <?php wpforo_phrase( 'Please copy the target topic URL from browser address bar and paste in the field below.' ) ?><br/>
1281 </div>
1282 <input id="spl-target-url" type="text" name="wpforo[target_topic_url]" required disabled placeholder="https://example.com/community/main-forum/target-topic/">
1283 <div class="wpf-tool-desc" style="margin: 15px 1px 0 1px;">
1284 <?php wpforo_phrase( 'All posts will be merged and displayed (ordered) in target topic according to posts dates. If you want to append merged posts to the end of the target topic you should allow to update posts dates to current date by check the option below.' ) ?>
1285 </div>
1286 </li>
1287 <li id="wpf_split_append" style="display: none;">
1288 <input id="spl-update-date-and-append" type="checkbox" name="wpforo[update_date_and_append]" value="1"/>
1289 <label for="spl-update-date-and-append"><?php wpforo_phrase( 'Update post dates (current date) to allow append posts to the end of the target topic.' ) ?></label>
1290 </li>
1291 <li id="wpf_split_new_title">
1292 <label for="spl-topic-title" class="wpf-input-label"><?php wpforo_phrase( 'New Topic Title' ) ?> <sup>*</sup></label>
1293 <input id="spl-topic-title" type="text" name="wpforo[new_topic_title]" required placeholder="<?php wpforo_phrase( 'Topic Title' ) ?>"/>
1294 </li>
1295 <li id="wpf_split_forumid"><label for="spl-topic-forum" class="wpf-input-label"><?php wpforo_phrase( 'New Topic Forum' ) ?> <sup>*</sup></label>
1296 <select id="spl-topic-forum" name="wpforo[new_topic_forumid]"><?php WPF()->forum->tree( 'select_box', false, WPF()->current_object['forumid'] ) ?></select></li>
1297 <li>
1298 <input id="split-update-to-target-title" type="checkbox" name="wpforo[to_target_title]" value="1" checked/>
1299 <label for="split-update-to-target-title"><?php wpforo_phrase( 'Update post titles with target topic title.' ) ?></label>
1300 </li>
1301 <li>
1302 <label class="wpf-input-label"><?php wpforo_phrase( 'Select Posts to Split' ) ?> <sup>*</sup></label>
1303 <div class="wpf-split-posts">
1304 <ul>
1305 <?php foreach( $posts as $post ) :
1306 if( $title = wpforo_text( $post['body'], 200, false ) ) {
1307 $value = wpforo_text( $post['body'], 100, false );
1308 } else {
1309 $title = wpforo_text( $post['title'], 200, false );
1310 $value = wpforo_text( $post['title'], 100, false );
1311 }
1312 ?>
1313 <li>
1314 <label title="<?php echo $title ?>">
1315 <input type="checkbox" name="wpforo[posts][]" value="<?php echo $post['postid'] ?>">
1316 <?php echo $value ?>
1317 </label>
1318 </li>
1319 <?php endforeach; ?>
1320 </ul>
1321 </div>
1322 </li>
1323 <li style="padding-top: 10px;"><i class="fas fa-info-circle wpfcl-5" style="font-size: 16px;"></i> &nbsp;<?php wpforo_phrase( 'Topic once split cannot be unsplit. The first post of new topic becomes the earliest reply.' ) ?></li>
1324 <li class="wpf-submit"><input type="submit" name="wpforo[topic_split]" value="<?php wpforo_phrase( 'Split' ) ?>"></li>
1325 </ul>
1326 </form>
1327 </div>
1328 <?php
1329 }
1330
1331 public function topic_move_form( $topicid = null ) {
1332 if( ! $topicid && empty( WPF()->current_object['topicid'] ) ) return;
1333 if( ! $topicid ) $topicid = WPF()->current_object['topicid'];
1334 ?>
1335 <div class="wpf-tool wpf-tool-split">
1336 <h3><i class="far fa-share-square"></i></h3>
1337 <div class="wpf-cl"></div>
1338 <form id="wpf_topicmoveform" method="POST" enctype="multipart/form-data" action="">
1339 <?php wp_nonce_field( 'wpforo_verify_form', '_wpfnonce' ); ?>
1340 <input type="hidden" name="wpfaction" value="topic_move">
1341 <input type="hidden" name="topic_move[topicid]" value="<?php echo intval( $topicid ) ?>"/>
1342 <ul>
1343 <li>
1344 <div id="wpf_movedialog" title="<?php esc_attr( wpforo_phrase( 'Move topic' ) ) ?>">
1345 <div class="form-field">
1346 <label for="parent"></label>
1347 <label for="spl-target-url" class="wpf-input-label" style="padding-bottom: 7px;"><?php wpforo_phrase( 'Choose Target Forum' ) ?><sup>*</sup></label>
1348 <label>
1349 <select name="topic_move[forumid]" class="postform">
1350 <?php WPF()->forum->tree( 'select_box', false ); ?>
1351 </select>
1352 </label>
1353 </div>
1354 </div>
1355 </li>
1356 <li style="padding-top: 20px;"><i class="fas fa-info-circle wpfcl-5" style="font-size: 16px;"></i>
1357 &nbsp;<?php wpforo_phrase( 'This action changes topic URL. Once the topic is moved to other forum the old URL of this topic will no longer be available.' ) ?>
1358 </li>
1359 <li class="wpf-submit"><input type="submit" value="<?php wpforo_phrase( 'Move' ) ?>"/></li>
1360 </ul>
1361 </form>
1362 </div>
1363 <?php
1364 }
1365
1366 public function post_search_form( $values ) {
1367 $type = wpfval( $values, 'type' );
1368 $is_tag = $type === 'tag';
1369 $needle = wpfval( $values, 'needle' );
1370 $date_period = (int) wpfval( $values, 'date_period' );
1371 $order = strtolower( (string) wpfval( $values, 'order' ) );
1372 $orderby = (string) wpfval( $values, 'orderby' );
1373 $forumids = (array) wpfval( $_GET, 'wpff' );
1374 $search_fields = WPF()->post->get_search_fields( (array) wpfval( $_GET, 'data' ) );
1375 ?>
1376 <form action="<?php echo wpforo_home_url() ?>" method="get">
1377 <?php wpforo_make_hidden_fields_from_url( wpforo_home_url() ) ?>
1378 <div class="wpforo-table">
1379 <div class="wpforo-tr">
1380 <div class="wpforo-td wpfw-60 wpfltd">
1381 <span class="wpf-search-label wpfcl-1">&nbsp;<?php wpforo_phrase( 'Search Phrase' ) ?>:</span><br>
1382 <label>
1383 <input type="text" name="wpfs" class="wpfs wpfw-90" value="<?php echo esc_attr( $needle ) ?>">
1384 </label>
1385 </div>
1386 <div class="wpforo-td wpfw-40 wpfrtd">
1387 <span class="wpf-search-label wpfcl-1">&nbsp;<?php wpforo_phrase( 'Search Type' ) ?>:</span><br>
1388 <label>
1389 <select name="wpfin" class="wpfw-90 wpfin">
1390 <option value="entire-posts" <?php echo $type === 'entire-posts' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Search Entire Posts' ) ?></option>
1391 <option value="titles-only" <?php echo $type === 'titles-only' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Search Titles Only' ) ?></option>
1392 <option value="tag" <?php echo $type === 'tag' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Find Topics by Tags' ) ?></option>
1393 <option value="user-posts" <?php echo $type === 'user-posts' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Find Posts by User' ) ?></option>
1394 <option value="user-topics" <?php echo $type === 'user-topics' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Find Topics Started by User' ) ?></option>
1395 </select>
1396 </label>
1397 </div>
1398 </div>
1399 </div>
1400 <div class="wpforo-table wpf-toggle-wrap wpf-search-advanced-wrap" <?php if( $is_tag ) echo 'style="display: none;"'; ?>>
1401 <div class="wpforo-tr">
1402 <div class="wpforo-td wpfw-100 wpfrtd wpf-toggle">
1403 <span class="wpf-toggle-button wpf-toggle-advanced">
1404 <i class="fas fa-chevron-down wpf-ico"></i><?php wpforo_phrase( 'Advanced search options' ) ?>
1405 </span>
1406 </div>
1407 </div>
1408 <div class="wpforo-tr wpf-cfields">
1409 <div class="wpforo-td wpfw-100 wpfltd wpf-last">
1410 <div class="wpf-search-advanced-fields">
1411 <div class="wpforo-table">
1412 <div class="wpforo-tr">
1413 <div class="wpforo-td wpfw-60 wpfltd">
1414 <span class="wpf-search-label wpfcl-1">&nbsp;<?php wpforo_phrase( 'Search in Forums' ) ?>:</span><br>
1415 <label>
1416 <select name="wpff[]" class="wpfw-90 wpff" multiple="multiple">
1417 <?php WPF()->forum->tree( 'select_box', false, $forumids ) ?>
1418 </select>
1419 </label>
1420 </div>
1421 <div class="wpforo-td wpfw-40 wpfrtd">
1422 <span class="wpf-search-label wpfcl-1">&nbsp;<?php wpforo_phrase( 'Search in date period' ) ?>:</span><br>
1423 <label>
1424 <select name="wpfd" class="wpfw-90 wpfd">
1425 <option value="0" <?php echo $date_period === 0 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Any Date' ) ?></option>
1426 <option value="1" <?php echo $date_period === 1 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Last 24 hours' ) ?></option>
1427 <option value="7" <?php echo $date_period === 7 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Last Week' ) ?></option>
1428 <option value="30" <?php echo $date_period === 30 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Last Month' ) ?></option>
1429 <option value="90" <?php echo $date_period === 90 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Last 3 Months' ) ?></option>
1430 <option value="180" <?php echo $date_period === 180 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Last 6 Months' ) ?></option>
1431 <option value="365" <?php echo $date_period === 365 ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Last Year ago' ) ?></option>
1432 </select>
1433 </label>
1434 <br>
1435 <span class="wpf-search-label wpfcl-1">&nbsp;<?php wpforo_phrase( 'Sort Search Results by' ) ?>:</span><br>
1436 <label>
1437 <select class="wpfw-90 wpfob" name="wpfob">
1438 <option value="relevancy" <?php echo $orderby === 'relevancy' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Relevancy' ) ?></option>
1439 <option value="date" <?php echo $orderby === 'date' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Date' ) ?></option>
1440 <option value="user" <?php echo $orderby === 'user' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'User' ) ?></option>
1441 <option value="forum" <?php echo $orderby === 'forum' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Forum' ) ?></option>
1442 </select>
1443 </label><br>
1444 <label>
1445 <select class="wpfw-90 wpfo" name="wpfo">
1446 <option value="desc" <?php echo $order === 'desc' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Descending order' ) ?></option>
1447 <option value="asc" <?php echo $order === 'asc' ? 'selected' : '' ?>>&nbsp;<?php wpforo_phrase( 'Ascending order' ) ?></option>
1448 </select>
1449 </label>
1450 </div>
1451 </div>
1452 </div>
1453 </div>
1454 </div>
1455 </div>
1456 </div>
1457 <?php if( $search_fields && ! $is_tag ) : ?>
1458 <div class="wpforo-table wpf-toggle-wrap wpf-search-custom-wrap">
1459 <div class="wpforo-tr">
1460 <div class="wpforo-td wpfw-100 wpfrtd wpf-toggle">
1461 <span class="wpf-toggle-button wpf-toggle-custom">
1462 <i class="fas fa-chevron-down wpf-ico"></i><?php wpforo_phrase( 'Filter by custom fields' ) ?>
1463 </span>
1464 </div>
1465 </div>
1466 <div class="wpforo-tr wpf-cfields">
1467 <div class="wpforo-td wpfw-100 wpfltd wpf-last">
1468 <div class="wpf-search-custom-fields">
1469 <?php wpforo_fields( $search_fields ) ?>
1470 </div>
1471 </div>
1472 </div>
1473 </div>
1474 <?php endif ?>
1475 <div class="wpforo-table">
1476 <div class="wpforo-tr">
1477 <div class="wpforo-td wpfw-100 wpfrtd wpf-last">
1478 <input type="submit" class="wpf-search" value="<?php wpforo_phrase( 'Search' ) ?>">
1479 </div>
1480 </div>
1481 </div>
1482 </form>
1483 <?php
1484 }
1485
1486 public function member_search_form() {
1487 do_action('wpforo_member_search_form_start');
1488 ?>
1489 <form action="<?php echo wpforo_members_url() ?>" method="get">
1490 <?php do_action('wpforo_member_search_form_before_fields'); ?>
1491 <?php wpforo_make_hidden_fields_from_url( wpforo_home_url() ) ?>
1492 <?php wpforo_fields( wpforo_search_fields() ); ?>
1493 <?php do_action('wpforo_member_search_form_after_fields'); ?>
1494 <div class="wpf-tr">
1495 <div class="wpf-td wpfw-1">
1496 <div class="wpf-field wpf-field-type-submit">
1497 <a href="<?php echo wpforo_members_url() ?>">
1498 <input type="button" class="wpf-button-secondary" value="<?php wpforo_phrase( 'Reset Search' ) ?>">
1499 </a>
1500 <?php if( wpforo_setting( 'members', 'search_type' ) === 'filter' ): ?>
1501 <a href="<?php echo wpforo_members_url() ?>">
1502 <input type="reset" class="wpf-button-secondary" value="<?php wpforo_phrase( 'Reset Fields' ) ?>">
1503 </a>
1504 <?php endif; ?>
1505 <input type="submit" class="wpf-member-search" name="_wpfms" value="<?php wpforo_phrase( 'Search' ) ?>"/>
1506 </div>
1507 <div class="wpf-field-cl"></div>
1508 </div>
1509 <div class="wpf-cl"></div>
1510 </div>
1511 </form>
1512 <?php
1513 do_action('wpforo_member_search_form_end');
1514 }
1515
1516 function pagenavi( $paged = null, $items_count = null, $items_per_page = null, $permalink = true, $class = '' ) {
1517 if( is_null( $paged ) ) $paged = WPF()->current_object['paged'];
1518 if( is_null( $items_count ) ) $items_count = WPF()->current_object['items_count'];
1519 if( is_null( $items_per_page ) ) $items_per_page = WPF()->current_object['items_per_page'];
1520
1521 if( $items_count <= $items_per_page ) return;
1522
1523 $pages_count = ceil( $items_count / $items_per_page );
1524
1525 $current_url = ( WPF()->current_url ? WPF()->current_url : wpforo_get_request_uri() );
1526 $sanitized_current_url = trim( WPF()->strip_url_paged_var( $current_url ), '/' );
1527
1528 if( $permalink ) {
1529 $rtrimed_url = '';
1530 $url_append_vars = '';
1531 if( preg_match( '#^(.+?)(/?[?&].*)?$#isu', $sanitized_current_url, $match ) ) {
1532 if( wpfval( $match, 1 ) ) $rtrimed_url = rtrim( $match[1], '/\\' );
1533 if( wpfval( $match, 2 ) ) $url_append_vars = '?' . trim( $match[2], '?&/\\' );
1534 }
1535 $url = str_replace( '%', '%%', $rtrimed_url . '/' . wpforo_settings_get_slug( 'paged' ) ) . '/%1$d/' . str_replace( '%', '%%', $url_append_vars );
1536 } else {
1537 $url = str_replace( '%', '%%', $sanitized_current_url ) . '&wpfpaged=%1$d';
1538 }
1539 ?>
1540
1541 <div class="wpf-navi <?php echo esc_attr( $class ) ?>">
1542 <div class="wpf-navi-wrap">
1543 <span class="wpf-page-info">
1544 <?php wpforo_phrase( 'Page' ) ?> <?php echo intval( $paged ) ?> / <?php echo intval( $pages_count ) ?>
1545 </span>
1546 <?php if( $paged - 1 > 0 ): $prev_url = ( ( $paged - 1 ) == 1 ? $sanitized_current_url : sprintf( $url, $paged - 1 ) ); ?>
1547 <a href="<?php echo esc_url( WPF()->user_trailingslashit( $prev_url ) ) ?>" class="wpf-prev-button" rel="prev">
1548 <i class="fas fa-chevron-left fa-sx"></i> <?php wpforo_phrase( 'prev' ) ?>
1549 </a>
1550 <?php endif ?>
1551 <select class="wpf-navi-dropdown" onchange="if (this.value) window.location.assign(this.value)" title="<?php esc_attr( wpforo_phrase( 'Select Page' ) ) ?>">
1552 <option value="<?php echo esc_url( WPF()->user_trailingslashit( $sanitized_current_url ) ) ?>" <?php wpfo_check( $paged, 1, 'selected' ) ?>>1</option>
1553 <?php for( $i = 2; $i <= $pages_count; $i ++ ) : ?>
1554 <option value="<?php echo esc_url( WPF()->user_trailingslashit( sprintf( $url, $i ) ) ) ?>" <?php wpfo_check( $paged, $i, 'selected' ) ?>>
1555 <?php echo $i ?>
1556 </option>
1557 <?php endfor; ?>
1558 </select>
1559 <?php if( $paged + 1 <= $pages_count ): ?>
1560 <a href="<?php echo esc_url( WPF()->user_trailingslashit( sprintf( $url, $paged + 1 ) ) ) ?>" class="wpf-next-button" rel="next">
1561 <?php wpforo_phrase( 'next' ) ?> <i class="fas fa-chevron-right fa-sx"></i>
1562 </a>
1563 <?php endif ?>
1564 </div>
1565 </div>
1566
1567 <?php
1568 }
1569
1570 /**
1571 * Get actions buttons
1572 *
1573 * @param array $buttons names function will return buttons by this array
1574 *
1575 * @param array $forum required
1576 *
1577 * @param array $topic required
1578 *
1579 * @param array $post required
1580 *
1581 * @param bool $echo
1582 *
1583 * $buttons = array( 'reply', 'answer', 'comment', 'quote', 'like', 'report', 'sticky', 'close', 'edit', 'delete', 'link' );
1584 *
1585 * @return string
1586 * @since 1.0.0
1587 *
1588 */
1589 function buttons( $buttons, $forum = [], $topic = [], $post = [], $echo = true ) {
1590 $buttons = (array) $buttons;
1591 $is_topic = (bool) wpfval( $post, 'is_first_post' );
1592
1593 $button_html = [];
1594 $login = is_user_logged_in();
1595
1596 $forumid = ( isset( $forum['forumid'] ) ) ? $forum['forumid'] : 0;
1597 $topicid = ( isset( $topic['topicid'] ) ) ? $topic['topicid'] : 0;
1598 $postid = ( isset( $post['postid'] ) ) ? $post['postid'] : 0;
1599
1600 if( $post ) {
1601 $userid = wpforo_bigintval( wpfval( $post, 'userid' ) );
1602 $is_owner = (int) ( WPF()->current_userid && wpforo_is_owner( $userid ) );
1603 $mention = (string) ( ! $is_owner && wpforo_setting( 'profiles', 'mention_nicknames' ) ? wpforo_member( $post, 'user_nicename' ) : '' );
1604 } else {
1605 $userid = 0;
1606 $is_owner = 0;
1607 $mention = '';
1608 }
1609
1610 $is_sticky = ( isset( $topic['type'] ) ) ? $topic['type'] : 0;
1611 $is_closed = ( isset( $topic['closed'] ) ) ? $topic['closed'] : 0;
1612 $is_private = ( isset( $topic['private'] ) ) ? $topic['private'] : 0;
1613 $is_solved = ( isset( $topic['solved'] ) ) ? $topic['solved'] : 0;
1614 $is_approve = ( isset( $post['status'] ) ) ? $post['status'] : 0;
1615
1616 foreach( $buttons as $button ) {
1617 switch( $button ) {
1618 case 'reply':
1619 if( $is_closed || $is_approve || ( $is_topic && ! wpforo_setting( 'topics', 'layout_threaded_first_post_reply' ) ) ) break;
1620 if( WPF()->perm->forum_can( 'cr', $forumid ) || ( wpforo_is_owner( wpforo_bigintval( wpfval( $topic, 'userid' ) ), (string) wpfval( $topic, 'email' ) ) && WPF()->perm->forum_can( 'ocr', $forumid ) ) ) {
1621 $layout = WPF()->forum->get_layout( $forumid );
1622 $layout_class = 'wpforo_layout_' . $layout;
1623 $button_html[] = '<span id="parentpostid' . wpforo_bigintval( $postid ) . '" class="wpforo-reply wpf-action ' . $layout_class . '" data-mention="' . esc_attr( $mention ) . '"><i class="fas fa-reply fa-rotate-180"></i><span class="wpf-button-text">' . wpforo_phrase( 'Reply', false ) . '</span></span>';
1624 } else {
1625 $button_html[] = ( $login ) ? '' : '<span class="wpf-action not_reg_user"><i class="fas fa-reply fa-rotate-180"></i><span class="wpf-button-text">' . wpforo_phrase( 'Reply', false ) . '</span></span>';
1626 }
1627 break;
1628 case 'answer':
1629 if( $is_closed || $is_approve ) break;
1630 if( WPF()->perm->forum_can( 'cr', $forumid ) || ( wpforo_is_owner( wpforo_bigintval( wpfval( $topic, 'userid' ) ), (string) wpfval( $topic, 'email' ) ) && WPF()->perm->forum_can( 'ocr', $forumid ) ) ) {
1631 if( WPF()->topic->can_answer( $topicid ) ) {
1632 $button_html[] = '<span class="wpforo-answer wpf-button" data-phrase="' . esc_attr( wpforo_phrase( 'Answer', false ) ) . '" data-mention="' . esc_attr( $mention ) . '"><i class="fas fa-pencil-alt"></i><span class="wpf-button-text">' . wpforo_phrase( 'Answer', false ) . '</span></span>';
1633 }
1634 } else {
1635 $button_html[] = ( $login ) ? '' : '<span class="wpf-button not_reg_user" data-phrase="' . esc_attr( wpforo_phrase( 'Answer', false ) ) . '"><i class="fas fa-pencil-alt"></i><span class="wpf-button-text">' . wpforo_phrase( 'Answer', false ) . '</span></span>';
1636 }
1637 break;
1638 case 'comment':
1639 if( $is_closed || $is_approve || ( $is_topic && ! wpforo_setting( 'topics', 'layout_qa_first_post_reply' ) ) ) break;
1640 $title = wpforo_phrase( 'Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.', false );
1641 if( WPF()->perm->forum_can( 'cr', $forumid ) || ( wpforo_is_owner( wpforo_bigintval( wpfval( $topic, 'userid' ) ), (string) wpfval( $topic, 'email' ) ) && WPF()->perm->forum_can( 'ocr', $forumid ) ) ) {
1642 $button_html[] = '<span id="parentpostid' . wpforo_bigintval( $postid ) . '" class="wpforo-qa-comment wpf-button" title="' . esc_attr( $title ) . '" data-phrase="' . esc_attr( wpforo_phrase( 'Add a comment', false ) ) . '" data-mention="' . esc_attr( $mention ) . '"><i class="far fa-comment"></i><span class="wpf-button-text">' . wpforo_phrase( 'Add a comment', false ) . '</span></span>';
1643 } else {
1644 $button_html[] = ( $login ) ? '' : '<span class="not_reg_user wpf-button" title="' . esc_attr( $title ) . '" data-phrase="' . esc_attr( wpforo_phrase( 'Add a comment', false ) ) . '"><i class="far fa-comment"></i><span class="wpf-button-text">' . wpforo_phrase( 'Add a comment', false ) . '</span></span>';
1645 }
1646 break;
1647 case 'comment_raw':
1648 if( $is_closed || $is_approve || ( $is_topic && ! wpforo_setting( 'topics', 'layout_qa_first_post_reply' ) ) ) break;
1649 $title = wpforo_phrase( 'Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.', false );
1650 if( WPF()->perm->forum_can( 'cr', $forumid ) || ( wpforo_is_owner( wpforo_bigintval( wpfval( $topic, 'userid' ) ), (string) wpfval( $topic, 'email' ) ) && WPF()->perm->forum_can( 'ocr', $forumid ) ) ) {
1651 $button_html[] = '<a class="wpforo-qa-comment" title="' . esc_attr( $title ) . '" data-phrase="' . esc_attr( wpforo_phrase( 'Add a comment', false, 'lower' ) ) . '" data-mention="' . esc_attr( $mention ) . '"><i class="far fa-comment"></i><span class="wpf-button-text">' . wpforo_phrase( 'Add a comment', false, 'lower' ) . '</span></a>';
1652 } else {
1653 $button_html[] = ( $login ) ? '' : '<a class="not_reg_user" title="' . esc_attr( $title ) . '" data-phrase="' . esc_attr( wpforo_phrase( 'Add a comment', false, 'lower' ) ) . '"><i class="far fa-comment"></i><span class="wpf-button-text">' . wpforo_phrase( 'Add a comment', false, 'lower' ) . '</span></a>';
1654 }
1655 break;
1656 case 'quote':
1657 if( $is_closed || $is_approve ) break;
1658 if( WPF()->perm->forum_can( 'cr', $forumid ) || ( wpforo_is_owner( wpforo_bigintval( wpfval( $topic, 'userid' ) ), (string) wpfval( $topic, 'email' ) ) && WPF()->perm->forum_can( 'ocr', $forumid ) ) ) {
1659 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Quote', false ) ) . '" class="wpf-action wpforo-quote" data-postid="' . wpforo_bigintval( $postid ) . '" data-mention="' . esc_attr( $mention ) . '" data-userid="' . esc_attr( $userid ) . '" data-isowner="' . esc_attr( $is_owner ) . '"><i class="fas fa-quote-left wpfsx"></i><span class="wpf-button-text">' . wpforo_phrase( 'Quote', false ) . '</span></span>';
1660 } else {
1661 $button_html[] = ( $login ) ? '' : '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Quote', false ) ) . '" class="wpf-action not_reg_user"><i class="fas fa-quote-left wpfsx"></i><span class="wpf-button-text">' . wpforo_phrase( 'Quote', false ) . '</span></span>';
1662 }
1663 break;
1664 case 'report':
1665 if( WPF()->perm->forum_can( 'r', $forumid ) && $login ) {
1666 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Report', false ) ) . '" class="wpf-action wpforo-report" data-postid="' . wpforo_bigintval( $postid ) . '"><i class="fas fa-exclamation-triangle"></i><span class="wpf-button-text">' . wpforo_phrase( 'Report', false ) . '</span></span>';
1667 }
1668 break;
1669 case 'sticky':
1670 $sticky_status = ( $is_sticky ? 'wpforo-unsticky' : 'wpforo-sticky' );
1671 if( WPF()->perm->forum_can( 's', $forumid ) ) {
1672 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( str_replace( 'wpforo-', '', $sticky_status ), false ) ) . '" class="wpf-action ' . $sticky_status . '" data-topicid="' . wpforo_bigintval( $topicid ) . '"><i class="fas fa-thumbtack wpfsx"></i><span class="wpforo-sticky-txt">' . wpforo_phrase( str_replace( 'wpforo-', '', $sticky_status ), false ) . '</span></span>';
1673 }
1674 break;
1675 case 'private':
1676 if( $login ) {
1677 if( WPF()->perm->forum_can( 'p', $forumid ) || ( WPF()->current_userid == $post['userid'] && WPF()->perm->forum_can( 'op', $forumid ) ) ) {
1678 $private_status = ( $is_private ? 'wpforo-public' : 'wpforo-private' );
1679 $private_icon = ( $private_status == 'wpforo-public' ) ? 'eye' : 'eye-slash';
1680 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( str_replace( 'wpforo-', '', $private_status ), false ) ) . '" id="wpfprivate' . intval( $topicid ) . '" class="wpf-action ' . $private_status . '"><i id="privateicon' . intval( $topicid ) . '" class="fas fa-' . esc_attr( $private_icon ) . ' wpfsx"></i><span id="privatetext' . intval( $topicid ) . '">' . wpforo_phrase( str_replace( 'wpforo-', '', $private_status ), false ) . '</span></span>';
1681 }
1682 }
1683 break;
1684 case 'solved':
1685 $solved_status = ( $is_solved ? 'wpforo-unsolved' : 'wpforo-solved' );
1686 if( WPF()->perm->forum_can( 'sv', $forumid ) || ( WPF()->current_userid == $post['userid'] && WPF()->perm->forum_can( 'osv', $forumid ) ) ) {
1687 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( str_replace( 'wpforo-', '', $solved_status ), false ) ) . '" id="wpfsolved' . wpforo_bigintval( $postid ) . '" class="wpf-action ' . $solved_status . '"><i class="fas fa-check-circle wpfsx"></i><span id="solvedtext' . wpforo_bigintval( $postid ) . '">' . wpforo_phrase( str_replace( 'wpforo-', '', $solved_status ), false ) . '</span></span>';
1688 }
1689 break;
1690 case 'approved':
1691 if( WPF()->perm->forum_can( 'au', $forumid ) && $login ) {
1692 $approve_status = ( ! $is_approve ? 'wpforo-unapprove' : 'wpforo-approve' );
1693 $approve_icon = ( $approve_status == 'wpforo-unapprove' ) ? 'fa-exclamation-circle' : 'fa-check';
1694 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( str_replace( 'wpforo-', '', $approve_status ), false ) ) . '" id="wpfapprove' . wpforo_bigintval( $postid ) . '" class="wpf-action ' . $approve_status . '"><i id="approveicon' . wpforo_bigintval( $postid ) . '" class="fas ' . esc_attr( $approve_icon ) . ' wpfsx"></i><span id="approvetext' . wpforo_bigintval( $postid ) . '">' . wpforo_phrase(
1695 str_replace( 'wpforo-', '', $approve_status ),
1696 false
1697 ) . '</span></span>';
1698 }
1699 break;
1700 case 'close':
1701 if( WPF()->perm->forum_can( 'cot', $forumid ) && $login ) {
1702 $open_status = ( $is_closed ? 'wpforo-open' : 'wpforo-close' );
1703 $open_icon = ( $open_status == 'wpforo-open' ) ? 'unlock' : 'lock';
1704 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( str_replace( 'wpforo-', '', $open_status ), false ) ) . '" id="wpfclose' . intval( $topicid ) . '" class="wpf-action ' . $open_status . '"><i id="closeicon' . intval( $topicid ) . '" class="fas fa-' . esc_attr( $open_icon ) . ' wpfsx"></i><span id="closetext' . intval( $topicid ) . '">' . wpforo_phrase( str_replace( 'wpforo-', '', $open_status ), false ) . '</span></span>';
1705 }
1706 break;
1707 case 'tools':
1708 if( WPF()->perm->forum_can( 'mt', $forumid ) && $login ) {
1709 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Tools: Move, Split, Merge', false ) ) . '" wpf-tooltip-size="medium" class="wpf-action wpf-button-outlined wpforo-tools"><i class="fas fa-cog"></i><span class="wpf-button-text">' . wpforo_phrase( 'Tools', false ) . '</span></span>';
1710 }
1711 break;
1712 case 'edit':
1713 if( $is_closed ) break;
1714 $diff = time() - strtotime( $post['created'] . ' GMT' );
1715 $_durr = $is_topic ? wpforo_setting( 'posting', 'edit_own_topic_durr' ) : wpforo_setting( 'posting', 'edit_own_post_durr' );
1716 if( ! $login && isset( $post['email'] ) && wpforo_is_owner( $post['userid'], $post['email'] ) && WPF()->perm->forum_can( ( $is_topic ? 'eot' : 'eor' ), $forumid ) && $diff < $_durr ) {
1717 $a = ( $is_topic ) ? 'wpfedittopicpid' : '';
1718 $b = $postid;
1719 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Edit', false ) ) . '" id="' . esc_attr( $a . $b ) . '" class="wpforo-edit wpf-action"><i class="fas fa-edit wpfsx"></i><span class="wpf-button-text">' . wpforo_phrase( 'Edit', false ) . '</span></span>';
1720 } elseif( $login ) {
1721 if( WPF()->perm->forum_can( ( $is_topic ? 'et' : 'er' ), $forumid ) || ( WPF()->current_userid == $post['userid'] && WPF()->perm->forum_can( ( $is_topic ? 'eot' : 'eor' ), $forumid ) && ( $_durr === 0 || $diff < $_durr ) ) ) {
1722 $a = ( $is_topic ) ? 'wpfedittopicpid' : '';
1723 $b = $postid;
1724 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Edit', false ) ) . '" id="' . esc_attr( $a . $b ) . '" class="wpforo-edit wpf-action"><i class="fas fa-edit wpfsx"></i><span class="wpf-button-text">' . wpforo_phrase( 'Edit', false ) . '</span></span>';
1725 }
1726 }
1727 break;
1728 case 'delete':
1729 if( $login ) {
1730 /*if( WPF()->member->current_user_is_new() && $post['status'] ){
1731 New registered user's unapproved topic/post | No Delete button.
1732 }else{*/
1733 $diff = time() - strtotime( $post['created'] . ' GMT' );
1734 $_durr = $is_topic ? wpforo_setting( 'posting', 'delete_own_topic_durr' ) : wpforo_setting( 'posting', 'delete_own_post_durr' );
1735 if( WPF()->perm->forum_can( ( $is_topic ? 'dt' : 'dr' ), $forumid ) || ( WPF()->current_userid == $post['userid'] && WPF()->perm->forum_can( ( $is_topic ? 'dot' : 'dor' ), $forumid ) && ( $_durr === 0 || $diff < $_durr ) ) ) {
1736 $a = ( $is_topic ) ? 'wpftopicdelete' : 'wpfreplydelete';
1737 $b = ( $is_topic ) ? $topicid : $postid;
1738 $button_html[] = '<span wpf-tooltip="' . esc_attr( wpforo_phrase( 'Delete', false ) ) . '" id="' . esc_attr( $a . $b ) . '" class="wpf-action wpforo-delete"><i class="fas fa-trash-alt wpfsx"></i><span class="wpf-button-text">' . wpforo_phrase( 'Delete', false ) . '</span></span>';
1739 }
1740 //}
1741 }
1742 break;
1743 case 'link':
1744 $full_url = esc_url( (string) wpforo_post( $postid, 'full_url' ) );
1745 $short_url = esc_url( (string) wpforo_post( $postid, 'short_url' ) );
1746 $title = esc_attr( wpforo_phrase( 'Post link', false ) );
1747 $button_html[] = sprintf(
1748 '<span class="wpf-action" data-copy-wpf-furl="%2$s" data-copy-wpf-shurl="%3$s" wpf-tooltip="' . esc_attr( wpforo_phrase( 'Post link', false ) ) . '" wpf-tooltip-position="left"><i class="fas fa-link wpfsx"></i></span>',
1749 $title,
1750 $full_url,
1751 $short_url
1752 );
1753 break;
1754 case 'positivevote':
1755 if( WPF()->perm->forum_can( 'v', $forumid ) && $login ) {
1756 $button_html[] = '<i class="wpforo-voteup fas fa-play fa-rotate-270 wpfcl-0 ' . ( WPF()->reaction->get_user_reaction_reaction( $postid ) === 1 ? 'wpf-vote-active' : '' ) . '" data-type="' . ( $is_topic ? 'topic' : 'reply' ) . '" data-postid="' . wpforo_bigintval( $postid ) . '"></i>';
1757 } else {
1758 $button_html[] = '<i class="not_reg_user fas fa-play fa-rotate-270 wpfcl-0"></i>';
1759 }
1760 break;
1761 case 'negativevote':
1762 if( WPF()->perm->forum_can( 'v', $forumid ) && $login ) {
1763 $button_html[] = '<i class="wpforo-votedown fas fa-play fa-rotate-90 wpfcl-0 ' . ( WPF()->reaction->get_user_reaction_reaction( $postid ) === - 1 ? 'wpf-vote-active' : '' ) . '" data-type="' . ( $is_topic ? 'topic' : 'reply' ) . '" data-postid="' . wpforo_bigintval( $postid ) . '"></i>';
1764 } else {
1765 $button_html[] = '<i class="not_reg_user fas fa-play fa-rotate-90 wpfcl-0"></i>';
1766 }
1767 break;
1768 case 'isanswer':
1769 if( ! $is_topic ) {
1770 $has_is_answer_post = WPF()->topic->has_is_answer_post( $post['topicid'] );
1771 $is_answer = (bool) WPF()->post->is_answered( $postid );
1772 $class = ( $is_answer ) ? '' : '-not';
1773 if( ! $has_is_answer_post || $is_answer ) {
1774 if( $login ) {
1775 $button_html[] = '<div class="wpf-toggle' . esc_attr( $class ) . '-answer" data-postid="' . wpforo_bigintval( $postid ) . '"><i class="fas fa-check"></i></div>';
1776 } else {
1777 $button_html[] = '<div class="wpf-toggle' . esc_attr( $class ) . '-answer not_reg_user"><i class="fas fa-check"></i></div>';
1778 }
1779 }
1780 }
1781 break;
1782 default:
1783 $bh = apply_filters( 'wpforo_template_buttons', '', $button, $forum, $topic, $post );
1784 if( $bh ) $button_html[] = $bh;
1785 break;
1786 } //switch
1787 } //foreach
1788
1789 $before = '<span class="wpforo-action-buttons-wrap">';
1790 $after = '</span>';
1791 $html = $before . implode( '', $button_html ) . $after;
1792
1793 if( $echo ) echo $html;
1794 return $html;
1795 }
1796
1797 /**
1798 * display QA Layout Votes count for loop current post
1799 *
1800 * @param array $post loop current post array
1801 *
1802 * @return void
1803 */
1804 public function vote_count( $post ) {
1805 $votes = ( ! empty( $post['votes'] ) ? $post['votes'] : 0 );
1806 printf( '<span class="wpfvote-num wpfcl-0">%d</span>', $votes );
1807 }
1808
1809 function breadcrumb( $current_object = null ) {
1810 if( ! $current_object ) $current_object = WPF()->current_object;
1811
1812 $lenght = apply_filters( 'wpforo_breadcrumb_text_length', 19 ); ?>
1813
1814 <style>.wpf-item-element {
1815 display: inline;
1816 }</style>
1817 <div class="wpf-breadcrumb" itemscope="" itemtype="https://schema.org/BreadcrumbList">
1818 <?php switch( $current_object['template'] ) :
1819 case 'search': ?>
1820 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1821 <meta itemprop="position" content="1">
1822 </div>
1823 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Search' ) ?></span></div>
1824 <span class="wpf-end">&nbsp;</span>
1825 <?php break;
1826 case 'signup': ?>
1827 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1828 <meta itemprop="position" content="1">
1829 </div>
1830 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Register' ) ?></span></div>
1831 <span class="wpf-end">&nbsp;</span>
1832 <?php break;
1833 case 'signin': ?>
1834 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1835 <meta itemprop="position" content="1">
1836 </div>
1837 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Login' ) ?></span></div>
1838 <span class="wpf-end">&nbsp;</span>
1839 <?php break;
1840 case 'members': ?>
1841 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1842 <meta itemprop="position" content="1">
1843 </div>
1844 <?php if( isset( $_GET['wpfms'] ) ) : ?>
1845 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><?php wpforo_phrase( 'Members' ) ?></a>
1846 <meta itemprop="position" content="2">
1847 </div>
1848 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Search' ) ?></span></div>
1849 <?php else : ?>
1850 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Members' ) ?></span></div>
1851 <?php endif ?>
1852 <span class="wpf-end">&nbsp;</span>
1853 <?php break;
1854 case 'recent': ?>
1855 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1856 <meta itemprop="position" content="1">
1857 </div>
1858 <?php if( wpfval( $_GET, 'view' ) === 'unread' ): ?>
1859 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Unread Posts' ) ?></span></div>
1860 <?php elseif( wpfval( $_GET, 'view' ) === 'prefix' ): ?>
1861 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Topic Prefix' ) ?></span></div>
1862 <?php else: ?>
1863 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Recent Posts' ) ?></span></div>
1864 <?php endif; ?>
1865 <span class="wpf-end">&nbsp;</span>
1866 <?php break;
1867 case 'tags': ?>
1868 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1869 <meta itemprop="position" content="1">
1870 </div>
1871 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Tags' ) ?></span></div>
1872 <span class="wpf-end">&nbsp;</span>
1873 <?php break;
1874 case 'profile': ?>
1875 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1876 <meta itemprop="position" content="1">
1877 </div>
1878 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><span itemprop="name"><?php wpforo_phrase( 'Members' ) ?></span></a>
1879 <meta itemprop="position" content="2">
1880 </div>
1881 <?php if( $current_object['user'] ) : ?>
1882 <div class="wpf-item-element active"><span><?php @wpforo_text( wpforo_user_dname( $current_object['user'] ), $lenght ) ?></span></div>
1883 <?php endif ?>
1884 <span class="wpf-end">&nbsp;</span>
1885 <?php break;
1886 case 'account': ?>
1887 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1888 <meta itemprop="position" content="1">
1889 </div>
1890 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><span itemprop="name"><?php wpforo_phrase( 'Members' ) ?></span></a>
1891 <meta itemprop="position" content="2">
1892 </div>
1893 <?php if( $current_object['user'] ) : ?>
1894 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo esc_url( (string) $current_object['user']['profile_url'] ) ?>"><span itemprop="name"><?php wpforo_text( wpforo_user_dname( $current_object['user'] ), $lenght ) ?></span></a>
1895 <meta itemprop="position" content="3">
1896 </div>
1897 <?php endif ?>
1898 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Account' ) ?></span></div>
1899 <span class="wpf-end">&nbsp;</span>
1900 <?php break;
1901 case 'activity': ?>
1902 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1903 <meta itemprop="position" content="1">
1904 </div>
1905 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><span itemprop="name"><?php wpforo_phrase( 'Members' ) ?></span></a>
1906 <meta itemprop="position" content="2">
1907 </div>
1908 <?php if( $current_object['user'] ) : ?>
1909 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo esc_url( (string) $current_object['user']['profile_url'] ) ?>"><span itemprop="name"><?php wpforo_text( wpforo_user_dname( $current_object['user'] ), $lenght ) ?></span></a>
1910 <meta itemprop="position" content="3">
1911 </div>
1912 <?php endif ?>
1913 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Activity' ) ?></span></div>
1914 <span class="wpf-end">&nbsp;</span>
1915 <?php break;
1916 case 'subscriptions': ?>
1917 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1918 <meta itemprop="position" content="1">
1919 </div>
1920 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><span itemprop="name"><?php wpforo_phrase( 'Members' ) ?></span></a>
1921 <meta itemprop="position" content="2">
1922 </div>
1923 <?php if( $current_object['user'] ) : ?>
1924 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo esc_url( (string) $current_object['user']['profile_url'] ) ?>"><span itemprop="name"><?php wpforo_text( wpforo_user_dname( $current_object['user'] ), $lenght ) ?></span></a>
1925 <meta itemprop="position" content="3">
1926 </div>
1927 <?php endif ?>
1928 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Subscriptions' ) ?></span></div>
1929 <span class="wpf-end">&nbsp;</span>
1930 <?php break;
1931 case 'messages': ?>
1932 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1933 <meta itemprop="position" content="1">
1934 </div>
1935 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><span itemprop="name"><?php wpforo_phrase( 'Members' ) ?></span></a>
1936 <meta itemprop="position" content="2">
1937 </div>
1938 <?php if( $current_object['user'] ) : ?>
1939 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo esc_url( (string) $current_object['user']['profile_url'] ) ?>"><span itemprop="name"><?php wpforo_text( wpforo_user_dname( $current_object['user'] ), $lenght ) ?></span></a>
1940 <meta itemprop="position" content="3">
1941 </div>
1942 <?php endif ?>
1943 <div class="wpf-item-element active"><span><?php wpforo_phrase( 'Messages' ) ?></span></div>
1944 <span class="wpf-end">&nbsp;</span>
1945 <?php break;
1946 case 'topic':
1947 case 'forum': ?>
1948 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root<?php echo( ! $current_object['forumid'] ? ' active' : '' ) ?>"><a itemprop="item" href="<?php echo( ! $current_object['forumid'] ? '#' : wpforo_home_url() ) ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1949 <meta itemprop="position" content="1">
1950 </div>
1951 <?php if( $current_object['forumid'] ) : ?>
1952 <?php $relative_ids = [];
1953 WPF()->forum->get_parents( $current_object['forumid'], $relative_ids );
1954 foreach( $relative_ids as $key => $rel_forumid ) : ?>
1955 <?php $forum = wpforo_forum( $rel_forumid ) ?>
1956 <?php if( ! empty( $forum ) ): ?>
1957 <?php if( $key != ( count( $relative_ids ) - 1 ) ) : ?>
1958 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo esc_url( (string) $forum['url'] ) ?>" title="<?php echo esc_attr( $forum['title'] ) ?>"><span itemprop="name"><?php wpforo_text( $forum['title'], $lenght ) ?></span></a>
1959 <meta itemprop="position" content="<?php echo $key + 2; ?>">
1960 </div>
1961 <?php else : ?>
1962 <div class="wpf-item-element active"><span><?php wpforo_text( $forum['title'], $lenght ) ?></span></div>
1963 <?php endif ?>
1964 <?php endif ?>
1965 <?php endforeach ?>
1966 <?php endif ?>
1967 <span class="wpf-end">&nbsp;</span>
1968 <?php break;
1969 case 'post': ?>
1970 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root<?php echo( ! $current_object['forumid'] ? ' active' : '' ) ?>"><a itemprop="item" href="<?php echo( ! $current_object['forumid'] ? '#' : wpforo_home_url() ) ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1971 <meta itemprop="position" content="1">
1972 </div>
1973 <?php if( $current_object['forumid'] ) : ?>
1974 <?php $relative_ids = [];
1975 WPF()->forum->get_parents( $current_object['forumid'], $relative_ids );
1976 foreach( $relative_ids as $key => $rel_forumid ) : ?>
1977 <?php $forum = wpforo_forum( $rel_forumid ) ?>
1978 <?php if( ! empty( $forum ) ): ?>
1979 <div class="wpf-item-element" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem"><a itemprop="item" href="<?php echo esc_url( (string) $forum['url'] ) ?>" title="<?php echo esc_attr( $forum['title'] ) ?>"><span itemprop="name"><?php wpforo_text( $forum['title'], $lenght ) ?></span></a>
1980 <meta itemprop="position" content="<?php echo $key + 2; ?>">
1981 </div>
1982 <?php endif ?>
1983 <?php endforeach ?>
1984 <?php endif ?>
1985 <?php if( $current_object['topic'] ) : ?>
1986 <div class="wpf-item-element active"><span><?php wpforo_text( $current_object['topic']['title'], $lenght ) ?></span></div>
1987 <?php endif ?>
1988 <span class="wpf-end">&nbsp;</span>
1989 <?php break;
1990 default: ?>
1991 <?php if( wpforo_is_member_template( $current_object['template'] ) && ( $template = $this->get_template( $current_object['template'] ) ) ) : ?>
1992 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
1993 <meta itemprop="position" content="1">
1994 </div>
1995 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo wpforo_members_url() ?>"><span itemprop="name"><?php wpforo_phrase( 'Members' ) ?></span></a>
1996 <meta itemprop="position" content="2">
1997 </div>
1998 <?php if( $current_object['user'] ) : ?>
1999 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element"><a itemprop="item" href="<?php echo esc_url( (string) $current_object['user']['profile_url'] ) ?>"><span itemprop="name"><?php wpforo_text( wpforo_user_dname( $current_object['user'] ), $lenght ) ?></span></a>
2000 <meta itemprop="position" content="3">
2001 </div>
2002 <?php endif ?>
2003 <div class="wpf-item-element active"><span><?php wpforo_phrase( $template['title'] ) ?></span></div>
2004 <span class="wpf-end">&nbsp;</span>
2005 <?php else : ?>
2006 <?php if( $current_object['forumid'] ): ?>
2007 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><i class="fas fa-home"></i><span itemprop="name" style="display:none;"><?php wpforo_phrase( 'Forums' ) ?></span></a>
2008 <meta itemprop="position" content="1">
2009 </div>
2010 <span class="wpf-end">&nbsp;</span>
2011 <?php else: ?>
2012 <div itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem" class="wpf-item-element wpf-root active"><a itemprop="item" href="<?php echo wpforo_home_url() ?>" title="<?php esc_attr( wpforo_phrase( 'Forums' ) ) ?>"><span itemprop="name"><?php wpforo_phrase( 'Forums' ) ?></span></a>
2013 <meta itemprop="position" content="1">
2014 </div>
2015 <span class="wpf-end">&nbsp;</span>
2016 <?php endif ?>
2017 <?php endif ?>
2018 <?php endswitch; ?>
2019 </div>
2020 <?php
2021 }
2022
2023 function icon( $type, $item = [], $echo = true, $data = 'icon' ) {
2024
2025 $icon = [];
2026 $status = false;
2027
2028 if( isset( $item['status'] ) && $item['status'] ) {
2029 $icon['class'] = 'fas fa-exclamation-circle';
2030 $icon['color'] = 'wpfcl-5';
2031 $icon['title'] = wpforo_phrase( 'Unapproved', false );
2032 if( $echo ) {
2033 $status = true;
2034 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2035 } else {
2036 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2037 }
2038 }
2039
2040 if( isset( $item['type'] ) ) {
2041
2042 if( $type == 'topic' ) {
2043 if( WPF()->topic->is_private( $item['topicid'] ) ) {
2044 $icon['class'] = 'fas fa-eye-slash';
2045 $icon['color'] = 'wpfcl-1';
2046 $icon['title'] = wpforo_phrase( 'Private', false );
2047 if( $echo ) {
2048 $status = true;
2049 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2050 } else {
2051 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2052 }
2053 }
2054 if( wpforo_topic( $item['topicid'], 'solved' ) ) {
2055 $icon['class'] = 'fas fa-check-circle';
2056 $icon['color'] = 'wpfcl-8';
2057 $icon['title'] = wpforo_phrase( 'Solved', false );
2058 if( $echo ) {
2059 $status = true;
2060 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2061 } else {
2062 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2063 }
2064 }
2065 }
2066
2067 if( $item['closed'] && $item['type'] == 1 ) {
2068 $icon['class'] = 'fas fa-lock';
2069 $icon['color'] = 'wpfcl-1';
2070 $icon['title'] = wpforo_phrase( 'Closed', false );
2071 if( $echo ) {
2072 $status = true;
2073 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2074 } else {
2075 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2076 }
2077 } elseif( $item['closed'] && $item['type'] != 1 ) {
2078 $icon['class'] = 'fas fa-lock';
2079 $icon['color'] = 'wpfcl-1';
2080 $icon['title'] = wpforo_phrase( 'Closed', false );
2081 if( $echo ) {
2082 $status = true;
2083 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2084 } else {
2085 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2086 }
2087 } elseif( ! $item['closed'] && $item['type'] == 1 ) {
2088 $icon['class'] = 'fas fa-thumbtack';
2089 $icon['color'] = 'wpfcl-10';
2090 $icon['title'] = wpforo_phrase( 'Sticky', false );
2091 if( $echo ) {
2092 $status = true;
2093 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2094 } else {
2095 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2096 }
2097 }
2098
2099 if( ! $status ) {
2100 if( $type == 'forum' ) {
2101 $icon['class'] = 'fas fa-comments';
2102 $icon['color'] = 'wpfcl-2';
2103 } elseif( $type == 'topic' ) {
2104 $icon = $this->icon_status( $item['posts'] );
2105 }
2106 if( $echo ) {
2107 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : ( wpfval( $icon, 'title' ) ? $icon['title'] : '' );
2108 } else {
2109 return ( $data == 'icon' ) ? implode( ' ', $icon ) : ( wpfval( $icon, 'title' ) ? $icon['title'] : '' );
2110 }
2111 }
2112
2113 }
2114
2115 return '';
2116 }
2117
2118 function icon_status( $item ) {
2119 $icon = [];
2120 if( wpfval( $item, 'type' ) ) {
2121 $icon['sticky']['class'] = 'fas fa-thumbtack';
2122 $icon['sticky']['color'] = 'wpfcl-10';
2123 $icon['sticky']['title'] = wpforo_phrase( 'Sticky', false );
2124 }
2125 if( wpfval( $item, 'topicid' ) && wpforo_topic( $item['topicid'], 'solved' ) ) {
2126 $icon['is_answer']['class'] = 'fas fa-check-circle';
2127 $icon['is_answer']['color'] = 'wpfcl-8';
2128 $icon['is_answer']['title'] = wpforo_phrase( 'Solved', false );
2129 }
2130 if( wpfval( $item, 'closed' ) ) {
2131 $icon['closed']['class'] = 'fas fa-lock';
2132 $icon['closed']['color'] = 'wpfcl-1';
2133 $icon['closed']['title'] = wpforo_phrase( 'Closed', false );
2134 }
2135 if( wpfval( $item, 'status' ) ) {
2136 $icon['status']['class'] = 'fas fa-exclamation-circle';
2137 $icon['status']['color'] = 'wpfcl-5';
2138 $icon['status']['title'] = wpforo_phrase( 'Unapproved', false );
2139 }
2140 if( wpfval( $item, 'private' ) ) {
2141 $icon['private']['class'] = 'fas fa-eye-slash';
2142 $icon['private']['color'] = 'wpfcl-1';
2143 $icon['private']['title'] = wpforo_phrase( 'Private', false );
2144 }
2145
2146 return $icon;
2147 }
2148
2149 function icon_base( $post_count ) {
2150 $icon = [];
2151 $min_posts_for_active_topic = (int) apply_filters('wpforo_active_topic_min_posts', 5);
2152 $min_posts_for_hot_topic = (int) apply_filters('wpforo_hot_topic_min_posts', 20);
2153 if( $post_count < 2 ) {
2154 $icon['class'] = 'far fa-file';
2155 $icon['color'] = 'wpfcl-2';
2156 $icon['title'] = wpforo_phrase( 'Not Replied', false );
2157 } elseif( $post_count <= $min_posts_for_active_topic ) {
2158 $icon['class'] = 'far fa-file-alt';
2159 $icon['color'] = 'wpfcl-2';
2160 $icon['title'] = wpforo_phrase( 'Replied', false );
2161 } elseif( $post_count <= $min_posts_for_hot_topic ) {
2162 $icon['class'] = 'fas fa-file-alt';
2163 $icon['color'] = 'wpfcl-2';
2164 $icon['title'] = wpforo_phrase( 'Active', false );
2165 } else {
2166 $icon['class'] = 'fa-solid fa-fire-flame-curved';
2167 $icon['color'] = 'wpfcl-5';
2168 $icon['title'] = wpforo_phrase( 'Hot', false );
2169 }
2170
2171 return $icon;
2172 }
2173
2174 public function member_social_buttons( $member ) {
2175 $socnets = [];
2176 if( empty( $member ) ) return;
2177 $social_access = (bool) WPF()->usergroup->can( 'vmsn' );
2178
2179 if( $social_access ) {
2180
2181 if( isset( $member['facebook'] ) && $member['facebook'] ) {
2182 $socnets['facebook']['set'] = $member['facebook'];
2183 $member['facebook'] = ( strpos( (string) $member['facebook'], 'facebook.com' ) === false ) ? 'https://www.facebook.com/' . trim( (string) $member['facebook'], '/' ) : $member['facebook'];
2184 $socnets['facebook']['value'] = $member['facebook'];
2185 $socnets['facebook']['protocol'] = 'https://';
2186 $socnets['facebook']['title'] = wpforo_phrase( 'Facebook', false );
2187 }
2188
2189 if( isset( $member['twitter'] ) && $member['twitter'] ) {
2190 $socnets['twitter']['set'] = $member['twitter'];
2191 $member['twitter'] = ( strpos( (string) $member['twitter'], 'twitter.com' ) === false ) ? 'https://twitter.com/' . trim( (string) $member['twitter'], '/' ) : $member['twitter'];
2192 $socnets['twitter']['value'] = $member['twitter'];
2193 $socnets['twitter']['protocol'] = 'https://';
2194 $socnets['twitter']['title'] = wpforo_phrase( 'X.com', false );
2195 }
2196
2197 if( isset( $member['skype'] ) && $member['skype'] ) {
2198 $socnets['skype']['set'] = $member['skype'];
2199 $socnets['skype']['value'] = $member['skype'];
2200 $socnets['skype']['protocol'] = 'skype:';
2201 $socnets['skype']['title'] = wpforo_phrase( 'Skype', false );
2202 }
2203
2204 ?>
2205 <div class="wpf-member-socnet-wrap">
2206 <?php if( ! empty( $socnets ) ): ?>
2207 <?php foreach( $socnets as $key => $socnet ): ?>
2208 <?php if( ! $socnet['set'] ) continue; ?>
2209 <?php $title = $member['display_name'] . ' - ' . $socnet['title']; ?>
2210 <?php $url = ( $key == 'skype' ) ? 'skype:' . esc_attr( $socnet['value'] ) : esc_url( (string) $socnet['protocol'] . str_replace( [ 'https://', 'http://', 'skype:', 'mailto:' ], '', $socnet['value'] ) ); ?>
2211 <a href="<?php echo $url ?>" class="wpf-member-socnet-button" title="<?php echo esc_attr( $title ) ?>">
2212 <img src="<?php echo esc_url( (string) WPFORO_URL ) ?>/assets/images/sn/<?php echo $key ?>.png" alt="<?php echo esc_attr( $title ) ?>" title="<?php echo esc_attr( $title ) ?>"/>
2213 </a>
2214 <?php endforeach; ?>
2215 <?php endif; ?>
2216 <?php do_action( 'wpforo_member_socnet_buttons', $member ); ?>
2217 </div>
2218 <?php
2219 }
2220 }
2221
2222 /**
2223 *
2224 * Checks in current active theme options if certain layout exists.
2225 *
2226 * @param mixed $identifier Layout id (folder name) OR @layout variable in header ( 1 or Extended )
2227 * @param string $identifier_type The type of first parameter 'id' OR 'name' (@layout)
2228 *
2229 * @return boolean true/false
2230 *
2231 **@since 1.0.0
2232 *
2233 */
2234 function layout_exists( $identifier, $identifier_type = 'id' ) {
2235 $layouts = $this->theme_info['layouts'];
2236 if( $identifier_type === 'id' ) {
2237 return ( isset( $layouts[ $identifier ] ) && ! empty( $layouts[ $identifier ] ) );
2238 } elseif( $identifier_type === 'name' ) {
2239 foreach( $layouts as $layout ) {
2240 if( ! isset( $layout['name'] ) && $layout['name'] === $identifier ) {
2241 return true;
2242 }
2243 }
2244 }
2245
2246 return false;
2247 }
2248
2249 /**
2250 *
2251 * Finds and returns all layouts information in array from theme's /layouts/ folder
2252 *
2253 * @param string $theme Theme id ( folder name ) e.g. 'classic'
2254 *
2255 * @return array
2256 *
2257 **@since 1.0.0
2258 *
2259 */
2260 function find_layouts( $theme = '' ) {
2261 if( ! $theme ) $theme = $this->theme;
2262 $layout_data = [];
2263 $layouts = $this->find_themes( '/' . $theme . '/layouts', 'php', 'layout' );
2264 if( ! empty( $layouts ) ) {
2265 foreach( $layouts as $layout ) {
2266 $lid = trim( basename( dirname( (string) $layout['file']['value'] ) ), '/' );
2267 $layout_data[ $lid ]['id'] = intval( $lid );
2268 $layout_data[ $lid ]['name'] = esc_html( $layout['name']['value'] );
2269 $layout_data[ $lid ]['version'] = $layout['version']['value'];
2270 $layout_data[ $lid ]['description'] = $layout['description']['value'];
2271 $layout_data[ $lid ]['author'] = $layout['author']['value'];
2272 $layout_data[ $lid ]['url'] = $layout['layout_url']['value'];
2273 $layout_data[ $lid ]['file'] = $layout['file']['value'];
2274 }
2275 }
2276
2277 return $layout_data;
2278 }
2279
2280 function show_layout_selectbox( $layoutid = 0 ) {
2281 $layouts = $this->find_layouts();
2282 if( ! empty( $layouts ) ) {
2283 foreach( $layouts as $layout ) : ?>
2284 <option value="<?php echo esc_attr( trim( (string) $layout['id'] ) ) ?>" <?php echo( $layoutid == $layout['id'] ? 'selected' : '' ); ?> ><?php echo esc_html( $layout['name'] ) ?></option>
2285 <?php
2286 endforeach;
2287 }
2288 }
2289
2290 /**
2291 * @param string $theme theme dir name if empty use current theme dir
2292 *
2293 * @return string dynamicly generated css
2294 */
2295 public function generate_dynamic_css( $theme = '' ) {
2296 $css = '';
2297 $search = [];
2298 $replace = [];
2299
2300 $color_style = wpforo_setting( 'styles', 'color_style' );
2301 $color_styles = wpforo_setting( 'styles', 'color_styles' );
2302 if( $colors = wpfval( $color_styles, $color_style ) ) {
2303 foreach( $colors as $colorid => $color ) {
2304 if( $color ) {
2305 $search[] = '__WPFCOLOR_' . $colorid . '__';
2306 $replace[] = $color;
2307 }
2308 }
2309 }
2310
2311 $css_matrix = ( $theme ? WPFORO_THEME_DIR . '/' . $theme : $this->template_dir ) . '/styles/matrix.css';
2312 if( file_exists( $css_matrix ) ) $css = wpforo_get_file_content( $css_matrix );
2313
2314 $dynamic_css = apply_filters( 'wpforo_dynamic_css_filter', '' );
2315 $dynamic_css = wpforo_add_wrapper( $dynamic_css );
2316
2317 $css .= "\r\n" . $dynamic_css;
2318 $css = apply_filters( 'wpforo_dynamic_css', $css );
2319
2320 $css = str_replace( $search, $replace, $css );
2321
2322 return trim( (string) $css );
2323 }
2324
2325 /**
2326 *
2327 * Finds and returns styles array from theme's /styles/colors.php file
2328 *
2329 * @param string $theme Theme id ( folder name ) e.g. 'classic'
2330 *
2331 * @return array
2332 *
2333 **@since 1.0.0
2334 *
2335 */
2336 function find_styles( $theme ) {
2337 $colors = [];
2338 $color_file = WPFORO_THEME_DIR . '/' . $theme . '/styles/colors.php';
2339 if( file_exists( $color_file ) ) {
2340 include( $color_file );
2341 }
2342
2343 return $colors;
2344 }
2345
2346 /**
2347 *
2348 * Scans certain theme directory and returns all information in array ( theme header, layouts, styles ).
2349 *
2350 * @param string $theme_file Theme folder name or main css file base path ( 'classic' OR classic/style.css' )
2351 *
2352 * @return array
2353 *
2354 **@since 1.0.0
2355 *
2356 */
2357 function find_theme( $theme_file ) {
2358 $theme = [];
2359 $theme_file = trim( trim( (string) $theme_file, '/' ) );
2360
2361 if( preg_match( '|\.\w{2,4}$|i', (string) $theme_file ) ) {
2362 $theme_folder = trim( basename( dirname( (string) $theme_file ) ), '/' );
2363 } else {
2364 $theme_folder = $theme_file;
2365 $theme_file = $theme_file . '/style.css';
2366 }
2367
2368 if( ! is_readable( WPFORO_THEME_DIR . '/' . $theme_file ) ) {
2369 $theme['error'] = __( 'Theme file not readable', 'wpforo' ) . ' (' . $theme_file . ')';
2370 } else {
2371 $theme_data = $this->find_theme_headers( WPFORO_THEME_DIR . '/' . $theme_file );
2372 $theme['id'] = $theme_folder;
2373 $theme['name'] = $theme_data['name']['value'];
2374 $theme['version'] = $theme_data['version']['value'];
2375 $theme['description'] = $theme_data['description']['value'];
2376 $theme['author'] = $theme_data['author']['value'];
2377 $theme['url'] = $theme_data['theme_url']['value'];
2378 $theme['file'] = $theme_file;
2379 $theme['folder'] = $theme_folder;
2380 $theme['layouts'] = $this->find_layouts( $theme_folder );
2381 $styles = $this->find_styles( $theme_folder );
2382 if( ! empty( $styles ) ) {
2383 reset( $styles );
2384 $theme['style'] = key( $styles );
2385 $theme['styles'] = $styles;
2386 }
2387 }
2388
2389 return $theme;
2390 }
2391
2392 /**
2393 *
2394 * Scans wpForo themes (wpf-themes) folder, reads main files' headers and returns information about all themes in array.
2395 * This function can also be used to scan and get information about layouts in each theme /layouts/ folder.
2396 *
2397 * @param string $base_dir Absolute path to scan directory (e.g. /home/public_html/wp-content/plugins/wpforo/themes/)
2398 * @param string $ext File extension which may contain header information
2399 * @param string $mode 'theme' or 'layout'
2400 *
2401 * @return array
2402 *
2403 **@since 1.0.0
2404 *
2405 */
2406 function find_themes( $base_dir = '', $ext = 'css', $mode = 'theme' ) {
2407 $themes = [];
2408 $themes_dir = @opendir( WPFORO_THEME_DIR . $base_dir );
2409 $theme_files = [];
2410 if( $themes_dir ) {
2411 while( ( $file = readdir( $themes_dir ) ) !== false ) {
2412 if( substr( (string) $file, 0, 1 ) == '.' ) continue;
2413 if( is_dir( WPFORO_THEME_DIR . $base_dir . '/' . $file ) ) {
2414 $themes_subdir = @opendir( WPFORO_THEME_DIR . $base_dir . '/' . $file );
2415 if( $themes_subdir ) {
2416 while( ( $subfile = readdir( $themes_subdir ) ) !== false ) {
2417 if( substr( (string) $subfile, 0, 1 ) == '.' ) continue;
2418 if( substr( (string) $subfile, - 4 ) == '.' . $ext ) $theme_files[] = "$file/$subfile";
2419 }
2420 closedir( $themes_subdir );
2421 }
2422 } else {
2423 if( substr( (string) $file, - 4 ) == '.' . $ext ) $theme_files[] = $file;
2424 }
2425 }
2426 closedir( $themes_dir );
2427 }
2428 if( empty( $theme_files ) ) return $themes;
2429 foreach( $theme_files as $theme_file ) {
2430 if( ! is_readable( WPFORO_THEME_DIR . $base_dir . '/' . $theme_file ) ) continue;
2431 if( $mode === 'theme' ) {
2432 $theme_data = $this->find_theme_headers( WPFORO_THEME_DIR . $base_dir . '/' . $theme_file );
2433 } elseif( $mode === 'layout' ) {
2434 $theme_data = $this->find_layout_headers( WPFORO_THEME_DIR . $base_dir . '/' . $theme_file );
2435 }
2436 if( empty( $theme_data['name']['value'] ) ) continue;
2437 $themes[ wpforo_clear_basename( $theme_file ) ] = $theme_data;
2438 }
2439
2440 return $themes;
2441 }
2442
2443 /**
2444 *
2445 * Reads theme main file's header variables and returns information in array.
2446 *
2447 * @param string $file Absolute path to file (e.g. /home/public_html/wp-content/plugins/wpforo/themes/style.css)
2448 *
2449 * @return array
2450 *
2451 **@since 1.0.0
2452 *
2453 */
2454 function find_theme_headers( $file ) {
2455 $theme_headers = [];
2456 $headers = [
2457 'name' => 'Theme Name',
2458 'version' => 'Version',
2459 'description' => 'Description',
2460 'author' => 'Author',
2461 'theme_url' => 'Theme URI',
2462 ];
2463 $fp = fopen( $file, 'r' );
2464 $data = fread( $fp, 8192 );
2465 fclose( $fp );
2466 $data = str_replace( "\r", "\n", $data );
2467 foreach( $headers as $header_key => $header_name ) {
2468 $theme_headers[ $header_key ]['name'] = $header_name;
2469 if( preg_match( '|^[\s\t/*#@]*' . preg_quote( $header_name, '|' ) . ':(.*)$|mi', (string) $data, $match ) && $match[1] ) {
2470 $theme_headers[ $header_key ]['value'] = trim( preg_replace( "/\s*(?:\*\/|\?>).*/", '', $match[1] ) );
2471 } else {
2472 $theme_headers[ $header_key ]['value'] = '';
2473 }
2474 }
2475 $theme_headers['file']['name'] = 'file';
2476 $theme_headers['file']['value'] = $file;
2477
2478 return $theme_headers;
2479 }
2480
2481 /**
2482 *
2483 * Reads layout main file's header variables and returns information in array.
2484 *
2485 * @param string $file Absolute path to file (e.g. /home/public_html/wp-content/plugins/wpforo/themes/layouts/1/forum.php)
2486 *
2487 * @return array
2488 *
2489 **@since 1.0.0
2490 *
2491 */
2492 function find_layout_headers( $file ) {
2493 $theme_headers = [];
2494 $headers = [
2495 'name' => 'layout',
2496 'version' => 'version',
2497 'description' => 'description',
2498 'author' => 'author',
2499 'layout_url' => 'url',
2500 ];
2501 $fp = fopen( $file, 'r' );
2502 $data = fread( $fp, 8192 );
2503 fclose( $fp );
2504 $data = str_replace( "\r", "\n", $data );
2505 foreach( $headers as $header_key => $header_name ) {
2506 $theme_headers[ $header_key ]['name'] = $header_name;
2507 if( preg_match( '|^[\s\t/*#@]*' . preg_quote( $header_name, '|' ) . ':(.*)$|mi', (string) $data, $match ) && $match[1] ) {
2508 $theme_headers[ $header_key ]['value'] = trim( preg_replace( "/\s*(?:\*\/|\?>).*/", '', $match[1] ) );
2509 } else {
2510 $theme_headers[ $header_key ]['value'] = '';
2511 }
2512 }
2513 $theme_headers['file']['name'] = 'file';
2514 $theme_headers['file']['value'] = trim( str_replace( WPFORO_THEME_DIR, '', (string) $file ), '/' );
2515
2516 return $theme_headers;
2517 }
2518
2519 public function theme_exists( $theme ) {
2520 $_theme = $this->find_theme( $theme );
2521 return ! wpfkey($_theme, 'error');
2522 }
2523
2524 public function copyright() {
2525 if( wpforo_setting( 'components', 'copyright' ) ): ?>
2526 <div id="wpforo-poweredby">
2527 <p class="wpf-by">
2528 <span onclick='document.getElementById("bywpforo").style.display = "inline";document.getElementById("awpforo").style.display = "none";' id="awpforo"> <img title="<?php esc_attr( wpforo_phrase( 'Powered by' ) ) ?> wpForo version <?php echo esc_html( WPFORO_VERSION ) ?>" alt="Powered by wpForo" class="wpdimg" src="<?php echo WPFORO_URL ?>/assets/images/wpforo-info.png"> </span><a id="bywpforo" target="_blank" href="https://wpforo.com/">&nbsp;<?php wpforo_phrase(
2529 'Powered by'
2530 ) ?> wpForo version <?php echo esc_html( WPFORO_VERSION ) ?></a>
2531 </p>
2532 </div>
2533 <?php
2534 endif;
2535 }
2536
2537 public function member_error() {
2538 echo apply_filters( 'wpforo_member_error_filter', wpforo_phrase( 'Members not found', false ) );
2539 }
2540
2541 public function ajx_active_tab_content() {
2542 wpforo_verify_nonce( 'wpforo_active_tab_content_ajax' );
2543 if( ! empty( $_POST['active_tab_id'] ) ) {
2544 $active_tab_id = sanitize_textarea_field( $_POST['active_tab_id'] );
2545 switch( $active_tab_id ) {
2546 case 'topic_merge_form':
2547 $this->topic_merge_form();
2548 exit();
2549 case 'reply_move_form':
2550 $this->reply_move_form();
2551 exit();
2552 case 'topic_split_form':
2553 $this->topic_split_form();
2554 exit();
2555 case 'topic_move_form':
2556 $this->topic_move_form();
2557 exit();
2558 }
2559 }
2560 echo 0;
2561 exit();
2562 }
2563
2564 public function add_footer_html() {
2565 $this->dialog();
2566 if( WPF()->current_object['template'] === 'post' ) $this->report_form();
2567 $this->notifications_bar();
2568 }
2569
2570 public function posts_ordering_dropdown( $orderby = null, $topicid = null ) {
2571 if( is_null( $topicid ) ) $topicid = wpforo_bigintval( wpfval( WPF()->current_object, 'topicid' ) );
2572 if( $topicid && $topic_url = wpforo_topic( $topicid, 'url' ) ) {
2573 if( is_null( $orderby ) ) $orderby = WPF()->current_object['orderby'];
2574 ?>
2575 <label>
2576 <select onchange="window.location.assign(this.value)">
2577 <option value="<?php echo $topic_url ?>?orderby=votes" <?php wpfo_check( $orderby, 'votes', 'selected' ) ?>>
2578 <?php wpforo_phrase( 'Most Voted' ) ?>
2579 </option>
2580 <option value="<?php echo $topic_url ?>?orderby=oldest" <?php wpfo_check( $orderby, 'oldest', 'selected' ) ?>>
2581 <?php wpforo_phrase( 'Oldest' ) ?>
2582 </option>
2583 <option value="<?php echo $topic_url ?>?orderby=newest" <?php wpfo_check( $orderby, 'newest', 'selected' ) ?>>
2584 <?php wpforo_phrase( 'Newest' ) ?>
2585 </option>
2586 </select>
2587 </label>
2588
2589 <?php
2590 }
2591 }
2592
2593 public function editor_buttons( $editor = 'post' ) {
2594 global $wp_styles;
2595 if( ! empty( $wp_styles ) && ( $fa = wpfval( $wp_styles->registered, 'wpforo-font-awesome' ) ) && ( $fa_rtl = wpfval( $wp_styles->registered, 'wpforo-font-awesome-rtl' ) ) ) {
2596 $content_css = $fa->src . ( is_rtl() ? ',' . $fa_rtl->src : '' );
2597 } else {
2598 $content_css = '';
2599 }
2600 $settings = [
2601 'topic' => [
2602 'media_buttons' => false,
2603 'textarea_name' => 'topic[body]',
2604 'textarea_rows' => get_option( 'default_post_edit_rows', 20 ),// rows = "..."
2605 'tabindex' => '',
2606 'editor_height' => 180,
2607 'editor_css' => '',
2608 'editor_class' => '',
2609 'teeny' => false,
2610 'dfw' => false,
2611 'tinymce' => [
2612 'toolbar1' => 'fontsizeselect,bold,italic,underline,strikethrough,forecolor,bullist,numlist,hr,alignleft,aligncenter,alignright,alignjustify,link,unlink,blockquote,pre,wpf_spoil,undo,redo,pastetext,source_code,emoticons,fullscreen',
2613 'toolbar2' => '',
2614 'toolbar3' => '',
2615 'toolbar4' => '',
2616 'content_style' => 'blockquote{border: #cccccc 1px dotted; background: #F7F7F7; padding:10px;font-size:12px; font-style:italic; margin: 20px 10px;} pre{border-left: 3px solid #ccc; outline: none !important; background: #fafcff;padding: 10px;font-size: 14px;margin: 20px 0 0 10px;display: block;width: 100%;} img.emoji{width: 20px;}',
2617 'object_resizing' => false,
2618 'autoresize_on_init' => true,
2619 'wp_autoresize_on' => true,
2620 'wp_keep_scroll_position' => true,
2621 'indent' => true,
2622 'add_unload_trigger' => false,
2623 'wpautop' => false,
2624 'setup' => 'wpforo_tinymce_setup',
2625 'content_css' => $content_css,
2626 'extended_valid_elements' => 'i[class|style],span[class|style]',
2627 'custom_elements' => '',
2628 ],
2629 'quicktags' => false,
2630 'default_editor' => 'tinymce',
2631 ],
2632 'post' => [
2633 'media_buttons' => false,
2634 'textarea_name' => 'post[body]',
2635 'textarea_rows' => get_option( 'default_post_edit_rows', 5 ),
2636 'editor_class' => 'wpeditor',
2637 'teeny' => false,
2638 'dfw' => false,
2639 'editor_height' => 150,
2640 'tinymce' => [
2641 'toolbar1' => 'fontsizeselect,bold,italic,underline,strikethrough,forecolor,bullist,numlist,hr,alignleft,aligncenter,alignright,alignjustify,link,unlink,blockquote,pre,wpf_spoil,undo,redo,pastetext,source_code,emoticons,fullscreen',
2642 'toolbar2' => '',
2643 'toolbar3' => '',
2644 'toolbar4' => '',
2645 'content_style' => 'blockquote{border: #cccccc 1px dotted; background: #F7F7F7; padding:10px;font-size:12px; font-style:italic; margin: 20px 10px;} pre{border-left: 3px solid #ccc; outline: none !important; background: #fafcff;padding: 10px;font-size: 14px;margin: 20px 0 0 10px;display: block;width: 100%;} img.emoji{width: 20px;}',
2646 'object_resizing' => false,
2647 'autoresize_on_init' => true,
2648 'wp_autoresize_on' => true,
2649 'wp_keep_scroll_position' => true,
2650 'indent' => true,
2651 'add_unload_trigger' => false,
2652 'wpautop' => false,
2653 'setup' => 'wpforo_tinymce_setup',
2654 'content_css' => $content_css,
2655 'extended_valid_elements' => 'i[class|style],span[class|style]',
2656 'custom_elements' => '',
2657 ],
2658 'quicktags' => false,
2659 'default_editor' => 'tinymce',
2660 ],
2661 ];
2662
2663 return apply_filters( 'wpforo_editor_settings', array_merge( $this->default->editor_settings, $settings[ $editor ] ), $editor );
2664 }
2665
2666 public function editor_settings_required_params( $settings ) {
2667 if( ! wpfkey( $settings, 'tinymce' ) ) $settings['tinymce'] = [];
2668 $settings['tinymce']['setup'] = 'wpforo_tinymce_setup';
2669
2670 if( is_rtl() ) {
2671 $settings['tinymce']['rtl_ui'] = true;
2672 $settings['plugins'] .= ',directionality';
2673 $settings['tinymce']['toolbar1'] .= ',ltr';
2674 $settings['tinymce']['directionality'] = 'rtl';
2675
2676 $settings['plugins'] = trim( (string) $settings['plugins'], ',' );
2677 $settings['tinymce']['toolbar1'] = trim( (string) $settings['tinymce']['toolbar1'], ',' );
2678 }
2679
2680 return $settings;
2681 }
2682
2683 public function add_topic_button( $forumid = null ) {
2684 $phrase = ( WPF()->forum->get_layout( $forumid ) === 3 ? wpforo_phrase( 'Ask a Question', false ) : wpforo_phrase( 'Add Topic', false ) );
2685 if( WPF()->current_object['template'] === 'forum' ) :
2686 if( wpforo_forum_list_need_add_topic_button( $forumid ) ) :
2687 if( WPF()->perm->forum_can( 'ct', $forumid ) ) : WPF()->current_object['load_tinymce'] = true; ?>
2688 <div class="wpf-head-bar-right">
2689 <button class="wpf-button add_wpftopic" data-phrase="<?php echo $phrase ?>">
2690 <i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span>
2691 </button>
2692 </div>
2693 <?php elseif( WPF()->current_user_groupid === 4 ) : ?>
2694 <div class="wpf-head-bar-right">
2695 <a href="<?php echo wpforo_login_url() ?>" class="wpf-button"><i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span></a>
2696 </div>
2697 <?php endif;
2698 endif;
2699 else :
2700 if( WPF()->perm->forum_can( 'ct', $forumid ) ): ?>
2701 <button id="add_wpftopic" class="wpf-button" data-phrase="<?php echo $phrase ?>">
2702 <i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span>
2703 </button>
2704 <?php elseif( WPF()->current_user_groupid === 4 ) : ?>
2705 <a href="<?php echo wpforo_login_url() ?>" class="wpf-button"><i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span></a>
2706 <?php endif;
2707 endif;
2708 }
2709
2710 private function notifications_bar() {
2711 echo '<div id="wpforo-notifications-bar">';
2712 $this->spinner();
2713 if( apply_filters( 'wpforo_message_bubble', true ) ) $this->msg_box();
2714 echo '</div>';
2715 }
2716
2717 private function msg_box() { ?>
2718 <div id="wpf-msg-box"></div>
2719 <?php
2720 }
2721
2722 private function spinner() { ?>
2723 <div id="wpforo-load" class="wpforo-load">
2724 <div class="wpf-load-ico-wrap"><i class="fas fa-3x fa-spinner fa-spin"></i></div>
2725 <div class="wpf-load-txt-wrap"><span class="loadtext"></span></div>
2726 </div>
2727 <?php
2728 }
2729
2730 private function dialog() { ?>
2731 <div id="wpforo-dialog-extra-wrap">
2732 <div id="wpforo-dialog-wrap">
2733 <div id="wpforo-dialog">
2734 <div id="wpforo-dialog-header">
2735 <strong id="wpforo-dialog-title"></strong>
2736 <i id="wpforo-dialog-close" class="fas fa-window-close fa-2x"></i>
2737 </div>
2738 <div id="wpforo-dialog-body"></div>
2739 </div>
2740 </div>
2741 <div id="wpforo-dialog-backups"></div>
2742 </div>
2743 <?php
2744 }
2745
2746 private function report_form() { ?>
2747 <form id="wpforo-report" data-title="<?php echo esc_attr( wpforo_phrase( 'Report to Administration', false ) ) ?>">
2748 <input type="hidden" id="wpforo-report-postid">
2749 <label for="wpforo-report-content"></label><textarea id="wpforo-report-content" required placeholder="<?php esc_attr( wpforo_phrase( 'Write message' ) ) ?>"></textarea>
2750 <input id="wpforo-report-send" type="button" value="<?php wpforo_phrase( 'Send Report' ) ?>" title="Ctrl+Enter">
2751 </form>
2752 <?php
2753 }
2754
2755 public function do_spoilers( $text ) {
2756 $text = preg_replace(
2757 '#(?:<(p|a|span|blockquote|b|i|pre|font|del|strike|strong|em|div|u|center|marquee|table|tr|td|th|tt|sup|sub|s|ul|ol|li|small|code|h\d)(?:[\r\n\t\s\0]+[^<>]*?)?>[\r\n\t\s\0]*)\[[\r\n\t\s\0]*spoiler(?:[\r\n\t\s\0]*title[\r\n\t\s\0]*=[\r\n\t\s\0]*\"([^\"]+)\")?[\r\n\t\s\0]*](?:[\r\n\t\s\0]*</\1>)#iu',
2758 '<div class="wpf-spoiler-wrap"><div class="wpf-spoiler-head"><i class="wpf-spoiler-chevron-name">' . wpforo_phrase( 'Spoiler', false ) . '</i><i class="wpf-spoiler-chevron fas fa-chevron-down"></i><div class="wpf-spoiler-title">$2</div></div><div class="wpf-spoiler-body">',
2759 (string) $text,
2760 - 1,
2761 $count1
2762 );
2763 $text = preg_replace( '#\[[\r\n\t\s\0]*spoiler(?:[\r\n\t\s\0]*title[\r\n\t\s\0]*=[\r\n\t\s\0]*\"([^\"]+)\")?[\r\n\t\s\0]*]#iu', '<div class="wpf-spoiler-wrap"><div class="wpf-spoiler-head"><i class="wpf-spoiler-chevron-name">' . wpforo_phrase( 'Spoiler', false ) . '</i><i class="wpf-spoiler-chevron fas fa-chevron-down"></i><div class="wpf-spoiler-title">$1</div></div><div class="wpf-spoiler-body">', (string) $text, - 1, $count2 );
2764 $text = preg_replace( '#(?:<(p|a|span|blockquote|b|i|pre|font|del|strike|strong|em|div|u|center|marquee|table|tr|td|th|tt|sup|sub|s|ul|ol|li|small|code|h\d)(?:[\r\n\t\s\0]+[^<>]*?)?>[\r\n\t\s\0]*)\[[\r\n\t\s\0]*/[\r\n\t\s\0]*spoiler[\r\n\t\s\0]*](?:[\r\n\t\s\0]*</\1>)#iu', '</div></div>', (string) $text, $count1 );
2765
2766 return preg_replace( '#\[[\r\n\t\s\0]*/[\r\n\t\s\0]*spoiler[\r\n\t\s\0]*]#iu', '</div></div>', (string) $text, $count2 );
2767 }
2768
2769 public function apply_quotes( $text ) {
2770 $text = preg_replace_callback( '#\[quote(\s[^\[\]]+|\s?)?]#iu', function( $m ){
2771 $userid = 0;
2772 $postid = 0;
2773 $mention = '';
2774 $posted_by = '';
2775 if( preg_match( '#data-userid=[\'"](\d+)[\'"]#iu', $m[1], $u ) ) $userid = wpforo_bigintval( $u[1] );
2776 if( preg_match( '#data-postid=[\'"](\d+)[\'"]#iu', $m[1], $p ) ) $postid = wpforo_bigintval( $p[1] );
2777
2778 if( $userid ){
2779 $profiles_mention_nicknames = wpforo_setting( 'profiles', 'mention_nicknames' );
2780 $posted_by = $mention = trim( (string) ($profiles_mention_nicknames ? wpforo_member( $userid, 'user_nicename' ) : wpforo_member( $userid, 'display_name' )) );
2781 if( $profiles_mention_nicknames ) $posted_by = '@' . $posted_by;
2782 }
2783
2784 return sprintf(
2785 '<blockquote data-userid="%1$d" data-postid="%2$d" data-mention="%3$s"><div class="wpforo-post-quote-head">%4$s %5$s</div>',
2786 $userid,
2787 $postid,
2788 $mention,
2789 ( $posted_by ? sprintf('<div class="wpforo-post-quote-author"><strong> %1$s: %2$s </strong></div>', wpforo_phrase( 'Posted by', false ), $posted_by) : '' ),
2790 ( $postid ? sprintf( '<div class="wpforo-post-quote-link"><a href="%1$s" title="%2$s">&uarr;</a></div>', WPF()->post->get_url( $postid ), wpforo_phrase( 'go to original post', false ) ) : '' )
2791 );
2792 }, (string) $text );
2793
2794 return preg_replace( '#\[/quote]#iu', '</blockquote>', (string) $text );
2795 }
2796
2797 public function please_login() {
2798 if( ! wpforo_is_bot() ) {
2799 $html = sprintf(
2800 '<div class="wpf-please-login">%1$s %2$s</div>',
2801 wpforo_get_login_or_register_notice_text(),
2802 wpforo_phrase( 'to reply to this topic.', false, 'lower' )
2803 );
2804 echo apply_filters( 'wpforo_login_message_in_topic', $html );
2805 }
2806 }
2807
2808 public function profile_board_panel( $user = [], $template = '', $active_boardid = null ) {
2809 if( !is_wpforo_multiboard() ) return '';
2810 if( is_numeric( $user ) ) $user = WPF()->member->get_member( $user );
2811 if( !$user ) $user = WPF()->current_object['user'];
2812 if( ! $template ) $template = WPF()->current_object['template'];
2813 if( is_null( $active_boardid ) ) $active_boardid = ( wpfkey( WPF()->GET, 'boardid' ) ? (int) WPF()->GET['boardid'] : WPF()->board->get_current( 'boardid' ) );
2814 $links = '';
2815 foreach( WPF()->board->get_boards( ['status' => true] ) as $board ){
2816 if( $template === 'subscriptions' && !wpforo_is_module_enabled( 'subscriptions', $board ) ) continue;
2817 $links .= sprintf(
2818 '<span class="wpf-member-template-link wpf-ajax-link %1$s"><a href="%2$s" title="%3$s">%4$s</a></span>',
2819 ( $active_boardid === $board['boardid'] ? 'wpf-active' : '' ),
2820 WPF()->user_trailingslashit( trim( WPF()->member->get_profile_url( $user, $template ), '/' ) . '/?boardid=' . $board['boardid'] ),
2821 $board['title'],
2822 wpforo_text($board['title'], 10, false)
2823 );
2824 }
2825 return sprintf(
2826 '<div class="wpf-board-panel">
2827 <div class="wpf-board-panel-left"><span>%1$s</span></div>
2828 <div class="wpf-board-panel-right">%2$s</div>
2829 </div>',
2830 wpforo_phrase('Board', false),
2831 $links
2832 );
2833 }
2834
2835 public function profile_activity_panel( $user = [], $boardid = null, $active_filter = '' ) {
2836 if( is_numeric( $user ) ) $user = WPF()->member->get_member( $user );
2837 if( !$user ) $user = WPF()->current_object['user'];
2838 if( is_null( $boardid ) ) $boardid = wpfkey( WPF()->GET, 'boardid' ) ? (int) WPF()->GET['boardid'] : WPF()->board->get_current( 'boardid' );
2839 if( !$active_filter ) $active_filter = (string) wpfval( WPF()->GET, 'filter' );
2840 WPF()->change_board( $boardid );
2841 $filters = [
2842 '' => wpforo_phrase( 'All', false ),
2843 'topics' => wpforo_phrase( 'Topics', false ),
2844 'replies' => wpforo_phrase( 'Replies', false ),
2845 ];
2846 $links = '';
2847 foreach( $filters as $filter => $label ) {
2848 $links .= sprintf(
2849 '<span class="wpf-member-template-link wpf-ajax-link %1$s"><a href="%2$s">%3$s</a></span>',
2850 ( $active_filter === $filter ? 'wpf-active' : ''),
2851 WPF()->member->get_activity_url( $filter, $boardid, $user ),
2852 $label
2853 );
2854 }
2855
2856 $topics = WPF()->topic->get_count( [ 'userid' => $user['userid'], 'status' => 0, 'private' => '0' ] );
2857 $posts = WPF()->post->get_count( [ 'userid' => $user['userid'], 'status' => 0, 'private' => '0' ] );
2858 return sprintf(
2859 '<div class="wpf-activity-panel">
2860 <div class="wpf-activity-panel-left">
2861 <span>%1$s</span>
2862 <span>/</span>
2863 <span>%2$s</span>
2864 </div>
2865 <div class="wpf-activity-panel-right">%3$s</div>
2866 </div>',
2867 wpforo_phrase('Topics', false) . ': ' . $topics,
2868 wpforo_phrase('Replies', false) . ': ' . ( $posts - $topics ),
2869 $links
2870 );
2871 }
2872
2873 public function profile_favored_panel( $user = [], $boardid = null, $active_filter = '' ) {
2874 if( is_numeric( $user ) ) $user = WPF()->member->get_member( $user );
2875 if( !$user ) $user = WPF()->current_object['user'];
2876 if( is_null( $boardid ) ) $boardid = wpfkey( WPF()->GET, 'boardid' ) ? (int) WPF()->GET['boardid'] : WPF()->board->get_current( 'boardid' );
2877 if( !$active_filter ) $active_filter = (string) wpfval( WPF()->current_object, 'filter' );
2878 $filters = [
2879 'bookmarks' => wpforo_phrase( 'Bookmarks', false ),
2880 'likes' => wpforo_phrase( 'Likes', false ),
2881 'dislikes' => wpforo_phrase( 'Dislikes', false ),
2882 ];
2883 $links = '';
2884 foreach( $filters as $filter => $label ) {
2885 $links .= sprintf(
2886 '<span class="wpf-member-template-link wpf-ajax-link %1$s"><a href="%2$s">%3$s</a></span>',
2887 ( $active_filter === $filter ? 'wpf-active' : ''),
2888 WPF()->member->get_favored_url( $filter, $boardid, $user ),
2889 $label
2890 );
2891 }
2892 return sprintf(
2893 '<div class="wpf-activity-panel">
2894 <div class="wpf-activity-panel-left">
2895 <span>%1$s</span>
2896 </div>
2897 <div class="wpf-activity-panel-right">%2$s</div>
2898 </div>',
2899 wpforo_phrase('Total Posts', false) . ': ' . WPF()->current_object['items_count'],
2900 $links
2901 );
2902 }
2903
2904 private function cantlogin_page() {
2905 $contact_form_phrase = ( wpforo_setting( 'authorization', 'manually_approval_contact_form' ) ) ? wpforo_phrase('Please use the contact form below if you want to contact the website administrator.', false ) : '';
2906 $html = sprintf(
2907 '<div class="wpflm-text">%1$s %2$s</div>',
2908 wpforo_phrase( 'You have been automatically signed out from the website. Your account is awaiting approval.', false ),
2909 $contact_form_phrase
2910 );
2911 if( wpforo_setting( 'authorization', 'manually_approval_contact_form' ) ){
2912 $html .= sprintf(
2913 '<div class="wpflm-form"><form method="POST" action="%1$s">
2914 <input type="hidden" name="wpfaction" value="cantlogin_contact">
2915 <input type="hidden" name="user_login" value="%2$s">
2916 <textarea name="msg" placeholder="%3$s"></textarea>
2917 <input type="submit" value="%4$s">
2918 </form></div>',
2919 wpforo_login_url(),
2920 WPF()->ram_cache->get( 'USER_LOGIN_REFERER' ),
2921 wpforo_phrase( 'Your message to the website administrator...', false ),
2922 wpforo_phrase( 'Send', false )
2923 );
2924 }
2925
2926 return '<div class="wpf-logout-message">' . apply_filters( 'wpforo_logout_message', $html ) . '</div>';
2927 }
2928
2929 public function change_cover_button( $user ) {
2930 if( WPF()->usergroup->can( 'upc' ) && WPF()->perm->user_can_edit_account( $user ) ){
2931 return sprintf(
2932 '<div class="wpf-edit-cover" title="%1$s">
2933 <i class="fas fa-images" data-action="editcover"></i>
2934 <ul class="wpf-edit-cover-options">
2935 <li class="wpf-upload-cover"><i class="fas fa-upload"></i> %2$s</li>
2936 <li class="wpf-delete-cover"><i class="fas fa-rotate-left"></i> %3$s</li>
2937 </ul>
2938 </div>',
2939 wpforo_phrase('Change Cover Image', false),
2940 wpforo_phrase('Upload New Cover', false),
2941 wpforo_phrase( 'Reset to Default', false )
2942 );
2943 }
2944
2945 return '';
2946 }
2947
2948 }
2949