BxCoursesTemplate.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  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. *
  6. * @defgroup Courses Courses
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. /*
  12. * Courses module representation.
  13. */
  14. class BxCoursesTemplate extends BxBaseModGroupsTemplate
  15. {
  16. function __construct(&$oConfig, &$oDb)
  17. {
  18. $this->MODULE = 'bx_courses';
  19. parent::__construct($oConfig, $oDb);
  20. }
  21. public function getCounters($aCounters)
  22. {
  23. $aTmplVars = [];
  24. foreach([BX_COURSES_CND_USAGE_ST, BX_COURSES_CND_USAGE_AT] as $iUsage) {
  25. $sUsage = $this->_oConfig->getUsageI2S($iUsage);
  26. $aTmplVarsCounters = [true];
  27. $bTmplVarsCounters = !empty($aCounters[$sUsage]) && is_array($aCounters[$sUsage]);
  28. if($bTmplVarsCounters) {
  29. $aTmplVarsCounters['bx_repeat:counters_' . $sUsage] = [];
  30. foreach($aCounters[$sUsage] as $sModule => $iCount)
  31. $aTmplVarsCounters['bx_repeat:counters_' . $sUsage][] = [
  32. 'title' => _t('_' . $sModule),
  33. 'value' => $iCount
  34. ];
  35. }
  36. $aTmplVars['bx_if:show_' . $sUsage] = [
  37. 'condition' => $bTmplVarsCounters,
  38. 'content' => $aTmplVarsCounters
  39. ];
  40. }
  41. return $this->parseHtmlByName('counters.html', $aTmplVars);
  42. }
  43. public function entryStructureByLevel($aContentInfo, $aParams = [])
  44. {
  45. $CNF = &$this->_oConfig->CNF;
  46. if(!isset($aParams['level']))
  47. return '';
  48. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  49. $iProfileId = bx_get_logged_profile_id();
  50. $oPermalink = BxDolPermalinks::getInstance();
  51. $iLevel = (int)$aParams['level'];
  52. $iSelected = (int)$aParams['selected'];
  53. $iStart = isset($aParams['start']) ? (int)$aParams['start'] : 0;
  54. $iPerPage = isset($aParams['per_page']) ? (int)$aParams['per_page'] : 0;
  55. $aNodes = $this->_oDb->getContentStructure([
  56. 'sample' => 'entry_id_full',
  57. 'entry_id' => $iContentId,
  58. 'level' => $iLevel,
  59. 'status' => 'active',
  60. 'start' => $iStart,
  61. 'per_page' => $iPerPage ? $iPerPage + 1 : 0
  62. ]);
  63. if(empty($aNodes) || !is_array($aNodes))
  64. return '';
  65. $aTmplVarsNodes = [];
  66. foreach($aNodes as $iKey => $aNode)
  67. $aTmplVarsNodes[] = $this->parseHtmlByName('node_l' . $iLevel . '.html', array_merge($aNode, [
  68. 'bx_if:selected' => [
  69. 'condition' => $aNode['node_id'] == $iSelected,
  70. 'content' => [true]
  71. ],
  72. 'index' => $iKey,
  73. 'link' => BX_DOL_URL_ROOT . $oPermalink->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&' . $CNF['FIELD_ID'] . '=' . $iContentId, [
  74. 'parent_id' => $aNode['node_id']
  75. ]),
  76. 'status' => $this->_getNodeStatus($iProfileId, $iContentId, $aNode['node_id']),
  77. ]));
  78. $oPaginate = new BxTemplPaginate([
  79. 'start' => $iStart,
  80. 'per_page' => $iPerPage,
  81. 'on_change_page' => "return !loadDynamicBlockAutoPaginate(this, '{start}', '{per_page}')"
  82. ]);
  83. $oPaginate->setNumFromDataArray($aTmplVarsNodes);
  84. return $this->parseHtmlByName('nodes_l' . $iLevel . '.html', [
  85. 'level' => $iLevel,
  86. 'bx_repeat:nodes' => $aTmplVarsNodes,
  87. 'paginate' => $oPaginate->getSimplePaginate()
  88. ]);
  89. }
  90. /**
  91. * For 2 levels bases structure ( Max Level = 2)
  92. */
  93. public function entryStructureByParentMl2($aContentInfo, $aParams = [])
  94. {
  95. $CNF = &$this->_oConfig->CNF;
  96. if(!isset($aParams['parent_id']))
  97. return '';
  98. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  99. $iParentId = (int)$aParams['parent_id'];
  100. $iProfileId = bx_get_logged_profile_id();
  101. $aNodes = $this->_oDb->getContentStructure([
  102. 'sample' => 'entry_id_full',
  103. 'entry_id' => $iContentId,
  104. 'parent_id' => $iParentId,
  105. 'status' => 'active'
  106. ]);
  107. if(empty($aNodes) || !is_array($aNodes))
  108. return '';
  109. $oPermalink = BxDolPermalinks::getInstance();
  110. $aTmplVarsNodes = [];
  111. foreach($aNodes as $iKey => $aNode) {
  112. $aTmplVarsNodes[] = [
  113. 'node' => $this->parseHtmlByName('ml2_node_l' . $aNode['level'] . '.html', array_merge($aNode, [
  114. 'index' => $iKey,
  115. 'link' => BX_DOL_URL_ROOT . $oPermalink->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY_NODE'] . '&id=' . $aNode['id']),
  116. 'status' => $this->_getNodeStatus($iProfileId, $iContentId, $aNode['node_id']),
  117. ]))
  118. ];
  119. }
  120. return $this->parseHtmlByName('ml2_nodes_l' . $aSubNode['level'] . '.html', [
  121. 'bx_repeat:nodes' => $aTmplVarsNodes
  122. ]);
  123. }
  124. /**
  125. * For 3 levels bases structure ( Max Level = 3)
  126. */
  127. public function entryStructureByParentMl3($aContentInfo, $aParams = [])
  128. {
  129. $CNF = &$this->_oConfig->CNF;
  130. if(empty($aParams['parent_id']))
  131. return '';
  132. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  133. $iParentId = (int)$aParams['parent_id'];
  134. $iProfileId = bx_get_logged_profile_id();
  135. $aNodes = $this->_oDb->getContentStructure([
  136. 'sample' => 'entry_id_full',
  137. 'entry_id' => $iContentId,
  138. 'parent_id' => $iParentId,
  139. 'status' => 'active'
  140. ]);
  141. if(empty($aNodes) || !is_array($aNodes))
  142. return '';
  143. $sJsObject = $this->_oConfig->getJsObject('entry');
  144. $oPermalink = BxDolPermalinks::getInstance();
  145. $aInputs = [];
  146. foreach($aNodes as $aNode) {
  147. $aInputs['node_' . $aNode['node_id']] = [
  148. 'type' => 'block_header',
  149. 'caption' => bx_process_output($aNode['title']),
  150. 'collapsed' => false,
  151. 'attrs' => ['id' => 'node_' . $aNode['node_id'], 'class' => ''],
  152. ];
  153. $aSubNodes = $this->_oDb->getContentStructure([
  154. 'sample' => 'entry_id_full',
  155. 'entry_id' => $iContentId,
  156. 'parent_id' => (int)$aNode['node_id'],
  157. 'status' => 'active'
  158. ]);
  159. if(!empty($aSubNodes) && is_array($aSubNodes)) {
  160. $aTmplVarsNodes = [];
  161. foreach($aSubNodes as $iKey => $aSubNode) {
  162. list($iPassPercent, $sPassProgress, $sPassStatus, $sPassTitle) = $this->_getNodePass($iProfileId, $iContentId, $aSubNode);
  163. $sLink = BX_DOL_URL_ROOT . $oPermalink->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY_NODE'] . '&id=' . $iContentId, [
  164. 'node_id' => $aSubNode['node_id']
  165. ]);
  166. $aTmplVarsNodes[] = [
  167. 'node' => $this->parseHtmlByName('ml3_node_l' . $aSubNode['level'] . '.html', array_merge($aSubNode, [
  168. 'index' => $iKey,
  169. 'link' => $sLink,
  170. 'pass_percent' => $iPassPercent,
  171. 'pass_progress' => $sPassProgress,
  172. 'pass_status' => $sPassStatus,
  173. 'bx_if:show_pass' => [
  174. 'condition' => $sPassTitle,
  175. 'content' => [
  176. 'js_object' => $sJsObject,
  177. 'id' => $aSubNode['node_id'],
  178. 'pass_href' => $sLink,
  179. 'pass_title' => $sPassTitle,
  180. ]
  181. ]
  182. ]))
  183. ];
  184. }
  185. $sInput = 'node_' . $aNode['node_id'] . '_subnodes';
  186. $aInputs[$sInput] = [
  187. 'type' => 'custom',
  188. 'name' => $sInput,
  189. 'caption' => '',
  190. 'content' => $this->parseHtmlByName('ml3_nodes_l' . $aSubNode['level'] . '.html', [
  191. 'bx_repeat:nodes' => $aTmplVarsNodes
  192. ]),
  193. ];
  194. }
  195. else
  196. $aInputs['node_' . $aNode['node_id']]['collapsed'] = true;
  197. }
  198. $oForm = new BxTemplFormView([
  199. 'form_attrs' => [
  200. 'id' => 'bx-courses-structure-by-parent-' . $iParentId,
  201. ],
  202. 'inputs' => $aInputs,
  203. ]);
  204. $oForm->setShowEmptySections(true);
  205. return $oForm->getCode();
  206. }
  207. public function entryNode($aContentInfo, $aParams = [])
  208. {
  209. $CNF = &$this->_oConfig->CNF;
  210. if(!isset($aParams['node_id']))
  211. return '';
  212. $sJsObject = $this->_oConfig->getJsObject('entry');
  213. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  214. $iNodeId = (int)$aParams['node_id'];
  215. $iUsage = isset($aParams['usage']) && $aParams['usage'] !== false ? (int)$aParams['usage'] : BX_COURSES_CND_USAGE_ST;
  216. $iProfileId = bx_get_logged_profile_id();
  217. $aNode = $this->_oDb->getContentNodes([
  218. 'sample' => 'id_full',
  219. 'id' => $iNodeId,
  220. ]);
  221. $aDataItems = $this->_oDb->getContentData([
  222. 'sample' => 'entry_node_ids',
  223. 'entry_id' => $iContentId,
  224. 'node_id' => $iNodeId,
  225. 'usage' => $iUsage
  226. ]);
  227. $sTxtUndefined = _t('_undefined');
  228. $aTmplVarsItems = [];
  229. if(!empty($aDataItems) && is_array($aDataItems))
  230. foreach($aDataItems as $iIndex => $aDataItem) {
  231. $sImageUrl = '';
  232. if(($sMethod = 'get_thumb') && bx_is_srv($aDataItem['content_type'], $sMethod))
  233. $sImageUrl = bx_srv($aDataItem['content_type'], $sMethod, [$aDataItem['content_id']]);
  234. $sLink = '';
  235. if(($sMethod = 'get_link') && bx_is_srv($aDataItem['content_type'], $sMethod))
  236. $sLink = bx_srv($aDataItem['content_type'], $sMethod, [$aDataItem['content_id']]);
  237. $aTmplVarsPass = [true];
  238. $bTmplVarsPass = $iUsage == BX_COURSES_CND_USAGE_ST && $sLink && !$this->_oModule->isDataPassed($iProfileId, $aDataItem) && ((int)$aNode['passing'] == 0 || $iIndex == 0 || $this->_oModule->isDataPassed($iProfileId, $aDataItems[$iIndex - 1]));
  239. if($bTmplVarsPass) {
  240. $aTmplVarsPass = [
  241. 'js_object' => $sJsObject,
  242. 'id' => $aDataItem['id'],
  243. 'link' => $sLink
  244. ];
  245. }
  246. $sType = _t('_bx_courses_txt_data_type_' . $aDataItem['content_type']);
  247. $sTitle = '';
  248. if(($sMethod = 'get_title') && bx_is_srv($aDataItem['content_type'], $sMethod))
  249. $sTitle = bx_srv($aDataItem['content_type'], $sMethod, [$aDataItem['content_id']]);
  250. if(!$sTitle && ($sMethod = 'get_text') && bx_is_srv($aDataItem['content_type'], $sMethod))
  251. $sTitle = bx_srv($aDataItem['content_type'], $sMethod, [$aDataItem['content_id']]);
  252. if(!$sTitle)
  253. $sTitle = $sTxtUndefined;
  254. $bTmplVarsShowLink = $iUsage == BX_COURSES_CND_USAGE_AT && $sLink;
  255. $aTmplVarsShowLink = $bTmplVarsShowLink ? [
  256. 'link' => $sLink,
  257. 'title' => $sTitle
  258. ] : [true];
  259. $aTmplVarsItems[] = [
  260. 'bx_if:show_image' => [
  261. 'condition' => $sImageUrl,
  262. 'content' => [
  263. 'image' => $sImageUrl
  264. ]
  265. ],
  266. 'bx_if:show_image_empty' => [
  267. 'condition' => !$sImageUrl,
  268. 'content' => [
  269. 'type' => $sType
  270. ]
  271. ],
  272. 'type' => $sType,
  273. 'bx_if:show_link' => [
  274. 'condition' => $bTmplVarsShowLink,
  275. 'content' => $aTmplVarsShowLink
  276. ],
  277. 'bx_if:show_text' => [
  278. 'condition' => !$bTmplVarsShowLink,
  279. 'content' => [
  280. 'title' => $sTitle,
  281. ]
  282. ],
  283. 'bx_if:show_pass' => [
  284. 'condition' => $bTmplVarsPass,
  285. 'content' => $aTmplVarsPass
  286. ]
  287. ];
  288. }
  289. $sMiName = 'node-data-';
  290. $sMiLink = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY_NODE'] . '&id=' . $iContentId, [
  291. 'node_id' => $iNodeId,
  292. 'usage' => ''
  293. ]);
  294. $oMenu = new BxTemplMenu([
  295. 'template' => 'menu_block_submenu_ver.html',
  296. 'menu_id'=> 'node-data',
  297. 'menu_items' => [
  298. ['id' => $sMiName . 'st', 'name' => $sMiName . 'st', 'class' => '', 'link' => $sMiLink . '0', 'target' => '_self', 'title' => _t('_bx_courses_menu_item_title_node_data_steps')],
  299. ['id' => $sMiName . 'at', 'name' => $sMiName . 'at', 'class' => '', 'link' => $sMiLink . '1', 'target' => '_self', 'title' => _t('_bx_courses_menu_item_title_node_data_attachments')]
  300. ]
  301. ]);
  302. $oMenu->setSelected('', $sMiName . $this->_oConfig->getUsageI2S($iUsage));
  303. return [
  304. 'content' => $this->parseHtmlByName('node_view.html', [
  305. 'index' => $aNode['order'],
  306. 'sample' => _t('_bx_courses_txt_sample_l' . $aNode['level'] . '_single'),
  307. 'title' => $aNode['title'],
  308. 'text' => $aNode['text'],
  309. 'bx_repeat:items' => $aTmplVarsItems
  310. ]),
  311. 'menu' => $oMenu
  312. ];
  313. }
  314. protected function _getNodeStatus($iProfileId, $iContentId, $iNodeId)
  315. {
  316. if($this->_oModule->isNodePassed($iProfileId, $iNodeId))
  317. return _t('_bx_courses_txt_status_completed');
  318. if($this->_oModule->isNodeStarted($iProfileId, $iNodeId))
  319. return _t('_bx_courses_txt_status_in_process');
  320. return _t('_bx_courses_txt_status_not_started');
  321. }
  322. protected function _getNodePass($iProfileId, $iContentId, $aNode)
  323. {
  324. $iTotal = 0;
  325. $iPassCount = $iPassPercent = 0;
  326. $sPassStatus = $sPassTitle = '';
  327. if(($iTotal = $this->_oModule->getDataTotalByNode($aNode)) != 0) {
  328. $aUserTrack = $this->_oDb->getContentData([
  329. 'sample' => 'user_track',
  330. 'entry_id' => $iContentId,
  331. 'node_id' => $aNode['node_id'],
  332. 'profile_id' => $iProfileId
  333. ]);
  334. $iPassCount = count($aUserTrack);
  335. $iPassPercent = round(100 * $iPassCount/$iTotal);
  336. if($iPassCount == 0) {
  337. $sPassStatus = '_bx_courses_txt_status_not_started';
  338. $sPassTitle = '_bx_courses_txt_pass_start';
  339. }
  340. else {
  341. if($iPassCount != $iTotal) {
  342. $sPassStatus = '_bx_courses_txt_status_in_process';
  343. $sPassTitle = '_bx_courses_txt_pass_continue';
  344. }
  345. else {
  346. $sPassStatus = '_bx_courses_txt_status_completed';
  347. $sPassTitle = '_bx_courses_txt_pass_again';
  348. }
  349. }
  350. }
  351. return [
  352. $iPassPercent,
  353. _t('_bx_courses_txt_n_m_steps', $iPassCount, $iTotal),
  354. _t($sPassStatus ? $sPassStatus : '_undefined'),
  355. _t($sPassTitle)
  356. ];
  357. }
  358. }
  359. /** @} */