OpenXE/www/pages/chat.php
2021-05-21 08:49:41 +02:00

392 lines
15 KiB
PHP

<?php
/*
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*
* Xentral (c) Xentral ERP Sorftware GmbH, Fuggerstrasse 11, D-86150 Augsburg, * Germany 2019
*
* This file is licensed under the Embedded Projects General Public License *Version 3.1.
*
* You should have received a copy of this license from your vendor and/or *along with this file; If not, please visit www.wawision.de/Lizenzhinweis
* to obtain the text of the corresponding license version.
*
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*/
?>
<?php
class Chat {
/** @var Application $app */
var $app;
/** @var \Xentral\Components\Template\TemplateInterface $tmpl */
protected $tmpl;
const MODULE_NAME = 'Chat';
public function __construct($app, $intern=false)
{
$this->app=$app;
if($intern){
return;
}
$this->tmpl = $this->app->Container->get('Template');
$this->tmpl->setDefaultNamespace('Modules/Chat');
$this->app->ActionHandlerInit($this);
$this->app->ActionHandler("list","ChatList");
$this->app->DefaultActionHandler("list");
$this->app->ActionHandlerListen($app);
}
public function Install()
{
$this->app->erp->CheckTable("chat");
$this->app->erp->CheckColumn("id","int(11)","chat","NOT NULL AUTO_INCREMENT");
$this->app->erp->CheckColumn("user_from","INT(11)","chat","DEFAULT '0' NOT NULL");
$this->app->erp->CheckColumn("user_to","INT(11)","chat","DEFAULT '0' NOT NULL");
$this->app->erp->CheckColumn("message","TEXT","chat","DEFAULT '' NOT NULL");
$this->app->erp->CheckColumn("prio","TINYINT(1)","chat","DEFAULT '0' NOT NULL");
$this->app->erp->CheckColumn("zeitstempel","DATETIME","chat");
$this->app->erp->CheckIndex("chat","user_from");
$this->app->erp->CheckIndex("chat","user_to");
if (!$this->app->DB->CheckTableExistence("chat_gelesen")){
$this->InstallGelesenTable();
}
}
protected function InstallGelesenTable()
{
// Neue Gelesen-Tabelle anlegen
$this->app->erp->CheckTable("chat_gelesen");
$this->app->erp->CheckColumn("id","int(11)","chat_gelesen","NOT NULL AUTO_INCREMENT");
$this->app->erp->CheckColumn("user","INT(11)","chat_gelesen","DEFAULT '0' NOT NULL");
$this->app->erp->CheckColumn("message","INT(11)","chat_gelesen","DEFAULT '0' NOT NULL");
$this->app->erp->CheckColumn("zeitstempel","DATETIME","chat_gelesen", "DEFAULT NULL");
$this->app->erp->CheckIndex("chat_gelesen","message");
//$this->app->DB->Query("ALTER TABLE chat_gelesen ADD UNIQUE (`user`, `message`)");
$this->app->erp->CheckIndex("chat_gelesen", array('user','message'), true);
$this->app->DB->Insert("INSERT INTO chat_gelesen (message, `user`, zeitstempel) SELECT DISTINCT id, user_to, NULL FROM chat WHERE gelesen = 1 OR user_to = 0");
if($this->app->DB->error())
{
// Alte Gelesen-Markierungen in neue Tabelle übernehmen
$readMessages = $this->app->DB->SelectArr("SELECT c.id, c.user_to FROM chat AS c WHERE c.gelesen = '1' AND c.user_to > 0");
foreach ($readMessages as $readMessage) {
$sql = "INSERT INTO chat_gelesen (message, `user`, zeitstempel) ";
$sql .= "VALUES ('".$readMessage['id']."', '".$readMessage['user_to']."', NULL)";
$this->app->DB->Insert($sql);
}
// Gelesen-Markierungen für öffentlichen Nachrichten übernehmen
$publicMessages = $this->app->DB->SelectArr("SELECT c.id, c.user_to FROM chat AS c WHERE c.user_to = 0");
foreach ($publicMessages as $publicMessage) {
$sql = "INSERT INTO chat_gelesen (message, `user`, zeitstempel) ";
$sql .= "VALUES ('".$publicMessage['id']."', '".$publicMessage['user_to']."', NULL)";
$this->app->DB->Insert($sql);
}
}
// Alte Gelesen-Spalte löschen
$this->app->DB->Query("ALTER TABLE chat DROP COLUMN gelesen");
}
public function ChatList()
{
$cmd = $this->app->Secure->GetGET('cmd');
switch ($cmd) {
case 'userlist':
$data = array();
$data['users'] = $this->GetUserlist();
$data['rooms'] = $this->GetRoomlist();
header('Content-Type: application/json');
echo json_encode($data);
exit;
case 'messages':
$user_id = (int)$this->app->Secure->GetPOST('user_id');
$before_message_id = (int)$this->app->Secure->GetPOST('before_message_id');
$after_message_id = (int)$this->app->Secure->GetPOST('after_message_id');
$after_readmark_id = (int)$this->app->Secure->GetPOST('after_readmark_id');
$data = $this->GetMessages($user_id, $after_message_id, $after_readmark_id, $before_message_id);
header('Content-Type: application/json');
echo json_encode($data);
exit;
case 'sendmessage':
$this->ChatSubmit();
exit;
case 'markread':
$messageIds = $this->app->Secure->GetPOST('messages');
$data = $this->MarkAsRead($messageIds);
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
$this->app->erp->StartseiteMenu();
if($this->app->DB->Select("SELECT chat_popup FROM `user` WHERE id = '".$this->app->User->GetID()."' LIMIT 1"))
{
$this->app->BuildNavigation = false;
$this->app->PopupJS = true;
$this->tmpl->assign('chatStandaloneClass', 'chat-standalone');
}
$this->tmpl->assign('tabText', 'Chat');
$this->tmpl->display('list.tpl');
}
protected function GetRoomList()
{
$userId = $this->app->User->GetID();
$registrierDatum = $this->app->DB->Select("SELECT u.logdatei FROM `user` AS u WHERE u.id = '".$userId."'");
// Öffentliche Nachrichten erst ab Registrierdatum zählen
$ungelesen = $this->app->DB->Select(
"SELECT COUNT(c.id)
FROM chat AS c
LEFT JOIN chat_gelesen AS g ON c.id = g.message AND (g.user = '".$userId."' OR g.user = 0)
WHERE c.user_to='0' AND c.zeitstempel > '".$registrierDatum."'
AND g.id IS NULL"
);
$data = array(
array(
'id' => 0,
'name' => 'Öffentlich',
'unread' => $ungelesen,
)
);
return $data;
}
protected function GetUserlist()
{
$userId = $this->app->User->GetID();
$users = $this->app->DB->SelectArr(
"SELECT DISTINCT u.id, a.name, uo.login, DATE_ADD(uo.time, INTERVAL 30 MINUTE) > NOW() AS recently_online
FROM user u
INNER JOIN adresse a ON a.id = u.adresse
INNER JOIN adresse_rolle ar ON ar.adresse = a.id
LEFT JOIN useronline uo ON uo.user_id = u.id AND uo.login = 1
WHERE u.activ = 1 AND u.kalender_ausblenden != 1 AND ar.subjekt = 'Mitarbeiter'
AND (ar.bis = '0000-00-00' OR ar.bis <= NOW())
AND ((u.hwtoken <> 4 ) OR u.hwtoken IS NULL)
ORDER BY a.name ASC"
);
$data = array();
$cusers = !empty($users)?count($users):0;
for($i=0;$i<$cusers;$i++)
{
$ungelesen = $this->app->DB->Select(
"SELECT COUNT(c.id) FROM chat AS c
LEFT JOIN chat_gelesen AS g ON c.id = g.message
WHERE c.user_to='" . $userId . "'
AND c.user_from='" . $users[$i]['id'] . "'
AND g.id IS NULL" // Kein Eintrag in chat_gelesen = ungelesen
);
$data[$i]['id'] = $users[$i]['id'];
$data[$i]['name'] = $users[$i]['name'];
$data[$i]['unread'] = (int)$ungelesen;
$data[$i]['online'] = (int)$users[$i]['login'] === 1 && (int)$users[$i]['recently_online'] === 1 ? true : false;
$data[$i]['self'] = ($users[$i]['id'] == $this->app->User->GetID()) ? true : false;
}
return $data;
}
protected function GetMessages($fromUserId, $afterMessageId = null, $afterReadmarkId = null, $beforeMessageId = null)
{
$fromUserId = (int)$fromUserId;
$selfUserId = (int)$this->app->User->GetID();
$andWhere = '';
if ($beforeMessageId !== null && $beforeMessageId !== 0) {
$andWhere = "AND c.id < " . (int)$beforeMessageId . " ";
}
if ($afterMessageId !== null && $afterMessageId !== 0) {
$andWhere = "AND c.id > " . (int)$afterMessageId . " ";
}
if ($fromUserId === 0) {
// Chat mit "Öffentlich"
$sql = "SELECT c.id, c.user_from, a.name AS user_from_name, g.id AS gelesen_id, g.zeitstempel AS gelesen_zeitstempel, c.message, c.user_to,
DATE_FORMAT(c.zeitstempel,'%d.%m.%Y') AS datum, DATE_FORMAT(c.zeitstempel,'%H:%i:%s') AS uhrzeit
FROM chat AS c
LEFT JOIN chat_gelesen AS g ON c.id = g.message AND (g.user = '".$selfUserId."' OR g.user = 0)
INNER JOIN `user` AS u ON c.user_from = u.id
INNER JOIN adresse AS a ON u.adresse = a.id
WHERE c.user_to = 0 ";
$sql .= $andWhere;
$sql .= "GROUP BY c.id ";
$sql .= "ORDER BY c.id DESC LIMIT 0, 20";
$messages = $this->app->DB->SelectArr($sql);
// Gelesen-Markierungen gibt es nicht im öffentlichen Chat
$readmarks = array();
} else {
// Chat mit Benutzer
// Nachrichten abrufen
$sql = "SELECT c.id, c.user_from, a.name AS user_from_name, g.id AS gelesen_id, c.message, c.prio, c.user_to,
DATE_FORMAT(c.zeitstempel,'%d.%m.%Y') AS datum, DATE_FORMAT(c.zeitstempel,'%H:%i:%s') AS uhrzeit
FROM chat AS c
LEFT JOIN chat_gelesen AS g ON c.id = g.message AND c.user_to = g.user
INNER JOIN `user` AS u ON c.user_from = u.id
INNER JOIN adresse AS a ON u.adresse = a.id
WHERE ((c.user_to = '" . $fromUserId . "' AND user_from = '" . $selfUserId . "')
OR (c.user_from = '" . $fromUserId . "' AND user_to = '" . $selfUserId . "')) ";
$sql .= $andWhere;
$sql .= "ORDER by c.id DESC LIMIT 0, 20";
$messages = $this->app->DB->SelectArr($sql);
// Gelesen-Markierungen abrufen
$sql = "SELECT g.id, g.message
FROM chat_gelesen AS g
WHERE g.user = '".$fromUserId."' ";
if ($afterReadmarkId > 0) {
$sql .= "AND g.id > '".$afterReadmarkId."' ";
$sql .= "ORDER BY g.id ASC LIMIT 0, 20";
} else {
// Nur die neueste Markierung mitschicken
$sql .= "ORDER BY g.id DESC LIMIT 0, 1";
}
$readmarks = $this->app->DB->SelectArr($sql);
}
$data = array(
'messages' => array(), // Chat-Nachrichten
'readmark' => array() // Gelesen-Markierungen
);
// Nachrichten aufbereiten
foreach ($messages as $message) {
$data['messages'][] = array(
'id' => (int)$message['id'],
'read' => ((int)$message['gelesen_id'] > 0) ? true : false,
'prio' => (!empty($message['prio']) && $message['prio'] === '1') ? true : false,
'text' => $this->MakeLinks($message['message']),
'user' => (int)$message['user_from'],
'name' => $message['user_from_name'],
'date' => $message['datum'],
'time' => $message['uhrzeit']
);
}
$data['messages'] = array_reverse($data['messages']);
// Gelesen-Markierungen aufbereiten
if (is_array($readmarks)) {
foreach ($readmarks as $readmark) {
$data['readmark'][] = array(
'id' => (int)$readmark['id'],
'message' => (int)$readmark['message'],
);
}
}
return $data;
}
protected function ChatSubmit()
{
/** @var \Xentral\Modules\SystemNotification\Service\NotificationServiceInterface $notification */
$notification = $this->app->Container->get('NotificationService');
$nachricht = $this->app->Secure->GetPOST("nachricht");
$empfaenger = $this->app->Secure->GetPOST("empfaenger");
$prio = $this->app->Secure->GetPOST("prio");
$nachricht = htmlspecialchars($nachricht);
if($nachricht!="")
{
$this->app->DB->Insert("INSERT INTO chat (id,user_from,user_to,message,zeitstempel,prio) VALUES ('','".$this->app->User->GetID()."','".$empfaenger."','$nachricht',NOW(),'.$prio.')");
if($prio == "1") {
$name = $this->app->DB->Select("SELECT a.name FROM user u LEFT JOIN adresse a ON a.id=u.adresse WHERE u.id=".$this->app->User->GetID());
if($empfaenger)
{
$notification->create($empfaenger, 'default', "$name (".date('d.m')." um ".date('H:i').")", $nachricht, true);
$notification->createPushNotification($empfaenger, 'Neue Chat-Nachricht von ' . $name, $nachricht, false);
}else{
$users = $this->app->DB->SelectArr("SELECT DISTINCT u.id, a.name,u.type,
uo.login FROM user u LEFT JOIN adresse a ON a.id=u.adresse LEFT JOIN useronline uo ON uo.user_id=u.id AND uo.login=1
LEFT JOIN adresse_rolle ar ON ar.adresse=a.id
WHERE u.activ=1 AND uo.login = 1 AND u.kalender_ausblenden!=1 AND ar.subjekt='Mitarbeiter' AND (ar.bis='0000-00-00' OR ar.bis <= NOW())
AND u.id!='".$this->app->User->GetID()."' AND ((u.hwtoken <> 4) OR u.hwtoken IS NULL) group by u.id");
if($users)
{
foreach($users as $user)
{
if($user['type'] == 'admin' || $this->app->DB->Select("SELECT id FROM userrights WHERE user = '".$user['id']."' AND module='chat' && action='list' and permission='1' LIMIT 1"))
{
$notification->create($user['id'], 'default', "$name (".date('d.m')." um ".date('H:i').")", $nachricht, true);
$notification->createPushNotification($user['id'], 'Neue Chat-Nachricht von ' . $name, $nachricht, false);
}
}
}
}
}
}
exit;
}
protected function MarkAsRead($messageIds)
{
if (!is_array($messageIds)) {
return array();
}
$data = array();
$userId = $this->app->User->GetID();
foreach ($messageIds as $messageId) {
if ((int)$messageId > 0) {
$sql = "INSERT INTO chat_gelesen(`user`, message, zeitstempel) VALUES ('".$userId."', '".$messageId."', NOW())";
$this->app->DB->Insert($sql);
$data[] = $messageId;
}
}
// IDs der gelesen-gesetzten Nachrichten zurücksenden
return $data;
}
protected function MakeLinks($str) {
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
$urls = array();
$urlsToReplace = array();
if(preg_match_all($reg_exUrl, $str, $urls)) {
$numOfMatches = count($urls[0]);
$numOfUrlsToReplace = 0;
for($i=0; $i<$numOfMatches; $i++) {
$alreadyAdded = false;
$numOfUrlsToReplace = count($urlsToReplace);
for($j=0; $j<$numOfUrlsToReplace; $j++) {
if($urlsToReplace[$j] == $urls[0][$i]) {
$alreadyAdded = true;
}
}
if(!$alreadyAdded) {
array_push($urlsToReplace, $urls[0][$i]);
}
}
$numOfUrlsToReplace = count($urlsToReplace);
for($i=0; $i<$numOfUrlsToReplace; $i++) {
$str = str_replace($urlsToReplace[$i], "<a href=\"".$urlsToReplace[$i]."\" target=\"_blank\">".$urlsToReplace[$i]."</a> ", $str);
}
return $str;
} else {
return $str;
}
}
}