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

3,227 lines 187.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 use stdClass;
6
7 // Exit if accessed directly
8 if( ! defined( 'ABSPATH' ) ) exit;
9
10 define( 'WPFORO_THEME_DIR', WPFORO_DIR . DIRECTORY_SEPARATOR . 'themes' );
11 define( 'WPFORO_THEME_URL', WPFORO_URL . '/themes' );
12
13 class Template {
14 public $default;
15 public $theme = '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( $item['type'] == 1 ) {
2297 $icon['class'] = 'fas fa-thumbtack';
2298 $icon['color'] = 'wpfcl-10';
2299 $icon['title'] = wpforo_phrase( 'Sticky', 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 if( wpforo_topic( $item['topicid'], 'solved' ) ) {
2308 $icon['class'] = 'fas fa-check-circle';
2309 $icon['color'] = 'wpfcl-8';
2310 $icon['title'] = wpforo_phrase( 'Solved', false );
2311 if( $echo ) {
2312 $status = true;
2313 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2314 } else {
2315 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2316 }
2317 }
2318 }
2319
2320 if( $item['closed'] ) {
2321 $icon['class'] = 'fas fa-lock';
2322 $icon['color'] = 'wpfcl-1';
2323 $icon['title'] = wpforo_phrase( 'Closed', false );
2324 if( $echo ) {
2325 $status = true;
2326 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2327 } else {
2328 return ( $data == 'icon' ) ? implode( ' ', $icon ) : $icon['title'];
2329 }
2330 }
2331
2332 if( ! $status ) {
2333 if( $type == 'forum' ) {
2334 $icon['class'] = 'fas fa-comments';
2335 $icon['color'] = 'wpfcl-2';
2336 } elseif( $type == 'topic' ) {
2337 $icon = $this->icon_status( $item['posts'] );
2338 }
2339 if( $echo ) {
2340 echo ( $data == 'icon' ) ? implode( ' ', $icon ) : ( wpfval( $icon, 'title' ) ? $icon['title'] : '' );
2341 } else {
2342 return ( $data == 'icon' ) ? implode( ' ', $icon ) : ( wpfval( $icon, 'title' ) ? $icon['title'] : '' );
2343 }
2344 }
2345
2346 }
2347
2348 return '';
2349 }
2350
2351 function icon_status( $item ) {
2352 $icon = [];
2353 if( wpfval( $item, 'type' ) ) {
2354 $icon['sticky']['class'] = 'fas fa-thumbtack';
2355 $icon['sticky']['color'] = 'wpfcl-10';
2356 $icon['sticky']['title'] = wpforo_phrase( 'Sticky', false );
2357 }
2358 if( wpfval( $item, 'topicid' ) && wpforo_topic( $item['topicid'], 'solved' ) ) {
2359 $icon['is_answer']['class'] = 'fas fa-check-circle';
2360 $icon['is_answer']['color'] = 'wpfcl-8';
2361 $icon['is_answer']['title'] = wpforo_phrase( 'Solved', false );
2362 }
2363 if( wpfval( $item, 'closed' ) ) {
2364 $icon['closed']['class'] = 'fas fa-lock';
2365 $icon['closed']['color'] = 'wpfcl-1';
2366 $icon['closed']['title'] = wpforo_phrase( 'Closed', false );
2367 }
2368 if( wpfval( $item, 'status' ) ) {
2369 $icon['status']['class'] = 'fas fa-exclamation-circle';
2370 $icon['status']['color'] = 'wpfcl-5';
2371 $icon['status']['title'] = wpforo_phrase( 'Unapproved', false );
2372 }
2373 if( wpfval( $item, 'private' ) ) {
2374 $icon['private']['class'] = 'fas fa-eye-slash';
2375 $icon['private']['color'] = 'wpfcl-1';
2376 $icon['private']['title'] = wpforo_phrase( 'Private', false );
2377 }
2378
2379 return $icon;
2380 }
2381
2382 function icon_base( $post_count ) {
2383 $icon = [];
2384 $min_posts_for_active_topic = (int) apply_filters( 'wpforo_active_topic_min_posts', 5 );
2385 $min_posts_for_hot_topic = (int) apply_filters( 'wpforo_hot_topic_min_posts', 20 );
2386 if( $post_count < 2 ) {
2387 $icon['class'] = 'far fa-file';
2388 $icon['color'] = 'wpfcl-2';
2389 $icon['title'] = wpforo_phrase( 'Not Replied', false );
2390 } elseif( $post_count <= $min_posts_for_active_topic ) {
2391 $icon['class'] = 'far fa-file-alt';
2392 $icon['color'] = 'wpfcl-2';
2393 $icon['title'] = wpforo_phrase( 'Replied', false );
2394 } elseif( $post_count <= $min_posts_for_hot_topic ) {
2395 $icon['class'] = 'fas fa-file-alt';
2396 $icon['color'] = 'wpfcl-2';
2397 $icon['title'] = wpforo_phrase( 'Active', false );
2398 } else {
2399 $icon['class'] = 'fa-solid fa-fire-flame-curved';
2400 $icon['color'] = 'wpfcl-5';
2401 $icon['title'] = wpforo_phrase( 'Hot', false );
2402 }
2403
2404 return $icon;
2405 }
2406
2407 public function member_social_buttons( $member ) {
2408 $socnets = [];
2409 if( empty( $member ) ) return;
2410 $social_access = (bool) WPF()->usergroup->can( 'vmsn' );
2411
2412 if( $social_access ) {
2413
2414 if( isset( $member['facebook'] ) && $member['facebook'] ) {
2415 $socnets['facebook']['set'] = $member['facebook'];
2416 $member['facebook'] = ( strpos( (string) $member['facebook'], 'facebook.com' ) === false ) ? 'https://www.facebook.com/' . trim(
2417 (string) $member['facebook'],
2418 '/'
2419 ) : $member['facebook'];
2420 $socnets['facebook']['value'] = $member['facebook'];
2421 $socnets['facebook']['protocol'] = 'https://';
2422 $socnets['facebook']['title'] = wpforo_phrase( 'Facebook', false );
2423 }
2424
2425 if( isset( $member['twitter'] ) && $member['twitter'] ) {
2426 $socnets['twitter']['set'] = $member['twitter'];
2427 $member['twitter'] = ( strpos( (string) $member['twitter'], 'x.com' ) === false ) ? 'https://x.com/' . trim(
2428 (string) $member['twitter'],
2429 '/'
2430 ) : $member['twitter'];
2431 $socnets['twitter']['value'] = $member['twitter'];
2432 $socnets['twitter']['protocol'] = 'https://';
2433 $socnets['twitter']['title'] = wpforo_phrase( 'X.com', false );
2434 }
2435
2436 if( isset( $member['skype'] ) && $member['skype'] ) {
2437 $socnets['skype']['set'] = $member['skype'];
2438 $socnets['skype']['value'] = $member['skype'];
2439 $socnets['skype']['protocol'] = 'skype:';
2440 $socnets['skype']['title'] = wpforo_phrase( 'Skype', false );
2441 }
2442
2443 ?>
2444 <div class="wpf-member-socnet-wrap">
2445 <?php if( ! empty( $socnets ) ): ?>
2446 <?php foreach( $socnets as $key => $socnet ): ?>
2447 <?php if( ! $socnet['set'] ) continue; ?>
2448 <?php $title = $member['display_name'] . ' - ' . $socnet['title']; ?>
2449 <?php $url = ( $key == 'skype' ) ? 'skype:' . esc_attr( $socnet['value'] ) : esc_url(
2450 (string) $socnet['protocol'] . str_replace( [ 'https://', 'http://', 'skype:', 'mailto:' ], '', $socnet['value'] )
2451 ); ?>
2452 <a href="<?php echo $url ?>" class="wpf-member-socnet-button" title="<?php echo esc_attr( $title ) ?>">
2453 <img src="<?php echo esc_url( (string) WPFORO_URL ) ?>/assets/images/sn/<?php echo $key ?>.png" alt="<?php echo esc_attr( $title ) ?>"
2454 title="<?php echo esc_attr( $title ) ?>"/>
2455 </a>
2456 <?php endforeach; ?>
2457 <?php endif; ?>
2458 <?php do_action( 'wpforo_member_socnet_buttons', $member ); ?>
2459 </div>
2460 <?php
2461 }
2462 }
2463
2464 /**
2465 *
2466 * Checks in current active theme options if certain layout exists.
2467 *
2468 * @param mixed $identifier Layout id (folder name) OR @layout variable in header ( 1 or Extended )
2469 * @param string $identifier_type The type of first parameter 'id' OR 'name' (@layout)
2470 *
2471 * @return boolean true/false
2472 *
2473 **@since 1.0.0
2474 *
2475 */
2476 function layout_exists( $identifier, $identifier_type = 'id' ) {
2477 $layouts = $this->theme_info['layouts'];
2478 if( $identifier_type === 'id' ) {
2479 return ( isset( $layouts[ $identifier ] ) && ! empty( $layouts[ $identifier ] ) );
2480 } elseif( $identifier_type === 'name' ) {
2481 foreach( $layouts as $layout ) {
2482 if( ! isset( $layout['name'] ) && $layout['name'] === $identifier ) {
2483 return true;
2484 }
2485 }
2486 }
2487
2488 return false;
2489 }
2490
2491 /**
2492 *
2493 * Finds and returns all layouts information in array from theme's /layouts/ folder
2494 *
2495 * @param string $theme Theme id ( folder name ) e.g. 'classic'
2496 *
2497 * @return array
2498 *
2499 **@since 1.0.0
2500 *
2501 */
2502 function find_layouts( $theme = '' ) {
2503 if( ! $theme ) $theme = $this->theme;
2504 $layout_data = [];
2505 $layouts = $this->find_themes( '/' . $theme . '/layouts', 'php', 'layout' );
2506 if( ! empty( $layouts ) ) {
2507 foreach( $layouts as $layout ) {
2508 $lid = trim( basename( dirname( (string) $layout['file']['value'] ) ), '/' );
2509 $layout_data[ $lid ]['id'] = intval( $lid );
2510 $layout_data[ $lid ]['name'] = esc_html( $layout['name']['value'] );
2511 $layout_data[ $lid ]['version'] = $layout['version']['value'];
2512 $layout_data[ $lid ]['description'] = $layout['description']['value'];
2513 $layout_data[ $lid ]['author'] = $layout['author']['value'];
2514 $layout_data[ $lid ]['url'] = $layout['layout_url']['value'];
2515 $layout_data[ $lid ]['file'] = $layout['file']['value'];
2516 }
2517 }
2518
2519 return $layout_data;
2520 }
2521
2522 function show_layout_selectbox( $layoutid = 0 ) {
2523 $layouts = $this->find_layouts();
2524 if( ! empty( $layouts ) ) {
2525 foreach( $layouts as $layout ) : ?>
2526 <option value="<?php echo esc_attr( trim( (string) $layout['id'] ) ) ?>" <?php echo( $layoutid == $layout['id'] ? 'selected' : '' ); ?> ><?php echo esc_html(
2527 $layout['name']
2528 ) ?></option>
2529 <?php
2530 endforeach;
2531 }
2532 }
2533
2534 /**
2535 * @param string $theme theme dir name if empty use current theme dir
2536 *
2537 * @return string dynamicly generated css
2538 */
2539 public function generate_dynamic_css( $theme = '' ) {
2540 $css = '';
2541 $search = [];
2542 $replace = [];
2543
2544 $color_style = wpforo_setting( 'styles', 'color_style' );
2545 $color_styles = wpforo_setting( 'styles', 'color_styles' );
2546 if( $colors = wpfval( $color_styles, $color_style ) ) {
2547 foreach( $colors as $colorid => $color ) {
2548 if( $color ) {
2549 $search[] = '__WPFCOLOR_' . $colorid . '__';
2550 $replace[] = $color;
2551 }
2552 }
2553 }
2554
2555 $css_matrix = ( $theme ? WPFORO_THEME_DIR . '/' . $theme : $this->template_dir ) . '/styles/matrix.css';
2556 if( file_exists( $css_matrix ) ) $css = wpforo_get_file_content( $css_matrix );
2557
2558 $dynamic_css = apply_filters( 'wpforo_dynamic_css_filter', '' );
2559 $dynamic_css = wpforo_add_wrapper( $dynamic_css );
2560
2561 $css .= "\r\n" . $dynamic_css;
2562 $css = apply_filters( 'wpforo_dynamic_css', $css );
2563
2564 $css = str_replace( $search, $replace, $css );
2565
2566 return trim( (string) $css );
2567 }
2568
2569 /**
2570 *
2571 * Finds and returns styles array from theme's /styles/colors.php file
2572 *
2573 * @param string $theme Theme id ( folder name ) e.g. 'classic'
2574 *
2575 * @return array
2576 *
2577 **@since 1.0.0
2578 *
2579 */
2580 function find_styles( $theme ) {
2581 $colors = [];
2582 $color_file = WPFORO_THEME_DIR . '/' . $theme . '/styles/colors.php';
2583 if( file_exists( $color_file ) ) {
2584 include( $color_file );
2585 }
2586
2587 return $colors;
2588 }
2589
2590 /**
2591 *
2592 * Scans certain theme directory and returns all information in array ( theme header, layouts, styles ).
2593 *
2594 * @param string $theme_file Theme folder name or main css file base path ( 'classic' OR classic/style.css' )
2595 *
2596 * @return array
2597 *
2598 **@since 1.0.0
2599 *
2600 */
2601 function find_theme( $theme_file ) {
2602 $theme = [];
2603 $theme_file = trim( trim( (string) $theme_file, '/' ) );
2604
2605 if( preg_match( '|\.\w{2,4}$|i', (string) $theme_file ) ) {
2606 $theme_folder = trim( basename( dirname( (string) $theme_file ) ), '/' );
2607 } else {
2608 $theme_folder = $theme_file;
2609 $theme_file = $theme_file . '/style.css';
2610 }
2611
2612 if( ! is_readable( WPFORO_THEME_DIR . '/' . $theme_file ) ) {
2613 $theme['error'] = __( 'Theme file not readable', 'wpforo' ) . ' (' . $theme_file . ')';
2614 } else {
2615 $theme_data = $this->find_theme_headers( WPFORO_THEME_DIR . '/' . $theme_file );
2616 $theme['id'] = $theme_folder;
2617 $theme['name'] = $theme_data['name']['value'];
2618 $theme['version'] = $theme_data['version']['value'];
2619 $theme['description'] = $theme_data['description']['value'];
2620 $theme['author'] = $theme_data['author']['value'];
2621 $theme['url'] = $theme_data['theme_url']['value'];
2622 $theme['file'] = $theme_file;
2623 $theme['folder'] = $theme_folder;
2624 $theme['layouts'] = $this->find_layouts( $theme_folder );
2625 $styles = $this->find_styles( $theme_folder );
2626 if( ! empty( $styles ) ) {
2627 reset( $styles );
2628 $theme['style'] = key( $styles );
2629 $theme['styles'] = $styles;
2630 }
2631 }
2632
2633 return $theme;
2634 }
2635
2636 /**
2637 *
2638 * Scans wpForo themes (wpf-themes) folder, reads main files' headers and returns information about all themes in array.
2639 * This function can also be used to scan and get information about layouts in each theme /layouts/ folder.
2640 *
2641 * @param string $base_dir Absolute path to scan directory (e.g. /home/public_html/wp-content/plugins/wpforo/themes/)
2642 * @param string $ext File extension which may contain header information
2643 * @param string $mode 'theme' or 'layout'
2644 *
2645 * @return array
2646 *
2647 **@since 1.0.0
2648 *
2649 */
2650 function find_themes( $base_dir = '', $ext = 'css', $mode = 'theme' ) {
2651 $themes = [];
2652 $themes_dir = @opendir( WPFORO_THEME_DIR . $base_dir );
2653 $theme_files = [];
2654 if( $themes_dir ) {
2655 while( ( $file = readdir( $themes_dir ) ) !== false ) {
2656 if( substr( (string) $file, 0, 1 ) == '.' ) continue;
2657 if( is_dir( WPFORO_THEME_DIR . $base_dir . '/' . $file ) ) {
2658 $themes_subdir = @opendir( WPFORO_THEME_DIR . $base_dir . '/' . $file );
2659 if( $themes_subdir ) {
2660 while( ( $subfile = readdir( $themes_subdir ) ) !== false ) {
2661 if( substr( (string) $subfile, 0, 1 ) == '.' ) continue;
2662 if( substr( (string) $subfile, - 4 ) == '.' . $ext ) $theme_files[] = "$file/$subfile";
2663 }
2664 closedir( $themes_subdir );
2665 }
2666 } else {
2667 if( substr( (string) $file, - 4 ) == '.' . $ext ) $theme_files[] = $file;
2668 }
2669 }
2670 closedir( $themes_dir );
2671 }
2672 if( empty( $theme_files ) ) return $themes;
2673 foreach( $theme_files as $theme_file ) {
2674 if( ! is_readable( WPFORO_THEME_DIR . $base_dir . '/' . $theme_file ) ) continue;
2675 if( $mode === 'theme' ) {
2676 $theme_data = $this->find_theme_headers( WPFORO_THEME_DIR . $base_dir . '/' . $theme_file );
2677 } elseif( $mode === 'layout' ) {
2678 $theme_data = $this->find_layout_headers( WPFORO_THEME_DIR . $base_dir . '/' . $theme_file );
2679 }
2680 if( empty( $theme_data['name']['value'] ) ) continue;
2681 $themes[ wpforo_clear_basename( $theme_file ) ] = $theme_data;
2682 }
2683
2684 return $themes;
2685 }
2686
2687 /**
2688 *
2689 * Reads theme main file's header variables and returns information in array.
2690 *
2691 * @param string $file Absolute path to file (e.g. /home/public_html/wp-content/plugins/wpforo/themes/style.css)
2692 *
2693 * @return array
2694 *
2695 **@since 1.0.0
2696 *
2697 */
2698 function find_theme_headers( $file ) {
2699 $theme_headers = [];
2700 $headers = [
2701 'name' => 'Theme Name',
2702 'version' => 'Version',
2703 'description' => 'Description',
2704 'author' => 'Author',
2705 'theme_url' => 'Theme URI',
2706 ];
2707 $fp = fopen( $file, 'r' );
2708 $data = fread( $fp, 8192 );
2709 fclose( $fp );
2710 $data = str_replace( "\r", "\n", $data );
2711 foreach( $headers as $header_key => $header_name ) {
2712 $theme_headers[ $header_key ]['name'] = $header_name;
2713 if( preg_match( '|^[\s\t/*#@]*' . preg_quote( $header_name, '|' ) . ':(.*)$|mi', (string) $data, $match ) && $match[1] ) {
2714 $theme_headers[ $header_key ]['value'] = trim( preg_replace( "/\s*(?:\*\/|\?>).*/", '', $match[1] ) );
2715 } else {
2716 $theme_headers[ $header_key ]['value'] = '';
2717 }
2718 }
2719 $theme_headers['file']['name'] = 'file';
2720 $theme_headers['file']['value'] = $file;
2721
2722 return $theme_headers;
2723 }
2724
2725 /**
2726 *
2727 * Reads layout main file's header variables and returns information in array.
2728 *
2729 * @param string $file Absolute path to file (e.g. /home/public_html/wp-content/plugins/wpforo/themes/layouts/1/forum.php)
2730 *
2731 * @return array
2732 *
2733 **@since 1.0.0
2734 *
2735 */
2736 function find_layout_headers( $file ) {
2737 $theme_headers = [];
2738 $headers = [
2739 'name' => 'layout',
2740 'version' => 'version',
2741 'description' => 'description',
2742 'author' => 'author',
2743 'layout_url' => 'url',
2744 ];
2745 $fp = fopen( $file, 'r' );
2746 $data = fread( $fp, 8192 );
2747 fclose( $fp );
2748 $data = str_replace( "\r", "\n", $data );
2749 foreach( $headers as $header_key => $header_name ) {
2750 $theme_headers[ $header_key ]['name'] = $header_name;
2751 if( preg_match( '|^[\s\t/*#@]*' . preg_quote( $header_name, '|' ) . ':(.*)$|mi', (string) $data, $match ) && $match[1] ) {
2752 $theme_headers[ $header_key ]['value'] = trim( preg_replace( "/\s*(?:\*\/|\?>).*/", '', $match[1] ) );
2753 } else {
2754 $theme_headers[ $header_key ]['value'] = '';
2755 }
2756 }
2757 $theme_headers['file']['name'] = 'file';
2758 $theme_headers['file']['value'] = trim( str_replace( WPFORO_THEME_DIR, '', (string) $file ), '/' );
2759
2760 return $theme_headers;
2761 }
2762
2763 public function theme_exists( $theme ) {
2764 $_theme = $this->find_theme( $theme );
2765
2766 return ! wpfkey( $_theme, 'error' );
2767 }
2768
2769 public function copyright() {
2770 if( wpforo_setting( 'components', 'copyright' ) ): ?>
2771 <div id="wpforo-poweredby">
2772 <p class="wpf-by">
2773 <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>
2774 </p>
2775 </div>
2776 <?php
2777 endif;
2778 }
2779
2780 public function member_error() {
2781 echo apply_filters( 'wpforo_member_error_filter', wpforo_phrase( 'Members not found', false ) );
2782 }
2783
2784 public function ajx_active_tab_content() {
2785 wpforo_verify_nonce( 'wpforo_active_tab_content_ajax' );
2786 if( ! empty( $_POST['active_tab_id'] ) ) {
2787 $active_tab_id = sanitize_textarea_field( $_POST['active_tab_id'] );
2788 switch( $active_tab_id ) {
2789 case 'topic_merge_form':
2790 $this->topic_merge_form();
2791 exit();
2792 case 'reply_move_form':
2793 $this->reply_move_form();
2794 exit();
2795 case 'topic_split_form':
2796 $this->topic_split_form();
2797 exit();
2798 case 'topic_move_form':
2799 $this->topic_move_form();
2800 exit();
2801 }
2802 }
2803 echo 0;
2804 exit();
2805 }
2806
2807 public function add_footer_html() {
2808 $this->dialog();
2809 if( WPF()->current_object['template'] === 'post' ) $this->report_form();
2810 $this->notifications_bar();
2811 }
2812
2813 public function posts_ordering_dropdown( $orderby = null, $topicid = null ) {
2814 if( is_null( $topicid ) ) $topicid = wpforo_bigintval( wpfval( WPF()->current_object, 'topicid' ) );
2815 if( $topicid && $topic_url = wpforo_topic( $topicid, 'url' ) ) {
2816 if( is_null( $orderby ) ) $orderby = WPF()->current_object['orderby'];
2817 ?>
2818 <label>
2819 <select onchange="window.location.assign('?orderby=' + this.value)">
2820 <option value="votes" <?php wpfo_check( $orderby, 'votes', 'selected' ) ?>>
2821 <?php wpforo_phrase( 'Most Voted' ) ?>
2822 </option>
2823 <option value="oldest" <?php wpfo_check( $orderby, 'oldest', 'selected' ) ?>>
2824 <?php wpforo_phrase( 'Oldest' ) ?>
2825 </option>
2826 <option value="newest" <?php wpfo_check( $orderby, 'newest', 'selected' ) ?>>
2827 <?php wpforo_phrase( 'Newest' ) ?>
2828 </option>
2829 </select>
2830 </label>
2831
2832 <?php
2833 }
2834 }
2835
2836 public function editor_buttons( $editor = 'post' ) {
2837 global $wp_styles;
2838 if( ! empty( $wp_styles ) && ( $fa = wpfval( $wp_styles->registered, 'wpforo-font-awesome' ) ) && ( $fa_rtl = wpfval( $wp_styles->registered, 'wpforo-font-awesome-rtl' ) ) ) {
2839 $content_css = $fa->src . ( is_rtl() ? ',' . $fa_rtl->src : '' );
2840 } else {
2841 $content_css = '';
2842 }
2843 $settings = [
2844 'topic' => [
2845 'media_buttons' => false,
2846 'textarea_name' => 'topic[body]',
2847 'textarea_rows' => get_option( 'default_post_edit_rows', 20 ),// rows = "..."
2848 'tabindex' => '',
2849 'editor_height' => 180,
2850 'editor_css' => '',
2851 'editor_class' => '',
2852 'teeny' => false,
2853 'dfw' => false,
2854 'tinymce' => [
2855 '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',
2856 'toolbar2' => '',
2857 'toolbar3' => '',
2858 'toolbar4' => '',
2859 '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;}',
2860 'object_resizing' => false,
2861 'autoresize_on_init' => true,
2862 'wp_autoresize_on' => true,
2863 'wp_keep_scroll_position' => true,
2864 'indent' => true,
2865 'add_unload_trigger' => false,
2866 'wpautop' => false,
2867 'setup' => 'wpforo_tinymce_setup',
2868 'content_css' => $content_css,
2869 'extended_valid_elements' => 'i[class|style],span[class|style]',
2870 'custom_elements' => '',
2871 ],
2872 'quicktags' => false,
2873 'default_editor' => 'tinymce',
2874 ],
2875 'post' => [
2876 'media_buttons' => false,
2877 'textarea_name' => 'post[body]',
2878 'textarea_rows' => get_option( 'default_post_edit_rows', 5 ),
2879 'editor_class' => 'wpeditor',
2880 'teeny' => false,
2881 'dfw' => false,
2882 'editor_height' => 150,
2883 'tinymce' => [
2884 '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',
2885 'toolbar2' => '',
2886 'toolbar3' => '',
2887 'toolbar4' => '',
2888 '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;}',
2889 'object_resizing' => false,
2890 'autoresize_on_init' => true,
2891 'wp_autoresize_on' => true,
2892 'wp_keep_scroll_position' => true,
2893 'indent' => true,
2894 'add_unload_trigger' => false,
2895 'wpautop' => false,
2896 'setup' => 'wpforo_tinymce_setup',
2897 'content_css' => $content_css,
2898 'extended_valid_elements' => 'i[class|style],span[class|style]',
2899 'custom_elements' => '',
2900 ],
2901 'quicktags' => false,
2902 'default_editor' => 'tinymce',
2903 ],
2904 ];
2905
2906 return apply_filters( 'wpforo_editor_settings', array_merge( $this->default->editor_settings, $settings[ $editor ] ), $editor );
2907 }
2908
2909 public function editor_settings_required_params( $settings ) {
2910 if( ! wpfkey( $settings, 'tinymce' ) ) $settings['tinymce'] = [];
2911 $settings['tinymce']['setup'] = 'wpforo_tinymce_setup';
2912
2913 if( is_rtl() ) {
2914 $settings['tinymce']['rtl_ui'] = true;
2915 $settings['plugins'] .= ',directionality';
2916 $settings['tinymce']['toolbar1'] .= ',ltr';
2917 $settings['tinymce']['directionality'] = 'rtl';
2918
2919 $settings['plugins'] = trim( (string) $settings['plugins'], ',' );
2920 $settings['tinymce']['toolbar1'] = trim( (string) $settings['tinymce']['toolbar1'], ',' );
2921 }
2922
2923 // Ensure <figure> tags allowed and alignment styles present
2924 $settings['tinymce']['extended_valid_elements'] = trim( (string) wpfval( $settings['tinymce'], 'extended_valid_elements' ) . ',figure[class|contenteditable|style|data*]', ',' );
2925 $settings['tinymce']['content_style'] .= 'figure.alignleft { float: left; }';
2926 $settings['tinymce']['content_style'] .= 'figure.aligncenter { clear: both; display: block; }';
2927 $settings['tinymce']['content_style'] .= 'figure.aligncenter a, figure.aligncenter img { display: block; margin-left: auto; margin-right: auto; }';
2928 $settings['tinymce']['content_style'] .= 'figure.alignright { float: right; }';
2929
2930 return $settings;
2931 }
2932
2933 public function add_topic_button( $forumid = null ) {
2934 $phrase = ( WPF()->forum->get_layout( $forumid ) === 3 ? wpforo_phrase( 'Ask a Question', false ) : wpforo_phrase( 'Add Topic', false ) );
2935 if( WPF()->current_object['template'] === 'forum' ) :
2936 if( wpforo_forum_list_need_add_topic_button( $forumid ) ) :
2937 if( WPF()->perm->forum_can( 'ct', $forumid ) ) : WPF()->current_object['load_tinymce'] = true; ?>
2938 <div class="wpf-head-bar-right">
2939 <button class="wpf-button add_wpftopic" data-phrase="<?php echo $phrase ?>">
2940 <i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span>
2941 </button>
2942 </div>
2943 <?php elseif( WPF()->current_user_groupid === 4 ) : ?>
2944 <div class="wpf-head-bar-right">
2945 <a href="<?php echo wpforo_login_url() ?>" class="wpf-button"><i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span></a>
2946 </div>
2947 <?php endif;
2948 endif;
2949 else :
2950 if( WPF()->perm->forum_can( 'ct', $forumid ) ): ?>
2951 <button id="add_wpftopic" class="wpf-button" data-phrase="<?php echo $phrase ?>">
2952 <i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span>
2953 </button>
2954 <?php elseif( WPF()->current_user_groupid === 4 ) : ?>
2955 <a href="<?php echo wpforo_login_url() ?>" class="wpf-button"><i class="fas fa-feather-alt"></i> <span><?php echo $phrase ?></span></a>
2956 <?php endif;
2957 endif;
2958 }
2959
2960 private function notifications_bar() {
2961 echo '<div id="wpforo-notifications-bar">';
2962 $this->spinner();
2963 if( apply_filters( 'wpforo_message_bubble', true ) ) $this->msg_box();
2964 echo '</div>';
2965 }
2966
2967 private function msg_box() { ?>
2968 <div id="wpf-msg-box"></div>
2969 <?php
2970 }
2971
2972 private function spinner() { ?>
2973 <div id="wpforo-load" class="wpforo-load">
2974 <div class="wpf-load-ico-wrap"><i class="fas fa-3x fa-spinner fa-spin"></i></div>
2975 <div class="wpf-load-txt-wrap"><span class="loadtext"></span></div>
2976 </div>
2977 <?php
2978 }
2979
2980 private function dialog() { ?>
2981 <div id="wpforo-dialog-extra-wrap">
2982 <div id="wpforo-dialog-wrap">
2983 <div id="wpforo-dialog">
2984 <div id="wpforo-dialog-header">
2985 <strong id="wpforo-dialog-title"></strong>
2986 <i id="wpforo-dialog-close" class="fas fa-window-close fa-2x"></i>
2987 </div>
2988 <div id="wpforo-dialog-body"></div>
2989 </div>
2990 </div>
2991 <div id="wpforo-dialog-backups"></div>
2992 </div>
2993 <?php
2994 }
2995
2996 private function report_form() { ?>
2997 <form id="wpforo-report" data-title="<?php echo esc_attr( wpforo_phrase( 'Report to Administration', false ) ) ?>">
2998 <input type="hidden" id="wpforo-report-postid">
2999 <label for="wpforo-report-content"></label><textarea id="wpforo-report-content" required placeholder="<?php esc_attr( wpforo_phrase( 'Write message' ) ) ?>"></textarea>
3000 <input id="wpforo-report-send" type="button" value="<?php wpforo_phrase( 'Send Report' ) ?>" title="Ctrl+Enter">
3001 </form>
3002 <?php
3003 }
3004
3005 public function do_spoilers( $text ) {
3006 $text = preg_replace(
3007 '#(?:<(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',
3008 '<div class="wpf-spoiler-wrap"><div class="wpf-spoiler-head"><i class="wpf-spoiler-chevron-name">' . wpforo_phrase(
3009 'Spoiler',
3010 false
3011 ) . '</i><i class="wpf-spoiler-chevron fas fa-chevron-down"></i><div class="wpf-spoiler-title">$2</div></div><div class="wpf-spoiler-body">',
3012 (string) $text,
3013 - 1,
3014 $count1
3015 );
3016 $text = preg_replace(
3017 '#\[[\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',
3018 '<div class="wpf-spoiler-wrap"><div class="wpf-spoiler-head"><i class="wpf-spoiler-chevron-name">' . wpforo_phrase(
3019 'Spoiler',
3020 false
3021 ) . '</i><i class="wpf-spoiler-chevron fas fa-chevron-down"></i><div class="wpf-spoiler-title">$1</div></div><div class="wpf-spoiler-body">',
3022 (string) $text,
3023 - 1,
3024 $count2
3025 );
3026 $text = preg_replace(
3027 '#(?:<(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',
3028 '</div></div>',
3029 (string) $text,
3030 $count1
3031 );
3032
3033 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 );
3034 }
3035
3036 public function apply_quotes( $text ) {
3037 $text = preg_replace_callback( '#\[quote(\s[^\[\]]+|\s?)?]#iu', function( $m ) {
3038 $userid = 0;
3039 $postid = 0;
3040 $mention = '';
3041 $posted_by = '';
3042 if( preg_match( '#data-userid=[\'"](\d+)[\'"]#iu', $m[1], $u ) ) $userid = wpforo_bigintval( $u[1] );
3043 if( preg_match( '#data-postid=[\'"](\d+)[\'"]#iu', $m[1], $p ) ) $postid = wpforo_bigintval( $p[1] );
3044
3045 if( $userid ) {
3046 $profiles_mention_nicknames = wpforo_setting( 'profiles', 'mention_nicknames' );
3047 $posted_by = $mention = trim( (string) ( $profiles_mention_nicknames ? wpforo_member( $userid, 'user_nicename' ) : wpforo_member( $userid, 'display_name' ) ) );
3048 if( $profiles_mention_nicknames ) $posted_by = '@' . $posted_by;
3049 }
3050
3051 return sprintf(
3052 '<blockquote data-userid="%1$d" data-postid="%2$d" data-mention="%3$s"><div class="wpforo-post-quote-head">%4$s %5$s</div>',
3053 $userid,
3054 $postid,
3055 $mention,
3056 ( $posted_by ? sprintf( '<div class="wpforo-post-quote-author"><strong> %1$s: %2$s </strong></div>', wpforo_phrase( 'Posted by', false ), $posted_by ) : '' ),
3057 ( $postid ? sprintf(
3058 '<div class="wpforo-post-quote-link"><a href="%1$s" title="%2$s">&uarr;</a></div>',
3059 WPF()->post->get_url( $postid ),
3060 wpforo_phrase( 'go to original post', false )
3061 ) : '' )
3062 );
3063 }, (string) $text );
3064
3065 return preg_replace( '#\[/quote]#iu', '</blockquote>', (string) $text );
3066 }
3067
3068 public function please_login() {
3069 if( ! wpforo_is_bot() ) {
3070 $html = sprintf(
3071 '<div class="wpf-please-login">%1$s %2$s</div>',
3072 wpforo_get_login_or_register_notice_text(),
3073 wpforo_phrase( 'to reply to this topic.', false, 'lower' )
3074 );
3075 echo apply_filters( 'wpforo_login_message_in_topic', $html );
3076 }
3077 }
3078
3079 public function profile_board_panel( $user = [], $template = '', $active_boardid = null ) {
3080 if( ! is_wpforo_multiboard() ) return '';
3081 if( is_numeric( $user ) ) $user = WPF()->member->get_member( $user );
3082 if( ! $user ) $user = WPF()->current_object['user'];
3083 if( ! $template ) $template = WPF()->current_object['template'];
3084 if( is_null( $active_boardid ) ) $active_boardid = ( wpfkey( WPF()->GET, 'boardid' ) ? (int) WPF()->GET['boardid'] : WPF()->board->get_current( 'boardid' ) );
3085 $links = '';
3086 $base_profile_url = remove_query_arg( 'boardid', WPF()->member->get_profile_url( $user, $template ) );
3087 foreach( WPF()->board->get_boards( [ 'status' => true ] ) as $board ) {
3088 if( $template === 'subscriptions' && ! wpforo_is_module_enabled( 'subscriptions', $board ) ) continue;
3089 $links .= sprintf(
3090 '<span class="wpf-member-template-link wpf-ajax-link %1$s"><a href="%2$s" title="%3$s">%4$s</a></span>',
3091 ( $active_boardid === $board['boardid'] ? 'wpf-active' : '' ),
3092 add_query_arg( 'boardid', $board['boardid'], $base_profile_url ),
3093 $board['title'],
3094 wpforo_text( $board['title'], 10, false )
3095 );
3096 }
3097
3098 return sprintf(
3099 '<div class="wpf-board-panel">
3100 <div class="wpf-board-panel-left"><span>%1$s</span></div>
3101 <div class="wpf-board-panel-right">%2$s</div>
3102 </div>',
3103 wpforo_phrase( 'Board', false ),
3104 $links
3105 );
3106 }
3107
3108 public function profile_activity_panel( $user = [], $boardid = null, $active_filter = '' ) {
3109 if( is_numeric( $user ) ) $user = WPF()->member->get_member( $user );
3110 if( ! $user ) $user = WPF()->current_object['user'];
3111 if( is_null( $boardid ) ) $boardid = wpfkey( WPF()->GET, 'boardid' ) ? (int) WPF()->GET['boardid'] : WPF()->board->get_current( 'boardid' );
3112 if( ! $active_filter ) $active_filter = (string) wpfval( WPF()->GET, 'filter' );
3113 WPF()->change_board( $boardid );
3114 $filters = [
3115 '' => wpforo_phrase( 'All', false ),
3116 'topics' => wpforo_phrase( 'Topics', false ),
3117 'replies' => wpforo_phrase( 'Replies', false ),
3118 ];
3119 $links = '';
3120 foreach( $filters as $filter => $label ) {
3121 $links .= sprintf(
3122 '<span class="wpf-member-template-link wpf-ajax-link %1$s"><a href="%2$s" rel="nofollow">%3$s</a></span>',
3123 ( $active_filter === $filter ? 'wpf-active' : '' ),
3124 WPF()->member->get_activity_url( $filter, $boardid, $user ),
3125 $label
3126 );
3127 }
3128
3129 $topics = WPF()->topic->get_count( [ 'userid' => $user['userid'], 'status' => 0, 'private' => '0' ] );
3130 $posts = WPF()->post->get_count( [ 'userid' => $user['userid'], 'status' => 0, 'private' => '0' ] );
3131
3132 return sprintf(
3133 '<div class="wpf-activity-panel">
3134 <div class="wpf-activity-panel-left">
3135 <span>%1$s</span>
3136 <span>/</span>
3137 <span>%2$s</span>
3138 </div>
3139 <div class="wpf-activity-panel-right">%3$s</div>
3140 </div>',
3141 wpforo_phrase( 'Topics', false ) . ': ' . $topics,
3142 wpforo_phrase( 'Replies', false ) . ': ' . ( $posts - $topics ),
3143 $links
3144 );
3145 }
3146
3147 public function profile_favored_panel( $user = [], $boardid = null, $active_filter = '' ) {
3148 if( is_numeric( $user ) ) $user = WPF()->member->get_member( $user );
3149 if( ! $user ) $user = WPF()->current_object['user'];
3150 if( is_null( $boardid ) ) $boardid = wpfkey( WPF()->GET, 'boardid' ) ? (int) WPF()->GET['boardid'] : WPF()->board->get_current( 'boardid' );
3151 if( ! $active_filter ) $active_filter = (string) wpfval( WPF()->current_object, 'filter' );
3152 $filters = [
3153 'bookmarks' => wpforo_phrase( 'Bookmarks', false ),
3154 'likes' => wpforo_phrase( 'Likes', false ),
3155 'dislikes' => wpforo_phrase( 'Dislikes', false ),
3156 ];
3157 $links = '';
3158 foreach( $filters as $filter => $label ) {
3159 $links .= sprintf(
3160 '<span class="wpf-member-template-link wpf-ajax-link %1$s"><a href="%2$s" rel="nofollow">%3$s</a></span>',
3161 ( $active_filter === $filter ? 'wpf-active' : '' ),
3162 WPF()->member->get_favored_url( $filter, $boardid, $user ),
3163 $label
3164 );
3165 }
3166
3167 return sprintf(
3168 '<div class="wpf-activity-panel">
3169 <div class="wpf-activity-panel-left">
3170 <span>%1$s</span>
3171 </div>
3172 <div class="wpf-activity-panel-right">%2$s</div>
3173 </div>',
3174 wpforo_phrase( 'Total Posts', false ) . ': ' . WPF()->current_object['items_count'],
3175 $links
3176 );
3177 }
3178
3179 private function cantlogin_page() {
3180 $contact_form_phrase = ( wpforo_setting( 'authorization', 'manually_approval_contact_form' ) ) ? wpforo_phrase(
3181 'Please use the contact form below if you want to contact the website administrator.',
3182 false
3183 ) : '';
3184 $html = sprintf(
3185 '<div class="wpflm-text">%1$s %2$s</div>',
3186 wpforo_phrase( 'You have been automatically signed out from the website. Your account is awaiting approval.', false ),
3187 $contact_form_phrase
3188 );
3189 if( wpforo_setting( 'authorization', 'manually_approval_contact_form' ) ) {
3190 $html .= sprintf(
3191 '<div class="wpflm-form"><form method="POST" action="%1$s">
3192 <input type="hidden" name="wpfaction" value="cantlogin_contact">
3193 <input type="hidden" name="user_login" value="%2$s">
3194 <textarea name="msg" placeholder="%3$s"></textarea>
3195 <input type="submit" value="%4$s">
3196 </form></div>',
3197 wpforo_login_url(),
3198 WPF()->ram_cache->get( 'USER_LOGIN_REFERER' ),
3199 wpforo_phrase( 'Your message to the website administrator...', false ),
3200 wpforo_phrase( 'Send', false )
3201 );
3202 }
3203
3204 return '<div class="wpf-logout-message">' . apply_filters( 'wpforo_logout_message', $html ) . '</div>';
3205 }
3206
3207 public function change_cover_button( $user ) {
3208 if( WPF()->usergroup->can( 'upc' ) && WPF()->perm->user_can_edit_account( $user ) ) {
3209 return sprintf(
3210 '<div class="wpf-edit-cover" title="%1$s">
3211 <i class="fas fa-images" data-action="editcover"></i>
3212 <ul class="wpf-edit-cover-options">
3213 <li class="wpf-upload-cover"><i class="fas fa-upload"></i> %2$s</li>
3214 <li class="wpf-delete-cover"><i class="fas fa-rotate-left"></i> %3$s</li>
3215 </ul>
3216 </div>',
3217 wpforo_phrase( 'Change Cover Image', false ),
3218 wpforo_phrase( 'Upload New Cover', false ),
3219 wpforo_phrase( 'Reset to Default', false )
3220 );
3221 }
3222
3223 return '';
3224 }
3225
3226 }
3227