api.ubmessenger.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. <?php
  2. /**
  3. * Ubilling instant messenger API
  4. */
  5. class UBMessenger {
  6. /**
  7. * Current user instance login
  8. *
  9. * @var string
  10. */
  11. protected $myLogin = '';
  12. /**
  13. * Messages database abstraction layer
  14. *
  15. * @var object
  16. */
  17. protected $messagesDb = '';
  18. /**
  19. * Constains system alter config as key=>value
  20. *
  21. * @var array
  22. */
  23. protected $altCfg = array();
  24. /**
  25. * Contains all cached employee names as login=>name
  26. *
  27. * @var array
  28. */
  29. protected $allEmployeeNames = array();
  30. /**
  31. * Contains available administrators
  32. *
  33. * @var array
  34. */
  35. protected $allAdmins = array();
  36. /**
  37. * Threads refresh interval in ms.
  38. *
  39. * @var int
  40. */
  41. protected $refreshInterval = 2000;
  42. /**
  43. * Contacts refresh interval in ms.
  44. *
  45. * @var int
  46. */
  47. protected $refreshContacts = 5000;
  48. /**
  49. * Admin online timeout interval in minutes
  50. *
  51. * @var int
  52. */
  53. protected $onlineTimeout = 10;
  54. /**
  55. * ZenFlow instance for refreshing messages data
  56. *
  57. * @var object
  58. */
  59. protected $threadsFlow = '';
  60. /**
  61. * Undocumented variable
  62. *
  63. * @var object
  64. */
  65. protected $contactsFlow = '';
  66. /**
  67. * Contains caching object instance
  68. *
  69. * @var object
  70. */
  71. protected $cache = '';
  72. /**
  73. * Contains default cacning timeout in seconds
  74. *
  75. * @var int
  76. */
  77. protected $cachingTimeout = 3600;
  78. /**
  79. * System messages helper instance
  80. *
  81. * @var object
  82. */
  83. protected $messages = '';
  84. /**
  85. * Contains current thread ID
  86. *
  87. * @var string
  88. */
  89. protected $currentThread = '';
  90. /**
  91. * Contains message sound notification path
  92. *
  93. * @var string
  94. */
  95. protected $messageSound = 'modules/jsc/sounds/message.mp3';
  96. //some predefined stuff like routes and keys here
  97. const TABLE_MESSAGES = 'ub_im';
  98. const URL_ME = '?module=ubim';
  99. const URL_AVATAR_CONTROL = '?module=avacontrol';
  100. const ROUTE_THREAD = 'showthread';
  101. const ROUTE_GOTHREAD = 'gothread';
  102. const ROUTE_REFRESH = 'checknew';
  103. const PROUTE_MSG_TO = 'im_message_to';
  104. const PROUTE_MSG_TEXT = 'im_message_text';
  105. const SCOPE_THREAD = 'rtubimthread';
  106. const SCOPE_CONTACTS = 'rtubimcontacts';
  107. const KEY_ADMS_ONLINE = 'UBIM_ADM_ONLINE';
  108. const KEY_MSG_COUNT = 'UBIM_MSGCOUNT_';
  109. const KEY_MSG_THREADS = 'UBIM_MSG_TH_';
  110. const KEY_ADMS_LIST = 'UBIM_ADM_LIST';
  111. const OPT_NOLINKIFY = 'UBIM_NO_LINKIFY';
  112. const OPT_NOAJAXSEND = 'UBIM_MSGSEND_NATIVE';
  113. public function __construct() {
  114. $this->setMyLogin();
  115. $this->initDb();
  116. $this->loadConfigs();
  117. $this->initCache();
  118. $this->initMessages();
  119. $this->loadAdmins();
  120. $this->loadEmployeeNames();
  121. }
  122. /**
  123. ________________ ______________
  124. / \ / / \-___
  125. / / \ \ \ | - - \
  126. | | | / - \ _ |
  127. / / \ / / // __ \
  128. | ___\ \| | / / \/ // // / /// / \
  129. | / \ | //\ __ |
  130. | | \ \ /// \
  131. / | _ | \ // \ |
  132. | | \ | \ /-- // |
  133. | | _\ /| / (o- / \|
  134. | __\ <_o)\o- / __ /\ |
  135. | | \ / ) / |
  136. \ || \ / __ |/ / \ |
  137. | |__ _ \ (____ *) - | |
  138. | | (*___) / | |
  139. | | _ | (____ | |
  140. | | //_______/ ####\ | |
  141. | / | UUUUU__ ____/ ) |_/
  142. \| \_nnnnnn_\-\ (___ /
  143. | ____________/ \____ |
  144. | / \ |
  145. |_____/ \___________\
  146. /\/\/\/\/\/\/\/\/\ /\/\/\/\/\/\/\/\/\/\/\/\/\
  147. / \ / \
  148. < I AM CORNHOLIO > < FUCK YOU! >
  149. \ / \ /
  150. \/\/\/\/\/\/\/\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/
  151. */
  152. /**
  153. * Sets current instance administrator login
  154. *
  155. * @return void
  156. */
  157. protected function setMyLogin() {
  158. $this->myLogin = whoami();
  159. }
  160. /**
  161. * Loads required configs
  162. *
  163. * @return void
  164. */
  165. protected function loadConfigs() {
  166. global $ubillingConfig;
  167. $this->altCfg = $ubillingConfig->getAlter();
  168. }
  169. /**
  170. * Inits message helper
  171. *
  172. * @return void
  173. */
  174. protected function initMessages() {
  175. $this->messages = new UbillingMessageHelper();
  176. }
  177. /**
  178. * Inits caching engine
  179. *
  180. * @return void
  181. */
  182. protected function initCache() {
  183. $this->cache = new UbillingCache();
  184. }
  185. /**
  186. * Preloads existing employee names
  187. *
  188. * @return void
  189. */
  190. protected function loadEmployeeNames() {
  191. $this->allEmployeeNames = ts_GetAllEmployeeLoginsAssocCached();
  192. }
  193. /**
  194. * Inits database abstraction layer
  195. *
  196. * @return void
  197. */
  198. protected function initDb() {
  199. $this->messagesDb = new NyanORM(self::TABLE_MESSAGES);
  200. }
  201. /**
  202. * Loads existing administrators
  203. *
  204. * @return void
  205. */
  206. protected function loadAdmins() {
  207. $cachedData = $this->cache->get(self::KEY_ADMS_LIST, $this->cachingTimeout);
  208. if (empty($cachedData) and !is_array($cachedData)) {
  209. $adminsRaw = rcms_scandir(DATA_PATH . 'users/');
  210. if (!empty($adminsRaw)) {
  211. foreach ($adminsRaw as $io => $eachAdmin) {
  212. $this->allAdmins[$eachAdmin] = $eachAdmin;
  213. }
  214. }
  215. $this->cache->set(self::KEY_ADMS_LIST, $this->allAdmins, $this->cachingTimeout);
  216. } else {
  217. $this->allAdmins = $cachedData;
  218. }
  219. }
  220. /**
  221. * Renders self-refreshing thread content
  222. *
  223. * @param string $threadId
  224. *
  225. * @return string
  226. */
  227. public function renderZenThread($threadId) {
  228. $result = '';
  229. if ($threadId) {
  230. if (isset($this->allAdmins[$threadId])) {
  231. $this->threadsFlow = new ZenFlow(self::SCOPE_THREAD . '_' . $threadId, $this->renderThreadContent($threadId), $this->refreshInterval);
  232. if (!@$this->altCfg['UBIM_MSG_MUTE']) {
  233. $this->threadsFlow->setSoundOnChange($this->messageSound);
  234. }
  235. $result .= $this->threadsFlow->render();
  236. }
  237. }
  238. return ($result);
  239. }
  240. /**
  241. * Returns self-refreshing contacts list
  242. *
  243. * @return void
  244. */
  245. protected function renderZenContacts() {
  246. $this->contactsFlow = new ZenFlow(self::SCOPE_CONTACTS, $this->renderContactList(), $this->refreshContacts);
  247. return ($this->contactsFlow->render());
  248. }
  249. /**
  250. * Creates new message for some user
  251. *
  252. * @param string $to admin login
  253. * @param string $text message text
  254. *
  255. * @return void
  256. */
  257. public function createMessage($to, $text) {
  258. $from = $this->myLogin;
  259. $to = ubRouting::filters($to, 'mres');
  260. $text = ubRouting::filters($text, 'mres');
  261. $text = strip_tags($text);
  262. $this->messagesDb->data('date', curdatetime());
  263. $this->messagesDb->data('from', $from);
  264. $this->messagesDb->data('to', $to);
  265. $this->messagesDb->data('text', $text);
  266. $this->messagesDb->data('read', '0');
  267. $this->messagesDb->create();
  268. $this->flushCachedData($to);
  269. log_register('UBIM SEND FROM {' . $from . '} TO {' . $to . '}');
  270. }
  271. /**
  272. * Flushes all relative to sent message cache keys
  273. *
  274. * @param string $to
  275. *
  276. * @return void
  277. */
  278. protected function flushCachedData($to) {
  279. $this->cache->delete(self::KEY_ADMS_ONLINE);
  280. $this->cache->delete(self::KEY_MSG_COUNT . $to);
  281. $this->cache->delete(self::KEY_MSG_COUNT . $this->myLogin);
  282. $this->cache->delete(self::KEY_MSG_THREADS . $to . '_' . $this->myLogin);
  283. $this->cache->delete(self::KEY_MSG_THREADS . $this->myLogin . '_' . $to);
  284. }
  285. /**
  286. * Deletes message by its ID
  287. *
  288. * @param int $msgid message id from messages database
  289. *
  290. * @return void
  291. */
  292. public function deleteMessage($msgId) {
  293. $msgId = ubRouting::filters($msgId, 'int');
  294. $this->messagesDb->where('id', '=', $msgId);
  295. $this->messagesDb->delete();
  296. log_register('UBIM DELETE [' . $msgId . ']');
  297. }
  298. /**
  299. * mark thread as read by sender
  300. *
  301. * @param string $sender sender login
  302. *
  303. * @return void
  304. */
  305. protected function threadMarkAsRead($sender) {
  306. $sender = ubRouting::filters($sender, 'mres');
  307. $this->messagesDb->data('read', '1');
  308. $this->messagesDb->where('to', '=', $this->myLogin);
  309. $this->messagesDb->where('from', '=', $sender);
  310. $this->messagesDb->where('read', '=', '0');
  311. $this->messagesDb->save();
  312. $this->flushCachedData($sender);
  313. }
  314. /**
  315. * Returns array of users from which we have some unread messages as login=>count
  316. *
  317. * @return array
  318. */
  319. function getAllUnreadMessagesUsers() {
  320. $result = array();
  321. $cachedData = $this->cache->get(self::KEY_MSG_COUNT . $this->myLogin, $this->cachingTimeout);
  322. if (empty($cachedData) and !is_array($cachedData)) {
  323. $this->messagesDb->where('read', '=', '0');
  324. $this->messagesDb->where('to', '=', $this->myLogin);
  325. $all = $this->messagesDb->getAll();
  326. if (!empty($all)) {
  327. foreach ($all as $io => $each) {
  328. if (isset($result[$each['from']])) {
  329. $result[$each['from']]++;
  330. } else {
  331. $result[$each['from']] = 1;
  332. }
  333. }
  334. }
  335. $this->cache->set(self::KEY_MSG_COUNT . $this->myLogin, $result, $this->cachingTimeout);
  336. } else {
  337. $result = $cachedData;
  338. }
  339. return ($result);
  340. }
  341. /**
  342. * Return contact list with some available users
  343. *
  344. * @return string
  345. */
  346. protected function renderContactList() {
  347. $admListOrdered = array();
  348. $activeAdmins = $this->getActiveAdmins();
  349. $haveUnread = $this->getAllUnreadMessagesUsers();
  350. $result = wf_tag('div', false, 'ubim-contacts-container');
  351. //list reordering
  352. if (!empty($this->allAdmins)) {
  353. $order = sizeof($this->allAdmins);
  354. foreach ($this->allAdmins as $io => $eachadmin) {
  355. $order++;
  356. if ($eachadmin != $this->myLogin) {
  357. if (isset($haveUnread[$eachadmin])) {
  358. $admListOrdered[$order] = $eachadmin;
  359. } else {
  360. $admListOrdered[($order + 9000)] = $eachadmin; // It`s Over 9000!
  361. }
  362. }
  363. }
  364. if (!empty($admListOrdered)) {
  365. ksort($admListOrdered);
  366. foreach ($admListOrdered as $io => $eachadmin) {
  367. $unreadCounter = (isset($haveUnread[$eachadmin])) ? $haveUnread[$eachadmin] : 0;
  368. if ($eachadmin != $this->myLogin) {
  369. $unreadLabel = '';
  370. $contactClass = 'ubim-contact';
  371. if (isset($activeAdmins[$eachadmin])) {
  372. $contactClass .= ' ubim-online ';
  373. }
  374. if (ubRouting::get(self::ROUTE_THREAD) == $eachadmin) {
  375. $contactClass .= ' ubim-open ';
  376. }
  377. if ($unreadCounter != 0) {
  378. $contactClass .= ' ubim-unread ';
  379. $unreadLabel .= wf_tag('div', false, 'ubim-unread-label') . $unreadCounter . ' ' . __('Unread message') . wf_tag('div', true);
  380. }
  381. $conatactAvatar = gravatar_ShowAdminAvatar($eachadmin, '64', 'ubim-avatar');
  382. $adminName = (isset($this->allEmployeeNames[$eachadmin])) ? $this->allEmployeeNames[$eachadmin] : $eachadmin;
  383. $contactBody = $conatactAvatar;
  384. $contactBody .= wf_tag('span', false, 'ubim-contact-name');
  385. $contactBody .= $adminName;
  386. $contactBody .= $unreadLabel;
  387. $contactBody .= wf_tag('span', true);
  388. $threadLink = wf_Link(self::URL_ME . '&' . self::ROUTE_THREAD . '=' . $eachadmin, $contactBody, false, $contactClass);
  389. $result .= $threadLink;
  390. }
  391. }
  392. } else {
  393. $result .= $this->messages->getStyledMessage(__('Administrators') . ' ' . __('not exists'), 'ubim-contact-name');
  394. }
  395. } else {
  396. $result .= $this->messages->getStyledMessage(__('Administrators') . ' ' . __('not exists'), 'ubim-contact-name');
  397. }
  398. $result .= wf_tag('div', true);
  399. return ($result);
  400. }
  401. /**
  402. * Return messenger main window grid
  403. *
  404. * @param string $threadContent
  405. *
  406. * @return string
  407. */
  408. public function renderMainWindow($threadContent = '') {
  409. $contactList = '';
  410. $contactList .= $this->renderZenContacts();
  411. if (empty($threadContent)) {
  412. if (ubRouting::checkGet(self::ROUTE_REFRESH)) {
  413. $threadContent .= $this->messages->getStyledMessage(__('Select a chat to start a conversation'), 'info');
  414. $threadContent .= wf_delimiter(1);
  415. $threadContent .= wf_tag('center') . wf_img('skins/unicornchat.png') . wf_tag('center', true);
  416. }
  417. }
  418. $threadContainer = wf_tag('div', false, 'ubim-thread', 'id="threadContainer"');
  419. $threadContainer .= $threadContent;
  420. $threadContainer .= wf_tag('div', true);
  421. $result = '';
  422. $result .= wf_tag('div', false, 'ubim-big');
  423. $result .= wf_tag('div', false, 'ubim-left');
  424. $result .= $contactList;
  425. $result .= wf_tag('div', true);
  426. $result .= wf_tag('div', false, 'ubim-right');
  427. $result .= $threadContainer;
  428. $result .= wf_tag('div', true);
  429. $result .= wf_tag('div', true);
  430. $result .= wf_CleanDiv();
  431. return ($result);
  432. }
  433. /**
  434. * Return conversation form for some thread
  435. *
  436. * @param string $to - thread username
  437. *
  438. * @return string
  439. */
  440. public function renderConversationForm($to) {
  441. $result = '';
  442. if (isset($this->allAdmins[$to])) {
  443. $this->currentThread = $to;
  444. $sendButtonTitle = '';
  445. if (!@$this->altCfg[self::OPT_NOAJAXSEND]) {
  446. $sendButtonTitle = 'title="' . __('Ctrl-Enter') . '"';
  447. }
  448. $inputs = wf_HiddenInput(self::PROUTE_MSG_TO, $to);
  449. $inputs .= wf_tag('textarea', false, 'ubim-input-message', 'id="ubim-chat-box" name="' . self::PROUTE_MSG_TEXT . '" placeholder="' . __('Write message') . '..." required autofocus');
  450. $inputs .= wf_tag('textarea', true);
  451. $inputs .= wf_tag('button', false, 'ubim-send-button', 'type="submit" ' . $sendButtonTitle . ' ');
  452. $inputs .= __('Send');
  453. $inputs .= wf_tag('button', true);
  454. $result .= wf_Form('', 'POST', $inputs, 'ubim-chat-form', '', 'ubim-converstation');
  455. $result .= wf_tag('span', false, '', 'id="response"') . wf_tag('span', true);
  456. //preventing page refresh on sending message
  457. if (!@$this->altCfg[self::OPT_NOAJAXSEND]) {
  458. $result .= wf_tag('script');
  459. $result .= "
  460. //Ctrl-Enter handling
  461. $('form').keydown(function(event) {
  462. if (event.ctrlKey && event.keyCode === 13) {
  463. $(this).trigger('submit');
  464. }
  465. })
  466. //smooth messages sending
  467. $(document).ready(function() {
  468. $('#ubim-converstation').on('submit', function(e) {
  469. e.preventDefault();
  470. $.ajax({
  471. type: 'POST',
  472. url: '" . self::URL_ME . '&' . self::ROUTE_THREAD . '=' . $to . "',
  473. data: $(this).serialize(),
  474. success: function(response) {
  475. $('#ubim-chat-box').val('');
  476. $('#ubim-chat-box').focus();
  477. },
  478. });
  479. });
  480. });
  481. ";
  482. $result .= wf_tag('script', true);
  483. }
  484. } else {
  485. $result .= $this->messages->getStyledMessage(__('Administrator') . ' {' . $to . '} ' . __('not exists'), 'error');
  486. log_register('UBIM FAIL THREAD {' . $to . '} NOT_EXISTS');
  487. }
  488. return ($result);
  489. }
  490. /**
  491. * Returns all messages array from thread with some specified admin
  492. *
  493. * @param string $threadUser
  494. *
  495. * @return array
  496. */
  497. protected function getThreadMessages($threadUser) {
  498. $threadUser = ubRouting::filters($threadUser, 'mres');
  499. $result = array();
  500. $cachedData = $this->cache->get(self::KEY_MSG_THREADS . $this->myLogin . '_' . $threadUser, $this->cachingTimeout);
  501. if (empty($cachedData) and !is_array($cachedData)) {
  502. $this->messagesDb->whereRaw("(`to`='" . $this->myLogin . "' AND `from`='" . $threadUser . "') OR (`to`='" . $threadUser . "' AND `from`='" . $this->myLogin . "')");
  503. $this->messagesDb->orderBy('id', 'DESC');
  504. $result = $this->messagesDb->getAll();
  505. $this->cache->set(self::KEY_MSG_THREADS . $this->myLogin . '_' . $threadUser, $result, $this->cachingTimeout);
  506. } else {
  507. $result = $cachedData;
  508. }
  509. return ($result);
  510. }
  511. /**
  512. * Shows thread for me with some user
  513. *
  514. * @param string $threadUser user to show thread
  515. *
  516. * @return string
  517. */
  518. public function renderThreadContent($threadUser) {
  519. $threadUser = ubRouting::filters($threadUser, 'mres');
  520. $adminName = (isset($this->allEmployeeNames[$threadUser])) ? $this->allEmployeeNames[$threadUser] : $threadUser;
  521. $curDate = curdate();
  522. $result = $this->messages->getStyledMessage(__('No conversations with') . ' ' . $adminName . ' ' . __('yet'), 'info');
  523. $unreadCount = 0;
  524. $alldata = $this->getThreadMessages($threadUser);
  525. if (!empty($alldata)) {
  526. $result = '';
  527. $result .= wf_tag('div', false, 'ubim-chat-container');
  528. foreach ($alldata as $io => $each) {
  529. //incrementing unread counter to me
  530. if (($each['read'] == 0) and ($each['to'] == $this->myLogin)) {
  531. $unreadCount++;
  532. }
  533. $statusIcon = ($each['read']) ? wf_img("skins/message_read.png") : wf_img("skins/message_unread.png");
  534. $fromName = (isset($this->allEmployeeNames[$each['from']])) ? $this->allEmployeeNames[$each['from']] : $each['from'];
  535. $messageTimestamp = strtotime($each['date']);
  536. $messageDate = date("Y-m-d", $messageTimestamp);
  537. if ($messageDate != $curDate) {
  538. $timeLabel = $each['date'];
  539. } else {
  540. $timeLabel = date("H:i:s", $messageTimestamp);
  541. }
  542. $messageText = nl2br($each['text']);
  543. if (@!$this->altCfg[self::OPT_NOLINKIFY]) {
  544. $messageText = $this->linkify($messageText);
  545. }
  546. //rendering message container
  547. $messageClass = 'ubim-message';
  548. if ($each['from'] == $this->myLogin) {
  549. $messageClass .= ' ubim-from-user ';
  550. } else {
  551. $messageClass .= ' ubim-from-other ';
  552. }
  553. $result .= wf_tag('div', false, $messageClass);
  554. // $result .= $fromName;
  555. $result .= gravatar_ShowAdminAvatar($each['from'], '64', 'ubim-chat-avatar', $fromName);
  556. $result .= wf_tag('div', false, 'ubim-message-bubble');
  557. $result .= wf_tag('div', false, 'ubim-message-author');
  558. $result .= $fromName;
  559. $result .= wf_tag('div', true);
  560. $result .= wf_tag('div', false, 'ubim-message-content');
  561. $result .= $messageText;
  562. $result .= wf_tag('div', true);
  563. $result .= wf_tag('span', false, 'ubim-timestamp');
  564. $result .= $timeLabel;
  565. $result .= ' ' . $statusIcon;
  566. $result .= wf_tag('span');
  567. $result .= wf_tag('div', true);
  568. $result .= wf_tag('div', true);
  569. }
  570. //mark all unread messages as read now
  571. if ($unreadCount > 0) {
  572. $this->threadMarkAsRead($threadUser);
  573. }
  574. $result .= wf_tag('div', true);
  575. }
  576. return ($result);
  577. }
  578. /**
  579. * Checks how many unread messages we have?
  580. *
  581. * @return int
  582. */
  583. public function checkForUnreadMessages() {
  584. $result = 0;
  585. $this->messagesDb->where('to', '=', $this->myLogin);
  586. $this->messagesDb->where('read', '=', '0');
  587. $result = $this->messagesDb->getFieldsCount();
  588. return ($result);
  589. }
  590. /**
  591. * Returns array of "active" administrators
  592. *
  593. * @return array
  594. */
  595. protected function getActiveAdmins() {
  596. $result = array();
  597. $cachedData = $this->cache->get(self::KEY_ADMS_ONLINE, $this->cachingTimeout);
  598. if (empty($cachedData) and !is_array($cachedData)) {
  599. $query = "SELECT DISTINCT `admin` from `weblogs` WHERE `date` > DATE_SUB(NOW(), INTERVAL " . $this->onlineTimeout . " MINUTE);";
  600. $all = simple_queryall($query);
  601. if (!empty($all)) {
  602. foreach ($all as $io => $each) {
  603. $result[$each['admin']] = $each['admin'];
  604. }
  605. }
  606. $this->cache->set(self::KEY_ADMS_ONLINE, $result, $this->cachingTimeout);
  607. } else {
  608. $result = $cachedData;
  609. }
  610. return ($result);
  611. }
  612. /**
  613. * Turn all URLs in clickable links.
  614. *
  615. * @param string $text
  616. *
  617. * @return string
  618. */
  619. protected function linkify($text) {
  620. $urlPattern = '/\b(https?:\/\/[^\s<>"\'\)]+)/i';
  621. $result = preg_replace_callback($urlPattern, function ($matches) {
  622. $url = $matches[0];
  623. if (preg_match('/\.(jpg|png|gif|webp|jpeg)$/i', $url)) {
  624. return wf_link($url, wf_img_sized(htmlspecialchars($url), '', '100%'), false, '', 'target="_blank"');
  625. }
  626. return wf_Link($url, htmlspecialchars($url), false, '', 'target="_blank"');
  627. }, $text);
  628. return ($result);
  629. }
  630. /**
  631. * Returns primary messenger window title
  632. *
  633. * @return string
  634. */
  635. public function renderMainWinTitle() {
  636. $result = '';
  637. $avaLabel = gravatar_ShowAdminAvatar(whoami(), '16', 'ubim-avacontrol', __('Avatar control'));
  638. $returnUrl = self::URL_ME;
  639. if ($this->currentThread) {
  640. $returnUrl .= '&' . self::ROUTE_THREAD . '=' . $this->currentThread;
  641. } else {
  642. $returnUrl .= '&' . self::ROUTE_REFRESH . '=true';
  643. }
  644. $baseTitle = '';
  645. $baseTitle .= wf_Link(self::URL_AVATAR_CONTROL . '&back=' . base64_encode($returnUrl), $avaLabel, false);
  646. $baseTitle .= ' ' . __('Instant messaging service');
  647. if ($this->currentThread) {
  648. $baseTitle .= ': ' . @$this->allEmployeeNames[$this->currentThread];
  649. }
  650. $result .= $baseTitle;
  651. return ($result);
  652. }
  653. }