PluginProbe
wpForo Forum / 3.0.2
wpForo Forum v3.0.2
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 3.0.2, at classes/Template.php

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