init_hooks(); $this->includes(); } private function init_hooks() { add_action('admin_menu', [$this, 'add_admin_menu'], 55); add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']); add_action('wp_ajax_jltma_popup_save', [$this, 'save_popup']); add_action('wp_ajax_jltma_popup_delete', [$this, 'delete_popup']); add_action('wp_ajax_jltma_popup_duplicate', [$this, 'duplicate_popup']); add_action('wp_ajax_jltma_popup_toggle_status', [$this, 'toggle_popup_status']); } private function includes() { // Classes are now autoloaded via the plugin autoloader } public function add_admin_menu() { add_submenu_page( 'master-addons-settings', __('Popup Builder', 'master-addons'), __('Popup Builder', 'master-addons'), 'manage_options', 'jltma-popups', [$this, 'render_popup_page'] ); } public function render_popup_page() { $action = isset($_GET['action']) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : 'list'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only display routing, no state change switch ($action) { case 'new': $this->render_new_popup_page(); break; case 'edit': $this->render_edit_popup_page(); break; case 'templates': $this->render_templates_page(); break; default: $this->render_list_page(); break; } } private function render_list_page() { $list_table = new Popup_List_Table(); $list_table->prepare_items(); ?>


display(); ?>

'popup_content', 'media_buttons' => true, 'textarea_rows' => 10, ); wp_editor($content, $editor_id, $settings); ?>
render_trigger_settings(); ?> render_display_conditions(); ?> render_design_settings(); ?>
render_sidebar_settings(); ?>
get_popup($popup_id); if (!$popup) { wp_die( esc_html__('Popup not found', 'master-addons') ); } ?>

content; $editor_id = 'popup-content'; $settings = array( 'textarea_name' => 'popup_content', 'media_buttons' => true, 'textarea_rows' => 10, ); wp_editor($content, $editor_id, $settings); ?>
render_trigger_settings($popup); ?> render_display_conditions($popup); ?> render_design_settings($popup); ?>
render_sidebar_settings($popup); ?>










render(); } public function enqueue_admin_assets($hook) { if (strpos($hook, 'jltma-popups') === false) { return; } \MasterAddons\Inc\Classes\Assets_Manager::enqueue('popup-builder-admin'); wp_localize_script('jltma-popup-builder-admin', 'jltma_popup_builder', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('jltma_popup_builder'), 'strings' => [ 'confirm_delete' => __('Are you sure you want to delete this popup?', 'master-addons'), 'saving' => __('Saving...', 'master-addons'), 'saved' => __('Saved!', 'master-addons'), 'error' => __('An error occurred. Please try again.', 'master-addons'), ] ]); } public function save_popup() { if (!check_ajax_referer('jltma_popup_save', 'jltma_popup_nonce', false)) { wp_die( esc_html__('Security check failed', 'master-addons') ); } if (!current_user_can('edit_posts')) { wp_send_json_error(['message' => esc_html__('Invalid access', 'master-addons')]); } $popup_id = isset( $_POST['popup_id'] ) ? absint( $_POST['popup_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above $popup_data = [ 'name' => isset( $_POST['popup_name'] ) ? sanitize_text_field( wp_unslash( $_POST['popup_name'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'type' => isset( $_POST['popup_type'] ) ? sanitize_text_field( wp_unslash( $_POST['popup_type'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'content' => isset( $_POST['popup_content'] ) ? wp_kses_post( wp_unslash( $_POST['popup_content'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'trigger_type' => isset( $_POST['trigger_type'] ) ? sanitize_text_field( wp_unslash( $_POST['trigger_type'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'trigger_delay' => isset( $_POST['trigger_delay'] ) ? absint( $_POST['trigger_delay'] ) : 0, // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'display_on' => isset( $_POST['display_on'] ) ? sanitize_text_field( wp_unslash( $_POST['display_on'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'show_frequency' => isset( $_POST['show_frequency'] ) ? sanitize_text_field( wp_unslash( $_POST['show_frequency'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'popup_position' => isset( $_POST['popup_position'] ) ? sanitize_text_field( wp_unslash( $_POST['popup_position'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'popup_width' => isset( $_POST['popup_width'] ) ? sanitize_text_field( wp_unslash( $_POST['popup_width'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'popup_animation' => isset( $_POST['popup_animation'] ) ? sanitize_text_field( wp_unslash( $_POST['popup_animation'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'status' => isset($_POST['popup_status']) ? 'active' : 'inactive', 'settings' => [ 'show_overlay' => isset($_POST['show_overlay']), 'close_on_overlay' => isset($_POST['close_on_overlay']), 'show_close_button' => isset($_POST['show_close_button']), 'close_on_esc' => isset($_POST['close_on_esc']), 'show_logged_in' => isset($_POST['show_logged_in']), 'show_logged_out' => isset($_POST['show_logged_out']), 'show_first_time' => isset($_POST['show_first_time']), 'popup_priority' => isset( $_POST['popup_priority'] ) ? absint( $_POST['popup_priority'] ) : 0, // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'popup_class' => isset( $_POST['popup_class'] ) ? sanitize_text_field( wp_unslash( $_POST['popup_class'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above 'popup_custom_css' => isset( $_POST['popup_custom_css'] ) ? sanitize_textarea_field( wp_unslash( $_POST['popup_custom_css'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above ] ]; global $wpdb; $table_name = $wpdb->prefix . 'jltma_popups'; if ($popup_id) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct update required for custom popup table, no WP core API equivalent $result = $wpdb->update( $table_name, [ 'name' => $popup_data['name'], 'type' => $popup_data['type'], 'content' => $popup_data['content'], 'settings' => json_encode($popup_data['settings']), 'status' => $popup_data['status'], 'updated_at' => current_time('mysql') ], ['id' => $popup_id] ); } else { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- direct insert required for custom popup table, no WP core API equivalent $result = $wpdb->insert( $table_name, [ 'name' => $popup_data['name'], 'type' => $popup_data['type'], 'content' => $popup_data['content'], 'settings' => json_encode($popup_data['settings']), 'status' => $popup_data['status'], 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ] ); $popup_id = $wpdb->insert_id; } if ($result !== false) { wp_send_json_success([ 'message' => __('Popup saved successfully', 'master-addons'), 'popup_id' => $popup_id ]); } else { wp_send_json_error(['message' => __('Failed to save popup', 'master-addons')]); } } public function delete_popup() { if (!check_ajax_referer('jltma_popup_builder', 'nonce', false)) { wp_die( esc_html__('Security check failed', 'master-addons') ); } if (!current_user_can('edit_posts')) { wp_send_json_error(['message' => esc_html__('Invalid access', 'master-addons')]); } $popup_id = isset( $_POST['popup_id'] ) ? absint( $_POST['popup_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above global $wpdb; $table_name = $wpdb->prefix . 'jltma_popups'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct delete required for custom popup table, no WP core API equivalent $result = $wpdb->delete($table_name, ['id' => $popup_id]); if ($result) { wp_send_json_success(['message' => __('Popup deleted successfully', 'master-addons')]); } else { wp_send_json_error(['message' => __('Failed to delete popup', 'master-addons')]); } } public function duplicate_popup() { if (!check_ajax_referer('jltma_popup_builder', 'nonce', false)) { wp_die( esc_html__('Security check failed', 'master-addons') ); } if (!current_user_can('edit_posts')) { wp_send_json_error(['message' => esc_html__('Invalid access', 'master-addons')]); } $popup_id = isset( $_POST['popup_id'] ) ? absint( $_POST['popup_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above global $wpdb; $table_name = $wpdb->prefix . 'jltma_popups'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table_name is a safe prefixed table name, value is prepared with %d $popup = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $popup_id)); if ($popup) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- direct insert required for custom popup table, no WP core API equivalent $result = $wpdb->insert( $table_name, [ 'name' => $popup->name . ' - Copy', 'type' => $popup->type, 'content' => $popup->content, 'settings' => $popup->settings, 'status' => 'inactive', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ] ); if ($result) { wp_send_json_success(['message' => __('Popup duplicated successfully', 'master-addons')]); } } wp_send_json_error(['message' => __('Failed to duplicate popup', 'master-addons')]); } public function toggle_popup_status() { if (!check_ajax_referer('jltma_popup_builder', 'nonce', false)) { wp_die( esc_html__('Security check failed', 'master-addons') ); } if (!current_user_can('edit_posts')) { wp_send_json_error(['message' => esc_html__('Invalid access', 'master-addons')]); } $popup_id = isset( $_POST['popup_id'] ) ? absint( $_POST['popup_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above global $wpdb; $table_name = $wpdb->prefix . 'jltma_popups'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table_name is a safe prefixed table name, value is prepared with %d $popup = $wpdb->get_row($wpdb->prepare("SELECT status FROM $table_name WHERE id = %d", $popup_id)); if ($popup) { $new_status = $popup->status === 'active' ? 'inactive' : 'active'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct update required for custom popup table, no WP core API equivalent $result = $wpdb->update( $table_name, ['status' => $new_status], ['id' => $popup_id] ); if ($result !== false) { wp_send_json_success([ 'message' => __('Status updated successfully', 'master-addons'), 'new_status' => $new_status ]); } } wp_send_json_error(['message' => __('Failed to update status', 'master-addons')]); } private function get_popup($id) { global $wpdb; $table_name = $wpdb->prefix . 'jltma_popups'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table_name is a safe prefixed table name, value is prepared with %d $popup = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $id)); if ($popup && !empty($popup->settings)) { $popup->settings = json_decode($popup->settings, true); } return $popup; } public static function create_database_table() { global $wpdb; $table_name = $wpdb->prefix . 'jltma_popups'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, type varchar(50) NOT NULL, content longtext NOT NULL, settings longtext, status varchar(20) DEFAULT 'active', views int DEFAULT 0, conversions int DEFAULT 0, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } }