BxDolCmts.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  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
  86. * - comments edit own
  87. * - comments remove own
  88. * - comments edit all
  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 implements iBxDolReplaceable
  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 __construct($sSystem, $iId, $iInit = 1)
  156. {
  157. parent::__construct();
  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, $iInit);
  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. public function init ($iId)
  264. {
  265. if (empty($this->iId) && $iId)
  266. $this->setId($iId);
  267. $this->addMarkers(array(
  268. 'object_id' => $this->getId(),
  269. 'user_id' => $this->_getAuthorId()
  270. ));
  271. }
  272. public function getId ()
  273. {
  274. return $this->_iId;
  275. }
  276. public function isEnabled ()
  277. {
  278. return isset($this->_aSystem['is_on']) && $this->_aSystem['is_on'];
  279. }
  280. public function getSystemId()
  281. {
  282. return $this->_aSystem['system_id'];
  283. }
  284. public function getSystemName()
  285. {
  286. return $this->_sSystem;
  287. }
  288. public function getStorageObjectName()
  289. {
  290. return $this->_sStorageObject;
  291. }
  292. public function getSystemInfo()
  293. {
  294. return $this->_aSystem;
  295. }
  296. public function getMaxLevel()
  297. {
  298. return $this->_iDpMaxLevel;
  299. }
  300. public function getOrder ()
  301. {
  302. return $this->_sOrder;
  303. }
  304. public function getPerView ($iCmtParentId = 0)
  305. {
  306. return $iCmtParentId == 0 ? $this->_aSystem['per_view'] : $this->_aSystem['per_view_replies'];
  307. }
  308. public function getBaseUrl()
  309. {
  310. return $this->_replaceMarkers($this->_sBaseUrl);
  311. }
  312. public function getListUrl()
  313. {
  314. return $this->getBaseUrl() . '#' . $this->getListAnchor();
  315. }
  316. public function getListAnchor()
  317. {
  318. return sprintf($this->_sListAnchor, str_replace('_', '-', $this->getSystemName()), $this->getId());
  319. }
  320. public function getConnectionObject($sType)
  321. {
  322. $sResult = '';
  323. switch($sType) {
  324. case BX_CMT_FILTER_FRIENDS:
  325. $sResult = $this->_sConnObjFriends;
  326. break;
  327. case BX_CMT_FILTER_SUBSCRIPTIONS:
  328. $sResult = $this->_sConnObjSubscriptions;
  329. break;
  330. }
  331. return $sResult;
  332. }
  333. public function getVoteObject($iId)
  334. {
  335. if(empty($this->_aSystem['object_vote']))
  336. return false;
  337. bx_import('BxDolVote');
  338. $oVote = BxDolVote::getObjectInstance($this->_aSystem['object_vote'], $iId);
  339. if(!$oVote->isEnabled())
  340. return false;
  341. return $oVote;
  342. }
  343. public function isNl2br ()
  344. {
  345. return $this->_aSystem['nl2br'];
  346. }
  347. public function isRatable ()
  348. {
  349. return $this->_aSystem['is_ratable'];
  350. }
  351. public function isAttachImageEnabled()
  352. {
  353. return true;
  354. }
  355. /**
  356. * set id to operate with votes
  357. */
  358. public function setId ($iId)
  359. {
  360. if ($iId == $this->getId()) return;
  361. $this->_iId = $iId;
  362. }
  363. /**
  364. * Add replace markers.
  365. * @param $a array of markers as key => value
  366. * @return true on success or false on error
  367. */
  368. public function addMarkers ($a)
  369. {
  370. if (empty($a) || !is_array($a))
  371. return false;
  372. $this->_aMarkers = array_merge ($this->_aMarkers, $a);
  373. return true;
  374. }
  375. /**
  376. * Database functions
  377. */
  378. public function getQueryObject ()
  379. {
  380. return $this->_oQuery;
  381. }
  382. public function getCommentsTableName ()
  383. {
  384. return $this->_oQuery->getTableName ();
  385. }
  386. public function getObjectTitle ($iObjectId = 0)
  387. {
  388. return $this->_oQuery->getObjectTitle ($iObjectId ? $iObjectId : $this->getId());
  389. }
  390. public function getCommentsCount ($iObjectId = 0, $iCmtVParentId = 0, $sFilter = '')
  391. {
  392. return $this->_oQuery->getCommentsCount ($iObjectId ? $iObjectId : $this->getId(), $iCmtVParentId, $this->_getAuthorId(), $sFilter);
  393. }
  394. public function getCommentsArray ($iVParentId, $sFilter, $aOrder, $iStart = 0, $iCount = -1)
  395. {
  396. return $this->_oQuery->getComments ($this->getId(), $iVParentId, $this->_getAuthorId(), $sFilter, $aOrder, $iStart, $iCount);
  397. }
  398. public function getCommentRow ($iCmtId)
  399. {
  400. return $this->_oQuery->getComment ($this->getId(), $iCmtId);
  401. }
  402. public function onObjectDelete ($iObjectId = 0)
  403. {
  404. // delete comments
  405. $aFiles = array();
  406. $this->_oQuery->deleteObjectComments ($iObjectId ? $iObjectId : $this->getId(), $aFiles);
  407. // delete files
  408. if ($aFiles) {
  409. bx_import('BxDolStorage');
  410. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  411. if ($oStorage)
  412. $oStorage->queueFilesForDeletion($aFiles);
  413. }
  414. }
  415. public static function onAuthorDelete ($iAuthorId)
  416. {
  417. bx_import('BxDolStorage');
  418. $aSystems = self::getSystems();
  419. foreach($aSystems as $sSystem => $aSystem) {
  420. $o = self::getObjectInstance($sSystem, 0);
  421. $oQuery = $o->getQueryObject();
  422. // delete comments
  423. $aFiles = array ();
  424. $oQuery->deleteAuthorComments($iAuthorId, $aFiles);
  425. // delete files
  426. $oStorage = BxDolStorage::getObjectInstance($o->getStorageObjectName());
  427. if ($oStorage)
  428. $oStorage->queueFilesForDeletion($aFiles);
  429. }
  430. return true;
  431. }
  432. public static function onModuleUninstall ($sModuleName, &$iFiles = null)
  433. {
  434. bx_import('BxDolStorage');
  435. $aSystems = self::getSystems();
  436. foreach($aSystems as $sSystem => $aSystem) {
  437. if (0 != strncasecmp($sModuleName, $sSystem, strlen($sModuleName)))
  438. continue;
  439. $o = self::getObjectInstance($sSystem, 0);
  440. $oQuery = $o->getQueryObject();
  441. // delete comments
  442. $aFiles = array ();
  443. $oQuery->deleteAll($aSystem['system_id'], $aFiles);
  444. // delete files
  445. $oStorage = BxDolStorage::getObjectInstance($o->getStorageObjectName());
  446. if ($oStorage && $aFiles)
  447. $oStorage->queueFilesForDeletion($aFiles);
  448. if (null !== $iFiles)
  449. $iFiles += count($aFiles);
  450. }
  451. return true;
  452. }
  453. /**
  454. * Permissions functions
  455. */
  456. public function checkAction ($sAction, $isPerformAction = false)
  457. {
  458. $iId = $this->_getAuthorId();
  459. $a = checkActionModule($iId, $sAction, 'system', $isPerformAction);
  460. return $a[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED;
  461. }
  462. public function checkActionErrorMsg ($sAction)
  463. {
  464. $iId = $this->_getAuthorId();
  465. $a = checkActionModule($iId, $sAction, 'system');
  466. return $a[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $a[CHECK_ACTION_MESSAGE] : '';
  467. }
  468. public function isVoteAllowed ($aCmt, $isPerformAction = false)
  469. {
  470. if(!$this->isRatable())
  471. return false;
  472. $oVote = $this->getVoteObject($aCmt['cmt_id']);
  473. if($oVote === false)
  474. return false;
  475. $iUserId = (int)$this->_getAuthorId();
  476. if($iUserId == 0)
  477. return false;
  478. if(isAdmin())
  479. return true;
  480. return $oVote->isAllowedVote($isPerformAction);
  481. }
  482. public function isPostReplyAllowed ($isPerformAction = false)
  483. {
  484. return $this->checkAction ('comments post', $isPerformAction);
  485. }
  486. public function msgErrPostReplyAllowed ()
  487. {
  488. return $this->checkActionErrorMsg('comments post');
  489. }
  490. public function isEditAllowed ($aCmt, $isPerformAction = false)
  491. {
  492. if(isAdmin())
  493. return true;
  494. if($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->checkAction ('comments edit own', $isPerformAction))
  495. return true;
  496. return $this->checkAction('comments edit all', $isPerformAction);
  497. }
  498. public function msgErrEditAllowed ()
  499. {
  500. return $this->checkActionErrorMsg ('comments edit own');
  501. }
  502. public function isRemoveAllowed ($aCmt, $isPerformAction = false)
  503. {
  504. if(isAdmin())
  505. return true;
  506. if($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->checkAction ('comments remove own', $isPerformAction))
  507. return true;
  508. return $this->checkAction ('comments remove all', $isPerformAction);
  509. }
  510. public function msgErrRemoveAllowed ()
  511. {
  512. return $this->checkActionErrorMsg('comments remove own');
  513. }
  514. /**
  515. * Actions functions
  516. */
  517. public function actionGetFormPost ()
  518. {
  519. if (!$this->isEnabled())
  520. return '';
  521. $iCmtParentId= isset($_REQUEST['CmtParent']) ? bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT) : 0;
  522. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  523. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  524. return $this->getFormBoxPost(array('parent_id' => $iCmtParentId, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
  525. }
  526. public function actionGetFormEdit ()
  527. {
  528. if (!$this->isEnabled()){
  529. $this->_echoResultJson(array());
  530. return;
  531. }
  532. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  533. $this->_echoResultJson($this->getFormEdit($iCmtId));
  534. }
  535. public function actionGetCmt ()
  536. {
  537. if (!$this->isEnabled())
  538. return '';
  539. $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
  540. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  541. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  542. $aCmt = $this->getCommentRow($iCmtId);
  543. $this->_echoResultJson(array(
  544. 'parent_id' => $aCmt['cmt_parent_id'],
  545. 'vparent_id' => $aCmt['cmt_vparent_id'],
  546. 'content' => $this->getComment($aCmt, array('type' => $sCmtBrowse), array('type' => $sCmtDisplay))
  547. ));
  548. }
  549. public function actionGetCmts ()
  550. {
  551. if (!$this->isEnabled())
  552. return '';
  553. $iCmtVParentId = bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT);
  554. $iCmtStart = isset($_REQUEST['CmtStart']) ? bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT) : -1;
  555. $iCmtPerView = isset($_REQUEST['CmtPerView']) ? bx_process_input($_REQUEST['CmtPerView'], BX_DATA_INT) : -1;
  556. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  557. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  558. $sCmtFilter = isset($_REQUEST['CmtFilter']) ? bx_process_input($_REQUEST['CmtFilter'], BX_DATA_TEXT) : '';
  559. return $this->getComments(array('vparent_id' => $iCmtVParentId, 'start' => $iCmtStart, 'per_view' => $iCmtPerView, 'type' => $sCmtBrowse, 'filter' => $sCmtFilter), array('type' => $sCmtDisplay));
  560. }
  561. public function actionGetImage ()
  562. {
  563. if (!$this->isEnabled())
  564. return '';
  565. $iImgId = bx_process_input(bx_get('ImgId'), BX_DATA_INT);
  566. return $this->getImage($iImgId);
  567. }
  568. public function actionSubmitPostForm()
  569. {
  570. if(!$this->isEnabled() || !$this->isPostReplyAllowed()) {
  571. $this->_echoResultJson(array());
  572. return;
  573. }
  574. $iCmtParentId = 0;
  575. if(bx_get('cmt_parent_id') !== false)
  576. $iCmtParentId = bx_process_input(bx_get('cmt_parent_id'), BX_DATA_INT);
  577. $this->_echoResultJson($this->getFormPost($iCmtParentId));
  578. }
  579. public function actionSubmitEditForm()
  580. {
  581. if (!$this->isEnabled()) {
  582. $this->_echoResultJson(array());
  583. return;
  584. };
  585. $iCmtId = 0;
  586. if(bx_get('cmt_id') !== false)
  587. $iCmtId = bx_process_input(bx_get('cmt_id'), BX_DATA_INT);
  588. $this->_echoResultJson($this->getFormEdit($iCmtId));
  589. }
  590. public function actionRemove()
  591. {
  592. if (!$this->isEnabled()) {
  593. $this->_echoResultJson(array());
  594. return;
  595. };
  596. $iCmtId = 0;
  597. if(bx_get('Cmt') !== false)
  598. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  599. $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
  600. if(!$aCmt) {
  601. $this->_echoResultJson(array('msg' => _t('_No such comment')));
  602. return;
  603. }
  604. if ($aCmt['cmt_replies'] > 0) {
  605. $this->_echoResultJson(array('msg' => _t('_Can not delete comments with replies')));
  606. return;
  607. }
  608. $iCmtAuthorId = $this->_getAuthorId();
  609. if(!$this->isRemoveAllowed($aCmt)) {
  610. $this->_echoResultJson(array('msg' => $aCmt['cmt_author_id'] == $iCmtAuthorId ? strip_tags($this->msgErrRemoveAllowed()) : _t('_Access denied')));
  611. return;
  612. }
  613. if($this->_oQuery->removeComment ($this->getId(), $aCmt['cmt_id'], $aCmt['cmt_parent_id'])) {
  614. $this->_triggerComment();
  615. bx_import('BxDolStorage');
  616. $oStorage = BxDolStorage::getObjectInstance($this->_sStorageObject);
  617. $aImages = $this->_oQuery->getImages($this->_aSystem['system_id'], $aCmt['cmt_id']);
  618. foreach($aImages as $aImage)
  619. $oStorage->deleteFile($aImage['image_id']);
  620. $this->_oQuery->deleteImages($this->_aSystem['system_id'], $aCmt['cmt_id']);
  621. $this->isRemoveAllowed(true);
  622. bx_import('BxDolAlerts');
  623. $oZ = new BxDolAlerts($this->_sSystem, 'commentRemoved', $this->getId(), $iCmtAuthorId, array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
  624. $oZ->alert();
  625. $this->_echoResultJson(array('id' => $iCmtId));
  626. return;
  627. }
  628. $this->_echoResultJson(array('msg' => _t('_cmt_err_cannot_perform_action')));
  629. }
  630. /**
  631. * Internal functions
  632. */
  633. protected function _getAuthorId ()
  634. {
  635. return isMember() ? bx_get_logged_profile_id() : 0;
  636. }
  637. protected function _getAuthorPassword ()
  638. {
  639. return isMember() ? $_COOKIE['memberPassword'] : "";
  640. }
  641. protected function _getAuthorIp ()
  642. {
  643. return getVisitorIP();
  644. }
  645. protected function _getAuthorInfo($iAuthorId = 0)
  646. {
  647. $oProfile = $this->_getAuthorObject($iAuthorId);
  648. return array(
  649. $oProfile->getDisplayName(),
  650. $oProfile->getUrl(),
  651. $oProfile->getThumb(),
  652. $oProfile->getUnit()
  653. );
  654. }
  655. protected function _getAuthorObject($iAuthorId = 0)
  656. {
  657. bx_import('BxDolProfile');
  658. $oProfile = BxDolProfile::getInstance($iAuthorId);
  659. if (!$oProfile) {
  660. bx_import('BxDolProfileUndefined');
  661. $oProfile = BxDolProfileUndefined::getInstance();
  662. }
  663. return $oProfile;
  664. }
  665. protected function _prepareTextForEdit ($s)
  666. {
  667. if ($this->isNl2br())
  668. return htmlspecialchars_decode(str_replace('<br />', "", $s));
  669. return $s;
  670. }
  671. protected function _prepareTextForSave ($s)
  672. {
  673. $iDataAction = $this->isNl2br() ? BX_DATA_TEXT_MULTILINE : BX_DATA_HTML;
  674. return bx_process_input($s, $iDataAction);
  675. }
  676. protected function _prepareTextForOutput ($s)
  677. {
  678. $sHttp = '';
  679. $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_]*)?/";
  680. $aMatches = array();
  681. if(preg_match($sPattern, $s, $aMatches) && empty($aMatches[1]))
  682. $sHttp = 'http://';
  683. $s = bx_process_output($s, BX_DATA_HTML);
  684. $s = preg_replace($sPattern, '<a href="' . $sHttp . '$0" target="_blank">$0</a>', $s);
  685. return $s;
  686. }
  687. protected function _prepareParams(&$aBp, &$aDp)
  688. {
  689. $aBp['type'] = isset($aBp['type']) && !empty($aBp['type']) ? $aBp['type'] : $this->_sBrowseType;
  690. $aBp['filter'] = isset($aBp['filter']) && !empty($aBp['filter']) ? $aBp['filter'] : $this->_sBrowseFilter;
  691. $aBp['parent_id'] = isset($aBp['parent_id']) ? $aBp['parent_id'] : 0;
  692. $aBp['start'] = isset($aBp['start']) ? $aBp['start'] : -1;
  693. $aBp['per_view'] = isset($aBp['per_view']) ? $aBp['per_view'] : -1;
  694. $aBp['order']['by'] = isset($aBp['order_by']) ? $aBp['order_by'] : $this->_aOrder['by'];
  695. $aBp['order']['way'] = isset($aBp['order_way']) ? $aBp['order_way'] : $this->_aOrder['way'];
  696. $aDp['type'] = isset($aDp['type']) && !empty($aDp['type']) ? $aDp['type'] : $this->_sDisplayType;
  697. switch($aDp['type']) {
  698. case BX_CMT_DISPLAY_FLAT:
  699. $aBp['vparent_id'] = -1;
  700. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView(0);
  701. break;
  702. case BX_CMT_DISPLAY_THREADED:
  703. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView($aBp['vparent_id']);
  704. break;
  705. }
  706. switch ($aBp['type']) {
  707. case BX_CMT_BROWSE_POPULAR:
  708. $aBp['order'] = array(
  709. 'by' => BX_CMT_ORDER_BY_POPULAR,
  710. 'way' => BX_CMT_ORDER_WAY_DESC
  711. );
  712. break;
  713. }
  714. $aBp['count'] = $this->getCommentsCount($this->_iId, $aBp['vparent_id'], $aBp['filter']);
  715. if($aBp['start'] != -1)
  716. return;
  717. $aBp['start'] = 0;
  718. if($aBp['type'] == BX_CMT_BROWSE_TAIL) {
  719. $aBp['start'] = $aBp['count'] - $aBp['per_view'];
  720. if($aBp['start'] < 0) {
  721. $aBp['per_view'] += $aBp['start'];
  722. $aBp['start'] = 0;
  723. }
  724. }
  725. $this->_setUserChoice($aDp['type'], $aBp['type'], $aBp['filter']);
  726. }
  727. protected function _triggerComment()
  728. {
  729. if(!$this->_aSystem['trigger_table'])
  730. return false;
  731. $iId = $this->getId();
  732. if(!$iId)
  733. return false;
  734. $iCount = $this->getCommentsCount($iId);
  735. return $this->_oQuery->updateTriggerTable($iId, $iCount);
  736. }
  737. /**
  738. * Replace provided markers in a string
  739. * @param $mixed string or array to replace markers in
  740. * @return string where all occured markers are replaced
  741. */
  742. protected function _replaceMarkers ($mixed)
  743. {
  744. return bx_replace_markers($mixed, $this->_aMarkers);
  745. }
  746. protected function _getUserChoice()
  747. {
  748. $mixedDp = $mixedBpType = $mixedBpFilter = false;
  749. if(!isLogged())
  750. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  751. $iUserId = $this->_getAuthorId();
  752. bx_import('BxDolSession');
  753. $oSession = BxDolSession::getInstance();
  754. $mixedDp = $oSession->getValue($this->_sDpSessionKey . $iUserId);
  755. $mixedBpType = $oSession->getValue($this->_sBpSessionKeyType . $iUserId);
  756. $mixedBpFilter = $oSession->getValue($this->_sBpSessionKeyFilter . $iUserId);
  757. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  758. }
  759. protected function _setUserChoice($sDp, $sBpType, $sBpFilter)
  760. {
  761. if(!isLogged())
  762. return;
  763. $iUserId = $this->_getAuthorId();
  764. bx_import('BxDolSession');
  765. $oSession = BxDolSession::getInstance();
  766. if(!empty($sDp))
  767. $oSession->setValue($this->_sDpSessionKey . $iUserId, $sDp);
  768. if(!empty($sBpType))
  769. $oSession->setValue($this->_sBpSessionKeyType . $iUserId, $sBpType);
  770. if(!empty($sBpFilter))
  771. $oSession->setValue($this->_sBpSessionKeyFilter . $iUserId, $sBpFilter);
  772. }
  773. protected function _sendNotificationEmail($iCmtId, $iCmtParentId)
  774. {
  775. $aCmt = $this->getCommentRow($iCmtId);
  776. $aCmtParent = $this->getCommentRow($iCmtParentId);
  777. if(empty($aCmt) || !is_array($aCmt) || empty($aCmtParent) || !is_array($aCmtParent) || (int)$aCmt['cmt_author_id'] == (int)$aCmtParent['cmt_author_id'])
  778. return;
  779. $oProfile = $this->_getAuthorObject($aCmtParent['cmt_author_id']);
  780. bx_import('BxDolAccount');
  781. $iAccount = $oProfile->getAccountId();
  782. $aAccount = BxDolAccount::getInstance($iAccount)->getInfo();
  783. $aPlus = array();
  784. $aPlus['reply_text'] = bx_process_output($aCmt['cmt_text']);
  785. $aPlus['comment_url'] = sprintf('%scmts.php?sys=%s&id=1&cmt_id=%d', BX_DOL_URL_ROOT, $this->_sSystem, $iCmtParentId);
  786. bx_import('BxDolEmailTemplates');
  787. $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('t_CommentReplied', $aPlus);
  788. return $aTemplate && sendMail($aAccount['email'], $aTemplate['Subject'], $aTemplate['Body']);
  789. }
  790. }
  791. /** @} */