app = $app;
if ($intern)
return;
$this->app->ActionHandlerInit($this);
$this->app->ActionHandler("list", "ticket_list");
$this->app->ActionHandler("create", "ticket_create"); // This automatically adds a "New" button
$this->app->ActionHandler("edit", "ticket_edit");
$this->app->ActionHandler("minidetail", "ticket_minidetail");
$this->app->ActionHandler("text", "ticket_text"); // Output text for iframe display
$this->app->ActionHandler("text_ausgang", "ticket_text_ausgang"); // Output text for iframe display
$this->app->ActionHandler("statusfix", "ticket_statusfix"); // Xentral 20 compatibility set all ticket status to latest ticket_nachricht status
$this->app->ActionHandler("datefix", "ticket_datefix"); // Xentral 20 compatibility set all ticket dates to latest ticket_nachricht date
$this->app->ActionHandler("dateien", "ticket_dateien");
$this->app->DefaultActionHandler("list");
$this->app->ActionHandlerListen($app);
}
public function Install() {
/* Fill out manually later */
}
function ticket_status_icon(string $status) {
return('');
}
public function TableSearch(&$app, $name, $erlaubtevars) {
function ticket_iconssql() {
return "CONCAT('')";
}
switch ($name) {
case "ticket_list":
$allowed['ticket_list'] = array('list');
$heading = array('','','Ticket #', 'Aktion','Adresse', 'Betreff', 'Tags', 'Verant.', 'Nachr.', 'Status', 'Projekt', 'Menü');
$width = array('1%','1%','5%', '5%', '5%', '30%', '1%', '5%', '1%', '1%', '1%', '1%');
$findcols = array('t.id','t.id','t.schluessel', 't.zeit', 'a.name', 't.betreff', 't.tags', 'w.warteschlange', 'nachrichten_anz', 't.status', 'p.abkuerzung');
$searchsql = array( 't.schluessel', 't.zeit', 'a.name', 't.betreff','t.notiz', 't.tags', 'w.warteschlange', 't.status', 'p.abkuerzung','(SELECT mail FROM ticket_nachricht tn WHERE tn.ticket = t.schluessel AND tn.versendet <> 1 LIMIT 1)');
$defaultorder = 1;
$defaultorderdesc = 0;
$menu = "
";
$timedifference = "if (
TIMESTAMPDIFF(hour, t.zeit, NOW()) < 24,
CONCAT(TIMESTAMPDIFF(hour, t.zeit, NOW()),'h'),
CONCAT(TIMESTAMPDIFF(day, t.zeit, NOW()), 'd ',MOD(TIMESTAMPDIFF(hour, t.zeit, NOW()),24),'h'))";
$dropnbox = "'' AS `open`,
CONCAT('') AS `auswahl`";
$priobetreff = "if(t.prio!=1,REGEXP_REPLACE(t.betreff, '<[^>]*>+', ''),CONCAT('',REGEXP_REPLACE(t.betreff, '<[^>]*>+', ''),''))"; //+ #20230916 XSS
$anzahlnachrichten = "(SELECT COUNT(n.id) FROM ticket_nachricht n WHERE n.ticket = t.schluessel)";
$letztemail = $app->erp->FormatDateTimeShort("(SELECT MAX(n.zeit) FROM ticket_nachricht n WHERE n.ticket = t.schluessel AND n.zeit IS NOT NULL)");
$tagstart = "";
$tagend = "";
$sql = "SELECT SQL_CALC_FOUND_ROWS
t.id,
".$dropnbox.",
CONCAT('',t.schluessel,''),".
$app->erp->FormatDateTimeShort('zeit')." as aktion,
CONCAT(COALESCE(CONCAT(a.name,'
'),''),COALESCE((SELECT mail FROM ticket_nachricht tn WHERE tn.ticket = t.schluessel AND tn.versendet <> 1 LIMIT 1),'')) as combiadresse,
CONCAT('',".$priobetreff.",'
',replace(substring(ifnull(t.notiz,''),1,500),'\n','
'),''),
CONCAT(''\n,'".$tagstart."',replace(t.tags,',','".$tagend."
".$tagstart."'),'".$tagend."','
'),
w.warteschlange,
".$anzahlnachrichten." as `nachrichten_anz`,
".ticket_iconssql().",
p.abkuerzung,
t.id
FROM ticket t
LEFT JOIN adresse a ON t.adresse = a.id
LEFT JOIN warteschlangen w ON t.warteschlange = w.label
LEFT JOIN projekt p on t.projekt = p.id";
$where = "1";
// Toggle filters
$this->app->Tpl->Add('JQUERYREADY', "$('#meinetickets').click( function() { fnFilterColumn1( 0 ); } );");
$this->app->Tpl->Add('JQUERYREADY', "$('#prio').click( function() { fnFilterColumn2( 0 ); } );");
$this->app->Tpl->Add('JQUERYREADY', "$('#geschlossene').click( function() { fnFilterColumn3( 0 ); } );");
$this->app->Tpl->Add('JQUERYREADY', "$('#spam').click( function() { fnFilterColumn4( 0 ); } );");
for ($r = 1;$r <= 4;$r++) {
$this->app->Tpl->Add('JAVASCRIPT', '
function fnFilterColumn' . $r . ' ( i )
{
if(oMoreData' . $r . $name . '==1)
oMoreData' . $r . $name . ' = 0;
else
oMoreData' . $r . $name . ' = 1;
$(\'#' . $name . '\').dataTable().fnFilter(
\'\',
i,
0,0
);
}
');
}
$more_data1 = $this->app->Secure->GetGET("more_data1");
if ($more_data1 == 1) {
$where .= " AND t.warteschlange IN (SELECT w.label FROM warteschlangen w WHERE adresse=".$this->app->User->GetAdresse().")"; // Queues of user
} else {
}
$more_data2 = $this->app->Secure->GetGET("more_data2");
if ($more_data2 == 1) {
$where .= " AND t.prio = '1'";
}
else {
}
$more_data3 = $this->app->Secure->GetGET("more_data3");
if ($more_data3 == 1) {
}
else {
$where .= " AND (t.status <> 'abgeschlossen')"; // Exclude and geschlossen
}
$more_data4 = $this->app->Secure->GetGET("more_data4");
if ($more_data4 == 1) {
}
else {
$where .= " AND (t.status <> 'spam')";
}
// END Toggle filters
$moreinfo = true; // Allow drop down details
$menucol = 11; // For moredata
$count = "SELECT count(DISTINCT id) FROM ticket t WHERE $where";
// echo(htmlentities($sql." ".$where));
// $groupby = "";
break;
}
$erg = false;
foreach ($erlaubtevars as $k => $v) {
if (isset($$v)) {
$erg[$v] = $$v;
}
}
return $erg;
}
// Ensure status 'offen' on self-assigned tickets
function ticket_set_self_assigned_status(array $ids) {
$sql = "UPDATE ticket SET status = 'offen'
WHERE
status = 'neu'
AND id IN (".implode(',',$ids).")
AND warteschlange IN (SELECT label FROM warteschlangen WHERE adresse = '".$this->app->User->GetAdresse()."')";
$this->app->DB->Update($sql);
}
function ticket_list() {
// Process multi action
$auswahl = $this->app->Secure->GetPOST('auswahl');
$submit = $this->app->Secure->GetPOST('submit');
$selectedIds = [];
if(!empty($auswahl)) {
foreach($auswahl as $selectedId) {
$selectedId = (int)$selectedId;
if($selectedId > 0) {
$selectedIds[] = $selectedId;
}
}
switch ($submit) {
case 'zuordnen':
$status = $this->app->Secure->GetPOST('status');
$warteschlange = $this->app->Secure->GetPOST('warteschlange');
$sql = "UPDATE ticket SET status = '".$status."', zeit = NOW()";
if ($warteschlange != '') {
$sql .= ", warteschlange = '".explode(" ",$warteschlange)[0]."'";
}
$sql .= " WHERE id IN (".implode(",",$selectedIds).")";
$this->app->DB->Update($sql);
$this->ticket_set_self_assigned_status($selectedIds);
break;
case 'spam_filter':
if($this->app->erp->RechteVorhanden('ticketregeln','create')) {
$sql = "UPDATE ticket SET status = 'spam', zeit = NOW()";
$sql .= " WHERE id IN (".implode(",",$selectedIds).")";
$this->app->DB->Update($sql);
foreach ($selectedIds as $selectedId) {
// Check existing
$sql = "SELECT id FROM ticket_regeln WHERE
empfaenger_email = '' AND
sender_email = (SELECT mailadresse FROM ticket WHERE id = ".$selectedId." LIMIT 1) AND
name = '' AND
betreff = '' AND
spam = 1 AND
aktiv = 1
";
if (!$this->app->DB->Select($sql)) {
$sql = "INSERT IGNORE INTO ticket_regeln (
empfaenger_email,
sender_email,
name,
betreff,
spam,
persoenlich,
prio,
dsgvo,
adresse,
warteschlange,
aktiv
) VALUES (
'',
(SELECT mailadresse FROM ticket WHERE id = ".$selectedId." LIMIT 1),
'',
'',
1,
0,
0,
0,
0,
'',
1
)";
$this->app->DB->Insert($sql);
}
}
}
break;
}
}
// List
$this->app->YUI->TagEditor('taglist', array('width'=>370));
$this->app->Tpl->Add('SCRIPTJAVASCRIPT','');
$this->app->erp->MenuEintrag("index.php?module=ticket&action=list", "Übersicht");
$this->app->erp->MenuEintrag("index.php?module=ticket&action=create", "Neu anlegen");
$this->app->erp->MenuEintrag("index.php", "Zurück");
$this->app->Tpl->Set('STATUS', $this->app->erp->GetStatusTicketSelect('neu'));
$this->app->YUI->AutoComplete("warteschlange","warteschlangename");
if(!$this->app->erp->RechteVorhanden('ticketregeln','create')) {
$this->app->Tpl->Set('SPAM_HIDDEN', 'hidden');
}
$this->app->YUI->TableSearch('TAB1', 'ticket_list', "show", "", "", basename(__FILE__), __CLASS__);
$this->app->Tpl->Parse('PAGE', "ticket_list.tpl");
}
function get_messages_of_ticket($ticket_id, $where, $limit) {
if ($limit) {
$limitsql = " LIMIT ".((int) $limit);
} else {
$limitsql = "";
}
if (empty($ticket_id)) {
$ticket_where = "";
} else {
$ticket_where = " AND t.id = ".$ticket_id;
}
if (empty($where)) {
$where = "1";
}
// $sql = "SELECT n.id, n.betreff, n.verfasser, n.mail, n.mail_cc, n.zeit, n.zeitausgang, n.versendet, n.text, n.verfasser_replyto, mail_replyto, (SELECT GROUP_CONCAT(value SEPARATOR ', ' FROM ticket_header th WHERE th.ticket_nachricht = n.id AND th.type = 'cc') value from) as cc FROM ticket_nachricht n INNER JOIN ticket t ON t.schluessel = n.ticket WHERE (".$where.") AND t.id = ".$ticket_id." ORDER BY n.zeit DESC ".$limitsql;
$sql = "SELECT n.id,
n.betreff,
n.bearbeiter,
n.verfasser,
n.mail,
t.quelle,
".$this->app->erp->FormatDateTimeShort('n.zeit','zeit').",
".$this->app->erp->FormatDateTimeShort('n.zeitausgang','zeitausgang').",
n.versendet,
n.text,
n.textausgang,
n.verfasser_replyto,
n.mail_replyto,
n.mail_cc,
(SELECT GROUP_CONCAT(value SEPARATOR ', ') FROM ticket_header th WHERE th.ticket_nachricht = n.id AND th.type = 'cc') as mail_cc_recipients,
(SELECT GROUP_CONCAT(value SEPARATOR ', ') FROM ticket_header th WHERE th.ticket_nachricht = n.id AND th.type = 'to') as mail_recipients
FROM ticket_nachricht n INNER JOIN ticket t ON t.schluessel = n.ticket
WHERE (".$where.") ".$ticket_where." ORDER BY n.zeit DESC ".$limitsql;
return $this->app->DB->SelectArr($sql);
}
function add_attachments_html($ticket_id, $message_id,$templatepos,$showdelete) {
$file_attachments = $this->app->erp->GetDateiSubjektObjekt('Anhang','Ticket',$message_id);
if (!empty($file_attachments)) {
$this->app->Tpl->Add('NACHRICHT_ANHANG',"
");
foreach ($file_attachments as $file_attachment) {
if ($showdelete) {
$deletetext = ''.
'';
} else {
$deletetext = "";
}
$attachtext = "";
/* Not implemented -> Attachment of ticket_nachricht to business object is the better option -> implement later
$attachtext = ''.
''; */
$this->app->Tpl->Add($templatepos,
"".
htmlentities($this->app->erp->GetDateiName($file_attachment)).
" (".
$this->app->erp->GetDateiSize($file_attachment).
")".
"".
$deletetext.
$attachtext.
"
");
}
}
}
function add_attachments_header_html($ticket_id, $templatepos) {
$file_attachments = $this->app->erp->GetDateiSubjektObjekt('%','ticket_header',$ticket_id);
if (!empty($file_attachments)) {
$this->app->Tpl->Add($templatepos,"{|Anhänge|}: | |
");
}
}
function add_messages_tpl($messages, $showdrafts) {
// Add Messages now
foreach ($messages as $message) {
$message['betreff'] = strip_tags($message['betreff']); //+ #20230916 XSS
// Clear this first
$this->app->Tpl->Set('NACHRICHT_ANHANG',"");
if (empty($message['betreff'])) {
$message['betreff'] = "...";
}
// Xentral 20 compatibility
if ($message['textausgang'] != '') {
// Sent message
$this->app->Tpl->Set("NACHRICHT_BETREFF",''.htmlentities($message['betreff']).'');
$this->app->Tpl->Set("NACHRICHT_ZEIT",$message['zeitausgang']);
$this->app->Tpl->Set("NACHRICHT_FLOAT","right");
$this->app->Tpl->Set("META_FLOAT","left");
$this->app->Tpl->Set("NACHRICHT_TEXT",$message['textausgang']);
$this->app->Tpl->Set("NACHRICHT_SENDER",htmlentities($message['bearbeiter']));
$this->app->Tpl->Set("NACHRICHT_RECIPIENTS",htmlentities($message['verfasser']." <".$message['mail'].">"));
// $this->app->Tpl->Set("NACHRICHT_TEXT",$message['textausgang']);
$this->app->Tpl->Set("NACHRICHT_TEXT",'');
$this->app->Tpl->Parse('MESSAGES', "ticket_nachricht.tpl");
}
if ($message['versendet'] == '1' && empty($message['textausgang'])) { // textausgang is always empty, except for old Xentral 20 tickets
// Sent message
if (is_null($message['zeitausgang'])) {
if (!$showdrafts) {
continue;
}
$this->app->Tpl->Set("NACHRICHT_BETREFF",htmlentities($message['betreff']." (Entwurf)"));
} else {
$this->app->Tpl->Set("NACHRICHT_BETREFF",''.htmlentities($message['betreff']).'');
}
$this->app->Tpl->Set("NACHRICHT_SENDER",htmlentities($message['verfasser']." <".$message['mail_replyto'].">"));
$this->app->Tpl->Set("NACHRICHT_RECIPIENTS",htmlentities($message['mail']));
$this->app->Tpl->Set("NACHRICHT_CC_RECIPIENTS",htmlentities($message['mail_cc']));
$this->app->Tpl->Set("NACHRICHT_FLOAT","right");
$this->app->Tpl->Set("META_FLOAT","left");
$this->app->Tpl->Set("NACHRICHT_ZEIT",$message['zeitausgang']);
$this->app->Tpl->Set("NACHRICHT_NAME",htmlentities($message['verfasser']));
} else {
// Received message
$this->app->Tpl->Set("NACHRICHT_SENDER",htmlentities($message['verfasser']." <".$message['mail'].">"));
if ($message['mail_recipients'] != '') {
$this->app->Tpl->Set("NACHRICHT_RECIPIENTS",htmlentities($message['mail_recipients']));
}
else {
// Xentral 20 compatibility
$this->app->Tpl->Set("NACHRICHT_RECIPIENTS",htmlentities($message['quelle']));
}
$this->app->Tpl->Set("NACHRICHT_CC_RECIPIENTS",htmlentities($message['mail_cc_recipients']));
$this->app->Tpl->Set("NACHRICHT_BETREFF",''.htmlentities($message['betreff']).'');
$this->app->Tpl->Set("NACHRICHT_FLOAT","left");
$this->app->Tpl->Set("META_FLOAT","right");
$this->app->Tpl->Set("NACHRICHT_ZEIT",$message['zeit']);
}
// $this->app->Tpl->Set("NACHRICHT_TEXT",$message['text']);
$this->app->Tpl->Set("NACHRICHT_TEXT",'');
$this->add_attachments_html($id,$message['id'],'NACHRICHT_ANHANG',false);
$this->app->Tpl->Parse('MESSAGES', "ticket_nachricht.tpl");
}
}
function ticket_text() {
$secure_html_tags = array(
'
',
'',
'',
'',
'