Changeset 3439073
- Timestamp:
- 01/14/2026 12:42:59 AM (5 hours ago)
- Location:
- website-toolbox-forums
- Files:
-
- 32 added
- 10 edited
-
tags/2.1.2 (added)
-
tags/2.1.2/admin (added)
-
tags/2.1.2/admin/admin.php (added)
-
tags/2.1.2/admin/css (added)
-
tags/2.1.2/admin/css/sidebar.css (added)
-
tags/2.1.2/admin/css/websitetoolbox.css (added)
-
tags/2.1.2/admin/images (added)
-
tags/2.1.2/admin/images/chat_icon.svg (added)
-
tags/2.1.2/admin/images/embedComments.png (added)
-
tags/2.1.2/admin/js (added)
-
tags/2.1.2/admin/js/websitetoolbox.js (added)
-
tags/2.1.2/admin/logs.php (added)
-
tags/2.1.2/admin/sidebar.js (added)
-
tags/2.1.2/admin/websitetoolbox_sidebar.php (added)
-
tags/2.1.2/core (added)
-
tags/2.1.2/core/client-info.js (added)
-
tags/2.1.2/core/events.php (added)
-
tags/2.1.2/core/logger.php (added)
-
tags/2.1.2/docs (added)
-
tags/2.1.2/docs/LOGGING_DOCUMENTATION.md (added)
-
tags/2.1.2/forumHook.php (added)
-
tags/2.1.2/img (added)
-
tags/2.1.2/img/wp-settingpage.png (added)
-
tags/2.1.2/readme.txt (added)
-
tags/2.1.2/uninstall.php (added)
-
tags/2.1.2/websitetoolbox.php (added)
-
tags/2.1.2/wt_forum_include.php (added)
-
trunk/admin/admin.php (modified) (30 diffs)
-
trunk/admin/css/websitetoolbox.css (modified) (1 diff)
-
trunk/admin/js/websitetoolbox.js (modified) (2 diffs)
-
trunk/admin/logs.php (added)
-
trunk/admin/websitetoolbox_sidebar.php (modified) (8 diffs)
-
trunk/core/client-info.js (added)
-
trunk/core/events.php (modified) (2 diffs)
-
trunk/core/logger.php (added)
-
trunk/docs (added)
-
trunk/docs/LOGGING_DOCUMENTATION.md (added)
-
trunk/forumHook.php (modified) (5 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/uninstall.php (modified) (2 diffs)
-
trunk/websitetoolbox.php (modified) (23 diffs)
-
trunk/wt_forum_include.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
website-toolbox-forums/trunk/admin/admin.php
r3395282 r3439073 4 4 */ 5 5 namespace WebsiteToolboxAdmin; 6 7 // If this file is called directly, abort. 8 if ( ! defined( 'ABSPATH' ) ) { 9 exit; 10 } 11 6 12 use WebsiteToolboxForum; 7 13 use WebsiteToolboxForum\globalVariables; … … 160 166 ); 161 167 wp_update_post($wtbPostData); 168 169 // Log embed page deactivation 170 \WebsiteToolboxLogger\Logger::info('PAGE_DEACTIVATE', 'Embed page set to draft during plugin deactivation', array( 171 'page_id' => $websitetoolboxpage_id, 172 'page_title' => $wtbPost->post_title, 173 'previous_status' => $wtbPost->post_status 174 )); 162 175 } 163 176 } … … 165 178 if(get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_username")){ 166 179 httpRequestForUninstallReinstallPlugin('uninstallPlugin'); 167 } 180 } 168 181 } 169 182 … … 183 196 $my_post['post_title'] = WebsiteToolboxForum\globalVariables::$PAGENAME; 184 197 } 198 199 // Check if a page with the same title already exists (before creating new one) 200 if ($my_post['post_title'] == WebsiteToolboxForum\globalVariables::$PAGENAME) { 201 // Use WP_Query for exact title matching (replaces deprecated get_page_by_title) 202 $query = new \WP_Query(array( 203 'post_type' => 'page', 204 'title' => $my_post['post_title'], 205 'posts_per_page' => 1, 206 'no_found_rows' => true, 207 'ignore_sticky_posts' => true, 208 'fields' => 'ids' 209 )); 210 211 $existingPage = null; 212 if ($query->have_posts()) { 213 $pageId = $query->posts[0]; 214 $existingPage = get_post($pageId); 215 } 216 wp_reset_postdata(); 217 218 if ($existingPage && $existingPage->ID != $forumPostId) { 219 // Log when another page with the same title exists 220 \WebsiteToolboxLogger\Logger::warning('PAGE_DUPLICATE', 'There is another page that exists with the same title "' . $my_post['post_title'] . '" on the website', array( 221 'existing_page_id' => $existingPage->ID, 222 'existing_page_title' => $existingPage->post_title, 223 'existing_page_url' => get_permalink($existingPage->ID), 224 'existing_page_status' => $existingPage->post_status, 225 'new_page_title' => $my_post['post_title'] 226 )); 227 } 228 } 229 185 230 $my_post['post_content'] = "Please go to the admin section and change your Website Toolbox Forum settings."; 186 231 $my_post['post_status'] = 'publish'; … … 191 236 $my_post['ping_status'] = 'closed'; 192 237 $postId = wp_insert_post( $my_post ); 238 239 // Log new embed page creation 240 if ($postId && !is_wp_error($postId)) { 241 $logContext = array( 242 'page_id' => $postId, 243 'page_title' => $my_post['post_title'], 244 'created_by' => 'plugin', 245 'page_link' => get_permalink($postId) 246 ); 247 248 // Check if another page with "Forum" title exists after creation 249 if ($my_post['post_title'] == WebsiteToolboxForum\globalVariables::$PAGENAME) { 250 // Use WP_Query for exact title matching (replaces deprecated get_page_by_title) 251 $query = new \WP_Query(array( 252 'post_type' => 'page', 253 'title' => $my_post['post_title'], 254 'posts_per_page' => 1, 255 'no_found_rows' => true, 256 'ignore_sticky_posts' => true, 257 'fields' => 'ids' 258 )); 259 260 $existingPage = null; 261 if ($query->have_posts()) { 262 $pageId = $query->posts[0]; 263 $existingPage = get_post($pageId); 264 } 265 wp_reset_postdata(); 266 267 // Check if found page is different from the one we just created 268 if ($existingPage && $existingPage->ID != $postId) { 269 $logContext['message'] = '"/forum" link already exists on the website'; 270 } 271 } 272 273 \WebsiteToolboxLogger\Logger::info('PAGE_CREATE', 'New embed page created via plugin', $logContext); 274 } else { 275 \WebsiteToolboxLogger\Logger::error('PAGE_CREATE', 'Failed to create embed page via plugin', \WebsiteToolboxLogger\Logger::sanitizeLogData(array( 276 'error' => is_wp_error($postId) ? $postId->get_error_message() : 'Unknown error' 277 ))); 278 } 279 193 280 return $postId; 194 281 } … … 198 285 Return: None */ 199 286 function showForumDashboardMenu() { 200 $wtbMenuName = 'Website Toolbox Forum'; 287 $iconUrl = 'data:image/svg+xml;base64,PHN2ZyBpZD0ibG9nb18xXyIgZGF0YS1uYW1lPSJsb2dvICgxKSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjMuMDI2IiBoZWlnaHQ9IjIzLjAyMyIgdmlld0JveD0iMCAwIDIzLjAyNiAyMy4wMjMiPgogIDxnIGlkPSJHcm91cF84MCIgZGF0YS1uYW1lPSJHcm91cCA4MCI+CiAgICA8ZyBpZD0iR3JvdXBfNzkiIGRhdGEtbmFtZT0iR3JvdXAgNzkiPgogICAgICA8cGF0aCBpZD0iUGF0aF82NiIgZGF0YS1uYW1lPSJQYXRoIDY2IiBkPSJNMjMuMDI0LDEzLjJhLjU3Ni41NzYsMCwwLDEtLjQyLjU0bC0yLjc3My40MmE4LjQ4OCw4LjQ4OCwwLDAsMS0uNTg1LDEuMzY0Yy41MS43MzQsMS4wNDksMS4zOTQsMS42LDIuMDY4YS41OTIuNTkyLDAsMCwxLC4xNS4zNzUuNS41LDAsMCwxLS4xMzUuMzQ1QzIwLjUsMTguOCwxOC40ODIsMjEsMTcuOTcyLDIxYS43NjMuNzYzLDAsMCwxLS4zOS0uMTM1bC0yLjA2OC0xLjYxOWE5LjAzNCw5LjAzNCwwLDAsMS0xLjM2NC41NywxOS41ODQsMTkuNTg0LDAsMCwxLS40MzUsMi43ODguNTUuNTUsMCwwLDEtLjU0LjQySDkuODQ4YS41MzcuNTM3LDAsMCwxLS41NC0uNDVsLS40Mi0yLjc1OGE4Ljg5Myw4Ljg5MywwLDAsMS0xLjM0OS0uNTU0bC0yLjExNCwxLjZBLjU3Ni41NzYsMCwwLDEsNS4wNSwyMWEuNTM3LjUzNywwLDAsMS0uMzc1LS4xNjVBMTguNjc1LDE4LjY3NSwwLDAsMSwyLjIsMTguMzE4YS41ODQuNTg0LDAsMCwxLS4xMDUtLjM0NS41NjYuNTY2LDAsMCwxLC4xMi0uMzQ1Yy41MS0uNjg5LDEuMDY0LTEuMzQ5LDEuNTc0LTIuMDUzYTcuOTQ5LDcuOTQ5LDAsMCwxLS42MTUtMS40ODRsLTIuNzQzLS40QS41NDkuNTQ5LDAsMCwxLDAsMTMuMTQ1VjkuODE4YS41ODEuNTgxLDAsMCwxLC40MDUtLjU0bDIuNzg4LS40MmE3LjkyNyw3LjkyNywwLDAsMSwuNTg1LTEuMzc5Yy0uNTEtLjcxOS0xLjA1LTEuMzk0LTEuNi0yLjA2OWEuNTU0LjU1NCwwLDAsMS0uMTUtLjM2QS41ODIuNTgyLDAsMCwxLDIuMTU5LDQuN2MuMzYtLjQ5NSwyLjM4My0yLjY4MywyLjg5My0yLjY4M2EuNjY3LjY2NywwLDAsMSwuMzkuMTVMNy41MSwzLjc3N2E5LjAzNCw5LjAzNCwwLDAsMSwxLjM2NC0uNTdBMTkuNTg0LDE5LjU4NCwwLDAsMSw5LjMwOS40MTkuNTQ3LjU0NywwLDAsMSw5Ljg0OCwwaDMuMzI4YS41MzcuNTM3LDAsMCwxLC41NC40NWwuNDIsMi43NThhOC44OTMsOC44OTMsMCwwLDEsMS4zNDkuNTU0bDIuMTI5LTEuNmEuNTExLjUxMSwwLDAsMSwuMzYtLjEzNS41OTIuNTkyLDAsMCwxLC4zNzUuMTUsMTguOSwxOC45LDAsMCwxLDIuNDczLDIuNTQ4LjUxMS41MTEsMCwwLDEsLjEuMzMuNTY2LjU2NiwwLDAsMS0uMTIuMzQ1Yy0uNTEuNjg5LTEuMDY0LDEuMzQ5LTEuNTc0LDIuMDUzYTguMjU0LDguMjU0LDAsMCwxLC42MTUsMS40NjlsMi43NDMuNDJhLjU0Ny41NDcsMCwwLDEsLjQzNS41NFYxMy4yWk0xMS41MTIsNy42NzRhMy44MzcsMy44MzcsMCwxLDAsMy44MzcsMy44MzdBMy44NDUsMy44NDUsMCwwLDAsMTEuNTEyLDcuNjc0WiIgZmlsbD0iY3VycmVudENvbG9yIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K'; 288 201 289 if(get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_username')) { 202 add_options_page( 'Website Toolbox', $wtbMenuName, 'manage_options', WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxUpdateOptions', 'WebsiteToolboxAdmin\\onForumUpdateSettings'); 203 $wtbMenuName = ''; 204 } 205 add_options_page( 'Website Toolbox', $wtbMenuName, 'manage_options', WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxoptions', 'WebsiteToolboxAdmin\\onForumDashboardLogin'); 290 // Add top-level menu 291 add_menu_page( 292 'Website Toolbox Forum', // Page title 293 'Website Toolbox', // Menu title 294 'manage_options', // Capability 295 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxUpdateOptions', // Menu slug 296 'WebsiteToolboxAdmin\\onForumUpdateSettings', // Callback function 297 $iconUrl, // Icon URL 298 81 299 ); 300 301 add_submenu_page( 302 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxUpdateOptions', // Parent slug 303 'Website Toolbox Forum Settings', // Page title 304 'Settings', // Menu title 305 'manage_options', // Capability 306 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxUpdateOptions', // Menu slug (same as parent) 307 'WebsiteToolboxAdmin\\onForumUpdateSettings' // Callback function 308 ); 309 } else { 310 add_menu_page( 311 'Website Toolbox Forum', // Page title 312 'Website Toolbox', // Menu title 313 'manage_options', // Capability 314 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxoptions', // Menu slug 315 'WebsiteToolboxAdmin\\onForumDashboardLogin', // Callback function 316 $iconUrl, // Icon URL 317 81 318 ); 319 320 // Rename the first submenu item to "Settings" 321 add_submenu_page( 322 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxoptions', // Parent slug 323 'Website Toolbox Forum', // Page title 324 'Settings', // Menu title 325 'manage_options', // Capability 326 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxoptions', // Menu slug (same as parent) 327 'WebsiteToolboxAdmin\\onForumDashboardLogin' // Callback function 328 ); 329 } 206 330 } 207 331 … … 286 410 $userRoles = array(); 287 411 if (!isset($wp_roles)){ 288 $wp_roles = new WP_Roles();412 $wp_roles = new \WP_Roles(); 289 413 } 290 414 $roles = $wp_roles->get_names(); … … 363 487 Return: Nothing */ 364 488 function forumSettingsPage($message = "") { 489 // Determine the correct page to submit to based on login status 490 $isLoggedIn = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_username'); 491 $submitPage = $isLoggedIn ? 'websitetoolboxUpdateOptions&change=1' : 'websitetoolboxoptions'; 492 493 // Build form action URL properly using WordPress functions 494 $formAction = admin_url('admin.php?page=' . WebsiteToolboxForum\globalVariables::$WTBPREFIX . $submitPage); 365 495 ?> 366 496 <!-- create a form in the wordpress admin panel --> 367 497 <div class="wrap"> 368 <form name="form_lol" action=" options-general.php?page=<?php echo esc_html((WebsiteToolboxForum\globalVariables::$WTBPREFIX)); ?>websitetoolboxoptions" method="POST" onsubmit="return ValidateForm();" class="custom-login-page"><?php498 <form name="form_lol" action="<?php echo esc_url($formAction); ?>" method="POST" onsubmit="return ValidateForm();" class="custom-login-page"><?php 369 499 dashboardLoginDescription(); 370 500 if($message == 'username' || $message == 'password') { 371 501 echo wp_kses("<div id='wtb-warning' class='error' style='margin-top:20px !important;'><p>Please enter your Website Toolbox $message. </p></div>", WebsiteToolboxInclude\wtbGetAllowedHTMLTags()); 372 } else if($message && $message != 'success') {502 } elseif($message && $message != 'success') { 373 503 $message = rtrim($message,'.'); 374 504 if(strpos($message,'username')){ … … 463 593 $wtbExist = 0; 464 594 $wtbForumpageid = createOrUpdateForumPage(); 465 } else if(!empty($wtbForumpageid) && $pageStatus !== 'publish') {595 } elseif(!empty($wtbForumpageid) && $pageStatus !== 'publish') { 466 596 onForumPluginActivation('settings'); 467 597 } … … 480 610 if($pageData && is_object($pageData) && isset($pageData->post_type) && $pageData->post_type == 'nav_menu_item') { 481 611 $wtbOptions = array_merge($wtbOptions, array(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_redirect"=>'')); 612 613 // Log when SSO is set up with existing custom link/menu item 614 \WebsiteToolboxLogger\Logger::info('PAGE_CONNECT', 'SSO configured with existing menu link', array( 615 'page_id' => $wtbForumpageid, 616 'post_type' => 'nav_menu_item', 617 'page_title' => $pageData->post_title, 618 'link_type' => 'custom_link', 619 'setup_type' => 'SSO with existing /forum link' 620 )); 482 621 } else { 483 622 if($pageData && is_object($pageData) && isset($pageData->guid)) { … … 587 726 set_transient('wtb_first_time_setup', 1, 30); 588 727 } 728 // Clear category cache after successful login 729 WebsiteToolboxForum\clearCategoryCache(); 730 589 731 unset($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated']); 590 wp_ redirect("options-general.php?page=".WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolboxUpdateOptions");732 wp_safe_redirect("admin.php?page=".WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolboxUpdateOptions"); 591 733 exit; 592 734 } … … 613 755 } 614 756 615 /* Purpose: to show setti gns field into forum plugin settingapage.757 /* Purpose: to show settings field into forum plugin settings page. 616 758 Parameter: None 617 759 Return: None */ … … 655 797 WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_settings_update_section' 656 798 ); 799 657 800 // To show "Update" button on forum settings page on WordPress admin panel. 658 801 add_settings_field( … … 677 820 function forumDashboardUpdateUsername($args) { 678 821 $websitetoolbox_username = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_username'); 679 $html = $websitetoolbox_username.' <a href=" options-general.php?page='.WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxoptions">Change</a>';822 $html = $websitetoolbox_username.' <a href="admin.php?page='.WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolboxUpdateOptions&change=1">Change</a>'; 680 823 echo wp_kses($html, WebsiteToolboxInclude\wtbGetAllowedHTMLTags()); 681 824 } … … 719 862 } 720 863 721 /* Purpose: To show plugin settigns page as well as error and success message.864 /* Purpose: To display the plugin's main (top-level) admin settings page, including error and success messages. 722 865 Parameter: None 723 866 Return: None */ … … 726 869 WebsiteToolboxInclude\startForumSession(); 727 870 $pid = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_pageid'); 728 if($message == '0') { 871 872 // Check for settings updated parameter 873 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display parameter from WordPress redirect 874 $settingsUpdated = (isset($_GET['settings-updated']) && $_GET['settings-updated'] === 'true') || $message === 'success'; 875 876 if ($settingsUpdated) { 877 echo '<div id="setting-error-settings_updated" class="updated notice is-dismissible"><p>Your settings have been updated.</p></div>'; 878 } elseif($message == '0') { 729 879 echo '<div id="setting-error-settings_updated" class="updated notice"><p>Your forum needs to <a href= "https://www.websitetoolbox.com/tool/members/domain?tool=mb" target="_blank">use a subdomain</a> for it to appear as embedded instead of full-screen in the Safari browser.</p></div>'; 730 } else if($message == 'success') {731 echo '<div id="setting-error-settings_updated" class="updated notice"><p>Your settings have been updated.</p></div>';732 880 } 733 881 printTestRequestStatus(); 882 883 // Build form action URL properly using WordPress functions 884 $formAction = admin_url('admin.php?page=' . WebsiteToolboxForum\globalVariables::$WTBPREFIX . 'websitetoolboxUpdateOptions'); 734 885 ?> 735 886 <!-- create a form in the wordpress admin panel --> 736 887 <div class="wrap"> 737 <form name="form_lol" action=" options-general.php?page=<?php echo esc_html((WebsiteToolboxForum\globalVariables::$WTBPREFIX)); ?>websitetoolboxUpdateOptions" method="POST" >888 <form name="form_lol" action="<?php echo esc_url($formAction); ?>" method="POST" > 738 889 <?php 739 890 wp_nonce_field('updateWtbSettings', 'update_wtplugin_nonce'); … … 749 900 Return: None */ 750 901 function onForumUpdateSettings() { 902 // Check user capability first for security 903 if (!current_user_can('manage_options')) { 904 wp_die('You do not have sufficient permissions to access this page.'); 905 } 906 907 // Check if user wants to change login credentials (GET request) or is submitting login form (POST with add_wtplugin_nonce) 908 $isLoginForm = (isset($_GET['change']) && $_GET['change'] === '1') || 909 (isset($_POST['add_wtplugin_nonce']) && !isset($_POST['update_wtplugin_nonce'])); 910 911 if ($isLoginForm) { 912 // Show login form to change credentials or process login 913 onForumDashboardLogin(); 914 return; 915 } 916 751 917 if(!get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_user_roles')){ 752 918 global $wp_roles; … … 950 1116 } 951 1117 } 952 showForumUpdateSettingsPage('success'); 1118 1119 // Clear category cache when settings are updated 1120 WebsiteToolboxForum\clearCategoryCache(); 1121 1122 // Redirect back to settings page with success message 1123 wp_safe_redirect(add_query_arg('settings-updated', 'true', admin_url('admin.php?page=' . WebsiteToolboxForum\globalVariables::$WTBPREFIX . 'websitetoolboxUpdateOptions'))); 953 1124 exit; 954 1125 } … … 1069 1240 $id = (int) $id; 1070 1241 // allow for transaction statement 1071 do_action('delete_user', $id);1072 1242 if ( 'novalue' === $reassign || null === $reassign ) { 1073 1243 // phpcs:ignore WordPress.DB.DirectDatabaseQuery … … 1102 1272 $wpdb->query("DELETE FROM $wpdb->usermeta WHERE user_id = %d, AND meta_key = '{%s}'", $id, $level_key); 1103 1273 } 1104 // allow for commit transaction1105 do_action('deleted_user', $id);1106 1274 return true; 1107 1275 } … … 1119 1287 $_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated'] = ''; 1120 1288 unset($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated']); 1121 } else if($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated'] == 2) {1289 } elseif($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated'] == 2) { 1122 1290 $_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated'] = ''; 1123 1291 unset($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated']); 1124 1292 } 1125 1293 1126 } else if($is_admin == 1 && isset($_SESSION['wtb_account_settings'])) {1294 } elseif($is_admin == 1 && isset($_SESSION['wtb_account_settings'])) { 1127 1295 if($_SESSION['wtb_account_settings'] == 1) { 1128 1296 echo wp_kses('<div id="wtb-warning" class="error"><p>Your Website Toolbox Forum account is currently disabled. Please <a href="https://www.websitetoolbox.com/tool/members/login/'.get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_username").'" target="_blank">login to your Website Toolbox account</a> for more information.</a></p></div>', WebsiteToolboxInclude\wtbGetAllowedHTMLTags()); 1129 } else if(isset($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtb_account_settings']) && $_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtb_account_settings'] == 2) { 1130 echo '<div id="wtb-warning" class="error"><p>The API Key integrated with the Website Toolbox Forum plugin is invalid. Please <a href="options-general.php?page=websitetoolboxoptions">log in</a> again to update it.</p></div>'; 1297 } elseif(isset($_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtb_account_settings']) && $_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtb_account_settings'] == 2) { 1298 $loginUrl = admin_url('admin.php?page=' . WebsiteToolboxForum\globalVariables::$WTBPREFIX . 'websitetoolboxUpdateOptions&change=1'); 1299 echo '<div id="wtb-warning" class="error"><p>The API Key integrated with the Website Toolbox Forum plugin is invalid. Please <a href="' . esc_url($loginUrl) . '">log in</a> again to update it.</p></div>'; 1131 1300 } 1132 1301 } … … 1169 1338 } 1170 1339 $_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbForumCheck'] = 1; 1171 } else if ($is_admin == 1 && is_plugin_active('website-toolbox-forums/websitetoolbox.php') && (!get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_username") || !get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_api") || !get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_url"))) {1340 } elseif ($is_admin == 1 && is_plugin_active('website-toolbox-forums/websitetoolbox.php') && (!get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_username") || !get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_api") || !get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX."websitetoolbox_url"))) { 1172 1341 $_SESSION[WebsiteToolboxForum\globalVariables::$WTBPREFIX.'wtbPluginActivated'] = 2; 1173 1342 } … … 1212 1381 // Add/update data if embeded option is enable. 1213 1382 if($redirect_option==1) { 1214 $postTitle = $pageData ->post_title;1383 $postTitle = $pageData && is_object($pageData) ? $pageData->post_title : ''; 1215 1384 if($wtbForumpageid) { 1216 1385 onForumPluginActivation('settings'); … … 1218 1387 // Create a new page for forum if forum is alrady integrated as a custom link on WordPress website. 1219 1388 // User save settings after enable "Embed" option. So that didn't effect on custom link. 1220 if($pageData ->post_type == 'nav_menu_item') {1389 if($pageData && is_object($pageData) && $pageData->post_type == 'nav_menu_item') { 1221 1390 $wtbForumpageid = createOrUpdateForumPage(); 1222 1391 // Update page id in options table … … 1243 1412 } 1244 1413 // Add/update embed code for the forum page on WordPress. 1245 $embedPageUrl = $pageData ->guid;1414 $embedPageUrl = $pageData && is_object($pageData) ? $pageData->guid : ''; 1246 1415 $wtb_embed_url = preg_replace('#^https?:#i', '', $wtb_url); 1247 1416 … … 1251 1420 $postContent = ''; 1252 1421 $embedCode = getEmbedCodeHTML($wtb_embed_url, $wtb_url); 1253 if($pageData ->post_content && strpos($pageData->post_content, $wtb_embed_url) !== false) {1422 if($pageData && is_object($pageData) && $pageData->post_content && strpos($pageData->post_content, $wtb_embed_url) !== false) { 1254 1423 $postContent = str_replace($embedCode, 'Embed Code', $pageData->post_content); 1255 1424 } … … 1519 1688 $response = testDeclineMemberRequest('getResponse'); 1520 1689 if($response) { 1521 wp_ redirect("options-general.php?page=websitetoolboxUpdateOptions&action=successRequest");1690 wp_safe_redirect("options-general.php?page=websitetoolboxUpdateOptions&action=successRequest"); 1522 1691 exit; 1523 1692 } else { 1524 wp_ redirect("options-general.php?page=websitetoolboxUpdateOptions&action=failRequest");1693 wp_safe_redirect("options-general.php?page=websitetoolboxUpdateOptions&action=failRequest"); 1525 1694 exit; 1526 1695 } … … 1567 1736 update_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_pageid', $existingPageId); 1568 1737 set_transient('wtb_used_existing_page', $existingPageId, 30); 1738 1739 // Log when existing page with embed code is found and used 1740 $pageData = get_post($existingPageId); 1741 \WebsiteToolboxLogger\Logger::info('PAGE_CONNECT', 'Existing embed page found and connected', array( 1742 'page_id' => $existingPageId, 1743 'page_title' => $pageData ? $pageData->post_title : 'Unknown', 1744 'page_url' => get_permalink($existingPageId), 1745 'created_by' => 'manual' 1746 )); 1747 1569 1748 return $existingPageId; 1570 1749 } else { … … 1605 1784 } 1606 1785 1786 /* Purpose: Track when forum embed page is deleted manually 1787 Parameter: Post ID 1788 Return: None */ 1789 function trackEmbedPageDeletion($postId) { 1790 $forumPageId = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_pageid'); 1791 1792 // Check if the deleted page is the forum embed page 1793 if ($postId == $forumPageId) { 1794 $postData = get_post($postId); 1795 if ($postData) { 1796 \WebsiteToolboxLogger\Logger::warning('PAGE_DELETE', 'Forum embed page deleted manually', array( 1797 'page_id' => $postId, 1798 'page_title' => $postData->post_title, 1799 'deleted_by' => 'manual', 1800 'post_status' => $postData->post_status 1801 )); 1802 } 1803 } 1804 } 1805 1806 /* Purpose: Track when forum embed page is trashed manually 1807 Parameter: Post ID 1808 Return: None */ 1809 function trackEmbedPageTrashed($postId) { 1810 $forumPageId = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_pageid'); 1811 1812 // Check if the trashed page is the forum embed page 1813 if ($postId == $forumPageId) { 1814 $postData = get_post($postId); 1815 if ($postData) { 1816 \WebsiteToolboxLogger\Logger::warning('PAGE_TRASH', 'Forum embed page moved to trash', array( 1817 'page_id' => $postId, 1818 'page_title' => $postData->post_title, 1819 'trashed_by' => 'manual', 1820 'previous_status' => $postData->post_status 1821 )); 1822 } 1823 } 1824 } 1825 1607 1826 /* Purpose: Display admin message about page creation/connection 1608 1827 Parameter: None 1609 1828 Return: None */ 1610 1829 function showPageActionMessage() { 1830 // Always clear transients first to prevent them from persisting 1611 1831 $wtbPageId = get_transient('wtb_used_existing_page'); 1612 1832 if ($wtbPageId) { … … 1618 1838 } 1619 1839 } 1840 1841 // Don't show message if settings-updated parameter is present (handled by showForumUpdateSettingsPage) 1842 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display parameter 1843 if (isset($_GET['settings-updated']) && $_GET['settings-updated'] === 'true') { 1844 return; 1845 } 1846 1620 1847 if (empty($wtbPageId)) { 1621 1848 return; -
website-toolbox-forums/trunk/admin/css/websitetoolbox.css
r3223937 r3439073 231 231 margin-right: 15px; 232 232 } 233 234 /* Website Toolbox Menu Icon Styles */ 235 #adminmenu .toplevel_page_websitetoolboxUpdateOptions .wp-menu-image img, 236 #adminmenu .toplevel_page_websitetoolboxoptions .wp-menu-image img { 237 width: 20px; 238 height: 20px; 239 padding: 0; 240 opacity: 0.6; 241 } 242 243 #adminmenu .toplevel_page_websitetoolboxUpdateOptions:hover .wp-menu-image img, 244 #adminmenu .toplevel_page_websitetoolboxoptions:hover .wp-menu-image img, 245 #adminmenu .toplevel_page_websitetoolboxUpdateOptions.current .wp-menu-image img, 246 #adminmenu .toplevel_page_websitetoolboxoptions.current .wp-menu-image img { 247 opacity: 1; 248 } 249 250 /* Forum Logs Page Styles */ 251 .wtb-logs-header { 252 background: #fff; 253 padding: 15px; 254 border: 1px solid #ccd0d4; 255 box-shadow: 0 1px 1px rgba(0,0,0,.04); 256 } 257 258 .wtb-table-wrapper { 259 overflow-x: auto; 260 margin-bottom: 15px; 261 } 262 263 .wtb-logs-table { 264 min-width: 100%; 265 table-layout: auto; 266 } 267 268 .wtb-log-message { 269 line-height: 1.6; 270 word-wrap: break-word; 271 overflow-wrap: break-word; 272 max-width: 100%; 273 } 274 275 .wtb-log-context { 276 max-width: 100%; 277 overflow-x: auto; 278 overflow-y: hidden; 279 margin-top: 10px; 280 padding: 10px; 281 background: #f5f5f5; 282 border-left: 3px solid #0073aa; 283 border-radius: 3px; 284 } 285 286 .wtb-log-context pre { 287 margin: 0; 288 white-space: pre; 289 word-wrap: normal; 290 overflow-wrap: normal; 291 max-width: none; 292 min-width: 100%; 293 } 294 295 .wtb-log-row td { 296 vertical-align: top; 297 } 298 299 /* Log Level Badge Styles */ 300 .wtb-log-level { 301 padding: 3px 8px; 302 border-radius: 3px; 303 font-size: 11px; 304 font-weight: bold; 305 display: inline-block; 306 } 307 308 .wtb-log-level-error { 309 background: #dc3232; 310 color: white; 311 } 312 313 .wtb-log-level-warning { 314 background: #ffb900; 315 color: #000; 316 } 317 318 .wtb-log-level-info { 319 background: #00a0d2; 320 color: white; 321 } 322 323 .wtb-log-level-debug { 324 background: #808080; 325 color: white; 326 } 327 328 /* Make table responsive */ 329 @media screen and (max-width: 1024px) { 330 .wp-list-table.widefat th:nth-child(7), 331 .wp-list-table.widefat td:nth-child(7) { 332 display: none; /* Hide User Agent on smaller screens */ 333 } 334 335 .wp-list-table.widefat th:nth-child(1), 336 .wp-list-table.widefat td:nth-child(1) { 337 width: 120px !important; 338 } 339 } 340 341 @media screen and (max-width: 782px) { 342 .wp-list-table.widefat th:nth-child(5), 343 .wp-list-table.widefat td:nth-child(5) { 344 display: none; /* Hide User on mobile */ 345 } 346 347 .wp-list-table.widefat th:nth-child(3), 348 .wp-list-table.widefat td:nth-child(3) { 349 width: 90px !important; 350 } 351 352 .wtb-log-message { 353 font-size: 13px; 354 } 355 356 .wtb-toggle-context { 357 margin-top: 5px !important; 358 margin-left: 0 !important; 359 } 360 } 361 362 .tablenav .actions select { 363 float: none; 364 } -
website-toolbox-forums/trunk/admin/js/websitetoolbox.js
r3123304 r3439073 3 3 wtbxPlugin.admin.disableSSOForAllUsersRole(); 4 4 wtbxPlugin.admin.showOptionsForUserRoles(); 5 wtbxPlugin.admin.toggleLogContext(); 5 6 var userRolesCheckbox = document.querySelector('input[name="user_roles[]"]'); 6 7 if (userRolesCheckbox) { … … 93 94 }); 94 95 } 96 }, 97 98 toggleLogContext: function() { 99 jQuery(document).off('click', '.wtb-toggle-context').on('click', '.wtb-toggle-context', function(e) { 100 e.preventDefault(); 101 e.stopPropagation(); 102 103 var $button = jQuery(this); 104 var logId = $button.data('log-id'); 105 var $context = jQuery('#context-' + logId); 106 107 if ($context.is(':visible')) { 108 $context.slideUp(200); 109 $button.text('Show Context'); 110 } else { 111 jQuery('.wtb-log-context').slideUp(200); 112 jQuery('.wtb-toggle-context').text('Show Context'); 113 114 $context.slideDown(200); 115 $button.text('Hide Context'); 116 } 117 return false; 118 }); 95 119 } 96 120 }; -
website-toolbox-forums/trunk/admin/websitetoolbox_sidebar.php
r3395282 r3439073 1 <?php 1 <?php 2 2 namespace WebsiteToolboxAdminSidebar; 3 4 // If this file is called directly, abort. 5 if ( ! defined( 'ABSPATH' ) ) { 6 exit; 7 } 8 3 9 use WebsiteToolboxForum; 4 10 use WebsiteToolboxForum\globalVariables; … … 6 12 function getAllCategoriesForSideBar(){ 7 13 global $pagenow; 14 15 // Cache categories to avoid duplicate API calls during the same request 16 static $cachedForumCategories = null; 17 18 // Return cached data if available 19 if ($cachedForumCategories !== null) { 20 return $cachedForumCategories; 21 } 22 8 23 $forumCategories = array(); 9 if($pagenow == 'post-new.php' || $pagenow == 'post.php' ){ 24 25 // Only fetch categories if on post/page edit screens and API key is configured 26 if(($pagenow == 'post-new.php' || $pagenow == 'post.php') && get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_api')){ 10 27 $categoryList = WebsiteToolboxForum\getCategoryList(); 11 28 if(is_array($categoryList)){ … … 13 30 } 14 31 } 32 33 // Cache the result before returning 34 $cachedForumCategories = $forumCategories; 15 35 return $forumCategories; 16 36 } … … 24 44 /* show metabox in classic editor */ 25 45 function custom_meta_box_markup($post){ 46 // Don't render metabox during deletion, trash, or untrash operations 47 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is a read-only check, not processing form data 48 if(isset($_GET['action']) && in_array($_GET['action'], array('delete', 'trash', 'untrash'))){ 49 return; 50 } 51 26 52 wp_nonce_field(basename(__FILE__), "meta-box-nonce"); 27 53 $forumCategories = getAllCategoriesForSideBar(); … … 51 77 $existingTopicId = get_post_meta($post->ID,'forum_topicId',true); 52 78 if($existingTopicId && $existingTopicId != ''){ 53 $getTopicId = WebsiteToolboxForum\apiRequest('GET', "/topics/".$existingTopicId); 79 // Check if API key is configured and not in a deletion/trash context 80 $apiKey = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_api'); 81 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is a read-only check, not processing form data 82 $isDeletionAction = (isset($_GET['action']) && in_array($_GET['action'], array('delete', 'trash', 'untrash'))); 83 84 if(!empty($apiKey) && !$isDeletionAction){ 85 $getTopicId = WebsiteToolboxForum\apiRequest('GET', "/topics/".$existingTopicId); 86 } 54 87 } 55 88 if(isset($getTopicId->status)){ … … 127 160 /* show sidebar in block editor */ 128 161 function sidebar_plugin_register() { 162 global $pagenow; 163 164 // Always register post meta for block editor (required for saving data) 165 register_post_meta( '', 'website_toolbox_forum_postUrl', array( 166 'single' => true, 167 'show_in_rest' => true, 168 'type' => 'string', 169 ) 170 ); 171 register_post_meta( '', 'website_toolbox_forum_category', array( 172 'single' => true, 173 'show_in_rest' => true, 174 'type' => 'string', 175 'auth_callback' => function() { 176 return current_user_can( 'edit_posts' ); 177 } 178 ) 179 ); 180 register_post_meta( '', 'website_toolbox_publish_on_forum', array( 181 'single' => true, 182 'show_in_rest' => true, 183 'type' => 'string', 184 'auth_callback' => function() { 185 return current_user_can( 'edit_posts' ); 186 } 187 ) 188 ); 189 190 // Only proceed with sidebar UI registration on post/page edit screens 191 if (!is_admin() || !in_array($pagenow, array('post-new.php', 'post.php'))) { 192 return; 193 } 194 195 // Don't run during deletion, trash, or untrash operations 196 if(isset($_GET['action']) && in_array($_GET['action'], array('delete', 'trash', 'untrash'))){ 197 return; 198 } 199 200 // Only proceed if API key is configured 201 if(!get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_api')){ 202 return; 203 } 204 129 205 $forumCategories = getAllCategoriesForSideBar(); 130 if(get_option("websitetoolbox_api")){ 131 $postTypeDefault = array(); 132 $sidebarCategories = array(); 206 $postTypeDefault = array(); 207 $sidebarCategories = array(); 133 208 wp_register_script( 134 209 'plugin-sidebar-js', … … 176 251 177 252 if(isset($_GET['post'])){ 178 $existingForumCategory = isset($_GET['post']) ? sanitize_text_field(wp_unslash($_GET['post']),'website_toolbox_forum_category',true) : ''; 179 $existingTopicId = isset($_GET['post']) ? sanitize_text_field(wp_unslash($_GET['post']),'forum_topicId',true) : ''; 253 $postId = sanitize_text_field(wp_unslash($_GET['post'])); 254 $existingForumCategory = get_post_meta($postId, 'website_toolbox_forum_category', true); 255 $existingTopicId = get_post_meta($postId, 'forum_topicId', true); 180 256 if($existingTopicId){ 181 $latestForumCategory = WebsiteToolboxForum\checkTopicCategory($existingTopicId,$existingForumCategory); 182 } 183 184 } 185 register_post_meta( '', 'website_toolbox_forum_postUrl', array( 186 'single' => true, 187 'show_in_rest' => true, 188 'type' => 'string', 189 ) 190 ); 191 register_post_meta( '', 'website_toolbox_forum_category', array( 192 'single' => true, 193 'show_in_rest' => true, 194 'type' => 'string', 195 'auth_callback' => function() { 196 return current_user_can( 'edit_posts' ); 197 } 198 ) 199 ); 200 register_post_meta( '', 'website_toolbox_publish_on_forum', array( 201 'single' => true, 202 'show_in_rest' => true, 203 'type' => 'string', 204 'auth_callback' => function() { 205 return current_user_can( 'edit_posts' ); 206 } 207 ) 208 ); 257 // Check if API key is configured and not in a deletion/trash context 258 $apiKey = get_option(WebsiteToolboxForum\globalVariables::$WTBPREFIX.'websitetoolbox_api'); 259 $isDeletionAction = (isset($_GET['action']) && in_array($_GET['action'], array('delete', 'trash', 'untrash'))); 260 261 if(!empty($apiKey) && !$isDeletionAction){ 262 $latestForumCategory = WebsiteToolboxForum\checkTopicCategory($existingTopicId,$existingForumCategory); 263 } 264 } 265 266 } 209 267 $postTypeDefault= array( 210 268 'pageContent' => get_option("websitetoolbox_page_content"), … … 217 275 wp_localize_script( 'plugin-sidebar-js', 'sidebarCategories', $sidebarCategories ); 218 276 wp_localize_script( 'plugin-sidebar-js', 'defaultParameter', $postTypeDefault ); 219 }220 277 } 221 278 -
website-toolbox-forums/trunk/core/events.php
r3395282 r3439073 4 4 */ 5 5 namespace WebsiteToolboxEvents; 6 7 // If this file is called directly, abort. 8 if ( ! defined( 'ABSPATH' ) ) { 9 exit; 10 } 11 6 12 use WebsiteToolboxForum; 7 13 use WebsiteToolboxAdmin; … … 213 219 } 214 220 WebsiteToolboxForum\resetCookieOnLogout(); 215 wp_ redirect($wtbLogoutUrl);221 wp_safe_redirect($wtbLogoutUrl); 216 222 exit; 217 223 } -
website-toolbox-forums/trunk/forumHook.php
r3380096 r3439073 1 1 <?php 2 3 // If this file is called directly, abort. 4 if ( ! defined( 'ABSPATH' ) ) { 5 exit; 6 } 7 2 8 add_action('admin_menu', 'WebsiteToolboxAdmin\\showForumDashboardMenu'); 9 add_action('admin_menu', 'WebsiteToolboxLogs\\addLogsMenu'); 10 add_action('admin_init', 'WebsiteToolboxLogs\\handleDownloadAction'); 3 11 add_action('admin_init', 'WebsiteToolboxAdmin\\showForumDashboardLoginPage'); 4 12 add_action('admin_init', 'WebsiteToolboxAdmin\\showForumDashboardUpdatePage'); 5 13 add_action('admin_init', 'WebsiteToolboxAdmin\\redirectAfterActivation' ); 6 add_action( 'admin_init', 'WebsiteToolboxInclude\\startForumSession');7 14 add_action('wp_head', 'WebsiteToolboxForum\\publishForumPage'); 15 /* SSO login/logout functionality on front-end pages */ 16 add_action('wp_head', 'WebsiteToolboxForum\\ssoLoginLogout', 999); 8 17 /* admin_notices to print notice(message) on admin section */ 9 18 add_action('admin_notices', 'WebsiteToolboxAdmin\\showWarnings'); … … 17 26 /* user_register hook called when a new account creates from from wordpress site (front end/back end) */ 18 27 add_action('user_register', 'WebsiteToolboxEvents\\createUserOnForum'); 19 /* print IMG tags to the footer if needed */20 add_action('wp_head','WebsiteToolboxForum\\ssoLoginLogout', 999);21 28 /* print IMG tags to the admin login page if user redirected to login page after logged-out. */ 22 29 add_action('login_head', 'WebsiteToolboxForum\\ssoLoginLogout'); … … 28 35 add_action( 'login_init', 'WebsiteToolboxAdmin\\checkReferelUrlOnLogin' ); 29 36 /* hooks for create topic on forum automatically */ 30 add_action( 'after_setup_theme', 'w tCheckForSidebar' );31 function w tCheckForSidebar() {37 add_action( 'after_setup_theme', 'websitetoolbox_check_for_sidebar' ); 38 function websitetoolbox_check_for_sidebar() { 32 39 global $pagenow; 33 40 … … 38 45 } 39 46 } 40 add_action( 'init', 'WebsiteToolboxInclude\\startForumSession');41 47 add_action( 'init', 'WebsiteToolboxInclude\\startForumSession'); 42 48 add_action( 'init', 'WebsiteToolboxAdminSidebar\\sidebar_plugin_register',10 ); … … 76 82 add_action('show_user_profile', 'WebsiteToolboxForum\\ssoLogoutOnUpdatePassword'); 77 83 add_action('admin_notices', 'WebsiteToolboxAdmin\\showPageActionMessage'); 84 /* Track when forum embed page is trashed manually */ 85 add_action('wp_trash_post', 'WebsiteToolboxAdmin\\trackEmbedPageTrashed'); 86 /* Track when forum embed page is deleted manually */ 87 add_action('before_delete_post', 'WebsiteToolboxAdmin\\trackEmbedPageDeletion'); 78 88 79 89 ?> -
website-toolbox-forums/trunk/readme.txt
r3408412 r3439073 4 4 Requires at least: 3.0.0 5 5 Tested up to: 6.9 6 Stable Tag: 2.1. 16 Stable Tag: 2.1.2 7 7 License: GPL-2.0-or-later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 107 107 == Changelog == 108 108 109 = 2.1.2 = 110 * Added an error log feature in the plugin so that the user can download the log if it exists. I also created a separate menu for Website Toolbox in the WordPress admin panel instead of displaying it under Settings. 111 109 112 = 2.1.1 = 110 113 * Renamed plugin from community to forum. -
website-toolbox-forums/trunk/uninstall.php
r3026489 r3439073 1 1 <?php 2 2 3 // If uninstall not called from WordPress, exit 4 if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { 5 exit; 6 } 7 3 8 include_once plugin_dir_path( __FILE__ ) . 'websitetoolbox.php'; 9 10 /** 11 * Handle plugin uninstallation 12 * Notifies the forum about the plugin being uninstalled 13 */ 14 function websitetoolbox_process_uninstall() { 4 15 $fields = array( 5 16 'action' => 'uninstallPlugin', … … 10 21 11 22 $response_array = wp_remote_post(WebsiteToolboxForum\globalVariables::$WTBSETTINGSPAGEURL, array('method' => 'POST', 'body' => $fields)); 23 24 return $response_array; 25 } 26 27 // Execute uninstall process 28 websitetoolbox_process_uninstall(); 12 29 13 30 ?> -
website-toolbox-forums/trunk/websitetoolbox.php
r3395282 r3439073 1 1 <?php 2 3 2 /** 4 3 * @package Website Toolbox Forum … … 12 11 * Author: Website Toolbox 13 12 * Author URI: https://www.websitetoolbox.com/wordpress 14 * Version: 2.1. 113 * Version: 2.1.2 15 14 * License: GPL-2.0-or-later 16 15 * License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 19 18 namespace WebsiteToolboxForum; 20 19 20 // If this file is called directly, abort. 21 if ( ! defined( 'ABSPATH' ) ) { 22 exit; 23 } 24 25 // Logging configuration constants 26 if (!defined('WTB_LOGGING_ENABLED')) { 27 define('WTB_LOGGING_ENABLED', 1); 28 } 29 if (!defined('WTB_LOG_RETENTION_DAYS')) { 30 define('WTB_LOG_RETENTION_DAYS', 30); 31 } 21 32 22 33 /* Class to define plugin specific global variable */ … … 38 49 include("forumHook.php"); 39 50 include("core/events.php"); 51 include("core/logger.php"); 52 53 // Initialize logger immediately after loading logger class 54 // This ensures the database table exists before any logging calls 55 try { 56 \WebsiteToolboxLogger\Logger::init(); 57 } catch (\Exception $e) { 58 // Use error_log as fallback since logger initialization failed 59 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 60 error_log(sprintf( 61 'Website Toolbox Forum: Logger initialization failed - %s in %s on line %d', 62 $e->getMessage(), 63 basename($e->getFile()), 64 $e->getLine() 65 )); 66 } 67 40 68 include("admin/admin.php"); 69 include("admin/logs.php"); 70 71 // Enqueue client OS detection script for accurate logging 72 function enqueueClientInfoScript() { 73 wp_enqueue_script( 74 'wtb-client-info', 75 plugins_url('core/client-info.js', __FILE__), 76 array(), 77 globalVariables::$VERSION, 78 true 79 ); 80 } 81 add_action('wp_enqueue_scripts', 'WebsiteToolboxForum\\enqueueClientInfoScript'); 82 add_action('admin_enqueue_scripts', 'WebsiteToolboxForum\\enqueueClientInfoScript'); 41 83 42 84 function redirectionToAvoidAMP() { … … 58 100 $updatedPageUrl = remove_query_arg('amp', $currentPageUrl); 59 101 $updatedPageUrl = add_query_arg( 'noamp', 'mobile', $updatedPageUrl); 60 wp_ redirect( $updatedPageUrl );102 wp_safe_redirect( $updatedPageUrl ); 61 103 exit; 62 104 } … … 69 111 function embedContent($content) { 70 112 $websitetoolboxpage_id = get_option(globalVariables::$WTBPREFIX.'websitetoolbox_pageid'); 71 $page_content = get_page($websitetoolboxpage_id); 113 $page_content = get_post($websitetoolboxpage_id); 114 115 // Log error if page content cannot be loaded 116 if (empty($page_content)) { 117 \WebsiteToolboxLogger\Logger::error('EMBED', 'Failed to load forum page content', \WebsiteToolboxLogger\Logger::sanitizeLogData(array( 118 'page_id' => $websitetoolboxpage_id, 119 'url' => isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '' 120 ))); 121 return $content; 122 } 123 72 124 $page_content = $page_content->post_content; 73 125 $theme_data = wp_get_theme(); … … 203 255 $isSSOEnableForRole = isSsoEnableForUserRole($userObj); 204 256 if (isset($isSSOEnableForRole) && $isSSOEnableForRole == 1) { 257 \WebsiteToolboxLogger\Logger::info('SSO', 'Attempting SSO login for user', array('user_id' => $wpLoggedinUserid, 'username' => $userObj->user_login)); 258 205 259 if (!empty($forumAddressChanged)) { 206 260 resetCookieOnLogout(); 261 \WebsiteToolboxLogger\Logger::info('SSO', 'Forum address changed, resetting cookies', array('user_id' => $wpLoggedinUserid)); 207 262 } 208 263 $responseArray = ssoHttpRequest($userObj); … … 211 266 if(isset($responseArray['authtoken'])) { 212 267 saveAuthToken($responseArray['authtoken'],$responseArray['wtbUserid']); 268 \WebsiteToolboxLogger\Logger::info('SSO', 'SSO login successful', array('user_id' => $wpLoggedinUserid, 'wtb_user_id' => $responseArray['wtbUserid'])); 213 269 return $responseArray['authtoken']; 270 } else { 271 \WebsiteToolboxLogger\Logger::error('SSO', 'SSO login failed - no authtoken returned', array('user_id' => $wpLoggedinUserid)); 214 272 } 215 273 } … … 263 321 $fields['pw'] = sanitize_text_field(wp_unslash($_POST['pwd'])); 264 322 } 323 324 \WebsiteToolboxLogger\Logger::debug('SSO_API', 'Sending SSO authentication request', array('url' => $URL, 'user' => $userObj->user_login, 'user_id' => $userObj->ID)); 325 265 326 // Send http or https request to get authentication token. 266 327 $response_array = wp_remote_post($URL, array('method' => 'POST', 'body' => $fields)); … … 269 330 $response = trim(wp_remote_retrieve_body($response_array)); 270 331 $response = json_decode($response); 271 if($response && $response->{'authtoken'} != "") {332 if($response && !empty($response->{'authtoken'})) { 272 333 $responseArray = array( 273 334 'authtoken' => $response->{'authtoken'}, 274 'wtbUserid' => $response->{'userid'}335 'wtbUserid' => isset($response->{'userid'}) ? $response->{'userid'} : null 275 336 ); 337 \WebsiteToolboxLogger\Logger::info('SSO_API', 'SSO authentication successful', array('user' => $userObj->user_login, 'wtb_user_id' => isset($response->{'userid'}) ? $response->{'userid'} : null)); 276 338 return $responseArray; 277 } 278 } else if (isset($_GET['from']) && $_GET['from'] == globalVariables::$WTBPREFIX.globalVariables::$loginParam) { 279 wp_die("Error message during discussion forum SSO: " . esc_html($response_array->get_error_message())); 280 } 339 } else { 340 // Log minimal metadata - avoid logging full response to prevent credential leakage 341 $responseType = is_object($response) ? 'object' : (is_array($response) ? 'array' : gettype($response)); 342 $hasAuthtoken = is_object($response) && isset($response->{'authtoken'}); 343 \WebsiteToolboxLogger\Logger::error('SSO_API', 'SSO authentication failed - invalid response', array( 344 'user' => $userObj->user_login, 345 'response_type' => $responseType, 346 'has_authtoken' => $hasAuthtoken, 347 'authtoken_empty' => $hasAuthtoken && empty($response->{'authtoken'}) 348 )); 349 if (isset($_GET['from']) && $_GET['from'] == globalVariables::$WTBPREFIX.globalVariables::$loginParam) { 350 wp_die("Error message during discussion forum SSO: Invalid authentication response"); 351 } 352 } 353 } else { 354 \WebsiteToolboxLogger\Logger::error('SSO_API', 'SSO authentication request failed', \WebsiteToolboxLogger\Logger::sanitizeLogData(array('user' => $userObj->user_login, 'error' => $response_array->get_error_message()))); 355 if (isset($_GET['from']) && $_GET['from'] == globalVariables::$WTBPREFIX.globalVariables::$loginParam) { 356 wp_die("Error message during discussion forum SSO: " . esc_html($response_array->get_error_message())); 357 } 358 } 359 } else { 360 \WebsiteToolboxLogger\Logger::warning('SSO_API', 'SSO request attempted but API key not configured', array('user_id' => $userObj->ID)); 281 361 } 282 362 } … … 357 437 $theArray = array(); 358 438 $prefix = esc_html(globalVariables::$WTBPREFIX); 359 $theqsl = "SELECT * FROM $wpdb->postmeta a, $wpdb->posts b WHERE a.`post_id`=b.`ID` AND b.`post_status`!='trash' AND (a.`meta_key` = '".globalVariables::$WTBPREFIX."_wtbredirect_active' || a.`meta_key` = '".globalVariables::$WTBPREFIX."_links_to' || a.`meta_key` = '".globalVariables::$WTBPREFIX."_links_to_target' || a.`meta_key` = '".globalVariables::$WTBPREFIX."_links_to_type') ORDER BY a.`post_id` ASC;"; 439 440 // Prepare meta keys with proper escaping 441 $meta_key_redirect = $prefix . '_wtbredirect_active'; 442 $meta_key_links_to = $prefix . '_links_to'; 443 $meta_key_links_to_target = $prefix . '_links_to_target'; 444 $meta_key_links_to_type = $prefix . '_links_to_type'; 445 446 $theqsl = $wpdb->prepare( 447 "SELECT * FROM {$wpdb->postmeta} a, {$wpdb->posts} b 448 WHERE a.post_id = b.ID 449 AND b.post_status != %s 450 AND (a.meta_key = %s OR a.meta_key = %s OR a.meta_key = %s OR a.meta_key = %s) 451 ORDER BY a.post_id ASC", 452 'trash', 453 $meta_key_redirect, 454 $meta_key_links_to, 455 $meta_key_links_to_target, 456 $meta_key_links_to_type 457 ); 458 360 459 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery 361 460 $thetemp = $wpdb->get_results($theqsl); … … 406 505 $wpLoggedinUserid = get_current_user_id(); 407 506 $userObj = new \WP_User($wpLoggedinUserid); 507 408 508 if(!empty($currentPageId) && $currentPageId == get_option(globalVariables::$WTBPREFIX.'websitetoolbox_pageid') && is_user_logged_in()) { 409 509 if(!empty($userObj) && !isSsoEnableForUserRole($userObj)) { … … 417 517 if(isset($_GET['ssoDisabled'])) { 418 518 $content = wp_kses('<div id="notice-warning" class="notice notice-warning is-dismissible"><p>Sorry! You don’t have permission to log in to the forum.<p></div>', \WebsiteToolboxInclude\wtbGetAllowedHTMLTags()); 419 } else if(get_option(globalVariables::$WTBPREFIX."websitetoolbox_redirect") == '') {420 wp_ redirect(get_option(globalVariables::$WTBPREFIX."websitetoolbox_url"));519 } elseif(get_option(globalVariables::$WTBPREFIX."websitetoolbox_redirect") == '') { 520 wp_safe_redirect(get_option(globalVariables::$WTBPREFIX."websitetoolbox_url")); 421 521 exit(); 422 522 } 423 } else if(get_option(globalVariables::$WTBPREFIX."websitetoolbox_redirect") != '') {523 } elseif(get_option(globalVariables::$WTBPREFIX."websitetoolbox_redirect") != '') { 424 524 $embedSrcCount = preg_match('/id="embedded_forum"\ssrc=(["\'])(.*?)\1/', $content, $match); 425 525 if($embedSrcCount == 1) { … … 520 620 Return: JSON data */ 521 621 function apiRequest($method, $path, $data = '', $header = '') { 622 // Check if API key is configured before making the request 623 $api_key = get_option(globalVariables::$WTBPREFIX . 'websitetoolbox_api'); 624 if (empty($api_key)) { 625 \WebsiteToolboxLogger\Logger::debug('API', 'API key not configured, skipping request', \WebsiteToolboxLogger\Logger::sanitizeLogData(array('method' => $method, 'path' => $path))); 626 return (object) array( 627 'status' => 'error', 628 'error' => (object) array( 629 'code' => 'InvalidAPIkeyOrMissing', 630 'message' => 'API key is not configured' 631 ) 632 ); 633 } 634 522 635 $url = globalVariables::$WTBAPIPAGEURL . $path; 523 636 if (!empty($data) && strtoupper($method) == "GET") { 524 $url = sprintf("%s?%s", $url, http_build_query($data)); 637 $queryString = http_build_query($data); 638 $url = sprintf("%s?%s", $url, $queryString); 525 639 } 526 640 $args = array( 527 641 'headers' => array( 528 'x-api-key' => get_option(globalVariables::$WTBPREFIX . 'websitetoolbox_api'),642 'x-api-key' => $api_key, 529 643 'Content-Type' => 'application/json', 530 644 'User-Agent' => 'Website Toolbox WordPress Plugin', … … 532 646 'body' => (!empty($data) && strtoupper($method) == "POST") ? wp_json_encode($data) : null, 533 647 ); 648 649 \WebsiteToolboxLogger\Logger::debug('API', 'API request initiated', \WebsiteToolboxLogger\Logger::sanitizeLogData(array('method' => $method, 'path' => $url))); 650 534 651 if (strtoupper($method) == "POST") { 535 652 $response = wp_remote_post($url, $args); 536 } else if (strtoupper($method) == "GET") {653 } elseif (strtoupper($method) == "GET") { 537 654 $response = wp_remote_get($url, $args); 655 } else { 656 // Unsupported HTTP method 657 \WebsiteToolboxLogger\Logger::error('API', 'Unsupported HTTP method', \WebsiteToolboxLogger\Logger::sanitizeLogData(array('method' => $method, 'path' => $url))); 658 return false; 538 659 } 660 661 if (is_wp_error($response)) { 662 \WebsiteToolboxLogger\Logger::error('API', 'API request failed', \WebsiteToolboxLogger\Logger::sanitizeLogData(array('method' => $method, 'path' => $url, 'error' => $response->get_error_message()))); 663 } else { 664 $response_code = wp_remote_retrieve_response_code($response); 665 $response_body = wp_remote_retrieve_body($response); 666 if ($response_code >= 400) { 667 // Log minimal metadata - avoid logging full response body to prevent credential leakage 668 $response_length = strlen($response_body); 669 $response_preview = $response_length > 0 ? substr($response_body, 0, 100) : ''; 670 671 // Parse response to check for specific error codes 672 $response_data = json_decode($response_body); 673 $error_code = isset($response_data->error->code) ? $response_data->error->code : ''; 674 675 // 404 errors are expected (e.g., topic not found when checking if it exists) 676 // 400 errors with InvalidAPIkeyOrMissing are expected when plugin is not configured 677 // Log them as DEBUG instead of WARNING 678 $expected_errors = array('InvalidAPIkeyOrMissing', 'MissingAPIkey', 'InvalidAPIkey'); 679 if ($response_code == 404 || ($response_code == 400 && in_array($error_code, $expected_errors))) { 680 $log_level = 'debug'; 681 } else { 682 $log_level = 'warning'; 683 } 684 685 \WebsiteToolboxLogger\Logger::$log_level('API', 'API request returned error status', \WebsiteToolboxLogger\Logger::sanitizeLogData(array( 686 'method' => $method, 687 'path' => $url, 688 'status_code' => $response_code, 689 'response_length' => $response_length, 690 'response_preview' => $response_preview // First 100 chars, will be sanitized 691 ))); 692 } else { 693 \WebsiteToolboxLogger\Logger::debug('API', 'API request successful', array('method' => $method, 'path' => $url, 'status_code' => $response_code)); 694 } 695 } 696 539 697 return json_decode(wp_remote_retrieve_body($response)); 540 698 } … … 576 734 if($userRoles && $userRoles['users'] == "all_users") { 577 735 $isSSOEnable = 1; 578 } else if($userRoles && $userRoles['users'] == "no_users") {736 } elseif($userRoles && $userRoles['users'] == "no_users") { 579 737 $isSSOEnable = 0; 580 738 } else { … … 586 744 $isSSOEnable = 1; 587 745 } 588 } else if($roleArrayLength && $roleArrayLength > 1) {746 } elseif($roleArrayLength && $roleArrayLength > 1) { 589 747 for($i = 0; $i < $roleArrayLength; $i++) { 590 748 if(in_array($currentUserRole[$i], $userRoles)) { … … 613 771 //code for create post automatically on forum start 614 772 function getCategoryList(){ 615 $limit = array("limit"=>'100'); 616 $result = apiRequest('GET', "/categories", $limit); 773 // Use WordPress transient cache to avoid duplicate API calls across requests 774 $cacheKey = globalVariables::$WTBPREFIX . 'category_list_cache'; 775 $lockKey = globalVariables::$WTBPREFIX . 'category_list_lock'; 776 777 // Check if cached data exists 778 $cachedCategories = get_transient($cacheKey); 779 if ($cachedCategories !== false) { 780 return $cachedCategories; 781 } 782 783 // Check if another process is already fetching categories 784 $isLocked = get_transient($lockKey); 785 if ($isLocked !== false) { 786 // Wait briefly and check cache again - another request might be populating it 787 usleep(100000); // Wait 100ms 788 $cachedCategories = get_transient($cacheKey); 789 if ($cachedCategories !== false) { 790 return $cachedCategories; 791 } 792 // If still not available, proceed anyway (lock might be stale) 793 } 794 795 // Set lock to prevent concurrent requests 796 set_transient($lockKey, true, 10); // Lock for 10 seconds max 797 798 $limit = array("limit"=>'100'); 799 $result = apiRequest('GET', "/categories", $limit); 800 801 // Release lock 802 delete_transient($lockKey); 803 617 804 if(isset($result->{'data'})){ 618 return $result->{'data'}; 805 $categories = $result->{'data'}; 806 // Cache for 5 minutes (300 seconds) to reduce API calls 807 set_transient($cacheKey, $categories, 300); 808 return $categories; 619 809 }else{ 620 return "There was an error returning the category list from Website Toolbox."; 810 $errorMessage = "There was an error returning the category list from Website Toolbox."; 811 // Cache error response for 1 minute to prevent repeated failed requests 812 set_transient($cacheKey, $errorMessage, 60); 813 return $errorMessage; 621 814 } 622 815 } 816 817 /* Purpose: Clear cached category list 818 * This should be called when forum settings are updated 819 */ 820 function clearCategoryCache(){ 821 $cacheKey = globalVariables::$WTBPREFIX . 'category_list_cache'; 822 $lockKey = globalVariables::$WTBPREFIX . 'category_list_lock'; 823 delete_transient($cacheKey); 824 delete_transient($lockKey); 825 } 826 623 827 function checkTopicCategory($topicId,$categoryId){ 624 828 global $post; … … 657 861 function addUpdateTopic($defaultCategoryId,$defaultContentType,$post){ 658 862 $post_id = $post->ID; 863 659 864 delete_post_meta( $post_id, 'website_toolbox_forum_publishing_error' ); 660 865 $current_user = wp_get_current_user(); 661 866 $userName = $current_user->user_login; 662 867 $title = wp_strip_all_tags( $post->post_title ); 663 $title = apply_filters( 'w pdc_publish_format_title', $title, $post_id );868 $title = apply_filters( 'websitetoolbox_publish_format_title', $title, $post_id ); 664 869 $current_post_type = get_post_type( $post_id ); 665 870 $publishFullPost = $defaultContentType; … … 669 874 } 670 875 if($publishFullPost != 0){ 876 // Check if API key is configured before making any API requests 877 $apiKey = get_option(globalVariables::$WTBPREFIX.'websitetoolbox_api'); 878 if(empty($apiKey)){ 879 return false; 880 } 881 671 882 if($publishFullPost === 1){ 672 883 if($post->post_excerpt){ … … 789 1000 function checkPostStatus($post_id,$post){ 790 1001 $publish_status = $post->post_status; 791 $publish_private = apply_filters( 'w pdc_publish_private_post', false, $post_id );1002 $publish_private = apply_filters( 'websitetoolbox_publish_private_post', false, $post_id ); 792 1003 if ( wp_is_post_revision( $post_id ) 793 1004 || ( $publish_status != 'publish' ) … … 960 1171 $embedPageUrl = get_option(globalVariables::$WTBPREFIX."websitetoolbox_embedUrl"); 961 1172 $embedPageUrl = add_query_arg( 'ssoDisabled', 1, $embedPageUrl); 962 wp_ redirect($embedPageUrl);1173 wp_safe_redirect($embedPageUrl); 963 1174 exit(); 964 1175 } 965 } else if(!$logoutRequst && !empty($wpLoggedinUserid) && !empty($userObj) && isSsoEnableForUserRole($userObj)) {1176 } elseif(!$logoutRequst && !empty($wpLoggedinUserid) && !empty($userObj) && isSsoEnableForUserRole($userObj)) { 966 1177 $redirectUrl = \WebsiteToolboxInclude\getRedirectURL(); 967 1178 if(!empty($redirectUrl)) { … … 970 1181 $embedPageUrl = add_query_arg( 'authtoken', sanitize_text_field(wp_unslash($_COOKIE[globalVariables::$WTBPREFIX.'wt_logout_token'])), $embedPageUrl); 971 1182 } 972 wp_ redirect($embedPageUrl);1183 wp_safe_redirect($embedPageUrl); 973 1184 exit(); 974 1185 } -
website-toolbox-forums/trunk/wt_forum_include.php
r3342958 r3439073 1 1 <?php 2 namespace WebsiteToolboxInclude; 2 3 3 namespace WebsiteToolboxInclude; 4 // If this file is called directly, abort. 5 if ( ! defined( 'ABSPATH' ) ) { 6 exit; 7 } 8 4 9 use WebsiteToolboxForum; 5 10
Note: See TracChangeset
for help on using the changeset viewer.