BxBaseModTextModule.php 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  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 BaseText Base classes for text modules
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. define('BX_BASE_MOD_TEXT_STATUS_ACTIVE', 'active');
  12. define('BX_BASE_MOD_TEXT_STATUS_HIDDEN', 'hidden');
  13. define('BX_BASE_MOD_TEXT_STATUS_AWAITING', 'awaiting');
  14. /**
  15. * Saved for backward compatibility.
  16. * Can be removed in future releases of UNA 13.
  17. */
  18. define('BX_BASE_MOD_TEXT_STATUS_PENDING', 'pending');
  19. /**
  20. * Base module class for text based modules
  21. */
  22. class BxBaseModTextModule extends BxBaseModGeneralModule implements iBxDolContentInfoService
  23. {
  24. function __construct(&$aModule)
  25. {
  26. parent::__construct($aModule);
  27. }
  28. // ====== ACTIONS METHODS
  29. public function actionFileEmbedVideo($iFileId)
  30. {
  31. $this->_oTemplate->embedVideo($iFileId);
  32. }
  33. public function actionFileEmbedSound($iFileId)
  34. {
  35. $this->_oTemplate->embedSound($iFileId);
  36. }
  37. // ====== SERVICE METHODS
  38. public function serviceGetSafeServices()
  39. {
  40. $a = parent::serviceGetSafeServices();
  41. return array_merge($a, array (
  42. 'GetBlockPollAnswers' => '',
  43. 'GetBlockPollResults' => '',
  44. 'GetMenuAddonManageToolsProfileStats' => '',
  45. 'BrowsePublic' => '',
  46. 'BrowsePopular' => '',
  47. 'BrowseTop' => '',
  48. 'BrowseUpdated' => '',
  49. 'BrowseAuthor' => '',
  50. 'CategoriesMultiListContext' => ''
  51. ));
  52. }
  53. public function serviceManageTools($sType = 'common')
  54. {
  55. $this->_oTemplate->addJs(['modules/base/text/js/|manage_tools.js']);
  56. return parent::serviceManageTools($sType);
  57. }
  58. /**
  59. * @page service Service Calls
  60. * @section bx_base_text Base Text
  61. * @subsection bx_base_general-page_blocks Page Blocks
  62. * @subsubsection bx_base_general-categories_multi_list_context categories_multi_list_context
  63. *
  64. * @code bx_srv('bx_posts', 'categories_multi_list_context', [...]); @endcode
  65. *
  66. * Display multi-categorories block with number of posts in each category for current context
  67. * @param $bDisplayEmptyCats display empty categories
  68. *
  69. * @see BxBaseModGeneralModule::serviceCategoriesMultiListContext
  70. */
  71. /**
  72. * @ref bx_base_general-categories_multi_list_context "categories_multi_list_context"
  73. */
  74. public function serviceCategoriesMultiListContext($iProfileId = 0, $bDisplayEmptyCats = true)
  75. {
  76. if ($iProfileId == 0)
  77. $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
  78. $oCategories = BxDolCategories::getInstance();
  79. $aCats = $oCategories->getData([
  80. 'type' => 'by_module&context_with_num',
  81. 'module' => $this->getName(),
  82. 'context_id' => $iProfileId
  83. ]
  84. );
  85. $aVars = array('bx_repeat:cats' => array());
  86. foreach ($aCats as $oCat) {
  87. $sValue = $oCat['value'];
  88. $iNum = $oCat['num'];
  89. $aVars['bx_repeat:cats'][] = array(
  90. 'url' => $oCategories->getUrl($this->getName(), $sValue, '&context_id=' . $iProfileId),
  91. 'name' => _t($sValue),
  92. 'value' => $sValue,
  93. 'num' => $iNum,
  94. );
  95. }
  96. if (!$aVars['bx_repeat:cats'])
  97. return '';
  98. return $this->_oTemplate->parseHtmlByName('category_list_multi.html', $aVars);
  99. }
  100. /**
  101. * Display media EXIF information.
  102. * @param $iMediaId media ID, if it's omitted then it's taken from 'id' GET variable.
  103. * @return HTML string with EXIF info. On error empty string is returned.
  104. */
  105. public function serviceMediaExif ($iMediaId = 0)
  106. {
  107. $CNF = &$this->_oConfig->CNF;
  108. return $this->_serviceTemplateFunc ('mediaExif', $iMediaId, $CNF['FUNCTION_FOR_GET_ITEM_INFO']);
  109. }
  110. public function serviceGetThumb ($iContentId, $sTranscoder = '')
  111. {
  112. $CNF = &$this->_oConfig->CNF;
  113. if(bx_is_api()){
  114. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  115. if (isset($CNF['FIELD_THUMB']))
  116. return bx_api_get_image($CNF['OBJECT_STORAGE'], $aContentInfo[$CNF['FIELD_THUMB']]);
  117. }
  118. if(empty($sTranscoder) && !empty($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY']))
  119. $sTranscoder = $CNF['OBJECT_IMAGES_TRANSCODER_GALLERY'];
  120. $mixedResult = $this->_getFieldValueThumb('FIELD_THUMB', $iContentId, $sTranscoder);
  121. return $mixedResult !== false ? $mixedResult : '';
  122. }
  123. public function serviceGetMenuAddonManageTools()
  124. {
  125. $CNF = &$this->_oConfig->CNF;
  126. $iNumTotal = $this->_oDb->getEntriesNumByParams();
  127. $iNum1 = $this->_oDb->getEntriesNumByParams([
  128. [
  129. 'key' => $CNF['FIELD_STATUS'],
  130. 'value' => 'hidden',
  131. 'operator' => '='
  132. ]
  133. ]);
  134. $iNum2 = 0;
  135. if (isset($CNF['OBJECT_REPORTS'])){
  136. $iNum2 = $this->_oDb->getEntriesNumByParams([
  137. [
  138. 'key' => 'reports',
  139. 'value' => '0',
  140. 'operator' => '>'
  141. ]
  142. ]);
  143. }
  144. return array('counter1_value' => $iNum1, 'counter2_value' => $iNum2, 'counter3_value' => $iNumTotal );
  145. }
  146. /**
  147. * @page service Service Calls
  148. * @section bx_base_text Base Text
  149. * @subsection bx_base_text-other Other
  150. * @subsubsection bx_base_text-get_menu_addon_manage_tools_profile_stats get_menu_addon_manage_tools_profile_stats
  151. *
  152. * @code bx_srv('bx_posts', 'get_menu_addon_manage_tools_profile_stats', []); @endcode
  153. *
  154. * Get number of posts for currently logged in user
  155. *
  156. * @see BxBaseModTextModule::serviceGetMenuAddonManageToolsProfileStats
  157. */
  158. /**
  159. * @ref bx_base_text-get_menu_addon_manage_tools_profile_stats "get_menu_addon_manage_tools_profile_stats"
  160. */
  161. public function serviceGetMenuAddonManageToolsProfileStats($iProfileId = 0)
  162. {
  163. if(!$iProfileId)
  164. $iProfileId = bx_get_logged_profile_id();
  165. bx_import('SearchResult', $this->_aModule);
  166. $sClass = $this->_aModule['class_prefix'] . 'SearchResult';
  167. $o = new $sClass();
  168. $o->fillFilters([
  169. 'author' => $iProfileId
  170. ]);
  171. $o->unsetPaginate();
  172. return $o->getNum();
  173. }
  174. /**
  175. * @page service Service Calls
  176. * @section bx_base_text Base Text
  177. * @subsection bx_base_text-browse Browse
  178. * @subsubsection bx_base_text-browse_public browse_public
  179. *
  180. * @code bx_srv('bx_posts', 'browse_public', [...]); @endcode
  181. *
  182. * Display public posts
  183. * @param $sUnitView unit view, such as: full, extended, gallery, showcase
  184. * @param $bEmptyMessage display or not "empty" message when there is no content
  185. * @param $bAjaxPaginate use AJAX paginate or not
  186. *
  187. * @see BxBaseModTextModule::serviceBrowsePublic
  188. */
  189. /**
  190. * @ref bx_base_text-browse_public "browse_public"
  191. */
  192. public function serviceBrowsePublic ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true)
  193. {
  194. return $this->_serviceBrowse ('public', $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  195. }
  196. /**
  197. * @page service Service Calls
  198. * @section bx_base_text Base Text
  199. * @subsection bx_base_text-browse Browse
  200. * @subsubsection bx_base_text-browse_popular browse_popular
  201. *
  202. * @code bx_srv('bx_posts', 'browse_popular', [...]); @endcode
  203. *
  204. * Display popular posts
  205. * @param $sUnitView unit view, such as: full, extended, gallery, showcase
  206. * @param $bEmptyMessage display or not "empty" message when there is no content
  207. * @param $bAjaxPaginate use AJAX paginate or not
  208. *
  209. * @see BxBaseModTextModule::serviceBrowsePopular
  210. */
  211. /**
  212. * @ref bx_base_text-browse_popular "browse_popular"
  213. */
  214. public function serviceBrowsePopular ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true)
  215. {
  216. return $this->_serviceBrowse ('popular', $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  217. }
  218. /**
  219. * @page service Service Calls
  220. * @section bx_base_text Base Text
  221. * @subsection bx_base_text-browse Browse
  222. * @subsubsection bx_base_text-browse_top browse_top
  223. *
  224. * @code bx_srv('bx_posts', 'browse_top', [...]); @endcode
  225. *
  226. * Display top posts
  227. * @param $sUnitView unit view, such as: full, extended, gallery, showcase
  228. * @param $bEmptyMessage display or not "empty" message when there is no content
  229. * @param $bAjaxPaginate use AJAX paginate or not
  230. *
  231. * @see BxBaseModTextModule::serviceBrowseTop
  232. */
  233. /**
  234. * @ref bx_base_text-browse_top "browse_top"
  235. */
  236. public function serviceBrowseTop ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true)
  237. {
  238. return $this->_serviceBrowse ('top', $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  239. }
  240. /**
  241. * @page service Service Calls
  242. * @section bx_base_text Base Text
  243. * @subsection bx_base_text-browse Browse
  244. * @subsubsection bx_base_text-browse_updated browse_updated
  245. *
  246. * @code bx_srv('bx_posts', 'browse_updated', [...]); @endcode
  247. *
  248. * Display recently updated posts
  249. * @param $sUnitView unit view, such as: full, extended, gallery, showcase
  250. * @param $bEmptyMessage display or not "empty" message when there is no content
  251. * @param $bAjaxPaginate use AJAX paginate or not
  252. *
  253. * @see BxBaseModTextModule::serviceBrowseUpdated
  254. */
  255. /**
  256. * @ref bx_base_text-browse_updated "browse_updated"
  257. */
  258. public function serviceBrowseUpdated ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true)
  259. {
  260. return $this->_serviceBrowse ('updated', $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
  261. }
  262. /**
  263. * @page service Service Calls
  264. * @section bx_base_text Base Text
  265. * @subsection bx_base_text-browse Browse
  266. * @subsubsection bx_base_text-browse_author browse_author
  267. *
  268. * @code bx_srv('bx_posts', 'browse_author', [...]); @endcode
  269. *
  270. * Display posts of specified author
  271. * @param $iProfileId profile ID
  272. * @param $aParams additional params, see BxBaseModGeneralModule::serviceBrowse
  273. *
  274. * @see BxBaseModTextModule::serviceBrowseAuthor
  275. */
  276. /**
  277. * @ref bx_base_text-browse_author "browse_author"
  278. */
  279. public function serviceBrowseAuthor ($iProfileId = 0, $aParams = array())
  280. {
  281. return $this->_serviceBrowseWithParam ('author', 'profile_id', $iProfileId, $aParams);
  282. }
  283. /**
  284. * @page service Service Calls
  285. * @section bx_base_text Base Text
  286. * @subsection bx_base_text-page_blocks Page Blocks
  287. * @subsubsection bx_base_text-entity_author entity_author
  288. *
  289. * @code bx_srv('bx_posts', 'entity_author', [...]); @endcode
  290. *
  291. * Display author block for the specified post
  292. * @param $iContentId content ID
  293. *
  294. * @see BxBaseModTextModule::serviceEntityAuthor
  295. */
  296. /**
  297. * @ref bx_base_text-entity_author "entity_author"
  298. */
  299. public function serviceEntityAuthor ($iContentId = 0)
  300. {
  301. return $this->_serviceTemplateFunc ('entryAuthor', $iContentId);
  302. }
  303. /**
  304. * @page service Service Calls
  305. * @section bx_base_text Base Text
  306. * @subsection bx_base_text-page_blocks Page Blocks
  307. * @subsubsection bx_base_text-entity_breadcrumb entity_breadcrumb
  308. *
  309. * @code bx_srv('bx_forum', 'entity_breadcrumb', [...]); @endcode
  310. *
  311. * Display breadcrumb for the specified post
  312. * @param $iContentId content ID
  313. *
  314. * @see BxBaseModTextModule::serviceEntityBreadcrumb
  315. */
  316. /**
  317. * @ref bx_base_text-entity_breadcrumb "entity_breadcrumb"
  318. */
  319. public function serviceEntityBreadcrumb ($iContentId = 0)
  320. {
  321. return $this->_serviceTemplateFunc ('entryBreadcrumb', $iContentId);
  322. }
  323. /**
  324. * Delete all content by profile
  325. * @param $iProfileId profile id
  326. * @return number of deleted items
  327. */
  328. public function serviceDeleteEntitiesByAuthor ($iProfileId)
  329. {
  330. $a = $this->_oDb->getEntriesByAuthor((int)$iProfileId);
  331. if (!$a)
  332. return 0;
  333. $iCount = 0;
  334. foreach ($a as $aContentInfo)
  335. $iCount += ('' == $this->serviceDeleteEntity($aContentInfo[$this->_oConfig->CNF['FIELD_ID']]) ? 1 : 0);
  336. return $iCount;
  337. }
  338. // ====== PERMISSION METHODS
  339. /**
  340. * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
  341. */
  342. public function checkAllowedSetThumb ($iContentId = 0)
  343. {
  344. // check ACL
  345. $aCheck = checkActionModule($this->_iProfileId, 'set thumb', $this->getName(), false);
  346. if ($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
  347. return $aCheck[CHECK_ACTION_MESSAGE];
  348. return CHECK_ACTION_RESULT_ALLOWED;
  349. }
  350. public function isAllowedApprove($mixedContent, $isPerformAction = false)
  351. {
  352. return $this->checkAllowedApprove($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
  353. }
  354. public function checkAllowedApprove($mixedContent, $isPerformAction = false)
  355. {
  356. $CNF = &$this->_oConfig->CNF;
  357. $sTxtError = '_sys_txt_access_denied';
  358. $iProfileId = bx_get_logged_profile_id();
  359. if(!is_array($mixedContent))
  360. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  361. if(empty($mixedContent) || !is_array($mixedContent))
  362. return _t($sTxtError);
  363. if(!isset($CNF['FIELD_STATUS_ADMIN']) || $mixedContent[$CNF['FIELD_STATUS_ADMIN']] != BX_BASE_MOD_GENERAL_STATUS_PENDING)
  364. return _t($sTxtError);
  365. if($this->_isModerator())
  366. return CHECK_ACTION_RESULT_ALLOWED;
  367. if(!empty($CNF['FIELD_ALLOW_VIEW_TO']) && (int)$mixedContent[$CNF['FIELD_ALLOW_VIEW_TO']] < 0) {
  368. $iContextProfileId = abs((int)$mixedContent[$CNF['FIELD_ALLOW_VIEW_TO']]);
  369. $oContextProfile = BxDolProfile::getInstance($iContextProfileId);
  370. $aAdmins = bx_srv($oContextProfile->getModule(), 'get_admins_to_manage_content', [$iContextProfileId]);
  371. if(!empty($aAdmins) && in_array($iProfileId, $aAdmins))
  372. return CHECK_ACTION_RESULT_ALLOWED;
  373. }
  374. return _t($sTxtError);
  375. }
  376. // ====== COMMON METHODS
  377. public function deleteAttachLinks($iId)
  378. {
  379. if(!$this->_oConfig->isAttachLinks())
  380. return;
  381. $CNF = &$this->_oConfig->CNF;
  382. $aLinks = $this->_oDb->getLinks($iId);
  383. if(empty($aLinks) || !is_array($aLinks))
  384. return;
  385. $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_PHOTOS']);
  386. foreach($aLinks as $aLink)
  387. if(!empty($aLink['media_id']))
  388. $oStorage->deleteFile($aLink['media_id']);
  389. $this->_oDb->deleteLinks($iId);
  390. }
  391. public function deleteAttachLinksUnused($iProfileId)
  392. {
  393. if(!$this->_oConfig->isAttachLinks())
  394. return;
  395. $CNF = &$this->_oConfig->CNF;
  396. $aLinks = $this->_oDb->getUnusedLinks($iProfileId);
  397. if(empty($aLinks) || !is_array($aLinks))
  398. return;
  399. $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_PHOTOS']);
  400. foreach($aLinks as $aLink)
  401. if(!empty($aLink['media_id']))
  402. $oStorage->deleteFile($aLink['media_id']);
  403. $this->_oDb->deleteUnusedLinks($iProfileId);
  404. }
  405. public function onApprove($mixedContent)
  406. {
  407. $CNF = &$this->_oConfig->CNF;
  408. if(!is_array($mixedContent))
  409. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  410. $this->alertAfterApprove($mixedContent);
  411. $this->onPublished($mixedContent[$CNF['FIELD_ID']]);
  412. }
  413. public function alertAfterAdd($aContentInfo)
  414. {
  415. $CNF = &$this->_oConfig->CNF;
  416. $iId = (int)$aContentInfo[$CNF['FIELD_ID']];
  417. $iAuthorId = (int)$aContentInfo[$CNF['FIELD_AUTHOR']];
  418. $sAction = 'added';
  419. if(isset($CNF['FIELD_STATUS']) && isset($aContentInfo[$CNF['FIELD_STATUS']]) && $aContentInfo[$CNF['FIELD_STATUS']] == BX_BASE_MOD_TEXT_STATUS_AWAITING)
  420. $sAction = 'deferred';
  421. else if(isset($CNF['FIELD_STATUS_ADMIN']) && isset($aContentInfo[$CNF['FIELD_STATUS_ADMIN']]) && $aContentInfo[$CNF['FIELD_STATUS_ADMIN']] == BX_BASE_MOD_GENERAL_STATUS_PENDING)
  422. $sAction = 'deferred';
  423. $aParams = $this->_alertParamsAdd($aContentInfo);
  424. /**
  425. * @hooks
  426. * @hookdef hook-system-prepare_alert_params 'system', 'prepare_alert_params' - hook to override alert (hook) params
  427. * - $unit_name - equals `system`
  428. * - $action - equals `prepare_alert_params`
  429. * - $object_id - not used
  430. * - $sender_id - not used
  431. * - $extra_params - array of additional params with the following array keys:
  432. * - `unit` - [string] unit name
  433. * - `action` - [string] by ref, action, can be overridden in hook processing
  434. * - `object_id` - [int] by ref, object id, can be overridden in hook processing
  435. * - `sender_id` - [int] by ref, action performer profile id, can be overridden in hook processing
  436. * - `extras` - [array] by ref, extra params array as key&value pairs, can be overridden in hook processing
  437. * @hook @ref hook-system-prepare_alert_params
  438. */
  439. bx_alert('system', 'prepare_alert_params', 0, 0, [
  440. 'unit'=> $this->getName(),
  441. 'action' => &$sAction,
  442. 'object_id' => &$iId,
  443. 'sender_id' => &$iAuthorId,
  444. 'extras' => &$aParams
  445. ]);
  446. /**
  447. * @hooks
  448. * @hookdef hook-bx_base_text-added '{module_name}', 'added' - hook after content was added (published)
  449. * - $unit_name - module name
  450. * - $action - equals `added`
  451. * - $object_id - content id
  452. * - $sender_id - content author profile id
  453. * - $extra_params - array of additional params with the following array keys:
  454. * - `status` - [string] content status
  455. * - `status_admin` - [string] content admin status
  456. * - `privacy_view` - [int] or [string] privacy for view content action, @see BxDolPrivacy
  457. * - `cf` - [int] content's audience filter value
  458. * @hook @ref hook-bx_base_text-added
  459. */
  460. /**
  461. * @hooks
  462. * @hookdef hook-bx_base_text-deferred '{module_name}', 'deferred' - hook after content was added with pending approval status
  463. * It's equivalent to @ref hook-bx_base_text-added
  464. * @hook @ref hook-bx_base_text-deferred
  465. */
  466. bx_alert($this->getName(), $sAction, $iId, $iAuthorId, $aParams);
  467. $this->_processModerationNotifications($aContentInfo);
  468. }
  469. public function alertAfterEdit($aContentInfo)
  470. {
  471. $CNF = &$this->_oConfig->CNF;
  472. $iId = (int)$aContentInfo[$CNF['FIELD_ID']];
  473. $aParams = $this->_alertParamsEdit($aContentInfo);
  474. /**
  475. * @hooks
  476. * @hookdef hook-bx_base_text-edited '{module_name}', 'edited' - hook after content was changed
  477. * It's equivalent to @ref hook-bx_base_text-added
  478. * @hook @ref hook-bx_base_text-edited
  479. */
  480. bx_alert($this->getName(), 'edited', $iId, false, $aParams);
  481. }
  482. /**
  483. * Get array of params to be passed in Add/Edit Alert.
  484. */
  485. protected function _alertParams($aContentInfo)
  486. {
  487. $aParams = parent::_alertParams($aContentInfo);
  488. $CNF = &$this->_oConfig->CNF;
  489. if(!empty($CNF['FIELD_STATUS']) && isset($aContentInfo[$CNF['FIELD_STATUS']]))
  490. $aParams['status'] = $aContentInfo[$CNF['FIELD_STATUS']];
  491. if(!empty($CNF['FIELD_STATUS_ADMIN']) && isset($aContentInfo[$CNF['FIELD_STATUS_ADMIN']]))
  492. $aParams['status_admin'] = $aContentInfo[$CNF['FIELD_STATUS_ADMIN']];
  493. if(!empty($CNF['FIELD_ALLOW_VIEW_TO']) && isset($aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]))
  494. $aParams['privacy_view'] = $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']];
  495. if(!empty($CNF['FIELD_CF']) && isset($aContentInfo[$CNF['FIELD_CF']]))
  496. $aParams['cf'] = $aContentInfo[$CNF['FIELD_CF']];
  497. return $aParams;
  498. }
  499. protected function _alertParamsAdd($aContentInfo)
  500. {
  501. $aParams = $this->_alertParams($aContentInfo);
  502. $CNF = &$this->_oConfig->CNF;
  503. if(!empty($CNF['OBJECT_METATAGS']))
  504. $aParams['timeline_group'] = $this->_getAlertParamTimelineGroup($aContentInfo);
  505. return $aParams;
  506. }
  507. protected function _alertParamsEdit($aContentInfo)
  508. {
  509. $aParams = $this->_alertParams($aContentInfo);
  510. $CNF = &$this->_oConfig->CNF;
  511. if(!empty($CNF['OBJECT_METATAGS']))
  512. $aParams['timeline_group'] = $this->_getAlertParamTimelineGroup($aContentInfo);
  513. return $aParams;
  514. }
  515. protected function _getAlertParamTimelineGroup($aContentInfo)
  516. {
  517. $CNF = &$this->_oConfig->CNF;
  518. return [
  519. 'by' => $this->getName() . '_' . abs((int)$aContentInfo[$CNF['FIELD_AUTHOR']]) . '_' . (int)$aContentInfo[$CNF['FIELD_ID']],
  520. 'field' => 'owner_id'
  521. ];
  522. }
  523. public function getEntryImageData($aContentInfo, $sField = 'FIELD_THUMB', $aTranscoders = array())
  524. {
  525. $CNF = &$this->_oConfig->CNF;
  526. $mResult = parent::getEntryImageData($aContentInfo, $sField, $aTranscoders);
  527. if ($mResult === false && isset($CNF['PARAM_USE_GALERY_AS_COVER']) && getParam($CNF['PARAM_USE_GALERY_AS_COVER']) == 'on'){
  528. if(!empty($CNF['OBJECT_STORAGE_PHOTOS']) && !empty($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW_PHOTOS'])){
  529. $sStorage = $CNF['OBJECT_STORAGE_PHOTOS'];
  530. $oStorage = BxDolStorage::getObjectInstance($sStorage);
  531. $aGhostFiles = $oStorage->getGhosts ($this->serviceGetContentOwnerProfileId($aContentInfo[$CNF['FIELD_ID']]), $aContentInfo[$CNF['FIELD_ID']]);
  532. if ($aGhostFiles){
  533. foreach ($aGhostFiles as $k => $a) {
  534. return array('id' => $a['id'], 'transcoder' => $CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW_PHOTOS']);
  535. }
  536. }
  537. }
  538. }
  539. return $mResult;
  540. }
  541. public function decodeDataAPI($aData, $aParams = [])
  542. {
  543. $CNF = &$this->_oConfig->CNF;
  544. $sModule = $this->getName();
  545. $iId = (int)$aData[$CNF['FIELD_ID']];
  546. $sSummary = '';
  547. if(!empty($CNF['PARAM_CHARS_SUMMARY_PLAIN'])) {
  548. $sSummary = $this->_oTemplate->getText($aData);
  549. $sSummary = BxTemplFunctions::getInstance()->getStringWithLimitedLength(strip_tags($sSummary), (int)getParam($CNF['PARAM_CHARS_SUMMARY_PLAIN']));
  550. }
  551. $aResult = [
  552. 'id' => $iId,
  553. 'module' => $sModule,
  554. 'module_title' => _t($CNF['T']['txt_sample_single']),
  555. 'added' => $aData[$CNF['FIELD_ADDED']],
  556. 'author' => $aData[$CNF['FIELD_AUTHOR']],
  557. 'author_data' => !empty($aData[$CNF['FIELD_AUTHOR']]) ? BxDolProfile::getData($aData[$CNF['FIELD_AUTHOR']]) : '',
  558. 'title' => $aData[$CNF['FIELD_TITLE']],
  559. 'url' => bx_api_get_relative_url($this->serviceGetLink($iId)),
  560. 'image' => $this->serviceGetThumb($iId),
  561. 'summary_plain' => $sSummary
  562. ];
  563. if(isset($aParams['extended']) && $aParams['extended'] === true)
  564. $aResult['text'] = $aData[$CNF['FIELD_TEXT']];
  565. if(!empty($CNF['OBJECT_MENU_SNIPPET_META']) && ($oMetaMenu = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_SNIPPET_META'], $this->_oTemplate)) !== false) {
  566. $oMetaMenu->setContentId($iId);
  567. $aResult['meta'] = $oMetaMenu->getCodeAPI();
  568. }
  569. return $aResult;
  570. }
  571. // ====== PROTECTED METHODS
  572. protected function _getImagesForTimelinePost($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
  573. {
  574. $CNF = &$this->_oConfig->CNF;
  575. $aResults = parent::_getImagesForTimelinePost($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  576. if (bx_is_api())
  577. return $aResults;
  578. if (count($aResults) == 0 && isset($CNF['PARAM_USE_GALERY_AS_COVER']) && getParam($CNF['PARAM_USE_GALERY_AS_COVER']) == 'on'){
  579. $aResults = $this->_getImagesForTimelinePostAttachInner($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  580. if (count($aResults) > 1){
  581. $aResults = array_slice($aResults, 0, 1);
  582. }
  583. }
  584. return $aResults;
  585. }
  586. protected function _getImagesForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
  587. {
  588. $CNF = &$this->_oConfig->CNF;
  589. $aTmp = parent::_getImagesForTimelinePost($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  590. $aResults = $this->_getImagesForTimelinePostAttachInner($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  591. if (bx_is_api())
  592. return $aResults;
  593. if (count($aTmp) == 0 && count($aResults) > 0 && isset($CNF['PARAM_USE_GALERY_AS_COVER']) && getParam($CNF['PARAM_USE_GALERY_AS_COVER']) == 'on'){
  594. $aResults = array_slice($aResults, 1);
  595. }
  596. return $aResults;
  597. }
  598. protected function _getImagesForTimelinePostAttachInner($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
  599. {
  600. $CNF = &$this->_oConfig->CNF;
  601. $aResults = parent::_getImagesForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  602. if(!$this->_oConfig->isAttachmentsInTimeline() || empty($CNF['OBJECT_STORAGE_PHOTOS']) || empty($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY_PHOTOS']))
  603. return $aResults;
  604. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  605. $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_PHOTOS']);
  606. $aGhostFiles = $oStorage->getGhosts($this->serviceGetContentOwnerProfileId($iContentId), $iContentId);
  607. if(!$aGhostFiles)
  608. return [];
  609. $oTranscoderSm = false;
  610. if(!empty($CNF['OBJECT_IMAGES_TRANSCODER_MINIATURE_PHOTOS']))
  611. $oTranscoderSm = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_MINIATURE_PHOTOS']);
  612. $oTranscoderMd = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY_PHOTOS']);
  613. $oTranscoderXl = false;
  614. if(!empty($CNF['OBJECT_IMAGES_TRANSCODER_VIEW_PHOTOS']))
  615. $oTranscoderXl = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_VIEW_PHOTOS']);
  616. foreach($aGhostFiles as $k => $a) {
  617. $sPhotoSrcMd = $oTranscoderMd->getFileUrl($a['id']);
  618. if(empty($sPhotoSrcMd))
  619. continue;
  620. $sPhotoSrcSm = $oTranscoderSm !== false ? $oTranscoderSm->getFileUrl($a['id']) : '';
  621. if(!$sPhotoSrcSm)
  622. $sPhotoSrcSm = $sPhotoSrcMd;
  623. $sPhotoSrcXl = $oTranscoderXl !== false ? $oTranscoderXl->getFileUrl($a['id']) : $oStorage->getFileUrlById($a['id']);
  624. if(!$sPhotoSrcXl)
  625. $sPhotoSrcXl = $sPhotoSrcMd;
  626. if (bx_is_api()){
  627. $aResults[] = bx_api_get_image($CNF['OBJECT_STORAGE_PHOTOS'], (int)$a['id']);
  628. }
  629. else{
  630. $aResults[] = [
  631. 'id' => $a['id'],
  632. 'src' => $sPhotoSrcMd,
  633. 'src_small' => $sPhotoSrcSm,
  634. 'src_medium' => $sPhotoSrcMd,
  635. 'src_orig' => $sPhotoSrcXl,
  636. ];
  637. }
  638. }
  639. return $aResults;
  640. }
  641. protected function _getVideosForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
  642. {
  643. $CNF = &$this->_oConfig->CNF;
  644. $aResults = parent::_getVideosForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  645. if(!$this->_oConfig->isAttachmentsInTimeline() || empty($CNF['OBJECT_STORAGE_VIDEOS']) || empty($CNF['OBJECT_VIDEOS_TRANSCODERS']))
  646. return $aResults;
  647. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  648. $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_VIDEOS']);
  649. $aGhostFiles = $oStorage->getGhosts($this->serviceGetContentOwnerProfileId($iContentId), $iContentId);
  650. if(!$aGhostFiles)
  651. return array();
  652. $oTcPoster = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['poster']);
  653. $oTcMp4 = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4']);
  654. $oTcMp4Hd = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4_hd']);
  655. if(!$oTcPoster || !$oTcMp4 || !$oTcMp4Hd)
  656. return array();
  657. $aResults = array();
  658. foreach ($aGhostFiles as $k => $a) {
  659. $sVideoUrl = $oStorage->getFileUrlById($a['id']);
  660. $aVideoFile = $oStorage->getFile($a['id']);
  661. $sVideoUrlHd = '';
  662. if (!empty($aVideoFile['dimensions']) && $oTcMp4Hd->isProcessHD($aVideoFile['dimensions']))
  663. $sVideoUrlHd = $oTcMp4Hd->getFileUrl($a['id']);
  664. $aResults[$a['id']] = array(
  665. 'id' => $a['id'],
  666. 'src_poster' => $oTcPoster->getFileUrl($a['id']),
  667. 'src_mp4' => $oTcMp4->getFileUrl($a['id']),
  668. 'src_mp4_hd' => $sVideoUrlHd,
  669. );
  670. }
  671. return $aResults;
  672. }
  673. protected function _getFilesForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
  674. {
  675. $CNF = &$this->_oConfig->CNF;
  676. $aResults = parent::_getFilesForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams);
  677. if(!$this->_oConfig->isAttachmentsInTimeline() || empty($CNF['OBJECT_STORAGE_FILES']))
  678. return $aResults;
  679. $iContentId = (int)$aContentInfo[$CNF['FIELD_ID']];
  680. $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_FILES']);
  681. $aGhostFiles = $oStorage->getGhosts($this->serviceGetContentOwnerProfileId($iContentId), $iContentId);
  682. if(!$aGhostFiles)
  683. return array();
  684. $oTranscoder = null;
  685. if(!empty($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY_FILES']))
  686. $oTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY_FILES']);
  687. foreach ($aGhostFiles as $k => $a) {
  688. $bImage = in_array($a['ext'], array('jpg', 'jpeg', 'png', 'gif'));
  689. $sPhotoSrc = '';
  690. if($bImage && $oTranscoder)
  691. $sPhotoSrc = $oTranscoder->getFileUrl($a['id']);
  692. if(empty($sPhotoSrc) && $oStorage)
  693. $sPhotoSrc = $this->_oTemplate->getIconUrl($oStorage->getIconNameByFileName($a['file_name']));
  694. $sUrl = $oStorage->getFileUrlById($a['id']);
  695. $aResults[] = array(
  696. 'id' => $a['id'],
  697. 'src' => $sPhotoSrc,
  698. 'src_medium' => $sPhotoSrc,
  699. 'src_orig' => $bImage ? $sUrl : '',
  700. 'url' => !$bImage ? $sUrl : ''
  701. );
  702. }
  703. return $aResults;
  704. }
  705. protected function _getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams = array())
  706. {
  707. $aResult = parent::_getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams);
  708. if(!$this->_oConfig->isAttachmentsInTimeline())
  709. return $aResult;
  710. $CNF = &$this->_oConfig->CNF;
  711. $bDynamic = isset($aBrowseParams['dynamic_mode']) && (bool)$aBrowseParams['dynamic_mode'] === true;
  712. if(!empty($CNF['PARAM_POLL_ENABLED']) && $CNF['PARAM_POLL_ENABLED'] == true)
  713. $aPolls = $this->_oDb->getPolls(array('type' => 'content_id', 'content_id' => (int)$aContentInfo[$CNF['FIELD_ID']]));
  714. if(!empty($aPolls) && is_array($aPolls)) {
  715. $sInclude = $this->_oTemplate->addCss(array('polls.css'), $bDynamic);
  716. $aResult['raw'] = ($bDynamic ? $sInclude : '') . $this->_oTemplate->parseHtmlByName('poll_items_embed.html', array(
  717. 'embed_url' => BX_DOL_URL_ROOT . bx_append_url_params($this->_oConfig->getBaseUri() . 'embed_polls/', array(
  718. 'id' => (int)$aContentInfo[$CNF['FIELD_ID']],
  719. 'param_switch_menu' => 0,
  720. 'param_showcase' => 1
  721. ))
  722. ));
  723. /*
  724. if((!empty($aResult['videos']) && is_array($aResult['videos'])) || (!empty($aResult['videos_attach']) && is_array($aResult['videos_attach'])))
  725. $aResult['_cache'] = false;
  726. */
  727. }
  728. return $aResult;
  729. }
  730. protected function _buildRssParams($sMode, $aArgs)
  731. {
  732. $aParams = array ();
  733. $sMode = bx_process_input($sMode);
  734. switch ($sMode) {
  735. case 'author':
  736. $aParams = array('author' => isset($aArgs[0]) ? (int)$aArgs[0] : '');
  737. break;
  738. }
  739. return $aParams;
  740. }
  741. public function serviceIsAllowedPostInContext()
  742. {
  743. return true;
  744. }
  745. }
  746. /** @} */