BxDolCmts.php 94 KB

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