Server : Apache/2.4.18 (Ubuntu) System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64 User : oppastar ( 1041) PHP Version : 7.0.33-0ubuntu0.16.04.15 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, Directory : /proc/self/root/var/www/laciasmara.com/public_html/shop/application/controllers/ |
Upload File : |
<?php defined('BASEPATH') or exit('No direct script access allowed'); class Search extends Public_Controller { public function __construct() { parent::__construct(); $this->load->model('Top_banner_m'); $this->load->model('Review_m'); $this->load->model('Footer_m'); $this->load->model('Statistic_m'); $this->load->model('Category_m'); $this->load->library('GoogleClient'); $this->load->library('VisitorTracking'); $loginUrl = $this->googleclient->getLoginUrl(); $this->data_footer['googleUrl'] = $loginUrl; // if ($this->session->userdata('site_lang') == 'english') { // $this->lang->load('product_detail', 'english'); // $this->lang->load('product_list', 'english'); // } else { // $this->lang->load('product_list', 'indonesian'); // $this->lang->load('product_detail', 'indonesian'); // } } public function index() { // if($this->input->get('search_product')) { $keyword = $this->security->xss_clean($this->input->get('search_product')); $brand = $this->security->xss_clean($this->input->get('brand')); $designer = $this->security->xss_clean($this->input->get('designer')); // } if ($keyword == NULL && $brand == NULL && $designer == NULL) { redirect(base_url()); } //check if post sort_product is exist if ($this->input->get('sort_product')) { $this->session->set_userdata('sort_product', $this->input->get('sort_product')); } //get no. of products per page (pagination) from configuration table $this->db->select('products_displayed')->from('configuration')->where('id_configuration', 1); $per_page = $this->db->get()->row(); //PRODUCTS //pagination in action $this->load->library('pagination'); $config = array(); $this->load->helper('pagination_helper'); // $config = pagination_format(); $config['base_url'] = base_url() . 'search/index/'; $this->load->model('product_m'); $config['total_rows'] = $this->product_m->count_products_by_search($keyword); $config['per_page'] = (int) $per_page->products_displayed; $config['uri_segment'] = 3; $config['reuse_query_string'] = true; $this->pagination->initialize($config); $this->data['sort_product_by'] = $this->session->userdata('sort_product'); $this->data['total_products'] = $config['total_rows']; if ($brand != NULL && $keyword == NULL && $designer == NULL) { $this->data['products'] = $this->product_m->get_products_by_brand($brand, $config['per_page'], $this->uri->segment($config['uri_segment']), ''); } if ($keyword != NULL && $brand == NULL && $designer == NULL) { $this->data['products'] = $this->product_m->get_products_by_search($keyword, $config['per_page'], $this->uri->segment($config['uri_segment'])); } if ($designer != NULL && $brand == NULL && $keyword == NULL) { $this->data['products'] = $this->product_m->get_products_by_designer($designer, $config['per_page'], $this->uri->segment($config['uri_segment']), ''); } $this->data['keyword'] = $keyword; $this->load->helper('product'); //LOAD LANGUAGE FILES FOR PRODUCT LIST PAGE if ($this->session->userdata('site_lang') == 'english') { $this->lang->load('product_detail', 'english'); $this->lang->load('product_list', 'english'); } else { $this->lang->load('product_list', 'indonesian'); $this->lang->load('product_detail', 'indonesian'); } $this->data['category_url'] = 'search'; //get SEO $this->data_header['browser_title'] = 'Search Products'; $this->data_header['meta_description'] = 'Search Products'; $this->load->view("themes/$this->theme_no/header", $this->data_header); $this->load->view("themes/$this->theme_no/product_list", $this->data); $this->load->view("themes/$this->theme_no/footer", $this->data_footer); } public function product() { // Ambil query dari URL $query = $this->input->get('q', TRUE); // 'TRUE' untuk XSS filtering $source = $this->input->get('utm_source', TRUE); $this->visitortracking->trackVisitor(); // Ambil data konfigurasi website $website_data = $this->db->select('website_icon, browser_title, meta_description') ->from('configuration') ->where('id_configuration', 1) ->get() ->row(); $banners = $this->Top_banner_m->get_active_banners(); // Gunakan optimized query untuk pencarian produk $optimized_query = $this->get_optimized_product_query(); // Tambahkan filter pencarian ke query $search_query = " SELECT * FROM ( $optimized_query ) AS product_results WHERE ( product_results.title LIKE ? OR product_results.alias LIKE ? OR EXISTS ( SELECT 1 FROM products p2 WHERE p2.id_products = product_results.id_products AND ( p2.description LIKE ? OR p2.meta_description LIKE ? ) ) OR EXISTS ( SELECT 1 FROM brands b2 WHERE b2.id_brands = product_results.brand_id AND ( b2.brand LIKE ? OR b2.alias LIKE ? ) ) ) ORDER BY product_results.sort_order ASC, product_results.best_seller DESC, product_results.new_arrival DESC, product_results.popular_product DESC, product_results.priority DESC, product_results.brand_priority DESC, product_results.created_at DESC "; // Prepare search parameters $search_term = "%{$query}%"; $search_params = [ $search_term, // title $search_term, // alias $search_term, // description $search_term, // meta_description $search_term, // brand $search_term // brand alias ]; // Execute query $products = $this->db->query($search_query, $search_params)->result_array(); // Format data produk $formatted_products = $this->prepare_search_products($products); $meta_description = ($this->session->userdata('site_lang') == 'english') ? "Can't decide? Just type and find the perfect pleasure to level up your intimate experience!" : "Jangan bingung pilih yang mana! Cukup ketik dan temukan piranti asmara yang cocok untuk nemenin pengalaman intim kamu."; $footer_categories = $this->Footer_m->get_all_categories(); $footer_social_media = $this->Footer_m->get_social_media(); $footer_payment_methods = $this->Footer_m->get_payment_methods(); $footer_asmaradoor = $this->Footer_m->get_asmaradoor(); $footer_bottom = $this->Footer_m->get_footer_bottom(); // Data untuk header $this->data_header = [ 'website_icon' => $website_data->website_icon, 'browser_title' => $website_data->browser_title, 'meta_description' => $meta_description, 'banners' => $banners, 'products' => $formatted_products, 'total_products' => count($formatted_products), 'logo_path' => 'https://storage.googleapis.com/laciasmara-photos/laciaasmara_assets/laciasmara_landing_page/laciasmara_landing_page_logo.webp', 'query' => $query, 'footer_categories' => $footer_categories, 'footer_social_media' => $footer_social_media, 'footer_payment_methods' => $footer_payment_methods, 'footer_asmaradoor' => $footer_asmaradoor, 'footer_bottom' => $footer_bottom, ]; if ($this->session->userdata('site_lang') == 'english') { $this->lang->load('mainpage', 'english'); } else { $this->lang->load('mainpage', 'indonesian'); } $this->data_footer['popular_categories'] = $this->Category_m->get_footer_popular_categories(); $this->data_footer['trending_searches'] = $this->Statistic_m->get_trending_searches(); // Load view $this->load->view("themes/$this->theme_no/header_new", $this->data_header); $this->load->view("themes/$this->theme_no/search_result", $this->data); $this->load->view("themes/$this->theme_no/footer_new", $this->data_footer); } private function get_optimized_product_query() { return " SELECT p.id_products, p.title, p.alias, p.brand_id, p.created_at, p.best_seller, p.new_arrival, p.popular_product, p.priority, -- Product Details COALESCE(primary_variant.id, first_variant.id) AS id_detail, COALESCE(primary_variant.price, first_variant.price) AS price, COALESCE(primary_variant.discounted_price, first_variant.discounted_price) AS discounted_price, COALESCE(primary_variant.sku, first_variant.sku) AS sku, -- Product Images COALESCE( main_image.image, COALESCE(primary_variant_image.image, first_variant_image.image), p.image ) AS image, COALESCE( main_image_secondary.image, COALESCE(primary_variant_image_secondary.image, first_variant_image_secondary.image), p.image1 ) AS image_secondary, -- Stock Information stock_summary.total_stock, stock_summary.total_stock_keep, stock_summary.total_stock_sell, stock_summary.available_variants, stock_summary.total_variants, -- Current variant stock COALESCE( GREATEST(0, COALESCE(primary_variant_stock.stock, 0) - COALESCE(primary_variant_stock.stock_keep, 0)), GREATEST(0, COALESCE(first_variant_stock.stock, 0) - COALESCE(first_variant_stock.stock_keep, 0)), 0 ) AS current_variant_stock_sell, -- Availability Flags CASE WHEN stock_summary.total_stock_sell <= 0 THEN 1 ELSE 0 END AS is_completely_sold_out, CASE WHEN COALESCE( GREATEST(0, COALESCE(primary_variant_stock.stock, 0) - COALESCE(primary_variant_stock.stock_keep, 0)), GREATEST(0, COALESCE(first_variant_stock.stock, 0) - COALESCE(first_variant_stock.stock_keep, 0)), 0 ) <= 0 THEN 1 ELSE 0 END AS current_variant_out_of_stock, CASE WHEN stock_summary.available_variants > 1 THEN 1 ELSE 0 END AS has_other_variants_available, -- Variants COALESCE( primary_variant_attrs.variants, first_variant_attrs.variants, 'No variants available' ) AS variants, -- Badges Information COALESCE(product_badges_data.badges_names, '') AS badges_names, COALESCE(product_badges_data.badges_data, '') AS badges_data, COALESCE(product_badges_data.badges_count, 0) AS badges_count, -- Additional data COALESCE(total_sales.total_sales, 0) AS total_sales, COALESCE(total_reviews.total_reviews, 0) AS total_reviews, COALESCE(reseller_price.price, 0) AS reseller_price, COALESCE(reseller_price.min_quantity, 0) AS reseller_min_quantity, COALESCE(b.priority, 0) AS brand_priority, -- Discount calculations CASE WHEN COALESCE(primary_variant.discounted_price, first_variant.discounted_price) > 0 AND COALESCE(primary_variant.discounted_price, first_variant.discounted_price) < COALESCE(primary_variant.price, first_variant.price) THEN (COALESCE(primary_variant.price, first_variant.price) - COALESCE(primary_variant.discounted_price, first_variant.discounted_price)) ELSE 0 END AS savings_amount, CASE WHEN COALESCE(primary_variant.discounted_price, first_variant.discounted_price) > 0 AND COALESCE(primary_variant.discounted_price, first_variant.discounted_price) < COALESCE(primary_variant.price, first_variant.price) THEN ROUND(((COALESCE(primary_variant.price, first_variant.price) - COALESCE(primary_variant.discounted_price, first_variant.discounted_price)) / COALESCE(primary_variant.price, first_variant.price)) * 100, 0) ELSE 0 END AS discount_percentage, -- Sort order CASE WHEN stock_summary.total_stock_sell <= 0 THEN 1 ELSE 0 END AS sort_order FROM products p -- Stock Summary LEFT JOIN ( SELECT pd.product_id, COUNT(DISTINCT pd.id) AS total_variants, SUM(COALESCE(s.stock, 0)) AS total_stock, SUM(COALESCE(s.stock_keep, 0)) AS total_stock_keep, SUM(GREATEST(0, COALESCE(s.stock, 0) - COALESCE(s.stock_keep, 0))) AS total_stock_sell, SUM(CASE WHEN GREATEST(0, COALESCE(s.stock, 0) - COALESCE(s.stock_keep, 0)) > 0 THEN 1 ELSE 0 END) AS available_variants FROM product_details pd LEFT JOIN stock s ON pd.id = s.id_product_detail GROUP BY pd.product_id ) stock_summary ON p.id_products = stock_summary.product_id -- Primary Variant LEFT JOIN ( SELECT pd.* FROM product_details pd INNER JOIN ( SELECT product_id, MIN(id) as min_id FROM product_details GROUP BY product_id ) min_pd ON pd.product_id = min_pd.product_id AND pd.id = min_pd.min_id ) primary_variant ON p.id_products = primary_variant.product_id LEFT JOIN ( SELECT pd.* FROM product_details pd LEFT JOIN stock s ON pd.id = s.id_product_detail INNER JOIN ( SELECT pd.product_id, MAX(GREATEST(0, COALESCE(s.stock, 0) - COALESCE(s.stock_keep, 0))) AS max_stock FROM product_details pd LEFT JOIN stock s ON pd.id = s.id_product_detail GROUP BY pd.product_id ) max_stock_pd ON pd.product_id = max_stock_pd.product_id LEFT JOIN stock s2 ON pd.id = s2.id_product_detail WHERE GREATEST(0, COALESCE(s2.stock, 0) - COALESCE(s2.stock_keep, 0)) = max_stock_pd.max_stock ) first_variant ON p.id_products = first_variant.product_id -- Stock for displayed variants LEFT JOIN stock primary_variant_stock ON primary_variant.id = primary_variant_stock.id_product_detail LEFT JOIN stock first_variant_stock ON first_variant.id = first_variant_stock.id_product_detail -- Product Images LEFT JOIN product_images main_image ON p.id_products = main_image.product_id AND main_image.product_details_id = 0 AND main_image.priority = 1 AND main_image.status = '1' LEFT JOIN product_images main_image_secondary ON p.id_products = main_image_secondary.product_id AND main_image_secondary.product_details_id = 0 AND main_image_secondary.priority = 2 AND main_image_secondary.status = '1' LEFT JOIN product_images primary_variant_image ON primary_variant.id = primary_variant_image.product_details_id AND primary_variant_image.priority = 1 AND primary_variant_image.status = '1' LEFT JOIN product_images primary_variant_image_secondary ON primary_variant.id = primary_variant_image_secondary.product_details_id AND primary_variant_image_secondary.priority = 2 AND primary_variant_image_secondary.status = '1' LEFT JOIN product_images first_variant_image ON first_variant.id = first_variant_image.product_details_id AND first_variant_image.priority = 1 AND first_variant_image.status = '1' LEFT JOIN product_images first_variant_image_secondary ON first_variant.id = first_variant_image_secondary.product_details_id AND first_variant_image_secondary.priority = 2 AND first_variant_image_secondary.status = '1' -- Variant Attributes LEFT JOIN ( SELECT pc.product_details_id, GROUP_CONCAT(DISTINCT CONCAT_WS(': ', pa.product_attribute, pad.attribute_detail) SEPARATOR '; ') AS variants FROM product_combination pc JOIN product_attributes pa ON pc.attribute_id = pa.id JOIN product_attributes_detail pad ON pc.attribute_detail_id = pad.id GROUP BY pc.product_details_id ) primary_variant_attrs ON primary_variant.id = primary_variant_attrs.product_details_id LEFT JOIN ( SELECT pc.product_details_id, GROUP_CONCAT(DISTINCT CONCAT_WS(': ', pa.product_attribute, pad.attribute_detail) SEPARATOR '; ') AS variants FROM product_combination pc JOIN product_attributes pa ON pc.attribute_id = pa.id JOIN product_attributes_detail pad ON pc.attribute_detail_id = pad.id GROUP BY pc.product_details_id ) first_variant_attrs ON first_variant.id = first_variant_attrs.product_details_id -- Product Badges (Enhanced but still simple) LEFT JOIN ( SELECT pb.product_id, COUNT(pb.badge_id) AS badges_count, GROUP_CONCAT(b.name ORDER BY pb.priority ASC SEPARATOR ', ') AS badges_names, GROUP_CONCAT( CONCAT( b.id, ':', b.name, ':', b.slug, ':', IFNULL(b.description, ''), ':', IFNULL(b.background_color, '#FF6B6B'), ':', IFNULL(b.text_color, '#FFFFFF'), ':', IFNULL(b.icon, ''), ':', pb.position, ':', pb.priority ) ORDER BY pb.priority ASC SEPARATOR '|' ) AS badges_data FROM product_badges pb INNER JOIN badges b ON pb.badge_id = b.id WHERE pb.is_active = 1 AND b.is_active = 1 AND (pb.start_date IS NULL OR pb.start_date <= NOW()) AND (pb.end_date IS NULL OR pb.end_date >= NOW()) GROUP BY pb.product_id ) product_badges_data ON p.id_products = product_badges_data.product_id -- Additional joins LEFT JOIN ( SELECT item_id, SUM(quantity) AS total_sales FROM orders_detail WHERE warehouse_id = 1 GROUP BY item_id ) total_sales ON COALESCE(primary_variant.id, first_variant.id) = total_sales.item_id LEFT JOIN ( SELECT product_id, COUNT(id) AS total_reviews FROM product_review GROUP BY product_id ) total_reviews ON p.id_products = total_reviews.product_id LEFT JOIN resellers_price reseller_price ON COALESCE(primary_variant.id, first_variant.id) = reseller_price.product_detail_id LEFT JOIN brands b ON p.brand_id = b.id_brands INNER JOIN category_product cp ON p.id_products = cp.id_product WHERE p.product_status = '1' AND p.deleted_at IS NULL GROUP BY p.id_products ORDER BY sort_order ASC, p.best_seller DESC, p.new_arrival DESC, p.popular_product DESC, p.priority DESC, COALESCE(b.priority, 0) DESC, p.created_at DESC "; } private function prepare_search_products($products) { $customer = $this->session->userdata('customer'); $is_reseller = false; $reseller_price_map = []; // Get reseller information (existing code) if (!empty($customer['customer_id'])) { $customer_id = $customer['customer_id']; $customer_data = $this->db->where('id_customers', $customer_id)->get('customers')->row_array(); if (!empty($customer_data['reseller_id'])) { $reseller = $this->db->where('id_resellers', $customer_data['reseller_id'])->get('resellers')->row_array(); if ($reseller) { $is_reseller = true; $reseller_prices = $this->db->where('reseller_id', $reseller['id_resellers'])->get('resellers_price')->result_array(); foreach ($reseller_prices as $price) { $reseller_price_map[$price['product_detail_id']] = $price['price']; } } } } $formatted_products = []; foreach ($products as $product) { // Price calculations $is_discounted = $product['discounted_price'] > 0; $default_price = $product['price']; $discounted_price = $product['discounted_price']; $current_price = $is_discounted ? $discounted_price : $default_price; $msrp_price = null; // Handle reseller pricing if ($is_reseller && isset($reseller_price_map[$product['id_detail']])) { $msrp_price = $current_price; $current_price = $reseller_price_map[$product['id_detail']]; } // Get reviews $review_data = $this->Review_m->get_product_reviews($product['id_products']); $average_rating = isset($review_data['average_rating']) ? round($review_data['average_rating'], 1) : 0; $total_reviews = isset($review_data['total_reviews']) ? $review_data['total_reviews'] : 0; // Parse variants $variants = !empty($product['variants']) ? explode('; ', $product['variants']) : []; $badges = $this->parse_badges_data($product['badges_data'] ?? ''); $badges_names = $product['badges_names'] ?? ''; // Stock calculations - all done in SQL now, just ensure non-negative values $current_variant_stock_sell = max(0, intval($product['current_variant_stock_sell'] ?? 0)); $total_stock_sell = max(0, intval($product['total_stock_sell'] ?? 0)); $formatted_products[] = [ 'id' => $product['id_products'], 'title' => $product['title'], 'id_detail' => $product['id_detail'], 'alias' => $product['alias'], 'sku' => $product['sku'], 'current_price' => $current_price, 'original_price' => $is_discounted ? $default_price : null, 'msrp_price' => $msrp_price, 'image' => $product['image'], 'image_secondary' => $product['image_secondary'], 'stock' => $product['total_stock'], 'stock_sell' => $current_variant_stock_sell, 'total_stock_sell' => $total_stock_sell, 'average_rating' => $average_rating, 'total_reviews' => $total_reviews, 'variants' => $variants, 'is_wishlisted' => $this->_check_wishlist_status($product['id_products'], $customer['customer_id'] ?? null), 'created_at' => $product['created_at'], 'brand_priority' => $product['brand_priority'], 'savings_amount' => $product['savings_amount'], 'is_discounted' => $is_discounted, 'discount_percentage' => $product['discount_percentage'], // Stock flags - now calculated in SQL 'is_completely_sold_out' => (bool) $product['is_completely_sold_out'], 'current_variant_out_of_stock' => (bool) $product['current_variant_out_of_stock'], 'has_other_variants_available' => (bool) $product['has_other_variants_available'], // Additional stock information 'total_variants' => (int) $product['total_variants'], 'available_variants' => (int) $product['available_variants'], // Badges 'badges' => $badges, 'badges_names' => $badges_names, // Simple comma-separated names for quick display 'badges_count' => (int) ($product['badges_count'] ?? 0), 'has_badges' => !empty($badges), // New arrivals flag for badges 'new_arrivals' => ($product['new_arrival'] === 'yes'), 'best_seller' => ($product['best_seller'] === 'yes'), 'popular_product' => ($product['popular_product'] === 'yes'), ]; } return $formatted_products; } private function parse_badges_data($badges_data) { $badges = []; if (empty($badges_data)) { return $badges; } $badges_raw = explode('|', $badges_data); foreach ($badges_raw as $badge_raw) { if (empty($badge_raw)) continue; $badge_parts = explode(':', $badge_raw); if (count($badge_parts) >= 9) { $badges[] = [ 'id' => (int) $badge_parts[0], 'name' => $badge_parts[1], 'slug' => $badge_parts[2], 'description' => $badge_parts[3], 'background_color' => !empty($badge_parts[4]) ? $badge_parts[4] : '#FF6B6B', 'text_color' => !empty($badge_parts[5]) ? $badge_parts[5] : '#FFFFFF', 'icon' => $badge_parts[6], 'position' => $badge_parts[7], 'priority' => (int) $badge_parts[8], // Additional computed properties 'css_class' => 'badge-' . $badge_parts[2], 'has_icon' => !empty($badge_parts[6]), 'style' => sprintf( 'background-color: %s; color: %s;', !empty($badge_parts[4]) ? $badge_parts[4] : '#FF6B6B', !empty($badge_parts[5]) ? $badge_parts[5] : '#FFFFFF' ) ]; } } // Already sorted by priority in SQL, but double check usort($badges, function ($a, $b) { return $a['priority'] - $b['priority']; }); return $badges; } private function _check_wishlist_status($product_id, $customer_id) { if (!$customer_id) return false; $exists = $this->db->where([ 'customer_id' => $customer_id, 'product_id' => $product_id ])->get('wishlists')->num_rows(); return $exists > 0; } public function search_dropdown() { header('Content-Type: application/json'); $query = $this->input->get('query', TRUE); // Debug query if (!$query) { echo json_encode(['error' => 'No query provided']); return; } $this->load->model('product_m'); $this->load->model('brand_m'); $this->load->model('category_m'); // Get search results for each type $products = $this->product_m->search_products($query); $brands = $this->brand_m->search_brands($query); $categories = $this->category_m->search_categories($query); // Process product results foreach ($products as &$product) { $product['url'] = base_url('product/' . $product['alias']); $product['image'] = base_url('uploads/product/' . $product['image']); $product['type'] = 'product'; } // Process brand results foreach ($brands as &$brand) { $brand['url'] = base_url('brand/' . $brand['alias']); $brand['image'] = !empty($brand['logo']) ? base_url('uploads/brand/' . $brand['logo']) : base_url('assets/images/no-image.png'); $brand['type'] = 'brand'; // Add a price placeholder for consistency in UI (can be empty) $brand['price'] = null; } // Process category results foreach ($categories as &$category) { $category['url'] = base_url('category/' . $category['alias']); $category['image'] = !empty($category['image']) ? base_url('uploads/category/' . $category['image']) : base_url('assets/images/no-image.png'); $category['type'] = 'category'; // Add a price placeholder for consistency in UI (can be empty) $category['price'] = null; } $all_results = [ 'products' => $products, 'brands' => $brands, 'categories' => $categories ]; // Send the combined results echo json_encode(['results' => $all_results]); } }