BxForumModule.php 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  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 Forum Forum
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. class BxForumModule extends BxBaseModTextModule
  12. {
  13. function __construct(&$aModule)
  14. {
  15. parent::__construct($aModule);
  16. }
  17. public function decodeDataApi ($aData, $bExtended = false)
  18. {
  19. $CNF = $this->_oConfig->CNF;
  20. $aResult = parent::decodeDataApi($aData, $bExtended);
  21. $iCategory = (int)($aData[$CNF['FIELD_CATEGORY']] ?? 0);
  22. $oCategory = BxDolCategory::getObjectInstance($CNF['OBJECT_CATEGORY']);
  23. if(!$iCategory || !$oCategory)
  24. return $aResult;
  25. /*
  26. * A category has a row in the categories table only after its icon is set in Studio,
  27. * so fall back to the icon the site's meta uses. An uploaded icon is a storage id.
  28. */
  29. $aCategoryData = $this->_oDb->getCategories(['type' => 'by_category', 'category' => $iCategory]);
  30. $sIcon = !empty($aCategoryData['icon']) ? $aCategoryData['icon'] : 'folder';
  31. if(is_numeric($sIcon))
  32. $sIcon = (string)BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_IMAGES)->getFileUrlById((int)$sIcon);
  33. $aResult['category'] = [
  34. 'name' => $oCategory->getCategoryTitle($iCategory),
  35. 'icon' => $sIcon
  36. ];
  37. return $aResult;
  38. }
  39. public function sortParticipants ($aParticipants, $iProfileIdLastComment, $iProfileIdAuthor, $iProfileIdCurrent = 0)
  40. {
  41. if (!$iProfileIdCurrent)
  42. $iProfileIdCurrent = bx_get_logged_profile_id();
  43. $aMoveUp = array($iProfileIdCurrent, $iProfileIdLastComment, $iProfileIdAuthor);
  44. asort($aParticipants, SORT_NUMERIC);
  45. foreach ($aMoveUp as $iProfileId) {
  46. if (!isset($aParticipants[$iProfileId]))
  47. continue;
  48. $a = array($iProfileId => $aParticipants[$iProfileId]);
  49. unset($aParticipants[$iProfileId]);
  50. $aParticipants = $a + $aParticipants;
  51. }
  52. return $aParticipants;
  53. }
  54. /**
  55. * Action methods
  56. */
  57. public function actionUpdateStatus($sAction = '', $iContentId = 0)
  58. {
  59. if(empty($sAction) && bx_get('action') !== false)
  60. $sAction = bx_process_input(bx_get('action'));
  61. if(empty($iContentId) && bx_get('id') !== false)
  62. $iContentId = (int)bx_get('id');
  63. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  64. if(empty($aContentInfo) || !is_array($aContentInfo))
  65. return echoJson(array('code' => 1, 'message' => _t('_bx_forum_err_not_found')));
  66. $sMethodCheck = 'checkAllowed' . bx_gen_method_name($sAction) . 'AnyEntry';
  67. $sResult = $this->$sMethodCheck($aContentInfo);
  68. if($sResult !== CHECK_ACTION_RESULT_ALLOWED)
  69. return echoJson(array('code' => 2, 'message' => $sResult));
  70. bx_audit(
  71. $iContentId,
  72. $this->getName(),
  73. '_sys_audit_action_' . $sAction,
  74. $this->_prepareAuditParams($aContentInfo, false)
  75. );
  76. if(!$this->_oDb->updateStatus($sAction, $aContentInfo))
  77. return echoJson(array('code' => 3, 'message' => _t('_error occured')));
  78. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  79. $this->alertAfterEdit($aContentInfo);
  80. echoJson(array('code' => 0, 'id' => $iContentId, 'reload' => 1));
  81. }
  82. public function actionAjaxGetAuthors()
  83. {
  84. $aResult = BxDolService::call('system', 'profiles_search', array(bx_get('term')), 'TemplServiceProfiles');
  85. header('Content-Type:text/javascript; charset=utf-8');
  86. echo json_encode($aResult);
  87. }
  88. /**
  89. * Service methods
  90. */
  91. public function serviceGetSafeServices()
  92. {
  93. $a = parent::serviceGetSafeServices();
  94. return array_merge($a, array (
  95. 'BrowseNew' => '',
  96. 'BrowseLatest' => '',
  97. 'BrowseTop' => '',
  98. 'BrowsePopular' => '',
  99. 'BrowseUpdated' => '',
  100. 'BrowsePartaken' => '',
  101. 'BrowseIndex' => '',
  102. 'Search' => '',
  103. ));
  104. }
  105. /**
  106. * @page service Service Calls
  107. * @section bx_forum Discussions
  108. * @subsection bx_forum-other Other
  109. * @subsubsection bx_forum-get_searchable_fields get_searchable_fields
  110. *
  111. * @code bx_srv('bx_forum', 'get_searchable_fields', [...]); @endcode
  112. *
  113. * Get searchable fields for Studio settings.
  114. *
  115. * @return an array with key-value pairs to be used in settings dropdown field.
  116. *
  117. * @see BxForumModule::serviceGetSearchableFields
  118. */
  119. /**
  120. * @ref bx_forum-get_searchable_fields "get_searchable_fields"
  121. */
  122. public function serviceGetSearchableFields ($aInputsAdd = array())
  123. {
  124. $CNF = &$this->_oConfig->CNF;
  125. $aResult = parent::serviceGetSearchableFields($aInputsAdd);
  126. $aResult[$CNF['FIELD_TEXT_COMMENTS']] = _t('_bx_forum_form_entry_input_text_comments');
  127. return $aResult;
  128. }
  129. /**
  130. * Service methods
  131. */
  132. /**
  133. * @page service Service Calls
  134. * @section bx_forum Discussions
  135. * @subsection bx_forum-other Other
  136. * @subsubsection bx_forum-get_info get_info
  137. *
  138. * @code bx_srv('bx_forum', 'get_info', [...]); @endcode
  139. *
  140. * Get content info by content ID. Is used in "Content Info Objects" system.
  141. *
  142. * @param $iContentId integer value with content ID.
  143. * @param $bSearchableFieldsOnly (optional) boolean value determining all info or "searchable fields" only will be returned.
  144. * @return an array with content info. Empty array is returned if something is wrong.
  145. *
  146. * @see BxForumModule::serviceGetInfo
  147. */
  148. /**
  149. * @ref bx_forum-get_info "get_info"
  150. */
  151. public function serviceGetInfo ($iContentId, $bSearchableFieldsOnly = true)
  152. {
  153. $aContentInfo = $this->_getFields($iContentId);
  154. if(empty($aContentInfo))
  155. return array();
  156. return $aContentInfo;
  157. }
  158. /**
  159. * @page service Service Calls
  160. * @section bx_forum Discussions
  161. * @subsection bx_forum-page_blocks Page Blocks
  162. * @subsubsection bx_forum-browse_new browse_new
  163. *
  164. * @code bx_srv('bx_forum', 'browse_new', [...]); @endcode
  165. *
  166. * Get page block with a list of items ordered by newness and represented as table.
  167. *
  168. * @param $sUnitView (optional) string with unit view type.
  169. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  170. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  171. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  172. *
  173. * @see BxForumModule::serviceBrowseNew
  174. */
  175. /**
  176. * @ref bx_forum-browse_new "browse_new"
  177. */
  178. public function serviceBrowseNew ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
  179. {
  180. $sType = 'new';
  181. if($sUnitView != 'table')
  182. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  183. return $this->_serviceBrowseTable(array(
  184. 'type' => $sType,
  185. 'empty_message' => $bEmptyMessage,
  186. 'ajax_paginate' => $bAjaxPaginate
  187. ), $bShowHeader);
  188. }
  189. /**
  190. * @page service Service Calls
  191. * @section bx_forum Discussions
  192. * @subsection bx_forum-page_blocks Page Blocks
  193. * @subsubsection bx_forum-browse_latest browse_latest
  194. *
  195. * @code bx_srv('bx_forum', 'browse_latest', [...]); @endcode
  196. *
  197. * Get page block with a list of items ordered by Recent Posts in them and represented as table.
  198. *
  199. * @param $sUnitView (optional) string with unit view type.
  200. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  201. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  202. * @param $bShowHeader (optional) boolean value determining whether a resulting table should have Header section or not.
  203. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  204. *
  205. * @see BxForumModule::serviceBrowseNew
  206. */
  207. /**
  208. * @ref bx_forum-browse_latest "browse_latest"
  209. */
  210. public function serviceBrowseLatest($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = true)
  211. {
  212. $sType = 'latest';
  213. if($sUnitView != 'table')
  214. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  215. return $this->_serviceBrowseTable(array(
  216. 'type' => $sType,
  217. 'empty_message' => $bEmptyMessage,
  218. 'ajax_paginate' => $bAjaxPaginate
  219. ), $bShowHeader);
  220. }
  221. /**
  222. * @page service Service Calls
  223. * @section bx_forum Discussions
  224. * @subsection bx_forum-page_blocks Page Blocks
  225. * @subsubsection bx_forum-browse_featured browse_featured
  226. *
  227. * @code bx_srv('bx_forum', 'browse_featured', [...]); @endcode
  228. *
  229. * Get page block with a list of featured items represented as table.
  230. *
  231. * @param $sUnitView (optional) string with unit view type.
  232. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  233. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  234. * @param $bShowHeader (optional) boolean value determining whether a resulting table should have Header section or not.
  235. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  236. *
  237. * @see BxForumModule::serviceBrowseFeatured
  238. */
  239. /**
  240. * @ref bx_forum-browse_featured "browse_featured"
  241. */
  242. public function serviceBrowseFeatured($sUnitView = false, $bEmptyMessage = false, $bAjaxPaginate = true, $bShowHeader = false)
  243. {
  244. $CNF = &$this->_oConfig->CNF;
  245. $sType = 'featured';
  246. if($sUnitView != 'table')
  247. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  248. return $this->_serviceBrowseTable(array(
  249. 'type' => $sType,
  250. 'empty_message' => $bEmptyMessage,
  251. 'ajax_paginate' => $bAjaxPaginate
  252. ), $bShowHeader);
  253. }
  254. /**
  255. * @page service Service Calls
  256. * @section bx_forum Discussions
  257. * @subsection bx_forum-page_blocks Page Blocks
  258. * @subsubsection bx_forum-browse_top browse_top
  259. *
  260. * @code bx_srv('bx_forum', 'browse_top', [...]); @endcode
  261. *
  262. * Get page block with a list of items ordered by a number of comments and represented as table.
  263. *
  264. * @param $sUnitView (optional) string with unit view type.
  265. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  266. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  267. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  268. *
  269. * @see BxForumModule::serviceBrowseTop
  270. */
  271. /**
  272. * @ref bx_forum-browse_top "browse_top"
  273. */
  274. public function serviceBrowseTop($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = true)
  275. {
  276. $sType = 'top';
  277. if($sUnitView != 'table')
  278. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  279. return $this->_serviceBrowseTable(array(
  280. 'type' => $sType,
  281. 'empty_message' => $bEmptyMessage,
  282. 'ajax_paginate' => $bAjaxPaginate
  283. ), $bShowHeader);
  284. }
  285. /**
  286. * @page service Service Calls
  287. * @section bx_forum Discussions
  288. * @subsection bx_forum-page_blocks Page Blocks
  289. * @subsubsection bx_forum-browse_popular browse_popular
  290. *
  291. * @code bx_srv('bx_forum', 'browse_popular', [...]); @endcode
  292. *
  293. * Get page block with a list of items ordered by a number of views and represented as table.
  294. *
  295. * @param $sUnitView (optional) string with unit view type.
  296. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  297. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  298. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  299. *
  300. * @see BxForumModule::serviceBrowsePopular
  301. */
  302. /**
  303. * @ref bx_forum-browse_popular "browse_popular"
  304. */
  305. public function serviceBrowsePopular ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
  306. {
  307. $sType = 'popular';
  308. if($sUnitView != 'table')
  309. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  310. return $this->_serviceBrowseTable(array(
  311. 'type' => $sType,
  312. 'empty_message' => $bEmptyMessage,
  313. 'ajax_paginate' => $bAjaxPaginate
  314. ), $bShowHeader);
  315. }
  316. /**
  317. * @page service Service Calls
  318. * @section bx_forum Discussions
  319. * @subsection bx_forum-page_blocks Page Blocks
  320. * @subsubsection bx_forum-browse_updated browse_updated
  321. *
  322. * @code bx_srv('bx_forum', 'browse_updated', [...]); @endcode
  323. *
  324. * Get page block with a list of updated items represented as table.
  325. *
  326. * @param $sUnitView (optional) string with unit view type.
  327. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  328. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  329. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  330. *
  331. * @see BxForumModule::serviceBrowseUpdated
  332. */
  333. /**
  334. * @ref bx_forum-browse_updated "browse_updated"
  335. */
  336. public function serviceBrowseUpdated ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
  337. {
  338. $sType = 'updated';
  339. if($sUnitView != 'table')
  340. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  341. return $this->_serviceBrowseTable(array(
  342. 'type' => $sType,
  343. 'empty_message' => $bEmptyMessage,
  344. 'ajax_paginate' => $bAjaxPaginate
  345. ), $bShowHeader);
  346. }
  347. /**
  348. * @page service Service Calls
  349. * @section bx_forum Discussions
  350. * @subsection bx_forum-page_blocks Page Blocks
  351. * @subsubsection bx_forum-browse_partaken browse_partaken
  352. *
  353. * @code bx_srv('bx_forum', 'browse_partaken', [...]); @endcode
  354. *
  355. * Get page block with a list of partaken items represented as table.
  356. *
  357. * @param $sUnitView (optional) string with unit view type.
  358. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  359. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  360. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  361. *
  362. * @see BxForumModule::serviceBrowsePartaken
  363. */
  364. /**
  365. * @ref bx_forum-browse_partaken "browse_partaken"
  366. */
  367. public function serviceBrowsePartaken ($iProfileId = 0, $aParams = [])
  368. {
  369. $sType = 'partaken';
  370. if(!$iProfileId)
  371. $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
  372. if(!$iProfileId)
  373. $iProfileId = bx_get_logged_profile_id();
  374. $bEmptyMessage = true;
  375. if(isset($aParams['empty_message'])) {
  376. $bEmptyMessage = (bool)$aParams['empty_message'];
  377. unset($aParams['empty_message']);
  378. }
  379. $bAjaxPaginate = true;
  380. if(isset($aParams['ajax_paginate'])) {
  381. $bAjaxPaginate = (bool)$aParams['ajax_paginate'];
  382. unset($aParams['ajax_paginate']);
  383. }
  384. $bShowHeader = false;
  385. if(isset($aParams['show_header'])) {
  386. $bShowHeader = (bool)$aParams['show_header'];
  387. unset($aParams['show_header']);
  388. }
  389. if(isset($aParams['unit_view']) && $aParams['unit_view'] != 'table')
  390. return $this->_serviceBrowse($sType, array_merge(['author' => $iProfileId], $aParams), BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  391. return $this->_serviceBrowseTable([
  392. 'type' => $sType,
  393. 'author' => $iProfileId,
  394. 'include_contexts' => isset($aParams['include_contexts']) && $aParams['include_contexts'],
  395. 'empty_message' => $bEmptyMessage,
  396. 'ajax_paginate' => $bAjaxPaginate
  397. ], $bShowHeader);
  398. }
  399. /**
  400. * @page service Service Calls
  401. * @section bx_forum Discussions
  402. * @subsection bx_forum-page_blocks Page Blocks
  403. * @subsubsection bx_forum-browse_index browse_index
  404. *
  405. * @code bx_srv('bx_forum', 'browse_index', [...]); @endcode
  406. *
  407. * Get page block for Site's Home page with a list of items ordered by newness and represented as table.
  408. *
  409. * @param $sUnitView (optional) string with unit view type.
  410. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  411. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  412. * @param $bShowHeader (optional) boolean value determining whether a resulting table should have Header section or not.
  413. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  414. *
  415. * @see BxForumModule::serviceBrowseIndex
  416. */
  417. /**
  418. * @ref bx_forum-browse_index "browse_index"
  419. */
  420. public function serviceBrowseIndex($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
  421. {
  422. $sType = 'index';
  423. if($sUnitView != 'table')
  424. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  425. return $this->_serviceBrowseTable(array(
  426. 'type' => $sType,
  427. 'per_page' => (int)$this->_oDb->getParam('bx_forum_per_page_index'),
  428. 'empty_message' => $bEmptyMessage,
  429. 'ajax_paginate' => $bAjaxPaginate
  430. ), $bShowHeader);
  431. }
  432. /**
  433. * @page service Service Calls
  434. * @section bx_forum Discussions
  435. * @subsection bx_forum-page_blocks Page Blocks
  436. * @subsubsection bx_forum-browse_author browse_author
  437. *
  438. * @code bx_srv('bx_forum', 'browse_author', [...]); @endcode
  439. *
  440. * Get page block with a list of items filtered by Author and represented as table.
  441. *
  442. * @param $iProfileId (optional) integer value with author ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
  443. * @param $aParams (optional) an array of additional params. It's not used for now.
  444. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  445. *
  446. * @see BxForumModule::serviceBrowseAuthor
  447. */
  448. /**
  449. * @ref bx_forum-browse_author "browse_author"
  450. */
  451. public function serviceBrowseAuthor ($iProfileId = 0, $aParams = array())
  452. {
  453. if(!$iProfileId)
  454. $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
  455. if(!$iProfileId)
  456. return '';
  457. $bEmptyMessage = true;
  458. if(isset($aParams['empty_message'])) {
  459. $bEmptyMessage = (bool)$aParams['empty_message'];
  460. unset($aParams['empty_message']);
  461. }
  462. $bAjaxPaginate = true;
  463. if(isset($aParams['ajax_paginate'])) {
  464. $bAjaxPaginate = (bool)$aParams['ajax_paginate'];
  465. unset($aParams['ajax_paginate']);
  466. }
  467. if($this->_bIsApi || (isset($aParams['unit_view']) && $aParams['unit_view'] != 'table'))
  468. return $this->_serviceBrowse('author', array_merge(array('author' => $iProfileId), $aParams), BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  469. return $this->_serviceBrowseTable(array(
  470. 'type' => 'author',
  471. 'author' => $iProfileId,
  472. 'where' => array('fld' => 'author', 'val' => $iProfileId, 'opr' => '='),
  473. 'per_page' => (int)$this->_oDb->getParam('bx_forum_per_page_profile'),
  474. 'empty_message' => $bEmptyMessage,
  475. 'ajax_paginate' => $bAjaxPaginate
  476. ), false);
  477. }
  478. /**
  479. * @page service Service Calls
  480. * @section bx_forum Discussions
  481. * @subsection bx_forum-page_blocks Page Blocks
  482. * @subsubsection bx_forum-browse_category browse_category
  483. *
  484. * @code bx_srv('bx_forum', 'browse_category', [...]); @endcode
  485. *
  486. * Get page block with a list of items filter by some category and represented as table.
  487. *
  488. * @param $sUnitView (optional) string with unit view type.
  489. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  490. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  491. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  492. *
  493. * @see BxForumModule::serviceBrowseCategory
  494. */
  495. /**
  496. * @ref bx_forum-browse_category "browse_category"
  497. */
  498. public function serviceBrowseCategory($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $aParams = [])
  499. {
  500. if (bx_is_api()){
  501. return parent::serviceBrowseCategory($sUnitView, $bEmptyMessage, $bAjaxPaginate, []);
  502. }
  503. $sType = 'category';
  504. $iCategory = bx_process_input(bx_get('category'), BX_DATA_INT);
  505. $aCategory = $this->_oDb->getCategories(array('type' => 'by_category', 'category' => $iCategory));
  506. if(!empty($aCategory['visible_for_levels']) && !BxDolAcl::getInstance()->isMemberLevelInSet($aCategory['visible_for_levels']))
  507. return $bEmptyMessage ? MsgBox(_t('_sys_txt_access_denied')) : '';
  508. if($sUnitView != 'table') {
  509. $aParams = array_merge(['category' => $iCategory], $aParams);
  510. if($sUnitView)
  511. $aParams['unit_view'] = $sUnitView;
  512. return $this->_serviceBrowse($sType, $aParams, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  513. }
  514. return $this->_serviceBrowseTable(array(
  515. 'type' => $sType,
  516. 'where' => array('fld' => 'cat', 'val' => $iCategory, 'opr' => '='),
  517. 'empty_message' => $bEmptyMessage,
  518. 'ajax_paginate' => $bAjaxPaginate
  519. ), !isset($aParams['show_header']) || (bool)$aParams['show_header'] === true);
  520. }
  521. /**
  522. * @page service Service Calls
  523. * @section bx_forum Discussions
  524. * @subsection bx_forum-page_blocks Page Blocks
  525. * @subsubsection bx_forum-browse_keyword browse_keyword
  526. *
  527. * @code bx_srv('bx_forum', 'browse_keyword', [...]); @endcode
  528. *
  529. * Get page block with a list of items filter by some keyword and represented as table.
  530. *
  531. * @param $sUnitView (optional) string with unit view type.
  532. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  533. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  534. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  535. *
  536. * @see BxForumModule::serviceBrowseKeyword
  537. */
  538. /**
  539. * @ref bx_forum-browse_keyword "browse_keyword"
  540. */
  541. public function serviceBrowseKeyword($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
  542. {
  543. $sType = 'keyword';
  544. $sKeyword = bx_process_input(bx_get('keyword'));
  545. if($sUnitView != 'table')
  546. return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  547. return $this->_serviceBrowseTable(array(
  548. 'type' => $sType,
  549. 'where' => $this->_getSearchKeywordDescriptor('#' . $sKeyword),
  550. 'empty_message' => $bEmptyMessage,
  551. 'ajax_paginate' => $bAjaxPaginate
  552. ), $bShowHeader);
  553. }
  554. /**
  555. * @page service Service Calls
  556. * @section bx_forum Discussions
  557. * @subsection bx_forum-page_blocks Page Blocks
  558. * @subsubsection bx_forum-browse_search_results browse_search_results
  559. *
  560. * @code bx_srv('bx_forum', 'browse_search_results', [...]); @endcode
  561. *
  562. * Get page block with search results by Author(s), Category, Keyword represented as table.
  563. *
  564. * @param $sUnitView (optional) string with unit view type.
  565. * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
  566. * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
  567. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  568. *
  569. * @see BxForumModule::serviceBrowseSearchResults
  570. */
  571. /**
  572. * @ref bx_forum-browse_search_results "browse_search_results"
  573. */
  574. public function serviceBrowseSearchResults($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true)
  575. {
  576. $sType = 'search';
  577. $aAuthors = bx_process_input(bx_get('author'));
  578. $iCategory = bx_process_input(bx_get('category'), BX_DATA_INT);
  579. $sKeyword = bx_process_input(bx_get('keyword'));
  580. $aCategory = $this->_oDb->getCategories(array('type' => 'by_category', 'category' => $iCategory));
  581. if(!empty($aCategory['visible_for_levels']) && !BxDolAcl::getInstance()->isMemberLevelInSet($aCategory['visible_for_levels']))
  582. return $bEmptyMessage ? MsgBox(_t('_sys_txt_access_denied')) : '';
  583. if($sUnitView != 'table')
  584. return $this->_serviceBrowse('', $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  585. $aWhereGroupAnd = array('grp' => true, 'opr' => 'AND', 'cnds' => array());
  586. if(!empty($aAuthors) && is_array($aAuthors))
  587. $aWhereGroupAnd['cnds'][] = $this->_getSearchAuthorDescriptor($aAuthors);
  588. if(!empty($iCategory))
  589. $aWhereGroupAnd['cnds'][] = array('fld' => 'cat', 'val' => $iCategory, 'opr' => '=');
  590. if(!empty($sKeyword))
  591. $aWhereGroupAnd['cnds'][] = $this->_getSearchKeywordDescriptor($sKeyword);
  592. return $this->_serviceBrowseTable(array(
  593. 'type' => $sType,
  594. 'where' => $aWhereGroupAnd,
  595. 'empty_message' => $bEmptyMessage,
  596. 'ajax_paginate' => $bAjaxPaginate
  597. ), false);
  598. }
  599. /**
  600. * @page service Service Calls
  601. * @section bx_forum Discussions
  602. * @subsection bx_forum-other Other
  603. * @subsubsection bx_forum-get_discussions_num get_discussions_num
  604. *
  605. * @code bx_srv('bx_forum', 'get_discussions_num', [...]); @endcode
  606. *
  607. * Get number of discussions for some profile.
  608. *
  609. * @param $iProfileId (optional) profile to get discussions for, if omitted then currently logged in profile is used.
  610. * @return integer value with a number of discussions.
  611. *
  612. * @see BxForumModule::serviceGetDiscussionsNum
  613. */
  614. /**
  615. * @ref bx_forum-get_discussions_num "get_discussions_num"
  616. */
  617. public function serviceGetDiscussionsNum ($iProfileId = 0)
  618. {
  619. if (!$iProfileId)
  620. $iProfileId = bx_get_logged_profile_id();
  621. return $this->_oDb->getEntriesNumByAuthor((int)$iProfileId);
  622. }
  623. /**
  624. * @page service Service Calls
  625. * @section bx_forum Discussions
  626. * @subsection bx_forum-other Other
  627. * @subsubsection bx_forum-get_unreplied_discussions_num get_unreplied_discussions_num
  628. *
  629. * @code bx_srv('bx_forum', 'get_unreplied_discussions_num', [...]); @endcode
  630. *
  631. * Get number of unreplied discussions for some profile.
  632. *
  633. * @param $iProfileId (optional) profile to get unreplied discussions for, if omitted then currently logged is profile is used.
  634. * @return integer value with a number of discussions.
  635. *
  636. * @see BxForumModule::serviceGetUnrepliedDiscussionsNum
  637. */
  638. /**
  639. * @ref bx_forum-get_unreplied_discussions_num "get_unreplied_discussions_num"
  640. */
  641. public function serviceGetUnrepliedDiscussionsNum ($iProfileId = 0)
  642. {
  643. if (!$iProfileId)
  644. $iProfileId = bx_get_logged_profile_id();
  645. return $this->_oDb->getUnrepliedDiscussionsNum((int)$iProfileId);
  646. }
  647. /**
  648. *
  649. */
  650. /**
  651. * @page service Service Calls
  652. * @section bx_forum Discussions
  653. * @subsection bx_forum-other Other
  654. * @subsubsection bx_forum-trigger_comment_post trigger_comment_post
  655. *
  656. * @code bx_srv('bx_forum', 'trigger_comment_post', [...]); @endcode
  657. *
  658. * Update last comment time and author when new comment was added in the discussion.
  659. *
  660. * @param $iContentId integer value with content ID.
  661. * @param $iProfileId integer value with profile ID.
  662. * @param $iCommentId integer value with comment ID.
  663. * @param $iTimestamp (optional) date in UNIX Timestamp format, if omitted then current date is used.
  664. * @param $sCommentText (optional) string value with text of comment.
  665. * @return boolean value determining where the operation is successful or not.
  666. *
  667. * @see BxForumModule::serviceTriggerCommentPost
  668. */
  669. /**
  670. * @ref bx_forum-trigger_comment_post "trigger_comment_post"
  671. */
  672. public function serviceTriggerCommentPost ($iContentId, $iProfileId, $iCommentId, $iTimestamp = 0, $sCommentText = '')
  673. {
  674. $CNF = $this->_oConfig->CNF;
  675. $iContentId = (int)$iContentId;
  676. if(!$iContentId)
  677. return false;
  678. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  679. if(!$aContentInfo)
  680. return false;
  681. $oCmts = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $iContentId);
  682. if(!$oCmts)
  683. return false;
  684. if(!$iTimestamp)
  685. $iTimestamp = time();
  686. if(!$this->_oDb->updateLastCommentTimeProfile((int)$iContentId, (int)$iProfileId, $iCommentId, $iTimestamp))
  687. return false;
  688. // send notification to author
  689. if($iProfileId != $aContentInfo[$CNF['FIELD_AUTHOR']]) {
  690. $oProfile = BxDolProfile::getInstanceMagic($iProfileId);
  691. if($oProfile)
  692. sendMailTemplate('bx_forum_new_reply', 0, $aContentInfo[$CNF['FIELD_AUTHOR']], array(
  693. 'SenderDisplayName' => $oProfile->getDisplayName(),
  694. 'SenderUrl' => $oProfile->getUrl(),
  695. 'PageUrl' => $oCmts->getItemUrl($iCommentId),
  696. 'PageTitle' => $oCmts->getObjectTitle(),
  697. 'Message' => $sCommentText,
  698. ), BX_EMAIL_NOTIFY);
  699. }
  700. return true;
  701. }
  702. /**
  703. * @page service Service Calls
  704. * @section bx_forum Discussions
  705. * @subsection bx_forum-page_blocks Page Blocks
  706. * @subsubsection bx_forum-entity_author entity_author
  707. *
  708. * @code bx_srv('bx_forum', 'entity_author', [...]); @endcode
  709. *
  710. * Get page block with author.
  711. *
  712. * @param $iContentId (optional) content ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
  713. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  714. *
  715. * @see BxForumModule::serviceEntityAuthor
  716. */
  717. /**
  718. * @ref bx_forum-entity_author "entity_author"
  719. */
  720. public function serviceEntityAuthor ($iContentId = 0)
  721. {
  722. if (bx_is_api())
  723. return $this->_serviceTemplateFunc ('entryAuthor', $iContentId);
  724. return bx_srv('system', 'get_block_author', ['bx_forum', $iContentId], 'TemplServices');
  725. }
  726. /**
  727. * @page service Service Calls
  728. * @section bx_forum Discussions
  729. * @subsection bx_forum-page_blocks Page Blocks
  730. * @subsubsection bx_forum-entity_participants entity_participants
  731. *
  732. * @code bx_srv('bx_forum', 'entity_participants', [...]); @endcode
  733. *
  734. * Get page block with discussion's collaborators.
  735. *
  736. * @param $iContentId (optional) content ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
  737. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  738. *
  739. * @see BxForumModule::serviceEntityParticipants
  740. */
  741. /**
  742. * @ref bx_forum-entity_participants "entity_participants"
  743. */
  744. public function serviceEntityParticipants ($iContentId = 0)
  745. {
  746. if (!$iContentId)
  747. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  748. if (!$iContentId)
  749. return false;
  750. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  751. if (!$aContentInfo)
  752. return false;
  753. return $this->_oTemplate->entryParticipants ($aContentInfo, 5, 'right');
  754. }
  755. /**
  756. * @page service Service Calls
  757. * @section bx_forum Discussions
  758. * @subsection bx_forum-page_blocks Page Blocks
  759. * @subsubsection bx_forum-search search
  760. *
  761. * @code bx_srv('bx_forum', 'search', [...]); @endcode
  762. *
  763. * Get page block with search form.
  764. *
  765. * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  766. *
  767. * @see BxForumModule::serviceSearch
  768. */
  769. /**
  770. * @ref bx_forum-search "search"
  771. */
  772. public function serviceSearch()
  773. {
  774. $CNF = $this->_oConfig->CNF;
  775. $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_SEARCH'], $CNF['OBJECT_FORM_SEARCH_DISPLAY_FULL'], $this->_oTemplate);
  776. $oForm->initChecker();
  777. return $oForm->getCode();
  778. }
  779. public function checkAllowedSubscribe(&$aDataEntry, $isPerformAction = false)
  780. {
  781. $CNF = &$this->_oConfig->CNF;
  782. $sMsg = $this->checkAllowedView($aDataEntry);
  783. if($sMsg !== CHECK_ACTION_RESULT_ALLOWED)
  784. return $sMsg;
  785. return $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $CNF['OBJECT_CONNECTION_SUBSCRIBERS'], false, false);
  786. }
  787. public function checkAllowedUnsubscribe(&$aDataEntry, $isPerformAction = false)
  788. {
  789. $CNF = &$this->_oConfig->CNF;
  790. return $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $CNF['OBJECT_CONNECTION_SUBSCRIBERS'], false, true);
  791. }
  792. public function checkAllowedStickAnyEntry($aDataEntry, $isPerformAction = false)
  793. {
  794. $CNF = &$this->_oConfig->CNF;
  795. if((int)$aDataEntry[$CNF['FIELD_STICK']] != 0)
  796. return false;
  797. return $this->_checkAllowedAction('stick any entry', $aDataEntry, $isPerformAction);
  798. }
  799. public function checkAllowedUnstickAnyEntry($aDataEntry, $isPerformAction = false)
  800. {
  801. $CNF = $this->_oConfig->CNF;
  802. if((int)$aDataEntry[$CNF['FIELD_STICK']] != 1)
  803. return false;
  804. return $this->_checkAllowedAction('stick any entry', $aDataEntry, $isPerformAction);
  805. }
  806. public function checkAllowedResolveAnyEntry($aDataEntry, $isPerformAction = false)
  807. {
  808. $CNF = &$this->_oConfig->CNF;
  809. if((int)$aDataEntry[$CNF['FIELD_RESOLVABLE']] != 1 || (int)$aDataEntry[$CNF['FIELD_RESOLVE']] != 0)
  810. return false;
  811. if($aDataEntry[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
  812. return CHECK_ACTION_RESULT_ALLOWED;
  813. return $this->_checkAllowedAction('resolve any entry', $aDataEntry, $isPerformAction);
  814. }
  815. public function checkAllowedUnresolveAnyEntry($aDataEntry, $isPerformAction = false)
  816. {
  817. $CNF = $this->_oConfig->CNF;
  818. if((int)$aDataEntry[$CNF['FIELD_RESOLVABLE']] != 1 || (int)$aDataEntry[$CNF['FIELD_RESOLVE']] != 1)
  819. return false;
  820. if($aDataEntry[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
  821. return CHECK_ACTION_RESULT_ALLOWED;
  822. return $this->_checkAllowedAction('resolve any entry', $aDataEntry, $isPerformAction);
  823. }
  824. public function checkAllowedLockAnyEntry($aDataEntry, $isPerformAction = false)
  825. {
  826. $CNF = $this->_oConfig->CNF;
  827. if((int)$aDataEntry[$CNF['FIELD_LOCK']] != 0)
  828. return false;
  829. return $this->_checkAllowedAction('lock any entry', $aDataEntry, $isPerformAction);
  830. }
  831. public function checkAllowedUnlockAnyEntry($aDataEntry, $isPerformAction = false)
  832. {
  833. $CNF = $this->_oConfig->CNF;
  834. if((int)$aDataEntry[$CNF['FIELD_LOCK']] != 1)
  835. return false;
  836. return $this->_checkAllowedAction('lock any entry', $aDataEntry, $isPerformAction);
  837. }
  838. public function checkAllowedHideAnyEntry($aDataEntry, $isPerformAction = false)
  839. {
  840. $CNF = $this->_oConfig->CNF;
  841. if($aDataEntry[$CNF['FIELD_STATUS_ADMIN']] == 'hidden')
  842. return false;
  843. return $this->_checkAllowedAction('hide any entry', $aDataEntry, $isPerformAction);
  844. }
  845. public function checkAllowedUnhideAnyEntry($aDataEntry, $isPerformAction = false)
  846. {
  847. $CNF = &$this->_oConfig->CNF;
  848. if($aDataEntry[$CNF['FIELD_STATUS_ADMIN']] != 'hidden')
  849. return false;
  850. return $this->_checkAllowedAction('hide any entry', $aDataEntry, $isPerformAction);
  851. }
  852. protected function _checkAllowedConnect (&$aDataEntry, $isPerformAction, $sObjConnection, $isMutual, $isInvertResult)
  853. {
  854. $CNF = &$this->_oConfig->CNF;
  855. if(!$this->_iProfileId)
  856. return _t('_sys_txt_access_denied');
  857. $isConnected = BxDolConnection::getObjectInstance($sObjConnection)->isConnected($this->_iProfileId, $aDataEntry[$CNF['FIELD_ID']], $isMutual);
  858. if($isInvertResult)
  859. $isConnected = !$isConnected;
  860. return $isConnected ? _t('_sys_txt_access_denied') : CHECK_ACTION_RESULT_ALLOWED;
  861. }
  862. /**
  863. * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
  864. */
  865. protected function _checkAllowedAction($sAction, $aDataEntry, $isPerformAction = false)
  866. {
  867. if($this->_isModerator($isPerformAction))
  868. return CHECK_ACTION_RESULT_ALLOWED;
  869. $aCheck = checkActionModule($this->_iProfileId, $sAction, $this->getName(), $isPerformAction);
  870. if($aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED)
  871. return CHECK_ACTION_RESULT_ALLOWED;
  872. return _t('_sys_txt_access_denied');
  873. }
  874. protected function _serviceBrowseTable($aParams, $isDisplayHeader = true)
  875. {
  876. $sGrid = $this->_oConfig->CNF['OBJECT_GRID'];
  877. if(!empty($aParams['grid'])) {
  878. $sGrid = $aParams['grid'];
  879. unset($aParams['grid']);
  880. }
  881. $oGrid = BxDolGrid::getObjectInstance($sGrid);
  882. if(!$oGrid)
  883. return false;
  884. $oGrid->setBrowseParams($aParams);
  885. $this->_oTemplate->addJsTranslation(array('_sys_grid_search'));
  886. $this->_oTemplate->addCss(array('grid_tools.css'));
  887. return $oGrid->getCode($isDisplayHeader);
  888. }
  889. protected function _getSearchAuthorDescriptor($aAutor)
  890. {
  891. return array('grp' => true, 'opr' => 'OR', 'cnds' => array(
  892. array('fld' => 'author', 'val' => $aAutor, 'opr' => 'IN'),
  893. array('fld' => 'author_comment', 'val' => $aAutor, 'opr' => 'IN'),
  894. ));
  895. }
  896. protected function _getSearchKeywordDescriptor($sKeyword)
  897. {
  898. return array('grp' => true, 'opr' => 'OR', 'cnds' => array(
  899. array('fld' => 'title', 'val' => $sKeyword, 'opr' => 'LIKE'),
  900. array('fld' => 'text', 'val' => $sKeyword, 'opr' => 'LIKE'),
  901. array('fld' => 'text_comments', 'val' => $sKeyword, 'opr' => 'LIKE')
  902. ));
  903. }
  904. }
  905. /** @} */