set_basename( false, __FILE__ ); } else { // Create a helper function for easy SDK access. function bc_fs() { global $bc_fs; if ( ! isset( $bc_fs ) ) { // Include Freemius SDK. require_once __DIR__ . '/vendor/freemius/wordpress-sdk/start.php'; $bc_fs = fs_dynamic_init( array( 'id' => '10864', 'slug' => 'forumax', 'premium_slug' => 'forumax-premium', 'type' => 'plugin', 'public_key' => 'pk_41277ad11125f6e2a1b4e66f40164', 'is_premium' => false, 'premium_suffix' => 'Pro', 'has_premium_version' => true, 'has_addons' => false, 'has_paid_plans' => true, 'parallel_activation' => array( 'enabled' => true, 'premium_version_basename' => 'forumax-premium/forumax.php', ), 'trial' => array( 'days' => 14, 'is_require_payment' => true, ), 'menu' => array( 'slug' => 'forumax', 'contact' => false, 'support' => false, 'first-path' => 'admin.php?page=forumax', ), ) ); } return $bc_fs; } // Add filter to hide the Freemius badge from the plugin page. bc_fs()->add_filter( 'hide_freemius_powered_by', '__return_true' ); // Disclose that opting in also pre-fills the in-plugin support chat // (see the Support Assistant class). The on-update screen falls back to this filter. bc_fs()->add_filter( 'connect_message', function ( $message ) { return $message . '

' . esc_html__( 'Opting in also pre-fills your name and email in the Forumax support chat, so you can get help without typing them. They are only sent to our helpdesk when you open the chat.', 'forumax' ); } ); // Keep the free and premium versions from auto-deactivating each other. bc_fs()->add_filter( 'deactivate_on_activation', '__return_false' ); // Suppress Freemius update row modification to avoid double notices or licensing nags on the plugins page. add_action( 'admin_init', function () { if ( function_exists( 'bc_fs' ) ) { $updater = FS_Plugin_Updater::instance( bc_fs() ); $basename = bc_fs()->get_plugin_basename(); remove_action( "after_plugin_row_{$basename}", array( $updater, 'catch_plugin_update_row' ), 9 ); remove_action( "after_plugin_row_{$basename}", array( $updater, 'edit_and_echo_plugin_update_row' ), 11 ); } } ); // Signal that SDK was initiated. do_action( 'bc_fs_loaded' ); } require_once __DIR__ . '/autoloader.php'; /** * Plugin's heart */ final class Forumax { const VERSION = '2.5.0'; /** * Class constructor. */ public function __construct() { $this->define_constants(); $this->core_includes(); register_activation_hook( __FILE__, array( $this, 'activate' ) ); register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) ); add_action( 'plugins_loaded', array( $this, 'init_plugin' ) ); add_action( 'after_setup_theme', array( $this, 'load_csf_files' ), 20 ); add_action( 'admin_init', array( $this, 'redirect_to_setup_wizard' ) ); add_action( 'upgrader_process_complete', array( $this, 'migrate_plugin_basename' ), 10, 2 ); // Added Documentation links to plugin row meta add_filter( 'plugin_row_meta', array( $this, 'forumax_row_meta' ), 10, 2 ); // Prevent deactivation if Forumax Pro is active add_action( 'admin_init', array( $this, 'prevent_deactivation_if_pro_active' ) ); add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'modify_deactivate_link' ), 10, 4 ); /** * Removes admin notices on the Forumax Forum builder page. * * @return void */ add_action( 'admin_head', function () { // Get the current screen $screen = get_current_screen(); // Check if the current screen is for your plugin page if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'forumax', 'forumax-builder', 'forumax-settings' ), true ) ) { // Remove admin notices remove_all_actions( 'admin_notices' ); remove_all_actions( 'all_admin_notices' ); // Re-add a specific notice if ( ! forumax_is_premium() && forumax_is_plugin_installed_for_days( 12 ) ) { add_action( 'admin_notices', 'forumax_offer_notice' ); } } } ); } /** * Define Plugin Constants. * * @return void */ public function define_constants() { define( 'FORUMAX_VERSION', self::VERSION ); define( 'FORUMAX_FILE', __FILE__ ); define( 'FORUMAX_DIR', __DIR__ . '/' ); define( 'FORUMAX_PATH', FORUMAX_DIR ); define( 'FORUMAX_URL', plugins_url( '/', __FILE__ ) ); define( 'FORUMAX_ASSETS', FORUMAX_URL . 'assets/' ); define( 'FORUMAX_FRONT_ASS', FORUMAX_URL . 'assets/frontend/' ); define( 'FORUMAX_ADMIN_ASS', FORUMAX_ASSETS . 'admin/' ); define( 'FORUMAX_STYLES', FORUMAX_URL . 'build/styles/' ); define( 'FORUMAX_IMG', FORUMAX_ASSETS . 'img/' ); define( 'FORUMAX_VEND', FORUMAX_ASSETS . 'vendors/' ); } /** * File includes. */ public function core_includes() { // Smart bbPress nVerify compatibility layer require_once __DIR__ . '/includes/sbv-compatibility.php'; // Docy Core compatibility layer (fixes Forums widget class not found error) require_once __DIR__ . '/includes/docy-core-compatibility.php'; // Keep single-topic theme-compat from loading every topic/reply. require_once __DIR__ . '/includes/topic-render-guard.php'; // Stop EazyDocs is_super_admin() from recursing during author cap checks. require_once __DIR__ . '/includes/eazydocs-compatibility.php'; require_once __DIR__ . '/includes/functions.php'; require_once __DIR__ . '/includes/template-functions.php'; require_once __DIR__ . '/includes/bbpress-config.php'; // Full Site Editing (block theme) compatibility – fixes blank page with Twenty Twenty-Five etc. require_once __DIR__ . '/includes/fse-compatibility.php'; require_once __DIR__ . '/includes/admin/menu/Approve_Topic.php'; require_once __DIR__ . '/includes/admin/menu/Create_Forum.php'; require_once __DIR__ . '/includes/admin/menu/Create_Topic.php'; require_once __DIR__ . '/includes/admin/menu/Delete_Forum.php'; require_once __DIR__ . '/includes/admin/menu/Delete_Topic.php'; require_once __DIR__ . '/includes/Elementor/Forumax_Widgets.php'; require_once __DIR__ . '/includes/ajax_actions.php'; include_once ABSPATH . 'wp-admin/includes/plugin.php'; require_once __DIR__ . '/widgets/widgets.php'; require_once __DIR__ . '/includes/Blocks/Blocks_Register.php'; new \admin\Blocks\Blocks_Register(); require_once __DIR__ . '/includes/Elementor/inc/forum-ajax.php'; // Core installer notice require_once __DIR__ . '/includes/admin/notices/_notices.php'; // Register Pro Widgets $theme = wp_get_theme(); if ( 'Ama' !== $theme->get( 'Name' ) || ! forumax_is_premium() ) { require_once __DIR__ . '/includes/admin/Pro_El_Widget_Map.php'; require_once __DIR__ . '/includes/admin/Pro_El_Widget_Service.php'; } // Hooks require FORUMAX_DIR . 'includes/hooks/actions.php'; require FORUMAX_DIR . 'includes/hooks/image_sizes.php'; require FORUMAX_DIR . 'includes/login-form.php'; require FORUMAX_DIR . '/includes/classes/Forumax_Forum_Class.php'; } /** * Initializing Forumax class. * * @return \Forumax */ static function init() { static $instance = false; if ( ! $instance ) { $instance = new self(); } } /** * Actions on plugin activation. * * @return void */ public function activate() { $installed = get_option( 'bbpc_installed' ); if ( ! $installed ) { update_option( 'bbpc_installed', time() ); } update_option( 'bbpc_version', FORUMAX_VERSION ); // Ensure default option for forumax_settings $defaults = array( 'is_bbpc_insert_media' => false, ); $current = get_option( 'bbp_core_settings', array() ); $updated = wp_parse_args( $current, $defaults ); update_option( 'bbp_core_settings', $updated ); // Migrate old docy-core widgets to Forumax widgets $this->migrate_docy_core_widgets(); // Set transient to redirect to setup wizard set_transient( 'forumax_activation_redirect', true, 30 ); } /** * Actions on plugin deactivation. * * @return void */ public function deactivate() { wp_clear_scheduled_hook( 'frmx_auto_close_stale_topics' ); } /** * Redirect to setup wizard after plugin activation. * * @return void */ public function redirect_to_setup_wizard() { // Check if we should redirect if ( ! get_transient( 'forumax_activation_redirect' ) ) { return; } // Don't redirect if activating multiple plugins or doing ajax if ( isset( $_GET['activate-multi'] ) || wp_doing_ajax() ) { delete_transient( 'forumax_activation_redirect' ); return; } // Don't redirect if user doesn't have permission if ( ! current_user_can( 'manage_options' ) ) { delete_transient( 'forumax_activation_redirect' ); return; } // Don't redirect while Freemius SDK is in activation/opt-in mode. // Freemius removes all submenu pages during activation mode, so // redirecting to forumax-setup would hit a non-existent page and // trigger "Sorry, you are not allowed to access this page." // The transient is preserved so the redirect fires after the // user completes or skips the Freemius opt-in. if ( function_exists( 'bc_fs' ) && bc_fs()->is_activation_mode() ) { return; } // Delete the transient so we don't redirect again delete_transient( 'forumax_activation_redirect' ); // Redirect to setup wizard wp_safe_redirect( admin_url( 'admin.php?page=forumax-setup' ) ); exit; } /** * Migrate plugin basename if the folder name changes during update. * * @param WP_Upgrader $upgrader_object * @param array $options * @return void */ public function migrate_plugin_basename( $upgrader_object, $options ) { if ( isset( $options['action'] ) && $options['action'] === 'update' && isset( $options['type'] ) && $options['type'] === 'plugin' ) { $active_plugins = get_option( 'active_plugins' ); if ( ! is_array( $active_plugins ) ) { return; } $changed = false; $migrations = array( 'bbp-core/bbp-core.php' => 'forumax/forumax.php', 'bbp-core/forumax.php' => 'forumax/forumax.php', 'bbp-core-pro/bbp-core.php' => 'forumax-pro/forumax.php', 'forumax-premium/bbp-core.php' => 'forumax-pro/forumax.php', 'forumax-premium/forumax.php' => 'forumax-pro/forumax.php', ); foreach ( $migrations as $old_basename => $new_basename ) { $key = array_search( $old_basename, $active_plugins, true ); if ( false !== $key ) { // Only migrate if the new file actually exists. if ( file_exists( WP_PLUGIN_DIR . '/' . $new_basename ) ) { $active_plugins[ $key ] = $new_basename; $changed = true; } } } if ( $changed ) { update_option( 'active_plugins', array_values( $active_plugins ) ); } } } /** * Migrate old Docy Core Forums widgets to Forumax widgets * * This function automatically converts any existing docy-core Forums widgets * to the new Forumax Forums List widgets to ensure seamless transition. * * @return void */ private function migrate_docy_core_widgets() { // Get all sidebars and their widgets $sidebars_widgets = get_option( 'sidebars_widgets', array() ); $widget_migrated = false; // Get old docy-core widget settings // WordPress stores widget settings with lowercase class name and hyphens $old_widget_option_key = 'widget_docycore-wpwidgets-forums'; $old_widget_options = get_option( $old_widget_option_key, array() ); // New Forumax widget option key $new_widget_option_key = 'widget_forumax-wpwidgets-forumax_forums_list'; $new_widget_options = get_option( $new_widget_option_key, array() ); // Loop through each sidebar foreach ( $sidebars_widgets as $sidebar_id => $widgets ) { if ( $sidebar_id === 'wp_inactive_widgets' || $sidebar_id === 'array_version' || ! is_array( $widgets ) ) { continue; } // Loop through widgets in this sidebar foreach ( $widgets as $key => $widget_id ) { // WordPress widget ID format: {widget_base_id}-{instance_number} // Example: docycore-wpwidgets-forums-2 // Check if this is an old docy-core Forums widget // Possible formats: // - docycore-wpwidgets-forums-{number} // - widget_docycore-wpwidgets-forums-{number} if ( preg_match( '/^(widget_)?docycore-wpwidgets-forums-(\d+)$/', $widget_id, $matches ) ) { $instance_number = $matches[2]; // Check if old widget has settings if ( isset( $old_widget_options[ $instance_number ] ) ) { // Copy settings to new Forumax widget $new_widget_options[ $instance_number ] = $old_widget_options[ $instance_number ]; // Update the widget ID in sidebar // New format: forumax-wpwidgets-forumax_forums_list-{number} $new_widget_id = 'forumax-wpwidgets-forumax_forums_list-' . $instance_number; $sidebars_widgets[ $sidebar_id ][ $key ] = $new_widget_id; $widget_migrated = true; // Log migration (for debugging) error_log( sprintf( 'Forumax: Migrated widget from "%s" to "%s" in sidebar "%s"', $widget_id, $new_widget_id, $sidebar_id ) ); } } } } // Save updated widget options and sidebars if any widget was migrated if ( $widget_migrated ) { update_option( $new_widget_option_key, $new_widget_options ); update_option( 'sidebars_widgets', $sidebars_widgets ); // Log successful migration error_log( 'Forumax: Widget migration completed successfully' ); } } /** * Initialize the plugin functionality. * * @return void */ public function init_plugin() { $this->load_features(); if ( is_admin() ) { new Admin(); new admin\Admin_Assets(); // Helpdesk docs assistant on Forumax admin pages. require_once __DIR__ . '/includes/admin/class-support-assistant.php'; \Forumax_Support_Assistant::get_instance(); // Check for widget migration on every admin load (once per session) // This catches cases where plugins were updated in wrong order add_action( 'admin_init', array( $this, 'check_widget_migration' ), 5 ); } elseif ( ! is_admin() ) { new Frontend\Frontend_Assets(); } // If bbPress is not active, don't load assets and widgets. if ( ! class_exists( 'bbPress' ) || ! class_exists( 'Forumax' ) ) { return; } new admin\Elementor\Forumax_Widgets(); } /** * Check and run widget migration if needed * * This runs on admin_init to catch widgets that need migration * even if the plugin was updated in the wrong order. * * @return void */ public function check_widget_migration() { /** * forumax list widget id update * * @var mixed */ $new_id = 'forumax_forums_list'; $new_option_name = 'widget_' . $new_id; $new_data = get_option( $new_option_name ); if ( empty( $new_data ) || ( is_array( $new_data ) && count( $new_data ) <= 1 ) ) { $docy_data = get_option( 'widget_forums' ); $docly_data = get_option( 'widget_doclycore\\wpwidgets\\forums_widget' ); $ama_data = get_option( 'widget_amacore\\wpwidgets\\forums_widget' ); if ( ! empty( $docy_data ) && is_array( $docy_data ) && count( $docy_data ) > 1 ) { update_option( $new_option_name, $docy_data ); } elseif ( ! empty( $docly_data ) && is_array( $docly_data ) && count( $docly_data ) > 1 ) { update_option( $new_option_name, $docly_data ); } elseif ( ! empty( $ama_data ) && is_array( $ama_data ) && count( $ama_data ) > 1 ) { update_option( $new_option_name, $ama_data ); } } // Check if migration has already been done $migration_done = get_option( 'forumax_widget_migration_done', false ); if ( $migration_done ) { return; // Already migrated } // Check if there are any old docy-core widgets that need migration $sidebars_widgets = get_option( 'sidebars_widgets', array() ); $needs_migration = false; foreach ( $sidebars_widgets as $sidebar_id => $widgets ) { if ( $sidebar_id === 'wp_inactive_widgets' || $sidebar_id === 'array_version' || ! is_array( $widgets ) ) { continue; } foreach ( $widgets as $widget_id ) { if ( preg_match( '/^(widget_)?docycore-wpwidgets-forums-(\d+)$/', $widget_id ) ) { $needs_migration = true; break 2; // Break out of both loops } } } if ( $needs_migration ) { // Run migration $this->migrate_docy_core_widgets(); // Mark as done update_option( 'forumax_widget_migration_done', true ); // Add admin notice add_action( 'admin_notices', function () { ?>

' . esc_html__( 'Documentation', 'forumax' ) . '', ); // Merge the custom links with the existing links $links = array_merge( $links, $plugin_links ); } return $links; } /** * Prevent deactivation of Forumax if Forumax Pro is active * Users must deactivate Forumax Pro first before deactivating Forumax * * @return void */ public function prevent_deactivation_if_pro_active() { // Check if we're on the plugins page if ( ! isset( $_SERVER['REQUEST_URI'] ) || strpos( $_SERVER['REQUEST_URI'], 'plugins.php' ) === false ) { return; } // Check if user is trying to deactivate this plugin if ( isset( $_GET['action'] ) && $_GET['action'] === 'deactivate' && isset( $_GET['plugin'] ) && $_GET['plugin'] === plugin_basename( __FILE__ ) ) { // Check if Forumax Pro is active if ( is_plugin_active( 'forumax-premium/forumax.php' ) ) { // Prevent deactivation wp_die( '

' . esc_html__( 'Cannot Deactivate Forumax', 'forumax' ) . '

' . '

' . esc_html__( 'You cannot deactivate Forumax while Forumax Pro is active.', 'forumax' ) . '

' . '

' . esc_html__( 'Please deactivate Forumax Pro first, then you can deactivate Forumax.', 'forumax' ) . '

', esc_html__( 'Plugin Dependency Error', 'forumax' ), array( 'back_link' => true ) ); } } } /** * Modify the deactivate link to show a disabled state when Forumax Pro is active * * @param array $actions An array of plugin action links. * @param string $plugin_file Path to the plugin file relative to the plugins directory. * @param array $plugin_data An array of plugin data. * @param string $context The plugin context (active, inactive, etc). * @return array Modified action links */ public function modify_deactivate_link( $actions, $plugin_file, $plugin_data, $context ) { // Check if Forumax Pro is active if ( is_plugin_active( 'forumax-premium/forumax.php' ) ) { // Remove the default deactivate link if ( isset( $actions['deactivate'] ) ) { unset( $actions['deactivate'] ); // Add a disabled deactivate message $actions['deactivate_disabled'] = '' . esc_html__( 'Deactivate', 'forumax' ) . ''; } } return $actions; } } /** * Initialize the Forumax plugin. * * @return \Forumax */ function forumax() { return Forumax::init(); } forumax();