BxDolCmts.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup TridentCore Trident Core
  7. * @{
  8. */
  9. define('BX_CMT_OLD_VOTES', 365*86400); ///< comment votes older than this number of seconds will be deleted automatically
  10. define('BX_CMT_ACTION_POST', 'post');
  11. define('BX_CMT_ACTION_EDIT', 'edit');
  12. define('BX_CMT_DISPLAY_FLAT', 'flat');
  13. define('BX_CMT_DISPLAY_THREADED', 'threaded');
  14. define('BX_CMT_BROWSE_HEAD', 'head');
  15. define('BX_CMT_BROWSE_TAIL', 'tail');
  16. define('BX_CMT_BROWSE_POPULAR', 'popular');
  17. define('BX_CMT_BROWSE_CONNECTION', 'connection');
  18. define('BX_CMT_ORDER_BY_DATE', 'date');
  19. define('BX_CMT_ORDER_BY_POPULAR', 'popular');
  20. define('BX_CMT_FILTER_ALL', 'all');
  21. define('BX_CMT_FILTER_OTHERS', 'others');
  22. define('BX_CMT_FILTER_FRIENDS', 'friends');
  23. define('BX_CMT_FILTER_SUBSCRIPTIONS', 'subscriptions');
  24. define('BX_CMT_ORDER_WAY_ASC', 'asc');
  25. define('BX_CMT_ORDER_WAY_DESC', 'desc');
  26. define('BX_CMT_PFP_TOP', 'top');
  27. define('BX_CMT_PFP_BOTTOM', 'bottom');
  28. define('BX_CMT_RATE_VALUE_PLUS', 1);
  29. define('BX_CMT_RATE_VALUE_MINUS', -1);
  30. /**
  31. * @page objects
  32. * @section comments Comments
  33. * @ref BxDolCmts
  34. */
  35. /**
  36. * Comments for any content
  37. *
  38. * Related classes:
  39. * - BxDolCmtsQuery - comments database queries
  40. * - BxBaseCmts - comments base representation
  41. * - BxTemplCmts - custom template representation
  42. *
  43. * AJAX comments for any content.
  44. * Self moderated - users rate all comments, and if comment is
  45. * below viewing treshold it is hidden by default.
  46. *
  47. * To add comments section to your module you need to add a record to 'sys_objects_cmts' table:
  48. *
  49. * - ID - autoincremented id for internal usage
  50. * - ObjectName - your unique module name, with vendor prefix, lowercase and spaces are underscored
  51. * - TableCmts - table name where comments are stored
  52. * - Nl2br - convert new lines to <br /> on saving
  53. * - PerView - number of comments on a page
  54. * - IsRatable - 0 or 1 allow to rate comments or not
  55. * - ViewingThreshold - comment viewing treshost, if comment is below this number it is hidden by default
  56. * - IsOn - is this comment object enabled
  57. * - RootStylePrefix - toot comments style prefix, if you need root comments look different\
  58. * - ObjectVote - Vote object name to process comments' votes. May be empty if Comment Vote is not needed.
  59. * - TriggerTable - table to be updated upon each comment
  60. * - TriggerFieldId - TriggerTable table field with unique record id of
  61. * - TriggerFieldComments - TriggerTable table field with comments count, it will be updated automatically upon eaech comment
  62. * - ClassName - your custom class name if you need to override default class, this class must have the same constructor arguments
  63. * - ClassFile - file where your ClassName is stored.
  64. *
  65. * You can refer to BoonEx modules for sample record in this table.
  66. *
  67. *
  68. *
  69. * @section example Example of usage:
  70. * After filling in the table you can show comments section in any place, using the following code:
  71. *
  72. * @code
  73. * $o = new BxTemplCmts('value of ObjectName field', $iYourEntryId);
  74. * if ($o->isEnabled())
  75. * echo $o->getCommentsFirst ();
  76. * @endcode
  77. *
  78. * Please note that you never need to use BxDolCmts class directly, use BxTemplCmts instead.
  79. * Also if you override comments class with your own then make it child of BxTemplCmts class.
  80. *
  81. *
  82. *
  83. * @section acl Memberships/ACL:
  84. * - comments post
  85. * - comments edit own
  86. * - comments remove own
  87. * - comments edit all
  88. *
  89. *
  90. *
  91. * @section alerts Alerts:
  92. * Alerts type/unit - every module has own type/unit, it equals to ObjectName.
  93. *
  94. * The following alerts are rised
  95. *
  96. * - commentPost - comment was posted
  97. * - $iObjectId - entry id
  98. * - $iSenderId - author of comment
  99. * - $aExtra['comment_id'] - just added comment id
  100. *
  101. * - commentRemoved - comments was removed
  102. * - $iObjectId - entry id
  103. * - $iSenderId - comment deleter id
  104. * - $aExtra['comment_id'] - removed comment id
  105. *
  106. * - commentUpdated - comments was updated
  107. * - $iObjectId - entry id
  108. * - $iSenderId - comment deleter id
  109. * - $aExtra['comment_id'] - updated comment id
  110. *
  111. * - commentRated - comments was rated
  112. * - $iObjectId - entry id
  113. * - $iSenderId - comment rater id
  114. * - $aExtra['comment_id'] - rated comment id
  115. * - $aExtra['rate'] - comment rate 1 or -1
  116. *
  117. */
  118. class BxDolCmts extends BxDol implements iBxDolReplaceable
  119. {
  120. protected $_oQuery = null;
  121. protected $_sFormObject;
  122. protected $_sFormDisplayPost;
  123. protected $_sFormDisplayEdit;
  124. protected $_sTableImages;
  125. protected $_sTableImages2Entries;
  126. protected $_sConnObjFriends;
  127. protected $_sConnObjSubscriptions;
  128. protected $_sMenuObjManage;
  129. protected $_sMenuObjActions;
  130. protected $_sViewUrl = '';
  131. protected $_sBaseUrl = '';
  132. protected $_sListAnchor = '';
  133. protected $_sSystem = 'profile'; ///< current comment system name
  134. protected $_aSystem = array (); ///< current comments system array
  135. protected $_iId = 0; ///< obect id to be commented
  136. protected $_aMarkers = array ();
  137. protected $_sDisplayType = '';
  138. protected $_sDpSessionKey = '';
  139. protected $_iDpMaxLevel = 0;
  140. protected $_sBrowseType = '';
  141. protected $_sBrowseFilter = '';
  142. protected $_sBpSessionKeyType = '';
  143. protected $_sBpSessionKeyFilter = '';
  144. protected $_aOrder = array();
  145. protected $_sSnippetLenthLiveSearch = 50;
  146. protected $_iRememberTime = 2592000;
  147. /**
  148. * Constructor
  149. * $sSystem - comments system name
  150. * $iId - obect id to be commented
  151. */
  152. function __construct($sSystem, $iId, $iInit = 1)
  153. {
  154. parent::__construct();
  155. $this->_aSystems = $this->getSystems();
  156. if(!isset($this->_aSystems[$sSystem]))
  157. return;
  158. $this->_sSystem = $sSystem;
  159. $this->_aSystem = $this->_aSystems[$sSystem];
  160. $this->_aSystem['table_images'] = 'sys_cmts_images';
  161. $this->_aSystem['table_images2entries'] = 'sys_cmts_images2entries';
  162. $this->_aSystem['table_ids'] = 'sys_cmts_ids';
  163. $this->_iDpMaxLevel = (int)$this->_aSystem['number_of_levels'];
  164. $this->_sDisplayType = $this->_iDpMaxLevel == 0 ? BX_CMT_DISPLAY_FLAT : BX_CMT_DISPLAY_THREADED;
  165. $this->_sDpSessionKey = 'bx_' . $this->_sSystem . '_dp_';
  166. $this->_sBrowseType = $this->_aSystem['browse_type'];
  167. $this->_sBrowseFilter = BX_CMT_FILTER_ALL;
  168. $this->_sBpSessionKeyType = 'bx_' . $this->_sSystem . '_bpt_';
  169. $this->_sBpSessionKeyFilter = 'bx_' . $this->_sSystem . '_bpf_';
  170. $this->_aOrder = array(
  171. 'by' => BX_CMT_ORDER_BY_DATE,
  172. 'way' => BX_CMT_ORDER_WAY_ASC
  173. );
  174. list($mixedUserDp, $mixedUserBpType, $mixedUserBpFilter) = $this->_getUserChoice();
  175. if(!empty($mixedUserDp))
  176. $this->_sDisplayType = $mixedUserDp;
  177. if(!empty($mixedUserBpType))
  178. $this->_sBrowseType = $mixedUserBpType;
  179. if(!empty($mixedUserBpFilter))
  180. $this->_sBrowseFilter = $mixedUserBpFilter;
  181. $this->_sViewUrl = BX_DOL_URL_ROOT . 'cmts.php';
  182. $this->_sBaseUrl = BxDolPermalinks::getInstance()->permalink($this->_aSystem['base_url']);
  183. if(get_mb_substr($this->_sBaseUrl, 0, 4) != 'http')
  184. $this->_sBaseUrl = BX_DOL_URL_ROOT . $this->_sBaseUrl;
  185. $this->_sListAnchor = "cmts-anchor-%s-%d";
  186. $this->_oQuery = new BxDolCmtsQuery($this);
  187. $this->_sFormObject = 'sys_comment';
  188. $this->_sFormDisplayPost = 'sys_comment_post';
  189. $this->_sFormDisplayEdit = 'sys_comment_edit';
  190. $this->_sConnObjFriends = 'sys_profiles_friends';
  191. $this->_sConnObjSubscriptions = 'sys_profiles_subscriptions';
  192. $this->_sMenuObjManage = 'sys_cmts_item_manage';
  193. $this->_sMenuObjActions = 'sys_cmts_item_actions';
  194. $this->_sMetatagsObj = 'sys_cmts';
  195. if ($iInit)
  196. $this->init($iId);
  197. }
  198. /**
  199. * get comments object instanse
  200. * @param $sSys comments object name
  201. * @param $iId associated content id, where comments are postred in
  202. * @param $iInit perform initialization
  203. * @return null on error, or ready to use class instance
  204. */
  205. public static function getObjectInstance($sSys, $iId, $iInit = true)
  206. {
  207. if(isset($GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId]))
  208. return $GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId];
  209. $aSystems = self::getSystems();
  210. if (!isset($aSystems[$sSys]))
  211. return null;
  212. $sClassName = 'BxTemplCmts';
  213. if(!empty($aSystems[$sSys]['class_name'])) {
  214. $sClassName = $aSystems[$sSys]['class_name'];
  215. if(!empty($aSystems[$sSys]['class_file']))
  216. require_once(BX_DIRECTORY_PATH_ROOT . $aSystems[$sSys]['class_file']);
  217. }
  218. $o = new $sClassName($sSys, $iId, $iInit);
  219. return ($GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId] = $o);
  220. }
  221. public static function &getSystems ()
  222. {
  223. if (!isset($GLOBALS['bx_dol_cmts_systems'])) {
  224. $GLOBALS['bx_dol_cmts_systems'] = BxDolDb::getInstance()->fromCache('sys_objects_cmts', 'getAllWithKey', '
  225. SELECT
  226. `ID` as `system_id`,
  227. `Name` AS `name`,
  228. `Table` AS `table`,
  229. `CharsPostMin` AS `chars_post_min`,
  230. `CharsPostMax` AS `chars_post_max`,
  231. `CharsDisplayMax` AS `chars_display_max`,
  232. `Nl2br` AS `nl2br`,
  233. `PerView` AS `per_view`,
  234. `PerViewReplies` AS `per_view_replies`,
  235. `BrowseType` AS `browse_type`,
  236. `IsBrowseSwitch` AS `is_browse_switch`,
  237. `PostFormPosition` AS `post_form_position`,
  238. `NumberOfLevels` AS `number_of_levels`,
  239. `IsDisplaySwitch` AS `is_display_switch`,
  240. `IsRatable` AS `is_ratable`,
  241. `ViewingThreshold` AS `viewing_threshold`,
  242. `IsOn` AS `is_on`,
  243. `RootStylePrefix` AS `root_style_prefix`,
  244. `BaseUrl` AS `base_url`,
  245. `ObjectVote` AS `object_vote`,
  246. `TriggerTable` AS `trigger_table`,
  247. `TriggerFieldId` AS `trigger_field_id`,
  248. `TriggerFieldTitle` AS `trigger_field_title`,
  249. `TriggerFieldComments` AS `trigger_field_comments`,
  250. `ClassName` AS `class_name`,
  251. `ClassFile` AS `class_file`
  252. FROM `sys_objects_cmts`', 'name');
  253. }
  254. return $GLOBALS['bx_dol_cmts_systems'];
  255. }
  256. public function init ($iId)
  257. {
  258. if (empty($this->iId) && $iId)
  259. $this->setId($iId);
  260. $this->addMarkers(array(
  261. 'object_id' => $this->getId(),
  262. 'user_id' => $this->_getAuthorId()
  263. ));
  264. }
  265. public function getId ()
  266. {
  267. return $this->_iId;
  268. }
  269. public function isEnabled ()
  270. {
  271. return isset($this->_aSystem['is_on']) && $this->_aSystem['is_on'];
  272. }
  273. public function getSystemId()
  274. {
  275. return $this->_aSystem['system_id'];
  276. }
  277. public function getSystemName()
  278. {
  279. return $this->_sSystem;
  280. }
  281. public function getStorageObjectName()
  282. {
  283. return $this->_getFormObject()->getStorageObjectName();
  284. }
  285. public function getTranscoderPreviewName()
  286. {
  287. return $this->_getFormObject()->getTranscoderPreviewName();
  288. }
  289. public function getSystemInfo()
  290. {
  291. return $this->_aSystem;
  292. }
  293. public function getMaxLevel()
  294. {
  295. return $this->_iDpMaxLevel;
  296. }
  297. public function getOrder ()
  298. {
  299. return $this->_sOrder;
  300. }
  301. public function getPerView ($iCmtParentId = 0)
  302. {
  303. return $iCmtParentId == 0 ? $this->_aSystem['per_view'] : $this->_aSystem['per_view_replies'];
  304. }
  305. public function getBaseUrl()
  306. {
  307. return $this->_replaceMarkers($this->_sBaseUrl);
  308. }
  309. public function getListUrl()
  310. {
  311. return $this->getBaseUrl() . '#' . $this->getListAnchor();
  312. }
  313. public function getListAnchor()
  314. {
  315. return sprintf($this->_sListAnchor, str_replace('_', '-', $this->getSystemName()), $this->getId());
  316. }
  317. public function getViewUrl($iCmtId)
  318. {
  319. if(empty($this->_aSystem['trigger_field_title']))
  320. return '';
  321. return bx_append_url_params($this->_sViewUrl, array(
  322. 'sys' => $this->_sSystem,
  323. 'id' => $this->_iId,
  324. 'cmt_id' => $iCmtId
  325. ));
  326. }
  327. public function getConnectionObject($sType)
  328. {
  329. $sResult = '';
  330. switch($sType) {
  331. case BX_CMT_FILTER_FRIENDS:
  332. $sResult = $this->_sConnObjFriends;
  333. break;
  334. case BX_CMT_FILTER_SUBSCRIPTIONS:
  335. $sResult = $this->_sConnObjSubscriptions;
  336. break;
  337. }
  338. return $sResult;
  339. }
  340. public function getVoteObject($iId)
  341. {
  342. if(empty($this->_aSystem['object_vote']))
  343. $this->_aSystem['object_vote'] = 'sys_cmts';
  344. $oVote = BxDolVote::getObjectInstance($this->_aSystem['object_vote'], $iId);
  345. if(!$oVote || !$oVote->isEnabled())
  346. return false;
  347. return $oVote;
  348. }
  349. public function isNl2br ()
  350. {
  351. return $this->_aSystem['nl2br'];
  352. }
  353. public function isRatable ()
  354. {
  355. return $this->_aSystem['is_ratable'];
  356. }
  357. public function isAttachImageEnabled()
  358. {
  359. return true;
  360. }
  361. /**
  362. * set id to operate with votes
  363. */
  364. public function setId ($iId)
  365. {
  366. if ($iId == $this->getId()) return;
  367. $this->_iId = $iId;
  368. }
  369. /**
  370. * Add replace markers.
  371. * @param $a array of markers as key => value
  372. * @return true on success or false on error
  373. */
  374. public function addMarkers ($a)
  375. {
  376. if (empty($a) || !is_array($a))
  377. return false;
  378. $this->_aMarkers = array_merge ($this->_aMarkers, $a);
  379. return true;
  380. }
  381. /**
  382. * Database functions
  383. */
  384. public function getQueryObject ()
  385. {
  386. return $this->_oQuery;
  387. }
  388. public function getCommentsTableName ()
  389. {
  390. return $this->_oQuery->getTableName ();
  391. }
  392. public function getObjectTitle ($iObjectId = 0)
  393. {
  394. return $this->_oQuery->getObjectTitle ($iObjectId ? $iObjectId : $this->getId());
  395. }
  396. public function getCommentsCount ($iObjectId = 0, $iCmtVParentId = -1, $sFilter = '')
  397. {
  398. return $this->_oQuery->getCommentsCount ($iObjectId ? $iObjectId : $this->getId(), $iCmtVParentId, $this->_getAuthorId(), $sFilter);
  399. }
  400. public function getCommentsArray ($iVParentId, $sFilter, $aOrder, $iStart = 0, $iCount = -1)
  401. {
  402. return $this->_oQuery->getComments ($this->getId(), $iVParentId, $this->_getAuthorId(), $sFilter, $aOrder, $iStart, $iCount);
  403. }
  404. public function getCommentRow ($iCmtId)
  405. {
  406. return $this->_oQuery->getComment ($this->getId(), $iCmtId);
  407. }
  408. public function onObjectDelete ($iObjectId = 0)
  409. {
  410. // delete comments
  411. $aFiles = $aCmtIds = array();
  412. $this->_oQuery->deleteObjectComments ($iObjectId ? $iObjectId : $this->getId(), $aFiles, $aCmtIds);
  413. // delete meta info
  414. $this->deleteMetaInfo($aCmtIds);
  415. // delete files
  416. if ($aFiles) {
  417. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  418. if ($oStorage)
  419. $oStorage->queueFilesForDeletion($aFiles);
  420. }
  421. }
  422. public static function onAuthorDelete ($iAuthorId)
  423. {
  424. $aSystems = self::getSystems();
  425. foreach($aSystems as $sSystem => $aSystem) {
  426. $o = self::getObjectInstance($sSystem, 0);
  427. $oQuery = $o->getQueryObject();
  428. // delete comments
  429. $aFiles = $aCmtIds = array ();
  430. $oQuery->deleteAuthorComments($iAuthorId, $aFiles, $aCmtIds);
  431. // delete meta info
  432. $o->deleteMetaInfo($aCmtIds);
  433. // delete files
  434. $oStorage = BxDolStorage::getObjectInstance($o->getStorageObjectName());
  435. if ($oStorage)
  436. $oStorage->queueFilesForDeletion($aFiles);
  437. }
  438. return true;
  439. }
  440. public static function onModuleUninstall ($sModuleName, &$iFiles = null)
  441. {
  442. $aSystems = self::getSystems();
  443. foreach($aSystems as $sSystem => $aSystem) {
  444. if (0 != strncasecmp($sModuleName, $sSystem, strlen($sModuleName)))
  445. continue;
  446. $o = self::getObjectInstance($sSystem, 0);
  447. $oQuery = $o->getQueryObject();
  448. // delete comments
  449. $aFiles = $aCmtIds = array ();
  450. $oQuery->deleteAll($aSystem['system_id'], $aFiles, $aCmtIds);
  451. // delete meta info
  452. $o->deleteMetaInfo($aCmtIds);
  453. // delete files
  454. $oStorage = BxDolStorage::getObjectInstance($o->getStorageObjectName());
  455. if ($oStorage && $aFiles)
  456. $oStorage->queueFilesForDeletion($aFiles);
  457. if (null !== $iFiles)
  458. $iFiles += count($aFiles);
  459. }
  460. return true;
  461. }
  462. public function deleteMetaInfo ($mixedCmtId)
  463. {
  464. if (!$this->_sMetatagsObj)
  465. return;
  466. if (!is_array($mixedCmtId))
  467. $mixedCmtId = array($mixedCmtId);
  468. $oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj);
  469. foreach ($mixedCmtId as $iCmtId) {
  470. $oMetatags->onDeleteContent($this->_oQuery->getUniqId($this->_aSystem['system_id'], $iCmtId));
  471. $this->_oQuery->deleteCmtIds($this->_aSystem['system_id'], $iCmtId);
  472. }
  473. }
  474. /**
  475. * Permissions functions
  476. */
  477. public function checkAction ($sAction, $isPerformAction = false)
  478. {
  479. $iId = $this->_getAuthorId();
  480. $a = checkActionModule($iId, $sAction, 'system', $isPerformAction);
  481. return $a[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED;
  482. }
  483. public function checkActionErrorMsg ($sAction)
  484. {
  485. $iId = $this->_getAuthorId();
  486. $a = checkActionModule($iId, $sAction, 'system');
  487. return $a[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $a[CHECK_ACTION_MESSAGE] : '';
  488. }
  489. public function isVoteAllowed ($aCmt, $isPerformAction = false)
  490. {
  491. if(!$this->isRatable())
  492. return false;
  493. $oVote = $this->getVoteObject($aCmt['cmt_id']);
  494. if($oVote === false)
  495. return false;
  496. $iUserId = (int)$this->_getAuthorId();
  497. if($iUserId == 0)
  498. return false;
  499. if(isAdmin())
  500. return true;
  501. return $oVote->isAllowedVote($isPerformAction);
  502. }
  503. public function isPostReplyAllowed ($isPerformAction = false)
  504. {
  505. return $this->checkAction ('comments post', $isPerformAction);
  506. }
  507. public function msgErrPostReplyAllowed ()
  508. {
  509. return $this->checkActionErrorMsg('comments post');
  510. }
  511. public function isEditAllowed ($aCmt, $isPerformAction = false)
  512. {
  513. if(isAdmin())
  514. return true;
  515. if($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->checkAction ('comments edit own', $isPerformAction))
  516. return true;
  517. return $this->checkAction('comments edit all', $isPerformAction);
  518. }
  519. public function msgErrEditAllowed ()
  520. {
  521. return $this->checkActionErrorMsg ('comments edit own');
  522. }
  523. public function isRemoveAllowed ($aCmt, $isPerformAction = false)
  524. {
  525. if(isAdmin())
  526. return true;
  527. if($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->checkAction ('comments remove own', $isPerformAction))
  528. return true;
  529. return $this->checkAction ('comments remove all', $isPerformAction);
  530. }
  531. public function msgErrRemoveAllowed ()
  532. {
  533. return $this->checkActionErrorMsg('comments remove own');
  534. }
  535. /**
  536. * Actions functions
  537. */
  538. public function actionGetFormPost ()
  539. {
  540. if (!$this->isEnabled())
  541. return '';
  542. $iCmtParentId= isset($_REQUEST['CmtParent']) ? bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT) : 0;
  543. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  544. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  545. return $this->getFormBoxPost(array('parent_id' => $iCmtParentId, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
  546. }
  547. public function actionGetFormEdit ()
  548. {
  549. if (!$this->isEnabled()){
  550. $this->_echoResultJson(array());
  551. return;
  552. }
  553. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  554. $this->_echoResultJson($this->getFormEdit($iCmtId));
  555. }
  556. public function actionGetCmt ()
  557. {
  558. if (!$this->isEnabled())
  559. return '';
  560. $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
  561. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  562. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  563. $aCmt = $this->getCommentRow($iCmtId);
  564. $this->_echoResultJson(array(
  565. 'parent_id' => $aCmt['cmt_parent_id'],
  566. 'vparent_id' => $aCmt['cmt_vparent_id'],
  567. 'content' => $this->getComment($aCmt, array('type' => $sCmtBrowse), array('type' => $sCmtDisplay))
  568. ));
  569. }
  570. public function actionGetCmts ()
  571. {
  572. if (!$this->isEnabled())
  573. return '';
  574. $aBp = $aDp = array();
  575. $this->_getParams($aBp, $aDp);
  576. return $this->getComments($aBp, $aDp);
  577. }
  578. public function actionSubmitPostForm()
  579. {
  580. if(!$this->isEnabled() || !$this->isPostReplyAllowed()) {
  581. $this->_echoResultJson(array());
  582. return;
  583. }
  584. $iCmtParentId = 0;
  585. if(bx_get('cmt_parent_id') !== false)
  586. $iCmtParentId = bx_process_input(bx_get('cmt_parent_id'), BX_DATA_INT);
  587. $this->_echoResultJson($this->getFormPost($iCmtParentId));
  588. }
  589. public function actionSubmitEditForm()
  590. {
  591. if (!$this->isEnabled()) {
  592. $this->_echoResultJson(array());
  593. return;
  594. };
  595. $iCmtId = 0;
  596. if(bx_get('cmt_id') !== false)
  597. $iCmtId = bx_process_input(bx_get('cmt_id'), BX_DATA_INT);
  598. $this->_echoResultJson($this->getFormEdit($iCmtId));
  599. }
  600. public function actionRemove()
  601. {
  602. if (!$this->isEnabled()) {
  603. $this->_echoResultJson(array());
  604. return;
  605. };
  606. $iCmtId = 0;
  607. if(bx_get('Cmt') !== false)
  608. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  609. $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
  610. if(!$aCmt) {
  611. $this->_echoResultJson(array('msg' => _t('_No such comment')));
  612. return;
  613. }
  614. if ($aCmt['cmt_replies'] > 0) {
  615. $this->_echoResultJson(array('msg' => _t('_Can not delete comments with replies')));
  616. return;
  617. }
  618. $iCmtAuthorId = $this->_getAuthorId();
  619. if(!$this->isRemoveAllowed($aCmt)) {
  620. $this->_echoResultJson(array('msg' => $aCmt['cmt_author_id'] == $iCmtAuthorId ? strip_tags($this->msgErrRemoveAllowed()) : _t('_Access denied')));
  621. return;
  622. }
  623. if($this->_oQuery->removeComment ($this->getId(), $aCmt['cmt_id'], $aCmt['cmt_parent_id'])) {
  624. $this->_triggerComment();
  625. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  626. $aImages = $this->_oQuery->getImages($this->_aSystem['system_id'], $aCmt['cmt_id']);
  627. foreach($aImages as $aImage)
  628. $oStorage->deleteFile($aImage['image_id']);
  629. $this->_oQuery->deleteImages($this->_aSystem['system_id'], $aCmt['cmt_id']);
  630. $this->isRemoveAllowed(true);
  631. $this->deleteMetaInfo ($aCmt['cmt_id']);
  632. $oZ = new BxDolAlerts($this->_sSystem, 'commentRemoved', $this->getId(), $iCmtAuthorId, array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
  633. $oZ->alert();
  634. $this->_echoResultJson(array('id' => $iCmtId));
  635. return;
  636. }
  637. $this->_echoResultJson(array('msg' => _t('_cmt_err_cannot_perform_action')));
  638. }
  639. /**
  640. * Internal functions
  641. */
  642. protected function _getAuthorId ()
  643. {
  644. return isMember() ? bx_get_logged_profile_id() : 0;
  645. }
  646. protected function _getAuthorPassword ()
  647. {
  648. return isMember() ? $_COOKIE['memberPassword'] : "";
  649. }
  650. protected function _getAuthorIp ()
  651. {
  652. return getVisitorIP();
  653. }
  654. protected function _getAuthorInfo($iAuthorId = 0)
  655. {
  656. $oProfile = $this->_getAuthorObject($iAuthorId);
  657. return array(
  658. $oProfile->getDisplayName(),
  659. $oProfile->getUrl(),
  660. $oProfile->getThumb(),
  661. $oProfile->getUnit()
  662. );
  663. }
  664. protected function _getAuthorObject($iAuthorId = 0)
  665. {
  666. $oProfile = BxDolProfile::getInstance($iAuthorId);
  667. if (!$oProfile)
  668. $oProfile = BxDolProfileUndefined::getInstance();
  669. return $oProfile;
  670. }
  671. protected function _getFormObject($sAction = BX_CMT_ACTION_POST)
  672. {
  673. $sDisplayName = '_sFormDisplay' . ucfirst($sAction);
  674. return BxDolForm::getObjectInstance($this->_sFormObject, $this->$sDisplayName);
  675. }
  676. protected function _getParams(&$aBp, &$aDp)
  677. {
  678. $aBp['vparent_id'] = isset($_REQUEST['CmtParent'])? bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT) : 0;
  679. $aBp['type'] = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  680. $aBp['filter'] = isset($_REQUEST['CmtFilter']) ? bx_process_input($_REQUEST['CmtFilter'], BX_DATA_TEXT) : '';
  681. $aBp['start'] = isset($_REQUEST['CmtStart']) ? bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT) : -1;
  682. $aBp['per_view'] = isset($_REQUEST['CmtPerView']) ? bx_process_input($_REQUEST['CmtPerView'], BX_DATA_INT) : -1;
  683. $aDp['type'] = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  684. $aDp['blink'] = isset($_REQUEST['CmtBlink']) ? bx_process_input($_REQUEST['CmtBlink'], BX_DATA_TEXT) : '';
  685. }
  686. protected function _prepareTextForEdit ($s)
  687. {
  688. if ($this->isNl2br())
  689. return htmlspecialchars_decode(str_replace('<br />', "", $s));
  690. return $s;
  691. }
  692. protected function _prepareTextForSave ($s)
  693. {
  694. $iDataAction = $this->isNl2br() ? BX_DATA_TEXT_MULTILINE : BX_DATA_HTML;
  695. return bx_process_input($s, $iDataAction);
  696. }
  697. protected function _prepareTextForOutput ($s, $iCmtId = 0)
  698. {
  699. $s = bx_process_output($s, BX_DATA_HTML);
  700. $s = bx_convert_links($s);
  701. if ($this->_sMetatagsObj && $iCmtId) {
  702. $oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj);
  703. $s = $oMetatags->keywordsParse($this->_oQuery->getUniqId($this->_aSystem['system_id'], $iCmtId), $s);
  704. }
  705. return $s;
  706. }
  707. protected function _prepareParams(&$aBp, &$aDp)
  708. {
  709. $aBp['type'] = isset($aBp['type']) && !empty($aBp['type']) ? $aBp['type'] : $this->_sBrowseType;
  710. $aBp['filter'] = isset($aBp['filter']) && !empty($aBp['filter']) ? $aBp['filter'] : $this->_sBrowseFilter;
  711. $aBp['parent_id'] = isset($aBp['parent_id']) ? $aBp['parent_id'] : 0;
  712. $aBp['start'] = isset($aBp['start']) ? $aBp['start'] : -1;
  713. $aBp['per_view'] = isset($aBp['per_view']) ? $aBp['per_view'] : -1;
  714. $aBp['order']['by'] = isset($aBp['order_by']) ? $aBp['order_by'] : $this->_aOrder['by'];
  715. $aBp['order']['way'] = isset($aBp['order_way']) ? $aBp['order_way'] : $this->_aOrder['way'];
  716. $aDp['type'] = isset($aDp['type']) && !empty($aDp['type']) ? $aDp['type'] : $this->_sDisplayType;
  717. $aDp['blink'] = isset($aDp['blink']) && !empty($aDp['blink']) ? $aDp['blink'] : array();
  718. if(!is_array($aDp['blink']))
  719. $aDp['blink'] = explode(',', $aDp['blink']);
  720. switch($aDp['type']) {
  721. case BX_CMT_DISPLAY_FLAT:
  722. $aBp['vparent_id'] = -1;
  723. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView(0);
  724. break;
  725. case BX_CMT_DISPLAY_THREADED:
  726. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView($aBp['vparent_id']);
  727. break;
  728. }
  729. switch ($aBp['type']) {
  730. case BX_CMT_BROWSE_POPULAR:
  731. $aBp['order'] = array(
  732. 'by' => BX_CMT_ORDER_BY_POPULAR,
  733. 'way' => BX_CMT_ORDER_WAY_DESC
  734. );
  735. break;
  736. }
  737. $aBp['count'] = $this->getCommentsCount($this->_iId, $aBp['vparent_id'], $aBp['filter']);
  738. if($aBp['start'] != -1)
  739. return;
  740. $aBp['start'] = 0;
  741. if($aBp['type'] == BX_CMT_BROWSE_TAIL) {
  742. $aBp['start'] = $aBp['count'] - $aBp['per_view'];
  743. if($aBp['start'] < 0) {
  744. $aBp['per_view'] += $aBp['start'];
  745. $aBp['start'] = 0;
  746. }
  747. }
  748. $this->_setUserChoice($aDp['type'], $aBp['type'], $aBp['filter']);
  749. }
  750. protected function _triggerComment()
  751. {
  752. if(!$this->_aSystem['trigger_table'])
  753. return false;
  754. $iId = $this->getId();
  755. if(!$iId)
  756. return false;
  757. $iCount = $this->getCommentsCount($iId);
  758. return $this->_oQuery->updateTriggerTable($iId, $iCount);
  759. }
  760. /**
  761. * Replace provided markers in a string
  762. * @param $mixed string or array to replace markers in
  763. * @return string where all occured markers are replaced
  764. */
  765. protected function _replaceMarkers ($mixed)
  766. {
  767. return bx_replace_markers($mixed, $this->_aMarkers);
  768. }
  769. protected function _getUserChoice()
  770. {
  771. $mixedDp = $mixedBpType = $mixedBpFilter = false;
  772. if(!isLogged())
  773. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  774. $iUserId = $this->_getAuthorId();
  775. $oSession = BxDolSession::getInstance();
  776. $mixedDp = $oSession->getValue($this->_sDpSessionKey . $iUserId);
  777. $mixedBpType = $oSession->getValue($this->_sBpSessionKeyType . $iUserId);
  778. $mixedBpFilter = $oSession->getValue($this->_sBpSessionKeyFilter . $iUserId);
  779. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  780. }
  781. protected function _setUserChoice($sDp, $sBpType, $sBpFilter)
  782. {
  783. if(!isLogged())
  784. return;
  785. $iUserId = $this->_getAuthorId();
  786. $oSession = BxDolSession::getInstance();
  787. if(!empty($sDp))
  788. $oSession->setValue($this->_sDpSessionKey . $iUserId, $sDp);
  789. if(!empty($sBpType))
  790. $oSession->setValue($this->_sBpSessionKeyType . $iUserId, $sBpType);
  791. if(!empty($sBpFilter))
  792. $oSession->setValue($this->_sBpSessionKeyFilter . $iUserId, $sBpFilter);
  793. }
  794. protected function _sendNotificationEmail($iCmtId, $iCmtParentId)
  795. {
  796. $aCmt = $this->getCommentRow($iCmtId);
  797. $aCmtParent = $this->getCommentRow($iCmtParentId);
  798. if(empty($aCmt) || !is_array($aCmt) || empty($aCmtParent) || !is_array($aCmtParent) || (int)$aCmt['cmt_author_id'] == (int)$aCmtParent['cmt_author_id'])
  799. return;
  800. $oProfile = $this->_getAuthorObject($aCmtParent['cmt_author_id']);
  801. if($oProfile instanceof BxDolProfileUndefined)
  802. return;
  803. $iAccount = $oProfile->getAccountId();
  804. $aAccount = BxDolAccount::getInstance($iAccount)->getInfo();
  805. $aPlus = array();
  806. $aPlus['reply_text'] = bx_process_output($aCmt['cmt_text']);
  807. $aPlus['comment_url'] = sprintf('%scmts.php?sys=%s&id=%d&cmt_id=%d', BX_DOL_URL_ROOT, $this->_sSystem, $this->_iId, $iCmtParentId);
  808. $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('t_CommentReplied', $aPlus);
  809. return $aTemplate && sendMail($aAccount['email'], $aTemplate['Subject'], $aTemplate['Body']);
  810. }
  811. }
  812. /** @} */