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

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