https://t.me/RX1948
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 :  /var/www/laciasmara.com/public_html/shop/application/controllers/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //var/www/laciasmara.com/public_html/shop/application/controllers/Api.php
<?php if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}
class Api extends Public_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('category_m');
        $this->load->model('Statistic_m');
        $this->load->model('Carousel_banner_m');
        $this->load->model('Top_banner_m');
        $this->load->model('Brand_m');
        $this->load->model('stocks_m');
    }

    public function test()
    {
        $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => 'success',
                'message' => 'Controller accessible',
                'method' => $_SERVER['REQUEST_METHOD'],
                'timestamp' => date('Y-m-d H:i:s')
            ]));
    }

    public function popular_categories()
    {
        $categories = $this->category_m->get_footer_popular_categories();
        echo json_encode($categories);
    }

    public function trending_searches()
    {
        $trending_searches = $this->Statistic_m->get_trending_searches();
        echo json_encode($trending_searches);
    }

    public function best_seller_products()
    {
        $this->db->select('
			p.id_products,
			p.title,
			p.alias,
			p.brand_id,
			p.created_at,
			pd.id AS id_detail,
			pd.price,
			pd.discounted_price,
			pd.sku,
			COALESCE(GROUP_CONCAT(DISTINCT CONCAT_WS(": ", pa.product_attribute, pad.attribute_detail) SEPARATOR "; "), "No variants available") AS variants,
			pi.image AS image,
			pi_secondary.image AS image_secondary,
			pc.attribute_detail_id,
			s.stock,
			s.stock_keep,
			(s.stock - s.stock_keep) AS stock_sell,
			SUM(od.quantity) AS total_sales,
			COUNT(pr.id) AS total_reviews,
			CASE
			WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
			THEN (pd.price - pd.discounted_price)
			ELSE 0
			END AS savings_amount,
			CASE
			WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
			THEN ROUND(((pd.price - pd.discounted_price) / pd.price) * 100, 0)
			ELSE 0
			END AS discount_percentage,
			-- Badges Information (Added)
			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
			')
            ->from('products p')
            ->join('product_details pd', 'p.id_products = pd.product_id', 'left')
            ->join('product_images pi', 'pd.id = pi.product_details_id AND pi.priority = 1 AND pi.status = 1', 'left')
            ->join('product_images pi_secondary', 'pd.id = pi_secondary.product_details_id AND pi_secondary.priority = 2 AND pi_secondary.status = 1', 'left')
            ->join('stock s', 'pd.id = s.id_product_detail AND s.warehouse_id = 1', 'left')
            ->join('orders_detail od', 'od.item_id = pd.id AND od.warehouse_id = 1', 'left')
            ->join('product_combination pc', 'pd.id = pc.product_details_id', 'left')
            ->join('product_attributes pa', 'pc.attribute_id = pa.id', 'left')
            ->join('product_attributes_detail pad', 'pc.attribute_detail_id = pad.id', 'left')
            ->join('product_review pr', 'pr.product_id = p.id_products', 'left')
            // Product Badges Join (Added)
            ->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', 'p.id_products = product_badges_data.product_id', 'left')
            ->where('p.product_status', '1')
            ->where('p.deleted_at', null)
            ->where('s.stock > 1')
            ->where('(s.stock - s.stock_keep) > 0')
            ->group_by('p.id_products')
            ->order_by('total_reviews', 'DESC')
            ->limit(10);
        $top_seller_products = $this->db->get()->result_array();

        echo json_encode($top_seller_products);
    }

    public function new_arrival_products()
    {
        $this->db->select('
			p.id_products,
			p.title,
			p.alias,
			p.brand_id,
			p.created_at,
			pd.id AS id_detail,
			pd.price,
			pd.discounted_price,
			pd.sku,
			COALESCE(GROUP_CONCAT(DISTINCT CONCAT_WS(": ", pa.product_attribute, pad.attribute_detail) SEPARATOR "; "), "No variants available") AS variants,
			pi.image AS image,
			pi_secondary.image AS image_secondary,
			pc.attribute_detail_id,
			s.stock,
			s.stock_keep,
			s.stock_reject,
			s.stock_sample,
			(s.stock - s.stock_keep - COALESCE(s.stock_reject, 0) - COALESCE(s.stock_sample, 0)) as stock_sell,
			SUM(od.quantity) AS total_sales,
			COUNT(pr.id) AS total_reviews,
			CASE
			WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
			THEN (pd.price - pd.discounted_price)
			ELSE 0
			END AS savings_amount,
			CASE
			WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
			THEN ROUND(((pd.price - pd.discounted_price) / pd.price) * 100, 0)
			ELSE 0
			END AS discount_percentage,
			-- Badges Information (Added)
			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
			')
            ->from('products p')
            ->join('product_details pd', 'p.id_products = pd.product_id', 'left')
            ->join('product_images pi', 'pd.id = pi.product_details_id AND pi.priority = 1 AND pi.status = 1', 'left')
            ->join('product_images pi_secondary', 'pd.id = pi_secondary.product_details_id AND pi_secondary.priority = 2 AND pi_secondary.status = 1', 'left')
            ->join('stock s', 'pd.id = s.id_product_detail AND s.warehouse_id = 1', 'left')
            ->join('orders_detail od', 'od.item_id = pd.id AND od.warehouse_id = 1', 'left')
            ->join('product_combination pc', 'pd.id = pc.product_details_id', 'left')
            ->join('product_attributes pa', 'pc.attribute_id = pa.id', 'left')
            ->join('product_attributes_detail pad', 'pc.attribute_detail_id = pad.id', 'left')
            ->join('product_review pr', 'pr.product_id = p.id_products', 'left')
            ->join('category_product cp', 'p.id_products = cp.id_product', 'inner')
            ->join('categories c', 'cp.id_category = c.id_categories', 'inner')
            // Product Badges Join (Added)
            ->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', 'p.id_products = product_badges_data.product_id', 'left')
            ->where('p.product_status', '1')
            ->where('p.deleted_at', null)
            ->where('s.stock > 1')
            ->where('(s.stock - s.stock_keep) > 0')
            ->where('c.alias', 'pendatang-baru')
            ->where('c.alias_en', 'new-arrivals')
            ->group_by('p.id_products')
            ->order_by('p.created_at', 'DESC')
            ->limit(10);
        $new_arrival_products = $this->db->get()->result_array();

        echo json_encode($new_arrival_products);
    }

    public function get_carousels()
    {
        $carousels = $this->Carousel_banner_m->get_active_carousel();
        echo json_encode($carousels);
    }

    public function get_banners()
    {
        $banners = $this->Top_banner_m->get_active_banners();
        echo json_encode($banners);
    }

    public function get_brands()
    {
        $brands = $this->Brand_m->get_all_brands();
        echo json_encode($brands);
    }

    public function get_testimonials()
    {
        $this->load->helper('url'); // agar base_url() bisa digunakan

        $this->db->select('DISTINCT(stock.id_product) as id_product');
        $this->db->from('stock');
        $this->db->where('warehouse_id', 1);
        $this->db->where('(stock - stock_keep) >', 0);
        $available_products = $this->db->get_compiled_select();

        $this->db->select('
            product_review.id,
            product_review.rating,
            product_review.display_name as customer_name,
            product_review.review as testimonial_text,
            products.title as product_name,
            products.alias as product_alias,
            products.id_products as product_id,
            customers.sex_type
        ');
        $stock_subquery = "(SELECT SUM(stock - stock_keep)
            FROM stock
            WHERE stock.id_product = product_review.product_id
            AND stock.warehouse_id = 1) as stock_sell";
        $this->db->select($stock_subquery, FALSE);
        $this->db->from('product_review');
        $this->db->join('products', 'product_review.product_id = products.id_products');
        $this->db->join('customers', 'product_review.customer_id = customers.id_customers');
        $this->db->join("($available_products) as available_products", 'product_review.product_id = available_products.id_product');
        $this->db->where('product_review.id IN (
            SELECT MAX(pr.id)
            FROM product_review pr
            GROUP BY pr.product_id
        )');
        $this->db->order_by('product_review.id', 'DESC');
        $this->db->limit(20);
        $reviews = $this->db->get()->result();

        $testimonials = [];
        foreach ($reviews as $review) {
            switch ($review->sex_type) {
                case 'male':
                    $image = "https://storage.googleapis.com/laciasmara-photos/laciasmara_test/Laciasmara_testimonial/male.png";
                    break;
                case 'female':
                    $image = "https://storage.googleapis.com/laciasmara-photos/laciasmara_test/Laciasmara_testimonial/female.png";
                    break;
                default:
                    $image = "https://storage.googleapis.com/laciasmara-photos/laciasmara_test/Laciasmara_testimonial/others.png";
            }
            $testimonials[] = [
                'customer_image' => $image,
                'customer_name' => $review->customer_name,
                'product_name' => $review->product_name,
                'product_link' => base_url('product/' . $review->product_alias),
                'star_rating' => $review->rating,
                'testimonial_text' => $review->testimonial_text,
            ];
        }

        echo json_encode($testimonials);
    }

    public function get_search_overlay_data()
    {
        // Set JSON response header
        header('Content-Type: application/json');

        try {
            // Ambil data popular categories dan trending searches
            $popular_categories = $this->category_m->get_footer_popular_categories();
            $trending_searches = $this->Statistic_m->get_trending_searches();

            // Format response
            $response = [
                'status' => 'success',
                'data' => [
                    'popular_categories' => $popular_categories,
                    'trending_searches' => $trending_searches
                ]
            ];

            echo json_encode($response);
        } catch (Exception $e) {
            // Handle error
            $response = [
                'status' => 'error',
                'message' => 'Gagal mengambil data'
            ];

            echo json_encode($response);
        }
    }

    /**
     * Bulk update stock endpoint
     * Method: POST
     * Expected JSON format:
     * {
     *   "stocks": [
     *     {"sku": "SKU001", "stock": 10},
     *     {"sku": "SKU002", "stock": 15}
     *   ]
     * }
     */
    public function bulk_stock_update()
    {
        header('Content-Type: application/json');

        try {
            // Hanya terima POST method
            if ($this->input->method() !== 'post') {
                $this->output
                    ->set_status_header(405)
                    ->set_output(json_encode([
                        'status' => 'error',
                        'message' => 'Method not allowed. Use POST method.'
                    ]));
                return;
            }

            // Ambil raw input JSON
            $input = json_decode($this->input->raw_input_stream, true);

            if (!$input || !isset($input['stocks']) || !is_array($input['stocks'])) {
                $this->output
                    ->set_status_header(400)
                    ->set_output(json_encode([
                        'status' => 'error',
                        'message' => 'Invalid JSON format. Expected: {"stocks": [{"sku": "string", "stock": number}]}'
                    ]));
                return;
            }

            $stocks_data = $input['stocks'];

            if (empty($stocks_data)) {
                $this->output
                    ->set_status_header(400)
                    ->set_output(json_encode([
                        'status' => 'error',
                        'message' => 'Stocks data cannot be empty'
                    ]));
                return;
            }

            // Validasi format data
            foreach ($stocks_data as $index => $stock_item) {
                if (!isset($stock_item['sku']) || !isset($stock_item['stock'])) {
                    $this->output
                        ->set_status_header(400)
                        ->set_output(json_encode([
                            'status' => 'error',
                            'message' => "Invalid data format at index {$index}. Required: sku and stock"
                        ]));
                    return;
                }

                if (!is_numeric($stock_item['stock']) || $stock_item['stock'] < 0) {
                    $this->output
                        ->set_status_header(400)
                        ->set_output(json_encode([
                            'status' => 'error',
                            'message' => "Invalid stock value at index {$index}. Stock must be a non-negative number"
                        ]));
                    return;
                }
            }

            // Proses bulk update
            $result = $this->stocks_m->bulk_update_stock($stocks_data);

            if ($result['success']) {
                $this->output
                    ->set_status_header(200)
                    ->set_output(json_encode([
                        'status' => 'success',
                        'message' => 'Bulk stock update completed successfully',
                        'data' => [
                            'total_processed' => $result['total_processed'],
                            'successful_updates' => $result['successful_updates'],
                            'failed_updates' => $result['failed_updates'],
                            'details' => $result['details']
                        ]
                    ]));
            } else {
                $this->output
                    ->set_status_header(500)
                    ->set_output(json_encode([
                        'status' => 'error',
                        'message' => 'Bulk update failed',
                        'data' => [
                            'total_processed' => $result['total_processed'],
                            'successful_updates' => $result['successful_updates'],
                            'failed_updates' => $result['failed_updates'],
                            'details' => $result['details']
                        ]
                    ]));
            }
        } catch (Exception $e) {
            log_message('error', 'Bulk stock update error: ' . $e->getMessage());

            $this->output
                ->set_status_header(500)
                ->set_output(json_encode([
                    'status' => 'error',
                    'message' => 'Internal server error occurred'
                ]));
        }
    }
}

https://t.me/RX1948 - 2025