HEX
Server: LiteSpeed
System:
User: ()
PHP: 7.4.33
Disabled: sendmail,mail,exec,shell_exec,dl,system,passthru,pclose,proc_open,proc_nice,proc_terminate,proc_get_status,proc_close,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,escapeshellcmd,escapeshellarg shell-exec,fpassthru,crack_check,crack_closedict,crack_getlastmessage,crack_opendict,psockopen,php_uname,symlink,ini_restore,posix_getpwuid,posix_getegid,posix_getcwd,posix_geteuid,posix_getgroups,posix_uname,posix_setuid,eval,show_source,passthru,popen,allow_url_fopen,get_current_user,getmyuid,getmygid,entre2v2,index_changer_wp,index_changer_joomla,exec_mode_1,exec_mode_2,exec_mode_3,wsoFooter,wsoEx,wsoViewSize,wsoPerms,wsoPermsColor,ukuran,tulis,ambil,tukar,entre2v2,rapih,magicboom,goaction,scookie,showstat,index_changer
Upload Files
File: /home/muratemr/theotto.tr/api/admin/customers.php
<?php
/**
 * api/admin/customers.php
 */

declare(strict_types=1);

require_once __DIR__ . '/../../includes/db.php';
require_once __DIR__ . '/../../includes/auth.php';
require_once __DIR__ . '/../../includes/functions.php';
require_once __DIR__ . '/../../includes/csrf.php';

require_permission('customers');
header('Content-Type: application/json');

set_exception_handler(function(Throwable $e) {
    http_response_code(500);
    header("Content-Type: application/json");
    echo json_encode(["success" => false, "message" => "Sunucu hatası: " . $e->getMessage()]);
    exit;
});

$action = post_str('action') ?: get_str('action');
$id     = post_int('id') ?: get_int('id');

// Okuma işlemleri için CSRF gerekmez
$read_actions = ['get_detail'];
if (!in_array($action, $read_actions)) {
    csrf_required();
}

switch ($action) {

    case 'set_tag':
        if (!$id) json_response(false, 'Geçersiz ID.');
        $tag_id = post_int('tag_id') ?: null;

        // Etikete ait auto_note varsa müşterinin notuna ekle
        if ($tag_id) {
            $tag = db_row('SELECT auto_note FROM customer_tags WHERE id=?', [$tag_id]);
            if ($tag && $tag['auto_note']) {
                $customer = db_row('SELECT admin_note FROM customers WHERE id=?', [$id]);
                $date     = date('d.m.Y');
                $append   = "\n[$date] " . $tag['auto_note'];
                $new_note = ($customer['admin_note'] ?? '') . $append;
                db_run('UPDATE customers SET tag_id=?, admin_note=? WHERE id=?', [$tag_id, $new_note, $id]);
                json_response(true, 'Etiket atandı ve not eklendi.');
            }
        }
        db_run('UPDATE customers SET tag_id=? WHERE id=?', [$tag_id, $id]);
        json_response(true, 'Etiket güncellendi.');

    case 'set_note':
        if (!$id) json_response(false, 'Geçersiz ID.');
        db_run('UPDATE customers SET admin_note=? WHERE id=?', [post_str('admin_note'), $id]);
        json_response(true, 'Not güncellendi.');

    case 'create':
        if (!is_admin()) json_response(false, 'Yetki gerekli.');
        $full_name  = trim(post_str('full_name'));
        $phone_raw  = trim(post_str('phone'));
        $admin_note = trim(post_str('admin_note'));

        if (!$full_name) json_response(false, 'Ad Soyad zorunlu.');
        if (!$phone_raw) json_response(false, 'Telefon zorunlu.');

        $phone = normalize_phone($phone_raw);
        if (strlen($phone) < 10) json_response(false, 'Geçerli bir telefon numarası girin.');

        // Aynı numarada müşteri var mı?
        $variants = [$phone, '0'.$phone, '90'.$phone];
        $ph = implode(',', array_fill(0, count($variants), '?'));
        $exists = db_value("SELECT COUNT(*) FROM customers WHERE phone IN ($ph)", $variants);
        if ($exists) json_response(false, 'Bu telefon numarasına ait müşteri zaten kayıtlı.');

        $new_id = db_insert(
            "INSERT INTO customers (full_name, phone, admin_note) VALUES (?, ?, ?)",
            [$full_name, $phone, $admin_note ?: null]
        );
        json_response(true, 'Müşteri oluşturuldu.', ['id' => (int)$new_id]);

    case 'update':
        if (!is_admin()) json_response(false, 'Yetki gerekli.');
        if (!$id) json_response(false, 'Geçersiz ID.');

        $full_name  = trim(post_str('full_name'));
        $phone_raw  = trim(post_str('phone'));
        $admin_note = trim(post_str('admin_note'));

        if (!$full_name) json_response(false, 'Ad Soyad zorunlu.');
        if (!$phone_raw) json_response(false, 'Telefon zorunlu.');

        $phone = normalize_phone($phone_raw);
        if (strlen($phone) < 10) json_response(false, 'Geçerli bir telefon numarası girin.');

        // Aynı telefon başka müşteride var mı?
        $variants = [$phone, '0'.$phone, '90'.$phone];
        $ph = implode(',', array_fill(0, count($variants), '?'));
        $dup = db_value("SELECT COUNT(*) FROM customers WHERE phone IN ($ph) AND id != ?",
            array_merge($variants, [$id]));
        if ($dup) json_response(false, 'Bu telefon numarası başka bir müşteriye ait.');

        $customer = db_row("SELECT id FROM customers WHERE id = ?", [$id]);
        if (!$customer) json_response(false, 'Müşteri bulunamadı.');

        db_run(
            "UPDATE customers SET full_name=?, phone=?, admin_note=? WHERE id=?",
            [$full_name, $phone, $admin_note ?: null, $id]
        );
        // Rezervasyonlardaki isim ve telefonu da güncelle
        db_run("UPDATE reservations SET full_name=?, phone=? WHERE customer_id=?",
            [$full_name, $phone, $id]);

        json_response(true, 'Müşteri güncellendi.');

    case 'delete':
        if (!is_admin()) json_response(false, 'Yetki gerekli.');
        if (!$id) json_response(false, 'Geçersiz ID.');

        $customer = db_row("SELECT id, full_name FROM customers WHERE id = ?", [$id]);
        if (!$customer) json_response(false, 'Müşteri bulunamadı.');

        // Rezervasyon sayısını bildir ama silmeyi engelleme
        $res_count = (int)db_value("SELECT COUNT(*) FROM reservations WHERE customer_id = ?", [$id]);

        // Rezervasyonları müşteriden kopar (customer_id null yap, isim/telefon korunur)
        db_run("UPDATE reservations SET customer_id = NULL WHERE customer_id = ?", [$id]);
        db_run("DELETE FROM customers WHERE id = ?", [$id]);

        $msg = 'Müşteri silindi.';
        if ($res_count > 0) $msg .= " ($res_count rezervasyon kaydı müşterisiz bırakıldı.)";
        json_response(true, $msg);

    case 'get_detail':
        // CSRF gerekmez - GET ile çağrılabilir
        $cid = get_int('id') ?: post_int('id');
        if (!$cid) json_response(false, 'ID gerekli.');

        $cust = db_row(
            "SELECT id, full_name, phone, admin_note FROM customers WHERE id=?",
            [$cid]
        );
        if (!$cust) json_response(false, 'Müşteri bulunamadı.');

        // admin_note'u log satırları + temiz not olarak ayır
        $name_log_pattern = '/^\d{2}\.\d{2}\.\d{4}: /';
        $note_lines = array_filter(explode("\n", $cust['admin_note'] ?? ''), 'strlen');
        $log_lines  = array_filter($note_lines, fn($l) => preg_match($name_log_pattern, ltrim($l)));
        $clean_lines = array_filter($note_lines, fn($l) => !preg_match($name_log_pattern, ltrim($l)));

        // Log satırlarını parse et
        $parsed_logs = [];
        foreach ($log_lines as $log) {
            // "03.05.2026: "Yeni" adıyla rezervasyon yaptı (eski: "Eski")"
            if (preg_match('/^(\d{2}\.\d{2}\.\d{4}): "([^"]+)" adıyla rezervasyon yaptı \(eski: "([^"]+)"\)/', trim($log), $m)) {
                $parsed_logs[] = ['date' => $m[1], 'new_name' => $m[2], 'old_name' => $m[3]];
            }
        }

        $cust['admin_note_clean'] = implode("\n", $clean_lines);
        $cust['name_logs'] = $parsed_logs;

        // Rezervasyon geçmişi
        $reservations = db_rows(
            "SELECT full_name, DATE_FORMAT(date,'%d.%m.%Y') AS date,
                    TIME_FORMAT(time,'%H:%i') AS time, guest_count, status
             FROM reservations WHERE customer_id=? ORDER BY date DESC LIMIT 30",
            [$cid]
        );

        json_response(true, '', [
            'customer'     => $cust,
            'reservations' => $reservations,
            'name_logs'    => $parsed_logs,
        ]);

    case 'set_name':
        if (!is_admin()) json_response(false, 'Yetki gerekli.');
        if (!$id) json_response(false, 'ID gerekli.');
        $new_name = trim(post_str('full_name'));
        if (!$new_name) json_response(false, 'İsim boş olamaz.');
        db_run("UPDATE customers SET full_name=? WHERE id=?", [$new_name, $id]);
        json_response(true, 'Müşteri ismi güncellendi.');

    default:
        json_response(false, 'Geçersiz işlem.');
}