api.taskbar.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. <?php
  2. /**
  3. * Taskbar loading and rendering class
  4. */
  5. class UbillingTaskbar {
  6. /**
  7. * Contains system alter config as key=>value
  8. *
  9. * @var array
  10. */
  11. protected $altCfg = array();
  12. /**
  13. * Contains system billing config as key=>value
  14. *
  15. * @var array
  16. */
  17. protected $billCfg = array();
  18. /**
  19. * Message helper object placeholder
  20. *
  21. * @var object
  22. */
  23. protected $messages = '';
  24. /**
  25. * Contains currently loaded categories as dir=>name
  26. *
  27. * @var array
  28. */
  29. protected $categories = array();
  30. /**
  31. * Contains available icon sizes as size=>name
  32. *
  33. * @var array
  34. */
  35. protected $iconSizes = array();
  36. /**
  37. * Contains current run alerts if available
  38. *
  39. * @var string
  40. */
  41. protected $currentAlerts = '';
  42. /**
  43. * Contains full list of loaded taskbar elements
  44. *
  45. * @var array
  46. */
  47. protected $loadedElements = array();
  48. /**
  49. * Taskbar elements rendered content
  50. *
  51. * @var string
  52. */
  53. protected $taskbarContent = '';
  54. /**
  55. * Contains current instance administrator login
  56. *
  57. * @var string
  58. */
  59. protected $myLogin = '';
  60. /**
  61. * Contains default taskbar elements path
  62. */
  63. const BASE_PATH = 'config/taskbar.d/';
  64. /**
  65. * Contains path to widgets code
  66. */
  67. const WIDGETS_CODEPATH = 'config/taskbar.d/widgets/';
  68. /**
  69. * Contains default module URL
  70. */
  71. const URL_ME = '?module=taskbar';
  72. /**
  73. * Some other predefined stuff
  74. */
  75. const ROUTE_WS = 'welcomescreen';
  76. const ROUTE_DISABLE_WS = 'disablewelcomescreen';
  77. /**
  78. * Creates new taskbar instance
  79. */
  80. public function __construct() {
  81. $this->loadConfigs();
  82. $this->initMessages();
  83. $this->setCategories();
  84. $this->setIconSizes();
  85. }
  86. /**
  87. * Loads system alter and billing configs into protected properties
  88. *
  89. * @global object $ubillingConfig
  90. *
  91. * @return void
  92. */
  93. protected function loadConfigs() {
  94. global $ubillingConfig;
  95. $this->altCfg = $ubillingConfig->getAlter();
  96. $this->billCfg = $ubillingConfig->getBilling();
  97. }
  98. /**
  99. * Inits system message helper object
  100. *
  101. * @return void
  102. */
  103. protected function initMessages() {
  104. $this->messages = new UbillingMessageHelper();
  105. }
  106. /**
  107. * Sets available taskbar element categories
  108. *
  109. * @return void
  110. */
  111. protected function setCategories() {
  112. $this->categories['widgets'] = '';
  113. $this->categories['iusers'] = __('Subscribers');
  114. $this->categories['instruments'] = __('Instruments');
  115. $this->categories['equipment'] = __('Equipment');
  116. $this->categories['maps'] = __('Maps');
  117. $this->categories['reports'] = __('Reports');
  118. $this->categories['directories'] = __('Directories');
  119. $this->categories['system'] = __('System');
  120. }
  121. /**
  122. * Sets available icon sizes
  123. *
  124. * @return void
  125. */
  126. protected function setIconSizes() {
  127. $this->iconSizes = array(
  128. '128' => __('Normal icons'),
  129. '96' => __('Lesser'),
  130. '64' => __('Macro'),
  131. '48' => __('Micro'),
  132. '32' => __('Nano')
  133. );
  134. }
  135. /**
  136. * Sets current administrators login into protected prof for further usage
  137. *
  138. * @return void
  139. */
  140. protected function setLogin() {
  141. $this->myLogin = whoami();
  142. }
  143. /**
  144. * Renders taskbar icon element
  145. *
  146. * @param string $url
  147. * @param string $name
  148. * @param string $icon
  149. *
  150. * @return string
  151. */
  152. protected function renderIconElement($url, $elementName, $elementIcon) {
  153. $result = '';
  154. $name = __($elementName);
  155. $iconPath = CUR_SKIN_PATH . 'taskbar/';
  156. $icon = $iconPath . $elementIcon;
  157. $elemQsId = 'ubtbelcont_' . $name . '_' . $elementName;
  158. if (!file_exists($icon)) {
  159. $icon = 'skins/taskbar/' . $elementIcon;
  160. }
  161. if (isset($_COOKIE['tb_iconsize'])) {
  162. //is icon customize enabled?
  163. if ($this->altCfg['TB_ICONCUSTOMSIZE']) {
  164. $iconsize = vf($_COOKIE['tb_iconsize'], 3);
  165. } else {
  166. $iconsize = $this->billCfg['TASKBAR_ICON_SIZE'];
  167. }
  168. } else {
  169. $iconsize = $this->billCfg['TASKBAR_ICON_SIZE'];
  170. }
  171. if ($this->altCfg['TB_LABELED']) {
  172. if ($iconsize > 63) {
  173. $result = '<div class="dashtask" id="' . $elemQsId . '" style="height:' . ($iconsize + 30) . 'px; width:' . ($iconsize + 30) . 'px;"> <a href="' . $url . '"><img src="' . $icon . '" border="0" width="' . $iconsize . '" height="' . $iconsize . '" alt="' . $name . '" title="' . $name . '"></a> <br><br>' . $name . ' </div>';
  174. } else {
  175. $result = '<div class="dashtask" id="' . $elemQsId . '" style="height:' . ($iconsize + 10) . 'px; width:' . ($iconsize + 10) . 'px;"> <a href="' . $url . '"><img src="' . $icon . '" border="0" width="' . $iconsize . '" height="' . $iconsize . '" alt="' . $name . '" title="' . $name . '"></a></div>';
  176. }
  177. } else {
  178. $result = '<a href="' . $url . '"><img src="' . $icon . '" border="0" width="' . $iconsize . '" height="' . $iconsize . '" alt="' . $name . '" title="' . $name . '"></a><img src="skins/taskbar/spacer.gif"> ';
  179. }
  180. return ($result);
  181. }
  182. /**
  183. * Checks element required rights, options and returns element content
  184. *
  185. * @param array $elementData
  186. *
  187. * @return string
  188. */
  189. protected function buildElement($elementData) {
  190. $result = '';
  191. $elementId = (isset($elementData['ID'])) ? $elementData['ID'] : '';
  192. $elementType = (!empty($elementData['TYPE'])) ? $elementData['TYPE'] : '';
  193. //basic taskbar icon
  194. if ($elementType == 'icon') {
  195. $accesCheck = false;
  196. $elementRight = (!empty($elementData['NEED_RIGHT'])) ? $elementData['NEED_RIGHT'] : '';
  197. if (!empty($elementRight)) {
  198. if (cfr($elementRight)) {
  199. $accesCheck = true;
  200. }
  201. } else {
  202. $accesCheck = true;
  203. }
  204. //basic rights check
  205. if ($accesCheck) {
  206. $elementOption = (!empty($elementData['NEED_OPTION'])) ? $elementData['NEED_OPTION'] : '';
  207. $optionCheck = false;
  208. if (!empty($elementOption)) {
  209. if (isset($this->altCfg[$elementOption])) {
  210. if ($this->altCfg[$elementOption]) {
  211. $optionCheck = true;
  212. }
  213. } else {
  214. if (!isset($elementData['UNIMPORTANT'])) {
  215. $this->currentAlerts .= $this->messages->getStyledMessage(__('Missed config option') . ': ' . $elementOption . ' ' . __('required by') . ' ' . $elementId, 'error');
  216. }
  217. }
  218. } else {
  219. $optionCheck = true;
  220. }
  221. if ($optionCheck) {
  222. $elementName = (!empty($elementData['NAME'])) ? $elementData['NAME'] : '';
  223. $elementUrl = (!empty($elementData['URL'])) ? $elementData['URL'] : '';
  224. $elementIcon = (!empty($elementData['ICON'])) ? $elementData['ICON'] : '';
  225. $result .= $this->renderIconElement($elementUrl, $elementName, $elementIcon);
  226. }
  227. }
  228. }
  229. //widgets loading
  230. if ($elementType == 'widget') {
  231. $accesCheck = false;
  232. $elementRight = (!empty($elementData['NEED_RIGHT'])) ? $elementData['NEED_RIGHT'] : '';
  233. if (!empty($elementRight)) {
  234. if (cfr($elementRight)) {
  235. $accesCheck = true;
  236. }
  237. } else {
  238. $accesCheck = true;
  239. }
  240. //basic rights check
  241. if ($accesCheck) {
  242. $elementOption = (!empty($elementData['NEED_OPTION'])) ? $elementData['NEED_OPTION'] : '';
  243. $optionCheck = false;
  244. if (!empty($elementOption)) {
  245. if (isset($this->altCfg[$elementOption])) {
  246. if ($this->altCfg[$elementOption]) {
  247. $optionCheck = true;
  248. }
  249. } else {
  250. if (!isset($elementData['UNIMPORTANT'])) {
  251. $this->currentAlerts .= $this->messages->getStyledMessage(__('Missed config option') . ': ' . $elementOption . ' ' . __('required by') . ' ' . $elementId, 'error');
  252. }
  253. }
  254. } else {
  255. $optionCheck = true;
  256. }
  257. /**
  258. * It's gonna take a lot to drag me away from you
  259. * There's nothing that a hundred men or more could ever do
  260. * I bless the rains down in Africa
  261. * Gonna take some time to do the things we never had
  262. */
  263. if ($optionCheck) {
  264. //run widget code
  265. if (isset($elementData['CODEFILE'])) {
  266. if (file_exists(self::WIDGETS_CODEPATH . $elementData['CODEFILE'])) {
  267. require_once(self::WIDGETS_CODEPATH . $elementData['CODEFILE']);
  268. if (class_exists($elementData['ID'])) {
  269. $widget = new $elementData['ID']();
  270. $result .= $widget->render();
  271. } else {
  272. $this->currentAlerts .= $this->messages->getStyledMessage(__('Widget class not exists') . ': ' . $elementData['ID'], 'error');
  273. }
  274. } else {
  275. $this->currentAlerts .= $this->messages->getStyledMessage(__('File not exist') . ': ' . self::WIDGETS_CODEPATH . $elementData['CODEFILE'], 'warning');
  276. }
  277. } else {
  278. $this->currentAlerts .= $this->messages->getStyledMessage(__('Wrong element format') . ': ' . $elementData['ID'], 'warning');
  279. }
  280. }
  281. }
  282. }
  283. return ($result);
  284. }
  285. /**
  286. * Loads and returns category taskbar elements
  287. *
  288. * @param string $category
  289. *
  290. * @return string
  291. */
  292. protected function loadCategoryElements($category) {
  293. $result = '';
  294. $elementsPath = self::BASE_PATH . $category . '/';
  295. $allElements = rcms_scandir($elementsPath, '*.ini');
  296. $categoryContent = '';
  297. if (!empty($allElements)) {
  298. $categoryName = (isset($this->categories[$category])) ? $this->categories[$category] : '';
  299. foreach ($allElements as $io => $eachfilename) {
  300. $elementData = parse_ini_file($elementsPath . $eachfilename);
  301. if ((isset($elementData['TYPE'])) and (isset($elementData['ID']))) {
  302. if (!isset($this->loadedElements[$elementData['ID']])) {
  303. $this->loadedElements[$elementData['ID']] = $elementData;
  304. $categoryContent .= $this->buildElement($elementData);
  305. } else {
  306. $this->currentAlerts .= $this->messages->getStyledMessage(__('Duplicate element ID') . ': ' . $elementData['ID'] . ' -> ' . $eachfilename, 'warning');
  307. }
  308. } else {
  309. $this->currentAlerts .= $this->messages->getStyledMessage(__('Wrong element format') . ': ' . $eachfilename, 'warning');
  310. }
  311. }
  312. //injecting optional ReportMaster reports here
  313. if ($category == 'reports') {
  314. if (@$this->altCfg['TB_REPORTMASTER']) {
  315. $reportMaster = new ReportMaster();
  316. $availableReports = $reportMaster->getTaskBarReports();
  317. if (!empty($availableReports)) {
  318. foreach ($availableReports as $eachReportId => $eachReportElement) {
  319. $categoryContent .= $this->buildElement($eachReportElement);
  320. }
  321. }
  322. }
  323. }
  324. if (!empty($categoryContent)) {
  325. $result .= wf_tag('p') . wf_tag('h3') . wf_tag('u') . $categoryName . wf_tag('u', true) . wf_tag('h3', true) . wf_tag('p', true);
  326. $result .= wf_tag('div', false, 'dashboard');
  327. $result .= $categoryContent;
  328. $result .= wf_tag('div', true);
  329. $result .= wf_CleanDiv();
  330. }
  331. }
  332. return ($result);
  333. }
  334. /**
  335. * Loads and try to render all of available taskbar categories
  336. *
  337. * @return string
  338. */
  339. protected function loadAllCategories() {
  340. $result = '';
  341. if (!empty($this->categories)) {
  342. foreach ($this->categories as $category => $categoryname) {
  343. $result .= $this->loadCategoryElements($category);
  344. }
  345. }
  346. return ($result);
  347. }
  348. /**
  349. * Returns icon resize form if enabled
  350. *
  351. * @return string
  352. */
  353. protected function renderResizeForm() {
  354. $result = '';
  355. if ($this->altCfg['TB_ICONCUSTOMSIZE']) {
  356. if (isset($_COOKIE['tb_iconsize'])) {
  357. $currentsize = vf($_COOKIE['tb_iconsize'], 3);
  358. } else {
  359. $currentsize = $this->billCfg['TASKBAR_ICON_SIZE'];
  360. }
  361. $resizeinputs = wf_SelectorAC('iconsize', $this->iconSizes, '', $currentsize, false);
  362. $result .= wf_tag('br');
  363. $result .= wf_Form('', 'POST', $resizeinputs);
  364. }
  365. return ($result);
  366. }
  367. /**
  368. * Catches and applies icon resize event
  369. *
  370. * @return void
  371. */
  372. protected function catchIconsizeChange() {
  373. if (isset($_POST['iconsize'])) {
  374. $iconsize = vf($_POST['iconsize'], 3);
  375. setcookie("tb_iconsize", $iconsize, time() + 2592000);
  376. rcms_redirect(self::URL_ME);
  377. }
  378. }
  379. /**
  380. * Returs available sticky notes if enabled
  381. *
  382. * @return string
  383. */
  384. protected function loadStickyNotes() {
  385. $result = '';
  386. if (isset($this->altCfg['STICKY_NOTES_ENABLED'])) {
  387. if ($this->altCfg['STICKY_NOTES_ENABLED']) {
  388. $stickyNotes = new StickyNotes(true);
  389. $result = $stickyNotes->renderTaskbarNotify();
  390. }
  391. }
  392. return ($result);
  393. }
  394. /**
  395. * Checks for default password usage, etc.
  396. *
  397. * @return void
  398. */
  399. protected function checkSecurity() {
  400. if (@!$this->altCfg['TB_DISABLE_SECURITY_CHECK']) {
  401. global $system;
  402. $controlLogin = 'admin';
  403. $badPasswords = file_get_contents(DATA_PATH . 'shitpass.dat');
  404. $badPasswords = trim($badPasswords);
  405. $badPasswords = explodeRows($badPasswords);
  406. $defaultPassOffset = 0;
  407. if (isset($_COOKIE['ubilling_user'])) {
  408. if (!file_exists('DEMO_MODE') and !file_exists('exports/FIRST_INSTALL')) {
  409. //am i using default account?
  410. if ($_COOKIE['ubilling_user'] == $controlLogin . ':' . $badPasswords[$defaultPassOffset]) {
  411. $notice = __('You are using the default login and password') . '. ' . __('Dont do this') . '.';
  412. // ugly hack to prevent elements autofocusing
  413. $label = wf_TextInput('dontfocusonlinks', '', '', false, '', '', '', '', 'style="width: 0; height: 0; top: -100px; position: absolute;"');
  414. $label .= wf_tag('div', false, '', 'style="min-width:550px;"') . $this->messages->getStyledMessage($notice, 'error') . wf_tag('div', true);
  415. $label .= wf_tag('br');
  416. $imagesPath = 'skins/changepass/';
  417. $allImgs = rcms_scandir($imagesPath);
  418. if (!empty($allImgs)) {
  419. $imageRnd = array_rand($allImgs);
  420. $randomImage = $allImgs[$imageRnd];
  421. $label .= wf_tag('center') . wf_img_sized($imagesPath . $randomImage, '', '', '300') . wf_tag('center' . true);
  422. $label .= wf_delimiter(1);
  423. }
  424. $label .= wf_Link('?module=adminreg&editadministrator=admin', __('Change admin user password'), true, 'confirmagree');
  425. $this->currentAlerts .= wf_modalOpenedAuto(__('Oh no') . '!' . ' ' . __('Danger') . '!', $label);
  426. } else {
  427. //fast check for few shitty passwords
  428. if (file_exists(USERS_PATH . $controlLogin)) {
  429. $adminData = $system->getUserData($controlLogin);
  430. if (!empty($adminData)) {
  431. $adminHash = trim($adminData['password']);
  432. foreach ($badPasswords as $passIdx => $eachHash) {
  433. if (!empty($eachHash)) {
  434. $eachHash = trim($eachHash);
  435. if (strpos($adminHash, $eachHash) !== false) {
  436. $this->currentAlerts .= $this->messages->getStyledMessage(__('For administrator') . ' «' . $controlLogin . '» ' . __('a very fucked up password is used') . '. ' . __('Dont do this') . '.', 'error');
  437. }
  438. }
  439. }
  440. }
  441. }
  442. }
  443. }
  444. }
  445. }
  446. }
  447. /**
  448. * Renders some welcome screen for newly installed Ubilling
  449. *
  450. * @return void
  451. */
  452. protected function renderWelcome() {
  453. if (@!$this->altCfg['TB_DISABLE_WELCOME_SCREEN']) {
  454. $newInstallFlag = 'exports/FIRST_INSTALL';
  455. if (!ubRouting::checkGet(self::ROUTE_DISABLE_WS)) {
  456. if (file_exists($newInstallFlag) or ubRouting::checkGet(self::ROUTE_WS)) {
  457. $urlsList = array(
  458. 'https://ubilling.net.ua/rds/defense/' => __('Donate to Armed Forces of Ukraine'),
  459. 'https://wiki.ubilling.net.ua/' => __('Read documentation'),
  460. '?module=adminreg&editadministrator=admin' => __('Change admin user password'),
  461. 'https://t.me/ubilling' => __('Join our community chat'),
  462. );
  463. //render content
  464. $welcomeLabel = '<!--ugly hack to prevent elements autofocusing --> <input type="text" name="dontfocusonlinks" style="width: 0; height: 0; top: -100px; position: absolute;"/>';
  465. $welcomeLabel .= wf_tag('h2') . __('Welcome to your new billing system') . '!' . wf_tag('h2', true);
  466. $welcomeLabel .= __('On behalf of the development team and everyone involved in the project, we would like to thank you for choosing Ubilling.');
  467. $welcomeLabel .= wf_tag('br');
  468. $welcomeLabel .= __('We hope you enjoy using it as much as we enjoyed working on it.');
  469. $welcomeLabel .= wf_delimiter(1);
  470. $welcomeLabel .= __('Here`s what you should do first') . ':';
  471. if (!empty($urlsList)) {
  472. $welcomeLabel .= wf_tag('ul');
  473. foreach ($urlsList as $eachUrl => $eachLabel) {
  474. $welcomeLabel .= wf_tag('li') . wf_Link($eachUrl, $eachLabel, false, '', 'target="_BLANK"') . wf_tag('li', true);
  475. }
  476. $welcomeLabel .= wf_tag('ul', true);
  477. }
  478. if (file_exists($newInstallFlag)) {
  479. $welcomeLabel .= wf_Link(self::URL_ME . '&' . self::ROUTE_DISABLE_WS . '=true', wf_img('skins/hide16.png') . ' ' . __('Dont show me this anymore'), true, 'ubButton');
  480. }
  481. $this->currentAlerts .= wf_modalOpenedAuto(__('Welcome to Ubilling') . '!', $welcomeLabel);
  482. }
  483. } else {
  484. @unlink($newInstallFlag);
  485. if (file_exists($newInstallFlag)) {
  486. log_register('WELCOME DISABLE FAIL');
  487. }
  488. ubRouting::nav(self::URL_ME);
  489. }
  490. }
  491. }
  492. /**
  493. * Renders administrators announcements if some unread is present/sets read some of them
  494. *
  495. * @return string
  496. */
  497. protected function loadAnnouncements() {
  498. $result = '';
  499. if (isset($this->altCfg['ANNOUNCEMENTS'])) {
  500. if ($this->altCfg['ANNOUNCEMENTS']) {
  501. $admAnnouncements = new AdminAnnouncements();
  502. if (wf_CheckGet(array('setacquainted'))) {
  503. $admAnnouncements->setAcquainted($_GET['setacquainted']);
  504. rcms_redirect(self::URL_ME);
  505. }
  506. $result .= $admAnnouncements->showAnnouncements();
  507. }
  508. }
  509. return ($result);
  510. }
  511. /**
  512. * Renders administrators voting poll form
  513. *
  514. * @return string
  515. */
  516. protected function loadPollVoteAdmin() {
  517. $result = '';
  518. if (isset($this->altCfg['POLLS_ENABLED'])) {
  519. if ($this->altCfg['POLLS_ENABLED']) {
  520. $poll = new PollVoteAdmin();
  521. if (wf_CheckPost(array('vote', 'poll_id'))) {
  522. $poll->createAdminVoteOnDB(vf($_POST['vote'], 3), vf($_POST['poll_id'], 3));
  523. }
  524. $result .= $poll->renderVotingForm();
  525. }
  526. }
  527. return ($result);
  528. }
  529. /**
  530. * Returns touch devices hotfix for draggable and other JQuery UI things
  531. *
  532. * @return string
  533. */
  534. protected function loadTouchFix() {
  535. $result = '';
  536. if (@$this->altCfg['TOUCH_FIX']) {
  537. $result .= '<!-- jQuery UI Touch Punch -->';
  538. $result .= wf_tag('script', false, '', 'type="text/javascript" language="javascript" src="modules/jsc/jquery.ui.touch-punch.min.js"');
  539. $result .= wf_tag('script', true);
  540. }
  541. return ($result);
  542. }
  543. /**
  544. * Renders the search form and frontend controller for taskbar elements
  545. *
  546. * @return string
  547. */
  548. public function renderQuickSearchForm() {
  549. global $ubillingConfig;
  550. $result = '';
  551. if (@$this->altCfg['TB_QUICKSEARCH_ENABLED']) {
  552. $result .= wf_tag('div', false, 'tbqsearchform');
  553. $result .= wf_TextInput('tbquicksearch', ' ' . '', '', false, 20, '', '', 'tbquicksearch', 'placeholder="' . __('Quick search') . '...' . '"');
  554. $result .= wf_tag('button', false, 'clear-btn', 'type="button" aria-label="Clear search"') . '&times;' . wf_tag('button', true);
  555. $result .= wf_tag('div', true);
  556. $result .= wf_tag('script');
  557. $result .= "
  558. document.getElementById('tbquicksearch').addEventListener('input', function () {
  559. const searchValue = this.value.toLowerCase();
  560. const tbElements = document.querySelectorAll('[id^=\"ubtbelcont_\"]');
  561. const statusContainer = document.getElementById('ubtbqsstatus');
  562. let visibleCount = 0;
  563. tbElements.forEach(tbElement => {
  564. const idText = tbElement.id.toLowerCase();
  565. if (searchValue === '' || idText.includes(searchValue)) {
  566. tbElement.classList.remove('hiddentbelem');
  567. tbElement.style.display = 'block';
  568. requestAnimationFrame(() => tbElement.style.opacity = '1');
  569. visibleCount++;
  570. } else {
  571. tbElement.classList.add('hiddentbelem');
  572. setTimeout(() => {
  573. if (tbElement.classList.contains('hiddentbelem')) {
  574. tbElement.style.display = 'none';
  575. }
  576. }, 300);
  577. }
  578. });
  579. //no elements found
  580. if (visibleCount === 0) {
  581. statusContainer.textContent = '" . __('Nothing found') . "';
  582. } else {
  583. statusContainer.textContent = '';
  584. }
  585. });
  586. document.addEventListener('DOMContentLoaded', () => {
  587. const searchInput = document.getElementById('tbquicksearch');
  588. const clearButton = document.querySelector('.clear-btn');
  589. searchInput.addEventListener('input', () => {
  590. if (searchInput.value.trim() !== '') {
  591. clearButton.style.display = 'flex';
  592. } else {
  593. clearButton.style.display = 'none';
  594. }
  595. });
  596. clearButton.addEventListener('click', () => {
  597. searchInput.value = '';
  598. clearButton.style.display = 'none';
  599. searchInput.dispatchEvent(new Event('input'));
  600. searchInput.focus();
  601. });
  602. });
  603. ";
  604. $result .= wf_tag('script', true);
  605. $result .= wf_CleanDiv();
  606. }
  607. return ($result);
  608. }
  609. /**
  610. * Renders quick search form as modal dialog
  611. *
  612. * @return string
  613. */
  614. public function renderQuickSearchModal() {
  615. $result = '';
  616. if (@$this->altCfg['TB_QUICKSEARCH_ENABLED'] and !@$this->altCfg['TB_QUICKSEARCH_INLINE']) {
  617. $result .= ' ' . wf_modalAuto(web_icon_search(), __('Search'), $this->renderQuickSearchForm());
  618. }
  619. return ($result);
  620. }
  621. /**
  622. * Returns rendered taskbar elements and services content
  623. *
  624. * @return string
  625. */
  626. public function renderTaskbar() {
  627. $result = '';
  628. $this->checkSecurity();
  629. $this->renderWelcome();
  630. $this->catchIconsizeChange();
  631. $this->taskbarContent = $this->loadAllCategories();
  632. if (!empty($this->currentAlerts)) {
  633. $result .= $this->currentAlerts;
  634. }
  635. if (@$this->altCfg['TB_QUICKSEARCH_INLINE'] ) {
  636. $result .= $this->renderQuickSearchForm();
  637. }
  638. $result .= wf_AjaxContainer('ubtbqsstatus');
  639. $result .= $this->taskbarContent;
  640. $result .= $this->renderResizeForm();
  641. $result .= $this->loadStickyNotes();
  642. $result .= $this->loadAnnouncements();
  643. $result .= $this->loadPollVoteAdmin();
  644. $result .= $this->loadTouchFix();
  645. return ($result);
  646. }
  647. }
  648. /**
  649. * Basic taskbar widgets class.
  650. */
  651. class TaskbarWidget {
  652. /**
  653. * Creates new instance of taskbar widget
  654. */
  655. public function __construct() {
  656. }
  657. /**
  658. * Returns content in default taskbar dashtask coontainer
  659. *
  660. * @param string $content
  661. * @param string $options
  662. *
  663. * @return string
  664. */
  665. protected function widgetContainer($content, $options = '') {
  666. $result = wf_tag('div', false, 'dashtask', $options);
  667. $result .= $content;
  668. $result .= wf_tag('div', true);
  669. return ($result);
  670. }
  671. /**
  672. * Returns result that directly embeds into taskbar
  673. *
  674. * @return string
  675. */
  676. public function render() {
  677. $result = 'EMPTY_WIDGET';
  678. return ($result);
  679. }
  680. }