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

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