'product_cat', 'hide_empty' => false, ]); if (is_wp_error($product_categories)) { $product_categories = []; } $product_tags = get_terms([ 'taxonomy' => 'product_tag', 'hide_empty' => false, ]); if (is_wp_error($product_tags)) { $product_tags = []; } // Get all products for specific product conditions $products = get_posts([ 'post_type' => 'product', 'posts_per_page' => 100, 'post_status' => 'publish', 'orderby' => 'title', 'order' => 'ASC', ]); /** * Helper function to deactivate conflicting templates. * Only deactivates templates with EXACTLY the same condition. * * @param int $current_template_id The template being activated. * @param string $template_type The template type. * @param array $new_conditions The new conditions being set. */ function ka_woo_deactivate_conflicting_templates(int $current_template_id, string $template_type, array $new_conditions): void { $new_condition_type = $new_conditions['rules'][0]['type'] ?? 'all'; $new_condition_values = $new_conditions['rules'][0]['values'] ?? []; // Get all templates of the same type $query = new WP_Query([ 'post_type' => 'elementor_library', 'posts_per_page' => -1, 'post_status' => ['publish', 'draft'], 'post__not_in' => [$current_template_id], 'meta_query' => [ [ 'key' => 'ka_woo_template_type', 'value' => $template_type, ], ], ]); foreach ($query->posts as $post) { $conditions = get_post_meta($post->ID, 'ka_woo_conditions', true); if (empty($conditions['enabled'])) { continue; } $existing_type = $conditions['rules'][0]['type'] ?? 'all'; $existing_values = $conditions['rules'][0]['values'] ?? []; // Check if conditions conflict (same type and overlapping values) $should_deactivate = false; $new_is_global = in_array($new_condition_type, ['all', 'always'], true); $existing_is_global = in_array($existing_type, ['all', 'always'], true); if ($new_is_global && $existing_is_global) { // Both are "all" - conflict $should_deactivate = true; } elseif ($new_condition_type === $existing_type && !empty($new_condition_values) && !empty($existing_values)) { // Same type with specific values - check for overlap $overlap = array_intersect($new_condition_values, $existing_values); if (!empty($overlap)) { $should_deactivate = true; } } if ($should_deactivate) { $conditions['enabled'] = false; update_post_meta($post->ID, 'ka_woo_conditions', $conditions); } } } // Handle create template action - create post and redirect to Elementor editor if (!empty($_GET['ka_woo_create']) && !empty($_GET['ka_woo_template_type'])) { $template_type = sanitize_key($_GET['ka_woo_template_type']); $valid_types = ['single_product', 'product_archive', 'cart', 'checkout', 'my_account']; if (in_array($template_type, $valid_types, true) && current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'ka_woo_create_' . $template_type)) { // Check Pro restriction if (!$can_use_pro && in_array($template_type, ['cart', 'checkout', 'my_account'], true)) { wp_safe_redirect(remove_query_arg(['ka_woo_create', 'ka_woo_template_type', '_wpnonce'])); exit; } // Get type label for title $type_labels = [ 'single_product' => __('Single Product', 'king-addons'), 'product_archive' => __('Shop & Category', 'king-addons'), 'cart' => __('Cart', 'king-addons'), 'checkout' => __('Checkout', 'king-addons'), 'my_account' => __('My Account', 'king-addons'), ]; // Create new post $post_id = wp_insert_post([ 'post_title' => $type_labels[$template_type] ?? __('WooCommerce Template', 'king-addons'), 'post_type' => 'elementor_library', 'post_status' => 'draft', ]); if ($post_id && !is_wp_error($post_id)) { // Set template type meta update_post_meta($post_id, 'ka_woo_template_type', $template_type); // Use 'page' as Elementor template type - this ensures Elementor editor works // Our custom document type may not be properly supported update_post_meta($post_id, '_elementor_template_type', 'page'); // Set default conditions (enabled by default) $default_rule_type = in_array($template_type, ['cart', 'checkout', 'my_account'], true) ? 'always' : 'all'; $default_conditions = [ 'enabled' => true, 'priority' => 10, 'rules' => [ [ 'type' => $default_rule_type, 'values' => [], ], ], ]; update_post_meta($post_id, 'ka_woo_conditions', $default_conditions); // Set _elementor_edit_mode so Elementor knows to use builder update_post_meta($post_id, '_elementor_edit_mode', 'builder'); // Initialize empty Elementor data update_post_meta($post_id, '_elementor_data', '[]'); // Redirect to Elementor editor $elementor_url = add_query_arg([ 'post' => $post_id, 'action' => 'elementor', ], admin_url('post.php')); wp_safe_redirect($elementor_url); exit; } } wp_safe_redirect(remove_query_arg(['ka_woo_create', 'ka_woo_template_type', '_wpnonce'])); exit; } // Handle toggle action if (!empty($_GET['ka_woo_toggle']) && !empty($_GET['template_id'])) { $template_id = (int) $_GET['template_id']; if (current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'ka_woo_toggle_' . $template_id)) { $conditions = get_post_meta($template_id, 'ka_woo_conditions', true); if (!is_array($conditions)) { $conditions = ['enabled' => false, 'rules' => [['type' => 'all', 'values' => []]]]; } $will_enable = empty($conditions['enabled']); $conditions['enabled'] = $will_enable; update_post_meta($template_id, 'ka_woo_conditions', $conditions); // If enabling, deactivate conflicting templates if ($will_enable) { $template_type = get_post_meta($template_id, 'ka_woo_template_type', true); ka_woo_deactivate_conflicting_templates($template_id, $template_type, $conditions); } } wp_safe_redirect(remove_query_arg(['ka_woo_toggle', 'template_id', '_wpnonce'])); exit; } // Handle conditions update action (Pro only) if (!empty($_POST['ka_woo_update_conditions']) && !empty($_POST['template_id'])) { $template_id = (int) $_POST['template_id']; if (current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'] ?? '')), 'ka_woo_conditions')) { // Only allow in Pro if ($can_use_pro) { $condition_type = sanitize_key($_POST['condition_type'] ?? 'all'); $condition_values = []; if (!empty($_POST['condition_values']) && is_array($_POST['condition_values'])) { $condition_values = array_map('intval', $_POST['condition_values']); } $template_type = (string) get_post_meta($template_id, 'ka_woo_template_type', true); $allowed_types = []; if ('single_product' === $template_type) { $allowed_types = ['all', 'product_cat', 'product_tag', 'specific_product']; } elseif ('product_archive' === $template_type) { $allowed_types = ['all', 'shop', 'product_cat', 'product_tag']; } elseif (in_array($template_type, ['cart', 'checkout', 'my_account'], true)) { $allowed_types = ['always']; } if (!in_array($condition_type, $allowed_types, true)) { $condition_type = $allowed_types[0] ?? 'all'; } // If a "specific" selector is chosen but nothing selected, treat it as global. if (in_array($condition_type, ['product_cat', 'product_tag', 'specific_product'], true) && empty($condition_values)) { $condition_type = 'all'; } $conditions = get_post_meta($template_id, 'ka_woo_conditions', true); if (!is_array($conditions)) { $conditions = ['enabled' => false]; } $conditions['rules'] = [ [ 'type' => $condition_type, 'values' => $condition_values, ], ]; update_post_meta($template_id, 'ka_woo_conditions', $conditions); // If enabled, deactivate conflicting templates if (!empty($conditions['enabled'])) { $template_type = get_post_meta($template_id, 'ka_woo_template_type', true); ka_woo_deactivate_conflicting_templates($template_id, $template_type, $conditions); } } } wp_safe_redirect(add_query_arg('page', 'king-addons-woo-builder', admin_url('admin.php'))); exit; } // Handle duplicate action if (!empty($_GET['ka_woo_duplicate']) && !empty($_GET['template_id'])) { $template_id = (int) $_GET['template_id']; if (current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'ka_woo_duplicate_' . $template_id)) { $original_post = get_post($template_id); if ($original_post && 'elementor_library' === $original_post->post_type) { // Create duplicate $new_post_id = wp_insert_post([ 'post_title' => $original_post->post_title . ' ' . __('(Copy)', 'king-addons'), 'post_type' => 'elementor_library', 'post_status' => 'draft', 'post_content' => $original_post->post_content, ]); if ($new_post_id && !is_wp_error($new_post_id)) { // Copy all meta $meta = get_post_meta($template_id); foreach ($meta as $key => $values) { foreach ($values as $value) { add_post_meta($new_post_id, $key, maybe_unserialize($value)); } } // Set as inactive by default $conditions = get_post_meta($new_post_id, 'ka_woo_conditions', true); if (!is_array($conditions)) { $conditions = []; } $conditions['enabled'] = false; update_post_meta($new_post_id, 'ka_woo_conditions', $conditions); } } } wp_safe_redirect(remove_query_arg(['ka_woo_duplicate', 'template_id', '_wpnonce'])); exit; } // Handle rename action (AJAX) if (!empty($_POST['ka_woo_rename']) && !empty($_POST['template_id']) && !empty($_POST['new_title'])) { if (current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'] ?? '')), 'ka_woo_rename')) { $template_id = (int) $_POST['template_id']; $new_title = sanitize_text_field(wp_unslash($_POST['new_title'])); wp_update_post([ 'ID' => $template_id, 'post_title' => $new_title, ]); } wp_safe_redirect(remove_query_arg(['ka_woo_rename', 'template_id', 'new_title', '_wpnonce'])); exit; } // Handle change type action if (!empty($_GET['ka_woo_change_type']) && !empty($_GET['template_id']) && !empty($_GET['new_type'])) { $template_id = (int) $_GET['template_id']; $new_type = sanitize_key($_GET['new_type']); $valid_types = ['single_product', 'product_archive', 'cart', 'checkout', 'my_account']; if (current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'ka_woo_change_type_' . $template_id)) { if (in_array($new_type, $valid_types, true)) { // Check Pro restriction for target type if ($can_use_pro || !in_array($new_type, ['cart', 'checkout', 'my_account'], true)) { update_post_meta($template_id, 'ka_woo_template_type', $new_type); } } } wp_safe_redirect(remove_query_arg(['ka_woo_change_type', 'template_id', 'new_type', '_wpnonce'])); exit; } // Handle delete action if (!empty($_GET['ka_woo_delete']) && !empty($_GET['template_id'])) { $template_id = (int) $_GET['template_id']; if (current_user_can('manage_options') && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'ka_woo_delete_' . $template_id)) { wp_trash_post($template_id); } wp_safe_redirect(remove_query_arg(['ka_woo_delete', 'template_id', '_wpnonce'])); exit; } // Template types $types = [ 'single_product' => [ 'label' => esc_html__('Single Product', 'king-addons'), 'icon' => '', 'desc' => esc_html__('Customize product pages', 'king-addons'), ], 'product_archive' => [ 'label' => esc_html__('Shop & Category', 'king-addons'), 'icon' => '', 'desc' => esc_html__('Design shop & category pages', 'king-addons'), ], 'cart' => [ 'label' => esc_html__('Cart', 'king-addons'), 'icon' => '', 'desc' => esc_html__('Custom cart layout', 'king-addons'), 'pro' => true, ], 'checkout' => [ 'label' => esc_html__('Checkout', 'king-addons'), 'icon' => '', 'desc' => esc_html__('Streamlined checkout', 'king-addons'), 'pro' => true, ], 'my_account' => [ 'label' => esc_html__('My Account', 'king-addons'), 'icon' => '', 'desc' => esc_html__('Account dashboard', 'king-addons'), 'pro' => true, ], ]; // Create links for each type - now uses our custom handler that creates the post and redirects to Elementor $create_links = []; foreach ($types as $slug => $data) { $create_links[$slug] = wp_nonce_url( add_query_arg( [ 'page' => 'king-addons-woo-builder', 'ka_woo_create' => '1', 'ka_woo_template_type' => $slug, ], admin_url('admin.php') ), 'ka_woo_create_' . $slug ); } // Get existing templates $query = new WP_Query([ 'post_type' => 'elementor_library', 'posts_per_page' => -1, 'post_status' => ['publish', 'draft'], 'meta_query' => [ [ 'key' => 'ka_woo_template_type', 'compare' => 'EXISTS', ], ], ]); $templates = []; foreach ($query->posts as $post) { $type = get_post_meta($post->ID, 'ka_woo_template_type', true); if (empty($type)) continue; $conditions = get_post_meta($post->ID, 'ka_woo_conditions', true); if (!is_array($conditions)) { $conditions = ['enabled' => false, 'rules' => [['type' => 'all', 'values' => []]]]; } $enabled = !empty($conditions['enabled']); $pro_locked = (!$can_use_pro && in_array($type, ['cart', 'checkout', 'my_account'], true)); // Parse condition for display $condition_type = $conditions['rules'][0]['type'] ?? 'all'; $condition_values = $conditions['rules'][0]['values'] ?? []; $condition_label = __('All', 'king-addons'); if (in_array($condition_type, ['always'], true)) { $condition_label = __('Always', 'king-addons'); } elseif (in_array($condition_type, ['shop', 'is_shop'], true)) { $condition_label = __('Shop Page Only', 'king-addons'); } elseif ('all' === $condition_type) { if ('single_product' === $type) { $condition_label = __('All Products', 'king-addons'); } elseif ('product_archive' === $type) { $condition_label = __('All Categories', 'king-addons'); } else { $condition_label = __('Always', 'king-addons'); } } elseif (!empty($condition_values)) { switch ($condition_type) { case 'product_cat': $cat_names = []; foreach ($condition_values as $cat_id) { $term = get_term($cat_id, 'product_cat'); if ($term && !is_wp_error($term)) { $cat_names[] = $term->name; } } $condition_label = !empty($cat_names) ? implode(', ', $cat_names) : __('Categories', 'king-addons'); break; case 'product_tag': $tag_names = []; foreach ($condition_values as $tag_id) { $term = get_term($tag_id, 'product_tag'); if ($term && !is_wp_error($term)) { $tag_names[] = $term->name; } } $condition_label = !empty($tag_names) ? implode(', ', $tag_names) : __('Tags', 'king-addons'); break; case 'specific_product': $product_titles = []; foreach ($condition_values as $product_id) { $product_titles[] = get_the_title($product_id); } $condition_label = !empty($product_titles) ? implode(', ', $product_titles) : __('Specific Products', 'king-addons'); break; } } $templates[] = [ 'id' => $post->ID, 'title' => get_the_title($post), 'type' => $type, 'enabled' => $enabled, 'status' => $post->post_status, 'date' => get_the_modified_date('M j, Y', $post), 'pro_locked' => $pro_locked, 'condition_type' => $condition_type, 'condition_values' => $condition_values, 'condition_label' => $condition_label, ]; } // Condition options based on template type $condition_options = [ 'single_product' => [ 'all' => __('All Products', 'king-addons'), 'product_cat' => __('Specific Categories', 'king-addons'), 'product_tag' => __('Specific Tags', 'king-addons'), 'specific_product' => __('Specific Products', 'king-addons'), ], 'product_archive' => [ 'all' => __('All Categories', 'king-addons'), 'shop' => __('Shop Page Only', 'king-addons'), 'product_cat' => __('Specific Categories (or Archives)', 'king-addons'), 'product_tag' => __('Specific Tags', 'king-addons'), ], 'cart' => [ 'always' => __('Always', 'king-addons'), ], 'checkout' => [ 'always' => __('Always', 'king-addons'), ], 'my_account' => [ 'always' => __('Always', 'king-addons'), ], ]; // Get Elementor edit URL if (!function_exists('ka_woo_get_elementor_edit_url')) { function ka_woo_get_elementor_edit_url(int $post_id): string { return add_query_arg(['post' => $post_id, 'action' => 'elementor'], admin_url('post.php')); } } ?>

$data): ?> < class="ka-wb-type "> Pro
>

'; $duplicate_url = wp_nonce_url(add_query_arg([ 'page' => 'king-addons-woo-builder', 'template_id' => $template['id'], 'ka_woo_duplicate' => 1, ], admin_url('admin.php')), 'ka_woo_duplicate_' . $template['id']); $delete_url = wp_nonce_url(add_query_arg([ 'page' => 'king-addons-woo-builder', 'template_id' => $template['id'], 'ka_woo_delete' => 1, ], admin_url('admin.php')), 'ka_woo_delete_' . $template['id']); ?>
__('All', 'king-addons')]; $show_conditions_button = count($template_options) > 1; // Show only if template type supports conditions ?>
$type_data): ?> 'king-addons-woo-builder', 'template_id' => $template['id'], 'ka_woo_change_type' => 1, 'new_type' => $type_slug, ], admin_url('admin.php')), 'ka_woo_change_type_' . $template['id']); ?>