BxDolCmts.php 34 KB

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