2020-06-07 19:04:43 +03:00
< ? php declare ( strict_types = 1 );
namespace openvk\Web\Presenters ;
2022-11-08 00:36:07 +03:00
use openvk\Web\Models\Entities\ { SupportAgent , Ticket , TicketComment };
use openvk\Web\Models\Repositories\ { Tickets , Users , TicketComments , SupportAgents };
2021-12-06 00:30:57 +03:00
use openvk\Web\Util\Telegram ;
2020-06-16 15:38:32 +03:00
use Chandler\Session\Session ;
2022-07-17 17:50:37 +03:00
use Chandler\Database\DatabaseConnection ;
2022-01-16 12:09:05 +03:00
use Parsedown ;
2020-06-07 19:04:43 +03:00
final class SupportPresenter extends OpenVKPresenter
{
protected $banTolerant = true ;
2022-08-05 23:00:52 +03:00
protected $deactivationTolerant = true ;
2022-09-17 00:19:46 +03:00
protected $presenterName = " support " ;
2020-06-07 19:04:43 +03:00
private $tickets ;
private $comments ;
function __construct ( Tickets $tickets , TicketComments $ticketComments )
{
2021-12-10 19:36:50 +03:00
$this -> tickets = $tickets ;
2020-06-07 19:04:43 +03:00
$this -> comments = $ticketComments ;
parent :: __construct ();
}
function renderIndex () : void
{
2021-12-10 19:36:50 +03:00
$this -> assertUserLoggedIn ();
$this -> template -> mode = in_array ( $this -> queryParam ( " act " ), [ " faq " , " new " , " list " ]) ? $this -> queryParam ( " act " ) : " faq " ;
2022-05-21 12:04:33 +03:00
if ( $this -> template -> mode === " faq " ) {
$lang = Session :: i () -> get ( " lang " , " ru " );
$base = OPENVK_ROOT . " /data/knowledgebase/faq " ;
if ( file_exists ( " $base . $lang .md " ))
$file = " $base . $lang .md " ;
else if ( file_exists ( " $base .md " ))
$file = " $base .md " ;
else
$file = NULL ;
if ( is_null ( $file )) {
$this -> template -> faq = [];
} else {
$lines = file ( $file );
$faq = [];
$index = 0 ;
foreach ( $lines as $line ) {
if ( strpos ( $line , " # " ) === 0 )
++ $index ;
$faq [ $index ][] = $line ;
}
$this -> template -> faq = array_map ( function ( $section ) {
$title = substr ( $section [ 0 ], 2 );
array_shift ( $section );
return [
$title ,
( new Parsedown ()) -> text ( implode ( " \n " , $section ))
];
}, $faq );
}
}
2022-01-07 01:59:51 +03:00
$this -> template -> count = $this -> tickets -> getTicketsCountByUserId ( $this -> user -> id );
if ( $this -> template -> mode === " list " ) {
$this -> template -> page = ( int ) ( $this -> queryParam ( " p " ) ? ? 1 );
$this -> template -> tickets = $this -> tickets -> getTicketsByUserId ( $this -> user -> id , $this -> template -> page );
}
2022-01-07 01:30:49 +03:00
2022-03-26 23:48:42 +03:00
if ( $this -> template -> mode === " new " )
$this -> template -> banReason = $this -> user -> identity -> getBanInSupportReason ();
2021-12-10 19:36:50 +03:00
if ( $_SERVER [ " REQUEST_METHOD " ] === " POST " ) {
2022-03-26 23:48:42 +03:00
if ( $this -> user -> identity -> isBannedInSupport ())
$this -> flashFail ( " err " , tr ( " not_enough_permissions " ), tr ( " not_enough_permissions_comment " ));
2021-12-10 19:36:50 +03:00
if ( ! empty ( $this -> postParam ( " name " )) && ! empty ( $this -> postParam ( " text " ))) {
2021-01-01 00:18:53 +03:00
$this -> willExecuteWriteAction ();
2021-12-16 21:25:42 +03:00
2020-06-07 19:04:43 +03:00
$ticket = new Ticket ;
$ticket -> setType ( 0 );
2022-01-07 01:59:51 +03:00
$ticket -> setUser_Id ( $this -> user -> id );
2020-06-07 19:04:43 +03:00
$ticket -> setName ( $this -> postParam ( " name " ));
$ticket -> setText ( $this -> postParam ( " text " ));
$ticket -> setcreated ( time ());
$ticket -> save ();
2021-12-06 00:30:57 +03:00
$helpdeskChat = OPENVK_ROOT_CONF [ " openvk " ][ " credentials " ][ " telegram " ][ " helpdeskChat " ];
if ( $helpdeskChat ) {
2021-12-06 00:48:44 +03:00
$serverUrl = ovk_scheme ( true ) . $_SERVER [ " SERVER_NAME " ];
2021-12-06 00:30:57 +03:00
$ticketText = ovk_proc_strtr ( $this -> postParam ( " text " ), 1500 );
$telegramText = " <b>📬 Новый тикет!</b> \n \n " ;
$telegramText .= " <a href=' $serverUrl /support/reply/ { $ticket -> getId () } '> { $ticket -> getName () } </a> \n " ;
$telegramText .= " $ticketText\n\n " ;
$telegramText .= " Автор: <a href=' $serverUrl { $ticket -> getUser () -> getURL () } '> { $ticket -> getUser () -> getCanonicalName () } </a> ( { $ticket -> getUser () -> getRegistrationIP () } ) \n " ;
Telegram :: send ( $helpdeskChat , $telegramText );
}
2022-08-09 08:52:36 +03:00
$this -> redirect ( " /support/view/ " . $ticket -> getId ());
2020-06-07 19:04:43 +03:00
} else {
2021-12-10 19:52:32 +03:00
$this -> flashFail ( " err " , tr ( " error " ), tr ( " you_have_not_entered_name_or_text " ));
2020-06-07 19:04:43 +03:00
}
}
}
function renderList () : void
{
$this -> assertUserLoggedIn ();
$this -> assertPermission ( 'openvk\Web\Models\Entities\TicketReply' , 'write' , 0 );
$act = $this -> queryParam ( " act " ) ? ? " open " ;
switch ( $act ) {
default :
2022-05-20 17:16:39 +03:00
# NOTICE falling through
2020-06-07 19:04:43 +03:00
case " open " :
$state = 0 ;
2022-05-20 17:16:39 +03:00
break ;
2020-06-07 19:04:43 +03:00
case " answered " :
$state = 1 ;
2022-05-20 17:16:39 +03:00
break ;
2020-06-07 19:04:43 +03:00
case " closed " :
$state = 2 ;
}
$this -> template -> act = $act ;
$this -> template -> page = ( int ) ( $this -> queryParam ( " p " ) ? ? 1 );
$this -> template -> count = $this -> tickets -> getTicketCount ( $state );
$this -> template -> iterator = $this -> tickets -> getTickets ( $state , $this -> template -> page );
}
function renderView ( int $id ) : void
{
$this -> assertUserLoggedIn ();
2021-12-10 19:36:50 +03:00
$ticket = $this -> tickets -> get ( $id );
$ticketComments = $this -> comments -> getCommentsById ( $id );
if ( ! $ticket || $ticket -> isDeleted () != 0 || $ticket -> getUserId () !== $this -> user -> id ) {
2020-06-07 19:04:43 +03:00
$this -> notFound ();
} else {
2021-12-10 19:36:50 +03:00
$this -> template -> ticket = $ticket ;
$this -> template -> comments = $ticketComments ;
$this -> template -> id = $id ;
2020-06-07 19:04:43 +03:00
}
}
function renderDelete ( int $id ) : void
{
2021-12-10 18:17:01 +03:00
$this -> assertUserLoggedIn ();
$this -> willExecuteWriteAction ();
if ( ! empty ( $id )) {
$ticket = $this -> tickets -> get ( $id );
2023-08-03 18:56:19 +03:00
if ( ! $ticket || $ticket -> isDeleted () != 0 || (( $ticket -> getUserId () !== $this -> user -> id || $ticket -> isFromSupport ()) && ! $this -> hasPermission ( 'openvk\Web\Models\Entities\TicketReply' , 'write' , 0 ))) {
2021-12-10 18:17:01 +03:00
$this -> notFound ();
} else {
2021-12-10 19:36:50 +03:00
if ( $ticket -> getUserId () !== $this -> user -> id && $this -> hasPermission ( 'openvk\Web\Models\Entities\TicketReply' , 'write' , 0 ))
2022-09-14 13:27:48 +03:00
$_redirect = " /support/tickets " ;
2021-12-10 18:17:01 +03:00
else
2022-09-14 13:27:48 +03:00
$_redirect = " /support?act=list " ;
2022-01-07 01:30:49 +03:00
2021-12-10 18:17:01 +03:00
$ticket -> delete ();
2022-09-14 13:27:48 +03:00
$this -> redirect ( $_redirect );
2020-06-07 19:04:43 +03:00
}
2021-12-10 18:17:01 +03:00
}
2020-06-07 19:04:43 +03:00
}
function renderMakeComment ( int $id ) : void
{
$ticket = $this -> tickets -> get ( $id );
2021-12-10 19:36:50 +03:00
if ( $ticket -> isDeleted () === 1 || $ticket -> getType () === 2 || $ticket -> getUserId () !== $this -> user -> id ) {
2020-06-07 19:04:43 +03:00
header ( " HTTP/1.1 403 Forbidden " );
header ( " Location: /support/view/ " . $id );
exit ;
}
2021-12-10 19:36:50 +03:00
if ( $_SERVER [ " REQUEST_METHOD " ] === " POST " ) {
if ( ! empty ( $this -> postParam ( " text " ))) {
2020-06-07 19:04:43 +03:00
$ticket -> setType ( 0 );
$ticket -> save ();
2022-01-07 01:59:51 +03:00
2021-01-01 00:18:53 +03:00
$this -> willExecuteWriteAction ();
2020-06-07 19:04:43 +03:00
$comment = new TicketComment ;
$comment -> setUser_id ( $this -> user -> id );
$comment -> setUser_type ( 0 );
$comment -> setText ( $this -> postParam ( " text " ));
$comment -> setTicket_id ( $id );
$comment -> setCreated ( time ());
$comment -> save ();
2022-08-09 08:52:36 +03:00
$this -> redirect ( " /support/view/ " . $id );
2020-06-07 19:04:43 +03:00
} else {
2021-12-10 19:52:32 +03:00
$this -> flashFail ( " err " , tr ( " error " ), tr ( " you_have_not_entered_text " ));
2020-06-07 19:04:43 +03:00
}
}
}
function renderAnswerTicket ( int $id ) : void
{
$this -> assertPermission ( 'openvk\Web\Models\Entities\TicketReply' , 'write' , 0 );
$ticket = $this -> tickets -> get ( $id );
2021-12-10 16:53:39 +03:00
if ( ! $ticket || $ticket -> isDeleted () != 0 )
$this -> notFound ();
2020-06-07 19:04:43 +03:00
$ticketComments = $this -> comments -> getCommentsById ( $id );
2021-12-26 20:15:32 +03:00
$this -> template -> ticket = $ticket ;
$this -> template -> comments = $ticketComments ;
$this -> template -> id = $id ;
$this -> template -> fastAnswers = OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " support " ][ " fastAnswers " ];
2020-06-07 19:04:43 +03:00
}
function renderAnswerTicketReply ( int $id ) : void
{
$this -> assertPermission ( 'openvk\Web\Models\Entities\TicketReply' , 'write' , 0 );
$ticket = $this -> tickets -> get ( $id );
2021-12-10 19:36:50 +03:00
if ( $_SERVER [ " REQUEST_METHOD " ] === " POST " ) {
2021-01-01 00:18:53 +03:00
$this -> willExecuteWriteAction ();
2021-12-10 19:36:50 +03:00
if ( ! empty ( $this -> postParam ( " text " )) && ! empty ( $this -> postParam ( " status " ))) {
2020-06-07 19:04:43 +03:00
$ticket -> setType ( $this -> postParam ( " status " ));
$ticket -> save ();
2022-01-07 01:30:49 +03:00
2020-06-07 19:04:43 +03:00
$comment = new TicketComment ;
$comment -> setUser_id ( $this -> user -> id );
$comment -> setUser_type ( 1 );
2021-11-25 22:20:52 +03:00
$comment -> setText ( $this -> postParam ( " text " ));
2022-01-07 01:30:49 +03:00
$comment -> setTicket_Id ( $id );
2020-06-07 19:04:43 +03:00
$comment -> setCreated ( time ());
$comment -> save ();
2021-12-10 19:36:50 +03:00
} elseif ( empty ( $this -> postParam ( " text " ))) {
2020-06-07 19:04:43 +03:00
$ticket -> setType ( $this -> postParam ( " status " ));
$ticket -> save ();
}
2021-12-10 19:52:32 +03:00
$this -> flashFail ( " succ " , tr ( " ticket_changed " ), tr ( " ticket_changed_comment " ));
2020-06-07 19:04:43 +03:00
}
}
2020-06-16 15:38:32 +03:00
function renderKnowledgeBaseArticle ( string $name ) : void
{
$lang = Session :: i () -> get ( " lang " , " ru " );
$base = OPENVK_ROOT . " /data/knowledgebase " ;
2022-01-16 12:09:05 +03:00
if ( file_exists ( " $base / $name . $lang .md " ))
$file = " $base / $name . $lang .md " ;
else if ( file_exists ( " $base / $name .md " ))
$file = " $base / $name .md " ;
2020-06-16 15:38:32 +03:00
else
$this -> notFound ();
$lines = file ( $file );
if ( ! preg_match ( " %^OpenVK-KB-Heading: (.+) $ % " , $lines [ 0 ], $matches )) {
$heading = " Article $name " ;
} else {
$heading = $matches [ 1 ];
array_shift ( $lines );
}
2022-01-16 01:03:35 +03:00
$content = implode ( $lines );
2020-06-16 15:38:32 +03:00
2022-01-16 12:09:05 +03:00
$parser = new Parsedown ();
2020-06-16 15:38:32 +03:00
$this -> template -> heading = $heading ;
2022-01-16 12:09:05 +03:00
$this -> template -> content = $parser -> text ( $content );
2020-06-16 15:38:32 +03:00
}
2021-12-15 01:56:23 +03:00
2022-01-28 16:34:13 +03:00
function renderDeleteComment ( int $id ) : void
{
$this -> assertUserLoggedIn ();
$this -> assertNoCSRF ();
$comment = $this -> comments -> get ( $id );
if ( is_null ( $comment ))
$this -> notFound ();
$ticket = $comment -> getTicket ();
if ( $ticket -> isDeleted ())
$this -> notFound ();
if ( ! ( $ticket -> getUserId () === $this -> user -> id && $comment -> getUType () === 0 ))
$this -> assertPermission ( " openvk \ Web \ Models \ Entities \T icketReply " , " write " , 0 );
$this -> willExecuteWriteAction ();
$comment -> delete ();
$this -> flashFail ( " succ " , tr ( " ticket_changed " ), tr ( " ticket_changed_comment " ));
}
2021-12-15 01:56:23 +03:00
function renderRateAnswer ( int $id , int $mark ) : void
{
$this -> willExecuteWriteAction ();
$this -> assertUserLoggedIn ();
2021-12-16 21:25:42 +03:00
$this -> assertNoCSRF ();
2021-12-15 01:56:23 +03:00
$comment = $this -> comments -> get ( $id );
2021-12-16 21:25:42 +03:00
if ( $this -> user -> id !== $comment -> getTicket () -> getUser () -> getId ())
2021-12-15 01:56:23 +03:00
exit ( header ( " HTTP/1.1 403 Forbidden " ));
2021-12-16 21:25:42 +03:00
if ( $mark !== 1 && $mark !== 2 )
2021-12-15 01:56:23 +03:00
exit ( header ( " HTTP/1.1 400 Bad Request " ));
$comment -> setMark ( $mark );
$comment -> save ();
2021-12-16 21:25:42 +03:00
exit ( header ( " HTTP/1.1 200 OK " ));
2021-12-15 01:56:23 +03:00
}
2022-03-26 23:48:42 +03:00
function renderQuickBanInSupport ( int $id ) : void
{
$this -> assertPermission ( " openvk \ Web \ Models \ Entities \T icketReply " , " write " , 0 );
$this -> assertNoCSRF ();
$user = ( new Users ) -> get ( $id );
if ( ! $user )
exit ( json_encode ([ " error " => " User does not exist " ]));
$user -> setBlock_In_Support_Reason ( $this -> queryParam ( " reason " ));
$user -> save ();
2022-07-17 17:50:37 +03:00
if ( $this -> queryParam ( " close_tickets " ))
DatabaseConnection :: i () -> getConnection () -> query ( " UPDATE tickets SET type = 2 WHERE user_id = " . $id );
2022-03-26 23:48:42 +03:00
$this -> returnJson ([ " success " => true , " reason " => $this -> queryParam ( " reason " ) ]);
}
function renderQuickUnbanInSupport ( int $id ) : void
{
$this -> assertPermission ( " openvk \ Web \ Models \ Entities \T icketReply " , " write " , 0 );
$this -> assertNoCSRF ();
$user = ( new Users ) -> get ( $id );
if ( ! $user )
exit ( json_encode ([ " error " => " User does not exist " ]));
$user -> setBlock_In_Support_Reason ( null );
$user -> save ();
$this -> returnJson ([ " success " => true ]);
}
2022-11-08 00:36:07 +03:00
function renderAgent ( int $id ) : void
{
$this -> assertPermission ( " openvk \ Web \ Models \ Entities \T icketReply " , " write " , 0 );
$support_names = new SupportAgents ;
if ( ! $support_names -> isExists ( $id ))
$this -> template -> mode = " edit " ;
$this -> template -> agent_id = $id ;
$this -> template -> mode = in_array ( $this -> queryParam ( " act " ), [ " info " , " edit " ]) ? $this -> queryParam ( " act " ) : " info " ;
$this -> template -> agent = $support_names -> get ( $id ) ? ? NULL ;
$this -> template -> counters = [
" all " => ( new TicketComments ) -> getCountByAgent ( $id ),
" good " => ( new TicketComments ) -> getCountByAgent ( $id , 1 ),
" bad " => ( new TicketComments ) -> getCountByAgent ( $id , 2 )
];
if ( $id != $this -> user -> identity -> getId ())
if ( $support_names -> isExists ( $id ))
$this -> template -> mode = " info " ;
else
$this -> redirect ( " /support/agent " . $this -> user -> identity -> getId ());
}
function renderEditAgent ( int $id ) : void
{
$this -> assertPermission ( " openvk \ Web \ Models \ Entities \T icketReply " , " write " , 0 );
$this -> assertNoCSRF ();
$support_names = new SupportAgents ;
$agent = $support_names -> get ( $id );
if ( $agent )
if ( $agent -> getAgentId () != $this -> user -> identity -> getId ()) $this -> flashFail ( " err " , tr ( " error " ), tr ( " forbidden " ));
if ( $support_names -> isExists ( $id )) {
$agent = $support_names -> get ( $id );
$agent -> setName ( $this -> postParam ( " name " ) ? ? tr ( " helpdesk_agent " ));
$agent -> setNumerate (( int ) $this -> postParam ( " number " ) ? ? NULL );
$agent -> setIcon ( $this -> postParam ( " avatar " ));
$agent -> save ();
$this -> flashFail ( " succ " , " Успех " , " Профиль отредактирован. " );
} else {
$agent = new SupportAgent ;
$agent -> setAgent ( $this -> user -> identity -> getId ());
$agent -> setName ( $this -> postParam ( " name " ) ? ? tr ( " helpdesk_agent " ));
$agent -> setNumerate (( int ) $this -> postParam ( " number " ) ? ? NULL );
$agent -> setIcon ( $this -> postParam ( " avatar " ));
$agent -> save ();
$this -> flashFail ( " succ " , " Успех " , " Профиль создан. Теперь пользователи видят Ваши псевдоним и аватарку вместо стандартных аватарки и номера. " );
}
}
2023-08-03 18:56:19 +03:00
function renderSendUserTicket () : void
{
$this -> assertPermission ( " openvk \ Web \ Models \ Entities \T icketReply " , " write " , 0 );
$this -> assertNoCSRF ();
if ( ! $this -> postParam ( " uid " ) || ! $this -> postParam ( " text " ))
$this -> returnJson ([ " success " => false , " error " => " Один или несколько обязательных параметров не были переданы " ]);
$user = ( new Users ) -> get (( int ) $this -> postParam ( " uid " ));
if ( ! $user ) $this -> returnJson ([ " success " => false , " error " => " Пользователь не найден " ]);
$ticket = new Ticket ;
$ticket -> setType ( 1 );
$ticket -> setUser_Id ( $user -> getId ());
$ticket -> setName ( " [Вопрос от Поддержки] " . ( $this -> postParam ( " title " ) ? " " . $this -> postParam ( " title " ) : " " ));
$ticket -> setText ( $this -> postParam ( " text " ));
$ticket -> setCreated ( time ());
$ticket -> setSupport_Sender ( $this -> user -> id );
$ticket -> save ();
$comment = new TicketComment ;
$comment -> setUser_Id ( $this -> user -> id );
$comment -> setUser_Type ( 1 );
$comment -> setText ( $this -> postParam ( " text " ));
$comment -> setCreated ( time ());
$comment -> setTicket_Id ( $ticket -> getId ());
$comment -> save ();
$user -> adminNotify (( $user -> isFemale () ? " Дорогая " : " Дорогой " ) . $user -> getFirstName () . " ! \n \n Вы получили новый вопрос (https:// $_SERVER[SERVER_NAME] /support/view/ { $ticket -> getId () } ) от Команды Поддержки " . OPENVK_ROOT_CONF [ " openvk " ][ " appearance " ][ " name " ]);
$this -> returnJson ([ " success " => true , " payload " => $ticket -> getId ()]);
}
2022-03-26 23:48:42 +03:00
}