BxDolCmts.php 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. bx_import('BxDolAcl');
  10. bx_import('BxDolPrivacy');
  11. define('BX_DOL_CMT_TYPE_COMMENTS', 'comments');
  12. define('BX_DOL_CMT_TYPE_REVIEWS', 'reviews');
  13. define('BX_CMT_OLD_VOTES', 365*86400); ///< comment votes older than this number of seconds will be deleted automatically
  14. define('BX_CMT_ACTION_POST', 'post');
  15. define('BX_CMT_ACTION_EDIT', 'edit');
  16. define('BX_CMT_DISPLAY_FLAT', 'flat');
  17. define('BX_CMT_DISPLAY_THREADED', 'threaded');
  18. define('BX_CMT_BROWSE_HEAD', 'head');
  19. define('BX_CMT_BROWSE_TAIL', 'tail');
  20. define('BX_CMT_BROWSE_POPULAR', 'popular');
  21. define('BX_CMT_BROWSE_CONNECTION', 'connection');
  22. define('BX_CMT_ORDER_BY_DATE', 'date');
  23. define('BX_CMT_ORDER_BY_POPULAR', 'popular');
  24. define('BX_CMT_FILTER_ALL', 'all');
  25. define('BX_CMT_FILTER_OTHERS', 'others');
  26. define('BX_CMT_FILTER_FRIENDS', 'friends');
  27. define('BX_CMT_FILTER_SUBSCRIPTIONS', 'subscriptions');
  28. define('BX_CMT_FILTER_PINNED', 'pinned');
  29. define('BX_CMT_ORDER_WAY_ASC', 'asc');
  30. define('BX_CMT_ORDER_WAY_DESC', 'desc');
  31. define('BX_CMT_PFP_TOP', 'top');
  32. define('BX_CMT_PFP_BOTTOM', 'bottom');
  33. define('BX_CMT_RATE_VALUE_PLUS', 1);
  34. define('BX_CMT_RATE_VALUE_MINUS', -1);
  35. define('BX_CMT_USAGE_BLOCK', 'block');
  36. define('BX_CMT_USAGE_INLINE', 'inline');
  37. define('BX_CMT_USAGE_DEFAULT', BX_CMT_USAGE_BLOCK);
  38. define('BX_CMT_STATUS_ACTIVE', 'active');
  39. define('BX_CMT_STATUS_HIDDEN', 'hidden');
  40. define('BX_CMT_STATUS_PENDING', 'pending');
  41. /**
  42. * Comments for any content
  43. *
  44. * Related classes:
  45. * - BxDolCmtsQuery - comments database queries
  46. * - BxBaseCmts - comments base representation
  47. * - BxTemplCmts - custom template representation
  48. *
  49. * AJAX comments for any content.
  50. * Self moderated - users rate all comments, and if comment is
  51. * below viewing treshold it is hidden by default.
  52. *
  53. * To add comments section to your module you need to add a record to 'sys_objects_cmts' table:
  54. *
  55. * - ID - autoincremented id for internal usage
  56. * - ObjectName - your unique module name, with vendor prefix, lowercase and spaces are underscored
  57. * - TableCmts - table name where comments are stored
  58. * - Html - 0 - convert new lines to <br /> on saving, 1 - standard(default) visual editor, 2 - full visual editor, 3 - mini visual editor.
  59. * - PerView - number of comments on a page
  60. * - IsRatable - 0 or 1 allow to rate comments or not
  61. * - ViewingThreshold - comment viewing treshost, if comment is below this number it is hidden by default
  62. * - IsOn - is this comment object enabled
  63. * - RootStylePrefix - toot comments style prefix, if you need root comments look different\
  64. * - ObjectVote - Vote object name to process comments' votes. May be empty if Comment Vote is not needed.
  65. * - TriggerTable - table to be updated upon each comment
  66. * - TriggerFieldId - TriggerTable table field with unique record id of
  67. * - TriggerFieldComments - TriggerTable table field with comments count, it will be updated automatically upon eaech comment
  68. * - ClassName - your custom class name if you need to override default class, this class must have the same constructor arguments
  69. * - ClassFile - file where your ClassName is stored.
  70. *
  71. * You can refer to BoonEx modules for sample record in this table.
  72. *
  73. *
  74. *
  75. * @section example Example of usage:
  76. * After filling in the table you can show comments section in any place, using the following code:
  77. *
  78. * @code
  79. * $o = new BxTemplCmts('value of ObjectName field', $iYourEntryId);
  80. * if ($o->isEnabled())
  81. * echo $o->getCommentsBlock ();
  82. * @endcode
  83. *
  84. * Please note that you never need to use BxDolCmts class directly, use BxTemplCmts instead.
  85. * Also if you override comments class with your own then make it child of BxTemplCmts class.
  86. *
  87. *
  88. *
  89. * @section acl Memberships/ACL:
  90. * - comments post
  91. * - comments edit own
  92. * - comments remove own
  93. * - comments edit all
  94. *
  95. *
  96. *
  97. * @section alerts Alerts:
  98. * Alerts type/unit - every module has own type/unit, it equals to ObjectName.
  99. *
  100. * The following alerts are rised
  101. *
  102. * - commentPost - comment was posted
  103. * - $iObjectId - entry id
  104. * - $iSenderId - author of comment
  105. * - $aExtra['comment_id'] - just added comment id
  106. *
  107. * - commentRemoved - comments was removed
  108. * - $iObjectId - entry id
  109. * - $iSenderId - comment deleter id
  110. * - $aExtra['comment_id'] - removed comment id
  111. *
  112. * - commentUpdated - comments was updated
  113. * - $iObjectId - entry id
  114. * - $iSenderId - comment deleter id
  115. * - $aExtra['comment_id'] - updated comment id
  116. *
  117. * - commentRated - comments was rated
  118. * - $iObjectId - entry id
  119. * - $iSenderId - comment rater id
  120. * - $aExtra['comment_id'] - rated comment id
  121. * - $aExtra['rate'] - comment rate 1 or -1
  122. *
  123. */
  124. class BxDolCmts extends BxDolFactory implements iBxDolReplaceable, iBxDolContentInfoService
  125. {
  126. /**
  127. * System tables which are UNITED for all
  128. * comment systems and cannot be overwritten.
  129. */
  130. public static $sTableSystems = 'sys_objects_cmts';
  131. public static $sTableIds = 'sys_cmts_ids';
  132. /**
  133. * System tables which are used by default and
  134. * can be overwritten in comment systems.
  135. * @see BxDolCmts::getTableNameImages and BxDolCmts::getTableNameImages2Entries
  136. */
  137. protected $_sTableImages = 'sys_cmts_images';
  138. protected $_sTableImages2Entries = 'sys_cmts_images2entries';
  139. protected $_aElementDefaults;
  140. protected $_aElementDefaultsApi;
  141. protected $_aElementParamsApi; //--- Params from DefaultsApi array to be passed to Api
  142. protected $_bIsApi;
  143. protected $_sType;
  144. protected $_oQuery = null;
  145. protected $_oTemplate = null;
  146. protected $_bPostQuote;
  147. protected $_bMinPostForm;
  148. protected $_sFormObject;
  149. protected $_sFormDisplayPost;
  150. protected $_sFormDisplayEdit;
  151. protected $_sConnObjFriends;
  152. protected $_sConnObjSubscriptions;
  153. protected $_sMenuObjManage;
  154. protected $_sMenuObjActions;
  155. protected $_sMenuObjCounters;
  156. protected $_sMenuObjMeta;
  157. protected $_sMetatagsObj;
  158. protected $_sViewUrl = '';
  159. protected $_sBaseUrl = '';
  160. protected $_sListAnchor = '';
  161. protected $_sItemAnchor = '';
  162. protected $_aSystems = [];
  163. protected $_sSystem = 'profile'; ///< current comment system name
  164. protected $_aSystem = []; ///< current comments system array
  165. protected $_iId = 0; ///< obect id to be commented
  166. protected $_iAuthorId = 0; ///< currently logged in user who browse, post, etc.
  167. protected $_aParams = [];
  168. protected $_aT = []; ///< an array of lang keys
  169. protected $_aMarkers = [];
  170. protected $_sDisplayType = '';
  171. protected $_sDpSessionKey = '';
  172. protected $_iDpMaxLevel = 0;
  173. protected $_sBrowseType = '';
  174. protected $_bBrowseFilter = false;
  175. protected $_sBrowseFilter = '';
  176. protected $_sBpSessionKeyType = '';
  177. protected $_sBpSessionKeyFilter = '';
  178. protected $_aOrder = array();
  179. protected $_sSnippetLenthLiveSearch = 50;
  180. protected $_iRememberTime = 2592000;
  181. protected $_bLiveUpdates = true;
  182. /**
  183. * Constructor
  184. * $sSystem - comments system name
  185. * $iId - obect id to be commented
  186. */
  187. protected function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
  188. {
  189. parent::__construct();
  190. $this->_bIsApi = bx_is_api();
  191. $this->_sType = BX_DOL_CMT_TYPE_COMMENTS;
  192. $this->_aSystems = $this->getSystems();
  193. if(!isset($this->_aSystems[$sSystem]))
  194. return;
  195. $this->_sSystem = $sSystem;
  196. $this->_aSystem = $this->_aSystems[$sSystem];
  197. $this->_aSystem['is_browse_filter'] = (int)$this->_bBrowseFilter;
  198. $this->_iAuthorId = $this->_getAuthorId();
  199. $this->_iDpMaxLevel = (int)$this->_aSystem['number_of_levels'];
  200. $this->_sDisplayType = $this->_iDpMaxLevel == 0 ? BX_CMT_DISPLAY_FLAT : BX_CMT_DISPLAY_THREADED;
  201. $this->_sDpSessionKey = 'bx_' . $this->_sSystem . '_dp_';
  202. $this->_sBrowseType = $this->_aSystem['browse_type'];
  203. $this->_sBrowseFilter = BX_CMT_FILTER_ALL;
  204. $this->_sBpSessionKeyType = 'bx_' . $this->_sSystem . '_bpt_';
  205. $this->_sBpSessionKeyFilter = 'bx_' . $this->_sSystem . '_bpf_';
  206. $this->_aOrder = array(
  207. 'by' => BX_CMT_ORDER_BY_DATE,
  208. 'way' => BX_CMT_ORDER_WAY_ASC
  209. );
  210. list($mixedUserDp, $mixedUserBpType, $mixedUserBpFilter) = $this->_getUserChoice();
  211. if(!empty($mixedUserDp))
  212. $this->_sDisplayType = $mixedUserDp;
  213. if(!empty($mixedUserBpType))
  214. $this->_sBrowseType = $mixedUserBpType;
  215. if(!empty($mixedUserBpFilter))
  216. $this->_sBrowseFilter = $mixedUserBpFilter;
  217. $this->_sViewUrl = 'page.php?i=cmts-view';
  218. $this->_sBaseUrl = $this->_aSystem['base_url'];
  219. $this->_sListAnchor = "cmts-anchor-%s-%d";
  220. $this->_sItemAnchor = "cmt-anchor-%s-%d-%d";
  221. $this->_oQuery = new BxDolCmtsQuery($this);
  222. $this->_bPostQuote = false;
  223. $this->_bMinPostForm = true;
  224. $this->_sFormObject = 'sys_comment';
  225. $this->_sFormDisplayPost = 'sys_comment_post';
  226. $this->_sFormDisplayEdit = 'sys_comment_edit';
  227. $this->_sConnObjFriends = 'sys_profiles_friends';
  228. $this->_sConnObjSubscriptions = 'sys_profiles_subscriptions';
  229. $this->_sMenuObjManage = 'sys_cmts_item_manage';
  230. $this->_sMenuObjActions = 'sys_cmts_item_actions';
  231. $this->_sMenuObjCounters = 'sys_cmts_item_counters';
  232. $this->_sMenuObjMeta = 'sys_cmts_item_meta';
  233. $this->_sMetatagsObj = 'sys_cmts';
  234. if(($aParams = bx_get('params')) !== false) {
  235. if(is_string($aParams))
  236. $aParams = json_decode($aParams, true);
  237. if(!empty($aParams) && is_array($aParams))
  238. $this->_aParams = array_merge($this->_aParams, $aParams);
  239. }
  240. $this->_aT = [
  241. 'block_comments_title' => '_cmt_block_comments_title',
  242. 'txt_sample_single' => '_cmt_txt_sample_comment_single',
  243. 'txt_sample_vote_single' => '_cmt_txt_sample_vote_single',
  244. 'txt_sample_reaction_single' => '_cmt_txt_sample_reaction_single',
  245. 'txt_sample_score_up_single' => '_cmt_txt_sample_score_up_single',
  246. 'txt_sample_score_down_single' => '_cmt_txt_sample_score_down_single',
  247. 'txt_min_form_placeholder' => '_cmt_txt_min_form_placeholder'
  248. ];
  249. if ($iInit)
  250. $this->init($iId);
  251. if ($oTemplate)
  252. $this->_oTemplate = $oTemplate;
  253. else
  254. $this->_oTemplate = BxDolTemplate::getInstance();
  255. }
  256. /**
  257. * get comments object instanse
  258. * @param $sSys comments object name
  259. * @param $iId associated content id, where comments are postred in
  260. * @param $iInit perform initialization
  261. * @return null on error, or ready to use class instance
  262. */
  263. public static function getObjectInstance($sSys, $iId, $iInit = true, $oTemplate = false)
  264. {
  265. if(isset($GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId]))
  266. return $GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId];
  267. $aSystems = self::getSystems();
  268. if (!isset($aSystems[$sSys]))
  269. return null;
  270. $sClassName = 'BxTemplCmts';
  271. if(!empty($aSystems[$sSys]['class_name'])) {
  272. $sClassName = $aSystems[$sSys]['class_name'];
  273. if(!empty($aSystems[$sSys]['class_file']))
  274. require_once(BX_DIRECTORY_PATH_ROOT . $aSystems[$sSys]['class_file']);
  275. }
  276. $o = new $sClassName($sSys, $iId, $iInit, $oTemplate);
  277. return ($GLOBALS['bxDolClasses']['BxDolCmts!' . $sSys . $iId] = $o);
  278. }
  279. /**
  280. * get comments object instanse
  281. * @param $iUniqId unique comment id
  282. * @return null on error, or ready to use class instance
  283. */
  284. public static function getObjectInstanceByUniqId($iUniqId, $iInit = true, $oTemplate = false)
  285. {
  286. $aData = BxDolCmtsQuery::getInfoByUniqId($iUniqId);
  287. if(empty($aData) || !is_array($aData))
  288. return null;
  289. return self::getObjectInstance($aData['system_name'], $aData['cmt_object_id']);
  290. }
  291. public static function &getSystems ()
  292. {
  293. $sKey = 'bx_dol_cache_memory_cmts_systems';
  294. if (!isset($GLOBALS[$sKey])) {
  295. $GLOBALS[$sKey] = BxDolDb::getInstance()->fromCache('sys_objects_cmts', 'getAllWithKey', '
  296. SELECT
  297. `ID` as `system_id`,
  298. `Name` AS `name`,
  299. `Module` AS `module`,
  300. `Table` AS `table`,
  301. `CharsPostMin` AS `chars_post_min`,
  302. `CharsPostMax` AS `chars_post_max`,
  303. `CharsDisplayMax` AS `chars_display_max`,
  304. `Html` AS `html`,
  305. `PerView` AS `per_view`,
  306. `PerViewReplies` AS `per_view_replies`,
  307. `BrowseType` AS `browse_type`,
  308. `IsBrowseSwitch` AS `is_browse_switch`,
  309. `PostFormPosition` AS `post_form_position`,
  310. `NumberOfLevels` AS `number_of_levels`,
  311. `IsDisplaySwitch` AS `is_display_switch`,
  312. `IsRatable` AS `is_ratable`,
  313. `ViewingThreshold` AS `viewing_threshold`,
  314. `IsOn` AS `is_on`,
  315. `RootStylePrefix` AS `root_style_prefix`,
  316. `BaseUrl` AS `base_url`,
  317. `ObjectVote` AS `object_vote`,
  318. `ObjectReaction` AS `object_reaction`,
  319. `ObjectScore` AS `object_score`,
  320. `ObjectReport` AS `object_report`,
  321. `TriggerTable` AS `trigger_table`,
  322. `TriggerFieldId` AS `trigger_field_id`,
  323. `TriggerFieldAuthor` AS `trigger_field_author`,
  324. `TriggerFieldTitle` AS `trigger_field_title`,
  325. `TriggerFieldComments` AS `trigger_field_comments`,
  326. `ClassName` AS `class_name`,
  327. `ClassFile` AS `class_file`
  328. FROM `' . self::$sTableSystems . '`', 'name');
  329. }
  330. return $GLOBALS[$sKey];
  331. }
  332. public static function getGlobalInfo ($iUniqueId)
  333. {
  334. return BxDolDb::getInstance()->getRow("SELECT `ti`.*, `ts`.`Name` AS `system_name` FROM `" . self::$sTableIds . "` AS `ti` LEFT JOIN `" . self::$sTableSystems . "` AS `ts` ON `ti`.`system_id`=`ts`.`ID` WHERE `ti`.`id`=:id LIMIT 1", array(
  335. 'id' => (int)$iUniqueId
  336. ));
  337. }
  338. public static function getGlobalNumByParams($aParams = [])
  339. {
  340. $sQuery = "SELECT COUNT(*) FROM `" . self::$sTableIds . "` WHERE 1";
  341. foreach($aParams as $aValue)
  342. $sQuery .= " AND `" . $aValue['key'] ."` " . $aValue['operator'] . " '" . $aValue['value'] . "'";
  343. return BxDolDb::getInstance()->getOne($sQuery);
  344. }
  345. public function init ($iId)
  346. {
  347. if (empty($this->iId) && $iId)
  348. $this->setId($iId);
  349. $this->addMarkers(array(
  350. 'object_id' => $this->getId(),
  351. 'user_id' => $this->_getAuthorId()
  352. ));
  353. }
  354. public function setParam($sName, $sValue)
  355. {
  356. $this->_aParams[$sName] = $sValue;
  357. }
  358. public function isParam($sName)
  359. {
  360. return isset($this->_aParams[$sName]);
  361. }
  362. public function getParam($sName)
  363. {
  364. return $this->_aParams[$sName];
  365. }
  366. public function getId ()
  367. {
  368. return $this->_iId;
  369. }
  370. public function isEnabled ()
  371. {
  372. return isset($this->_aSystem['is_on']) && $this->_aSystem['is_on'];
  373. }
  374. public function getSystemId()
  375. {
  376. return $this->_aSystem['system_id'];
  377. }
  378. public function getSystemName()
  379. {
  380. return $this->_sSystem;
  381. }
  382. public function getSystemInfo()
  383. {
  384. return $this->_aSystem;
  385. }
  386. public function getStorageObjectName()
  387. {
  388. return $this->_getFormObject()->getStorageObjectName();
  389. }
  390. public function getTranscoderPreviewName()
  391. {
  392. return $this->_getFormObject()->getTranscoderPreviewName();
  393. }
  394. public function getFormObject()
  395. {
  396. return $this->_getFormObject();
  397. }
  398. public function getTableNameImages()
  399. {
  400. return $this->_sTableImages;
  401. }
  402. public function getTableNameImages2Entries()
  403. {
  404. return $this->_sTableImages2Entries;
  405. }
  406. public function getLanguageKey($sIndex)
  407. {
  408. return isset($this->_aT[$sIndex]) ? $this->_aT[$sIndex] : '';
  409. }
  410. public function getMaxLevel()
  411. {
  412. return $this->_iDpMaxLevel;
  413. }
  414. public function getOrder ()
  415. {
  416. return $this->_sOrder;
  417. }
  418. public function getPerView ($iCmtParentId = 0)
  419. {
  420. return $iCmtParentId == 0 ? $this->_aSystem['per_view'] : $this->_aSystem['per_view_replies'];
  421. }
  422. public function getStatusAdmin()
  423. {
  424. return $this->isEditAllowedAll() || $this->isRemoveAllowedAll() || $this->isAutoApprove() ? BX_CMT_STATUS_ACTIVE : BX_CMT_STATUS_PENDING;
  425. }
  426. public function getViewUrl($iCmtId, $bAbsolute = true)
  427. {
  428. if(empty($this->_aSystem['trigger_field_title']))
  429. return '';
  430. $s = BxDolPermalinks::getInstance()->permalink($this->_sViewUrl, [
  431. 'sys' => $this->_sSystem,
  432. 'id' => $this->_iId,
  433. 'cmt_id' => $iCmtId
  434. ]);
  435. return $bAbsolute ? bx_absolute_url($s) : $s;
  436. }
  437. public function getViewText($mixedItem)
  438. {
  439. if(!is_array($mixedItem))
  440. $mixedItem = $this->getCommentSimple((int)$mixedItem);
  441. if(empty($mixedItem) || !is_array($mixedItem))
  442. return '';
  443. return $this->_prepareTextForOutput($mixedItem['cmt_text'], (int)$mixedItem['cmt_id']);
  444. }
  445. public function getBaseUrl()
  446. {
  447. $sUrl = $this->_replaceMarkers($this->_sBaseUrl);
  448. $sUrl = BxDolPermalinks::getInstance()->permalink($sUrl);
  449. if(get_mb_substr($sUrl, 0, 6) != 'http:/' && get_mb_substr($sUrl, 0, 7) != 'https:/')
  450. $sUrl = BX_DOL_URL_ROOT . $sUrl;
  451. return $sUrl;
  452. }
  453. public function getListUrl()
  454. {
  455. $sBaseUrl = $this->getBaseUrl();
  456. if(empty($sBaseUrl))
  457. return '';
  458. return $sBaseUrl . $this->getListAnchor(true);
  459. }
  460. public function getItemUrl($iItemId)
  461. {
  462. $sBaseUrl = $this->getBaseUrl();
  463. if(empty($sBaseUrl))
  464. return '';
  465. return $sBaseUrl . $this->getItemAnchor($iItemId, true);
  466. }
  467. public function getListAnchor($bWithHash = false)
  468. {
  469. return ($bWithHash ? '#' : '') . sprintf($this->_sListAnchor, str_replace('_', '-', $this->getSystemName()), $this->getId());
  470. }
  471. public function getItemAnchor($iItemId, $bWithHash = false)
  472. {
  473. return ($bWithHash ? '#' : '') . sprintf($this->_sItemAnchor, str_replace('_', '-', $this->getSystemName()), $this->getId(), $iItemId);
  474. }
  475. public function getAttachments($iCmtId)
  476. {
  477. $aResult = array();
  478. if(!$this->isAttachImageEnabled())
  479. return $aResult;
  480. $aFiles = $this->_oQuery->getFiles($this->_aSystem['system_id'], $iCmtId);
  481. if(empty($aFiles) || !is_array($aFiles))
  482. return $aResult;
  483. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  484. $oTranscoder = BxDolTranscoderImage::getObjectInstance($this->getTranscoderPreviewName());
  485. foreach($aFiles as $aFile) {
  486. $bImage = $oTranscoder && $oTranscoder->isMimeTypeSupported($aFile['mime_type']);
  487. $sPreview = '';
  488. if($bImage)
  489. $sPreview = $oTranscoder->getFileUrl($aFile['image_id']);
  490. if(!$sPreview)
  491. $sPreview = $this->_oTemplate->getIconUrl($oStorage->getIconNameByFileName($aFile['file_name']));
  492. $sUrl = $oStorage->getFileUrlById($aFile['image_id']);
  493. $aResult[] = array(
  494. 'id' => $aFile['image_id'],
  495. 'src' => $sPreview,
  496. 'src_orig' => $bImage ? $sUrl : '',
  497. 'url' => !$bImage ? $sUrl : ''
  498. );
  499. }
  500. return $aResult;
  501. }
  502. public function getConnectionObject($sType)
  503. {
  504. $sResult = '';
  505. switch($sType) {
  506. case BX_CMT_FILTER_FRIENDS:
  507. $sResult = $this->_sConnObjFriends;
  508. break;
  509. case BX_CMT_FILTER_SUBSCRIPTIONS:
  510. $sResult = $this->_sConnObjSubscriptions;
  511. break;
  512. }
  513. return $sResult;
  514. }
  515. public function getVoteObject($iEniqId)
  516. {
  517. if(empty($this->_aSystem['object_vote']))
  518. $this->_aSystem['object_vote'] = 'sys_cmts';
  519. $oVote = BxDolVote::getObjectInstance($this->_aSystem['object_vote'], $iEniqId, true, $this->_oTemplate);
  520. if(!$oVote || !$oVote->isEnabled())
  521. return false;
  522. return $oVote;
  523. }
  524. public function getReactionObject($iEniqId)
  525. {
  526. if(empty($this->_aSystem['object_reaction']))
  527. $this->_aSystem['object_reaction'] = 'sys_cmts_reactions';
  528. $oReaction = BxDolVote::getObjectInstance($this->_aSystem['object_reaction'], $iEniqId, true, $this->_oTemplate);
  529. if(!$oReaction || !$oReaction->isEnabled())
  530. return false;
  531. return $oReaction;
  532. }
  533. public function getScoreObject($iEniqId)
  534. {
  535. if(empty($this->_aSystem['object_score']))
  536. $this->_aSystem['object_score'] = 'sys_cmts';
  537. $oScore = BxDolScore::getObjectInstance($this->_aSystem['object_score'], $iEniqId, true, $this->_oTemplate);
  538. if(!$oScore || !$oScore->isEnabled())
  539. return false;
  540. return $oScore;
  541. }
  542. public function getReportObject($iEniqId)
  543. {
  544. if(empty($this->_aSystem['object_report']))
  545. $this->_aSystem['object_report'] = 'sys_cmts';
  546. $oReport = BxDolReport::getObjectInstance($this->_aSystem['object_report'], $iEniqId, true, $this->_oTemplate);
  547. if(!$oReport || !$oReport->isEnabled())
  548. return false;
  549. return $oReport;
  550. }
  551. /**
  552. * Is used as:
  553. * 1. Live Update's session key.
  554. * 2. HTML ID for Live Update's 'New Content' button.
  555. * @return string with ID.
  556. */
  557. public function getNotificationId()
  558. {
  559. return 'cmts-notification-' . $this->_sSystem . '-' . $this->_iId;
  560. }
  561. public function getSocketName()
  562. {
  563. return 'cmts_' . $this->_sSystem;
  564. }
  565. /**
  566. * @deprecated since version 10.0.0-B3 and can be removed in later versions.
  567. */
  568. public function setTableNameFiles($sTable)
  569. {
  570. $this->_sTableImages = $sTable;
  571. $this->_oQuery->setTableNameFiles($sTable);
  572. }
  573. /**
  574. * @deprecated since version 10.0.0-B3 and can be removed in later versions.
  575. */
  576. public function setTableNameFiles2Entries($sTable)
  577. {
  578. $this->_sTableImages2Entries = $sTable;
  579. $this->_oQuery->setTableNameFiles2Entries($sTable);
  580. }
  581. public function isHtml ()
  582. {
  583. return $this->_aSystem['html'] > 0;
  584. }
  585. public function isRatable ()
  586. {
  587. return $this->_aSystem['is_ratable'];
  588. }
  589. public function isAttachImageEnabled()
  590. {
  591. return true;
  592. }
  593. public function isAutoApprove()
  594. {
  595. return getParam('sys_cmts_enable_auto_approve') == 'on';
  596. }
  597. /**
  598. * set id to operate with votes
  599. */
  600. public function setId ($iId)
  601. {
  602. if ($iId == $this->getId()) return;
  603. $this->_iId = $iId;
  604. }
  605. /**
  606. * Add replace markers.
  607. * @param $a array of markers as key => value
  608. * @return true on success or false on error
  609. */
  610. public function addMarkers ($a)
  611. {
  612. if (empty($a) || !is_array($a))
  613. return false;
  614. $this->_aMarkers = array_merge ($this->_aMarkers, $a);
  615. return true;
  616. }
  617. /**
  618. * Database functions
  619. */
  620. public function getQueryObject ()
  621. {
  622. return $this->_oQuery;
  623. }
  624. public function getCommentsTableName ()
  625. {
  626. return $this->_oQuery->getTableName ();
  627. }
  628. public function getObjectAuthorId ($iObjectId = 0)
  629. {
  630. if(empty($this->_aSystem['trigger_field_author']))
  631. return 0;
  632. return $this->_oQuery->getObjectAuthorId ($iObjectId ? $iObjectId : $this->getId());
  633. }
  634. public function getObjectTitle ($iObjectId = 0)
  635. {
  636. if(empty($this->_aSystem['trigger_field_title']))
  637. return '';
  638. $sTitle = $this->_oQuery->getObjectTitle ($iObjectId ? $iObjectId : $this->getId());
  639. if(get_mb_substr($sTitle, 0, 1) == '_')
  640. $sTitle = _t($sTitle);
  641. return $sTitle;
  642. }
  643. public function getObjectPrivacyView ($iObjectId = 0)
  644. {
  645. if(empty($iObjectId))
  646. $iObjectId = $this->getId();
  647. $sFieldPrivacyView = '';
  648. if(!empty($this->_aSystem['trigger_field_privacy_view']))
  649. $sFieldPrivacyView = $this->_aSystem['trigger_field_privacy_view'];
  650. if(($iPrivacyView = $this->_oQuery->getObjectPrivacyView($iObjectId, $sFieldPrivacyView)) !== false)
  651. return $iPrivacyView;
  652. return BX_DOL_PG_ALL;
  653. }
  654. /*
  655. * Gets Content Filter object.
  656. */
  657. public function getObjectContentFilter ()
  658. {
  659. $oCf = BxDolContentFilter::getInstance();
  660. if(!$oCf->isEnabledForComments())
  661. return false;
  662. return $oCf;
  663. }
  664. public function getCommentsCountAll ($iObjectId = 0, $bForceCalculate = false)
  665. {
  666. return $this->_oQuery->getCommentsCountAll ($iObjectId ? $iObjectId : $this->getId(), $this->_getAuthorId(), $bForceCalculate);
  667. }
  668. public function getCommentsCount ($iObjectId = 0, $iCmtVParentId = -1, $sFilter = '')
  669. {
  670. return $this->_oQuery->getCommentsCount ($iObjectId ? $iObjectId : $this->getId(), $iCmtVParentId, $this->_getAuthorId(), $sFilter);
  671. }
  672. public function getCommentsArray ($iVParentId, $sFilter, $aOrder, $iStart = 0, $iCount = -1)
  673. {
  674. return $this->_oQuery->getComments ($this->getId(), $iVParentId, $this->_getAuthorId(), $sFilter, $aOrder, $iStart, $iCount);
  675. }
  676. public function getCommentsBy ($aParams = [])
  677. {
  678. return $this->_oQuery->getCommentsBy($aParams);
  679. }
  680. /**
  681. * Get comment's unique id.
  682. */
  683. public function getCommentUniqId($iCmtId, $iAuthorId = 0)
  684. {
  685. return $this->_oQuery->getUniqId($this->getSystemId(), $iCmtId, ['author_id' => $iAuthorId]);
  686. }
  687. /**
  688. * Get comment's short info.
  689. */
  690. public function getCommentSimple ($iCmtId)
  691. {
  692. return $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
  693. }
  694. /**
  695. * Get comment's full info.
  696. */
  697. public function getCommentRow ($iCmtId)
  698. {
  699. return $this->_oQuery->getComment ($this->getId(), $iCmtId);
  700. }
  701. public function getCommentParents ($mixedCmt, $iDepthMax = 0)
  702. {
  703. if(!is_array($mixedCmt))
  704. $mixedCmt = $this->_oQuery->getCommentsBy(['type' => 'id', 'id' => (int)$mixedCmt]);
  705. $iDepth = 0;
  706. $aParents = [];
  707. $this->_getParents($mixedCmt, $iDepthMax, $iDepth, $aParents);
  708. return $aParents;
  709. }
  710. public function onObjectDelete ($iObjectId = 0)
  711. {
  712. // delete comments
  713. $aFiles = $aCmtIds = [];
  714. $this->_oQuery->deleteObjectComments ($iObjectId ? $iObjectId : $this->getId(), $aFiles, $aCmtIds);
  715. // delete votes
  716. $this->deleteVotes($aCmtIds);
  717. // delete reactions
  718. $this->deleteReactions($aCmtIds);
  719. // delete scores
  720. $this->deleteScores($aCmtIds);
  721. // delete reports
  722. $this->deleteReports($aCmtIds);
  723. // delete meta info
  724. $this->deleteMetaInfo($aCmtIds);
  725. // delete files
  726. if ($aFiles) {
  727. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  728. if ($oStorage)
  729. $oStorage->queueFilesForDeletion($aFiles);
  730. }
  731. // delete unique IDs
  732. $this->deleteUniqueIds($aCmtIds);
  733. }
  734. public static function onAuthorDelete ($iAuthorId)
  735. {
  736. $aSystems = self::getSystems();
  737. foreach($aSystems as $sSystem => $aSystem) {
  738. $o = self::getObjectInstance($sSystem, 0);
  739. $oQuery = $o->getQueryObject();
  740. // delete comments
  741. $aFiles = $aCmtIds = array ();
  742. $oQuery->deleteAuthorComments($iAuthorId, $aFiles, $aCmtIds);
  743. // delete votes
  744. $o->deleteVotes($aCmtIds);
  745. // delete reactions
  746. $o->deleteReactions($aCmtIds);
  747. // delete scores
  748. $o->deleteScores($aCmtIds);
  749. // delete reports
  750. $o->deleteReports($aCmtIds);
  751. // delete meta info
  752. $o->deleteMetaInfo($aCmtIds);
  753. // delete files
  754. $oStorage = BxDolStorage::getObjectInstance($o->getStorageObjectName());
  755. if ($oStorage)
  756. $oStorage->queueFilesForDeletion($aFiles);
  757. // delete unique IDs
  758. $o->deleteUniqueIds($aCmtIds);
  759. }
  760. return true;
  761. }
  762. public static function onModuleEnable ($sModuleName)
  763. {
  764. $aSystems = self::getSystems();
  765. foreach($aSystems as $sSystem => $aSystem) {
  766. if ($sModuleName !== $aSystem['module'])
  767. continue;
  768. $o = self::getObjectInstance($sSystem, 0);
  769. $o->registerTranscoders();
  770. }
  771. return true;
  772. }
  773. public static function onModuleDisable ($sModuleName)
  774. {
  775. $aSystems = self::getSystems();
  776. foreach($aSystems as $sSystem => $aSystem) {
  777. if ($sModuleName !== $aSystem['module'])
  778. continue;
  779. $o = self::getObjectInstance($sSystem, 0);
  780. $o->unregisterTranscoders();
  781. }
  782. return true;
  783. }
  784. public static function onModuleUninstall ($sModuleName, &$iFiles = null)
  785. {
  786. $aSystems = self::getSystems();
  787. foreach($aSystems as $sSystem => $aSystem) {
  788. if ($sModuleName !== $aSystem['module'])
  789. continue;
  790. $o = self::getObjectInstance($sSystem, 0);
  791. $oQuery = $o->getQueryObject();
  792. // delete comments
  793. $aFiles = $aCmtIds = array ();
  794. $oQuery->deleteAll($aSystem['system_id'], $aFiles, $aCmtIds);
  795. // delete votes
  796. $o->deleteVotes($aCmtIds);
  797. // delete reactions
  798. $o->deleteReactions($aCmtIds);
  799. // delete scores
  800. $o->deleteScores($aCmtIds);
  801. // delete reports
  802. $o->deleteReports($aCmtIds);
  803. // delete meta info
  804. $o->deleteMetaInfo($aCmtIds);
  805. // delete files
  806. $oStorage = BxDolStorage::getObjectInstance($o->getStorageObjectName());
  807. if ($oStorage && $aFiles)
  808. $oStorage->queueFilesForDeletion($aFiles);
  809. if (null !== $iFiles)
  810. $iFiles += count($aFiles);
  811. // delete unique IDs
  812. $o->deleteUniqueIds($aCmtIds);
  813. }
  814. return true;
  815. }
  816. public function deleteVotes ($mixedCmtId)
  817. {
  818. if(!is_array($mixedCmtId))
  819. $mixedCmtId = [$mixedCmtId];
  820. foreach($mixedCmtId as $iCmtId)
  821. if(($oReport = $this->getVoteObject($this->getCommentUniqId($iCmtId))) !== false)
  822. $oReport->onObjectDelete();
  823. }
  824. public function deleteReactions ($mixedCmtId)
  825. {
  826. if(!is_array($mixedCmtId))
  827. $mixedCmtId = [$mixedCmtId];
  828. foreach($mixedCmtId as $iCmtId)
  829. if(($oReport = $this->getReactionObject($this->getCommentUniqId($iCmtId))) !== false)
  830. $oReport->onObjectDelete();
  831. }
  832. public function deleteScores ($mixedCmtId)
  833. {
  834. if(!is_array($mixedCmtId))
  835. $mixedCmtId = [$mixedCmtId];
  836. foreach($mixedCmtId as $iCmtId)
  837. if(($oReport = $this->getScoreObject($this->getCommentUniqId($iCmtId))) !== false)
  838. $oReport->onObjectDelete();
  839. }
  840. public function deleteReports ($mixedCmtId)
  841. {
  842. if(!is_array($mixedCmtId))
  843. $mixedCmtId = [$mixedCmtId];
  844. foreach($mixedCmtId as $iCmtId)
  845. if(($oReport = $this->getReportObject($this->getCommentUniqId($iCmtId))) !== false)
  846. $oReport->onObjectDelete();
  847. }
  848. public function deleteMetaInfo ($mixedCmtId)
  849. {
  850. if(!is_array($mixedCmtId))
  851. $mixedCmtId = array($mixedCmtId);
  852. $oMetatags = false;
  853. if(!empty($this->_sMetatagsObj))
  854. $oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj);
  855. if($oMetatags)
  856. foreach($mixedCmtId as $iCmtId)
  857. $oMetatags->onDeleteContent($this->getCommentUniqId($iCmtId));
  858. }
  859. public function deleteUniqueIds ($mixedCmtId)
  860. {
  861. if(!is_array($mixedCmtId))
  862. $mixedCmtId = array($mixedCmtId);
  863. foreach($mixedCmtId as $iCmtId)
  864. $this->_oQuery->deleteCmtIds($this->_aSystem['system_id'], $iCmtId);
  865. }
  866. /**
  867. * Permissions functions
  868. */
  869. public function isAdmin($iCmtAuthorId)
  870. {
  871. return BxDolAcl::getInstance()->isMemberLevelInSet(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR), $iCmtAuthorId);
  872. }
  873. public function checkAction ($sAction, $isPerformAction = false)
  874. {
  875. $iId = $this->_getAuthorId();
  876. $a = checkActionModule($iId, $sAction, 'system', $isPerformAction);
  877. return $a[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED;
  878. }
  879. public function checkActionErrorMsg ($sAction)
  880. {
  881. $iId = $this->_getAuthorId();
  882. $a = checkActionModule($iId, $sAction, 'system');
  883. return $a[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $a[CHECK_ACTION_MESSAGE] : '';
  884. }
  885. public function isViewAllowed ($isPerformAction = false)
  886. {
  887. if (BxDolRequest::serviceExists($this->_aSystem['module'], 'check_allowed_comments_view')) {
  888. $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_view', array($this->getId(), $this->getSystemName()));
  889. if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
  890. return $mixedResult;
  891. }
  892. return CHECK_ACTION_RESULT_ALLOWED;
  893. }
  894. public function isVoteAllowed ($aCmt, $isPerformAction = false)
  895. {
  896. if(!$this->isRatable())
  897. return false;
  898. $oVote = $this->getVoteObject($this->getCommentUniqId($aCmt['cmt_id']));
  899. if($oVote === false)
  900. return false;
  901. $iUserId = (int)$this->_getAuthorId();
  902. if($iUserId == 0)
  903. return false;
  904. if(isAdmin())
  905. return true;
  906. return $oVote->isAllowedVote($isPerformAction);
  907. }
  908. public function isScoreAllowed ($aCmt, $isPerformAction = false)
  909. {
  910. if(!$this->isRatable())
  911. return false;
  912. $oScore = $this->getScoreObject($this->getCommentUniqId($aCmt['cmt_id']));
  913. if($oScore === false)
  914. return false;
  915. $iUserId = (int)$this->_getAuthorId();
  916. if($iUserId == 0)
  917. return false;
  918. if(isAdmin())
  919. return true;
  920. return $oScore->isAllowedVote($isPerformAction);
  921. }
  922. public function isReportAllowed ($aCmt, $isPerformAction = false)
  923. {
  924. $oReport = $this->getReportObject($aCmt['cmt_id']);
  925. if($oReport === false)
  926. return false;
  927. $iUserId = (int)$this->_getAuthorId();
  928. if($iUserId == 0)
  929. return false;
  930. if(isAdmin())
  931. return true;
  932. return $oReport->isAllowedReport($isPerformAction);
  933. }
  934. public function isPostAllowed ($isPerformAction = false)
  935. {
  936. if (BxDolRequest::serviceExists($this->_aSystem['module'], 'check_allowed_comments_post')) {
  937. $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_post', array($this->getId(), $this->getSystemName()));
  938. if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
  939. return false;
  940. }
  941. return $this->checkAction ('comments post', $isPerformAction);
  942. }
  943. public function msgErrPostAllowed ()
  944. {
  945. return $this->checkActionErrorMsg('comments post');
  946. }
  947. /**
  948. * Determines whether a 'reply' action allowed or not.
  949. * @param integer or array $mixedCmt - ID or an array which describes the comment to be replied
  950. * @param boolean $isPerformAction
  951. * @return boolean
  952. */
  953. public function isReplyAllowed ($mixedCmt, $isPerformAction = false)
  954. {
  955. return $this->isPostAllowed($isPerformAction);
  956. }
  957. public function msgErrReplyAllowed ()
  958. {
  959. return $this->msgErrPostAllowed ();
  960. }
  961. public function isQuoteAllowed ($mixedCmt, $isPerformAction = false)
  962. {
  963. return $this->_bPostQuote && $this->isReplyAllowed ($mixedCmt, $isPerformAction);
  964. }
  965. public function msgErrQuoteAllowed ()
  966. {
  967. return $this->msgErrReplyAllowed ();
  968. }
  969. public function isPinAllowed ($aCmt, $isPerformAction = false)
  970. {
  971. if((int)$aCmt['cmt_parent_id'] != 0 || (int)$aCmt['cmt_pinned'] != 0)
  972. return false;
  973. if(isAdmin())
  974. return true;
  975. return $this->checkAction ('comments pin', $isPerformAction);
  976. }
  977. public function msgErrPinAllowed ()
  978. {
  979. return $this->checkActionErrorMsg('comments pin');
  980. }
  981. public function isUnpinAllowed ($aCmt, $isPerformAction = false)
  982. {
  983. if((int)$aCmt['cmt_pinned'] == 0)
  984. return false;
  985. if(isAdmin())
  986. return true;
  987. return $this->checkAction ('comments pin', $isPerformAction);
  988. }
  989. public function msgErrUnpinAllowed ()
  990. {
  991. return $this->checkActionErrorMsg('comments pin');
  992. }
  993. public function isEditAllowed ($aCmt, $isPerformAction = false)
  994. {
  995. if(isAdmin())
  996. return true;
  997. if($this->isEditAllowedAll($isPerformAction))
  998. return true;
  999. $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_post', array($this->getId(), $this->getSystemName()));
  1000. if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
  1001. return false;
  1002. return abs($aCmt['cmt_author_id']) == $this->_getAuthorId() && $this->checkAction ('comments edit own', $isPerformAction);
  1003. }
  1004. public function msgErrEditAllowed ()
  1005. {
  1006. return $this->checkActionErrorMsg ('comments edit own');
  1007. }
  1008. public function isEditAllowedAll ($isPerformAction = false)
  1009. {
  1010. return $this->checkAction('comments edit all', $isPerformAction);
  1011. }
  1012. public function isRemoveAllowed ($aCmt, $isPerformAction = false)
  1013. {
  1014. if(isAdmin())
  1015. return true;
  1016. if($this->isRemoveAllowedAll($isPerformAction))
  1017. return true;
  1018. if(abs($aCmt['cmt_author_id']) == $this->_getAuthorId() && $this->checkAction ('comments remove own', $isPerformAction))
  1019. return true;
  1020. $aContentInfo = BxDolRequest::serviceExists($this->_aSystem['module'], 'get_all') ? BxDolService::call($this->_aSystem['module'], 'get_all', array(array('type' => 'id', 'id' => $this->getId()))) : array();
  1021. $oModule = BxDolModule::getInstance($this->_aSystem['module']);
  1022. $CNF = $oModule->_oConfig->CNF;
  1023. if (isset($CNF['FIELD_AUTHOR']) && $aContentInfo[$CNF['FIELD_AUTHOR']] == $this->_getAuthorId() && $this->checkAction('comments remove in own content', $isPerformAction)){
  1024. return true;
  1025. }
  1026. if (isset($CNF['FIELD_ALLOW_VIEW_TO']) && $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']] < 0){
  1027. $iGroupProfileId = -(int)$aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']];
  1028. $oProfileContext = BxDolProfile::getInstance($iGroupProfileId);
  1029. $oModule = BxDolModule::getInstance($oProfileContext->getModule());
  1030. if ($oModule->_oConfig->isRoles() && $oModule->getRole($iGroupProfileId, $this->_getAuthorId()) === BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR && $this->checkAction('comments remove in group context', $isPerformAction)){
  1031. return true;
  1032. }
  1033. }
  1034. return false;
  1035. }
  1036. public function isRemoveAllowedAll ($isPerformAction = false)
  1037. {
  1038. return $this->checkAction ('comments remove all', $isPerformAction);
  1039. }
  1040. public function msgErrRemoveAllowed ()
  1041. {
  1042. return $this->checkActionErrorMsg('comments remove own');
  1043. }
  1044. public function isMoreAllowed ($aCmt, $isPerformAction = false)
  1045. {
  1046. $oMenuManage = BxDolMenu::getObjectInstance($this->_sMenuObjManage);
  1047. $oMenuManage->setCmtsData($this, $aCmt['cmt_id']);
  1048. return $oMenuManage->isVisible();
  1049. }
  1050. public function isModerator($isPerformAction = false)
  1051. {
  1052. return $this->isEditAllowedAll($isPerformAction) || $this->isRemoveAllowedAll($isPerformAction);
  1053. }
  1054. /**
  1055. * Actions functions
  1056. */
  1057. public function actionPin ()
  1058. {
  1059. if (!$this->isEnabled())
  1060. return echoJson(array());
  1061. $iCmtId = 0;
  1062. if(bx_get('Cmt') !== false)
  1063. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  1064. $aCmt = $this->getCommentRow($iCmtId);
  1065. if(empty($aCmt) || !is_array($aCmt))
  1066. return echoJson(array());
  1067. $iWay = 0;
  1068. if(bx_get('way') !== false)
  1069. $iWay = bx_process_input(bx_get('way'), BX_DATA_INT);
  1070. if(!$this->_oQuery->updateComments(array('cmt_pinned' => $iWay ? time() : 0), array('cmt_id' => $iCmtId)))
  1071. return echoJson(array());
  1072. $aBp = $aDp = array();
  1073. $this->_getParams($aBp, $aDp);
  1074. $this->_prepareParams($aBp, $aDp);
  1075. echoJson(array(
  1076. 'parent_id' => $aCmt['cmt_parent_id'],
  1077. 'per_view' => $aBp['per_view']
  1078. ));
  1079. }
  1080. public function actionGetFormPost ()
  1081. {
  1082. if (!$this->isEnabled())
  1083. return '';
  1084. $iCmtParentId = bx_get('CmtParent');
  1085. $iCmtParentId = $iCmtParentId !== false ? bx_process_input($iCmtParentId, BX_DATA_INT) : 0;
  1086. $sCmtBrowse = bx_get('CmtBrowse');
  1087. $sCmtBrowse = $sCmtBrowse !== false ? bx_process_input($sCmtBrowse, BX_DATA_TEXT) : '';
  1088. $sCmtDisplay = bx_get('CmtDisplay');
  1089. $sCmtDisplay = $sCmtDisplay !== false ? bx_process_input($sCmtDisplay, BX_DATA_TEXT) : '';
  1090. $bQuote = bx_get('CmtQuote');
  1091. $bQuote = $bQuote !== false ? bx_process_input($bQuote, BX_DATA_INT) == 1 : false;
  1092. $bMinPostForm = bx_get('CmtMinPostForm');
  1093. $bMinPostForm = $bMinPostForm !== false ? bx_process_input($bMinPostForm, BX_DATA_INT) == 1 : $this->_bMinPostForm;
  1094. return $this->getFormBoxPost(array('parent_id' => $iCmtParentId, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay, 'dynamic_mode' => true, 'quote' => $bQuote, 'min_post_form' => $bMinPostForm));
  1095. }
  1096. public function actionGetFormEdit ()
  1097. {
  1098. if (!$this->isEnabled())
  1099. return echoJson(array());
  1100. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  1101. echoJson($this->getFormEdit($iCmtId, array('dynamic_mode' => true)));
  1102. }
  1103. public function actionGetCmt ()
  1104. {
  1105. if(!$this->isEnabled())
  1106. return '';
  1107. if($this->isViewAllowed() !== CHECK_ACTION_RESULT_ALLOWED)
  1108. return '';
  1109. $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
  1110. $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
  1111. $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
  1112. $aCmt = $this->getCommentRow($iCmtId);
  1113. echoJson([
  1114. 'parent_id' => $aCmt['cmt_parent_id'],
  1115. 'vparent_id' => $aCmt['cmt_parent_id'],
  1116. 'content' => $this->getComment($aCmt, ['type' => $sCmtBrowse], ['type' => $sCmtDisplay, 'dynamic_mode' => true])
  1117. ]);
  1118. }
  1119. public function actionGetCmts ()
  1120. {
  1121. if (!$this->isEnabled())
  1122. return '';
  1123. if($this->isViewAllowed() !== CHECK_ACTION_RESULT_ALLOWED)
  1124. return '';
  1125. $aBp = $aDp = array();
  1126. $this->_getParams($aBp, $aDp);
  1127. $aDp['dynamic_mode'] = true;
  1128. //--- Beg: Using pregenerated structure
  1129. if(isset($aDp['structure']) && $aDp['structure'] === true) {
  1130. $iCmtId = isset($aBp['parent_id']) ? (int)$aBp['parent_id'] : 0;
  1131. $mixedStructure = $this->getCommentStructure($iCmtId, $aBp, $aDp);
  1132. if($mixedStructure === false || empty($mixedStructure[$iCmtId]['items']))
  1133. return '';
  1134. $aDp['structure'] = $mixedStructure[$iCmtId]['items'];
  1135. return $this->getCommentsByStructure($aBp, $aDp);
  1136. }
  1137. //--- End: Using pregenerated structure
  1138. else
  1139. return $this->{'getComments' . ($aBp['pinned'] ? 'Pinned' : '')}($aBp, $aDp);
  1140. }
  1141. public function actionSubmitPostForm()
  1142. {
  1143. if(!$this->isEnabled())
  1144. return echoJson(array());
  1145. $iCmtParentId = 0;
  1146. if(bx_get('cmt_parent_id') !== false)
  1147. $iCmtParentId = bx_process_input(bx_get('cmt_parent_id'), BX_DATA_INT);
  1148. echoJson($this->getFormPost($iCmtParentId, array('dynamic_mode' => true)));
  1149. }
  1150. public function actionSubmitEditForm()
  1151. {
  1152. if (!$this->isEnabled()) {
  1153. echoJson(array());
  1154. return;
  1155. };
  1156. $iCmtId = 0;
  1157. if(bx_get('cmt_id') !== false)
  1158. $iCmtId = bx_process_input(bx_get('cmt_id'), BX_DATA_INT);
  1159. echoJson($this->getFormEdit($iCmtId, array('dynamic_mode' => true)));
  1160. }
  1161. public function actionRemove()
  1162. {
  1163. if (!$this->isEnabled())
  1164. return echoJson([]);
  1165. $iCmtId = 0;
  1166. if(bx_get('Cmt') !== false)
  1167. $iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
  1168. echoJson($this->remove($iCmtId));
  1169. }
  1170. public function remove($iCmtId)
  1171. {
  1172. $aCmt = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iCmtId));
  1173. if(!$aCmt)
  1174. return array('msg' => _t('_No such comment'));
  1175. $iObjId = $this->getId();
  1176. if(!$iObjId){
  1177. $this->setId($aCmt['cmt_object_id']);
  1178. $iObjId = $aCmt['cmt_object_id'];
  1179. }
  1180. $iObjAthrId = $this->getObjectAuthorId($iObjId);
  1181. $iObjAthrPrivacyView = $this->getObjectPrivacyView($iObjId);
  1182. if($aCmt['cmt_replies'] > 0) {
  1183. if(!$this->isModerator())
  1184. return array('msg' => _t('_Can not delete comments with replies'));
  1185. $aReplies = $this->_oQuery->getCommentsBy(array('type' => 'parent_id', 'parent_id' => $iCmtId));
  1186. foreach($aReplies as $aReply)
  1187. $this->remove($aReply['cmt_id']);
  1188. }
  1189. $iPerformerId = $this->_getAuthorId();
  1190. if(!$this->isRemoveAllowed($aCmt))
  1191. return array('msg' => $aCmt['cmt_author_id'] == $iPerformerId ? strip_tags($this->msgErrRemoveAllowed()) : _t('_Access denied'));
  1192. $iCmtPrntId = (int)$aCmt['cmt_parent_id'];
  1193. if(!$this->_oQuery->removeComment($iObjId, $iCmtId, $iCmtPrntId))
  1194. return array('msg' => _t('_cmt_err_cannot_perform_action'));
  1195. $this->_triggerComment();
  1196. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  1197. $aImages = $this->_oQuery->getFiles($this->_aSystem['system_id'], $iCmtId);
  1198. foreach($aImages as $aImage)
  1199. $oStorage->deleteFile($aImage['image_id']);
  1200. $this->_oQuery->deleteImages($this->_aSystem['system_id'], $iCmtId);
  1201. $this->isRemoveAllowed($aCmt, true);
  1202. $this->deleteVotes($iCmtId);
  1203. $this->deleteReactions($iCmtId);
  1204. $this->deleteScores($iCmtId);
  1205. $this->deleteReports($iCmtId);
  1206. $this->deleteMetaInfo($iCmtId);
  1207. $aAuditParams = $this->_prepareAuditParams($iCmtId, array('comment_author_id' => $aCmt['cmt_author_id'], 'comment_text' => $aCmt['cmt_text']));
  1208. bx_audit($iObjId, $this->_aSystem['module'], '_sys_audit_action_delete_comment', $aAuditParams);
  1209. $aAlertParams = $this->_prepareAlertParams($aCmt);
  1210. /**
  1211. * @hooks
  1212. * @hookdef hook-bx_dol_comment-commentRemoved '{object_name}', 'commentRemoved' - hook after a comment was removed
  1213. * - $unit_name - comment object name
  1214. * - $action - equals `commentRemoved`
  1215. * - $object_id - commented object id
  1216. * - $sender_id - profile id who performed the action
  1217. * - $extra_params - array of additional params with the following array keys:
  1218. * - `source` - [string] unique comment source string
  1219. * - `object_system` - [string] comment object name
  1220. * - `object_id` - [int] commented object id
  1221. * - `object_author_id` - [int] commented object author profile id
  1222. * - `comment_id` - [int] comment id unique in the comment object scope
  1223. * - `comment_uniq_id` - [int] system wide unique comment id
  1224. * - `comment_author_id` - [int] comment author profile id
  1225. * - `comment_text` - [string] comment text
  1226. * - `privacy_view` - [int] or [string] privacy for view comment action, @see BxDolPrivacy
  1227. * - `cf` - [int] comment's audience filter value
  1228. * @hook @ref hook-bx_dol_comment-commentRemoved
  1229. */
  1230. bx_alert($this->_sSystem, 'commentRemoved', $iObjId, $iPerformerId, $aAlertParams);
  1231. /**
  1232. * @hooks
  1233. * @hookdef hook-comment-deleted 'comment', 'deleted' - hook after a comment was removed
  1234. * It's equivalent to @ref hook-bx_dol_comment-commentRemoved
  1235. * except 'comment id' is provided in $object_id
  1236. * @hook @ref hook-comment-deleted
  1237. */
  1238. bx_alert('comment', 'deleted', $iCmtId, $iPerformerId, $aAlertParams);
  1239. if(!empty($iCmtPrntId)) {
  1240. $aCmtPrnt = $this->_oQuery->getCommentSimple($iObjId, $iCmtPrntId);
  1241. if(!empty($aCmtPrnt) && is_array($aCmtPrnt)) {
  1242. $aAlertParamsReply = $this->_prepareAlertParamsReply($aCmt, $aCmtPrnt);
  1243. /**
  1244. * @hooks
  1245. * @hookdef hook-bx_dol_comment-replyRemoved '{object_name}', 'replyRemoved' - hook after a reply was removed
  1246. * - $unit_name - comment object name
  1247. * - $action - equals `replyRemoved`
  1248. * - $object_id - commented object id
  1249. * - $sender_id - profile id who performed the action
  1250. * - $extra_params - array of additional params with the following array keys:
  1251. * - `source` - [string] unique comment source string
  1252. * - `object_system` - [string] comment object name
  1253. * - `object_id` - [int] commented object id
  1254. * - `object_author_id` - [int] commented object author profile id
  1255. * - `object_author_id` - [int] commented object author profile id
  1256. * - `parent_id` - [int] parent comment id unique in the comment object scope
  1257. * - `parent_uniq_id` - [int] system wide unique parent comment id
  1258. * - `parent_author_id` - [int] parent comment author profile id
  1259. * - `comment_id` - [int] comment id unique in the comment object scope
  1260. * - `comment_uniq_id` - [int] system wide unique comment id
  1261. * - `comment_author_id` - [int] comment author profile id
  1262. * - `comment_text` - [string] comment text
  1263. * - `privacy_view` - [int] or [string] privacy for view comment action, @see BxDolPrivacy
  1264. * @hook @ref hook-bx_dol_comment-replyRemoved
  1265. */
  1266. bx_alert($this->_sSystem, 'replyRemoved', $iCmtPrntId, $iPerformerId, $aAlertParamsReply);
  1267. /**
  1268. * @hooks
  1269. * @hookdef hook-reply-deleted 'reply', 'deleted' - hook after a reply was removed
  1270. * It's equivalent to @ref hook-bx_dol_comment-replyRemoved
  1271. * except 'comment id' is provided in $object_id
  1272. * @hook @ref hook-reply-deleted
  1273. */
  1274. bx_alert('reply', 'deleted', $iCmtId, $iPerformerId, $aAlertParamsReply);
  1275. }
  1276. }
  1277. $this->deleteUniqueIds($iCmtId);
  1278. $iCount = (int)$this->getCommentsCountAll(0, true);
  1279. $aResult = [
  1280. 'id' => $iCmtId,
  1281. 'count' => $iCount,
  1282. 'countf' => $iCount > 0 ? $this->getCounter() : ''
  1283. ];
  1284. if(($oSockets = BxDolSockets::getInstance()) && $oSockets->isEnabled()) {
  1285. $oSockets->sendEvent($this->getSocketName(), $iObjId, 'comment_deleted', json_encode(array_merge($aResult, [
  1286. 'author_id' => $iPerformerId
  1287. ])));
  1288. /**
  1289. * Send 'content edited' event.
  1290. * Note. 0 is used as $iContentId to allow to subscribe on all events at once.
  1291. */
  1292. $oSockets->sendEvent($this->_aSystem['module'], 0, 'edited', json_encode([
  1293. 'id' => $iObjId,
  1294. 'author_id' => $this->getObjectAuthorId(),
  1295. 'cmt_author_id' => $aCmt['cmt_author_id'],
  1296. 'peformer_id' => $iPerformerId
  1297. ]));
  1298. }
  1299. return $aResult;
  1300. }
  1301. public function add($aValues)
  1302. {
  1303. return $this->_getFormAdd($aValues);
  1304. }
  1305. public function actionResumeLiveUpdate()
  1306. {
  1307. $sKey = $this->getNotificationId();
  1308. bx_import('BxDolSession');
  1309. BxDolSession::getInstance()->unsetValue($sKey);
  1310. }
  1311. public function actionPauseLiveUpdate()
  1312. {
  1313. $sKey = $this->getNotificationId();
  1314. bx_import('BxDolSession');
  1315. BxDolSession::getInstance()->setValue($sKey, 1);
  1316. }
  1317. public function actionGetSiblingFiles()
  1318. {
  1319. $iFileId = 0;
  1320. if(bx_get('file_id') !== false)
  1321. $iFileId = bx_process_input(bx_get('file_id'), BX_DATA_INT);
  1322. if(!($aFileInfo = $this->_oQuery->getFileInfoById((int)$iFileId)))
  1323. return echoJson(['error' => _t('_sys_txt_error_occured')]);
  1324. $aSiblings = [];
  1325. $aFiles = $this->_oQuery->getFiles($aFileInfo['system_id'], $aFileInfo['cmt_id']);
  1326. foreach($aFiles as $iIndex => $aFile) {
  1327. if($aFile['id'] != $iFileId)
  1328. continue;
  1329. $aSiblings['prev'] = isset($aFiles[$iIndex - 1]) ? $aFiles[$iIndex - 1] : false;
  1330. $aSiblings['next'] = isset($aFiles[$iIndex + 1]) ? $aFiles[$iIndex + 1] : false;
  1331. }
  1332. $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
  1333. $oTranscoder = BxDolTranscoderImage::getObjectInstance($this->getTranscoderPreviewName());
  1334. foreach($aSiblings as $sSibling => $aSibling) {
  1335. if(!$aSibling)
  1336. continue;
  1337. $sFile = '';
  1338. if($oTranscoder && $oTranscoder->isMimeTypeSupported($aSibling['mime_type']))
  1339. $sFile = $oStorage->getFileUrlById($aSibling['image_id']);
  1340. else
  1341. $sFile = $this->_oTemplate->getIconUrl($oStorage->getIconNameByFileName($aFile['file_name']));
  1342. $aImageInfo = BxDolImageResize::getInstance()->getImageSize($sFile);
  1343. $iWidth = $iHeight = 0;
  1344. if(isset($aImageInfo['w']))
  1345. $iWidth = (int)$aImageInfo['w'];
  1346. if(isset($aImageInfo['h']))
  1347. $iHeight = (int)$aImageInfo['h'];
  1348. $aSiblings[$sSibling] = array_merge($aSibling, [
  1349. 'file' => $sFile,
  1350. 'file_id' => $aSibling['id'],
  1351. 'w' => $iWidth,
  1352. 'h' => $iHeight
  1353. ]);
  1354. }
  1355. return echoJson($aSiblings);
  1356. }
  1357. public function onPostAfter($iCmtId, $aDp = [])
  1358. {
  1359. $iObjId = (int)$this->getId();
  1360. $aCmt = $this->_oQuery->getCommentSimple($iObjId, $iCmtId);
  1361. if(empty($aCmt) || !is_array($aCmt))
  1362. return false;
  1363. $iCmtPrntId = (int)$aCmt['cmt_parent_id'];
  1364. $iPerformerId = (int)$aCmt['cmt_author_id'];
  1365. $aAlertParams = $this->_prepareAlertParams($aCmt);
  1366. /**
  1367. * @hooks
  1368. * @hookdef hook-bx_dol_comment-commentPost '{object_name}', 'commentPost' - hook after a comment was added
  1369. * - $unit_name - comment object name
  1370. * - $action - equals `commentPost`
  1371. * - $object_id - commented object id
  1372. * - $sender_id - profile id who performed the action
  1373. * - $extra_params - array of additional params with the following array keys:
  1374. * - `source` - [string] unique comment source string
  1375. * - `object_system` - [string] comment object name
  1376. * - `object_id` - [int] commented object id
  1377. * - `object_author_id` - [int] commented object author profile id
  1378. * - `comment_id` - [int] comment id unique in the comment object scope
  1379. * - `comment_uniq_id` - [int] system wide unique comment id
  1380. * - `comment_author_id` - [int] comment author profile id
  1381. * - `comment_text` - [string] comment text
  1382. * - `privacy_view` - [int] or [string] privacy for view comment action, @see BxDolPrivacy
  1383. * - `cf` - [int] comment's audience filter value
  1384. * @hook @ref hook-bx_dol_comment-commentPost
  1385. */
  1386. bx_alert($this->_sSystem, 'commentPost', $iObjId, $iPerformerId, $aAlertParams);
  1387. /**
  1388. * @hooks
  1389. * @hookdef hook-comment-added 'comment', 'added' - hook after a comment was added
  1390. * It's equivalent to @hook @ref hook-bx_dol_comment-commentPost
  1391. * except 'comment id' is provided in $object_id
  1392. * @hook @ref hook-comment-added
  1393. */
  1394. bx_alert('comment', 'added', $iCmtId, $iPerformerId, $aAlertParams);
  1395. $aAuditParams = $this->_prepareAuditParams($iCmtId, array('comment_author_id' => $aCmt['cmt_author_id'], 'comment_text' => $aCmt['cmt_text']));
  1396. bx_audit($iObjId, $this->_aSystem['module'], '_sys_audit_action_add_comment', $aAuditParams);
  1397. if(!empty($iCmtPrntId)) {
  1398. $aCmtPrnt = $this->_oQuery->getCommentSimple($iObjId, $iCmtPrntId);
  1399. if(!empty($aCmtPrnt) && is_array($aCmtPrnt)) {
  1400. $aAlertParamsReply = $this->_prepareAlertParamsReply($aCmt, $aCmtPrnt);
  1401. /**
  1402. * @hooks
  1403. * @hookdef hook-bx_dol_comment-replyPost '{object_name}', 'replyPost' - hook after a reply was added
  1404. * - $unit_name - comment object name
  1405. * - $action - equals `replyPost`
  1406. * - $object_id - parent comment id
  1407. * - $sender_id - profile id who performed the action
  1408. * - $extra_params - array of additional params with the following array keys:
  1409. * - `source` - [string] unique comment source string
  1410. * - `object_system` - [string] comment object name
  1411. * - `object_id` - [int] commented object id
  1412. * - `object_author_id` - [int] commented object author profile id
  1413. * - `object_author_id` - [int] commented object author profile id
  1414. * - `parent_id` - [int] parent comment id unique in the comment object scope
  1415. * - `parent_uniq_id` - [int] system wide unique parent comment id
  1416. * - `parent_author_id` - [int] parent comment author profile id
  1417. * - `comment_id` - [int] comment id unique in the comment object scope
  1418. * - `comment_uniq_id` - [int] system wide unique comment id
  1419. * - `comment_author_id` - [int] comment author profile id
  1420. * - `comment_text` - [string] comment text
  1421. * - `privacy_view` - [int] or [string] privacy for view comment action, @see BxDolPrivacy
  1422. * @hook @ref hook-bx_dol_comment-replyPost
  1423. */
  1424. bx_alert($this->_sSystem, 'replyPost', $iCmtPrntId, $iPerformerId, $aAlertParamsReply);
  1425. /**
  1426. * @hooks
  1427. * @hookdef hook-comment-replied 'comment', 'replied' - hook after a reply was added
  1428. * It's equivalent to @ref hook-bx_dol_comment-replyPost
  1429. * except 'comment id' is provided in $object_id
  1430. * @hook @ref hook-comment-replied
  1431. */
  1432. bx_alert('comment', 'replied', $iCmtId, $iPerformerId, $aAlertParamsReply);
  1433. }
  1434. }
  1435. $iCount = (int)$this->getCommentsCountAll(0, true);
  1436. $aResult = [
  1437. 'id' => $iCmtId,
  1438. 'parent_id' => $iCmtPrntId,
  1439. 'count' => $iCount,
  1440. 'countf' => $iCount > 0 ? $this->getCounter(['show_script' => false]) : ''
  1441. ];
  1442. if(($oSockets = BxDolSockets::getInstance()) && $oSockets->isEnabled()) {
  1443. $oSockets->sendEvent($this->getSocketName(), $iObjId, 'comment_added', json_encode(array_merge($aResult, [
  1444. 'author_id' => $iPerformerId,
  1445. 'anchor' => $this->getItemAnchor($iCmtId)
  1446. ])));
  1447. /**
  1448. * Send 'content edited' event.
  1449. * Note. 0 is used as $iContentId to allow to subscribe on all events at once.
  1450. */
  1451. $oSockets->sendEvent($this->_aSystem['module'], 0, 'edited', json_encode([
  1452. 'id' => $iObjId,
  1453. ]));
  1454. }
  1455. return $aResult;
  1456. }
  1457. public function onEditAfter($iCmtId, $aDp = [])
  1458. {
  1459. $aCmt = $this->getCommentRow($iCmtId);
  1460. if(empty($aCmt) || !is_array($aCmt))
  1461. return false;
  1462. $aBp = [];
  1463. $this->_getParams($aBp, $aDp);
  1464. $iObjId = (int)$this->getId();
  1465. $iPerformerId = $this->_getAuthorId();
  1466. $aAlertParams = $this->_prepareAlertParams($aCmt);
  1467. /**
  1468. * @hooks
  1469. * @hookdef hook-bx_dol_comment-commentUpdated '{object_name}', 'commentUpdated' - hook after a comment was updated (edited)
  1470. * - $unit_name - comment object name
  1471. * - $action - equals `commentUpdated`
  1472. * - $object_id - commented object id
  1473. * - $sender_id - profile id who performed the action
  1474. * - $extra_params - array of additional params with the following array keys:
  1475. * - `source` - [string] unique comment source string
  1476. * - `object_system` - [string] comment object name
  1477. * - `object_id` - [int] commented object id
  1478. * - `object_author_id` - [int] commented object author profile id
  1479. * - `comment_id` - [int] comment id unique in the comment object scope
  1480. * - `comment_uniq_id` - [int] system wide unique comment id
  1481. * - `comment_author_id` - [int] comment author profile id
  1482. * - `comment_text` - [string] comment text
  1483. * - `privacy_view` - [int] or [string] privacy for view comment action, @see BxDolPrivacy
  1484. * - `cf` - [int] comment's audience filter value
  1485. * @hook @ref hook-bx_dol_comment-commentUpdated
  1486. */
  1487. bx_alert($this->_sSystem, 'commentUpdated', $iObjId, $iPerformerId, $aAlertParams);
  1488. /**
  1489. * @hooks
  1490. * @hookdef hook-comment-edited 'comment', 'edited' - hook after a comment was updated (edited)
  1491. * It's equivalent to @ref hook-bx_dol_comment-commentUpdated
  1492. * except 'comment id' is provided in $object_id
  1493. * @hook @ref hook-comment-edited
  1494. */
  1495. bx_alert('comment', 'edited', $iCmtId, $iPerformerId, $aAlertParams);
  1496. $aAuditParams = $this->_prepareAuditParams($iCmtId, ['comment_author_id' => $aCmt['cmt_author_id'], 'comment_text' => $aCmt['cmt_text']]);
  1497. bx_audit($iObjId, $this->_aSystem['module'], '_sys_audit_action_edit_comment', $aAuditParams);
  1498. $aResult = [
  1499. 'id' => $iCmtId,
  1500. 'content' => $this->_getContent($aCmt, $aBp, $aDp)
  1501. ];
  1502. if(($oSockets = BxDolSockets::getInstance()) && $oSockets->isEnabled()) {
  1503. $oSockets->sendEvent($this->getSocketName(), $iObjId, 'comment_edited', json_encode(array_merge($aResult, [
  1504. 'author_id' => $iPerformerId,
  1505. 'anchor' => $this->getItemAnchor($iCmtId)
  1506. ])));
  1507. /**
  1508. * Send 'content edited' event.
  1509. * Note. 0 is used as $iContentId to allow to subscribe on all events at once.
  1510. */
  1511. $oSockets->sendEvent($this->_aSystem['module'], 0, 'edited', json_encode([
  1512. 'id' => $iObjId,
  1513. ]));
  1514. }
  1515. return $aResult;
  1516. }
  1517. public function serviceGetAuthor ($iContentId)
  1518. {
  1519. $aComment = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iContentId));
  1520. $this->setId($aComment['cmt_object_id']);
  1521. return $aComment['cmt_author_id'];
  1522. }
  1523. public function serviceGetDateAdded ($iContentId)
  1524. {
  1525. $aComment = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iContentId));
  1526. $this->setId($aComment['cmt_object_id']);
  1527. return $aComment['cmt_time'];
  1528. }
  1529. public function serviceGetDateChanged ($iContentId)
  1530. {
  1531. return 0;
  1532. }
  1533. public function serviceGetLink ($iContentId)
  1534. {
  1535. $aComment = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iContentId));
  1536. $this->setId($aComment['cmt_object_id']);
  1537. return $this->getViewUrl($iContentId);
  1538. }
  1539. public function serviceGetTitle ($iContentId)
  1540. {
  1541. return '';
  1542. }
  1543. public function serviceGetText ($iContentId)
  1544. {
  1545. $aComment = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iContentId));
  1546. $this->setId($aComment['cmt_object_id']);
  1547. return $aComment['cmt_text'];
  1548. }
  1549. public function serviceGetThumb ($iContentId)
  1550. {
  1551. return '';
  1552. }
  1553. public function serviceGetInfo ($iContentId, $bSearchableFieldsOnly = true)
  1554. {
  1555. $aComment = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iContentId));
  1556. $this->setId($aComment['cmt_object_id']);
  1557. return BxDolContentInfo::formatFields($aComment);
  1558. }
  1559. public function serviceGetInfoApi ($iContentId, $bExtendedUnits = false)
  1560. {
  1561. $aData = $this->serviceGetInfo($iContentId, false);
  1562. if($aData)
  1563. $aData = $this->getDataAPI($aData, ['extended' => $bExtendedUnits]);
  1564. return $aData;
  1565. }
  1566. public function serviceGetSearchResultUnit ($iContentId, $sUnitTemplate = '')
  1567. {
  1568. $aComment = $this->_oQuery->getCommentsBy(array('type' => 'id', 'id' => $iContentId));
  1569. if(empty($aComment) || !is_array($aComment))
  1570. return '';
  1571. $this->setId($aComment['cmt_object_id']);
  1572. return $this->getComment($aComment, array(), array('type' => BX_CMT_DISPLAY_FLAT, 'view_only' => true));
  1573. }
  1574. public function serviceGetAll ($aParams = array())
  1575. {
  1576. if(empty($aParams) || !is_array($aParams))
  1577. $aParams = array('type' => 'all');
  1578. return $this->_oQuery->getCommentsBy($aParams);
  1579. }
  1580. public function serviceGetSearchableFieldsExtended($aInputsAdd = array())
  1581. {
  1582. $oForm = BxDolForm::getObjectInstance('sys_comment', 'sys_comment_post', $this->_oTemplate);
  1583. if(!$oForm)
  1584. return array();
  1585. $aSrchNamesExcept = array();
  1586. $aSrchCaptionsSystem = array(
  1587. 'cmt_author_id' => '_sys_form_comment_input_caption_system_cmt_author_id',
  1588. 'cmt_text' => '_sys_form_comment_input_caption_system_cmt_text'
  1589. );
  1590. $aSrchCaptions = array(
  1591. 'cmt_author_id' => '_sys_form_comment_input_caption_cmt_author_id',
  1592. 'cmt_text' => '_sys_form_comment_input_caption_cmt_text'
  1593. );
  1594. $aResult = array(
  1595. 'cmt_author_id' => array(
  1596. 'type' => 'text_auto',
  1597. 'caption_system' => $aSrchCaptionsSystem['cmt_author_id'],
  1598. 'caption' => $aSrchCaptions['cmt_author_id'],
  1599. 'info' => '',
  1600. 'value' => '',
  1601. 'values' => '',
  1602. 'pass' => ''
  1603. )
  1604. );
  1605. $aInputs = $oForm->aInputs;
  1606. if(!empty($aInputsAdd) && is_array($aInputsAdd))
  1607. $aInputs = array_merge($aInputs, $aInputsAdd);
  1608. foreach($aInputs as $aInput)
  1609. if(in_array($aInput['type'], BxDolSearchExtended::$SEARCHABLE_TYPES) && !in_array($aInput['name'], $aSrchNamesExcept))
  1610. $aResult[$aInput['name']] = array(
  1611. 'type' => $aInput['type'],
  1612. 'caption_system' => !empty($aInput['caption_system_src']) ? $aInput['caption_system_src'] : '',
  1613. 'caption' => !empty($aInput['caption_src']) ? $aInput['caption_src'] : (!empty($aSrchCaptions[$aInput['name']]) ? $aSrchCaptions[$aInput['name']] : ''),
  1614. 'info' => !empty($aInput['info_src']) ? $aInput['info_src'] : '',
  1615. 'value' => !empty($aInput['value']) ? $aInput['value'] : '',
  1616. 'values' => !empty($aInput['values_src']) ? $aInput['values_src'] : '',
  1617. 'pass' => !empty($aInput['db']['pass']) ? $aInput['db']['pass'] : ''
  1618. );
  1619. return $aResult;
  1620. }
  1621. /**
  1622. * Overwrite this method and register transcoder(s) if comments object uses custom transcoder(s),
  1623. * which differs from default one 'sys_cmts_images_preview'
  1624. */
  1625. public function registerTranscoders()
  1626. {}
  1627. /**
  1628. * Overwrite this method and unregister transcoder(s) if comments object uses custom transcoder(s),
  1629. * which differs from default one 'sys_cmts_images_preview'
  1630. */
  1631. public function unregisterTranscoders()
  1632. {}
  1633. public function serviceGetSearchResultExtended($aParams, $iStart = 0, $iPerPage = 0, $bFilterMode = false)
  1634. {
  1635. if((empty($aParams) || !is_array($aParams)) && !$bFilterMode)
  1636. return array();
  1637. return $this->_oQuery->getCommentsBy(array('type' => 'search_ids', 'search_params' => $aParams, 'start' => $iStart, 'per_page' => $iPerPage));
  1638. }
  1639. public function getAuthorInfo($iAuthorId = 0)
  1640. {
  1641. return $this->_getAuthorInfo($iAuthorId);
  1642. }
  1643. public function getParams(&$aBp, &$aDp)
  1644. {
  1645. return $this->_getParams($aBp, $aDp);
  1646. }
  1647. public function prepareParams(&$aBp, &$aDp)
  1648. {
  1649. return $this->_prepareParams($aBp, $aDp);
  1650. }
  1651. /**
  1652. * Internal functions
  1653. */
  1654. protected function _getAuthorId ()
  1655. {
  1656. return isMember() ? bx_get_logged_profile_id() : 0;
  1657. }
  1658. protected function _getAuthorPassword ()
  1659. {
  1660. return getLoggedPassword();
  1661. }
  1662. protected function _getAuthorIp ()
  1663. {
  1664. return getVisitorIP();
  1665. }
  1666. protected function _getAuthorInfo($iAuthorId = 0)
  1667. {
  1668. $iUserId = $this->_getAuthorId();
  1669. $iAuthorId = (int)$iAuthorId;
  1670. $oProfile = $this->_getAuthorObject($iAuthorId);
  1671. if (!$oProfile->isActive() && !isAdmin() && !BxDolAcl::getInstance()->isMemberLevelInSet(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR)))
  1672. $oProfile = BxDolProfileUndefined::getInstance();
  1673. return array(
  1674. $oProfile->getDisplayName(),
  1675. $oProfile->getUrl(),
  1676. $oProfile->getThumb(),
  1677. $oProfile->getUnit(0, array('template' => 'unit_wo_info')),
  1678. $oProfile->getBadges()
  1679. );
  1680. }
  1681. protected function _getAuthorObject($iAuthorId = 0)
  1682. {
  1683. return BxDolProfile::getInstanceMagic((int)$iAuthorId);
  1684. }
  1685. protected function _getFormObject($sAction = BX_CMT_ACTION_POST)
  1686. {
  1687. $sDisplayName = '_sFormDisplay' . ucfirst($sAction);
  1688. return BxDolForm::getObjectInstance($this->_sFormObject, $this->$sDisplayName, $this->_oTemplate, $this->_sSystem);
  1689. }
  1690. protected function _unsetFormObject($sAction = BX_CMT_ACTION_POST)
  1691. {
  1692. $sDisplayName = '_sFormDisplay' . ucfirst($sAction);
  1693. return BxDolForm::unsetObjectInstance($this->_sFormObject, $this->$sDisplayName, $this->_oTemplate, $this->_sSystem);
  1694. }
  1695. protected function _getParams(&$aBp, &$aDp)
  1696. {
  1697. //--- Process 'Browse' params.
  1698. $aBp['parent_id'] = isset($aBp['parent_id']) ? (int)$aBp['parent_id'] : 0;
  1699. $aBp['vparent_id'] = isset($aBp['vparent_id']) ? (int)$aBp['vparent_id'] : 0;
  1700. if(bx_get('CmtParent') !== false)
  1701. $aBp['vparent_id'] = bx_process_input(bx_get('CmtParent'), BX_DATA_INT);
  1702. $aBp['type'] = isset($aBp['type']) ? $aBp['type'] : '';
  1703. if(bx_get('CmtBrowse') !== false)
  1704. $aBp['type'] = bx_process_input(bx_get('CmtBrowse'), BX_DATA_TEXT);
  1705. $aBp['filter'] = isset($aBp['filter']) ? $aBp['filter'] : '';
  1706. if(bx_get('CmtFilter') !== false)
  1707. $aBp['filter'] = bx_process_input(bx_get('CmtFilter'), BX_DATA_TEXT);
  1708. $aBp['start'] = isset($aBp['start']) ? (int)$aBp['start'] : -1;
  1709. if(bx_get('CmtStart') !== false)
  1710. $aBp['start'] = bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT);
  1711. $aBp['per_view'] = isset($aBp['per_view']) ? (int)$aBp['per_view'] : -1;
  1712. if(bx_get('CmtPerView') !== false)
  1713. $aBp['per_view'] = bx_process_input($_REQUEST['CmtPerView'], BX_DATA_INT);
  1714. $aBp['pinned'] = isset($aBp['pinned']) ? (int)$aBp['pinned'] : 0;
  1715. if(bx_get('CmtPinned') !== false)
  1716. $aBp['pinned'] = bx_process_input(bx_get('CmtPinned'), BX_DATA_INT);
  1717. //--- Process 'Display' params.
  1718. $aDp['type'] = isset($aDp['type']) ? $aDp['type'] : '';
  1719. if(bx_get('CmtDisplay') !== false)
  1720. $aDp['type'] = bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT);
  1721. if(bx_get('CmtDisplayStructure') !== false) {
  1722. $aDp['structure'] = bx_process_input($_REQUEST['CmtDisplayStructure'], BX_DATA_INT) == 1;
  1723. if($aDp['structure'] && bx_get('CmtParent') !== false)
  1724. $aBp['parent_id'] = bx_process_input(bx_get('CmtParent'), BX_DATA_INT);
  1725. }
  1726. $aDp['blink'] = isset($aDp['blink']) ? $aDp['blink'] : '';
  1727. if(bx_get('CmtBlink') !== false)
  1728. $aDp['blink'] = bx_process_input($_REQUEST['CmtBlink'], BX_DATA_TEXT);
  1729. $aDp['quote'] = isset($aDp['quote']) ? (int)$aDp['quote'] : 0;
  1730. if(bx_get('CmtQuote') !== false)
  1731. $aDp['quote'] = bx_process_input($_REQUEST['CmtQuote'], BX_DATA_INT);
  1732. $aDp['min_post_form'] = isset($aDp['min_post_form']) ? (bool)$aDp['min_post_form'] : $this->_bMinPostForm;
  1733. if(bx_get('CmtMinPostForm') !== false)
  1734. $aDp['min_post_form'] = bx_process_input(bx_get('CmtMinPostForm'), BX_DATA_INT) == 1;
  1735. $aDp['in_designbox'] = isset($aDp['in_designbox']) ? (bool)$aDp['in_designbox'] : true;
  1736. $aDp['dynamic_mode'] = isset($aDp['dynamic_mode']) ? (bool)$aDp['dynamic_mode'] : false;
  1737. $aDp['show_empty'] = isset($aDp['show_empty']) ? (bool)$aDp['show_empty'] : false;
  1738. }
  1739. protected function _prepareAlertParams($aCmt)
  1740. {
  1741. $iObjId = (int)$this->getId();
  1742. $iObjAthrId = $this->getObjectAuthorId($iObjId);
  1743. $iObjAthrPrivacyView = $this->getObjectPrivacyView($iObjId);
  1744. $iCmtId = (int)$aCmt['cmt_id'];
  1745. $iCmtUniqId = $this->getCommentUniqId($iCmtId);
  1746. $iCmtCf = isset($aCmt['cmt_cf']) ? (int)$aCmt['cmt_cf'] : BxDolContentFilter::getInstance()->getDefaultValue();
  1747. return array(
  1748. 'source' => 'sys_cmts_' . $iCmtUniqId,
  1749. 'object_system' => $this->_sSystem,
  1750. 'object_id' => $iObjId,
  1751. 'object_author_id' => $iObjAthrId,
  1752. 'comment_id' => $iCmtId,
  1753. 'comment_uniq_id' => $iCmtUniqId,
  1754. 'comment_author_id' => $aCmt['cmt_author_id'],
  1755. 'comment_parent_id' => $aCmt['cmt_parent_id'],
  1756. 'comment_text' => $aCmt['cmt_text'],
  1757. 'privacy_view' => $iObjAthrPrivacyView,
  1758. 'cf' => $iCmtCf
  1759. );
  1760. }
  1761. protected function _prepareAlertParamsReply($aCmt, $aCmtPrnt)
  1762. {
  1763. $iObjId = (int)$this->getId();
  1764. $iObjAthrId = $this->getObjectAuthorId($iObjId);
  1765. $iObjAthrPrivacyView = $this->getObjectPrivacyView($iObjId);
  1766. $iCmtPrntId = (int)$aCmt['cmt_parent_id'];
  1767. $iCmtPrntUniqId = $this->getCommentUniqId($iCmtPrntId);
  1768. $iCmtId = (int)$aCmt['cmt_id'];
  1769. $iCmtUniqId = $this->getCommentUniqId($iCmtId);
  1770. return array(
  1771. 'source' => 'sys_cmts_' . $iCmtUniqId,
  1772. 'object_system' => $this->_sSystem,
  1773. 'object_id' => $iObjId,
  1774. 'object_author_id' => $iObjAthrId,
  1775. 'parent_id' => $iCmtPrntId,
  1776. 'parent_uniq_id' => $iCmtPrntUniqId,
  1777. 'parent_author_id' => $aCmtPrnt['cmt_author_id'],
  1778. 'comment_id' => $iCmtId,
  1779. 'comment_uniq_id' => $iCmtUniqId,
  1780. 'comment_author_id' => $aCmt['cmt_author_id'],
  1781. 'comment_text' => $aCmt['cmt_text'],
  1782. 'privacy_view' => $iObjAthrPrivacyView,
  1783. );
  1784. }
  1785. protected function _prepareAuditParams($iId, $aData)
  1786. {
  1787. $sModule = $this->_aSystem['module'];
  1788. $oModule = BxDolModule::getInstance($sModule);
  1789. $CNF = isset($oModule->_oConfig->CNF) ? $oModule->_oConfig->CNF : array();
  1790. $aContentInfo = BxDolRequest::serviceExists($sModule, 'get_all') ? BxDolService::call($sModule, 'get_all', array(array('type' => 'id', 'id' => $this->getId()))) : array();
  1791. $iContextId = 0;
  1792. if (!empty($aContentInfo)){
  1793. $iContextId = isset($CNF['FIELD_ALLOW_VIEW_TO']) && (!empty($aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]) && (int)$aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']] < 0) ? - $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']] : 0;
  1794. }
  1795. $AuditParams = array(
  1796. 'content_title' => $this->getObjectTitle() ,
  1797. 'context_profile_id' => $iContextId,
  1798. 'content_info_object' => isset($CNF['OBJECT_CMTS_CONTENT_INFO']) ? $CNF['OBJECT_CMTS_CONTENT_INFO'] : '',
  1799. 'data' => array_merge(array('comment_id' => $iId), $aData)
  1800. );
  1801. if ($iContextId > 0)
  1802. $AuditParams['context_profile_title'] = BxDolProfile::getInstance($iContextId)->getDisplayName();
  1803. return $AuditParams;
  1804. }
  1805. protected function _prepareTextForOutput ($s, $iCmtId = 0)
  1806. {
  1807. $iDataAction = !$this->isHtml() ? BX_DATA_TEXT_MULTILINE : BX_DATA_HTML;
  1808. $s = bx_process_output($s, $iDataAction);
  1809. $s = bx_linkify_html($s, 'class="' . BX_DOL_LINK_CLASS . '"');
  1810. if($iCmtId && $this->_sMetatagsObj && ($oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj)) !== false)
  1811. $s = $oMetatags->metaParse($this->_oQuery->getUniqId($this->_aSystem['system_id'], $iCmtId), $s);
  1812. return $s;
  1813. }
  1814. protected function _prepareStructureBp($sDType, &$aBp)
  1815. {
  1816. $aBp['type'] = !empty($aBp['type']) ? $aBp['type'] : $this->_sBrowseType;
  1817. $aBp['filter'] = !empty($aBp['filter']) ? $aBp['filter'] : $this->_sBrowseFilter;
  1818. $aBp['parent_id'] = isset($aBp['parent_id']) ? $aBp['parent_id'] : 0;
  1819. $aBp['start'] = isset($aBp['start']) ? $aBp['start'] : -1;
  1820. $aBp['init_view'] = isset($aBp['init_view']) ? $aBp['init_view'] : -1;
  1821. $aBp['per_view'] = isset($aBp['per_view']) ? $aBp['per_view'] : -1;
  1822. $aBp['order']['by'] = isset($aBp['order_by']) ? $aBp['order_by'] : $this->_aOrder['by'];
  1823. $aBp['order']['way'] = isset($aBp['order_way']) ? $aBp['order_way'] : $this->_aOrder['way'];
  1824. if($aBp['per_view'] == -1)
  1825. switch($sDType) {
  1826. case BX_CMT_DISPLAY_FLAT:
  1827. $aBp['per_view'] = $this->getPerView(0);
  1828. break;
  1829. case BX_CMT_DISPLAY_THREADED:
  1830. $aBp['per_view'] = $this->getPerView($aBp['parent_id']);
  1831. break;
  1832. }
  1833. }
  1834. protected function _prepareParams(&$aBp, &$aDp)
  1835. {
  1836. $aBp['type'] = !empty($aBp['type']) ? $aBp['type'] : $this->_sBrowseType;
  1837. $aBp['filter'] = !empty($aBp['filter']) ? $aBp['filter'] : $this->_sBrowseFilter;
  1838. $aBp['parent_id'] = isset($aBp['parent_id']) ? $aBp['parent_id'] : 0;
  1839. $aBp['start'] = isset($aBp['start']) ? $aBp['start'] : -1;
  1840. $aBp['init_view'] = isset($aBp['init_view']) ? $aBp['init_view'] : -1;
  1841. $aBp['per_view'] = isset($aBp['per_view']) ? $aBp['per_view'] : -1;
  1842. $aBp['pinned'] = isset($aBp['pinned']) ? (int)$aBp['pinned'] : 0;
  1843. $aBp['order']['by'] = isset($aBp['order_by']) ? $aBp['order_by'] : $this->_aOrder['by'];
  1844. $aBp['order']['way'] = isset($aBp['order_way']) ? $aBp['order_way'] : $this->_aOrder['way'];
  1845. $aDp['type'] = !empty($aDp['type']) ? $aDp['type'] : $this->_sDisplayType;
  1846. $aDp['blink'] = !empty($aDp['blink']) ? $aDp['blink'] : array();
  1847. if(!is_array($aDp['blink']))
  1848. $aDp['blink'] = explode(',', $aDp['blink']);
  1849. $aDp['quote'] = !empty($aDp['quote']) ? (int)$aDp['quote'] : 0;
  1850. if(!isset($aDp['min_post_form']))
  1851. $aDp['min_post_form'] = $this->_bMinPostForm;
  1852. switch($aDp['type']) {
  1853. case BX_CMT_DISPLAY_FLAT:
  1854. $aBp['vparent_id'] = -1;
  1855. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView(0);
  1856. break;
  1857. case BX_CMT_DISPLAY_THREADED:
  1858. $iParent = 0;
  1859. if(isset($aBp['vparent_id']))
  1860. $iParent = $aBp['vparent_id'];
  1861. else if(isset($aBp['parent_id']))
  1862. $iParent = $aBp['parent_id'];
  1863. $aBp['per_view'] = $aBp['per_view'] != -1 ? $aBp['per_view'] : $this->getPerView($iParent);
  1864. break;
  1865. }
  1866. switch ($aBp['type']) {
  1867. case BX_CMT_BROWSE_POPULAR:
  1868. $aBp['order'] = array(
  1869. 'by' => BX_CMT_ORDER_BY_POPULAR,
  1870. 'way' => BX_CMT_ORDER_WAY_DESC
  1871. );
  1872. break;
  1873. }
  1874. if(!isset($aBp['count']))
  1875. $aBp['count'] = $this->getCommentsCount($this->_iId, $aBp['vparent_id'], $aBp['filter']);
  1876. if($aBp['start'] != -1)
  1877. return;
  1878. $aBp['start'] = 0;
  1879. if($aBp['type'] == BX_CMT_BROWSE_TAIL) {
  1880. $sPerView = ($aBp['init_view'] != -1 ? 'init' : 'per') . '_view';
  1881. $aBp['start'] = $aBp['count'] - $aBp[$sPerView];
  1882. if($aBp['start'] < 0) {
  1883. $aBp[$sPerView] += $aBp['start'];
  1884. $aBp['start'] = 0;
  1885. }
  1886. }
  1887. $this->_setUserChoice($aDp['type'], $aBp['type'], $aBp['filter']);
  1888. }
  1889. protected function _triggerComment()
  1890. {
  1891. if(!$this->_aSystem['trigger_table'] || !$this->_aSystem['trigger_field_id'] || !$this->_aSystem['trigger_field_comments'])
  1892. return false;
  1893. $iId = $this->getId();
  1894. if(!$iId)
  1895. return false;
  1896. $iCount = $this->getCommentsCount($iId);
  1897. return $this->_oQuery->updateTriggerTable($iId, $iCount);
  1898. }
  1899. /**
  1900. * Replace provided markers in a string
  1901. * @param $mixed string or array to replace markers in
  1902. * @return string where all occured markers are replaced
  1903. */
  1904. protected function _replaceMarkers ($mixed)
  1905. {
  1906. return bx_replace_markers($mixed, $this->_aMarkers);
  1907. }
  1908. protected function _getUserChoice()
  1909. {
  1910. $mixedDp = $mixedBpType = $mixedBpFilter = false;
  1911. if(!isLogged())
  1912. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  1913. $iUserId = $this->_getAuthorId();
  1914. $oSession = BxDolSession::getInstance();
  1915. $mixedDp = $oSession->getValue($this->_sDpSessionKey . $iUserId);
  1916. $mixedBpType = $oSession->getValue($this->_sBpSessionKeyType . $iUserId);
  1917. $mixedBpFilter = $oSession->getValue($this->_sBpSessionKeyFilter . $iUserId);
  1918. return array($mixedDp, $mixedBpType, $mixedBpFilter);
  1919. }
  1920. protected function _setUserChoice($sDp, $sBpType, $sBpFilter)
  1921. {
  1922. if(!isLogged())
  1923. return;
  1924. $iUserId = $this->_getAuthorId();
  1925. $oSession = BxDolSession::getInstance();
  1926. if(!empty($sDp))
  1927. $oSession->setValue($this->_sDpSessionKey . $iUserId, $sDp);
  1928. if(!empty($sBpType))
  1929. $oSession->setValue($this->_sBpSessionKeyType . $iUserId, $sBpType);
  1930. if(!empty($sBpFilter))
  1931. $oSession->setValue($this->_sBpSessionKeyFilter . $iUserId, $sBpFilter);
  1932. }
  1933. protected function _sendNotificationEmail($iCmtId, $iCmtParentId)
  1934. {
  1935. $aCmt = $this->getCommentRow($iCmtId);
  1936. $aCmtParent = $this->getCommentRow($iCmtParentId);
  1937. if(empty($aCmt) || !is_array($aCmt) || empty($aCmtParent) || !is_array($aCmtParent) || (int)$aCmt['cmt_author_id'] == (int)$aCmtParent['cmt_author_id'])
  1938. return;
  1939. $oProfile = $this->_getAuthorObject($aCmtParent['cmt_author_id']);
  1940. if($oProfile instanceof BxDolProfileUndefined)
  1941. return;
  1942. $iAccount = $oProfile->getAccountId();
  1943. $aAccount = BxDolAccount::getInstance($iAccount)->getInfo();
  1944. $aPlus = array();
  1945. $aPlus['sender_display_name'] = $oProfile->getDisplayName();
  1946. $aPlus['reply_text'] = $this->_prepareTextForOutput($aCmt['cmt_text'], $iCmtId);
  1947. $sPageUrl = $this->getBaseUrl();
  1948. if(empty($sPageUrl))
  1949. $sPageUrl = $this->getViewUrl($iCmtParentId);
  1950. else
  1951. $sPageUrl .= $this->getItemAnchor($iCmtParentId, true);
  1952. $aPlus['page_url'] = $sPageUrl;
  1953. $sPageTitle = $this->getObjectTitle();
  1954. if(empty($sPageTitle))
  1955. $sPageTitle = _t('_Content');
  1956. $aPlus['page_title'] = $sPageTitle;
  1957. $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('t_CommentReplied', $aPlus);
  1958. return $aTemplate && sendMail($aAccount['email'], $aTemplate['Subject'], $aTemplate['Body']);
  1959. }
  1960. protected function _isShowDoComment($aParams, $isAllowedComment, $bCount)
  1961. {
  1962. $bShowDoComment = !isset($aParams['show_do_comment']) || $aParams['show_do_comment'] == true;
  1963. return $bShowDoComment && ($isAllowedComment || $bCount);
  1964. }
  1965. protected function _isShowCounter($aParams, $isAllowedComment, $bCount)
  1966. {
  1967. $bShowCounter = isset($aParams['show_counter']) && $aParams['show_counter'] === true;
  1968. return $bShowCounter && ($isAllowedComment || $bCount);
  1969. }
  1970. /**
  1971. * Note. By default image based controls aren't used.
  1972. * Therefore it can be overwritten in custom template.
  1973. */
  1974. protected function _getImageDo()
  1975. {
  1976. return '';
  1977. }
  1978. protected function _getIconDo()
  1979. {
  1980. return 'far comment';
  1981. }
  1982. protected function _getTitleDo()
  1983. {
  1984. return '_cmt_txt_do';
  1985. }
  1986. protected function _getParents($aCmt, $iDepthMax, &$iDepth, &$aParents)
  1987. {
  1988. $iParentId = (int)$aCmt['cmt_parent_id'];
  1989. if($iParentId == 0)
  1990. return;
  1991. $aParents[] = $iParentId;
  1992. $iDepth++;
  1993. if($iDepthMax != 0 && $iDepth == $iDepthMax)
  1994. return;
  1995. $aCmt = $this->_oQuery->getCommentsBy(['type' => 'id', 'id' => $iParentId]);
  1996. $this->_getParents($aCmt, $iDepthMax, $iDepth, $aParents);
  1997. }
  1998. public function _getStructure($mixedItem, $aBp, &$iLevel, &$aStructure)
  1999. {
  2000. $bItem = !empty($mixedItem) && is_array($mixedItem);
  2001. $iCmtId = $bItem ? (int)$mixedItem['cmt_id'] : 0;
  2002. $iCmtIndex = $iCmtId;
  2003. if($bItem)
  2004. $aStructure[$iCmtIndex] = [
  2005. 'id' => $mixedItem['cmt_id'],
  2006. 'order' => isset($mixedItem['cmt_order']) ? $mixedItem['cmt_order'] : 0,
  2007. 'items' => [],
  2008. ];
  2009. if(!$bItem || (int)$mixedItem['cmt_replies'] > 0) {
  2010. $aItems = $this->_oQuery->getStructure($this->_iId, $this->_iAuthorId, $iCmtId, $aBp['filter'], $aBp['order']);
  2011. if(!empty($aItems)) {
  2012. if($bItem && $iLevel < (int)$this->_aSystem['number_of_levels']) {
  2013. $iPassLevel = $iLevel + 1;
  2014. $aPassStructure = &$aStructure[$iCmtIndex]['items'];
  2015. }
  2016. else {
  2017. $iPassLevel = $iLevel;
  2018. $aPassStructure = &$aStructure; //--- Is NEEDED here to correctly check sublevels.
  2019. }
  2020. foreach($aItems as $aItem)
  2021. $this->_getStructure($aItem, $aBp, $iPassLevel, $aPassStructure);
  2022. //--- Sort subitems
  2023. $iWay = isset($aBp['order']['way']) && $aBp['order']['way'] == 'desc' ? -1 : 1;
  2024. uasort($aPassStructure, function($aItem1, $aItem2) use ($iWay) {
  2025. if($aItem1['order'] == $aItem2['order'])
  2026. return 0;
  2027. return $iWay * ($aItem1['order'] < $aItem2['order'] ? -1 : 1);
  2028. });
  2029. }
  2030. }
  2031. }
  2032. public function _getStructureAPI($mixedItem, $aBp, &$iLevel, &$aStructure)
  2033. {
  2034. $bItem = !empty($mixedItem) && is_array($mixedItem);
  2035. $iCmtId = $bItem ? (int)$mixedItem['cmt_id'] : 0;
  2036. $sCmtIndex = 'i' . $iCmtId;
  2037. if($bItem) {
  2038. $oMenuActions = BxDolMenu::getObjectInstance($this->_sMenuObjActions);
  2039. $oMenuActions->setCmtsData($this, $iCmtId, $aBp);
  2040. $oMenuManage = BxDolMenu::getObjectInstance($this->_sMenuObjManage);
  2041. $oMenuManage->setCmtsData($this, $iCmtId, $aBp);
  2042. $aData = $this->getCommentSimple($iCmtId);
  2043. bx_import('BxDolEmbed');
  2044. $aData['embed'] = bx_linkify_embeded($aData['cmt_text']);
  2045. $aData = array_merge($this->getDataAPI($aData), [
  2046. 'menu_actions' => $oMenuActions->getCodeAPI(),
  2047. 'menu_manage' => $oMenuManage->getShortCodeAPI(),
  2048. ]);
  2049. $aStructure[$sCmtIndex] = [
  2050. 'id' => $iCmtId,
  2051. 'order' => isset($mixedItem['cmt_order']) ? $mixedItem['cmt_order'] : 0,
  2052. 'data' => $aData,
  2053. 'files' => $this->_getAttachments($mixedItem),
  2054. 'items' => [],
  2055. ];
  2056. }
  2057. if(!$bItem || (int)$mixedItem['cmt_replies'] > 0) {
  2058. $aItems = $this->_oQuery->getStructure($this->_iId, $this->_iAuthorId, $iCmtId, $aBp['filter'], $aBp['order']);
  2059. if(!empty($aItems)) {
  2060. if($bItem && $iLevel < (int)$this->_aSystem['number_of_levels']) {
  2061. $iPassLevel = $iLevel + 1;
  2062. $aPassStructure = &$aStructure[$sCmtIndex]['items'];
  2063. }
  2064. else {
  2065. $iPassLevel = $iLevel;
  2066. $aPassStructure = [];
  2067. }
  2068. foreach($aItems as $aItem)
  2069. $this->_getStructureAPI($aItem, $aBp, $iPassLevel, $aPassStructure);
  2070. //--- Sort subitems
  2071. $iWay = isset($aBp['order']['way']) && $aBp['order']['way'] == 'desc' ? -1 : 1;
  2072. uasort($aPassStructure, function($aItem1, $aItem2) use ($iWay) {
  2073. if($aItem1['order'] == $aItem2['order'])
  2074. return 0;
  2075. return $iWay * ($aItem1['order'] < $aItem2['order'] ? -1 : 1);
  2076. });
  2077. $aStructure[$sCmtIndex]['items'] = $aPassStructure;
  2078. }
  2079. }
  2080. }
  2081. public function getDataAPI($aData, $aParams = [])
  2082. {
  2083. $aDataApi = array_merge($aData, [
  2084. 'cmt_url' => '/' . $this->getViewUrl($aData['cmt_id'], false),
  2085. 'author_data' => BxDolProfile::getData($aData['cmt_author_id']),
  2086. ]);
  2087. $sModule = $this->_aSystem['module'];
  2088. $aExtras = [
  2089. 'module' => $sModule,
  2090. 'data' => $aData,
  2091. 'params' => $aParams,
  2092. 'data_api' => &$aDataApi,
  2093. ];
  2094. /**
  2095. * @hooks
  2096. * @hookdef hook-system-decode_comment_data_api 'system', 'decode_comment_data_api' - hook to override comment data prepared for sending in API response
  2097. * - $unit_name - equals `system`
  2098. * - $action - equals `decode_comment_data_api`
  2099. * - $object_id - not used
  2100. * - $sender_id - not used
  2101. * - $extra_params - array of additional params with the following array keys:
  2102. * - `module` - [string] module name
  2103. * - `data` - [array] comment info array as key&value pairs
  2104. * - `params` - [array] params array as key&value pairs
  2105. * - `data_api` - [array] by ref, comment data prepared for sending in API response, can be overridden in hook processing
  2106. * @hook @ref hook-system-decode_comment_data_api
  2107. */
  2108. bx_alert('system', 'decode_comment_data_api', 0, 0, $aExtras);
  2109. /**
  2110. * @hooks
  2111. * @hookdef hook-bx_dol_comment-decode_comment_data_api '{object_name}', 'decode_comment_data_api' - hook to override comment data prepared for sending in API response
  2112. * It's equivalent to @ref hook-system-decode_comment_data_api
  2113. * @hook @ref hook-bx_dol_comment-decode_comment_data_api
  2114. */
  2115. bx_alert($sModule, 'decode_comment_data_api', 0, 0, $aExtras);
  2116. return $aDataApi;
  2117. }
  2118. }
  2119. /** @} */