BxDolCmts.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  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 DolphinCore Dolphin Core
  7. * @{
  8. */
  9. bx_import('BxDolCmtsQuery');
  10. define('BX_CMT_OLD_VOTES', 365*86400); ///< comment votes older than this number of seconds will be deleted automatically
  11. define('BX_CMT_ACTION_POST', 'post');
  12. define('BX_CMT_ACTION_EDIT', 'edit');
  13. define('BX_CMT_DISPLAY_FLAT', 'flat');
  14. define('BX_CMT_DISPLAY_THREADED', 'threaded');
  15. define('BX_CMT_BROWSE_HEAD', 'head');
  16. define('BX_CMT_BROWSE_TAIL', 'tail');
  17. define('BX_CMT_BROWSE_POPULAR', 'popular');
  18. define('BX_CMT_BROWSE_CONNECTION', 'connection');
  19. define('BX_CMT_ORDER_BY_DATE', 'date');
  20. define('BX_CMT_ORDER_BY_POPULAR', 'popular');
  21. define('BX_CMT_FILTER_ALL', 'all');
  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. * bx_import ('BxTemplCmts');
  74. * $o = new BxTemplCmts('value of ObjectName field', $iYourEntryId);
  75. * if ($o->isEnabled())
  76. * echo $o->getCommentsFirst ();
  77. * @endcode
  78. *
  79. * Please note that you never need to use BxDolCmts class directly, use BxTemplCmts instead.
  80. * Also if you override comments class with your own then make it child of BxTemplCmts class.
  81. *
  82. *
  83. *
  84. * @section acl Memberships/ACL:
  85. * - comments post - ACTION_ID_COMMENTS_POST
  86. * - comments vote - ACTION_ID_COMMENTS_VOTE
  87. * - comments edit own - ACTION_ID_COMMENTS_EDIT_OWN
  88. * - comments remove own - ACTION_ID_COMMENTS_REMOVE_OWN
  89. *
  90. *
  91. *
  92. * @section alerts Alerts:
  93. * Alerts type/unit - every module has own type/unit, it equals to ObjectName.
  94. *
  95. * The following alerts are rised
  96. *
  97. * - commentPost - comment was posted
  98. * - $iObjectId - entry id
  99. * - $iSenderId - author of comment
  100. * - $aExtra['comment_id'] - just added comment id
  101. *
  102. * - commentRemoved - comments was removed
  103. * - $iObjectId - entry id
  104. * - $iSenderId - comment deleter id
  105. * - $aExtra['comment_id'] - removed comment id
  106. *
  107. * - commentUpdated - comments was updated
  108. * - $iObjectId - entry id
  109. * - $iSenderId - comment deleter id
  110. * - $aExtra['comment_id'] - updated comment id
  111. *
  112. * - commentRated - comments was rated
  113. * - $iObjectId - entry id
  114. * - $iSenderId - comment rater id
  115. * - $aExtra['comment_id'] - rated comment id
  116. * - $aExtra['rate'] - comment rate 1 or -1
  117. *
  118. */
  119. class BxDolCmts extends BxDol
  120. {
  121. protected $_oQuery = null;
  122. protected $_sFormObject;
  123. protected $_sFormDisplayPost;
  124. protected $_sFormDisplayEdit;
  125. protected $_sStorageObject;
  126. protected $_sTranscoderPreview;
  127. protected $_sTableImages;
  128. protected $_sTableImages2Entries;
  129. protected $_aImageUploaders;
  130. protected $_sConnObjFriends;
  131. protected $_sConnObjSubscriptions;
  132. protected $_sMenuObjManage;
  133. protected $_sMenuObjActions;
  134. protected $_sViewUrl = '';
  135. protected $_sBaseUrl = '';
  136. protected $_sListAnchor = '';
  137. protected $_sSystem = 'profile'; ///< current comment system name
  138. protected $_aSystem = array (); ///< current comments system array
  139. protected $_iId = 0; ///< obect id to be commented
  140. protected $_aMarkers = array ();
  141. protected $_sDisplayType = '';
  142. protected $_sDpSessionKey = '';
  143. protected $_iDpMaxLevel = 0;
  144. protected $_sBrowseType = '';
  145. protected $_sBrowseFilter = '';
  146. protected $_sBpSessionKeyType = '';
  147. protected $_sBpSessionKeyFilter = '';
  148. protected $_aOrder = array();
  149. protected $_iRememberTime = 2592000;
  150. /**
  151. * Constructor
  152. * $sSystem - comments system name
  153. * $iId - obect id to be commented
  154. */
  155. function BxDolCmts( $sSystem, $iId, $iInit = 1)
  156. {
  157. parent::BxDol();
  158. $this->_aSystems = $this->getSystems();
  159. if(!isset($this->_aSystems[$sSystem]))
  160. return;
  161. $this->_sSystem = $sSystem;
  162. $this->_aSystem = $this->_aSystems[$sSystem];
  163. $this->_aSystem['table_images'] = 'sys_cmts_images';
  164. $this->_aSystem['table_images2entries'] = 'sys_cmts_images2entries';
  165. $this->_iDpMaxLevel = (int)$this->_aSystem['number_of_levels'];
  166. $this->_sDisplayType = $this->_iDpMaxLevel == 0 ? BX_CMT_DISPLAY_FLAT : BX_CMT_DISPLAY_THREADED;
  167. $this->_sDpSessionKey = 'bx_' . $this->_sSystem . '_dp_';
  168. $this->_sBrowseType = $this->_aSystem['browse_type'];
  169. $this->_sBrowseFilter = BX_CMT_FILTER_ALL;
  170. $this->_sBpSessionKeyType = 'bx_' . $this->_sSystem . '_bpt_';
  171. $this->_sBpSessionKeyFilter = 'bx_' . $this->_sSystem . '_bpf_';
  172. $this->_aOrder = array(
  173. 'by' => BX_CMT_ORDER_BY_DATE,
  174. 'way' => BX_CMT_ORDER_WAY_ASC
  175. );
  176. list($mixedUserDp, $mixedUserBpType, $mixedUserBpFilter) = $this->_getUserChoice();
  177. if(!empty($mixedUserDp))
  178. $this->_sDisplayType = $mixedUserDp;
  179. if(!empty($mixedUserBpType))
  180. $this->_sBrowseType = $mixedUserBpType;
  181. if(!empty($mixedUserBpFilter))
  182. $this->_sBrowseFilter = $mixedUserBpFilter;
  183. $this->_sViewUrl = BX_DOL_URL_ROOT . 'cmts.php';
  184. $this->_sBaseUrl = $this->_aSystem['base_url'];
  185. if(get_mb_substr($this->_sBaseUrl, 0, 4) != 'http')
  186. $this->_sBaseUrl = BX_DOL_URL_ROOT . $this->_sBaseUrl;
  187. $this->_sListAnchor = "cmts-anchor-%s-%d";
  188. $this->_oQuery = new BxDolCmtsQuery($this);
  189. $this->_sFormObject = 'sys_comment';
  190. $this->_sFormDisplayPost = 'sys_comment_post';
  191. $this->_sFormDisplayEdit = 'sys_comment_edit';
  192. $this->_sStorageObject = 'sys_cmts_images';
  193. $this->_sTranscoderPreview = 'sys_cmts_images_preview';
  194. $this->_aImageUploaders = array('sys_cmts_simple');
  195. $this->_sConnObjFriends = 'sys_profiles_friends';
  196. $this->_sConnObjSubscriptions = 'sys_profiles_subscriptions';
  197. $this->_sMenuObjManage = 'sys_cmts_item_manage';
  198. $this->_sMenuObjActions = 'sys_cmts_item_actions';
  199. if ($iInit)
  200. $this->init($iId);
  201. }
  202. /**
  203. * get comments object instanse
  204. * @param $sSys comments object name
  205. * @param $iId associated content id, where comments are postred in
  206. * @param $iInit perform initialization
  207. * @return null on error, or ready to use class instance
  208. */
  209. public static function getObjectInstance($sSys, $iId, $iInit = true)
  210. {
  211. if(isset($GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId]))
  212. return $GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId];
  213. $aSystems = self::getSystems();
  214. if (!isset($aSystems[$sSys]))
  215. return null;
  216. bx_import('BxTemplCmts');
  217. $sClassName = 'BxTemplCmts';
  218. if(!empty($aSystems[$sSys]['class_name'])) {
  219. $sClassName = $aSystems[$sSys]['class_name'];
  220. if(!empty($aSystems[$sSys]['class_file']))
  221. require_once(BX_DIRECTORY_PATH_ROOT . $aSystems[$sSys]['class_file']);
  222. else
  223. bx_import($sClassName);
  224. }
  225. $o = new $sClassName($sSys, $iId, true);
  226. return ($GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId] = $o);
  227. }
  228. public static function &getSystems ()
  229. {
  230. if (!isset($GLOBALS['bx_dol_cmts_systems'])) {
  231. $GLOBALS['bx_dol_cmts_systems'] = BxDolDb::getInstance()->fromCache('sys_objects_cmts', 'getAllWithKey', '
  232. SELECT
  233. `ID` as `system_id`,
  234. `Name` AS `name`,
  235. `Table` AS `table`,
  236. `CharsPostMin` AS `chars_post_min`,
  237. `CharsPostMax` AS `chars_post_max`,
  238. `CharsDisplayMax` AS `chars_display_max`,
  239. `Nl2br` AS `nl2br`,
  240. `PerView` AS `per_view`,
  241. `PerViewReplies` AS `per_view_replies`,
  242. `BrowseType` AS `browse_type`,
  243. `IsBrowseSwitch` AS `is_browse_switch`,
  244. `PostFormPosition` AS `post_form_position`,
  245. `NumberOfLevels` AS `number_of_levels`,
  246. `IsDisplaySwitch` AS `is_display_switch`,
  247. `IsRatable` AS `is_ratable`,
  248. `ViewingThreshold` AS `viewing_threshold`,
  249. `IsOn` AS `is_on`,
  250. `RootStylePrefix` AS `root_style_prefix`,
  251. `BaseUrl` AS `base_url`,
  252. `ObjectVote` AS `object_vote`,
  253. `TriggerTable` AS `trigger_table`,
  254. `TriggerFieldId` AS `trigger_field_id`,
  255. `TriggerFieldTitle` AS `trigger_field_title`,
  256. `TriggerFieldComments` AS `trigger_field_comments`,
  257. `ClassName` AS `class_name`,
  258. `ClassFile` AS `class_file`
  259. FROM `sys_objects_cmts`', 'name');
  260. }
  261. return $GLOBALS['bx_dol_cmts_systems'];
  262. }
  263. /**
  264. * it is called on cron every day or similar period to clean old comment votes
  265. */
  266. public static function maintenance() {
  267. $iResult = 0;
  268. $oDb = BxDolDb::getInstance();
  269. $aSystems = self::getSystems();
  270. foreach($aSystems as $aSystem) {
  271. if(!$aSystem['is_on'])
  272. continue;
  273. $sQuery = $oDb->prepare("DELETE FROM `{$aSystem['table_track']}` WHERE `cmt_rate_ts` < (UNIX_TIMESTAMP() - ?)", BX_CMT_OLD_VOTES);
  274. $iDeleted = (int)$oDb->query($sQuery);
  275. if($iDeleted > 0)
  276. $oDb->query("OPTIMIZE TABLE `{$aSystem['table_track']}`");
  277. $iResult += $iDeleted;
  278. }
  279. return $iResult;
  280. }
  281. public function init ($iId)
  282. {
  283. if (!$this->isEnabled())
  284. return;
  285. if (empty($this->iId) && $iId)
  286. $this->setId($iId);
  287. $this->addMarkers(array(
  288. 'object_id' => $this->getId(),
  289. 'user_id' => $this->_getAuthorId()
  290. ));
  291. }
  292. public function getId ()
  293. {
  294. return $this->_iId;
  295. }
  296. public function isEnabled ()
  297. {
  298. return isset($this->_aSystem['is_on']) && $this->_aSystem['is_on'];
  299. }
  300. public function getSystemId()
  301. {
  302. return $this->_aSystem['system_id'];
  303. }
  304. public function getSystemName()
  305. {
  306. return $this->_sSystem;
  307. }
  308. public function getSystemInfo()
  309. {
  310. return $this->_aSystem;
  311. }
  312. public function getMaxLevel()
  313. {
  314. return $this->_iDpMaxLevel;
  315. }
  316. public function getOrder ()
  317. {
  318. return $this->_sOrder;
  319. }
  320. public function getPerView ($iCmtParentId = 0)
  321. {
  322. return $iCmtParentId == 0 ? $this->_aSystem['per_view'] : $this->_aSystem['per_view_replies'];
  323. }
  324. public function getBaseUrl()
  325. {
  326. return $this->_replaceMarkers($this->_sBaseUrl);
  327. }
  328. public function getListUrl()
  329. {
  330. return $this->getBaseUrl() . '#' . $this->getListAnchor();
  331. }
  332. public function getListAnchor()
  333. {
  334. return sprintf($this->_sListAnchor, str_replace('_', '-', $this->getSystemName()), $this->getId());
  335. }
  336. public function getConnectionObject($sType)
  337. {
  338. $sResult = '';
  339. switch($sType) {
  340. case BX_CMT_FILTER_FRIENDS:
  341. $sResult = $this->_sConnObjFriends;
  342. break;
  343. case BX_CMT_FILTER_SUBSCRIPTIONS:
  344. $sResult = $this->_sConnObjSubscriptions;
  345. break;
  346. }
  347. return $sResult;
  348. }
  349. public function getVoteObject($iId)
  350. {
  351. if(empty($this->_aSystem['object_vote']))
  352. return false;
  353. bx_import('BxDolVote');
  354. $oVote = BxDolVote::getObjectInstance($this->_aSystem['object_vote'], $iId);
  355. if(!$oVote->isEnabled())
  356. return false;
  357. return $oVote;
  358. }
  359. public function isNl2br ()
  360. {
  361. return $this->_aSystem['nl2br'];
  362. }
  363. public function isRatable ()
  364. {
  365. return $this->_aSystem['is_ratable'];
  366. }
  367. public function isAttachImageEnabled()
  368. {
  369. return true;
  370. }
  371. /**
  372. * set id to operate with votes
  373. */
  374. public function setId ($iId)
  375. {
  376. if ($iId == $this->getId()) return;
  377. $this->_iId = $iId;
  378. }
  379. /**
  380. * Add replace markers.
  381. * @param $a array of markers as key => value
  382. * @return true on success or false on error
  383. */
  384. public function addMarkers ($a) {
  385. if (empty($a) || !is_array($a))
  386. return false;
  387. $this->_aMarkers = array_merge ($this->_aMarkers, $a);
  388. return true;
  389. }
  390. /**
  391. * Database functions
  392. */
  393. public function getCommentsTableName ()
  394. {
  395. return $this->_oQuery->getTableName ();
  396. }
  397. public function getObjectTitle ($iObjectId = 0)
  398. {
  399. return $this->_oQuery->getObjectTitle ($iObjectId ? $iObjectId : $this->getId());
  400. }
  401. public function getCommentsCount ($iObjectId = 0, $iCmtVParentId = 0, $sFilter = '')
  402. {
  403. return $this->_oQuery->getCommentsCount ($iObjectId ? $iObjectId : $this->getId(), $iCmtVParentId, $this->_getAuthorId(), $sFilter);
  404. }
  405. public function getCommentsArray ($iVParentId, $sFilter, $aOrder, $iStart = 0, $iCount = -1)
  406. {
  407. return $this->_oQuery->getComments ($this->getId(), $iVParentId, $this->_getAuthorId(), $sFilter, $aOrder, $iStart, $iCount);
  408. }
  409. public function getCommentRow ($iCmtId)
  410. {
  411. return $this->_oQuery->getComment ($this->getId(), $iCmtId, $this->_getAuthorId());
  412. }
  413. public function onObjectDelete ($iObjectId = 0)
  414. {
  415. return $this->_oQuery->deleteObjectComments ($iObjectId ? $iObjectId : $this->getId());
  416. }
  417. public function onAuthorDelete ($iAuthorId)
  418. {
  419. foreach($this->_aSystems as $sSystem => $aSystem) {
  420. $oQuery = new BxDolCmtsQuery($aSystem);
  421. $oQuery->deleteAuthorComments($iAuthorId);
  422. }
  423. return true;
  424. }
  425. /**
  426. * Permissions functions
  427. */
  428. public function checkAction ($iAction, $isPerformAction = false)
  429. {
  430. $iId = $this->_getAuthorId();
  431. $check_res = checkAction($iId, $iAction, $isPerformAction);
  432. return $check_res[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED;
  433. }
  434. public function checkActionErrorMsg ($iAction)
  435. {
  436. $iId = $this->_getAuthorId();
  437. $check_res = checkAction($iId, $iAction);
  438. return $check_res[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $check_res[CHECK_ACTION_MESSAGE] : '';
  439. }
  440. public function isVoteAllowed ($aCmt, $isPerformAction = false)
  441. {
  442. if(!$this->isRatable())
  443. return false;
  444. $oVote = $this->getVoteObject($aCmt['cmt_id']);
  445. if($oVote === false)
  446. return false;
  447. $iUserId = (int)$this->_getAuthorId();
  448. if($iUserId == 0)
  449. return false;
  450. if(isAdmin())
  451. return true;
  452. return $oVote->isAllowedVote($isPerformAction);
  453. }
  454. public function msgErrVoteAllowed ()
  455. {
  456. return $this->checkActionErrorMsg(ACTION_ID_VOTE);
  457. }
  458. public function isPostReplyAllowed ($isPerformAction = false)
  459. {
  460. return $this->checkAction (ACTION_ID_COMMENTS_POST, $isPerformAction);
  461. }
  462. public function msgErrPostReplyAllowed ()
  463. {
  464. return $this->checkActionErrorMsg(ACTION_ID_COMMENTS_POST);
  465. }
  466. public function isEditAllowed ($aCmt, $isPerformAction = false)
  467. {
  468. if(isAdmin())
  469. return true;
  470. if($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->checkAction (ACTION_ID_COMMENTS_EDIT_OWN, $isPerformAction))
  471. return true;
  472. return $this->checkAction(ACTION_ID_COMMENTS_EDIT_ALL, $isPerformAction);
  473. }
  474. public function msgErrEditAllowed ()
  475. {
  476. return $this->checkActionErrorMsg (ACTION_ID_COMMENTS_EDIT_OWN);
  477. }
  478. public function isRemoveAllowed ($aCmt, $isPerformAction = false)
  479. {
  480. if(isAdmin())
  481. return true;
  482. if($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->checkAction (ACTION_ID_COMMENTS_REMOVE_OWN, $isPerformAction))
  483. return true;
  484. return $this->checkAction (ACTION_ID_COMMENTS_REMOVE_ALL, $isPerformAction);
  485. }
  486. public function msgErrRemoveAllowed ()
  487. {
  488. return $this->checkActionErrorMsg(ACTION_ID_COMMENTS_REMOVE_OWN);
  489. }
  490. /**
  491. * Actions functions
  492. */
  493. public function actionGetFormPost () {
  494. if (!$this->isEnabled())
  495. return '';
  496. $iCmtParentId= isset($_REQUEST['CmtParent']) ? bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT) : 0;
  497. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  498. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  499. return $this->getFormBoxPost(array('parent_id' => $iCmtParentId, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
  500. }
  501. public function actionGetFormEdit ()
  502. {
  503. if (!$this->isEnabled()){
  504. $this->_echoResultJson(array());
  505. return;
  506. }
  507. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  508. $this->_echoResultJson($this->getFormEdit($iCmtId));
  509. }
  510. public function actionGetCmt () {
  511. if (!$this->isEnabled())
  512. return '';
  513. $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
  514. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  515. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  516. $aCmt = $this->getCommentRow($iCmtId);
  517. $this->_echoResultJson(array(
  518. 'parent_id' => $aCmt['cmt_parent_id'],
  519. 'vparent_id' => $aCmt['cmt_vparent_id'],
  520. 'content' => $this->getComment($aCmt, array('type' => $sCmtBrowse), array('type' => $sCmtDisplay))
  521. ));
  522. }
  523. public function actionGetCmts () {
  524. if (!$this->isEnabled())
  525. return '';
  526. $iCmtVParentId = bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT);
  527. $iCmtStart = isset($_REQUEST['CmtStart']) ? bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT) : -1;
  528. $iCmtPerView = isset($_REQUEST['CmtPerView']) ? bx_process_input($_REQUEST['CmtPerView'], BX_DATA_INT) : -1;
  529. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  530. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  531. $sCmtFilter = isset($_REQUEST['CmtFilter']) ? bx_process_input($_REQUEST['CmtFilter'], BX_DATA_TEXT) : '';
  532. return $this->getComments(array('vparent_id' => $iCmtVParentId, 'start' => $iCmtStart, 'per_view' => $iCmtPerView, 'type' => $sCmtBrowse, 'filter' => $sCmtFilter), array('type' => $sCmtDisplay));
  533. }
  534. public function actionGetImage ()
  535. {
  536. if (!$this->isEnabled())
  537. return '';
  538. $iImgId = bx_process_input(bx_get('ImgId'), BX_DATA_INT);
  539. return $this->getImage($iImgId);
  540. }
  541. public function actionSubmitPostForm()
  542. {
  543. if(!$this->isEnabled() || !$this->isPostReplyAllowed()) {
  544. $this->_echoResultJson(array());
  545. return;
  546. }
  547. $iCmtParentId = 0;
  548. if(bx_get('cmt_parent_id') !== false)
  549. $iCmtParentId = bx_process_input(bx_get('cmt_parent_id'), BX_DATA_INT);
  550. $this->_echoResultJson($this->getFormPost($iCmtParentId));
  551. }
  552. public function actionSubmitEditForm()
  553. {
  554. if (!$this->isEnabled()) {
  555. $this->_echoResultJson(array());
  556. return;
  557. };
  558. $iCmtId = 0;
  559. if(bx_get('cmt_id') !== false)
  560. $iCmtId = bx_process_input(bx_get('cmt_id'), BX_DATA_INT);
  561. $this->_echoResultJson($this->getFormEdit($iCmtId));
  562. }
  563. public function actionRemove()
  564. {
  565. if (!$this->isEnabled()) {
  566. $this->_echoResultJson(array());
  567. return;
  568. };
  569. $iCmtId = 0;
  570. if(bx_get('Cmt') !== false)
  571. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  572. $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
  573. if(!$aCmt) {
  574. $this->_echoResultJson(array('msg' => _t('_No such comment')));
  575. return;
  576. }
  577. if ($aCmt['cmt_replies'] > 0) {
  578. $this->_echoResultJson(array('msg' => _t('_Can not delete comments with replies')));
  579. return;
  580. }
  581. $iCmtAuthorId = $this->_getAuthorId();
  582. if(!$this->isRemoveAllowed($aCmt)) {
  583. $this->_echoResultJson(array('msg' => $aCmt['cmt_author_id'] == $iCmtAuthorId ? strip_tags($this->msgErrRemoveAllowed()) : _t('_Access denied')));
  584. return;
  585. }
  586. if($this->_oQuery->removeComment ($this->getId(), $aCmt['cmt_id'], $aCmt['cmt_parent_id'])) {
  587. $this->_triggerComment();
  588. bx_import('BxDolStorage');
  589. $oStorage = BxDolStorage::getObjectInstance($this->_sStorageObject);
  590. $aImages = $this->_oQuery->getImages($this->_aSystem['system_id'], $aCmt['cmt_id']);
  591. foreach($aImages as $aImage)
  592. $oStorage->deleteFile($aImage['image_id']);
  593. $this->_oQuery->deleteImages($this->_aSystem['system_id'], $aCmt['cmt_id']);
  594. $this->isRemoveAllowed(true);
  595. bx_import('BxDolAlerts');
  596. $oZ = new BxDolAlerts($this->_sSystem, 'commentRemoved', $this->getId(), $iCmtAuthorId, array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
  597. $oZ->alert();
  598. $this->_echoResultJson(array('id' => $iCmtId));
  599. return;
  600. }
  601. $this->_echoResultJson(array('msg' => _t('_cmt_err_cannot_perform_action')));
  602. }
  603. /**
  604. * Internal functions
  605. */
  606. protected function _getAuthorId ()
  607. {
  608. return isMember() ? bx_get_logged_profile_id() : 0;
  609. }
  610. protected function _getAuthorPassword ()
  611. {
  612. return isMember() ? $_COOKIE['memberPassword'] : "";
  613. }
  614. protected function _getAuthorIp ()
  615. {
  616. return getVisitorIP();
  617. }
  618. protected function _getAuthorInfo($iAuthorId = 0)
  619. {
  620. $oProfile = $this->_getAuthorObject($iAuthorId);
  621. return array(
  622. $oProfile->getDisplayName(),
  623. $oProfile->getUrl(),
  624. $oProfile->getThumb(),
  625. $oProfile->getUnit()
  626. );
  627. }
  628. protected function _getAuthorObject($iAuthorId = 0)
  629. {
  630. bx_import('BxDolProfile');
  631. $oProfile = BxDolProfile::getInstance($iAuthorId);
  632. if (!$oProfile) {
  633. bx_import('BxDolProfileUndefined');
  634. $oProfile = BxDolProfileUndefined::getInstance();
  635. }
  636. return $oProfile;
  637. }
  638. protected function _prepareTextForEdit ($s)
  639. {
  640. if ($this->isNl2br())
  641. return str_replace('<br />', "", $s);
  642. return $s;
  643. }
  644. protected function _prepareTextForSave ($s)
  645. {
  646. $iDataAction = $this->isNl2br() ? BX_DATA_TEXT_MULTILINE : BX_DATA_TEXT; // TODO: make sure that it is processed before output !
  647. return bx_process_input($s, $iDataAction);
  648. }
  649. protected function _prepareTextForOutput ($s)
  650. {
  651. $sHttp = '';
  652. $iDataAction = $this->isNl2br() ? BX_DATA_TEXT_MULTILINE : BX_DATA_TEXT;
  653. $sPattern = "/((https?|ftp|news):\/\/)?([a-z]([a-z0-9\-]*\.)+(aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|[a-z]{2})|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&amp;]*)?)?(#[a-z][a-z0-9_]*)?/";
  654. $aMatches = array();
  655. if(preg_match($sPattern, $s, $aMatches) && empty($aMatches[1]))
  656. $sHttp = 'http://';
  657. $s = bx_process_output($s, $iDataAction);
  658. $s = preg_replace($sPattern, '<a href="' . $sHttp . '$0" target="_blank">$0</a>', $s);
  659. return $s;
  660. }
  661. protected function _prepareParams(&$aBp, &$aDp)
  662. {
  663. $aBp['type'] = isset($aBp['type']) && !empty($aBp['type']) ? $aBp['type'] : $this->_sBrowseType;
  664. $aBp['filter'] = isset($aBp['filter']) && !empty($aBp['filter']) ? $aBp['filter'] : $this->_sBrowseFilter;
  665. $aBp['parent_id'] = isset($aBp['parent_id']) ? $aBp['parent_id'] : 0;
  666. $aBp['start'] = isset($aBp['start']) ? $aBp['start'] : -1;
  667. $aBp['per_view'] = isset($aBp['per_view']) ? $aBp['per_view'] : -1;
  668. $aBp['order']['by'] = isset($aBp['order_by']) ? $aBp['order_by'] : $this->_aOrder['by'];
  669. $aBp['order']['way'] = isset($aBp['order_way']) ? $aBp['order_way'] : $this->_aOrder['way'];
  670. $aDp['type'] = isset($aDp['type']) && !empty($aDp['type']) ? $aDp['type'] : $this->_sDisplayType;
  671. switch($aDp['type']) {
  672. case BX_CMT_DISPLAY_FLAT:
  673. $aBp['vparent_id'] = -1;
  674. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView(0);
  675. break;
  676. case BX_CMT_DISPLAY_THREADED:
  677. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView($aBp['vparent_id']);
  678. break;
  679. }
  680. switch ($aBp['type']) {
  681. case BX_CMT_BROWSE_POPULAR:
  682. $aBp['order'] = array(
  683. 'by' => BX_CMT_ORDER_BY_POPULAR,
  684. 'way' => BX_CMT_ORDER_WAY_DESC
  685. );
  686. break;
  687. }
  688. $aBp['count'] = $this->getCommentsCount($this->_iId, $aBp['vparent_id'], $aBp['filter']);
  689. if($aBp['start'] != -1)
  690. return;
  691. $aBp['start'] = 0;
  692. if($aBp['type'] == BX_CMT_BROWSE_TAIL) {
  693. $aBp['start'] = $aBp['count'] - $aBp['per_view'];
  694. if($aBp['start'] < 0) {
  695. $aBp['per_view'] += $aBp['start'];
  696. $aBp['start'] = 0;
  697. }
  698. }
  699. $this->_setUserChoice($aDp['type'], $aBp['type'], $aBp['filter']);
  700. }
  701. protected function _triggerComment()
  702. {
  703. if(!$this->_aSystem['trigger_table'])
  704. return false;
  705. $iId = $this->getId();
  706. if(!$iId)
  707. return false;
  708. $iCount = $this->getCommentsCount($iId);
  709. return $this->_oQuery->updateTriggerTable($iId, $iCount);
  710. }
  711. protected function _isSpam($s) {
  712. return bx_is_spam($s);
  713. }
  714. /**
  715. * Replace provided markers in a string
  716. * @param $mixed string or array to replace markers in
  717. * @return string where all occured markers are replaced
  718. */
  719. protected function _replaceMarkers ($mixed) {
  720. return bx_replace_markers($mixed, $this->_aMarkers);
  721. }
  722. protected function _getUserChoice()
  723. {
  724. $mixedDp = $mixedBpType = $mixedBpFilter = false;
  725. if(!isLogged())
  726. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  727. $iUserId = $this->_getAuthorId();
  728. bx_import('BxDolSession');
  729. $oSession = BxDolSession::getInstance();
  730. $mixedDp = $oSession->getValue($this->_sDpSessionKey . $iUserId);
  731. $mixedBpType = $oSession->getValue($this->_sBpSessionKeyType . $iUserId);
  732. $mixedBpFilter = $oSession->getValue($this->_sBpSessionKeyFilter . $iUserId);
  733. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  734. }
  735. protected function _setUserChoice($sDp, $sBpType, $sBpFilter)
  736. {
  737. if(!isLogged())
  738. return;
  739. $iUserId = $this->_getAuthorId();
  740. bx_import('BxDolSession');
  741. $oSession = BxDolSession::getInstance();
  742. if(!empty($sDp))
  743. $oSession->setValue($this->_sDpSessionKey . $iUserId, $sDp);
  744. if(!empty($sBpType))
  745. $oSession->setValue($this->_sBpSessionKeyType . $iUserId, $sBpType);
  746. if(!empty($sBpFilter))
  747. $oSession->setValue($this->_sBpSessionKeyFilter . $iUserId, $sBpFilter);
  748. }
  749. protected function _sendNotificationEmail($iCmtId, $iCmtParentId)
  750. {
  751. $aCmt = $this->getCommentRow($iCmtId);
  752. $aCmtParent = $this->getCommentRow($iCmtParentId);
  753. if(empty($aCmt) || !is_array($aCmt) || empty($aCmtParent) || !is_array($aCmtParent) || (int)$aCmt['cmt_author_id'] == (int)$aCmtParent['cmt_author_id'])
  754. return;
  755. $oProfile = $this->_getAuthorObject($aCmtParent['cmt_author_id']);
  756. bx_import('BxDolAccount');
  757. $iAccount = $oProfile->getAccountId();
  758. $aAccount = BxDolAccount::getInstance($iAccount)->getInfo();
  759. $aPlus = array();
  760. $aPlus['reply_text'] = bx_process_output($aCmt['cmt_text']);
  761. $aPlus['comment_url'] = sprintf('%scmts.php?sys=%s&id=1&cmt_id=%d', BX_DOL_URL_ROOT, $this->_sSystem, $iCmtParentId);
  762. bx_import('BxDolEmailTemplates');
  763. $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('t_CommentReplied', $aPlus);
  764. return $aTemplate && sendMail($aAccount['email'], $aTemplate['Subject'], $aTemplate['Body']);
  765. }
  766. }
  767. /** @} */