Вход Регистрация
Файл: pages/social/ticket.php
Строк: 319
<?php
// Physical module map v50.6.
if (!defined('GAME_ROOT')) define('GAME_ROOT'dirname(__DIR__2));
chdir(GAME_ROOT);
if (
PHP_SAPI !== 'cli') { $_SERVER['PHP_SELF']='/ticket.php'$_SERVER['SCRIPT_NAME']='/ticket.php'; }

/* Техподдержка PHP 8.4/PDO: user + staff inbox. by Метриум (Стэлп) */
require_once './system/common.php';
require_once 
'./system/functions.php';
require_once 
'./system/user.php';
if(!
$user){ header('Location:/'); exit; }

function 
ticket_topic_label(string $type): string {
    return 
match($type){'sms'=>'Вопросы об оплате с помощью SMS','payment'=>'Вопросы об оплате прочими способами',default=>'Общие вопросы'};
}
function 
ticket_clean(string $s,int $max=2000): string { return trim(mb_substr(strip_tags($s),0,$max,'UTF-8')); }
function 
ticket_status(string $s): string { return match($s){'close'=>'Закрыт','read'=>'Есть ответ','user'=>'Ожидает ответа администрации',default=>'Новое'}; }
function 
ticket_redirect(string $url): never header('Location: '.$url); exit; }

$mode=(string)($_GET['mode']??'home');
$type=(string)($_GET['type']??'');
$id=max(0,(int)($_GET['id']??0));
$allowed=['general','sms','payment'];
if(
$type!==''&&!in_array($type,$allowed,true)) $type='';
$isStaff=(int)($user['access']??0)>0;
// One-time compatibility for legacy installations where ticket titles were only VARCHAR(25).
if(function_exists('game_meta_get') && (int)game_meta_get('ticket_schema','0')<2){
    
$col=db_fetch_one("SHOW COLUMNS FROM `ticket` LIKE 'title'");
    if(
$col && preg_match('/varchar\((\d+)\)/i',(string)($col['Type']??''),$m) && (int)$m[1]<120){
        
db_query("ALTER TABLE `ticket` MODIFY COLUMN `title` varchar(120) NOT NULL");
    }
    
game_meta_set('ticket_schema','2');
}
$isStaffMode=$isStaff && in_array($mode,['viev_all','view_all','admin_view'],true);

if((
$_SERVER['REQUEST_METHOD']??'GET')==='POST'){
    
security_require_csrf();
    
$action=(string)($_POST['action']??'');

    if(
$isStaff && in_array($action,['admin_reply','admin_close','admin_reopen'],true)){
        
$ticketId=max(1,(int)($_POST['ticket_id']??$id));
        
$tik=db_fetch_one('SELECT * FROM `ticket` WHERE `id`=:i LIMIT 1',['i'=>$ticketId]);
        if(!
$tik){ $_SESSION['ticket_notice']='Обращение не найдено.'ticket_redirect('/adm/support/'); }
        if(
$action==='admin_reply'){
            
$text=ticket_clean((string)($_POST['body']??''),2000);
            if(
mb_strlen($text,'UTF-8')<2){ $_SESSION['ticket_notice']='Введите ответ.'ticket_redirect('/ticket/?mode=admin_view&id='.$ticketId); }
            
db_prepare('INSERT INTO `ticket_answer` (`type`,`text`,`ticket`) VALUES (?,?,?)',['admin',$text,$ticketId]);
            
db_execute("UPDATE `ticket` SET `status`='read' WHERE `id`=:i",['i'=>$ticketId]);
            
// System mail gives the player a visible (+) in mail/header.
            
$msg='Техподдержка ответила на обращение «'.mb_substr((string)$tik['title'],0,80,'UTF-8').'». Откройте раздел техподдержки.';
            
db_prepare('INSERT INTO `mail` (`from`,`to`,`text`,`time`,`read`) VALUES (0,?,?,?,0)',[(int)$tik['user'],$msg,time()]);
            
$_SESSION['ticket_notice']='Ответ отправлен.';
        } elseif(
$action==='admin_close'){
            
db_execute("UPDATE `ticket` SET `status`='close' WHERE `id`=:i",['i'=>$ticketId]);
            
$_SESSION['ticket_notice']='Обращение закрыто.';
        } else {
            
db_execute("UPDATE `ticket` SET `status`='user' WHERE `id`=:i",['i'=>$ticketId]);
            
$_SESSION['ticket_notice']='Обращение снова открыто.';
        }
        
ticket_redirect('/ticket/?mode=admin_view&id='.$ticketId);
    }

    if(!
security_honeypot_ok() || !security_rate_limit('ticket:'.(int)$user['id'],8,3600)){
        
$_SESSION['ticket_notice']='Слишком много обращений. Попробуйте позже.'ticket_redirect('/ticket/');
    }
    if(
$action==='create' && in_array($type,$allowed,true)){
        
$body='';
        if(
$type==='sms'){
            
$fields=[
                
'Ваша страна'=>ticket_clean((string)($_POST['country']??''),100),
                
'Ваш оператор сотовой связи'=>ticket_clean((string)($_POST['operator']??''),100),
                
'Номер телефона, с которого вы отправляли SMS'=>ticket_clean((string)($_POST['phone']??''),80),
                
'Короткий номер, на который вы отправляли SMS'=>ticket_clean((string)($_POST['short_number']??''),50),
                
'Дата и время отправления SMS'=>ticket_clean((string)($_POST['sent_at']??''),80),
                
'Текст отправленного SMS'=>ticket_clean((string)($_POST['sent_text']??''),500),
                
'Текст полученного в ответ SMS'=>ticket_clean((string)($_POST['reply_text']??''),500),
                
'Содержание'=>ticket_clean((string)($_POST['body']??''),3000),
            ];
            foreach(
$fields as $k=>$v) if($v!==''$body.=$k.': '.$v."n";
        } else 
$body=ticket_clean((string)($_POST['body']??''),4000);
        if(
mb_strlen($body,'UTF-8')<5){ $_SESSION['ticket_notice']='Заполните обращение.'ticket_redirect('/ticket/?mode=create&type='.$type); }
        
db_prepare('INSERT INTO `ticket` (`time`,`user`,`title`,`text`,`status`) VALUES (?,?,?,?,?)',[time(),(int)$user['id'],ticket_topic_label($type),$body,'new']);
        
ticket_redirect('/ticket/?mode=view&id='.(int)db_insert_id());
    }
    if(
$action==='reply' && $id>0){
        
$tik=db_fetch_one('SELECT * FROM `ticket` WHERE `id`=:i AND `user`=:u LIMIT 1',['i'=>$id,'u'=>(int)$user['id']]);
        
$text=ticket_clean((string)($_POST['body']??''),2000);
        if(
$tik && $tik['status']!=='close' && mb_strlen($text,'UTF-8')>=2){
            
db_prepare('INSERT INTO `ticket_answer` (`type`,`text`,`ticket`) VALUES (?,?,?)',['user',$text,$id]);
            
db_execute("UPDATE `ticket` SET `status`='user' WHERE `id`=:i",['i'=>$id]);
        }
        
ticket_redirect('/ticket/?mode=view&id='.$id);
    }
}

$title=$isStaffMode?'Техподдержка — обращения':'Тех. поддержка';
require 
'./system/h.php';
$notice=(string)($_SESSION['ticket_notice']??''); unset($_SESSION['ticket_notice']);
?>
<div class="support-ref">
<?php if($notice!==''): ?><div class="support-notice"><?=security_html($notice)?></div><?php endif; ?>
<?php 
if($isStaffMode && $mode!=='admin_view'):
    
$status=(string)($_GET['status']??'open');
    
$where=$status==='closed'?"t.`status`='close'":"t.`status`<>'close'";
    
$rows=db_prepare("SELECT t.*,u.`login` FROM `ticket` t LEFT JOIN `users` u ON u.`id`=t.`user` WHERE $where ORDER BY FIELD(t.`status`,'new','user','read','close'),t.`time` DESC,t.`id` DESC LIMIT 100")->fetchAll();
?>
<div class="support-title">Обращения игроков</div>
<div class="center"><a href="/adm/support/">Открытые</a> · <a href="/adm/support/?status=closed">Закрытые</a></div>
<?php if(!$rows): ?><div class="support-notice">Обращений в этом разделе нет.</div><?php endif; ?>
<?php 
foreach($rows as $t): ?>
<a class="support-ticket-row" href="/ticket/?mode=admin_view&id=<?=(int)$t['id']?>"><span class="support-doc">▤</span><b><?=security_html((string)$t['title'])?></b><br><small><?=security_html((string)($t['login']??('Игрок #'.$t['user'])))?> · <?=date('d.m.y H:i',(int)$t['time'])?> · <?=security_html(ticket_status((string)$t['status']))?></small></a>
<?php endforeach; ?>
<a class="support-back" href="/adm/">› В админку</a>

<?php elseif($isStaffMode && $mode==='admin_view'):
    
$tik=$id>0?db_fetch_one('SELECT t.*,u.`login` FROM `ticket` t LEFT JOIN `users` u ON u.`id`=t.`user` WHERE t.`id`=:i LIMIT 1',['i'=>$id]):null;
    if(!
$tik): ?><div class="support-notice">Обращение не найдено.</div><a class="support-back" href="/adm/support/">› К обращениям</a>
    <?php else: $answers=db_prepare('SELECT * FROM `ticket_answer` WHERE `ticket`=:i ORDER BY `id` ASC',['i'=>$id])->fetchAll(); ?>
    <div class="support-thread-head"><b><?=security_html((string)$tik['title'])?></b><br>Автор: <a href="/user/<?=(int)$tik['user']?>/"><?=security_html((string)($tik['login']??('Игрок #'.$tik['user'])))?></a><br>Статус: <?=security_html(ticket_status((string)$tik['status']))?></div>
    <div class="support-msg"><span class="support-date">Вопрос · <?=date('d.m.Y H:i',(int)$tik['time'])?></span><br><?=nl2br(security_html((string)$tik['text']))?></div>
    <?php foreach($answers as $a): ?><div class="support-msg"><span class="support-date"><?=($a['type']==='admin'?'Администрация':'Игрок')?>:</span><br><?=nl2br(security_html((string)$a['text']))?></div><?php endforeach; ?>
    <?php if($tik['status']!=='close'): ?><form method="post" action="/ticket/?mode=admin_view&id=<?=$id?>" class="support-form"><?=security_csrf_field()?><input type="hidden" name="action" value="admin_reply"><input type="hidden" name="ticket_id" value="<?=$id?>"><label>Ответ:<textarea name="body" rows="4" required></textarea></label><button class="support-submit" type="submit">Ответить</button></form>
    <form method="post" action="/ticket/?mode=admin_view&id=<?=$id?>" class="inline-form"><?=security_csrf_field()?><input type="hidden" name="action" value="admin_close"><input type="hidden" name="ticket_id" value="<?=$id?>"><button class="link-button" type="submit">Закрыть обращение</button></form>
    <?php else: ?><form method="post" action="/ticket/?mode=admin_view&id=<?=$id?>" class="inline-form"><?=security_csrf_field()?><input type="hidden" name="action" value="admin_reopen"><input type="hidden" name="ticket_id" value="<?=$id?>"><button class="link-button" type="submit">Открыть снова</button></form><?php endif; ?>
    <a class="support-back" href="/adm/support/">› К обращениям</a>
    <?php endif; ?>

<?php elseif($mode==='home'): ?>
<div class="support-title">Выберите тему:</div>
<a class="support-link" href="/ticket/?mode=create&type=general">Общие вопросы</a>
<a class="support-link" href="/ticket/?mode=create&type=sms">Вопросы об оплате с помощью SMS</a>
<a class="support-link" href="/ticket/?mode=create&type=payment">Вопросы об оплате прочими способами</a>
<?php $q=db_prepare('SELECT * FROM `ticket` WHERE `user`=:u ORDER BY `time` DESC,`id` DESC LIMIT 50',['u'=>(int)$user['id']]); $mine=$q->fetchAll(); if($mine): ?>
<div class="support-sep"></div><div class="support-title">Мои обращения</div>
<?php foreach($mine as $t): ?><a class="support-ticket-row" href="/ticket/?mode=view&id=<?=(int)$t['id']?>"><span class="support-doc">▤</span><?=security_html((string)$t['title'])?> <span class="support-date">(<?=date('d.m.y H:i',(int)$t['time'])?>)</span><?php if($t['status']==='read'): ?> <span class="green">(+)</span><?php endif; ?></a><?php endforeach; endif; ?>
<?php 
if($isStaff): ?><div class="support-sep"></div><a class="support-link" href="/adm/support/">Панель обращений администрации</a><?php endif; ?>

<?php elseif($mode==='create' && in_array($type,$allowed,true)): ?>
<form method="post" action="/ticket/?mode=create&type=<?=security_html($type)?>" class="support-form"><?=security_csrf_field()?><input type="text" name="website" class="hp-field" tabindex="-1" autocomplete="off"><input type="hidden" name="action" value="create"><div>Тема: <?=security_html(ticket_topic_label($type))?></div>
<?php if($type==='sms'): ?><label>Ваша страна:<input type="text" name="country"></label><label>Ваш оператор сотовой связи:<input type="text" name="operator"></label><label>Номер телефона:<input type="text" name="phone"></label><label>Короткий номер:<input type="text" name="short_number"></label><label>Дата и время отправления SMS:<input type="text" name="sent_at"></label><label>Текст отправленного SMS:<input type="text" name="sent_text"></label><label>Ответ SMS:<input type="text" name="reply_text"></label><?php endif; ?>
<label>Содержание:<textarea name="body" rows="4" required></textarea></label><button type="submit" class="support-submit">Создать</button></form>

<?php else:
$tik=$id>0?db_fetch_one('SELECT * FROM `ticket` WHERE `id`=:i AND `user`=:u LIMIT 1',['i'=>$id,'u'=>(int)$user['id']]):null;
if(!
$tik): ?><div class="support-notice">Обращение не найдено.</div>
<?php else: $answers=db_prepare('SELECT * FROM `ticket_answer` WHERE `ticket`=:i ORDER BY `id` ASC',['i'=>(int)$tik['id']])->fetchAll();
if(
$tik['status']==='read'db_execute("UPDATE `ticket` SET `status`='new' WHERE `id`=:i",['i'=>(int)$tik['id']]); ?>
<div class="support-thread-head"><b><?=security_html((string)$tik['title'])?></b><br>Автор: <a href="/user/<?=(int)$user['id']?>/"><?=security_html((string)$user['login'])?></a><br>Статус: <?=security_html(ticket_status((string)$tik['status']))?></div>
<div class="support-msg"><span class="support-date">Вопрос: <?=date('d F H:i',(int)$tik['time'])?></span><br><?=nl2br(security_html((string)$tik['text']))?></div>
<?php foreach($answers as $a): ?><div class="support-msg"><span class="support-date"><?=($a['type']==='admin'?'Ответ администрации':'Я')?>:</span><br><?=nl2br(security_html((string)$a['text']))?></div><?php endforeach; ?>
<?php 
if($tik['status']!=='close'): ?><form method="post" action="/ticket/?mode=view&id=<?=(int)$tik['id']?>" class="support-form"><?=security_csrf_field()?><input type="hidden" name="action" value="reply"><label>Ответ:<textarea name="body" rows="3"></textarea></label><button class="support-submit" type="submit">Отправить</button></form><?php endif; ?>
<a class="support-back" href="/ticket/">› Вернуться назад</a>
<?php endif; endif; ?>
</div>
<?php require './system/f.php'?>
Онлайн: 3
Реклама