PluginProbe
wpForo Forum / 2.4.2
wpForo Forum v2.4.2
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / classes / Template.php

Template.php in wpForo Forum 2.4.2, at classes/Template.php

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