popup_cpt = Popup_CPT::get_instance(); $this->init_hooks(); } private function init_hooks() { add_action('admin_menu', [$this, 'add_admin_menu'], 55); add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']); add_action('admin_footer', [$this, 'render_popup_modals_in_footer']); add_action('wp_ajax_jltma_popup_get_data', [$this, 'get_popup_data']); add_action('wp_ajax_jltma_popup_save_data', [$this, 'save_popup_data']); add_action('wp_ajax_jltma_popup_delete', [$this, 'delete_popup']); add_action('wp_ajax_jltma_popup_get_templates', [$this, 'get_popup_templates']); add_action('wp_ajax_jltma_popup_import_template', [$this, 'import_popup_template']); add_filter('submenu_file', [$this, 'highlight_popup_menu'], 10, 2); } public function add_admin_menu() { add_submenu_page( 'master-addons-settings', __('Popup Builder', 'master-addons'), __('Popup Builder', 'master-addons'), 'manage_options', 'edit.php?post_type=jltma_popup' ); } public function highlight_popup_menu($submenu_file, $parent_file) { global $current_screen; if ($current_screen && $current_screen->post_type === $this->popup_cpt->get_post_type()) { $submenu_file = 'edit.php?post_type=jltma_popup'; } return $submenu_file; } /** * Render popup modals in footer (similar to Theme Builder) */ public function render_popup_modals_in_footer() { $screen = get_current_screen(); if ($screen && $screen->id === 'edit-jltma_popup') { $this->render_popup_modal(); $this->render_templates_modal(); } } private function render_popup_modal() { ?>
id !== 'edit-jltma_popup') { return; } // Enqueue popup builder assets via Assets Manager Assets_Manager::enqueue('popup-builder-admin'); // Condition type options (Pro adds "Exclude") $condition_type_options = apply_filters('master_addons/popup_builder/condition_type_options', [ ['value' => 'include', 'label' => __('Include', 'master-addons')], ['value' => 'exclude', 'label' => __('Exclude (Pro)', 'master-addons'), 'pro' => true], ]); // Condition rule options (Pro unlocks all beyond "Entire Site") $condition_rule_options = apply_filters('master_addons/popup_builder/condition_rule_options', [ ['value' => 'entire_site', 'label' => __('Entire Site', 'master-addons')], ['value' => 'front_page', 'label' => __('Front Page (Pro)', 'master-addons'), 'pro' => true], ['value' => 'singular', 'label' => __('Singular (Pro)', 'master-addons'), 'pro' => true], ['value' => 'archive', 'label' => __('Archive (Pro)', 'master-addons'), 'pro' => true], ['value' => 'search', 'label' => __('Search (Pro)', 'master-addons'), 'pro' => true], ['value' => '404', 'label' => __('404 Page (Pro)', 'master-addons'), 'pro' => true], ]); // Localize script with REST API endpoints wp_localize_script('jltma-popup-builder-admin', 'jltmaPopupAdmin', [ 'resturl' => get_rest_url() . 'master-addons/v1/', 'nonce' => wp_create_nonce('wp_rest'), 'ajax_url' => admin_url('admin-ajax.php'), 'admin_url' => admin_url(), 'plugin_url' => JLTMA_URL, 'popup_nonce' => wp_create_nonce('jltma_popup_nonce'), 'woocommerce_active' => class_exists('WooCommerce'), 'is_premium' => apply_filters('master_addons/is_premium', false), 'condition_type_options' => $condition_type_options, 'condition_rule_options' => $condition_rule_options, 'strings' => [ 'confirm_delete' => __('Are you sure you want to delete this popup?', 'master-addons'), 'saving' => __('Saving...', 'master-addons'), 'saved' => __('Popup saved successfully!', 'master-addons'), 'error' => __('An error occurred. Please try again.', 'master-addons'), 'popup_name_required' => __('Popup name is required.', 'master-addons'), 'loading_templates' => __('Loading templates...', 'master-addons'), 'importing_template' => __('Importing template...', 'master-addons'), 'template_imported' => __('Template imported successfully!', 'master-addons'), 'import_failed' => __('Failed to import template. Please try again.', 'master-addons'), 'all_categories' => __('All', 'master-addons'), 'use_template' => __('Import', 'master-addons'), 'preview' => __('Preview', 'master-addons'), 'no_templates' => __('No templates found.', 'master-addons'), 'search_placeholder' => __('Search templates...', 'master-addons'), 'retry' => __('Retry', 'master-addons'), 'load_error' => __('Failed to load templates. Please check your connection and try again.', 'master-addons'), ] ]); // Global masteraddons variable for consistency wp_localize_script('jltma-popup-builder-admin', 'masteraddons', [ 'resturl' => get_rest_url() . 'masteraddons/v2/', 'rest_nonce' => wp_create_nonce('wp_rest'), 'ajax_nonce' => wp_create_nonce('jltma_frontend_ajax_nonce'), 'woocommerce_active' => class_exists('WooCommerce'), ]); } public function get_popup_data() { check_ajax_referer('jltma_popup_nonce', '_nonce'); $popup_id = isset( $_GET['popup_id'] ) ? absint( $_GET['popup_id'] ) : 0; if (!$popup_id) { wp_send_json_error(['message' => 'Invalid popup ID']); } $popup = get_post($popup_id); if (!$popup || $popup->post_type !== $this->popup_cpt->get_post_type()) { wp_send_json_error(['message' => 'Popup not found']); } $data = [ 'id' => $popup_id, 'title' => $popup->post_title, 'activation' => get_post_meta($popup_id, '_jltma_popup_activation', true) ?: 'no', 'conditions_data' => get_post_meta($popup_id, '_jltma_popup_conditions_data', true) ?: [], ]; wp_send_json_success($data); } public function save_popup_data() { check_ajax_referer('jltma_popup_nonce', '_nonce'); $popup_id = isset($_POST['popup_id']) ? intval($_POST['popup_id']) : 0; $title = isset($_POST['title']) ? sanitize_text_field(wp_unslash($_POST['title'])) : ''; $activation = isset($_POST['activation']) ? sanitize_text_field(wp_unslash($_POST['activation'])) : ''; // Handle conditions data $conditions_data = $this->parse_conditions_from_post(); if ($popup_id) { // Update existing popup wp_update_post([ 'ID' => $popup_id, 'post_title' => $title, ]); } else { // Create new popup $popup_id = wp_insert_post([ 'post_title' => $title, 'post_type' => $this->popup_cpt->get_post_type(), 'post_status' => 'publish', ]); if (is_wp_error($popup_id)) { wp_send_json_error(['message' => 'Failed to create popup']); return; } } // Free: only allow include + entire_site. Pro hooks this filter to return data as-is. $conditions_data = apply_filters('master_addons/popup_builder/sanitize_conditions', $this->sanitize_free_conditions($conditions_data) ); // Save meta data update_post_meta($popup_id, '_jltma_popup_activation', $activation); update_post_meta($popup_id, '_jltma_popup_conditions_data', $conditions_data); // Enable Elementor for this post with our custom document type if (defined('ELEMENTOR_VERSION')) { update_post_meta($popup_id, '_elementor_edit_mode', 'builder'); update_post_meta($popup_id, '_elementor_template_type', 'jltma_popup'); update_post_meta($popup_id, '_wp_page_template', 'elementor_canvas'); } // Get proper Elementor edit URL $edit_url = get_edit_post_link($popup_id); if (defined('ELEMENTOR_VERSION')) { try { $document = \Elementor\Plugin::$instance->documents->get($popup_id); if ($document) { $edit_url = $document->get_edit_url(); } else { // Fallback to standard Elementor URL format $edit_url = admin_url('post.php?post=' . $popup_id . '&action=elementor'); } } catch (\Exception $e) { // Fallback to standard Elementor URL format $edit_url = admin_url('post.php?post=' . $popup_id . '&action=elementor'); } } $response_data = [ 'id' => $popup_id, 'title' => $title, 'activation' => $activation, 'edit_url' => $edit_url, ]; wp_send_json_success($response_data); } public function delete_popup() { check_ajax_referer('jltma_popup_nonce', '_nonce'); $popup_id = isset( $_POST['popup_id'] ) ? absint( $_POST['popup_id'] ) : 0; if (!$popup_id) { wp_send_json_error(['message' => 'Invalid popup ID']); } $result = wp_delete_post($popup_id, true); if ($result) { wp_send_json_success(['message' => 'Popup deleted successfully']); } else { wp_send_json_error(['message' => 'Failed to delete popup']); } } private function render_templates_modal() { ?>

'Unauthorized']); return; } $cache = Template_Library_Cache::get_instance(); $templates = $cache->get_cached_templates('master_popups'); $categories = $cache->get_cached_categories('master_popups'); if ($templates === false) { $templates = []; } if ($categories === false) { $categories = []; } // Normalize categories from {"slug": "name"} object to [{slug, name}] array $normalized_categories = []; if (is_array($categories) || is_object($categories)) { foreach ($categories as $slug => $name) { $normalized_categories[] = [ 'slug' => $slug, 'name' => is_string($name) ? $name : (string) $name, ]; } } wp_send_json_success([ 'templates' => $templates, 'categories' => $normalized_categories, ]); } /** * AJAX: Import a popup template */ public function import_popup_template() { check_ajax_referer('jltma_popup_nonce', '_nonce'); if (!current_user_can('manage_options')) { wp_send_json_error(['message' => 'Unauthorized']); return; } $template_id = intval($_POST['template_id'] ?? 0); $title = sanitize_text_field( wp_unslash( $_POST['title'] ?? '' ) ); if (!$template_id) { wp_send_json_error(['message' => 'Invalid template ID']); return; } if (empty($title)) { $title = 'Popup #' . $template_id; } // Fetch template content via the existing API source $elementor_content = null; if (function_exists('MasterAddons\\Inc\\Admin\\Templates\\master_addons_templates')) { $templates_instance = Templates\master_addons_templates(); if ($templates_instance && isset($templates_instance->temp_manager)) { $source = $templates_instance->temp_manager->get_source('master-api'); if ($source) { $template_data = $source->get_item($template_id, 'master_popups'); if ($template_data && !empty($template_data['content'])) { $elementor_content = $template_data['content']; } } } } // Fallback: read directly from the cached template file (bulk-cached format uses 'dependencies') if (empty($elementor_content) && class_exists('MasterAddons\Inc\Classes\Template_Library_Cache')) { $cache_dir = wp_upload_dir()['basedir'] . '/master_addons/templates-library/master_popups/templates/'; $cache_file = $cache_dir . 'template-' . $template_id . '.json'; if (file_exists($cache_file)) { $cached_raw = json_decode(file_get_contents($cache_file), true); if ($cached_raw && !empty($cached_raw['dependencies'])) { $elementor_content = $cached_raw['dependencies']; } elseif ($cached_raw && !empty($cached_raw['content'])) { $elementor_content = $cached_raw['content']; } } } // Create the popup post $popup_id = wp_insert_post([ 'post_title' => $title, 'post_type' => $this->popup_cpt->get_post_type(), 'post_status' => 'publish', ]); if (is_wp_error($popup_id)) { wp_send_json_error(['message' => 'Failed to create popup']); return; } // Set Elementor data if template content was fetched if (!empty($elementor_content)) { if (is_array($elementor_content)) { $elementor_content = wp_json_encode($elementor_content); } update_post_meta($popup_id, '_elementor_data', wp_slash($elementor_content)); if (defined('ELEMENTOR_VERSION')) { update_post_meta($popup_id, '_elementor_version', ELEMENTOR_VERSION); // Clear Elementor cache so it picks up the new content if (class_exists('\Elementor\Plugin')) { \Elementor\Plugin::$instance->files_manager->clear_cache(); } } } // Set activation and default conditions $activation = sanitize_text_field( wp_unslash( $_POST['activation'] ?? 'no' ) ); update_post_meta($popup_id, '_jltma_popup_activation', $activation); // Parse conditions if provided $conditions_data = $this->parse_conditions_from_post(); if (empty($conditions_data)) { $conditions_data = [['type' => 'include', 'rule' => 'entire_site', 'specific' => '', 'posts' => []]]; } update_post_meta($popup_id, '_jltma_popup_conditions_data', $conditions_data); // Enable Elementor for this post if (defined('ELEMENTOR_VERSION')) { update_post_meta($popup_id, '_elementor_edit_mode', 'builder'); update_post_meta($popup_id, '_elementor_template_type', 'jltma_popup'); update_post_meta($popup_id, '_wp_page_template', 'elementor_canvas'); } // Get Elementor edit URL $edit_url = admin_url('post.php?post=' . $popup_id . '&action=elementor'); if (defined('ELEMENTOR_VERSION')) { try { $document = \Elementor\Plugin::$instance->documents->get($popup_id); if ($document) { $edit_url = $document->get_edit_url(); } } catch (\Exception $e) { // Fallback already set above } } wp_send_json_success([ 'id' => $popup_id, 'title' => $title, 'edit_url' => $edit_url, ]); } /** * Parse conditions from POST data (reusable helper) */ /** * Sanitize conditions for free version — only allow include + entire_site. */ private function sanitize_free_conditions($conditions_data) { if (empty($conditions_data) || !is_array($conditions_data)) { return [['type' => 'include', 'rule' => 'entire_site']]; } $filtered = array_filter($conditions_data, function ($c) { return (isset($c['type']) && $c['type'] === 'include' && isset($c['rule']) && $c['rule'] === 'entire_site'); }); return !empty($filtered) ? array_values($filtered) : [['type' => 'include', 'rule' => 'entire_site']]; } private function parse_conditions_from_post() { $conditions_data = []; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in calling method (import_popup_template) $condition_types = isset( $_POST['jltma_condition_type'] ) ? map_deep( wp_unslash( $_POST['jltma_condition_type'] ), 'sanitize_text_field' ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Missing // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in calling method (import_popup_template) $condition_rules = isset( $_POST['jltma_condition_rule'] ) ? map_deep( wp_unslash( $_POST['jltma_condition_rule'] ), 'sanitize_text_field' ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Missing // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in calling method (import_popup_template) $condition_specifics = isset( $_POST['jltma_condition_specific'] ) ? map_deep( wp_unslash( $_POST['jltma_condition_specific'] ), 'sanitize_text_field' ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Missing // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in calling method (import_popup_template) $condition_posts = isset( $_POST['jltma_condition_posts'] ) ? map_deep( wp_unslash( $_POST['jltma_condition_posts'] ), 'sanitize_text_field' ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Missing foreach ($condition_types as $index => $type) { $rule = $condition_rules[$index] ?? ''; $specific = $condition_specifics[$index] ?? ''; $posts = $condition_posts[$index] ?? []; if (!empty($type) && !empty($rule)) { $conditions_data[] = [ 'type' => sanitize_text_field($type), 'rule' => sanitize_text_field($rule), 'specific' => sanitize_text_field($specific), 'posts' => array_map('intval', (array) $posts), ]; } } return $conditions_data; } }