can_use_premium_code(); // TODO: TEST: For UI testing, it doesn't enable the real premium // $is_premium_active = false; // Arrays for categories and tags $categories = []; $tags = []; $category_counts = []; // Getting unique categories and tags foreach ($templates['templates'] as $template) { if (!in_array($template['category'], $categories)) { $categories[] = $template['category']; } foreach ($template['tags'] as $tag) { if (!in_array($tag, $tags)) { $tags[] = $tag; } } $category = $template['category']; $category_counts[$category] = isset($category_counts[$category]) ? $category_counts[$category] + 1 : 1; } sort($categories); // Get filters from query $search_query = isset($_GET['s']) ? sanitize_text_field($_GET['s']) : ''; $selected_category = isset($_GET['category']) ? sanitize_text_field($_GET['category']) : ''; $selected_collection = isset($_GET['collection']) ? sanitize_text_field($_GET['collection']) : ''; $selected_tags = isset($_GET['tags']) ? array_filter(explode(',', sanitize_text_field($_GET['tags']))) : []; $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; // Use the common function to get filtered templates and pagination $result = $this->get_filtered_templates($templates, $search_query, $selected_category, $selected_tags, $selected_collection, $current_page); if (isset($_GET['ajax']) && $_GET['ajax']) { wp_send_json_success(['grid_html' => $result['grid_html'], 'pagination_html' => $result['pagination_html']]); } if ($is_premium_active) { ?>

can_use_premium_code()): ?> can_use_premium_code()): ?>
Tags
  • $4.99/month
  • '; echo '
  • Unlimited Downloads
  • '; echo '
  • Keep all templates forever
  • '; ?>
    $template) { $found_in_title = false; $found_in_tags = false; foreach ($search_terms as $term) { if ($term && stripos($template['title'], $term) !== false) { $found_in_title = true; } foreach ($template['tags'] as $tag) { if (stripos($tag, $term) !== false) { $found_in_tags = true; break; } } // if (!$found_in_title && !$found_in_tags) { // continue; // } } if ($selected_category && $template['category'] !== $selected_category) { continue; } if ($selected_tags) { $template_tags = $template['tags']; foreach ($selected_tags as $tag) { if (!in_array($tag, $template_tags)) { continue 2; } } } if ($selected_collection && $template['collection'] != $selected_collection) { continue; } // Attach the template key for later use $template['template_key'] = $key; if ($found_in_title) { $matched_by_title[] = $template; } elseif ($found_in_tags) { $matched_by_tags[] = $template; } } // Combine the arrays, so templates matching by title come first $filtered_templates = array_merge($matched_by_title, $matched_by_tags); } } // Pagination setup $items_per_page = 20; $total_templates = count($filtered_templates); $offset = ($current_page - 1) * $items_per_page; $paged_templates = array_slice($filtered_templates, $offset, $items_per_page); ob_start(); if (empty($paged_templates)) { echo '

    ' . esc_html__('No templates found.', 'king-addons') . '

    '; } else { foreach ($paged_templates as $key => $template) { $attr_key = ($has_search) ? $template['template_key'] : $key; ?>
    " alt="">

    add_query_arg(array( 'paged' => '%#%', 's' => $search_query, 'category' => $selected_category, 'collection' => $selected_collection, 'tags' => implode(',', $selected_tags), )), 'format' => '?paged=%#%', 'current' => $current_page, 'total' => ceil($total_templates / $items_per_page), 'prev_text' => __('← Previous', 'king-addons'), 'next_text' => __('Next →', 'king-addons'), 'end_size' => 9, 'mid_size' => 3, )); if ($pages) { echo '
    '; echo $pages; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '
    '; } $pagination_html = ob_get_clean(); return ['grid_html' => $grid_html, 'pagination_html' => $pagination_html]; } public function king_addons_enqueue_scripts(): void { $screen = get_current_screen(); if ($screen->id === 'toplevel_page_king-addons-templates') { wp_enqueue_style('king-addons-templates-style', KING_ADDONS_URL . 'includes/admin/css/templates.css', '', KING_ADDONS_VERSION); if (!wp_script_is(KING_ADDONS_ASSETS_UNIQUE_KEY . '-' . 'jquery' . '-' . 'jquery')) { wp_enqueue_script(KING_ADDONS_ASSETS_UNIQUE_KEY . '-' . 'jquery' . '-' . 'jquery', '', '', KING_ADDONS_VERSION); } wp_enqueue_script('king-addons-templates-script', KING_ADDONS_URL . 'includes/admin/js/templates.js', '', KING_ADDONS_VERSION, true); wp_localize_script('king-addons-templates-script', 'kingAddonsData', array( 'adminUrl' => admin_url('admin-post.php'), 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('kingAddonsNonce'), )); } // if ($screen->id === 'king-addons_page_king-addons-account') { // wp_enqueue_style('king-addons-account-style', KING_ADDONS_URL . 'includes/admin/css/account.css', '', KING_ADDONS_VERSION); // } } public function __construct() { add_action('admin_enqueue_scripts', array($this, 'king_addons_enqueue_scripts')); // Get the performance setting $improve_import = get_option('king_addons_improve_import_performance', '1'); // Conditionally add time limit adjustments based on setting if ($improve_import === '1') { add_action('wp_ajax_import_elementor_page_with_images', function () { @set_time_limit(300); }, 0); add_action('wp_ajax_process_import_images', function () { @set_time_limit(300); }, 0); } add_action( 'wp_ajax_import_elementor_page_with_images', [$this, 'import_elementor_page_with_images'] ); add_action( 'wp_ajax_process_import_images', [$this, 'process_import_images'] ); add_action('wp_ajax_filter_templates', array($this, 'handle_filter_templates')); // Sections catalog endpoints add_action('wp_ajax_king_addons_get_sections_catalog', array($this, 'handle_get_sections_catalog')); add_action('wp_ajax_king_addons_import_section_admin', array($this, 'handle_import_section_to_page')); add_action('http_api_curl', array($this, 'set_custom_curl_options'), 10, 3); } public function set_custom_curl_options($handle) { curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 60); curl_setopt($handle, CURLOPT_DNS_CACHE_TIMEOUT, 300); curl_setopt($handle, CURLOPT_TIMEOUT, 300); } function handle_filter_templates(): void { if (!current_user_can('manage_options')) { return; } if (!isset($_POST['action']) || $_POST['action'] !== 'filter_templates') { wp_send_json_error('Invalid request'); return; } $search_query = isset($_POST['s']) ? sanitize_text_field($_POST['s']) : ''; $selected_category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : ''; $selected_collection = isset($_POST['collection']) ? sanitize_text_field($_POST['collection']) : ''; $selected_tags = isset($_POST['tags']) ? array_filter(explode(',', sanitize_text_field($_POST['tags']))) : []; $current_page = isset($_POST['paged']) ? max(1, intval($_POST['paged'])) : 1; $templates = TemplatesMap::getTemplatesMapArray(); // Use the common function to get filtered templates and pagination $result = $this->get_filtered_templates($templates, $search_query, $selected_category, $selected_tags, $selected_collection, $current_page); wp_send_json_success(['grid_html' => $result['grid_html'], 'pagination_html' => $result['pagination_html']]); } public function import_elementor_page_with_images(): void { if (!current_user_can('manage_options')) { return; } $import_data = json_decode(stripslashes($_POST['data']), true); if (json_last_error() !== JSON_ERROR_NONE) { wp_send_json_error('JSON decode error: ' . json_last_error_msg()); return; } if (isset($import_data['content']) && isset($import_data['images']) && isset($import_data['title'])) { $content = $import_data['content']; $image_data = $import_data['images']; $page_title = sanitize_text_field($import_data['title']); $elementor_version = sanitize_text_field($import_data['elementor_version']); // Check if this is for existing page (from popup import) $existing_page_id = isset($import_data['existing_page_id']) ? intval($import_data['existing_page_id']) : 0; $create_new_page = isset($import_data['create_new_page']) ? (bool)$import_data['create_new_page'] : true; delete_transient('elementor_import_content'); delete_transient('elementor_import_images'); delete_transient('elementor_import_total_images'); delete_transient('elementor_import_images_processed'); delete_transient('elementor_import_image_retry_count'); delete_transient('elementor_import_page_title'); delete_transient('elementor_import_elementor_version'); delete_transient('elementor_import_existing_page_id'); delete_transient('elementor_import_create_new_page'); set_transient('elementor_import_content', $content, 60 * 60); set_transient('elementor_import_images', $image_data, 60 * 60); set_transient('elementor_import_total_images', count($image_data), 60 * 60); set_transient('elementor_import_images_processed', 0, 60 * 60); set_transient('elementor_import_image_retry_count', [], 60 * 60); set_transient('elementor_import_page_title', $page_title, 60 * 60); set_transient('elementor_import_elementor_version', $elementor_version, 60 * 60); set_transient('elementor_import_existing_page_id', $existing_page_id, 60 * 60); set_transient('elementor_import_create_new_page', $create_new_page, 60 * 60); error_log('King Addons Import: Initialized ' . ($create_new_page ? 'new page' : 'existing page') . ' import. Existing page ID: ' . $existing_page_id); wp_send_json_success([ 'message' => 'Import initialized.', 'images' => $image_data, 'existing_page_id' => $existing_page_id, 'create_new_page' => $create_new_page ]); } else { wp_send_json_error('Invalid import data.'); } } private function replace_image_data(array &$array, $old_url, $new_url, $old_id, $new_id) { foreach ($array as $key => &$value) { if (is_array($value)) { // Standard structure with both 'url' and 'id' if ( isset($value['url'], $value['id']) && $value['url'] === $old_url && $value['id'] === $old_id ) { $value['url'] = $new_url; $value['id'] = $new_id; } // Background image structure (common in Elementor) if ( isset($value['url']) && $value['url'] === $old_url && (!isset($value['id']) || $value['id'] === $old_id) ) { $value['url'] = $new_url; if (isset($value['id'])) { $value['id'] = $new_id; } } // Recursively check deeper nested arrays $this->replace_image_data($value, $old_url, $new_url, $old_id, $new_id); } elseif (is_string($value)) { // Direct URL string replacement if ($value === $old_url) { $array[$key] = $new_url; } // CSS background-image style replacement if (strpos($value, 'background-image:') !== false && strpos($value, $old_url) !== false) { $array[$key] = str_replace($old_url, $new_url, $value); } // URL() function replacement in CSS if (strpos($value, 'url(') !== false && strpos($value, $old_url) !== false) { $array[$key] = str_replace($old_url, $new_url, $value); } // JSON string containing URLs (for widget settings) if (strpos($value, '{') === 0 && strpos($value, $old_url) !== false) { $decoded = json_decode($value, true); if (is_array($decoded)) { $this->replace_image_data($decoded, $old_url, $new_url, $old_id, $new_id); $array[$key] = json_encode($decoded); } } } } } public function process_import_images(): void { // Conditionally increase execution time limit based on setting $improve_import = get_option('king_addons_improve_import_performance', '1'); if ($improve_import === '1') { @set_time_limit(300); } if (!current_user_can('manage_options')) { wp_send_json_error('The current user can not manage options and create pages. Please change it in the WordPress settings.'); return; } $start_time = time(); $timeout = 30; $content = get_transient('elementor_import_content'); $image_data = get_transient('elementor_import_images'); $total_images = get_transient('elementor_import_total_images'); $images_processed = get_transient('elementor_import_images_processed'); $image_retry_count = get_transient('elementor_import_image_retry_count'); $page_title = get_transient('elementor_import_page_title'); $elementor_version = get_transient('elementor_import_elementor_version'); $existing_page_id = get_transient('elementor_import_existing_page_id'); $create_new_page = get_transient('elementor_import_create_new_page'); if (!is_array($image_retry_count)) { $image_retry_count = []; } if ($images_processed < $total_images) { $current_image = $image_data[$images_processed]; $url = $current_image['url']; if (!isset($image_retry_count[$url])) { $image_retry_count[$url] = 0; } $new_image_id = $this->download_image_to_media_gallery($url, $image_retry_count[$url]); if ($new_image_id === false) { $image_retry_count[$url]++; set_transient('elementor_import_image_retry_count', $image_retry_count, 60 * 60); if ($image_retry_count[$url] > 3) { $images_processed++; set_transient('elementor_import_images_processed', $images_processed, 60 * 60); $progress = round(($images_processed / $total_images) * 90) + 10; wp_send_json_success([ 'progress' => $progress, 'message' => "Processed $images_processed of $total_images images.", 'image_url' => $url, 'images_processed' => $images_processed, 'new_image_id' => 'SKIPPED' ]); } else { wp_send_json_error([ 'retry' => true, 'image_url' => $url ]); } } else { $new_url = wp_get_attachment_url($new_image_id); $images_processed++; set_transient('elementor_import_images_processed', $images_processed, 60 * 60); $progress = round(($images_processed / $total_images) * 90) + 10; $this->replace_image_data($content, $url, $new_url, $current_image['id'], $new_image_id); set_transient('elementor_import_content', $content, 60 * 60); wp_send_json_success([ 'progress' => $progress, 'message' => "Processed $images_processed of $total_images images.", 'image_url' => $url, 'new_image_url' => $new_url ]); } } else { // All images processed if ($create_new_page) { // Original behavior - create new page $new_post_id = wp_insert_post([ 'post_title' => $page_title, 'post_content' => '', 'post_status' => 'publish', 'post_type' => 'page', ]); if ($new_post_id) { update_post_meta($new_post_id, '_elementor_data', wp_slash(json_encode($content))); update_post_meta($new_post_id, '_elementor_edit_mode', 'builder'); update_post_meta($new_post_id, '_elementor_template_type', 'page'); update_post_meta($new_post_id, '_elementor_version', $elementor_version); update_post_meta($new_post_id, '_wp_page_template', 'elementor_canvas'); update_post_meta($new_post_id, '_wp_gutenberg_disable', '1'); update_post_meta($new_post_id, '_wp_gutenberg_enabled', '0'); delete_transient('elementor_import_content'); delete_transient('elementor_import_images'); delete_transient('elementor_import_total_images'); delete_transient('elementor_import_images_processed'); delete_transient('elementor_import_image_retry_count'); delete_transient('elementor_import_page_title'); delete_transient('elementor_import_elementor_version'); delete_transient('elementor_import_existing_page_id'); delete_transient('elementor_import_create_new_page'); wp_send_json_success([ 'message' => "Page imported successfully!", 'page_url' => get_permalink($new_post_id), ]); } else { wp_send_json_error('Failed to import page.'); } } else { // New behavior - for existing page, just signal completion // Content and images are processed and stored in transients // Will be merged by king_addons_merge_with_existing_page endpoint error_log('King Addons Import: Image processing completed for existing page. Content ready for merge.'); wp_send_json_success([ 'message' => "Image processing completed! Content ready for merge.", 'images_processed' => $images_processed, 'existing_page_id' => $existing_page_id, 'processing_complete' => true ]); } } if (time() >= $start_time + $timeout) { wp_send_json_error('Process timeout, please resume the import.'); } } public function download_image_to_media_gallery($image_url, $image_retry_count) { try { $response = wp_remote_get($image_url, ['timeout' => 30]); if (is_wp_error($response)) { throw new Exception('HTTP request error: ' . $response->get_error_message()); } $status_code = wp_remote_retrieve_response_code($response); if ($status_code !== 200) { throw new Exception( 'HTTP status code ' . $status_code . ' when trying to download: ' . $image_url ); } $image_data = wp_remote_retrieve_body($response); if (empty($image_data)) { throw new Exception('Failed to retrieve image data from URL: ' . $image_url); } $image_name = pathinfo(basename($image_url), PATHINFO_FILENAME); $image_extension = pathinfo(basename($image_url), PATHINFO_EXTENSION); $unique_image_name = $image_name . '-' . time() . '.' . $image_extension; $upload_dir = wp_upload_dir(); if (! file_exists($upload_dir['path'])) { wp_mkdir_p($upload_dir['path']); } $image_file = $upload_dir['path'] . '/' . $unique_image_name; if (file_put_contents($image_file, $image_data) === false) { throw new Exception('Failed to write image data to file: ' . $image_file); } $wp_filetype = wp_check_filetype($unique_image_name); $attachment = [ 'post_mime_type' => $wp_filetype['type'], 'post_title' => sanitize_file_name($unique_image_name), 'post_content' => '', 'post_status' => 'inherit', ]; $attach_id = wp_insert_attachment($attachment, $image_file); // Conditionally disable intermediate image sizes based on setting $improve_import = get_option('king_addons_improve_import_performance', '1'); if ($improve_import === '1') { // Disable ALL extra sizes and big-image scaling add_filter('intermediate_image_sizes', '__return_empty_array', 999); add_filter('big_image_size_threshold', '__return_false', 999); /* Save only the original file info — no thumbnails, no EXIF */ // Get image dimensions $image_size = getimagesize($image_file); $width = $image_size ? $image_size[0] : 0; $height = $image_size ? $image_size[1] : 0; $meta = [ 'file' => wp_basename($image_file), 'filesize' => filesize($image_file), 'width' => $width, 'height' => $height, 'sizes' => [], 'image_meta' => [], ]; wp_update_attachment_metadata($attach_id, $meta); // Clean up filters remove_filter('intermediate_image_sizes', '__return_empty_array', 999); remove_filter('big_image_size_threshold', '__return_false', 999); } else { if ($image_retry_count > 1) { add_filter('intermediate_image_sizes', '__return_empty_array', 999); } // Generate default metadata if optimization is off require_once(ABSPATH . 'wp-admin/includes/image.php'); $attach_data = wp_generate_attachment_metadata($attach_id, $image_file); wp_update_attachment_metadata($attach_id, $attach_data); if ($image_retry_count > 1) { remove_filter('intermediate_image_sizes', '__return_empty_array', 999); } } return $attach_id; } catch (Exception $e) { error_log('[KING_ADDONS_ERROR] ' . $e->getMessage()); return false; } } /** * AJAX handler for getting sections catalog data */ public function handle_get_sections_catalog(): void { if (!current_user_can('manage_options')) { wp_send_json_error('Insufficient permissions'); return; } // Check nonce - handle both admin area and popup if (isset($_POST['nonce'])) { $valid_nonce = wp_verify_nonce($_POST['nonce'], 'kingAddonsNonce') || wp_verify_nonce($_POST['nonce'], 'king_addons_template_catalog'); if (!$valid_nonce) { wp_send_json_error('Invalid nonce'); return; } } if (!class_exists('King_Addons\\SectionsMap')) { require_once KING_ADDONS_PATH . 'includes/SectionsMap.php'; } $sections_map = SectionsMap::getSectionsMapArray(); $sections = $sections_map['sections'] ?? []; $is_premium_active = function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code(); // Get filters from request $search_query = sanitize_text_field($_POST['search'] ?? ''); $selected_category = sanitize_text_field($_POST['category'] ?? ''); $selected_type = sanitize_text_field($_POST['section_type'] ?? ''); $selected_plan = sanitize_text_field($_POST['plan'] ?? ''); $current_page = max(1, intval($_POST['page'] ?? 1)); // Get categories and section types for filters $categories = []; $section_types = []; foreach ($sections as $section_key => $section) { if (!in_array($section['category'], $categories)) { $categories[] = $section['category']; } if (!in_array($section['section_type'], $section_types)) { $section_types[] = $section['section_type']; } } sort($categories); sort($section_types); // Filter sections $filtered_sections = []; foreach ($sections as $section_key => $section) { // Add section key for frontend $section['section_key'] = $section_key; // Note: Premium sections are shown but restricted for import if no premium license // Apply search filter if (!empty($search_query)) { $found_in_title = stripos($section['title'], $search_query) !== false; $found_in_tags = false; foreach ($section['tags'] ?? [] as $tag) { if (stripos($tag, $search_query) !== false) { $found_in_tags = true; break; } } if (!$found_in_title && !$found_in_tags) { continue; } } // Apply category filter if (!empty($selected_category) && $section['category'] !== $selected_category) { continue; } // Apply section type filter if (!empty($selected_type) && $section['section_type'] !== $selected_type) { continue; } // Apply plan filter if (!empty($selected_plan) && $section['plan'] !== $selected_plan) { continue; } $filtered_sections[] = $section; } // Pagination $items_per_page = 20; $total_sections = count($filtered_sections); $total_pages = ceil($total_sections / $items_per_page); $offset = ($current_page - 1) * $items_per_page; $paged_sections = array_slice($filtered_sections, $offset, $items_per_page); wp_send_json_success([ 'sections' => $paged_sections, 'categories' => $categories, 'section_types' => $section_types, 'pagination' => [ 'current_page' => $current_page, 'total_pages' => $total_pages, 'total_sections' => $total_sections, 'items_per_page' => $items_per_page ], 'is_premium_active' => $is_premium_active ]); } /** * AJAX handler for importing section to current page (from main admin catalog) */ public function handle_import_section_to_page(): void { if (!current_user_can('edit_posts')) { wp_send_json_error('Insufficient permissions'); return; } if (!wp_verify_nonce($_POST['nonce'], 'kingAddonsNonce')) { wp_send_json_error('Invalid nonce'); return; } $section_key = sanitize_text_field($_POST['section_key']); $section_plan = sanitize_text_field($_POST['section_plan']); $is_premium_active = function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code(); // Determine API URL and install ID (same logic as templates) if ($is_premium_active && $section_plan === 'premium') { $api_url = 'https://api.kingaddons.com/get-section.php'; // Use the same method as original templates catalog if (function_exists('king_addons_freemius')) { $freemius_site = king_addons_freemius()->get_site(); $install_id = $freemius_site ? $freemius_site->id : 0; } else { $install_id = 0; } error_log('King Addons Premium Section: Using install_id: ' . $install_id . ' for premium section: ' . $section_key); } elseif ($section_plan === 'free') { $api_url = 'https://api.kingaddons.com/get-section-free.php'; $install_id = 0; error_log('King Addons Free Section: Fetching free section: ' . $section_key); } else { error_log('King Addons Section Error: Premium section requires premium license. Section: ' . $section_key . ', Plan: ' . $section_plan . ', Premium Active: ' . ($is_premium_active ? 'Yes' : 'No')); wp_send_json_error('Premium section requires premium license'); return; } // Get section data from API (same as templates) $response = wp_remote_post($api_url, [ 'headers' => ['Content-Type' => 'application/json'], 'body' => json_encode([ 'key' => $section_key, 'install' => $install_id, ]), 'timeout' => 60 ]); if (is_wp_error($response)) { wp_send_json_error('Failed to fetch section: ' . $response->get_error_message()); return; } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); error_log('King Addons Section API Response: ' . substr($body, 0, 500) . (strlen($body) > 500 ? '...' : '')); if (!$data) { error_log('King Addons Section Error: Failed to decode JSON response'); wp_send_json_error('Invalid JSON response from section API'); return; } if (!isset($data['success']) || !$data['success']) { $error_message = isset($data['message']) ? $data['message'] : 'Unknown API error'; error_log('King Addons Section Error: API returned error: ' . $error_message); wp_send_json_error('Section API error: ' . $error_message); return; } // Return section data for frontend processing (adjust format from your API) wp_send_json_success([ 'section_data' => $data['section'], // Your API returns 'section' not 'landing' 'message' => 'Section data retrieved successfully' ]); } } Templates::instance();