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__( '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();