PluginProbe
wpForo Forum / 2.0.8
wpForo Forum v2.0.8
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.0.8, at classes/Template.php

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