BxTasksTemplate.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. * @defgroup Tasks Tasks
  6. * @ingroup UnaModules
  7. *
  8. * @{
  9. */
  10. require_once('BxTasksMenuTimer.php');
  11. class BxTasksTemplate extends BxBaseModTextTemplate
  12. {
  13. public function __construct(&$oConfig, &$oDb)
  14. {
  15. $this->MODULE = 'bx_tasks';
  16. parent::__construct($oConfig, $oDb);
  17. }
  18. public function getJsCode($sType, $aParams = [], $mixedWrap = true)
  19. {
  20. $aParams = array_merge([
  21. 'aHtmlIds' => $this->_oConfig->getHtmlIds()
  22. ], $aParams);
  23. return parent::getJsCode($sType, $aParams, $mixedWrap);
  24. }
  25. public function getJsCodeTimer($sType, $aParams = [], $mixedWrap = true)
  26. {
  27. $aParams = array_merge([
  28. 'aHtmlIds' => $this->_oConfig->getHtmlIds()
  29. ], $aParams);
  30. if(is_array($mixedWrap))
  31. return parent::getJsCode($sType, $aParams, [
  32. 'wrap' => true,
  33. 'mask' => "{var} {object} = new {class}({params}); {object}.init({content_id}, {profile_id}, {started});",
  34. 'mask_markers' => $mixedWrap
  35. ]);
  36. else
  37. parent::getJsCode($sType, $aParams, $mixedWrap);
  38. }
  39. public function getBlockMenuBrowse()
  40. {
  41. $CNF = &$this->_oConfig->CNF;
  42. $iProfileId = bx_get_logged_profile_id();
  43. $sMenuUse = '';
  44. if(($oMenu = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_USE_TOOLS_SUBMENU'])) !== false)
  45. $sMenuUse = $oMenu->getCode();
  46. $sMenuManage = '';
  47. if(($oMenu = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_MANAGE_TOOLS_SUBMENU'])) !== false)
  48. $sMenuManage = $oMenu->getCode();
  49. $sMenuBrowse = '';
  50. if(($oMenu = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_BROWSE'])) !== false) {
  51. $oMenu->setProfileId($iProfileId);
  52. $sMenuBrowse = $oMenu->getCode();
  53. }
  54. return $this->parseHtmlByName('menu_browse.html', [
  55. 'menu_use' => $sMenuUse,
  56. 'bx_if:show_menu_manage' => [
  57. 'condition' => $sMenuManage != '',
  58. 'content' => [
  59. 'menu_manage' => $sMenuManage
  60. ]
  61. ],
  62. 'bx_if:show_menu_browse' => [
  63. 'condition' => $sMenuBrowse != '',
  64. 'content' => [
  65. 'menu_browse' => $sMenuBrowse
  66. ]
  67. ]
  68. ]);
  69. }
  70. /**
  71. * Use Gallery image for both because currently there is no Unit types with small thumbnails.
  72. */
  73. protected function getUnitThumbAndGallery ($aData)
  74. {
  75. list($sPhotoThumb, $sPhotoGallery) = parent::getUnitThumbAndGallery($aData);
  76. return array($sPhotoGallery, $sPhotoGallery);
  77. }
  78. public function entryText ($aData, $sTemplateName = 'entry-text.html')
  79. {
  80. $CNF = &$this->_oConfig->CNF;
  81. $iContentId = (int)$aData[$CNF['FIELD_ID']];
  82. $sResult = '';
  83. if(!$this->_oModule->isAllowEdit($iContentId)) {
  84. $aVars = $this->getTmplVarsText($aData);
  85. $sResult = $this->parseHtmlByName($sTemplateName, $aVars);
  86. }
  87. else
  88. $sResult = $this->getModule()->serviceEntityEdit($iContentId, $CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT_BODY']);
  89. return $sResult;
  90. }
  91. public function entryAssignments ($aProfiles)
  92. {
  93. $CNF = &$this->_oConfig->CNF;
  94. $aTmplVarsProfiles = [];
  95. foreach($aProfiles as $mixedProfile) {
  96. $bProfile = is_array($mixedProfile);
  97. $oProfile = BxDolProfile::getInstance($bProfile ? (int)$mixedProfile['id'] : (int)$mixedProfile);
  98. if(!$oProfile)
  99. continue;
  100. $aUnitParams = ['template' => ['name' => 'unit', 'size' => 'thumb']];
  101. if($bProfile && is_array($mixedProfile['info']))
  102. $aUnitParams['template']['vars'] = $mixedProfile['info'];
  103. $aTmplVarsProfiles[] = [
  104. 'unit' => $oProfile->getUnit(0, $aUnitParams)
  105. ];
  106. }
  107. return $aTmplVarsProfiles ? $this->parseHtmlByName('entry-assignments.html', [
  108. 'bx_repeat:profiles' => $aTmplVarsProfiles
  109. ]) : MsgBox(_t('_sys_txt_empty'));
  110. }
  111. public function entryTimer ($iContentId, $iProfileId)
  112. {
  113. $this->addCss(['timer.css']);
  114. $this->addJs(['timer.js']);
  115. return $this->getTimer($iContentId, $iProfileId) . $this->getJsCodeTimer('timer', [], [
  116. 'content_id' => $iContentId,
  117. 'profile_id' => $iProfileId,
  118. 'started' => $this->_oDb->isTimerStarted($iContentId, $iProfileId),
  119. ]);
  120. }
  121. public function getBlockTimers ($iProfileId)
  122. {
  123. $CNF = &$this->_oConfig->CNF;
  124. $oModule = $this->getModule();
  125. $sJsObject = $this->_oConfig->getJsObject('timer');
  126. $aTimers = $this->_oDb->getTimers(['sample' => 'profile_id', 'profile_id' => $iProfileId]);
  127. if(!$aTimers || !is_array($aTimers))
  128. return MsgBox(_t('_Empty'));
  129. $oPermalinks = BxDolPermalinks::getInstance();
  130. $aTmplVarsSections = [];
  131. foreach($aTimers as $aTimer) {
  132. $aContentInfo = $this->_oDb->getContentInfoById($aTimer['content_id']);
  133. if(!$aContentInfo && !is_array($aContentInfo))
  134. continue;
  135. $sContextType = $sContextTitle = $sContextUrl = '';
  136. if(($iAllowViewTo = (int)$aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]) < 0 && ($oContext = BxDolProfile::getInstance(abs($iAllowViewTo))) !== false) {
  137. $sContextType = $oContext->getModule();
  138. $sContextTitle = $oContext->getDisplayName();
  139. $sContextUrl = $oContext->getUrl();
  140. }
  141. if(!isset($aTmplVarsSections[$sContextType]))
  142. $aTmplVarsSections[$sContextType] = [
  143. 'section_title' => $oModule->getModuleTitle($sContextType),
  144. 'bx_repeat:timers' => []
  145. ];
  146. $aTmplVarsSections[$sContextType]['bx_repeat:timers'][] = [
  147. 'bx_if:show_context' => [
  148. 'condition' => $sContextTitle && $sContextUrl,
  149. 'content' => [
  150. 'title' => $sContextTitle,
  151. 'url' => $sContextUrl
  152. ]
  153. ],
  154. 'content_title' => $aContentInfo[$CNF['FIELD_TITLE']],
  155. 'content_url' => bx_absolute_url($oPermalinks->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aContentInfo[$CNF['FIELD_ID']])),
  156. 'timer' => $this->getTimer($aTimer['content_id'], $iProfileId),
  157. 'js_code_timer' => $sJsObject . '.init(' . $aTimer['content_id'] . ', ' . $iProfileId . ', ' . ($aTimer['started'] != 0 ? 1 : 0) . ');'
  158. ];
  159. }
  160. $this->addCss(['timer.css']);
  161. $this->addJs(['timer.js']);
  162. return $this->parseHtmlByName('browse_timers.html', [
  163. 'js_code' => $this->getJsCode('timer', [
  164. 'bMulti' => true
  165. ]),
  166. 'bx_repeat:sections' => array_values($aTmplVarsSections)
  167. ]);
  168. }
  169. public function getTimer ($iContentId, $iProfileId)
  170. {
  171. $CNF = &$this->_oConfig->CNF;
  172. $sPrefix = str_replace('_', '-', $this->_oConfig->getName());
  173. $sJsObject = $this->_oConfig->getJsObject('timer');
  174. $aTimer = $this->_oDb->getTimers(['sample' => 'content_profile_ids', 'content_id' => $iContentId, 'profile_id' => $iProfileId]);
  175. $bTimer = $aTimer && is_array($aTimer);
  176. $bStarted = $bTimer && (int)$aTimer['started'] > 0;
  177. $iHours = $iMinutes = $iSeconds = 0;
  178. if($bTimer) {
  179. $iDuration = (int)$aTimer['duration'];
  180. if($bStarted)
  181. $iDuration += time() - (int)$aTimer['started'];
  182. list($iHours, $iMinutes, $iSeconds) = $this->_oConfig->timeI2A($iDuration, true);
  183. }
  184. $oActions = new BxTasksMenuTimer([
  185. 'object' => $sPrefix . '_timer',
  186. 'template' => 'menu_custom_hor.html',
  187. 'menu_id' => $this->_oConfig->getHtmlIds('timer_actions'),
  188. 'persistent' => 0
  189. ]);
  190. $oActions->setParams($iContentId, $iProfileId);
  191. return $this->parseHtmlByName('entry-timer.html', [
  192. 'html_id' => $this->_oConfig->getHtmlIds('timer') . $iContentId . '-' . $iProfileId,
  193. 'hours' => sprintf("%02d", $iHours),
  194. 'minutes' => sprintf("%02d", $iMinutes),
  195. 'seconds' => sprintf("%02d", $iSeconds),
  196. 'actions' => $oActions->getCode()
  197. ]);
  198. }
  199. public function getEntriesList($iContextId = 0, $aParams = [])
  200. {
  201. $CNF = &$this->_oConfig->CNF;
  202. $sJsObject = $this->_oConfig->getJsObject('tasks');
  203. $iLoggedId = bx_get_logged_profile_id();
  204. $oModule = $this->getModule();
  205. $bContext = !empty($iContextId);
  206. $bAllowAdd = $bContext && $oModule->isAllowAdd($iContextId);
  207. $aFilters = [];
  208. if(($sFilters = $_COOKIE[$CNF['COOKIE_SETTING_KEY']] ?? false))
  209. $aFilters = json_decode($sFilters, true);
  210. $iFilterSelected = $aParams['filter'] ?? ($aFilters[$iContextId] ?? 0);
  211. $sFilters = $this->_getEntriesFilters($iContextId, array_merge($aParams, ['filter_selected' => $iFilterSelected]));
  212. $this->addCssJs();
  213. $this->addJs([
  214. 'jquery-ui/jquery-ui.min.js',
  215. 'tasks.js',
  216. 'modules/base/general/js/|forms.js'
  217. ]);
  218. return $this->parseHtmlByName('browse_tasks.html', [
  219. 'object' => $sJsObject,
  220. 'context_id' => $iContextId,
  221. 'bx_if:show_filters' => [
  222. 'condition' => !empty($sFilters),
  223. 'content' => [
  224. 'object' => $sJsObject,
  225. 'context_id' => $iContextId,
  226. 'filters' => $sFilters
  227. ]
  228. ],
  229. 'bx_if:allow_add_list' => [
  230. 'condition' => $bAllowAdd,
  231. 'content' => [
  232. 'context_id' => $iContextId,
  233. 'object' => $sJsObject,
  234. ]
  235. ],
  236. 'bx_if:allow_manage_settings' => [
  237. 'condition' => $bContext,
  238. 'content' => [
  239. 'context_id' => $iContextId,
  240. ]
  241. ],
  242. 'tasks' => $this->getEntries($iContextId, array_merge($aParams, [
  243. 'filter' => $iFilterSelected,
  244. ])),
  245. 'js_code' => $this->getJsCode('tasks', ['t_confirm_block_deletion' => _t('_bx_tasks_txt_msg_confirm_tasklist_deletion')])
  246. ]);
  247. }
  248. public function getEntries($iContextId = 0, $aParams = [])
  249. {
  250. $CNF = &$this->_oConfig->CNF;
  251. $sJsObject = $this->_oConfig->getJsObject('tasks');
  252. $oModule = $this->getModule();
  253. $oPermalinks = BxDolPermalinks::getInstance();
  254. $oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
  255. $aTypes = BxDolFormQuery::getDataItems($CNF['OBJECT_PRE_LIST_TYPES']);
  256. $aPriorities = BxDolFormQuery::getDataItems($CNF['OBJECT_PRE_LIST_PRIORITIES']);
  257. $aStates = BxDolFormQuery::getDataItems($CNF['OBJECT_PRE_LIST_STATES']);
  258. $bContext = !empty($iContextId);
  259. $bAllowAdd = $bContext && $oModule->isAllowAdd($iContextId);
  260. $bAllowManage = $bContext && $oModule->isAllowManageByContext($iContextId);
  261. $aLists = [];
  262. if(!$bContext) {
  263. $iProfile = $aParams['for_profile'] ?? bx_get_logged_profile_id();
  264. $aContexts = $this->_oModule->getContexts();
  265. foreach($aContexts as $sName => $sTitle) {
  266. $aIds = $this->_oModule->_oDb->getContextsIdsByType($sName, $iProfile);
  267. foreach($aIds as $iId) {
  268. $oContext = BxDolProfile::getInstance($iId);
  269. if(!$oContext)
  270. continue;
  271. $aLists[] = [
  272. 'id' => $sName,
  273. 'context_id' => $iId,
  274. 'title' => _t('_bx_tasks_txt_list_title', $oContext->getDisplayName(), $sTitle)
  275. ];
  276. }
  277. }
  278. }
  279. else
  280. $aLists = $this->_oDb->getLists($iContextId);
  281. $aParams = array_merge($aParams, [
  282. 'with_stats' => true
  283. ]);
  284. $aTmplVarsLists = [];
  285. foreach($aLists as $aList) {
  286. $iTasksContextId = $bContext ? $iContextId : ($aList['context_id'] ?? false);
  287. if(!$iTasksContextId)
  288. continue;
  289. $bTasksAllowManage = $bContext ? $bAllowManage : $oModule->isAllowManageByContext($iTasksContextId);
  290. $aTasks = $this->_oDb->getTasks($iTasksContextId, $bContext ? $aList['id'] : 0, $aParams);
  291. if(!$aTasks || !is_array($aTasks))
  292. continue;
  293. $aTmplVarsTasks = [];
  294. foreach($aTasks as $aTask) {
  295. $sTime = '';
  296. if(!empty($aTask['time_total']))
  297. $sTime = _t('_bx_tasks_txt_total', $this->_oConfig->timeI2S($aTask['time_total']) . (!empty($aTask['time']) ? ' (' . $this->_oConfig->timeI2S($aTask['time']) . ')' : ''));
  298. if(!empty($aTask['estimate']))
  299. $sTime .= ' ' . _t('_bx_tasks_txt_estimate', $this->_oConfig->timeI2S(60 * (int)$aTask['estimate']));
  300. $aMembers = $oConnection->getConnectedInitiators($aTask[$CNF['FIELD_ID']]);
  301. $aTmplVarsMembers = [];
  302. foreach($aMembers as $iMember)
  303. if(($oProfile = BxDolProfile::getInstance($iMember)) !== false && !($oProfile instanceof BxDolProfileUndefined))
  304. $aTmplVarsMembers[] = ['info' => $oProfile->getUnit(0, ['template' => 'unit_wo_info'])];
  305. $bCompleted = $aTask[$CNF['FIELD_COMPLETED']] == 1;
  306. $aTmplVarsTasks[] = [
  307. 'id' => $aTask[$CNF['FIELD_ID']],
  308. 'title' => bx_process_output($aTask[$CNF['FIELD_TITLE']]),
  309. 'created' => bx_time_js($aTask[$CNF['FIELD_ADDED']]),
  310. 'class' => $bCompleted ? 'completed' : 'uncompleted',
  311. 'due' => $aTask[$CNF['FIELD_DUE_DATE']] > 0 ? bx_time_js($aTask[$CNF['FIELD_DUE_DATE']]) : '',
  312. 'type' => $aTypes[$aTask[$CNF['FIELD_TYPE']]] ?? '',
  313. 'priority' => $aPriorities[$aTask[$CNF['FIELD_PRIORITY']]] ?? '',
  314. 'state' => $aStates[$aTask[$CNF['FIELD_STATE']]] ?? '',
  315. 'time' => $sTime,
  316. 'bx_repeat:members' => $aTmplVarsMembers,
  317. 'badges' => $oModule->serviceGetBadges($aTask[$CNF['FIELD_ID']], true),
  318. 'url' => bx_absolute_url($oPermalinks->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aTask[$CNF['FIELD_ID']])),
  319. 'object' => $sJsObject,
  320. 'bx_if:allow_manage' => [
  321. 'condition' => $bTasksAllowManage,
  322. 'content' => [
  323. 'id' => $aTask[$CNF['FIELD_ID']],
  324. 'object' => $sJsObject,
  325. 'checked' => $bCompleted ? 'checked' : '',
  326. ]
  327. ],
  328. 'bx_if:deny_manage' => [
  329. 'condition' => !$bTasksAllowManage,
  330. 'content' => [
  331. 'id' => $aTask[$CNF['FIELD_ID']],
  332. 'checked' => $bCompleted ? 'checked' : '',
  333. ]
  334. ]
  335. ];
  336. }
  337. $sClass = $sCompleted = $sAll = "";
  338. if (isset($aFilterValues[$aList[$CNF['FIELD_ID']]])){
  339. $sClass = $aFilterValues[$aList[$CNF['FIELD_ID']]];
  340. if ($sClass == 'completed')
  341. $sCompleted= 'selected';
  342. if ($sClass == 'all')
  343. $sAll = 'selected';
  344. }
  345. $aTmplVarsAllowEditList = $aTmplVarsAllowAdd = [];
  346. if($bAllowAdd) {
  347. $aTmplVarsAllowEditList = [
  348. 'title' => $aList[$CNF['FIELD_TITLE']],
  349. 'context_id' => $iContextId,
  350. 'list_id' => $aList[$CNF['FIELD_ID']],
  351. 'object' => $sJsObject,
  352. ];
  353. $aTmplVarsAllowAdd = [
  354. 'context_id' => $iContextId,
  355. 'list_id' => $aList[$CNF['FIELD_ID']],
  356. 'object' => $sJsObject,
  357. ];
  358. }
  359. $aTmplVarsAllowDeleteList = [];
  360. if($bAllowManage) {
  361. $aTmplVarsAllowDeleteList = [
  362. 'context_id' => $iContextId,
  363. 'list_id' => $aList[$CNF['FIELD_ID']],
  364. 'object' => $sJsObject,
  365. ];
  366. }
  367. $aTmplVarsLists[] = [
  368. 'bx_if:allow_edit_list' => [
  369. 'condition' => $bAllowAdd,
  370. 'content' => $aTmplVarsAllowEditList
  371. ],
  372. 'bx_if:allow_add' => [
  373. 'condition' => $bAllowAdd,
  374. 'content' => $aTmplVarsAllowAdd
  375. ],
  376. 'bx_if:allow_delete_list' => [
  377. 'condition' => $bAllowManage,
  378. 'content' => $aTmplVarsAllowDeleteList
  379. ],
  380. 'bx_if:deny_edit_list' => [
  381. 'condition' => !$bAllowAdd,
  382. 'content' => [
  383. 'title' => $aList[$CNF['FIELD_TITLE']],
  384. ]
  385. ],
  386. 'bx_repeat:tasks' => $aTmplVarsTasks,
  387. 'context_id' => $iContextId,
  388. 'list_id' => $aList[$CNF['FIELD_ID']],
  389. 'object' => $sJsObject
  390. ];
  391. }
  392. return $this->parseHtmlByName('tasks.html', [
  393. 'html_id' => $this->_oConfig->getHtmlIds('tasks'),
  394. 'bx_repeat:task_lists' => $aTmplVarsLists,
  395. ]);
  396. }
  397. public function getStickers($aStickers)
  398. {
  399. $aTmplVarsStickers = [];
  400. foreach($aStickers as $aSticker)
  401. $aTmplVarsStickers[] = [
  402. 'title' => $aSticker['title'],
  403. 'bx_if:show_color' => [
  404. 'condition' => $aSticker['color'] != '',
  405. 'content' => [
  406. 'color' => $aSticker['color']
  407. ]
  408. ]
  409. ];
  410. return $this->parseHtmlByName('stickers.html', [
  411. 'bx_repeat:stickers' => $aTmplVarsStickers
  412. ]);
  413. }
  414. protected function _getEntriesFilters($iContextId = 0, $aParams = [])
  415. {
  416. $sJsObject = $this->_oConfig->getJsObject('tasks');
  417. $iLoggedId = bx_get_logged_profile_id();
  418. $this->_oDb->cleanFilters($iContextId, $iLoggedId);
  419. $aInput = [
  420. 'type' => 'select',
  421. 'name' => 'filters',
  422. 'value' => $aParams['filter_selected'] ?? 0,
  423. 'values' => [
  424. ['key' => 0, 'value' => _t('_bx_tasks_filter_title_select')]
  425. ],
  426. 'attrs' => [
  427. 'onchange' => $sJsObject . '.applyFilter(this, ' . $iContextId . ')'
  428. ]
  429. ];
  430. $aTypes = [
  431. '_bx_tasks_txt_flt_system' => ['sample' => 'active', 'context_id' => 0, 'author' => 0],
  432. '_bx_tasks_txt_flt_contextual' => ['sample' => 'active', 'context_id' => $iContextId, 'author' => 0],
  433. '_bx_tasks_txt_flt_my_permanent' => ['sample' => 'active', 'context_id' => $iContextId, 'author' => $iLoggedId, 'permanent' => 1],
  434. '_bx_tasks_txt_flt_my_temporary' => ['sample' => 'active', 'context_id' => $iContextId, 'author' => $iLoggedId, 'permanent' => 0]
  435. ];
  436. foreach($aTypes as $sTitle => $aType) {
  437. $aFilterItems = $this->_oDb->getFilters($aType);
  438. if($aFilterItems && is_array($aFilterItems)) {
  439. $aInput['values'][] = ['type' => 'group_header', 'value' => _t($sTitle)];
  440. foreach($aFilterItems as $aFilterItem)
  441. $aInput['values'][] = [
  442. 'key' => $aFilterItem['id'],
  443. 'value' => _t($aFilterItem['title'])
  444. ];
  445. $aInput['values'][] = ['type' => 'group_end'];
  446. }
  447. }
  448. $oForm = new BxTemplFormView([]);
  449. return $oForm->genInputSelect($aInput);
  450. }
  451. }
  452. /** @} */