BxMessengerDb.php 137 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255
  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 Messenger Messenger
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. /**
  12. * Database queries
  13. */
  14. class BxMessengerDb extends BxBaseModGeneralDb
  15. {
  16. private $CNF;
  17. function __construct(&$oConfig)
  18. {
  19. parent::__construct($oConfig);
  20. $this->CNF = &$oConfig->CNF;
  21. }
  22. /**
  23. * Get all lot by class name
  24. *@param string $sClass
  25. *@return array lot info
  26. */
  27. public function getLotByClass($sClass)
  28. {
  29. if (!$sClass)
  30. return '';
  31. $sQuery = $this->prepare("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_CLASS']}` = ? LIMIT 1", $sClass);
  32. return $this->getRow($sQuery);
  33. }
  34. /**
  35. * Get all lot by page url
  36. *@param string $sUrl or the page
  37. *@return array lot info
  38. */
  39. public function getLotByUrl($sUrl)
  40. {
  41. $sQuery = $this->prepare("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_URL']}` = ? LIMIT 1", $sUrl);
  42. return $this->getRow($sQuery);
  43. }
  44. /**
  45. * Get all lot by id
  46. *@param int $iId lot id
  47. *@return array lot info
  48. */
  49. public function getLotInfoById($iId)
  50. {
  51. $sQuery = $this->prepare("SELECT `l`.*, `g`.`{$this->CNF['FMGL_GROUP_ID']}` FROM `{$this->CNF['TABLE_ENTRIES']}` as `l`
  52. LEFT JOIN `{$this->CNF['TABLE_GROUPS_LOTS']}` as `g` ON `g`.`{$this->CNF['FMGL_LOT_ID']}` = `l`.`{$this->CNF['FIELD_ID']}`
  53. WHERE `l`.`{$this->CNF['FIELD_ID']}` = ? LIMIT 1", (int) $iId);
  54. return $this->getRow($sQuery);
  55. }
  56. /**
  57. * Get lot by id or url
  58. *@param int $iId lot id
  59. *@param string $sUrl url or url of the page with talk
  60. *@param int $iAuthor profile id
  61. *@return array lot info
  62. */
  63. public function getLotByIdOrUrl($iId, $sUrl, $iAuthorId = 0)
  64. {
  65. if ($iId)
  66. return $this->getLotInfoById($iId);
  67. if ($sUrl)
  68. return $this->getLotByUrl($sUrl);
  69. return array();
  70. }
  71. /**
  72. * Check if is the member author of the lot or jot
  73. *@param int $iId lot id
  74. *@param int $iAuthor profile id
  75. *@param boolean $bLotAuthor if true checks Lot, otherwise jot
  76. *@return boolean
  77. */
  78. public function isAuthor($iId, $iAuthorId, $bLotAuthor = true)
  79. {
  80. if (!$iAuthorId)
  81. return false;
  82. if ($bLotAuthor)
  83. $sQuery = $this->prepare("SELECT COUNT(*) FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_ID']}` = ? AND `{$this->CNF['FIELD_AUTHOR']}` = ? LIMIT 1", (int) $iId, (int) $iAuthorId);
  84. else
  85. $sQuery = $this->prepare("SELECT COUNT(*) FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = ? AND `{$this->CNF['FIELD_MESSAGE_AUTHOR']}` = ? LIMIT 1", (int) $iId, (int) $iAuthorId);
  86. return $this->getOne($sQuery) == 1;
  87. }
  88. /**
  89. * Deletes lot by lot Id
  90. *@param int $iLotId lot id
  91. *@return int affected rows
  92. */
  93. public function deleteLot($iLotId)
  94. {
  95. $aJots = $this->getJotsByLotId(['lot' => $iLotId]);
  96. foreach ($aJots as $iKey => $aJot)
  97. $this->clearJotsConnections($aJot[$this->CNF['FIELD_MESSAGE_ID']], $iLotId);
  98. $this->query("DELETE FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  99. WHERE `{$this->CNF['FIELD_NEW_LOT']}`=:lot
  100. ", array('lot' => $iLotId));
  101. $this->query("DELETE FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_ID']}` = :id", array('id' => $iLotId));
  102. $this->query("DELETE FROM `{$this->CNF['TABLE_LOT_SETTINGS']}` WHERE `{$this->CNF['FLS_ID']}` = :id", array('id' => $iLotId));
  103. $this->query("DELETE FROM `{$this->CNF['TABLE_USERS_INFO']}` WHERE `{$this->CNF['FIELD_INFO_LOT_ID']}` = :id", array('id' => $iLotId));
  104. $this->query("DELETE FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_FK']}` = :id", array('id' => $iLotId));
  105. $this->query("DELETE FROM `{$this->CNF['TABLE_MASS_TRACKER']}` WHERE `{$this->CNF['FIELD_MASS_CONVO_ID']}` = :id", array('id' => $iLotId));
  106. $this->removeNotifications(0, $iLotId);
  107. return true;
  108. }
  109. /**
  110. * Clear lot history
  111. *@param int $iLotId lot id
  112. *@return boolean result
  113. */
  114. public function clearLot($iLotId)
  115. {
  116. $aJots = $this->getJotsByLotId(['lot' => $iLotId]);
  117. foreach ($aJots as $iKey => $aJot)
  118. $this->clearJotsConnections($aJot[$this->CNF['FIELD_MESSAGE_ID']], $iLotId);
  119. return $this->query("DELETE FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_FK']}` = :id", array('id' => $iLotId));
  120. }
  121. /**
  122. * Deletes jot
  123. *@param int iJotId jot id
  124. *@param int iProfileId member who deleted jot
  125. *@param boolean $bCompletely if true totally remove from the site
  126. *@return int affected rows
  127. */
  128. public function deleteJot($iJotId, $iProfileId, $bCompletely = false)
  129. {
  130. $iJotId = (int) $iJotId;
  131. if ($bCompletely) {
  132. $this->clearJotsConnections($iJotId);
  133. return $this->query("DELETE FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = :id", array('id' => $iJotId));
  134. }
  135. return $this->query("UPDATE `{$this->CNF['TABLE_MESSAGES']}`
  136. SET
  137. `{$this->CNF['FIELD_MESSAGE_TRASH']}` = 1,
  138. `{$this->CNF['FIELD_MESSAGE_LAST_EDIT']}` = UNIX_TIMESTAMP(),
  139. `{$this->CNF['FIELD_MESSAGE_EDIT_BY']}` = :profile
  140. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = :id", array('id' => $iJotId, 'profile' => $iProfileId));
  141. }
  142. public function clearJotsConnections($iJotId, $iLotId = 0)
  143. {
  144. $this->removeFilesByJotId($iJotId);
  145. $this->deleteJotReactions($iJotId);
  146. $this->deleteSavedJotItems($iJotId);
  147. if (!$iLotId)
  148. $iLotId = $this->getLotByJotId($iJotId, true);
  149. if ($iLotId) {
  150. $aUnreadJots = $this->getAll("SELECT *
  151. FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  152. WHERE `{$this->CNF['FIELD_NEW_JOT']}`<=:jot AND `{$this->CNF['FIELD_NEW_LOT']}`=:lot", array('jot' => $iJotId, 'lot' => $iLotId));
  153. foreach ($aUnreadJots as &$aUnreadJot) {
  154. $iProfileId = (int) $aUnreadJot[$this->CNF['FIELD_NEW_PROFILE']];
  155. $iUnreadJotId = (int) $aUnreadJot[$this->CNF['FIELD_NEW_JOT']];
  156. if ($iUnreadJotId && $iUnreadJotId < (int) $iJotId)
  157. $this->query("
  158. UPDATE `{$this->CNF['TABLE_NEW_MESSAGES']}`
  159. SET `{$this->CNF['FIELD_NEW_UNREAD']}`=`{$this->CNF['FIELD_NEW_UNREAD']}` - 1
  160. WHERE `{$this->CNF['FIELD_NEW_LOT']}`=:lot AND `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile AND `{$this->CNF['FIELD_NEW_UNREAD']}` > 0
  161. ", array('lot' => $iLotId, 'profile' => $iProfileId));
  162. else
  163. $this->deleteNewJot($iProfileId, $iLotId, $iJotId);
  164. }
  165. }
  166. }
  167. public function updateJot($iJotId, $sField, $mixedValue)
  168. {
  169. return $this->query("UPDATE `{$this->CNF['TABLE_MESSAGES']}`
  170. SET
  171. `{$sField}` =:value
  172. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = :id", array('id' => $iJotId, 'value' => $mixedValue));
  173. }
  174. /**
  175. * Removes participant from the participants list
  176. *@param int $iLotId lot id
  177. *@param int $iParticipant profile id
  178. *@return int/false
  179. */
  180. public function leaveLot($iLotId, $iParticipant)
  181. {
  182. $this->deleteNewJot($iParticipant, $iLotId);
  183. return $this->removeParticipant($iLotId, $iParticipant);
  184. }
  185. /**
  186. * Get Lot(Talk) settings for a member
  187. *@param int $iLotId lot id
  188. *@param int $iParticipant profile id
  189. *@param string $sName name the option
  190. *@param boolean $bParams get from params array, otherwise from table's field
  191. *@return mixed option value
  192. */
  193. private function getParams($iLotId, $iParticipant, $sName = 0, $bParams = false)
  194. {
  195. $sQuery = $this->prepare("SELECT * FROM `{$this->CNF['TABLE_USERS_INFO']}`
  196. WHERE `{$this->CNF['FIELD_INFO_LOT_ID']}` = ? AND `{$this->CNF['FIELD_INFO_USER_ID']}` = ?
  197. LIMIT 1", (int) $iLotId, (int) $iParticipant);
  198. $aInfo = $this->getRow($sQuery);
  199. if (empty($aInfo))
  200. return false;
  201. if (!$sName)
  202. return $aInfo;
  203. if (!$bParams) {
  204. $aParams = unserialize($aInfo[$this->CNF['FIELD_INFO_PARAMS']]);
  205. return isset($aParams[$sName]) ? $aParams[$sName] : 0;
  206. }
  207. return $aInfo[$sName];
  208. }
  209. /**
  210. * Save Lot(Talk) settings for a member
  211. *@param int $iLotId lot id
  212. *@param int $iParticipant profile id
  213. *@param array $aParams options list
  214. *@param boolean $bParams get from params array otherwise as table field
  215. *@return int affected rows
  216. */
  217. private function setParams($iLotId, $iParticipant, $sName, $sValue, $bParams = false)
  218. {
  219. $aParams = $this->getParams($iLotId, $iParticipant);
  220. if (!$bParams) {
  221. if (empty($aParams))
  222. return $this->query("INSERT INTO `{$this->CNF['TABLE_USERS_INFO']}` SET `{$this->CNF['FIELD_INFO_PARAMS']}` = :values, `{$this->CNF['FIELD_INFO_LOT_ID']}` = :id, `{$this->CNF['FIELD_INFO_USER_ID']}` = :user", array('user' => $iParticipant, 'id' => $iLotId, 'values' => serialize(array($sName => $sValue))));
  223. return $this->query("UPDATE `{$this->CNF['TABLE_USERS_INFO']}` SET `{$this->CNF['FIELD_INFO_PARAMS']}` = :values WHERE `{$this->CNF['FIELD_INFO_LOT_ID']}` = :id AND `{$this->CNF['FIELD_INFO_USER_ID']}` = :user", array('user' => $iParticipant, 'id' => $iLotId, 'values' => serialize(array($sName => $sValue))));
  224. }
  225. if (empty($aParams))
  226. return $this->query("INSERT INTO `{$this->CNF['TABLE_USERS_INFO']}` SET `{$sName}` = :value, `{$this->CNF['FIELD_INFO_LOT_ID']}` = :id, `{$this->CNF['FIELD_INFO_USER_ID']}` = :user", array('user' => $iParticipant, 'id' => $iLotId, 'value' => $sValue));
  227. return $this->query("UPDATE `{$this->CNF['TABLE_USERS_INFO']}` SET `{$sName}` = :value WHERE `{$this->CNF['FIELD_INFO_LOT_ID']}` = :id AND `{$this->CNF['FIELD_INFO_USER_ID']}` = :user", array('user' => $iParticipant, 'id' => $iLotId, 'value' => $sValue));
  228. }
  229. /**
  230. * Make the lot mute for a member
  231. *@param int $iLotId lot id
  232. *@param int $iParticipant profile id
  233. *@return int set value
  234. */
  235. public function muteLot($iLotId, $iParticipant)
  236. {
  237. $iCurrentNotification = (int) $this->getParams($iLotId, $iParticipant, 'notification');
  238. $iNotification = (int) !$iCurrentNotification;
  239. $this->setParams($iLotId, $iParticipant, 'notification', $iNotification);
  240. return $iNotification;
  241. }
  242. /**
  243. * Mark the lot with star
  244. *@param int $iLotId lot id
  245. *@param int $iParticipant profile id
  246. *@return int set
  247. */
  248. public function starLot($iLotId, $iParticipant)
  249. {
  250. $iCurrent = (int) $this->getParams($iLotId, $iParticipant, 'star', true);
  251. $iNew = (int) !$iCurrent;
  252. $this->setParams($iLotId, $iParticipant, 'star', $iNew, true);
  253. return $iNew;
  254. }
  255. /**
  256. * Talks from the list that the member marked with a star
  257. *@param int $iProfileId profile id
  258. *@param array $aLotIds lots ids
  259. *@return array lots ids
  260. */
  261. public function getStarredLots($iProfileId, $aLotIds)
  262. {
  263. $aLotIds = array_filter(array_map('intval', (array)$aLotIds));
  264. if (!$iProfileId || empty($aLotIds)) {
  265. return [];
  266. }
  267. return $this->getColumn("SELECT `{$this->CNF['FIELD_INFO_LOT_ID']}` FROM `{$this->CNF['TABLE_USERS_INFO']}`
  268. WHERE `{$this->CNF['FIELD_INFO_USER_ID']}` = :profile AND `{$this->CNF['FIELD_INFO_STAR']}` = 1
  269. AND `{$this->CNF['FIELD_INFO_LOT_ID']}` IN (" . implode(',', $aLotIds) . ")", ['profile' => (int)$iProfileId]);
  270. }
  271. public function isStarred($iLotId, $iParticipant)
  272. {
  273. return $this->getParams($iLotId, $iParticipant, 'star', true);
  274. }
  275. /**
  276. * Check if the lot is mute for a member
  277. *@param int $iLotId lot id
  278. *@param int $iParticipant profile id
  279. *@return boolean
  280. */
  281. public function isMuted($iLotId, $iParticipant)
  282. {
  283. return $this->getParams($iLotId, $iParticipant, 'notification');
  284. }
  285. /**
  286. /**
  287. * Save participants list for the lot
  288. *@param int $iLotId lot id
  289. *@param array $aParticipants
  290. *@return int affected rows
  291. */
  292. public function saveParticipantsList($iLotId, $aParticipants)
  293. {
  294. $sParticipants = '';
  295. if (!empty($aParticipants) && is_array($aParticipants)) {
  296. $aParticipants = array_map('intval', $aParticipants);
  297. $sParticipants = implode(',', $aParticipants);
  298. }
  299. return $this->query("UPDATE `{$this->CNF['TABLE_ENTRIES']}` SET `{$this->CNF['FIELD_PARTICIPANTS']}` = :parts WHERE `{$this->CNF['FIELD_ID']}` = :id", array('parts' => $sParticipants, 'id' => $iLotId));
  300. }
  301. public function findThePageOwner($mixedPage)
  302. {
  303. $iAuthorId = 0;
  304. if (!$mixedPage)
  305. return $iAuthorId;
  306. if (is_string($mixedPage))
  307. parse_str($mixedPage, $aUrl);
  308. else if (is_array($mixedPage))
  309. $aUrl = $mixedPage;
  310. if (empty($aUrl) || !isset($aUrl['id']) || !isset($aUrl['i']))
  311. return $iAuthorId;
  312. $sModule = $this->getOne("SELECT `module` FROM `sys_objects_page` WHERE LOWER(`uri`)=:uri", array('uri' => strtolower($aUrl['i'])));
  313. if (!$sModule)
  314. return $iAuthorId;
  315. $aTable = $this->getRow("SELECT `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`
  316. FROM `sys_objects_cmts`
  317. WHERE `Module`=:module LIMIT 1", array('module' => $sModule));
  318. if (empty($aTable))
  319. return $iAuthorId;
  320. if (isset($aTable['TriggerTable']) && isset($aTable['TriggerFieldId']) && isset($aTable['TriggerFieldAuthor']))
  321. return $this->getOne(
  322. "SELECT `{$aTable['TriggerFieldAuthor']}`
  323. FROM `{$aTable['TriggerTable']}`
  324. WHERE `{$aTable['TriggerFieldId']}`=:id",
  325. array('id' => $aUrl['id'])
  326. );
  327. return $iAuthorId;
  328. }
  329. function createLot($iProfileId, $aData)
  330. {
  331. $sUrl = isset($aData['url']) ? $aData['url'] : '';
  332. $aParticipants = isset($aData['participants']) ? $aData['participants'] : array();
  333. $iAuthorId = $this->findThePageOwner($sUrl);
  334. if (isset($aData['thread']) || !$iAuthorId)
  335. $iAuthorId = $iProfileId;
  336. $iLotId = $this->createNewLot($iAuthorId, $aData, $aParticipants);
  337. if (!$iLotId)
  338. return false;
  339. bx_alert($this->_oConfig->getObject('alert'), 'create_lot', $iLotId, $iProfileId, $this->getLotInfoById($iLotId));
  340. foreach ($aParticipants as &$iParticipant) {
  341. if ((int) $iParticipant === (int) $iProfileId)
  342. continue;
  343. bx_alert($this->_oConfig->getObject('alert'), 'add_part', $iParticipant, $iProfileId, array('lot_id' => $iLotId, 'author_id' => $iAuthorId));
  344. }
  345. return $iLotId;
  346. }
  347. /**
  348. * Save message for participants to database
  349. *@param array $aData lot settings
  350. *@param array $aParticipants participants list, if it empty then used default for lot
  351. *@return int affected rows
  352. */
  353. public function saveMessage($aData)
  354. {
  355. $iLotId = isset($aData['lot']) ? (int) $aData['lot'] : 0;
  356. $aLotInfo = $iLotId ? $this->getLotInfoById($iLotId) : [];
  357. if (empty($aLotInfo) && $aData['type'] == BX_IM_TYPE_PRIVATE && !$aData['title'])
  358. $aLotInfo = $this->findLotByParams($aData);
  359. if ($iLotId && $aData['type'] == BX_IM_TYPE_PRIVATE && !$this->isParticipant($iLotId, $aData['member_id']))
  360. return false;
  361. if (empty($aLotInfo)) {
  362. $iLotId = $this->createLot((int) $aData['member_id'], $aData);
  363. if (isset($aData['group_id']) && (int) $aData['group_id'] && (int) $iLotId)
  364. $this->addLotToGroup($iLotId, $aData['group_id']);
  365. } else
  366. $iLotId = $aLotInfo[$this->CNF['FIELD_ID']];
  367. if (($aData['type'] != BX_IM_TYPE_PRIVATE || $this->isAuthor($iLotId, $aData['member_id'])) && !$this->isParticipant($iLotId, $aData['member_id'], true)) {
  368. if ($this->addMemberToParticipantsList($iLotId, $aData['member_id']))
  369. bx_alert(
  370. $this->_oConfig->getObject('alert'),
  371. 'participant_joined',
  372. $iLotId,
  373. $aData['member_id'],
  374. array(
  375. 'url' => $aData['url'],
  376. 'object_author_id' => !empty($aLotInfo[$this->CNF['FIELD_AUTHOR']]) ? $aLotInfo[$this->CNF['FIELD_AUTHOR']] : $this->findThePageOwner($aData['url'])
  377. )
  378. );
  379. }
  380. $aData['message'] = clear_xss($aData['message']);
  381. return $this->addJot($iLotId, $aData['message'], $aData['member_id']);
  382. }
  383. /**
  384. * Find appropriate Talk using input params
  385. *@param array $aData params
  386. *@return array Lot info
  387. */
  388. public function findLotByParams($aData)
  389. {
  390. $sUrl = isset($aData['url']) ? $aData['url'] : '';
  391. $aParticipants = isset($aData['participants']) && is_array($aData['participants']) ? $aData['participants'] : [];
  392. $sClass = isset($aData['class']) ? $aData['class'] : '';
  393. $iType = isset($aData['type']) ? $aData['type'] : 0;
  394. $aWhere = $aWhereBindings = [];
  395. $aLots = [];
  396. if (!empty($aParticipants)) {
  397. $aItems = $this->getLotsByParticipantsList($aParticipants, $iType, true);
  398. foreach ($aItems as &$aItem)
  399. $aLots[] = $aItem[$this->CNF['FIELD_ID']];
  400. if (!empty($aLots))
  401. $aWhere[] = "`{$this->CNF['FIELD_ID']}` IN (" . implode(',', $aLots) . ")";
  402. else
  403. return [];
  404. }
  405. if ($sClass) {
  406. $aWhere[] = "`{$this->CNF['FIELD_CLASS']}` =:class";
  407. $aWhereBindings['class'] = $sClass;
  408. }
  409. if ($sUrl) {
  410. $aWhere[] = "`{$this->CNF['FIELD_URL']}` =:url";
  411. $aWhereBindings['url'] = $sUrl;
  412. }
  413. if ($iType) {
  414. $aWhere[] = "`{$this->CNF['FIELD_TYPE']}` =:type";
  415. $aWhereBindings['type'] = $iType;
  416. }
  417. return $this->getRow("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}`
  418. WHERE " . implode(' AND ', $aWhere) . " LIMIT 1", $aWhereBindings);
  419. }
  420. function getLotsByParticipantsList($aParticipants, $mixedType = false, $bGetAll = false)
  421. {
  422. $aParticipantsList = $aResult = [];
  423. if (empty($aParticipants))
  424. return $aResult;
  425. foreach ($aParticipants as &$iParticipant)
  426. $aParticipantsList[] = "(^|,)" . (int) $iParticipant . "(,|$)";
  427. if (empty($aParticipantsList))
  428. return $aResult;
  429. $aWhere[] = "`{$this->CNF['FIELD_PARTICIPANTS']}` REGEXP '" . implode('|', $aParticipantsList) . "'";
  430. if ($mixedType)
  431. $aWhere[] = "`{$this->CNF['FIELD_TYPE']}` = " . $mixedType;
  432. $aLots = $this->getAll("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE " . implode(' AND ', $aWhere) . " ORDER BY `{$this->CNF['FIELD_ID']}` ASC ");
  433. if (empty($aLots))
  434. return $aResult;
  435. foreach ($aLots as &$aLot) {
  436. $aTalkParticipants = explode(',', $aLot[$this->CNF['FIELD_PARTICIPANTS']]);
  437. if (count($aTalkParticipants) != count($aParticipants))
  438. continue;
  439. sort($aTalkParticipants);
  440. sort($aParticipants);
  441. if (array_values($aTalkParticipants) == array_values($aParticipants))
  442. $aResult[] = $aLot;
  443. }
  444. return !$bGetAll && !empty($aResult) ? current($aResult) : $aResult;
  445. }
  446. /**
  447. * Mark message as read in lot history
  448. *@param int $iJotId message id
  449. *@param int iProfileId
  450. */
  451. public function readMessage($iJotId, $iProfileId)
  452. {
  453. $aJotInfo = $this->getJotById($iJotId);
  454. if (!empty($aJotInfo) && $this->deleteNewJot($iProfileId, $aJotInfo[$this->CNF['FIELD_MESSAGE_FK']], $iJotId))
  455. bx_alert($this->_oConfig->getObject('alert'), 'read_jot', $iJotId, $iProfileId, array('author_id' => $aJotInfo[$this->CNF['FIELD_MESSAGE_AUTHOR']], 'lot_id' => $aJotInfo[$this->CNF['FIELD_MESSAGE_FK']]));
  456. }
  457. /**
  458. * Mark all message as read in lot history for member
  459. * @param int $iLot lot id
  460. * @param int iProfileId
  461. * @return false
  462. */
  463. public function readAllMessages($iLot, $iProfileId)
  464. {
  465. $CNF = &$this->_oConfig->CNF;
  466. $aNew = $this->getNewJots($iProfileId, $iLot);
  467. if (empty($aNew))
  468. return false;
  469. bx_alert(
  470. $this->_oConfig->getObject('alert'),
  471. 'read_bulk_jot',
  472. $iLot,
  473. $iProfileId,
  474. array(
  475. 'first_jot' => $aNew[$CNF['FIELD_NEW_JOT']],
  476. 'count' => $aNew[$CNF['FIELD_NEW_JOT']],
  477. 'lot_id' => $iLot
  478. )
  479. );
  480. $this->deleteNewJot($iProfileId, $iLot);
  481. $this->markNotificationAsRead($iProfileId, $iLot);
  482. }
  483. /**
  484. *Add new new jot to database
  485. *@param int $iLotID lot id
  486. *@param string $sMessage posted message
  487. *@param int iProfile Id owner of the message
  488. *@return int affected rows
  489. */
  490. public function addJot($iLotId, $sMessage, $iProfileId)
  491. {
  492. $sQuery = $this->prepare("INSERT INTO `{$this->CNF['TABLE_MESSAGES']}`
  493. SET `{$this->CNF['FIELD_MESSAGE']}` = ?,
  494. `{$this->CNF['FIELD_MESSAGE_FK']}` = ?,
  495. `{$this->CNF['FIELD_MESSAGE_AUTHOR']}` = ?,
  496. `{$this->CNF['FIELD_MESSAGE_ADDED']}` = UNIX_TIMESTAMP()", $sMessage, $iLotId, $iProfileId);
  497. if (!$this->query($sQuery))
  498. return false;
  499. $iJotId = $this->lastId();
  500. $aParticipants = $this->getParticipantsList($iLotId, true, $iProfileId);
  501. $this->markAsNewJot($aParticipants, $iLotId, $iJotId);
  502. return $iJotId;
  503. }
  504. /**
  505. *Create new chat/lot with list of participants
  506. *@param int iProfileId owner of the lot
  507. *@param string $sTitle lot title
  508. *@param int $iType type of the lot
  509. *@param string $sUrl url of the page
  510. *@param array $aParticipants list of participants
  511. *@return int affected rows
  512. */
  513. public function createNewLot($iProfileId, $aData, $aParticipants = array())
  514. {
  515. $CNF = &$this->_oConfig->CNF;
  516. // before to create lot
  517. bx_alert($this->_oConfig->getObject('alert'), 'create_lot_before', 0, $iProfileId, array(
  518. 'data' => &$aData,
  519. 'participants' => &$aParticipants
  520. ));
  521. $sTitle = isset($aData['title']) ? $aData['title'] : '';
  522. $iType = isset($aData['type']) ? (int) $aData['type'] : BX_IM_TYPE_PRIVATE;
  523. $sUrl = isset($aData['url']) ? $aData['url'] : '';
  524. $sPage = isset($aData['page']) ? $aData['page'] : '';
  525. $sClass = isset($aData['class']) ? $aData['class'] : BX_MSG_TALK_CLASS_CUSTOM;
  526. $iThread = isset($aData['thread']) ? (int) $aData['thread'] : BX_ATT_TYPE_CUSTOM;
  527. $iVisibility = isset($aData['visibility']) ? (int) $aData['visibility'] : 0;
  528. $sHash = $this->_oConfig->generateConvoHash(time());
  529. $mixedParticipants = !empty($aParticipants) ? implode(',', $aParticipants) : '';
  530. $sQuery = $this->prepare(
  531. "INSERT INTO `{$this->CNF['TABLE_ENTRIES']}`
  532. SET `{$this->CNF['FIELD_TITLE']}` = ?,
  533. `{$this->CNF['FIELD_TYPE']}` = ?,
  534. `{$this->CNF['FIELD_AUTHOR']}` = ?,
  535. `{$this->CNF['FIELD_ADDED']}` = UNIX_TIMESTAMP(),
  536. `{$this->CNF['FIELD_PARTICIPANTS']}` = ?,
  537. `{$this->CNF['FIELD_VISIBILITY']}` = ?,
  538. `{$this->CNF['FIELD_CLASS']}` = ?,
  539. `{$this->CNF['FIELD_PARENT_JOT']}` = ?,
  540. `{$this->CNF['FIELD_URL']}` = ?,
  541. `{$this->CNF['FIELD_HASH']}` = ?",
  542. $sTitle,
  543. $iType,
  544. $iProfileId,
  545. $mixedParticipants,
  546. $iVisibility,
  547. $sClass,
  548. $iThread,
  549. $sUrl,
  550. $sHash
  551. );
  552. return $this->query($sQuery) ? $this->lastId() : false;
  553. }
  554. /**
  555. *Get list of types of member lots
  556. *@param int iProfileId
  557. *@param string $sParam keyword to filter lots
  558. *@return array found lots types with lots count per each type
  559. */
  560. public function getMemberLotsTypes($iProfileId, $sParam = '')
  561. {
  562. $sWhere = '';
  563. $aWhere = array();
  564. if ($iProfileId) {
  565. $aSWhere[] = "FIND_IN_SET(:profile, `{$this->CNF['FIELD_PARTICIPANTS']}`)";
  566. $aWhere = array('profile' => $iProfileId);
  567. }
  568. if ($sParam) {
  569. $sParam = "%{$sParam}%";
  570. $aSWhere[] = " (`{$this->CNF['FIELD_TITLE']}` LIKE :title OR `{$this->CNF['FIELD_URL']}` LIKE :url OR `{$this->CNF['FIELD_TYPE']}` LIKE :type)";
  571. $aWhere = array_merge($aWhere, array('title' => $sParam, 'url' => $sParam, 'type' => $sParam));
  572. }
  573. if (!empty($aWhere))
  574. $sWhere = "WHERE (" . implode(' AND ', $aSWhere) . ')';
  575. return $this->getPairs("SELECT `{$this->CNF['FIELD_TYPE']}`, COUNT(*) as `count`
  576. FROM `{$this->CNF['TABLE_ENTRIES']}`
  577. {$sWhere}
  578. GROUP BY `{$this->CNF['FIELD_TYPE']}`", $this->CNF['FIELD_TYPE'], 'count', $aWhere);
  579. }
  580. /**
  581. *Get list of all existed types
  582. *@return array types
  583. */
  584. public function getAllLotsTypes()
  585. {
  586. return $this->getAll("SELECT * FROM `{$this->CNF['TABLE_TYPES']}` ORDER BY `{$this->CNF['FIELD_TYPE_ID']}` ASC");
  587. }
  588. /**
  589. *Get list of all existed types as pairs: Id - Value
  590. *@return array types
  591. */
  592. public function getLotsTypesPairs()
  593. {
  594. return $this->getPairs("SELECT * FROM `{$this->CNF['TABLE_TYPES']}` ORDER BY `{$this->CNF['FIELD_TYPE_ID']}`", $this->CNF['FIELD_TYPE_ID'], $this->CNF['FIELD_TYPE_NAME']);
  595. }
  596. public function getLotTypeId($sType)
  597. {
  598. return $this->getOne("SELECT `{$this->CNF['FIELD_TYPE_ID']}` FROM `{$this->CNF['TABLE_TYPES']}` WHERE `{$this->CNF['FIELD_TYPE_NAME']}`=:name LIMIT 1", ['name' => $sType]);
  599. }
  600. /**
  601. * Check if this ype of lot exists
  602. *@param int $iType type of the lot
  603. *@return boolean
  604. */
  605. public function isLotType($iType)
  606. {
  607. return $this->getOne("SELECT COUNT(*) FROM `{$this->CNF['TABLE_TYPES']}` WHERE `{$this->CNF['FIELD_TYPE_ID']}` = :type LIMIT 1", array('type' => $iType)) == 1;
  608. }
  609. /**
  610. * Get lot's participant list
  611. *@param int $iLotId lot id
  612. *@param boolean $bArray if true, returns result as array, otherwise string with ids separated commas
  613. *@param int $bExcludeProfile allows to exclude profile from the list, usually it is owner
  614. *@return string/array
  615. */
  616. public function getParticipantsList($iLotId, $bArray = true, $bExcludeProfile = 0)
  617. {
  618. $sParticipants = $this->getOne("SELECT `{$this->CNF['FIELD_PARTICIPANTS']}` FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_ID']}` = :value", array('value' => $iLotId));
  619. if (!$sParticipants)
  620. return [];
  621. $aParticipants = explode(',', $sParticipants);
  622. if ($bExcludeProfile && ($iId = array_search($bExcludeProfile, $aParticipants)) !== FALSE)
  623. unset($aParticipants[$iId]);
  624. return !$bArray ? implode(',', $aParticipants) : $aParticipants;
  625. }
  626. /**
  627. * Check if it is participant of the lot
  628. *@param int $iLotId lot id
  629. *@param int $iParticipantId profile id
  630. *@param boolean $bAsParticipant if true to check only participants list without lot owner
  631. *@return boolean
  632. */
  633. public function isParticipant($iLotId, $iParticipantId, $bAsParticipant = false)
  634. {
  635. $aParticipants = $this->getParticipantsList($iLotId);
  636. if (array_search($iParticipantId, $aParticipants) !== FALSE)
  637. return true;
  638. $aLotInfo = $this->getLotInfoById($iLotId);
  639. if (!empty($aLotInfo) && $aLotInfo[$this->CNF['FIELD_TYPE']] == BX_IM_TYPE_BROADCAST)
  640. return $this->isBroadcastParticipant($iLotId, $iParticipantId);
  641. return !$bAsParticipant ? $this->getOne("SELECT COUNT(*) FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_ID']}` = :lot AND `{$this->CNF['FIELD_AUTHOR']}` = :author LIMIT 1", array('lot' => (int) $iLotId, 'author' => (int) $iParticipantId)) == 1 : false;
  642. }
  643. /**
  644. * Add profile to lot's participants list
  645. *@param int $iLotId lot id
  646. *@param int $iParticipantId profile id
  647. *@return int affected rows
  648. */
  649. public function addMemberToParticipantsList($iLotId, $iParticipantId)
  650. {
  651. $sParticipants = $this->getParticipantsList($iLotId, false /* as string list */);
  652. $sParticipants = $sParticipants ? "{$sParticipants},{$iParticipantId}" : $iParticipantId;
  653. return $this->query("UPDATE `{$this->CNF['TABLE_ENTRIES']}` SET `{$this->CNF['FIELD_PARTICIPANTS']}` = :parts WHERE `{$this->CNF['FIELD_ID']}` = :id", array('parts' => $sParticipants, 'id' => $iLotId));
  654. }
  655. /**
  656. * Remove profile from participants list
  657. *@param int $iLotId lot id
  658. *@param int $iParticipantId profile id
  659. *@return mixed false or affected rows
  660. */
  661. public function removeParticipant($iLotId, $iParticipantId)
  662. {
  663. $aParticipants = $this->getParticipantsList($iLotId);
  664. $iKey = array_search($iParticipantId, $aParticipants);
  665. if ($iKey !== FALSE) {
  666. unset($aParticipants[$iKey]);
  667. return $this->saveParticipantsList($iLotId, $aParticipants);
  668. }
  669. return false;
  670. }
  671. /**
  672. * Get jots list for specified lot
  673. * @param $aData
  674. * @return array of the jots
  675. */
  676. public function getJotsByLotId($aData)
  677. { /* $iLotId, $iStart = BX_IM_EMPTY, $sMode = 'new', $iLimit = BX_IM_EMPTY, $bInclude = false */
  678. $iLotId = isset($aData['lot']) ? (int)$aData['lot'] : BX_IM_EMPTY;
  679. $iStart = isset($aData['start']) ? (int)$aData['start'] : BX_IM_EMPTY;
  680. $sMode = $aData['mode'] ?? 'new';
  681. $iLimit = isset($aData['limit']) ? (int) $aData['limit'] : BX_IM_EMPTY;
  682. $bInclude = isset($aData['include']) && $aData['include'];
  683. $sArea = $aData['area'] ?? '';
  684. $sJoin = $sWhereJoin = $sLimit = '';
  685. $aSWhere[] = "`m`.`{$this->CNF['FIELD_MESSAGE_FK']}` = :lot_id ";
  686. $aBindings['lot_id'] = (int) $iLotId;
  687. $sInsideOrder = $sMode == 'all' ? 'ASC' : 'DESC';
  688. if ($iStart && $sMode !== 'all') {
  689. $sEqual = '';
  690. if ($bInclude)
  691. $sEqual = '=';
  692. $aSWhere[] = "`m`.`{$this->CNF['FIELD_MESSAGE_ID']}` " . ($sMode == 'new' ? '>' . $sEqual : '<' . $sEqual) . " :start ";
  693. $aBindings['start'] = (int) $iStart;
  694. if ($sMode == 'new')
  695. $sInsideOrder = 'ASC';
  696. }
  697. if ($iLimit) {
  698. $sLimit = "LIMIT :limit";
  699. $aBindings['limit'] = (int) $iLimit;
  700. }
  701. if (!empty($aBindings))
  702. $sWhere = 'WHERE ' . implode(' AND ', $aSWhere);
  703. if ($sArea)
  704. list($sJoin, $sWhereJoin, $sFields, $sGroupBy) = $this->getJotsByArea($sArea);
  705. $sQuery = "SELECT `m`.* FROM `{$this->CNF['TABLE_MESSAGES']}` as `m`
  706. {$sJoin}
  707. {$sWhere} {$sWhereJoin}
  708. ORDER BY `m`.`{$this->CNF['FIELD_MESSAGE_ID']}` {$sInsideOrder}
  709. {$sLimit}";
  710. return $this->getAll($iStart && $sMode == 'new' ? $sQuery : "({$sQuery}) ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}`", $aBindings);
  711. }
  712. function getJotsByArea($sArea)
  713. {
  714. $CNF = &$this->_oConfig->CNF;
  715. $sGroupBy = $sJoin = $sWhere = $sFields = '';
  716. $iProfileId = bx_get_logged_profile_id();
  717. switch ($sArea) {
  718. case BX_MSG_TALK_TYPE_MR:
  719. $sUrl = BxDolProfile::getInstance($iProfileId)->getUrl();
  720. $sJoin = "LEFT JOIN `{$CNF['TABLE_JOT_REACTIONS']}` as `r` ON `m`.`{$CNF['FIELD_MESSAGE_ID']}` = `r`.`{$CNF['FIELD_REACT_JOT_ID']}`";
  721. $sWhere = "AND ((`r`.`{$CNF['FIELD_REACT_JOT_ID']}` IS NOT NULL AND `m`.`{$CNF['FIELD_MESSAGE_AUTHOR']}`= '{$iProfileId}') OR `m`.`{$CNF['FIELD_MESSAGE']}` LIKE '\"%" . '/' . bx_ltrim_str($sUrl, BX_DOL_URL_ROOT) . "\"')";
  722. break;
  723. case BX_MSG_TALK_TYPE_THREADS:
  724. break;
  725. case BX_MSG_TALK_TYPE_SAVED:
  726. $sJoin = "INNER JOIN `{$CNF['TABLE_SAVED_JOTS']}` as `s` ON `s`.`{$CNF['FSJ_ID']}` = `m`.`{$CNF['FIELD_MESSAGE_ID']}` AND `s`.`{$CNF['FSJ_PROFILE_ID']}` = " . (int)$iProfileId;
  727. $sWhere = "AND `s`.`{$CNF['FSJ_ID']}` IS NOT NULL";
  728. break;
  729. case BX_MSG_TALK_TYPE_REPLIES:
  730. $sJoin = "LEFT JOIN `{$CNF['TABLE_MESSAGES']}` as `r` ON `r`.`{$CNF['FIELD_MESSAGE_ID']}` = `m`.`{$CNF['FIELD_MESSAGE_REPLY']}`";
  731. $sWhere = "AND `m`.`{$CNF['FIELD_MESSAGE_REPLY']}` <> 0 AND `r`.`{$CNF['FIELD_MESSAGE_AUTHOR']}`={$iProfileId}";
  732. }
  733. return [$sJoin, $sWhere, $sFields, $sGroupBy];
  734. }
  735. public function getUnreadMessages($iProfileId, $iLotId, $mixedLimit = 10)
  736. {
  737. $sWhere = "WHERE `{$this->CNF['FIELD_MESSAGE_FK']}` = :lot_id";
  738. $aWhere = array('lot_id' => (int) $iLotId);
  739. $aLotInfo = $this->getNewJots($iProfileId, $iLotId);
  740. if (empty($aLotInfo))
  741. return false;
  742. $sWhere .= " AND `{$this->CNF['FIELD_MESSAGE_ID']}` > :jot";
  743. $aWhere['jot'] = $aLotInfo[$this->CNF['FIELD_NEW_JOT']];
  744. $sLimit = '';
  745. if ($mixedLimit)
  746. $sLimit = "LIMIT " . (int) $mixedLimit;
  747. $sQuery = "SELECT * FROM `{$this->CNF['TABLE_MESSAGES']}`
  748. {$sWhere}
  749. ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}`
  750. {$sLimit}";
  751. return $this->getAll($sQuery, $aWhere);
  752. }
  753. public function getPrevJot($iLotId, $iStart)
  754. {
  755. $sWhere = "WHERE `{$this->CNF['FIELD_MESSAGE_FK']}` = :lot_id";
  756. $aWhere = array('lot_id' => (int) $iLotId);
  757. if ($iStart) {
  758. $sWhere .= " AND `{$this->CNF['FIELD_MESSAGE_ID']}` < :jot";
  759. $aWhere['jot'] = $iStart;
  760. }
  761. $sQuery = "SELECT `{$this->CNF['FIELD_MESSAGE_ID']}` FROM `{$this->CNF['TABLE_MESSAGES']}`
  762. {$sWhere}
  763. ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}` DESC
  764. LIMIT 1";
  765. return $this->getOne($sQuery, $aWhere);
  766. }
  767. public function getIntervalJotsCount($iLotId, $iJotId)
  768. {
  769. $sQuery = "SELECT COUNT(*)
  770. FROM `{$this->CNF['TABLE_MESSAGES']}`
  771. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}`=:lot_id
  772. AND `{$this->CNF['FIELD_MESSAGE_ADDED']}` > (UNIX_TIMESTAMP() - :interval)
  773. AND `{$this->CNF['FIELD_MESSAGE_ID']}` < :jot";
  774. return $this->getOne($sQuery, array('lot_id' => (int) $iLotId, 'interval' => $this->CNF['PARAM_MESSAGES_INTERVAL'] * 60, 'jot' => (int) $iJotId));
  775. }
  776. function getLotJotsCount($iLotId)
  777. {
  778. if (!$iLotId)
  779. return false;
  780. // find the user with most number of unread messages
  781. $iUnread = $this->getOne("SELECT `{$this->CNF['FIELD_NEW_UNREAD']}` FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  782. WHERE `{$this->CNF['FIELD_NEW_LOT']}`=:id
  783. ORDER BY `{$this->CNF['FIELD_NEW_UNREAD']}` DESC
  784. LIMIT 1", array('id' => $iLotId));
  785. $iTotal = $this->getOne("SELECT COUNT(*)
  786. FROM `{$this->CNF['TABLE_MESSAGES']}`
  787. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}`=:id
  788. ", array('id' => $iLotId));
  789. return array('unread' => $iUnread, 'read' => ($iTotal - $iUnread));
  790. }
  791. /**
  792. * Get lot id by jot id
  793. *@param int $iJotId jot id
  794. *@param boolean bIdOnly return id or array with info
  795. *@return mixed lot id or lot info in array
  796. */
  797. public function getLotByJotId($iJotId, $bIdOnly = true)
  798. {
  799. $iLotId = $this->getOne("SELECT `{$this->CNF['FIELD_MESSAGE_FK']}`
  800. FROM `{$this->CNF['TABLE_MESSAGES']}`
  801. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = :jot LIMIT 1", array('jot' => $iJotId));
  802. if (!$iLotId)
  803. return false;
  804. return $bIdOnly ? $iLotId : $this->getRow("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}`
  805. WHERE `{$this->CNF['FIELD_ID']}` = :lot LIMIT 1", array('lot' => $iLotId));
  806. }
  807. public function getLotByJotPairs(&$aJotsList)
  808. {
  809. $aJotsList = array_map('intval', $aJotsList);
  810. return !empty($aJotsList) ? $this->getAll("SELECT `{$this->CNF['FIELD_MESSAGE_FK']}`, `{$this->CNF['FIELD_MESSAGE_ID']}`
  811. FROM `{$this->CNF['TABLE_MESSAGES']}`
  812. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` IN (" . implode(',', $aJotsList) . ")") : false;
  813. }
  814. /**
  815. * Get lot id by parent id
  816. *@param int $iJotId jot id
  817. *@return mixed lot id or lot info in array
  818. */
  819. public function getLotByParentId($iParentId)
  820. {
  821. return $this->getRow("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}`
  822. WHERE `{$this->CNF['FIELD_PARENT_JOT']}`=:id LIMIT 1", array('id' => $iParentId));
  823. }
  824. /**
  825. * Get the latest posted jot(message)
  826. *@param int $iLotId lot id
  827. *@param int $iProfileId if not specified then just latest jot of any member
  828. *@param boolean $bNotTrash don't show trash message
  829. *@return array with jot info
  830. */
  831. public function getLatestJot($iLotId, $iProfileId = 0, $bNotTrash = true)
  832. {
  833. $sWhere = '';
  834. $aWhere['lot'] = $iLotId;
  835. if ($iProfileId) {
  836. $sWhere = " AND `{$this->CNF['FIELD_MESSAGE_AUTHOR']}` = :profile";
  837. $aWhere['profile'] = $iProfileId;
  838. }
  839. if ($bNotTrash)
  840. $sWhere .= " AND `{$this->CNF['FIELD_MESSAGE_TRASH']}` = 0";
  841. return $this->getRow("SELECT *
  842. FROM `{$this->CNF['TABLE_MESSAGES']}`
  843. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}` = :lot {$sWhere}
  844. ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}` DESC
  845. LIMIT 1", $aWhere);
  846. }
  847. public function getLatestJotsAuthors($iLotId, $iExcludeProfileId = 0, $iLimit = 3)
  848. {
  849. $sWhere = '';
  850. $aWhere = ['lot' => $iLotId, 'limit' => $iLimit];
  851. if ($iExcludeProfileId) {
  852. $sWhere = " AND `{$this->CNF['FIELD_MESSAGE_ID']}` != :profile";
  853. $aWhere['profile'] = (int) $iExcludeProfileId;
  854. }
  855. return $this->getPairs("SELECT `{$this->CNF['FIELD_MESSAGE_AUTHOR']}`, MAX(`{$this->CNF['FIELD_MESSAGE_ADDED']}`) as `{$this->CNF['FIELD_MESSAGE_ADDED']}`
  856. FROM `{$this->CNF['TABLE_MESSAGES']}`
  857. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}` = :lot {$sWhere}
  858. GROUP BY `{$this->CNF['FIELD_MESSAGE_AUTHOR']}`
  859. ORDER BY `{$this->CNF['FIELD_MESSAGE_ADDED']}` DESC
  860. LIMIT :limit", $this->CNF['FIELD_MESSAGE_ADDED'], $this->CNF['FIELD_MESSAGE_AUTHOR'], $aWhere);
  861. }
  862. /**
  863. * Get jot(message) by id
  864. *@param int $iJotId id
  865. *@return array with jot info
  866. */
  867. public function getJotById($iJotId)
  868. {
  869. $sQuery = $this->prepare("SELECT * FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = ?", $iJotId);
  870. return $this->getRow($sQuery);
  871. }
  872. /**
  873. * Get messages number between two messages
  874. * @param $iLotId
  875. * @param $iJotStart
  876. * @param $iJotEnd
  877. * @return array with jot info
  878. */
  879. public function getJotsNumber($iLotId, $iJotStart, $iJotEnd = 0)
  880. {
  881. $aWhere = array('id' => $iLotId, 'start' => $iJotStart);
  882. $sWhere = "`{$this->CNF['FIELD_MESSAGE_ID']}` > :start";
  883. if ($iJotEnd) {
  884. $sWhere = "`{$this->CNF['FIELD_MESSAGE_ID']}` BETWEEN :start AND :end";
  885. $aWhere['end'] = $iJotEnd;
  886. }
  887. return $this->getOne("SELECT COUNT(*) FROM `{$this->CNF['TABLE_MESSAGES']}`
  888. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}`=:id AND {$sWhere}
  889. ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}` ASC
  890. ", $aWhere);
  891. }
  892. /**
  893. * Get all pages with comments block
  894. *@return array list with pages
  895. */
  896. public function getPagesWithComments()
  897. {
  898. return $this->getPairs("SELECT * FROM `sys_objects_cmts`", 'Name', 'BaseUrl');
  899. }
  900. /**
  901. * Check if the page already contains messenger block
  902. *@param $sPage page name
  903. *@return boolean
  904. */
  905. public function isBlockAdded($sPage)
  906. {
  907. $sPage = bx_process_input($sPage);
  908. $sQuery = $this->prepare("SELECT COUNT(*) FROM `sys_pages_blocks` WHERE `object` = ? AND `title` = '_bx_messenger_page_block_title_messenger'", $sPage);
  909. return $this->getOne($sQuery) == 1;
  910. }
  911. /**
  912. * Add messenger block to the page
  913. *@param $sPage page name
  914. *@return affected rows
  915. */
  916. public function addMessengerBlock($sPage)
  917. {
  918. $sPage = bx_process_input($sPage);
  919. $aInfo = $this->findCommentsBlock($sPage);
  920. if (!empty($aInfo))
  921. return $this->query("INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`, `active`) VALUES
  922. (:page, :cell, 'bx_messenger', '_bx_messenger_page_block_title_messenger', 0, 2147483647, 'service', 'a:3:{s:6:\"module\";s:12:\"bx_messenger\";s:6:\"method\";s:19:\"get_block_messenger\";s:6:\"params\";a:1:{i:0;s:6:\"{type}\";}}', 0, 0, :order, 0)",
  923. array('page' => $sPage, 'cell' => $aInfo['cell_id'], 'order' => $aInfo['order'] + 1)
  924. );
  925. return $this->query("INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`, `active`) VALUES
  926. (:page, 1, 'bx_messenger', '_bx_messenger_page_block_title_messenger', 0, 2147483647, 'service', 'a:3:{s:6:\"module\";s:12:\"bx_messenger\";s:6:\"method\";s:19:\"get_block_messenger\";s:6:\"params\";a:1:{i:0;s:6:\"{type}\";}}', 0, 0, 0, 0)",
  927. array('page' => $sPage)
  928. );
  929. }
  930. /**
  931. * Find comments block on the page
  932. *@param $sPage page name
  933. *@return array block info
  934. */
  935. private function findCommentsBlock($sPage)
  936. {
  937. $sPage = bx_process_input($sPage);
  938. $sQuery = $this->prepare("SELECT * FROM `sys_pages_blocks` WHERE `object` = ? AND `title` LIKE '%comments%'", $sPage);
  939. return $this->getRow($sQuery);
  940. }
  941. public function getUnreadJotsMessagesCount($iProfileId, $iLotId, $iParentId = 0)
  942. {
  943. if (!(int) $iLotId)
  944. return false;
  945. return $this->getNewJots($iProfileId, $iLotId, true);
  946. }
  947. function getLotsWithUnreadMessages($iProfileId)
  948. {
  949. if (!$iProfileId)
  950. return false;
  951. return $this->getPairs("SELECT `{$this->CNF['FIELD_NEW_UNREAD']}`, `{$this->CNF['FIELD_NEW_LOT']}`
  952. FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  953. WHERE `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile AND `{$this->CNF['FIELD_NEW_UNREAD']}` > 0
  954. ", $this->CNF['FIELD_NEW_LOT'], $this->CNF['FIELD_NEW_UNREAD'], array('profile' => $iProfileId));
  955. }
  956. function getNewJots($iProfileId, $iLotId, $bCount = false)
  957. {
  958. $aInfo = $this->getRow("SELECT *
  959. FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  960. WHERE `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile AND `{$this->CNF['FIELD_NEW_LOT']}`=:lot
  961. ", array('lot' => $iLotId, 'profile' => $iProfileId));
  962. if (empty($aInfo))
  963. return 0;
  964. return $bCount ? (int) $aInfo[$this->CNF['FIELD_NEW_UNREAD']] : $aInfo;
  965. }
  966. function getForWhomJotIsNew($iLotId, $iJotId)
  967. {
  968. if (!$iLotId && !$iJotId)
  969. return [];
  970. return $this->getColumn("SELECT `{$this->CNF['FIELD_NEW_PROFILE']}`
  971. FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  972. WHERE `{$this->CNF['FIELD_NEW_JOT']}` <=:jot AND `{$this->CNF['FIELD_NEW_LOT']}`=:lot
  973. ", array('jot' => $iJotId, 'lot' => $iLotId));
  974. }
  975. private function addNewJotItem($iProfileId, $iLotId, $iJotId)
  976. {
  977. if (!(int) $iProfileId)
  978. return false;
  979. $iJotNumber = 0;
  980. $iLastJot = $iJotId;
  981. $aJotInfo = $this->getNewJots($iProfileId, $iLotId);
  982. if (!empty($aJotInfo)) {
  983. $iJotNumber = (int) $aJotInfo[$this->CNF['FIELD_NEW_UNREAD']];
  984. $iLastJot = (int) $aJotInfo[$this->CNF['FIELD_NEW_JOT']];
  985. }
  986. return $this->query("REPLACE INTO `{$this->CNF['TABLE_NEW_MESSAGES']}`
  987. SET
  988. `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile,
  989. `{$this->CNF['FIELD_NEW_UNREAD']}`=:number,
  990. `{$this->CNF['FIELD_NEW_LOT']}`=:lot,
  991. `{$this->CNF['FIELD_NEW_JOT']}`=:jot
  992. ", array(
  993. 'profile' => $iProfileId,
  994. 'lot' => $iLotId,
  995. 'number' => $iJotNumber + 1,
  996. 'jot' => $iLastJot
  997. ));
  998. }
  999. private function addNewJotItems($aProfileIds, $iLotId, $iJotId)
  1000. {
  1001. $aProfileIds = array_values(
  1002. array_unique(
  1003. array_filter($aProfileIds, fn($iProfileId) => $iProfileId > 0)
  1004. )
  1005. );
  1006. if (empty($aProfileIds))
  1007. return false;
  1008. $bExecuted = false;
  1009. foreach (array_chunk($aProfileIds, 200) as $aChunk) {
  1010. $aValues = array_map(function ($iProfileId) use ($iLotId, $iJotId) {
  1011. return sprintf("(%d, %d, 1, %d)", (int) $iLotId, (int) $iJotId, (int) $iProfileId);
  1012. }, $aChunk);
  1013. $bExecuted |= (bool) $this->query("
  1014. INSERT INTO `{$this->CNF['TABLE_NEW_MESSAGES']}`
  1015. (`{$this->CNF['FIELD_NEW_LOT']}`, `{$this->CNF['FIELD_NEW_JOT']}`, `{$this->CNF['FIELD_NEW_UNREAD']}`, `{$this->CNF['FIELD_NEW_PROFILE']}`)
  1016. VALUES " . implode(',', $aValues) . "
  1017. ON DUPLICATE KEY UPDATE
  1018. `{$this->CNF['FIELD_NEW_UNREAD']}` = `{$this->CNF['FIELD_NEW_UNREAD']}` + 1,
  1019. `{$this->CNF['FIELD_NEW_JOT']}` = IF(
  1020. `{$this->CNF['FIELD_NEW_JOT']}` = 0 OR `{$this->CNF['FIELD_NEW_JOT']}` > VALUES(`{$this->CNF['FIELD_NEW_JOT']}`),
  1021. VALUES(`{$this->CNF['FIELD_NEW_JOT']}`),
  1022. `{$this->CNF['FIELD_NEW_JOT']}`
  1023. )
  1024. ");
  1025. }
  1026. return $bExecuted;
  1027. }
  1028. function markAsNewJot($mixedProfile, $iLotId, $iJotId, $bUpdateLot = true)
  1029. {
  1030. if (is_array($mixedProfile))
  1031. $this->addNewJotItems($mixedProfile, $iLotId, $iJotId);
  1032. elseif ((int) $mixedProfile)
  1033. $this->addNewJotItem($mixedProfile, $iLotId, $iJotId);
  1034. if (!$bUpdateLot)
  1035. return true;
  1036. return $this->query("UPDATE `{$this->CNF['TABLE_ENTRIES']}`
  1037. SET `{$this->CNF['FIELD_UPDATED']}` = UNIX_TIMESTAMP()
  1038. WHERE `{$this->CNF['FIELD_ID']}` = :id", array('id' => $iLotId));
  1039. }
  1040. function deleteNewJot($iProfileId, $iLotId = 0, $iJotId = 0)
  1041. {
  1042. if ($iJotId) {
  1043. $iLotId = $iLotId ? $iLotId : $this->getLotByJotId($iJotId);
  1044. $aNewJotInfo = $this->getNewJots($iProfileId, $iLotId);
  1045. if (empty($aNewJotInfo) || ((int) $aNewJotInfo[$this->CNF['FIELD_NEW_JOT']] > (int) $iJotId))
  1046. return false;
  1047. $iCount = (int) $this->getOne("SELECT COUNT(*) FROM `{$this->CNF['TABLE_MESSAGES']}`
  1048. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}`=:lot AND `{$this->CNF['FIELD_MESSAGE_ID']}` > :jot
  1049. ", array('lot' => $iLotId, 'jot' => $iJotId));
  1050. if ($iCount)
  1051. return $this->query("REPLACE INTO `{$this->CNF['TABLE_NEW_MESSAGES']}`
  1052. SET
  1053. `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile,
  1054. `{$this->CNF['FIELD_NEW_UNREAD']}`=:number,
  1055. `{$this->CNF['FIELD_NEW_JOT']}`=:jot,
  1056. `{$this->CNF['FIELD_NEW_LOT']}`=:lot
  1057. ", array(
  1058. 'profile' => $iProfileId,
  1059. 'lot' => $iLotId,
  1060. 'number' => $iCount,
  1061. 'jot' => $iJotId
  1062. ));
  1063. }
  1064. return $iLotId ?
  1065. $this->query("DELETE FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  1066. WHERE `{$this->CNF['FIELD_NEW_LOT']}`=:lot AND `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile
  1067. ", array('profile' => $iProfileId, 'lot' => $iLotId))
  1068. :
  1069. $this->query("DELETE FROM `{$this->CNF['TABLE_NEW_MESSAGES']}`
  1070. WHERE `{$this->CNF['FIELD_NEW_PROFILE']}`=:profile
  1071. ", array('profile' => $iProfileId));
  1072. }
  1073. public function searchMessage($sParam, $iProfileId = 0, $iLotId = 0)
  1074. {
  1075. $aResult = array();
  1076. if (!$sParam)
  1077. return $aResult;
  1078. $aParams = preg_split('/[\s]/', $sParam, -1, PREG_SPLIT_NO_EMPTY);
  1079. $sCriteria = implode('%', $aParams);
  1080. $aWhere = array('criteria' => "%{$sCriteria}%");
  1081. if ($iLotId) {
  1082. $sWhere = " AND `j`.`{$this->CNF['FIELD_MESSAGE_FK']}`=:id";
  1083. $aWhere['id'] = (int) $iLotId;
  1084. }
  1085. if ($iProfileId) {
  1086. $sWhere = " AND (`l`.`{$this->CNF['FIELD_PARTICIPANTS']}` REGEXP '(^|,){$iProfileId}(,|$)' OR `l`.`{$this->CNF['FIELD_AUTHOR']}`=:profile)";
  1087. $aWhere['profile'] = (int) $iProfileId;
  1088. }
  1089. return $this->getPairs("SELECT `j`.`{$this->CNF['FIELD_MESSAGE_ID']}`, `j`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  1090. FROM `{$this->CNF['TABLE_MESSAGES']}` as `j`
  1091. RIGHT JOIN `{$this->CNF['TABLE_ENTRIES']}` as `l` on `l`.`{$this->CNF['FIELD_ID']}` = `j`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  1092. WHERE `j`.`{$this->CNF['FIELD_MESSAGE']}` LIKE :criteria {$sWhere}", $this->CNF['FIELD_MESSAGE_ID'], $this->CNF['FIELD_MESSAGE_FK'], $aWhere);
  1093. }
  1094. function getMyTalksIdList($iProfileId)
  1095. {
  1096. if (!$iProfileId)
  1097. return [];
  1098. $sField = $this->CNF['FIELD_ID'];
  1099. $aList = $this->getMyLots($iProfileId);
  1100. return array_map(function ($aTalk) use ($sField) {
  1101. return $aTalk[$sField];
  1102. }, $aList);
  1103. }
  1104. /**
  1105. * Get all member's lots
  1106. *@param int $iProfileId
  1107. *@param array $aParams filter params
  1108. *@param array $aReturn may contain special values for search function
  1109. *@return array list of lots
  1110. */
  1111. public function getMyLots($iProfileId, $aParams = [], &$aReturn = [])
  1112. {
  1113. $sOrAddon = $sJoin = $sWhere = '';
  1114. $aSWhere = array();
  1115. $aWhere = array('profile' => (int) $iProfileId, 'parts' => '(^|,)' . (int) $iProfileId . '(,|$)');
  1116. // talks groups
  1117. if (isset($aParams['group']) && (int) $aParams['group']) {
  1118. $aSWhere[] = " `g`.`{$this->CNF['FMGL_GROUP_ID']}`=:group_id ";
  1119. $aWhere['group_id'] = (int) $aParams['group'];
  1120. $sOrAddon = " OR `l`.`{$this->CNF['FIELD_TYPE']}` = " . BX_IM_TYPE_PUBLIC;
  1121. }
  1122. //if threads
  1123. if (isset($aParams['threads']))
  1124. $aSWhere[] = " `l`.`{$this->CNF['FIELD_PARENT_JOT']}` !=0 ";
  1125. // Search criteria: the caller's (API) or the ones selected in the module settings.
  1126. $aCriteria = isset($aParams['search_criteria']) && is_array($aParams['search_criteria']) ? $aParams['search_criteria'] : null;
  1127. $fIsCriteria = function($sCriteria) use ($aCriteria) {
  1128. return $aCriteria !== null ? in_array($sCriteria, $aCriteria) : $this->_oConfig->isSearchCriteria($sCriteria);
  1129. };
  1130. $sParam = isset($aParams['term']) && $aParams['term'] ? $aParams['term'] : '';
  1131. if ($sParam) {
  1132. $aParamWhere = [];
  1133. if ($fIsCriteria(BX_SEARCH_CRITERIA_TITLES)) {
  1134. $aParamWhere[] = "`l`.`{$this->CNF['FIELD_TITLE']}` LIKE :title";
  1135. $aWhere['title'] = "%{$sParam}%";
  1136. }
  1137. if ($fIsCriteria(BX_SEARCH_CRITERIA_PARTS)) {
  1138. $aProfiles = BxDolService::call('system', 'profiles_search', array($sParam), 'TemplServiceProfiles');
  1139. if (!empty($aProfiles)) {
  1140. $aRegexp = array();
  1141. foreach ($aProfiles as &$aProfile) {
  1142. // Site: 'value' holds the profile id; API: profiles come as unit data with 'id'.
  1143. $iPartId = (int)(isset($aProfile['value']) ? $aProfile['value'] : (isset($aProfile['id']) ? $aProfile['id'] : 0));
  1144. if ($iPartId) {
  1145. $aRegexp[] = "(^|,){$iPartId}(,|$)";
  1146. }
  1147. }
  1148. if (!empty($aRegexp)) {
  1149. $aWhere['part_search'] = implode('|', $aRegexp);
  1150. $aParamWhere[] = "`{$this->CNF['FIELD_PARTICIPANTS']}` REGEXP :part_search";
  1151. }
  1152. }
  1153. }
  1154. if ($fIsCriteria(BX_SEARCH_CRITERIA_CONTENT)) {
  1155. $aSelectedLots = $this->searchMessage($sParam, $iProfileId);
  1156. if (!empty($aSelectedLots)) {
  1157. $aParamWhere[] = "`l`.`{$this->CNF['FIELD_ID']}` IN (" . implode(',', array_unique($aSelectedLots)) . ")";
  1158. $aReturn['jots_list'] = $aSelectedLots;
  1159. }
  1160. }
  1161. if (!empty($aParamWhere))
  1162. $aSWhere[] = '(' . implode(' OR ', $aParamWhere) . ')';
  1163. else
  1164. return false;
  1165. }
  1166. if (isset($aParams['type']) && $aParams['type']) {
  1167. if (is_numeric($aParams['type'])) {
  1168. $aSWhere[] = " `l`.`{$this->CNF['FIELD_TYPE']}` = :type AND `l`.`{$this->CNF['FIELD_PARENT_JOT']}` = 0 ";
  1169. $aWhere['type'] = (int) $aParams['type'];
  1170. } else if (is_array($aParams['type'])) {
  1171. $aSWhere[] = " `l`.`{$this->CNF['FIELD_TYPE']}` IN (" . implode(',', $aParams['type']) . ") AND `l`.`{$this->CNF['FIELD_PARENT_JOT']}` = 0 ";
  1172. }
  1173. } else {
  1174. $sJoin .= "LEFT JOIN `{$this->CNF['TABLE_MASS_TRACKER']}` as `mt` ON `mt`.`{$this->CNF['FIELD_MASS_CONVO_ID']}` = `l`.`{$this->CNF['FIELD_ID']}` AND `mt`.`{$this->CNF['FIELD_MASS_USER_ID']}`=:profile";
  1175. $sOrAddon = " OR `mt`.`{$this->CNF['FIELD_MASS_USER_ID']}` IS NOT NULL";
  1176. }
  1177. $bStar = isset($aParams['star']) && $aParams['star'] === true;
  1178. if ($bStar) {
  1179. $sJoin .= " INNER JOIN `{$this->CNF['TABLE_USERS_INFO']}` as `u` ON `u`.`{$this->CNF['FIELD_INFO_LOT_ID']}` = `l`.`{$this->CNF['FIELD_ID']}` AND `u`.`{$this->CNF['FIELD_INFO_USER_ID']}`=:profile";
  1180. $aSWhere[] = "`u`.`{$this->CNF['FIELD_INFO_STAR']}` = 1";
  1181. }
  1182. if (isset($aParams['visibility'])) {
  1183. if ($aParams['visibility'] !== BX_MSG_VISIBILITY_ALL) {
  1184. $aWhere['visibility'] = $aParams['visibility'];
  1185. $aSWhere[] = " `l`.`{$this->CNF['FIELD_VISIBILITY']}` = :visibility";
  1186. }
  1187. } else {
  1188. $aSWhere[] = " `l`.`{$this->CNF['FIELD_VISIBILITY']}` = :visibility";
  1189. $aWhere['visibility'] = BX_MSG_VISIBILITY_VISIBLE;
  1190. }
  1191. $sFields = $sHaving = '';
  1192. $iLastLot = isset($aParams['last_lot']) ? (int) $aParams['last_lot'] : 0;
  1193. if ($iLastLot) {
  1194. $aWhere['last_lot'] = $iLastLot;
  1195. $aSWhere[] = "`l`.`{$this->CNF['FIELD_ID']}` < :last_lot";
  1196. }
  1197. $iLot = isset($aParams['lot']) && (int) $aParams['lot'] ? (int) $aParams['lot'] : 0;
  1198. if ($iLot) {
  1199. $aWhere['lot'] = $iLot;
  1200. $aSWhere[] = "`l`.`{$this->CNF['FIELD_ID']}` = :lot";
  1201. }
  1202. if (!empty($aSWhere))
  1203. $sWhere = ' AND ' . implode(' AND ', $aSWhere);
  1204. $aWhere['start'] = isset($aParams['start']) ? (int) $aParams['start'] : 0;
  1205. $aWhere['per_page'] = isset($aParams['per_page']) ? (int) $aParams['per_page'] : (int) $this->CNF['MAX_LOTS_NUMBER'];
  1206. $sLimit = "LIMIT :start, :per_page";
  1207. $bShowLeft = isset($aParams['left']);
  1208. $sLeft = "";
  1209. if ($bShowLeft)
  1210. $sLeft = "SQL_CALC_FOUND_ROWS";
  1211. $aResult = $this->getAll("SELECT
  1212. {$sLeft}
  1213. {$sFields}
  1214. `l`.*,
  1215. IF (`g`.`{$this->CNF['FMGL_GROUP_ID']}` IS NOT NULL, `g`.`{$this->CNF['FMGL_GROUP_ID']}`, 0) as `{$this->CNF['FMGL_GROUP_ID']}`,
  1216. IF (`l`.`{$this->CNF['FIELD_UPDATED']}` = 0, `l`.`{$this->CNF['FIELD_ADDED']}`, `l`.`{$this->CNF['FIELD_UPDATED']}`) as `order`
  1217. FROM `{$this->CNF['TABLE_ENTRIES']}` as `l`
  1218. LEFT JOIN `{$this->CNF['TABLE_GROUPS_LOTS']}` as `g` ON `g`.`{$this->CNF['FMGL_LOT_ID']}` = `l`.`{$this->CNF['FIELD_ID']}`
  1219. {$sJoin}
  1220. WHERE (`l`.`{$this->CNF['FIELD_PARTICIPANTS']}` REGEXP :parts OR `l`.`{$this->CNF['FIELD_AUTHOR']}`=:profile {$sOrAddon}) {$sWhere}
  1221. {$sHaving}
  1222. ORDER BY `order` DESC
  1223. {$sLimit}", $aWhere);
  1224. if ($bShowLeft)
  1225. $aReturn['left'] = (int) $this->getOne("SELECT FOUND_ROWS()") - $aWhere['start'];
  1226. return $aResult;
  1227. }
  1228. /**
  1229. * Check if the title of the lot type must contain link
  1230. *@param int $iType
  1231. *@return boolean
  1232. */
  1233. public function isLinkedTitle($iType)
  1234. {
  1235. $sQuery = $this->prepare("SELECT `{$this->CNF['FIELD_TYPE_LINKED']}` FROM `{$this->CNF['TABLE_TYPES']}` WHERE `{$this->CNF['FIELD_TYPE_ID']}` = ? LIMIT 1", $iType);
  1236. return (int) $this->getOne($sQuery) == 1;
  1237. }
  1238. /**
  1239. * Get time when member was online
  1240. *@param int $iProfileId
  1241. *@return boolean
  1242. */
  1243. public function lastOnline($iProfileId)
  1244. {
  1245. $sSql = $this->prepare("SELECT
  1246. IF (`ts`.`date` != '', `ts`.`date`, `ta`.`logged`) as `logged`
  1247. FROM `sys_profiles` AS `tp`
  1248. INNER JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id`
  1249. LEFT JOIN `sys_sessions` AS `ts` ON `tp`.`account_id`=`ts`.`user_id`
  1250. WHERE
  1251. `tp`.`id` = ? AND
  1252. `ta`.`profile_id`=`tp`.`id`
  1253. LIMIT 1", $iProfileId);
  1254. return $this->getOne($sSql);
  1255. }
  1256. /**
  1257. * Delete all profiles info from lots and jots
  1258. *@param int $iProfileId
  1259. *@param bool $bTalks if true to remove the talk where removed user participates
  1260. *@return int affected rows
  1261. */
  1262. public function deleteProfileInfo($iProfileId, $bTalks = false)
  1263. {
  1264. $bResult = true;
  1265. $aWhere['profile'] = (int) $iProfileId;
  1266. $bResult &= $this->query("DELETE
  1267. FROM `{$this->CNF['TABLE_ENTRIES']}`
  1268. WHERE `{$this->CNF['FIELD_AUTHOR']}`=:profile", $aWhere);
  1269. $aJots = $this->getAll("SELECT *
  1270. FROM `{$this->CNF['TABLE_MESSAGES']}`
  1271. WHERE `{$this->CNF['FIELD_MESSAGE_AUTHOR']}`=:profile", $aWhere);
  1272. foreach ($aJots as &$aJot)
  1273. $this->clearJotsConnections($aJot[$this->CNF['FIELD_MESSAGE_ID']], $aJot[$this->CNF['FIELD_MESSAGE_FK']]);
  1274. $bResult &= $this->query("DELETE
  1275. FROM `{$this->CNF['TABLE_MESSAGES']}`
  1276. WHERE `{$this->CNF['FIELD_MESSAGE_AUTHOR']}`=:profile", $aWhere);
  1277. $this->query("DELETE FROM `{$this->CNF['TABLE_MASS_TRACKER']}` WHERE `{$this->CNF['FIELD_MASS_USER_ID']}` =:profile_id", ['profile_id' => $iProfileId]);
  1278. if ($bTalks)
  1279. $bResult &= (bool) $this->query("DELETE
  1280. FROM `{$this->CNF['TABLE_ENTRIES']}`
  1281. WHERE FIND_IN_SET(:profile, `{$this->CNF['FIELD_PARTICIPANTS']}`) AND `type`=:type", array_merge($aWhere, ['type' => BX_IM_TYPE_PRIVATE]));
  1282. $aLots = $this->getAll("SELECT *
  1283. FROM `{$this->CNF['TABLE_ENTRIES']}`
  1284. WHERE FIND_IN_SET(:profile, `{$this->CNF['FIELD_PARTICIPANTS']}`)", $aWhere);
  1285. if (empty($aLots))
  1286. return $bResult;
  1287. foreach ($aLots as &$aLot) {
  1288. $bResult &= $this->removeParticipant($aLot[$this->CNF['FIELD_ID']], $iProfileId);
  1289. }
  1290. return $bResult;
  1291. }
  1292. /**
  1293. * Add attachment to the jot
  1294. *@param int $iJotId jot id
  1295. *@param text mixedContent attachment content
  1296. *@param int sType attachment type
  1297. *@return int affected rows
  1298. */
  1299. public function addAttachment($iJotId, $aAttachments, $mixedType = false)
  1300. {
  1301. $iJotId = (int) $iJotId;
  1302. if (!$iJotId || !($aJotInfo = $this->getJotById($iJotId)) || empty($aAttachments))
  1303. return false;
  1304. if ($mixedType !== false) {
  1305. if (empty($aJotInfo[$this->CNF['FIELD_MESSAGE_AT']]))
  1306. $aAttachments = array($mixedType => $aAttachments);
  1307. else
  1308. $aAttachments = @unserialize($aJotInfo[$this->CNF['FIELD_MESSAGE_AT']]) + array($mixedType => $aAttachments);
  1309. }
  1310. $sQuery = $this->prepare("UPDATE `{$this->CNF['TABLE_MESSAGES']}`
  1311. SET
  1312. `{$this->CNF['FIELD_MESSAGE_AT']}` = ?
  1313. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = ?", @serialize($aAttachments), $iJotId);
  1314. return $this->query($sQuery);
  1315. }
  1316. /**
  1317. * Add attachment to the jot
  1318. *@param int $iJotId jot id
  1319. *@param int $iProfileId profile id
  1320. *@param string $sMessage
  1321. *@return int affected rows
  1322. */
  1323. public function editJot($iJotId, $iProfileId, $sMessage)
  1324. {
  1325. $iJotId = (int) $iJotId;
  1326. $aJotInfo = array();
  1327. if (!$iJotId || !($aJotInfo = $this->getJotById($iJotId)) || !$sMessage)
  1328. return false;
  1329. $sWhere = '';
  1330. if ($aJotInfo[$this->CNF['FIELD_MESSAGE_AT_TYPE']] == BX_ATT_TYPE_REPOST)
  1331. $sWhere = ",`{$this->CNF['FIELD_MESSAGE_AT_TYPE']}` = '', `{$this->CNF['FIELD_MESSAGE_AT']}` = ''";
  1332. $sMessage = clear_xss($sMessage);
  1333. $sQuery = $this->prepare("UPDATE `{$this->CNF['TABLE_MESSAGES']}`
  1334. SET `{$this->CNF['FIELD_MESSAGE']}` = ?,
  1335. `{$this->CNF['FIELD_MESSAGE_LAST_EDIT']}` = UNIX_TIMESTAMP(),
  1336. `{$this->CNF['FIELD_MESSAGE_EDIT_BY']}` = ?
  1337. {$sWhere}
  1338. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = ?", $sMessage, $iProfileId, $iJotId);
  1339. return $this->query($sQuery);
  1340. }
  1341. /**
  1342. * Check if the Jot already has attachment
  1343. *@param int $iJotId jot id
  1344. *@param string $sType attachment type
  1345. *@return int original attachment Id
  1346. */
  1347. public function hasAttachment($iJotId, $sType = BX_ATT_TYPE_REPOST)
  1348. {
  1349. $aValues = $this->getRow("SELECT
  1350. `{$this->CNF['FIELD_MESSAGE_AT']}`,
  1351. `{$this->CNF['FIELD_MESSAGE_AT_TYPE']}`
  1352. FROM `{$this->CNF['TABLE_MESSAGES']}`
  1353. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = :id", array('id' => $iJotId));
  1354. if (!isset($aValues[$this->CNF['FIELD_MESSAGE_AT']]))
  1355. return false;
  1356. if ($aValues[$this->CNF['FIELD_MESSAGE_AT_TYPE']]) {
  1357. if ($aValues[$this->CNF['FIELD_MESSAGE_AT_TYPE']] == $sType && (int) $aValues[$this->CNF['FIELD_MESSAGE_AT']] && $aValues[$this->CNF['FIELD_MESSAGE_AT']] !== $iJotId)
  1358. return (int) $aValues[$this->CNF['FIELD_MESSAGE_AT']];
  1359. return false;
  1360. }
  1361. $mixedResult = @unserialize($aValues[$this->CNF['FIELD_MESSAGE_AT']]);
  1362. if (is_array($mixedResult)) {
  1363. if (isset($mixedResult[$sType]) && (int) $mixedResult[$sType] && (int) $mixedResult[$sType] != $iJotId)
  1364. return (int) $mixedResult[$sType];
  1365. }
  1366. return false;
  1367. }
  1368. public function updateFiles($iJotId, $mixedValues)
  1369. {
  1370. $sQuery = $this->prepare("UPDATE `{$this->CNF['OBJECT_STORAGE']}` SET " . $this->arrayToSQL($mixedValues) . " WHERE `{$this->CNF['FIELD_ST_ID']}` = ?", $iJotId);
  1371. return $this->query($sQuery);
  1372. }
  1373. public function getJotFiles($iJot, $bCount = false, $iProfileId = 0)
  1374. {
  1375. $sProfileWhere = '';
  1376. if ((int) $iProfileId)
  1377. $sProfileWhere = "AND `t`.`{$this->CNF['FJMT_USER_ID']}`=" . (int) $iProfileId;
  1378. return !$bCount ?
  1379. $this->getAll("SELECT `f`.*, IF (`t`.`{$this->CNF['FJMT_COLLAPSED']}` IS NULL, 0, 1) as `{$this->CNF['FJMT_COLLAPSED']}`
  1380. FROM `{$this->CNF['OBJECT_STORAGE']}` as `f`
  1381. LEFT JOIN `{$this->CNF['TABLE_JOTS_MEDIA_TRACKER']}` as `t` ON `f`.`{$this->CNF['FIELD_ST_ID']}`=`t`.`{$this->CNF['FJMT_FILE_ID']}` {$sProfileWhere}
  1382. WHERE `{$this->CNF['FIELD_ST_JOT']}` = :id", array('id' => $iJot)) :
  1383. $this->getOne("SELECT COUNT(*) FROM `{$this->CNF['OBJECT_STORAGE']}` WHERE `{$this->CNF['FIELD_ST_JOT']}` = :id", array('id' => $iJot));
  1384. }
  1385. private function removeFilesByJotId($iJotId)
  1386. {
  1387. $aFiles = $this->getJotFiles($iJotId);
  1388. if (empty($aFiles))
  1389. return false;
  1390. $oStorage = BxDolStorage::getObjectInstance($this->CNF['OBJECT_STORAGE']);
  1391. $bResult = true;
  1392. foreach ($aFiles as &$aFile) {
  1393. $bResult &= $oStorage->deleteFile($aFile[$this->CNF['FIELD_ST_ID']], $aFile[$this->CNF['FIELD_ST_AUTHOR']]);
  1394. $this->removeMediaTracker($aFile[$this->CNF['FIELD_ST_ID']]);
  1395. }
  1396. return $bResult;
  1397. }
  1398. public function removeFileFromJot($iJotId, $iFileId)
  1399. {
  1400. $aJotInfo = $this->getJotById($iJotId);
  1401. $aAttachment = $aFiles = [];
  1402. if ($aJotInfo[$this->CNF['FIELD_MESSAGE_AT_TYPE']] === BX_ATT_TYPE_FILES) {
  1403. $aFiles = explode(',', $aJotInfo[$this->CNF['FIELD_MESSAGE_AT']]);
  1404. } else
  1405. if (!$aJotInfo[$this->CNF['FIELD_MESSAGE_AT_TYPE']] && isset($aJotInfo[$this->CNF['FIELD_MESSAGE_AT']])) {
  1406. $aAttachment = @unserialize($aJotInfo[$this->CNF['FIELD_MESSAGE_AT']]);
  1407. if (isset($aAttachment[BX_ATT_TYPE_FILES])) {
  1408. $mixedFiles = $aAttachment[BX_ATT_TYPE_FILES];
  1409. if (is_string($mixedFiles))
  1410. $aFiles = explode(',', $mixedFiles);
  1411. else if (is_array($mixedFiles))
  1412. $aFiles = $mixedFiles;
  1413. } else
  1414. return false;
  1415. }
  1416. $oStorage = BxDolStorage::getObjectInstance($this->CNF['OBJECT_STORAGE']);
  1417. $aFile = $oStorage->getFile($iFileId);
  1418. $sFileName = $aFile[$this->CNF['FIELD_ST_NAME']];
  1419. if (!empty($aFiles))
  1420. $aFiles = array_filter($aFiles, function ($sValue) use ($sFileName) {
  1421. return $sValue !== $sFileName;
  1422. });
  1423. else
  1424. return false;
  1425. $aAttachment[BX_ATT_TYPE_FILES] = $aFiles;
  1426. $sQuery = $this->prepare("UPDATE `{$this->CNF['TABLE_MESSAGES']}`
  1427. SET
  1428. `{$this->CNF['FIELD_MESSAGE_AT_TYPE']}` = '',
  1429. `{$this->CNF['FIELD_MESSAGE_AT']}` = ?
  1430. WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = ?", @serialize($aAttachment), $iJotId);
  1431. return $this->query($sQuery);
  1432. }
  1433. public function isFileVendor($iFileId, $iProfileId)
  1434. {
  1435. $oStorage = BxDolStorage::getObjectInstance($this->CNF['OBJECT_STORAGE']);
  1436. $aFile = $oStorage->getFile($iFileId);
  1437. return $aFile[$this->CNF['FIELD_ST_AUTHOR']] == $iProfileId;
  1438. }
  1439. public function isEmptyJotMessage($iJotId)
  1440. {
  1441. $aJotInfo = $this->getJotById($iJotId);
  1442. return empty($aJotInfo) || !$aJotInfo['FIELD_MESSAGE'];
  1443. }
  1444. public function getFirstUnreadJot($iProfileId, $iLotId)
  1445. {
  1446. if (!$iLotId)
  1447. return 0;
  1448. $aUnreadJots = $this->getNewJots($iProfileId, $iLotId);
  1449. return !empty($aUnreadJots) ? (int) $aUnreadJots[$this->CNF['FIELD_NEW_JOT']] : 0;
  1450. }
  1451. /**
  1452. * @param int $iObjectId item's object ID
  1453. * @param string $sType module's name from sys_modules
  1454. * @param int $iProfileId comments' author
  1455. * @param int $iStart get comments from position
  1456. * @param int $iPerPage number of the comments to get at once
  1457. * @return array list of the comments
  1458. *
  1459. */
  1460. public function getLiveComments($iObjectId, $sType, $iProfileId, $iStart = 0, $iPerPage = 0)
  1461. {
  1462. $aWhere = array('object' => $iObjectId, 'type' => $sType);
  1463. $sLimit = $sAuthor = '';
  1464. if ((int) $iProfileId) {
  1465. $aWhere['author'] = (int) $iProfileId;
  1466. $sAuthor = "AND `{$this->CNF['FIELD_LCMTS_AUTHOR']}`=:author";
  1467. }
  1468. if ($iPerPage) {
  1469. $aWhere['start'] = (int) $iStart;
  1470. $aWhere['per_page'] = (int) $iPerPage;
  1471. $sLimit = "LIMIT :start, :per_page";
  1472. }
  1473. $aComments = $this->getAll(
  1474. "SELECT
  1475. SQL_CALC_FOUND_ROWS
  1476. `{$this->CNF['FIELD_LCMTS_ID']}`,
  1477. `{$this->CNF['FIELD_LCMTS_TEXT']}`,
  1478. `{$this->CNF['FIELD_LCMTS_AUTHOR']}`,
  1479. `{$this->CNF['FIELD_LCMTS_DATE']}`,
  1480. `{$this->CNF['FIELD_LCMTS_OBJECT_ID']}`
  1481. FROM `{$this->CNF['TABLE_LIVE_COMMENTS']}` as `c`
  1482. LEFT JOIN `{$this->CNF['TABLE_CMTS_OBJECTS']}` as `s` ON `s`.`{$this->CNF['FIELD_COBJ_ID']}` = `c`.`{$this->CNF['FIELD_LCMTS_SYS_ID']}`
  1483. WHERE `s`.`{$this->CNF['FIELD_COBJ_MODULE']}` = :type AND `{$this->CNF['FIELD_LCMTS_OBJECT_ID']}` = :object {$sAuthor}
  1484. ORDER BY `{$this->CNF['FIELD_LCMTS_ID']}` DESC
  1485. {$sLimit}",
  1486. $aWhere
  1487. );
  1488. return array('result' => $aComments, 'total' => (int) $this->getOne("SELECT FOUND_ROWS()"));
  1489. }
  1490. /**
  1491. * @param string $sText message body
  1492. * @param int $iObjectId item's object ID
  1493. * @param string $sName module's name from sys_modules
  1494. * @param int $iProfileId comments' author
  1495. * @param int $iDate comments' time
  1496. * @return mixed last added comments id or false
  1497. *
  1498. */
  1499. public function addLiveComment($sText, $iObjectId, $sName, $iProfileId, $iDate = 0)
  1500. {
  1501. $iSystem = $this->getOne("SELECT `{$this->CNF['FIELD_COBJ_ID']}`
  1502. FROM `{$this->CNF['TABLE_CMTS_OBJECTS']}`
  1503. WHERE `{$this->CNF['FIELD_COBJ_MODULE']}`=:name LIMIT 1", array('name' => $sName));
  1504. if (!$iSystem)
  1505. return false;
  1506. $sQuery = $this->prepare("REPLACE INTO `{$this->CNF['TABLE_LIVE_COMMENTS']}`
  1507. SET
  1508. `{$this->CNF['FIELD_LCMTS_TEXT']}`=?,
  1509. `{$this->CNF['FIELD_LCMTS_AUTHOR']}`=?,
  1510. `{$this->CNF['FIELD_LCMTS_DATE']}`=?,
  1511. `{$this->CNF['FIELD_LCMTS_OBJECT_ID']}`=?,
  1512. `{$this->CNF['FIELD_LCMTS_SYS_ID']}`=?
  1513. ", $sText, $iProfileId, $iDate ? $iDate : time(), $iObjectId, $iSystem);
  1514. return $this->query($sQuery) ? $this->lastId() : false;
  1515. }
  1516. public function removeLiveComment($iObjectId, $iProfileId)
  1517. {
  1518. return $this->query("DELETE FROM `{$this->CNF['TABLE_LIVE_COMMENTS']}`
  1519. WHERE `{$this->CNF['FIELD_LCMTS_AUTHOR']}`=:author AND `{$this->CNF['FIELD_LCMTS_ID']}`=:object_id", array('author' => $iProfileId, 'object_id' => $iObjectId));
  1520. }
  1521. public function getLotFiles($iLotId, $iStart = 0, $iPerPage = 0)
  1522. {
  1523. $aWhere = array('id' => $iLotId);
  1524. $sLimit = '';
  1525. if ($iPerPage) {
  1526. $aWhere['start'] = (int) $iStart;
  1527. $aWhere['per_page'] = (int) $iPerPage;
  1528. $sLimit = "LIMIT :start, :per_page";
  1529. }
  1530. return $this->getAll("SELECT `s`.*
  1531. FROM `{$this->CNF['OBJECT_STORAGE']}` as `s`
  1532. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `j` ON `s`.`{$this->CNF['FIELD_ST_JOT']}` = `j`.`{$this->CNF['FIELD_MESSAGE_ID']}`
  1533. LEFT JOIN `{$this->CNF['TABLE_ENTRIES']}` as `l` ON `l`.`{$this->CNF['FIELD_ID']}` = `j`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  1534. WHERE `l`.`{$this->CNF['FIELD_ID']}` = :id
  1535. ORDER BY `s`.`{$this->CNF['FIELD_ST_ADDED']}` DESC
  1536. {$sLimit}
  1537. ", $aWhere);
  1538. }
  1539. public function getLotFilesCount($iLot)
  1540. {
  1541. return (int) $this->getOne("SELECT COUNT(*)
  1542. FROM `{$this->CNF['OBJECT_STORAGE']}` as `s`
  1543. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `j` ON `s`.`{$this->CNF['FIELD_ST_JOT']}` = `j`.`{$this->CNF['FIELD_MESSAGE_ID']}`
  1544. LEFT JOIN `{$this->CNF['TABLE_ENTRIES']}` as `l` ON `l`.`{$this->CNF['FIELD_ID']}` = `j`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  1545. WHERE `l`.`{$this->CNF['FIELD_ID']}` = :id
  1546. ORDER BY `s`.`{$this->CNF['FIELD_ST_ADDED']}` DESC
  1547. ", array('id' => $iLot));
  1548. }
  1549. public function getSentNtfsNumber($iProfileId, $iLotId)
  1550. {
  1551. $iInterval = (int) $this->CNF['PARAM_NTFS_INTERVAL'];
  1552. return $this->getOne("SELECT COUNT(*)
  1553. FROM `bx_notifications_events`
  1554. WHERE `action`='got_jot_ntfs'
  1555. AND `type`=:type
  1556. AND `object_owner_id`=:profile
  1557. AND `object_id`=:lot_id
  1558. AND `date` > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL :interval HOUR))",
  1559. array(
  1560. 'type' => $this->_oConfig->getName(),
  1561. 'profile' => $iProfileId,
  1562. 'lot_id' => $iLotId,
  1563. 'interval' => $iInterval
  1564. )
  1565. );
  1566. }
  1567. /**
  1568. * @param int $iJotId id of the message
  1569. * @param int $iProfileId viewer id
  1570. * @param int $iJotAuthor message's author
  1571. * @param int $iLotAuthorId author id
  1572. * @return bool
  1573. */
  1574. public function isAllowedToDeleteJot($iJotId, $iProfileId = 0, $iJotAuthor = 0, $iLotAuthorId = 0)
  1575. {
  1576. if (!$iJotId)
  1577. return true;
  1578. if (!($aJot = $this->getJotById($iJotId)))
  1579. return false;
  1580. if (!$iProfileId)
  1581. $iProfileId = bx_get_logged_profile_id();
  1582. $mixedResult = $this->_oConfig->isAllowedAction(BX_MSG_ACTION_DELETE_MESSAGES, $iProfileId);
  1583. if ($mixedResult === true)
  1584. return true;
  1585. if (!$iJotAuthor)
  1586. $iJotAuthor = $aJot[$this->CNF['FIELD_MESSAGE_AUTHOR']];
  1587. if (!$iLotAuthorId) {
  1588. $iLotId = $aJot[$this->CNF['FIELD_MESSAGE_FK']];
  1589. $bIsLotAuthor = $this->isAuthor($iLotId, $iProfileId);
  1590. } else
  1591. $bIsLotAuthor = $iLotAuthorId == $iProfileId;
  1592. return ($this->CNF['ALLOW_TO_REMOVE_MESSAGE'] && $iJotAuthor == $iProfileId) || ($this->CNF['ALLOW_TO_MODERATE_MESSAGE_FOR_AUTHORS'] && $bIsLotAuthor);
  1593. }
  1594. public function isAllowedToEditJot($iJotId, $iProfileId)
  1595. {
  1596. if (!$iJotId || !($aJot = $this->getJotById($iJotId)))
  1597. return false;
  1598. $mixedResult = $this->_oConfig->isAllowedAction(BX_MSG_ACTION_EDIT_MESSAGES, $iProfileId);
  1599. if ($mixedResult === true)
  1600. return true;
  1601. $iJotAuthor = $aJot[$this->CNF['FIELD_MESSAGE_AUTHOR']];
  1602. $iLotId = $aJot[$this->CNF['FIELD_MESSAGE_FK']];
  1603. $bIsLotAuthor = $this->isAuthor($iLotId, $iProfileId);
  1604. return ($this->CNF['ALLOW_TO_REMOVE_MESSAGE'] && +$iJotAuthor === +$iProfileId) || ($this->CNF['ALLOW_TO_MODERATE_MESSAGE_FOR_AUTHORS'] && $bIsLotAuthor);
  1605. }
  1606. function createJVC($iLotId, $iProfileId)
  1607. {
  1608. $aJVC = $this->getJVC($iLotId);
  1609. $aOpened = array();
  1610. if (empty($aJVC)) {
  1611. $aLotInfo = $this->getLotInfoById($iLotId);
  1612. $sRoom = $this->_oConfig->getRoomId($aLotInfo[$this->CNF['FIELD_ID']], $aLotInfo[$this->CNF['FIELD_AUTHOR']]);
  1613. $this->query(
  1614. "INSERT INTO `{$this->CNF['TABLE_JVC']}`
  1615. SET
  1616. `{$this->CNF['FJVC_ROOM']}`=:room,
  1617. `{$this->CNF['FJVC_LOT_ID']}`=:lot_id,
  1618. `{$this->CNF['FJVC_NUMBER']}`=1
  1619. ",
  1620. array(
  1621. 'room' => $sRoom,
  1622. 'lot_id' => $iLotId
  1623. )
  1624. );
  1625. $iJVCId = $this->lastId();
  1626. } else {
  1627. $iJVCId = $aJVC[$this->CNF['FJVC_ID']];
  1628. $aOpened = $this->closeAllOpenedConversations($iJVCId);
  1629. $sRoom = $aJVC[$this->CNF['FJVC_ROOM']];
  1630. $this->query("UPDATE `{$this->CNF['TABLE_JVC']}`
  1631. SET `{$this->CNF['FJVC_NUMBER']}`= 1
  1632. WHERE `{$this->CNF['FJVC_LOT_ID']}`= :lot_id
  1633. ", array('lot_id' => $iLotId));
  1634. }
  1635. if ($iJVCId && ($iJVCItemId = $this->addJVCItem($iJVCId, $iProfileId))) {
  1636. $this->updateJVC($iLotId, $this->CNF['FJVC_ACTIVE'], $iJVCItemId);
  1637. $iJotId = $this->addJot($iLotId, '', $iProfileId);
  1638. $this->updateJot($iJotId, $this->CNF['FIELD_MESSAGE_VIDEOC'], $iJVCItemId);
  1639. }
  1640. return array('jitsi_id' => $iJVCId, 'jot_id' => $iJotId, $this->CNF['FJVC_ROOM'] => $sRoom, 'opened' => array_values($aOpened));
  1641. }
  1642. public function getJotIdByJitsiItem($iJitsiId)
  1643. {
  1644. $sQuery = $this->prepare("SELECT `{$this->CNF['FIELD_MESSAGE_ID']}`
  1645. FROM `{$this->CNF['TABLE_MESSAGES']}`
  1646. WHERE `{$this->CNF['FIELD_MESSAGE_VIDEOC']}` = ?
  1647. ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}` DESC
  1648. LIMIT 1", $iJitsiId);
  1649. return $this->getOne($sQuery);
  1650. }
  1651. function addJVCItem($iId, $iProfileId)
  1652. {
  1653. $this->query(
  1654. "INSERT INTO `{$this->CNF['TABLE_JVCT']}` SET
  1655. `{$this->CNF['FJVCT_AUTHOR_ID']}` = :author,
  1656. `{$this->CNF['FJVCT_FK']}`= :id,
  1657. `{$this->CNF['FJVCT_PART']}`= :part,
  1658. `{$this->CNF['FJVCT_JOINED']}`= :part,
  1659. `{$this->CNF['FJVCT_START']}` = UNIX_TIMESTAMP()
  1660. ",
  1661. array(
  1662. 'author' => $iProfileId,
  1663. 'id' => $iId,
  1664. 'part' => $iProfileId
  1665. )
  1666. );
  1667. return $this->lastId();
  1668. }
  1669. function closeAllOpenedConversations($iJVCId)
  1670. {
  1671. $aAllOpenedChats = $this->getPairs("SELECT `j`.`{$this->CNF['FIELD_MESSAGE_ID']}`, `v`.`{$this->CNF['FJVCT_ID']}` as `jot_id`
  1672. FROM `{$this->CNF['TABLE_JVCT']}` as `v`
  1673. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `j` ON `v`.`{$this->CNF['FJVCT_ID']}` = `j`.`{$this->CNF['FIELD_MESSAGE_VIDEOC']}`
  1674. WHERE `{$this->CNF['FJVCT_FK']}`= :id AND `{$this->CNF['FJVCT_END']}`= 0", 'jot_id', $this->CNF['FIELD_MESSAGE_ID'], array('id' => $iJVCId));
  1675. if (empty($aAllOpenedChats))
  1676. return array();
  1677. $this->query(
  1678. "UPDATE `{$this->CNF['TABLE_JVCT']}`
  1679. SET
  1680. `{$this->CNF['FJVCT_END']}`= UNIX_TIMESTAMP()
  1681. WHERE `{$this->CNF['FJVCT_FK']}`= :id AND `{$this->CNF['FJVCT_END']}`= 0",
  1682. array('id' => $iJVCId)
  1683. );
  1684. return $aAllOpenedChats;
  1685. }
  1686. function joinToActiveJVC($iLotId, $iProfileId, $bJoin = true)
  1687. {
  1688. $aItem = $this->getActiveJVCItem($iLotId);
  1689. if (empty($aItem))
  1690. return false;
  1691. $aParticipants = array();
  1692. if ($aItem[$this->CNF['FJVCT_PART']])
  1693. $aParticipants = explode(',', $aItem[$this->CNF['FJVCT_PART']]);
  1694. if (!in_array($iProfileId, $aParticipants))
  1695. $aParticipants[] = $iProfileId;
  1696. $aJoined = $aItem[$this->CNF['FJVCT_JOINED']] ? explode(',', $aItem[$this->CNF['FJVCT_JOINED']]) : array();
  1697. if (!in_array($iProfileId, $aJoined))
  1698. $aJoined[] = $iProfileId;
  1699. $this->updateJVCItem($aItem[$this->CNF['FJVCT_ID']], $this->CNF['FJVCT_PART'], implode(',', $aParticipants));
  1700. if ($bJoin)
  1701. $this->updateJVCItem($aItem[$this->CNF['FJVCT_ID']], $this->CNF['FJVCT_JOINED'], implode(',', $aJoined));
  1702. $this->updateJVC($iLotId, $this->CNF['FJVC_NUMBER'], count($aParticipants));
  1703. return true;
  1704. }
  1705. function updateJVC($iLotId, $sField, $mixedValue)
  1706. {
  1707. return $this->query(
  1708. "UPDATE `{$this->CNF['TABLE_JVC']}` SET
  1709. `{$sField}`=:value
  1710. WHERE `{$this->CNF['FJVC_LOT_ID']}`=:lot_id",
  1711. array(
  1712. 'lot_id' => $iLotId,
  1713. 'value' => $mixedValue
  1714. )
  1715. );
  1716. }
  1717. function leaveJVC($iLotId, $sField, $mixedValue)
  1718. {
  1719. return $this->query(
  1720. "UPDATE `{$this->CNF['TABLE_JVC']}` SET
  1721. `{$sField}`=:value
  1722. WHERE `{$this->CNF['FJVC_LOT_ID']}`=:lot_id",
  1723. array(
  1724. 'lot_id' => $iLotId,
  1725. 'value' => $mixedValue
  1726. )
  1727. );
  1728. }
  1729. function updateJVCItem($iId, $sField, $mixedValue)
  1730. {
  1731. return $this->query(
  1732. "UPDATE `{$this->CNF['TABLE_JVCT']}` SET
  1733. `{$sField}`=:value
  1734. WHERE `{$this->CNF['FJVC_ID']}`=:id",
  1735. array(
  1736. 'id' => $iId,
  1737. 'value' => $mixedValue
  1738. )
  1739. );
  1740. }
  1741. function closeJVC($iLotId)
  1742. {
  1743. $aJVC = $this->getJVC($iLotId);
  1744. if (empty($aJVC) || !(int) $aJVC[$this->CNF['FJVC_ACTIVE']])
  1745. return false;
  1746. $this->query(
  1747. "UPDATE `{$this->CNF['TABLE_JVCT']}`
  1748. SET
  1749. `{$this->CNF['FJVCT_JOINED']}`=:joined,
  1750. `{$this->CNF['FJVCT_END']}`= UNIX_TIMESTAMP()
  1751. WHERE `{$this->CNF['FJVCT_ID']}`= :id",
  1752. array(
  1753. 'id' => $aJVC[$this->CNF['FJVC_ACTIVE']],
  1754. 'joined' => '',
  1755. )
  1756. );
  1757. $this->updateJVC($iLotId, $this->CNF['FJVC_ACTIVE'], 0);
  1758. return $this->updateJVC($iLotId, $this->CNF['FJVC_NUMBER'], 0);
  1759. }
  1760. function stopJVC($iLotId, $iProfileId)
  1761. {
  1762. $aJVC = $this->getJVC($iLotId);
  1763. if (empty($aJVC) || !(int) $aJVC[$this->CNF['FJVC_ACTIVE']])
  1764. return false;
  1765. $aTrack = $this->getRow(
  1766. "SELECT * FROM `{$this->CNF['TABLE_JVCT']}`
  1767. WHERE `{$this->CNF['FJVCT_ID']}`= :id",
  1768. array(
  1769. 'id' => $aJVC[$this->CNF['FJVC_ACTIVE']]
  1770. )
  1771. );
  1772. $aJoined = explode(',', $aTrack[$this->CNF['FJVCT_JOINED']]);
  1773. if (in_array($iProfileId, $aJoined))
  1774. unset($aJoined[array_search($iProfileId, $aJoined)]);
  1775. else
  1776. $this->joinToActiveJVC($iLotId, $iProfileId, false);
  1777. $sEnd = '';
  1778. $iJoinedNumber = count($aJoined);
  1779. if (!$iJoinedNumber)
  1780. $sEnd = ",`{$this->CNF['FJVCT_END']}`= UNIX_TIMESTAMP()";
  1781. $this->query(
  1782. "UPDATE `{$this->CNF['TABLE_JVCT']}`
  1783. SET
  1784. `{$this->CNF['FJVCT_JOINED']}`=:joined
  1785. {$sEnd}
  1786. WHERE `{$this->CNF['FJVCT_ID']}`= :id",
  1787. array(
  1788. 'id' => $aJVC[$this->CNF['FJVC_ACTIVE']],
  1789. 'joined' => implode(',', $aJoined),
  1790. )
  1791. );
  1792. if (!$iJoinedNumber)
  1793. $this->updateJVC($iLotId, $this->CNF['FJVC_ACTIVE'], 0);
  1794. return $this->updateJVC($iLotId, $this->CNF['FJVC_NUMBER'], $iJoinedNumber);
  1795. }
  1796. function getJVC($iLotId)
  1797. {
  1798. return $this->getRow(
  1799. "SELECT * FROM `{$this->CNF['TABLE_JVC']}`
  1800. WHERE `{$this->CNF['FJVC_LOT_ID']}`= :lot_id",
  1801. array('lot_id' => $iLotId)
  1802. );
  1803. }
  1804. function getJVCItem($iId)
  1805. {
  1806. return $this->getRow(
  1807. "SELECT *
  1808. FROM `{$this->CNF['TABLE_JVCT']}`
  1809. WHERE `{$this->CNF['FJVCT_ID']}`= :id",
  1810. array('id' => $iId)
  1811. );
  1812. }
  1813. function getActiveJVCItem($iLotId, $sFiled = '')
  1814. {
  1815. $aJVC = $this->getJVC($iLotId);
  1816. if (empty($aJVC) || !(int) $aJVC[$this->CNF['FJVC_ACTIVE']])
  1817. return false;
  1818. $aInfo = $this->getJVCItem($aJVC[$this->CNF['FJVC_ACTIVE']]);
  1819. if ($sFiled)
  1820. return isset($aInfo[$sFiled]) ? $aInfo[$sFiled] : false;
  1821. return $aInfo;
  1822. }
  1823. /*********************** REACT JOT Integration part *****************/
  1824. /**
  1825. * Returns installed list of modules with comments ability
  1826. * @param string $sModule
  1827. * @return array
  1828. */
  1829. function getAllCmtsModule($sModule = '')
  1830. {
  1831. return $this->getAllWithKey("SELECT
  1832. `c`.`Module` as `module`,
  1833. `TriggerTable` as `table`,
  1834. `TriggerFieldId` as `id`,
  1835. `TriggerFieldAuthor` as `owner`,
  1836. `TriggerFieldTitle` as `title`,
  1837. `TriggerFieldComments` as `cmts`,
  1838. `sm`.*,
  1839. `m`.`icon`
  1840. FROM `sys_objects_cmts` as `c`
  1841. LEFT JOIN `sys_modules` as `sm` ON `sm`.`name` = `c`.`module`
  1842. LEFT JOIN `sys_menu_items` as `m` ON `c`.`module` = `m`.`module` AND `m`.`set_name` = 'sys_site'
  1843. WHERE `c`.`module` != 'bx_timeline'
  1844. GROUP BY `c`.`module`
  1845. ", 'module');
  1846. }
  1847. function addJotReaction($iJotId, $iProfileId, $aEmoji)
  1848. {
  1849. $CNF = &$this->_oConfig->CNF;
  1850. return $this->query("REPLACE INTO `{$CNF['TABLE_JOT_REACTIONS']}`
  1851. SET
  1852. `{$CNF['FIELD_REACT_JOT_ID']}` = :jot_id,
  1853. `{$CNF['FIELD_REACT_NATIVE']}` = :native,
  1854. `{$CNF['FIELD_REACT_EMOJI_ID']}` = :emoji_id,
  1855. `{$CNF['FIELD_REACT_PROFILE_ID']}` = :profile_id,
  1856. `{$CNF['FIELD_REACT_ADDED']}` = UNIX_TIMESTAMP()
  1857. ", array(
  1858. 'jot_id' => $iJotId,
  1859. 'native' => $aEmoji['native'],
  1860. 'emoji_id' => $aEmoji['id'],
  1861. 'profile_id' => $iProfileId
  1862. ));
  1863. }
  1864. function deleteReaction($iJotId, $iProfileId, $sEmoji)
  1865. {
  1866. $CNF = &$this->_oConfig->CNF;
  1867. return $this->query("DELETE FROM `{$CNF['TABLE_JOT_REACTIONS']}`
  1868. WHERE
  1869. `{$CNF['FIELD_REACT_JOT_ID']}` = :jot_id AND
  1870. `{$CNF['FIELD_REACT_PROFILE_ID']}` = :profile_id AND
  1871. `{$CNF['FIELD_REACT_EMOJI_ID']}` = :emoji_id
  1872. ", array(
  1873. 'jot_id' => $iJotId,
  1874. 'profile_id' => $iProfileId,
  1875. 'emoji_id' => $sEmoji
  1876. ));
  1877. }
  1878. function deleteJotReactions($iJotId)
  1879. {
  1880. $CNF = &$this->_oConfig->CNF;
  1881. return $this->query("DELETE FROM `{$CNF['TABLE_JOT_REACTIONS']}`
  1882. WHERE
  1883. `{$CNF['FIELD_REACT_JOT_ID']}` = :jot_id
  1884. ", array(
  1885. 'jot_id' => $iJotId
  1886. ));
  1887. }
  1888. function updateReaction($iJotId, $iProfileId, $sEmojiId, $sAction = BX_JOT_REACTION_ADD)
  1889. {
  1890. $CNF = &$this->_oConfig->CNF;
  1891. if ($sAction === BX_JOT_REACTION_ADD) {
  1892. $sNative = $this->getOne("SELECT `{$CNF['FIELD_REACT_NATIVE']}`
  1893. FROM `{$CNF['TABLE_JOT_REACTIONS']}`
  1894. WHERE `{$CNF['FIELD_REACT_JOT_ID']}` = :jot_id AND `{$CNF['FIELD_REACT_EMOJI_ID']}`=:emoji LIMIT 1", ['jot_id' => $iJotId, 'emoji' => $sEmojiId]);
  1895. return $this->addJotReaction($iJotId, $iProfileId, array('native' => $sNative, 'id' => $sEmojiId));
  1896. }
  1897. return $this->deleteReaction($iJotId, $iProfileId, $sEmojiId);
  1898. }
  1899. function getJotReactions($iJotId)
  1900. {
  1901. $CNF = &$this->_oConfig->CNF;
  1902. return $this->getAll("SELECT * FROM `{$CNF['TABLE_JOT_REACTIONS']}`
  1903. WHERE
  1904. `{$CNF['FIELD_REACT_JOT_ID']}` = :jot_id
  1905. ORDER BY `{$CNF['FIELD_REACT_ADDED']}`", array('jot_id' => $iJotId));
  1906. }
  1907. public function findInHistory($iLotId = 0, $sText = '', $iStart = 0, $iLimit = 10, $sOrder = 'DESC', $bSkipDeleted = false)
  1908. {
  1909. if (!$sText)
  1910. return array();
  1911. $aWhere[] = "`j`.`{$this->CNF['FIELD_MESSAGE']}` LIKE :message";
  1912. $aParams['message'] = "%{$sText}%";
  1913. if ($iLotId) {
  1914. $aWhere[] = " `l`.`{$this->CNF['FIELD_ID']}`=:id ";
  1915. $aParams['id'] = $iLotId;
  1916. }
  1917. if ($bSkipDeleted) {
  1918. $aWhere[] = " `j`.`{$this->CNF['FIELD_MESSAGE_TRASH']}` = 0 ";
  1919. }
  1920. $sLimit = '';
  1921. $sOrder = $sOrder === 'ASC' ? 'ASC' : 'DESC';
  1922. if ($iLimit) {
  1923. $aParams['start'] = (int) $iStart;
  1924. $aParams['limit'] = (int) $iLimit;
  1925. $sLimit = "LIMIT :start, :limit";
  1926. }
  1927. if (!empty($aWhere))
  1928. $sWhere = implode(' AND ', $aWhere);
  1929. return $this->getAll("SELECT
  1930. `l`.`{$this->CNF['FIELD_TITLE']}`,
  1931. `l`.`{$this->CNF['FIELD_TYPE']}`,
  1932. `l`.`{$this->CNF['FIELD_ADDED']}` as `talk_added`,
  1933. `l`.`{$this->CNF['FIELD_AUTHOR']}` as `talk_author`,
  1934. `l`.`{$this->CNF['FIELD_PARTICIPANTS']}`,
  1935. `j`.`{$this->CNF['FIELD_MESSAGE']}`,
  1936. `j`.`{$this->CNF['FIELD_MESSAGE_ID']}` as `message_id`,
  1937. `j`.`{$this->CNF['FIELD_ADDED']}` as `message_added`,
  1938. `j`.`{$this->CNF['FIELD_MESSAGE_AUTHOR']}` as `message_author`
  1939. FROM `{$this->CNF['TABLE_ENTRIES']}` as `l`
  1940. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `j` ON `l`.`{$this->CNF['FIELD_ID']}` = `j`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  1941. WHERE {$sWhere}
  1942. ORDER BY `j`.`{$this->CNF['FIELD_MESSAGE_ID']}` {$sOrder}
  1943. {$sLimit}", $aParams);
  1944. }
  1945. public function removeNotifications($iJotId, $iConvoId = 0)
  1946. {
  1947. $sModule = $this->_oConfig->getName();
  1948. if ($iConvoId)
  1949. return $this->query("DELETE FROM `bx_notifications_events` WHERE `object_id`=:id AND `type`=:name", ['id' => $iConvoId, 'name' => $sModule]);
  1950. return $this->query("DELETE FROM `bx_notifications_events` WHERE `subobject_id`=:id AND `type`=:name", ['id' => $iJotId, 'name' => $sModule]);
  1951. }
  1952. public function markNotificationAsRead($iRecipientId, $iLotId)
  1953. {
  1954. if (!$this->isModuleByName('bx_notifications'))
  1955. return false;
  1956. $aEvents = $this->getAll("SELECT `e`.`id`
  1957. FROM `bx_notifications_events` AS `e`
  1958. LEFT JOIN `bx_notifications_queue` AS `q` ON `q`.`event_id` = `e`.`id`
  1959. WHERE `action`='got_jot_ntfs'
  1960. AND `e`.`type`=:type
  1961. AND `e`.`object_owner_id`=:object_owner_id
  1962. AND `e`.`object_id`=:lot_id",
  1963. array(
  1964. 'type' => $this->_oConfig->getName(),
  1965. 'lot_id' => $iLotId,
  1966. 'object_owner_id' => $iRecipientId
  1967. )
  1968. );
  1969. if (empty($aEvents))
  1970. return false;
  1971. foreach ($aEvents as &$aEvent) {
  1972. if (
  1973. $this->query(
  1974. "DELETE FROM `bx_notifications_events` WHERE `id`=:id",
  1975. array(
  1976. 'id' => $aEvent['id']
  1977. )
  1978. )
  1979. )
  1980. $this->query("DELETE FROM `bx_notifications_queue` WHERE `profile_id`=:profile_id AND `event_id`=:event_id", array(
  1981. 'profile_id' => $iRecipientId,
  1982. 'event_id' => $aEvent['id']
  1983. ));
  1984. }
  1985. }
  1986. function getPublicRoomParticipants($sRoom)
  1987. {
  1988. $aRoom = $this->getPublicVideoRoom($sRoom);
  1989. if (empty($aRoom) || !$aRoom[$this->CNF['FPJVC_PARTS']])
  1990. return array();
  1991. return explode(',', $aRoom[$this->CNF['FPJVC_PARTS']]);
  1992. }
  1993. function createPublicVideoRoom($sRoom, $iProfileId)
  1994. {
  1995. $CNF = &$this->_oConfig->CNF;
  1996. $aRoom = $this->getPublicVideoRoom($sRoom);
  1997. if (!empty($aRoom)) {
  1998. if (!(int) $aRoom[$CNF['FPJVC_STATUS']])
  1999. return $this->query("UPDATE `{$this->CNF['TABLE_PUBLIC_JVC']}`
  2000. SET
  2001. `{$this->CNF['FPJVC_CREATED']}`=UNIX_TIMESTAMP(),
  2002. `{$this->CNF['FPJVC_STATUS']}`=1,
  2003. `{$this->CNF['FPJVC_PARTS']}`=:part
  2004. WHERE `{$this->CNF['FPJVC_ROOM']}`=:room
  2005. ", array('room' => $sRoom, 'part' => $iProfileId));
  2006. else
  2007. return $this->updatePublicVideoRoom($sRoom, $iProfileId, BX_JOT_PUBLIC_JITSI_JOIN);
  2008. }
  2009. return $this->query("REPLACE INTO `{$this->CNF['TABLE_PUBLIC_JVC']}`
  2010. SET
  2011. `{$this->CNF['FPJVC_ROOM']}`=:room,
  2012. `{$this->CNF['FPJVC_CREATED']}`=UNIX_TIMESTAMP(),
  2013. `{$this->CNF['FPJVC_PARTS']}`=:part
  2014. ", array('room' => $sRoom, 'part' => $iProfileId));
  2015. }
  2016. function getPublicVideoRoom($sRoom)
  2017. {
  2018. if (!$sRoom)
  2019. return false;
  2020. return $this->getRow("SELECT * FROM `{$this->CNF['TABLE_PUBLIC_JVC']}`
  2021. WHERE `{$this->CNF['FPJVC_ROOM']}`=:room LIMIT 1", array('room' => $sRoom));
  2022. }
  2023. function updatePublicVideoRoom($sRoom, $iProfileId, $sAction)
  2024. {
  2025. $aRoom = $this->getPublicVideoRoom($sRoom);
  2026. if (empty($aRoom))
  2027. return false;
  2028. if ($sAction == BX_JOT_PUBLIC_JITSI_CLOSE)
  2029. return $this->query("UPDATE `{$this->CNF['TABLE_PUBLIC_JVC']}`
  2030. SET
  2031. `{$this->CNF['FPJVC_STATUS']}`=0
  2032. WHERE `{$this->CNF['FPJVC_ROOM']}`=:room
  2033. ", array('room' => $sRoom));
  2034. $aParticipants = array();
  2035. if ($aRoom[$this->CNF['FPJVC_PARTS']])
  2036. $aParticipants = explode(',', $aRoom[$this->CNF['FPJVC_PARTS']]);
  2037. if ($sAction == BX_JOT_PUBLIC_JITSI_JOIN && !in_array($iProfileId, $aParticipants))
  2038. $aParticipants[] = $iProfileId;
  2039. if ($sAction == BX_JOT_PUBLIC_JITSI_LEAVE)
  2040. $aParticipants = array_diff($aParticipants, array($iProfileId));
  2041. return $this->query(
  2042. "UPDATE `{$this->CNF['TABLE_PUBLIC_JVC']}`
  2043. SET
  2044. `{$this->CNF['FPJVC_PARTS']}`=:parts,
  2045. `{$this->CNF['FPJVC_STATUS']}`=:status
  2046. WHERE `{$this->CNF['FPJVC_ROOM']}`=:room
  2047. ",
  2048. array(
  2049. 'room' => $sRoom,
  2050. 'parts' => implode(',', $aParticipants),
  2051. 'status' => (int) !empty($aParticipants)
  2052. )
  2053. );
  2054. }
  2055. function saveLotSettings($iLotId, $mixedOptions, $sField = 'actions')
  2056. {
  2057. if (!$iLotId || !$sField)
  2058. return false;
  2059. if (empty($mixedOptions))
  2060. $mixedOptions = [];
  2061. $mixedData = is_array($mixedOptions) ? @serialize($mixedOptions) : (int) $mixedOptions;
  2062. $aLotSettings = $this->getLotSettings($iLotId, false);
  2063. if (empty($aLotSettings)) {
  2064. return $this->query("INSERT INTO `{$this->CNF['TABLE_LOT_SETTINGS']}`
  2065. SET
  2066. `{$sField}` = :data,
  2067. `{$this->CNF['FLS_ID']}` = :id", array('data' => $mixedData, 'id' => $iLotId));
  2068. }
  2069. return $this->query("UPDATE `{$this->CNF['TABLE_LOT_SETTINGS']}`
  2070. SET
  2071. `{$sField}` = :actions
  2072. WHERE `{$this->CNF['FLS_ID']}` = :id", array('actions' => $mixedData, 'id' => $iLotId));
  2073. }
  2074. function isActionAllowed($iLotId, $sAction = BX_MSG_SETTING_MSG)
  2075. {
  2076. $mixedOptions = $this->getLotSettings($iLotId);
  2077. if ($mixedOptions === false)
  2078. return true;
  2079. return in_array($sAction, $mixedOptions);
  2080. }
  2081. function getLotSettings($iLotId, $sField = 'actions')
  2082. {
  2083. $mixedOptions = false;
  2084. if (!$iLotId || !($mixedOptions = $this->getRow("SELECT * FROM `{$this->CNF['TABLE_LOT_SETTINGS']}` WHERE `{$this->CNF['FLS_ID']}` = :id", array('id' => $iLotId))))
  2085. return false;
  2086. return $sField && isset($mixedOptions[$sField]) ?
  2087. ($sField !== $this->CNF['FLS_ICON'] ? @unserialize($mixedOptions[$sField]) : (int) $mixedOptions[$sField]) : $mixedOptions;
  2088. }
  2089. function getLotAttachmentType($sName)
  2090. {
  2091. $sService = $this->getOne("SELECT `{$this->CNF['FLAT_SERVICE']}` FROM `{$this->CNF['TABLE_LOT_ATTACHMENTS']}` WHERE `{$this->CNF['FLAT_NAME']}`=:name LIMIT 1", array('name' => $sName));
  2092. return $sService ? @unserialize($sService) : false;
  2093. }
  2094. function updateLotAttachmentType(&$aData)
  2095. {
  2096. if (!isset($aData['name']) || !isset($aData['service']))
  2097. return false;
  2098. $sService = is_array($aData['service']) ? @serialize($aData['service']) : $aData['service'];
  2099. return $this->query(
  2100. "REPLACE INTO `{$this->CNF['TABLE_LOT_ATTACHMENTS']}`
  2101. SET
  2102. `{$this->CNF['FLSE_NAME']}`=:name,
  2103. `{$this->CNF['FLAT_SERVICE']}`=:service",
  2104. array('name' => $aData['name'], 'service' => $sService)
  2105. );
  2106. }
  2107. function getGroup($iGroupId)
  2108. {
  2109. return $this->getRow("SELECT * FROM `{$this->CNF['TABLE_GROUPS']}` WHERE `{$this->CNF['FMG_ID']}`=:id LIMIT 1", array('id' => $iGroupId));
  2110. }
  2111. function addGroup($iProfileId, $aParams)
  2112. {
  2113. $aGroup = array();
  2114. if (isset($aParams[$this->CNF['FMG_ID']]))
  2115. $aGroup = $this->getGroup($aParams[$this->CNF['FMG_ID']]);
  2116. if (empty($aGroup))
  2117. return $this->query(
  2118. "INSERT INTO `{$this->CNF['TABLE_GROUPS']}`
  2119. SET `{$this->CNF['FMG_NAME']}` = :name,
  2120. `{$this->CNF['FMG_PRIVACY']}` = :privacy,
  2121. `{$this->CNF['FMG_AUTHOR']}` = :author,
  2122. `{$this->CNF['FMG_DESC']}` = :desc,
  2123. `{$this->CNF['FMG_ADDED']}` = UNIX_TIMESTAMP()",
  2124. array(
  2125. 'name' => $aParams[$this->CNF['FMG_NAME']],
  2126. 'author' => $iProfileId,
  2127. 'desc' => $aParams[$this->CNF['FMG_DESC']],
  2128. 'privacy' => $aParams[$this->CNF['FMG_PRIVACY']]
  2129. )
  2130. );
  2131. return $this->query(
  2132. "UPDATE `{$this->CNF['TABLE_GROUPS']}`
  2133. SET `{$this->CNF['FMG_NAME']}` = :name,
  2134. `{$this->CNF['FMG_PRIVACY']}` = :privacy,
  2135. `{$this->CNF['FMG_DESC']}` = :desc
  2136. WHERE `{$this->CNF['FMG_ID']}`=:id",
  2137. array('name' => $aParams[$this->CNF['FMG_NAME']], 'desc' => $aParams[$this->CNF['FMG_DESC']], 'privacy' => $aParams[$this->CNF['FMG_PRIVACY']], 'id' => $aParams[$this->CNF['FMG_ID']])
  2138. );
  2139. }
  2140. function getGroups($iProfileId = 0)
  2141. {
  2142. if ($iProfileId)
  2143. return $this->getAll("SELECT * FROM `{$this->CNF['TABLE_GROUPS']}` WHERE `{$this->CNF['FMG_AUTHOR']}`=:profile", array('author' => $iProfileId));
  2144. return $this->getAll("SELECT * FROM `{$this->CNF['TABLE_GROUPS']}` ORDER BY {$this->CNF['FMG_NAME']}", array('author' => $iProfileId));
  2145. }
  2146. function addLotToGroup($iLotId, $iGroupId)
  2147. {
  2148. return $this->query("REPLACE INTO `{$this->CNF['TABLE_GROUPS_LOTS']}`
  2149. SET `{$this->CNF['FMGL_LOT_ID']}`=:lot_id,
  2150. `{$this->CNF['FMGL_GROUP_ID']}`=:group_id", array('group_id' => $iGroupId, 'lot_id' => $iLotId));
  2151. }
  2152. function saveJotItem($iJotId, $iProfileId)
  2153. {
  2154. return $this->query("REPLACE INTO `{$this->CNF['TABLE_SAVED_JOTS']}`
  2155. SET `{$this->CNF['FSJ_ID']}`=:jot_id,
  2156. `{$this->CNF['FSJ_PROFILE_ID']}`=:profile_id", array('jot_id' => $iJotId, 'profile_id' => $iProfileId));
  2157. }
  2158. /**
  2159. * Talks where the member has saved messages
  2160. * @param int $iProfileId profile id
  2161. * @return array lots ids
  2162. */
  2163. public function getSavedLotIds($iProfileId)
  2164. {
  2165. if (!$iProfileId) {
  2166. return [];
  2167. }
  2168. return array_map('intval', $this->getColumn("SELECT DISTINCT `m`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  2169. FROM `{$this->CNF['TABLE_SAVED_JOTS']}` AS `s`
  2170. INNER JOIN `{$this->CNF['TABLE_MESSAGES']}` AS `m` ON `m`.`{$this->CNF['FIELD_MESSAGE_ID']}` = `s`.`{$this->CNF['FSJ_ID']}`
  2171. WHERE `s`.`{$this->CNF['FSJ_PROFILE_ID']}` = :profile_id", ['profile_id' => (int)$iProfileId]));
  2172. }
  2173. /**
  2174. * Messages from the list that the member saved
  2175. * @param int $iProfileId profile id
  2176. * @param array $aJotIds jots ids
  2177. * @return array jots ids
  2178. */
  2179. public function getSavedJotsByIds($iProfileId, $aJotIds)
  2180. {
  2181. $aJotIds = array_filter(array_map('intval', (array)$aJotIds));
  2182. if (!$iProfileId || empty($aJotIds)) {
  2183. return [];
  2184. }
  2185. return $this->getColumn("SELECT `{$this->CNF['FSJ_ID']}` FROM `{$this->CNF['TABLE_SAVED_JOTS']}`
  2186. WHERE `{$this->CNF['FSJ_PROFILE_ID']}` = :profile_id AND `{$this->CNF['FSJ_ID']}` IN (" . implode(',', $aJotIds) . ")", ['profile_id' => (int)$iProfileId]);
  2187. }
  2188. function isJotSaved($iJotId, $iProfileId)
  2189. {
  2190. return $this->getOne(
  2191. "SELECT COUNT(*) FROM `{$this->CNF['TABLE_SAVED_JOTS']}`
  2192. WHERE `{$this->CNF['FSJ_ID']}`=:jot_id AND `{$this->CNF['FSJ_PROFILE_ID']}`=:profile_id",
  2193. ['jot_id' => $iJotId, 'profile_id' => $iProfileId]
  2194. ) != 0;
  2195. }
  2196. function deleteSavedJotItems($iJotId = 0, $iProfileId = 0)
  2197. {
  2198. if ($iJotId && $iProfileId)
  2199. return $this->query(
  2200. "DELETE FROM `{$this->CNF['TABLE_SAVED_JOTS']}`
  2201. WHERE `{$this->CNF['FSJ_ID']}`=:jot_id AND `{$this->CNF['FSJ_PROFILE_ID']}`=:profile_id",
  2202. array('jot_id' => $iJotId, 'profile_id' => $iProfileId)
  2203. );
  2204. if ($iJotId)
  2205. $this->query(
  2206. "DELETE FROM `{$this->CNF['TABLE_SAVED_JOTS']}`
  2207. WHERE `{$this->CNF['FSJ_ID']}`=:jot_id",
  2208. array('jot_id' => $iJotId)
  2209. );
  2210. return $iProfileId ? $this->query(
  2211. "DELETE FROM `{$this->CNF['TABLE_SAVED_JOTS']}`
  2212. WHERE `{$this->CNF['FSJ_PROFILE_ID']}`=:profile_id",
  2213. array('profile_id' => $iProfileId)
  2214. ) : false;
  2215. }
  2216. function getSavedJots($iProfileId)
  2217. {
  2218. return $this->getAllWithKey("SELECT `m`.* FROM `{$this->CNF['TABLE_SAVED_JOTS']}` as `s`
  2219. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `m` ON `s`.`{$this->CNF['FSJ_ID']}` = `m`.`{$this->CNF['FIELD_ID']}`
  2220. FROM `{$this->CNF['FSJ_PROFILE_ID']}`=:profile_id", $this->CNF['FIELD_ID'], array('profile_id' => $iProfileId));
  2221. }
  2222. function getSavedJotInLots($iProfileId, $aParams)
  2223. {
  2224. $CNF = &$this->_oConfig->CNF;
  2225. $aWhere['start'] = isset($aParams['start']) ? (int) $aParams['start'] : 0;
  2226. $aWhere['per_page'] = isset($aParams['per_page']) ? (int) $aParams['per_page'] : (int) $this->CNF['MAX_LOTS_NUMBER'];
  2227. $sLimit = "LIMIT :start, :per_page";
  2228. $sWhere = '';
  2229. if (isset($aParams['term'])) {
  2230. $aParams = preg_split('/[\s]/', $aParams['term'], -1, PREG_SPLIT_NO_EMPTY);
  2231. $sCriteria = implode('%', $aParams);
  2232. $aWhere['criteria'] = "%{$sCriteria}%";
  2233. $sWhere = "AND `m`.`{$CNF['FIELD_MESSAGE']}` like :criteria";
  2234. }
  2235. return $this->getAll("SELECT `m`.`{$this->CNF['FIELD_MESSAGE_FK']}`,`l`.* FROM `{$this->CNF['TABLE_SAVED_JOTS']}` as `s`
  2236. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `m` ON `s`.`{$this->CNF['FSJ_ID']}` = `m`.`{$this->CNF['FIELD_ID']}`
  2237. LEFT JOIN `{$this->CNF['TABLE_ENTRIES']}` as `l` ON `l`.`{$this->CNF['FIELD_ID']}` = `m`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  2238. WHERE `{$this->CNF['FSJ_PROFILE_ID']}`=:profile_id {$sWhere}
  2239. GROUP BY `m`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  2240. {$sLimit}", ['profile_id' => $iProfileId] + $aWhere);
  2241. }
  2242. public function getJotReplies($iLotId, $bCount = false)
  2243. {
  2244. $aWhere = array('id' => $iLotId);
  2245. if ($bCount)
  2246. return $this->getOne("SELECT COUNT(*) FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_FK']}`=:id", $aWhere);
  2247. return $this->getAll("SELECT * FROM `{$this->CNF['TABLE_MESSAGES']}`
  2248. WHERE `{$this->CNF['FIELD_MESSAGE_FK']}`=:id
  2249. ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}`
  2250. ", $aWhere);
  2251. }
  2252. function getReactionsMentionsLots($iProfileId, $aParams)
  2253. {
  2254. $CNF = &$this->_oConfig->CNF;
  2255. $aWhere['start'] = isset($aParams['start']) ? (int) $aParams['start'] : 0;
  2256. $aWhere['per_page'] = isset($aParams['per_page']) ? (int) $aParams['per_page'] : (int) $this->CNF['MAX_LOTS_NUMBER'];
  2257. $sLimit = "LIMIT :start, :per_page";
  2258. $sUrl = BxDolProfile::getInstance($iProfileId)->getUrl();
  2259. $aWhere['parts'] = '(^|,)' . (int) $iProfileId . '(,|$)';
  2260. $sWhere = '';
  2261. if (isset($aParams['term'])) {
  2262. $aParams = preg_split('/[\s]/', $aParams['term'], -1, PREG_SPLIT_NO_EMPTY);
  2263. $sCriteria = implode('%', $aParams);
  2264. $aWhere['criteria'] = "%{$sCriteria}%";
  2265. $sWhere = "AND `m`.`{$CNF['FIELD_MESSAGE']}` like :criteria";
  2266. }
  2267. return $this->getAll("SELECT `m`.`{$CNF['FIELD_MESSAGE_FK']}`, `l`.*
  2268. FROM `{$CNF['TABLE_MESSAGES']}` as `m`
  2269. LEFT JOIN `{$CNF['TABLE_ENTRIES']}` as `l` ON `l`.`{$CNF['FIELD_ID']}` = `m`.`{$CNF['FIELD_MESSAGE_FK']}`
  2270. LEFT JOIN `{$CNF['TABLE_JOT_REACTIONS']}` as `r` ON `m`.`{$CNF['FIELD_MESSAGE_ID']}` = `r`.`{$CNF['FIELD_REACT_JOT_ID']}`
  2271. WHERE ((`r`.`{$CNF['FIELD_REACT_JOT_ID']}` IS NOT NULL AND `m`.`{$CNF['FIELD_MESSAGE_AUTHOR']}`=:profile_id )
  2272. OR `m`.`{$CNF['FIELD_MESSAGE']}` LIKE '\"%" . '/' . bx_ltrim_str($sUrl, BX_DOL_URL_ROOT) . "\"' ) AND
  2273. (`l`.`{$CNF['FIELD_PARTICIPANTS']}` REGEXP :parts OR `l`.`{$CNF['FIELD_AUTHOR']}`=:profile_id) {$sWhere}
  2274. GROUP BY `m`.`{$CNF['FIELD_MESSAGE_FK']}`
  2275. {$sLimit}", ['profile_id' => $iProfileId] + $aWhere);
  2276. }
  2277. function getLotsWithReplies($iProfileId, $aParams = [])
  2278. {
  2279. $CNF = &$this->_oConfig->CNF;
  2280. $aWhere['start'] = isset($aParams['start']) ? (int) $aParams['start'] : 0;
  2281. $aWhere['per_page'] = isset($aParams['per_page']) ? (int) $aParams['per_page'] : (int) $this->CNF['MAX_LOTS_NUMBER'];
  2282. $sLimit = "LIMIT :start, :per_page";
  2283. $sWhere = '';
  2284. if (isset($aParams['term'])) {
  2285. $aParams = preg_split('/[\s]/', $aParams['term'], -1, PREG_SPLIT_NO_EMPTY);
  2286. $sCriteria = implode('%', $aParams);
  2287. $aWhere['criteria'] = "%{$sCriteria}%";
  2288. $sWhere = "AND `m`.`{$CNF['FIELD_MESSAGE']}` like :criteria";
  2289. }
  2290. return $this->getAll("SELECT `m`.`{$CNF['FIELD_MESSAGE_FK']}`, `l`.*
  2291. FROM `{$this->CNF['TABLE_MESSAGES']}` as `m`
  2292. LEFT JOIN `{$this->CNF['TABLE_ENTRIES']}` as `l` ON `l`.`{$this->CNF['FIELD_ID']}` = `m`.`{$this->CNF['FIELD_MESSAGE_FK']}`
  2293. LEFT JOIN `{$CNF['TABLE_MESSAGES']}` as `r` ON `r`.`{$CNF['FIELD_MESSAGE_ID']}` = `m`.`{$CNF['FIELD_MESSAGE_REPLY']}`
  2294. WHERE `r`.`{$CNF['FIELD_MESSAGE_AUTHOR']}`=:profile_id AND `m`.`{$CNF['FIELD_MESSAGE_REPLY']}` <> 0 {$sWhere}
  2295. GROUP BY `m`.`{$CNF['FIELD_MESSAGE_FK']}`
  2296. {$sLimit}", ['profile_id' => $iProfileId] + $aWhere);
  2297. }
  2298. function registerGroup($sUrl, $iLotId, $bForce = false)
  2299. {
  2300. $aUrl = [];
  2301. parse_str($sUrl, $aUrl);
  2302. if (!empty($aUrl) && isset($aUrl['i'])) {
  2303. $oPage = BxDolPage::getObjectInstanceByModuleAndURI(BX_IM_EMPTY_URL, $aUrl['i']);
  2304. if (!$oPage && !$bForce)
  2305. return false;
  2306. $sModule = '';
  2307. $sTitle = _t('_bx_messenger_page_unknown');
  2308. $iAuthor = $iProfileId = 0;
  2309. $iPrivacy = BX_DOL_PG_ALL;
  2310. if ($oPage && ($aPageInfo = $oPage->getObject()) && ($sModule = $oPage->getModule()) && ($oModule = BxDolModule::getInstance($sModule))) {
  2311. $CNF = &$oModule->_oConfig->CNF;
  2312. $sTitle = _t($aPageInfo['title']);
  2313. $iAuthor = $aPageInfo['author'];
  2314. if (isset($aUrl['id']) && !empty($oModule) && ($aResult = bx_srv($sModule, 'get_info', array($aUrl['id'], false)))) {
  2315. $sTitle = $aResult[$CNF['FIELD_TITLE']];
  2316. $iAuthor = $aResult[$CNF['FIELD_AUTHOR']];
  2317. $iProfileId = isset($aResult['profile_id']) ? $aResult['profile_id'] : 0;
  2318. $iPrivacy = isset($aResult[$CNF['FIELD_ALLOW_VIEW_TO']]);
  2319. }
  2320. }
  2321. if (
  2322. $this->query(
  2323. "INSERT INTO `{$this->CNF['TABLE_GROUPS']}`
  2324. SET `{$this->CNF['FMG_NAME']}` = :name,
  2325. `{$this->CNF['FMG_PRIVACY']}` = :privacy,
  2326. `{$this->CNF['FMG_AUTHOR']}` = :author,
  2327. `{$this->CNF['FMG_URL']}` = :url,
  2328. `{$this->CNF['FMG_MODULE']}` = :module,
  2329. `{$this->CNF['FMG_PROFILE_ID']}` =:profile_id,
  2330. `{$this->CNF['FMG_ADDED']}` = UNIX_TIMESTAMP()",
  2331. array(
  2332. 'name' => $sTitle,
  2333. 'author' => $iAuthor,
  2334. 'url' => $sUrl,
  2335. 'module' => in_array($sModule, $this->CNF['ADD-TO-PAGES-AREA'][BX_MSG_TALK_TYPE_PAGES]) ? BX_MSG_TALK_TYPE_PAGES : $sModule,
  2336. 'profile_id' => $iProfileId,
  2337. 'privacy' => $iPrivacy
  2338. )
  2339. )
  2340. )
  2341. return $this->addLotToGroup($iLotId, $this->lastId());
  2342. }
  2343. return false;
  2344. }
  2345. function getMyLotsByGroups($iProfileId, $bCount = false)
  2346. {
  2347. $aWhere = array('profile' => (int) $iProfileId, 'parts' => '(^|,)' . (int) $iProfileId . '(,|$)');
  2348. if ($bCount)
  2349. $sCount = "SQL_CALC_FOUND_ROWS";
  2350. $aGroups = $this->getAll("SELECT
  2351. `l`.*, `g`.`{$this->CNF['FMG_PROFILE_ID']}`,`g`.`{$this->CNF['FMG_MODULE']}`, `g`.`{$this->CNF['FMG_NAME']}`, `gl`.`{$this->CNF['FMGL_GROUP_ID']}`,
  2352. IF (`l`.`{$this->CNF['FIELD_UPDATED']}` = 0, `l`.`{$this->CNF['FIELD_ADDED']}`, `l`.`{$this->CNF['FIELD_UPDATED']}`) as `order`,
  2353. IF (`l`.`{$this->CNF['FIELD_URL']}` = '', `g`.`{$this->CNF['FMG_URL']}`, `l`.`{$this->CNF['FIELD_URL']}`) as `gurl`,
  2354. `un`.`{$this->CNF['FIELD_NEW_UNREAD']}` as `unread`
  2355. FROM `{$this->CNF['TABLE_ENTRIES']}` as `l`
  2356. LEFT JOIN `{$this->CNF['TABLE_NEW_MESSAGES']}` as `un` ON `l`.`{$this->CNF['FIELD_ID']}` = `un`.`{$this->CNF['FIELD_NEW_LOT']}` AND `un`.`{$this->CNF['FIELD_NEW_PROFILE']}`=:profile
  2357. LEFT JOIN `{$this->CNF['TABLE_GROUPS_LOTS']}` as `gl` ON `gl`.`{$this->CNF['FMGL_LOT_ID']}` = `l`.`{$this->CNF['FIELD_ID']}`
  2358. LEFT JOIN `{$this->CNF['TABLE_GROUPS']}` as `g` ON `g`.`{$this->CNF['FMG_ID']}` = `gl`.`{$this->CNF['FMGL_GROUP_ID']}`
  2359. WHERE (`l`.`{$this->CNF['FIELD_PARTICIPANTS']}` REGEXP :parts OR `l`.`{$this->CNF['FIELD_AUTHOR']}`=:profile) AND `gl`.`{$this->CNF['FMGL_GROUP_ID']}` IS NOT NULL
  2360. ORDER BY `g`.`{$this->CNF['FMG_MODULE']}`", $aWhere);
  2361. // print_r($aGroups);
  2362. $aResult = array();
  2363. $sModule = '';
  2364. foreach ($aGroups as &$aGroup) {
  2365. if (!isset($aGroup[$this->CNF['FMG_MODULE']]))
  2366. continue;
  2367. if ($aGroup[$this->CNF['FMG_MODULE']] != $sModule)
  2368. $sModule = $aGroup[$this->CNF['FMG_MODULE']];
  2369. if (!isset($aResult[$sModule][$aGroup[$this->CNF['FMGL_GROUP_ID']]])) {
  2370. $aResult[$sModule][$aGroup[$this->CNF['FMGL_GROUP_ID']]] = [
  2371. $this->CNF['FMG_NAME'] => $aGroup[$this->CNF['FMG_NAME']],
  2372. $this->CNF['FMG_ID'] => $aGroup[$this->CNF['FMG_PROFILE_ID']], // group profile id of the module
  2373. $this->CNF['FMGL_GROUP_ID'] => $aGroup[$this->CNF['FMGL_GROUP_ID']],
  2374. $this->CNF['FMG_URL'] => $aGroup['gurl']
  2375. ];
  2376. }
  2377. // fill each groups with existed talks in it group
  2378. $aResult[$sModule][$aGroup[$this->CNF['FMGL_GROUP_ID']]][$this->CNF['GROUPS_ITEMS_FIELD']][] = [
  2379. $this->CNF['FIELD_ADDED'] => $aGroup[$this->CNF['FIELD_ADDED']],
  2380. $this->CNF['FIELD_AUTHOR'] => $aGroup[$this->CNF['FIELD_AUTHOR']],
  2381. $this->CNF['FIELD_TITLE'] => $aGroup[$this->CNF['FIELD_TITLE']],
  2382. $this->CNF['FIELD_PARTICIPANTS'] => $aGroup[$this->CNF['FIELD_PARTICIPANTS']],
  2383. $this->CNF['FIELD_ID'] => $aGroup[$this->CNF['FIELD_ID']],
  2384. $this->CNF['FMG_URL'] => $aGroup[$this->CNF['FIELD_URL']]
  2385. //$this->CNF['FMG_PROFILE_ID'] => $aGroup[$this->CNF['FMG_PROFILE_ID']],
  2386. ];
  2387. }
  2388. return $aResult;
  2389. }
  2390. function getGroupIdByLotId($iLotId)
  2391. {
  2392. return $this->getOne("SELECT `{$this->CNF['FMGL_GROUP_ID']}`
  2393. FROM `{$this->CNF['TABLE_GROUPS_LOTS']}`
  2394. WHERE `{$this->CNF['FMGL_LOT_ID']}`=:id", array('id' => $iLotId));
  2395. }
  2396. function getTalksByGroupId($iGroupId)
  2397. {
  2398. return $this->getAllWithKey("SELECT `l`.*
  2399. FROM `{$this->CNF['TABLE_GROUPS_LOTS']}` as `gl`
  2400. LEFT JOIN `{$this->CNF['TABLE_ENTRIES']}` as `l` ON `gl`.`{$this->CNF['FMGL_LOT_ID']}` = `l`.`{$this->CNF['FIELD_ID']}`
  2401. WHERE `gl`.`{$this->CNF['FMGL_GROUP_ID']}`=:id AND `l`.`id` IS NOT NULL
  2402. ", $this->CNF['FIELD_ID'], array('id' => $iGroupId));
  2403. }
  2404. function getGroupById($iGroupId)
  2405. {
  2406. return $this->getRow("SELECT *
  2407. FROM `{$this->CNF['TABLE_GROUPS']}`
  2408. WHERE `{$this->CNF['FMG_ID']}`=:id LIMIT 1", array('id' => $iGroupId));
  2409. }
  2410. function getGroupByUrl($sUrl)
  2411. {
  2412. return $this->getRow("SELECT * FROM `{$this->CNF['TABLE_GROUPS']}` WHERE `{$this->CNF['FMG_URL']}`=:url LIMIT 1", array('url' => $sUrl));
  2413. }
  2414. function getLotType($iLotId)
  2415. {
  2416. $aInfo = $this->getLotInfoById($iLotId);
  2417. if (empty($aInfo))
  2418. return false;
  2419. if ($aInfo[$this->CNF['FMGL_GROUP_ID']]) {
  2420. $aGroupInfo = $this->getGroup($aInfo[$this->CNF['FMGL_GROUP_ID']]);
  2421. return [
  2422. 'group_id' => $aInfo[$this->CNF['FMGL_GROUP_ID']],
  2423. 'type' => BX_MSG_TALK_TYPE_GROUPS,
  2424. 'groups_type' => $aGroupInfo[$this->CNF['FMG_MODULE']]
  2425. ];
  2426. }
  2427. if ((int) $aInfo[$this->CNF['FIELD_PARENT_JOT']])
  2428. return ['type' => BX_MSG_TALK_TYPE_THREADS];
  2429. if ($aInfo[$this->CNF['FIELD_TYPE']] == BX_IM_TYPE_PRIVATE)
  2430. return ['type' => BX_MSG_TALK_TYPE_DIRECT];
  2431. if ($aInfo[$this->CNF['FIELD_TYPE']] == BX_IM_TYPE_BROADCAST)
  2432. return ['type' => BX_MSG_TALK_TYPE_BROADCAST];
  2433. return false;
  2434. }
  2435. function getUnreadMessagesStat($iProfileId)
  2436. {
  2437. $aItems = $this->getLotsWithUnreadMessages($iProfileId);
  2438. $aResult = [];
  2439. if (empty($aItems))
  2440. return $aResult;
  2441. foreach ($aItems as $iLotId => $iCount) {
  2442. if (!($aType = $this->getLotType($iLotId)))
  2443. continue;
  2444. if (isset($aType['group_id']))
  2445. $aResult['groups'][$aType['groups_type']][$aType['group_id']][$iLotId] = +$iCount;
  2446. else
  2447. $aResult[$aType['type']][$iLotId] = +$iCount;
  2448. }
  2449. return array_merge($aResult, [BX_MSG_TALK_TYPE_INBOX => count($aItems)]);
  2450. }
  2451. function addMediaTrack($iFileId, $iProfileId)
  2452. {
  2453. return $this->query("REPLACE INTO `{$this->CNF['TABLE_JOTS_MEDIA_TRACKER']}`
  2454. SET `{$this->CNF['FJMT_FILE_ID']}`=:id,
  2455. `{$this->CNF['FJMT_USER_ID']}`=:user_id", ['id' => $iFileId, 'user_id' => $iProfileId]);
  2456. }
  2457. function isFileCollapsed($iFileId, $iProfileId)
  2458. {
  2459. return $this->getOne(
  2460. "SELECT COUNT(*) FROM `{$this->CNF['TABLE_JOTS_MEDIA_TRACKER']}`
  2461. WHERE `{$this->CNF['FJMT_FILE_ID']}`=:id AND `{$this->CNF['FJMT_USER_ID']}`=:user_id",
  2462. ['id' => $iFileId, 'user_id' => $iProfileId]
  2463. );
  2464. }
  2465. function removeMediaTracker($iFileId = 0, $iProfileId = 0)
  2466. {
  2467. if (!$iFileId && !$iProfileId)
  2468. return false;
  2469. $aWhereParams = $aWhere = [];
  2470. if ($iFileId) {
  2471. $aWhere[] = "`{$this->CNF['FJMT_FILE_ID']}`=:id";
  2472. $aWhereParams['id'] = $iFileId;
  2473. }
  2474. if ($iProfileId) {
  2475. $aWhere[] = "`{$this->CNF['FJMT_USER_ID']}`=:user_id";
  2476. $aWhereParams['user_id'] = $iProfileId;
  2477. }
  2478. $sWhere = implode(' AND ', $aWhere);
  2479. return $this->query("DELETE FROM `{$this->CNF['TABLE_JOTS_MEDIA_TRACKER']}`
  2480. WHERE {$sWhere}", $aWhereParams);
  2481. }
  2482. public function getObjectAuthorId($iId)
  2483. {
  2484. $sQuery = $this->prepare("SELECT `{$this->CNF['FIELD_MESSAGE_AUTHOR']}` FROM `{$this->CNF['TABLE_MESSAGES']}` WHERE `{$this->CNF['FIELD_MESSAGE_ID']}` = ? LIMIT 1", $iId);
  2485. return (int) $this->getOne($sQuery);
  2486. }
  2487. public function isPerformed($iObjectId, $iAuthorId, $sEmoji)
  2488. {
  2489. $sQuery = $this->prepare("SELECT COUNT(*)
  2490. FROM `{$this->CNF['TABLE_JOT_REACTIONS']}`
  2491. WHERE `{$this->CNF['FIELD_REACT_JOT_ID']}` = ? AND `{$this->CNF['FIELD_REACT_PROFILE_ID']}` = ? AND
  2492. `{$this->CNF['FIELD_REACT_EMOJI_ID']}` = ? LIMIT 1", $iObjectId, $iAuthorId, $sEmoji);
  2493. return (int) $this->getOne($sQuery) != 0;
  2494. }
  2495. public function putVote($iObjectId, $iAuthorId, $sAuthorIp, $aData, $bUndo = false)
  2496. {
  2497. $sReaction = $aData['reaction'];
  2498. $aReactions = BxDolFormQuery::getDataItems('sys_vote_reactions', false, BX_DATA_VALUES_ALL);
  2499. if (!isset($aReactions[$sReaction]))
  2500. return false;
  2501. if (!$aReaction = @unserialize($aReactions[$sReaction]['Data']))
  2502. return false;
  2503. $sQuery = "SELECT `id` FROM `{$this->CNF['TABLE_JOT_REACTIONS']}` WHERE `{$this->CNF['FIELD_REACT_JOT_ID']}` = :object_id
  2504. AND `{$this->CNF['FIELD_REACT_EMOJI_ID']}` = :reaction AND `{$this->CNF['FIELD_REACT_PROFILE_ID']}`=:author LIMIT 1";
  2505. $bExists = (int) $this->getOne($sQuery, array('object_id' => $iObjectId, 'reaction' => $sReaction, 'author' => $iAuthorId)) != 0;
  2506. if ($bExists && $bUndo)
  2507. return $this->deleteReaction($iObjectId, $iAuthorId, $aData['reaction']);
  2508. else
  2509. return $this->addJotReaction($iObjectId, $iAuthorId, ['id' => $this->_oConfig->convertApp2Emoji($aData['reaction']), 'native' => $aReaction['emoji']]);
  2510. return $this->lastId();
  2511. }
  2512. public function getVote($iObjectId)
  2513. {
  2514. $aReactions = BxDolFormQuery::getDataItems('sys_vote_reactions', false, BX_DATA_VALUES_ALL);
  2515. $aReactionsGot = $this->getPairs("SELECT COUNT(*) as `count`, `{$this->CNF['FIELD_REACT_EMOJI_ID']}` FROM `{$this->CNF['TABLE_JOT_REACTIONS']}` WHERE `{$this->CNF['FIELD_REACT_JOT_ID']}` = :object_id GROUP BY `{$this->CNF['FIELD_REACT_EMOJI_ID']}`", $this->CNF['FIELD_REACT_EMOJI_ID'], 'count', array('object_id' => $iObjectId));
  2516. $aResult = array();
  2517. foreach ($aReactions as $sName => $iValue) {
  2518. $iCount = $iSum = 0;
  2519. if (!empty($aReactionsGot[$sName])) {
  2520. $iCount = (int) $aReactionsGot[$sName];
  2521. $iSum += $iCount;
  2522. }
  2523. $aResult['count_' . $sName] = $iCount;
  2524. $aResult['sum_' . $sName] = $iSum;
  2525. $aResult['rate_' . $sName] = $iCount != 0 ? $iSum / $iCount : 0;
  2526. }
  2527. $aResult['count_default'] = $iCount;
  2528. $aResult['sum_default'] = $iSum;
  2529. return $aResult;
  2530. }
  2531. public function getTrack($iObjectId, $iAuthorId)
  2532. {
  2533. return $this->getRow("SELECT *, `{$this->CNF['FIELD_REACT_EMOJI_ID']}` as `reaction` FROM `{$this->CNF['TABLE_JOT_REACTIONS']}` WHERE `{$this->CNF['FIELD_REACT_JOT_ID']}` = :object_id AND `{$this->CNF['FIELD_REACT_PROFILE_ID']}` = :author_id LIMIT 1", array(
  2534. 'object_id' => $iObjectId,
  2535. 'author_id' => $iAuthorId
  2536. ));
  2537. }
  2538. public function getPerformed($aParams = array())
  2539. {
  2540. $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
  2541. $aBindings = array();
  2542. $sSelectClause = '`tt`.*';
  2543. $sJoinClause = $sWhereClause = '';
  2544. $sLimitClause = isset($aParams['start']) && !empty($aParams['per_page']) ? "LIMIT " . $aParams['start'] . ", " . $aParams['per_page'] : "";
  2545. if (!empty($aParams['type']))
  2546. switch ($aParams['type']) {
  2547. case 'by':
  2548. $aBindings['object_id'] = $aParams['object_id'];
  2549. $sJoinClause = "INNER JOIN `sys_profiles` AS `tp` ON `tt`.`user_id`=`tp`.`id` AND `tp`.`status`='active'";
  2550. $sWhereClause = "AND `tt`.`jot_id` = :object_id";
  2551. if (!empty($aParams['reaction'])) {
  2552. $aMethod['name'] = 'getColumn';
  2553. $aBindings['reaction'] = $this->_oConfig->convertApp2Emoji($aParams['reaction']);
  2554. $sSelectClause = "`tt`.`user_id`";
  2555. $sWhereClause .= " AND `tt`.`emoji_id`=:reaction";
  2556. } else {
  2557. $aMethod['name'] = 'getAll';
  2558. $sSelectClause = "`tt`.`user_id`, `tt`.`emoji_id`";
  2559. }
  2560. break;
  2561. }
  2562. $aMethod['params'][0] = "SELECT " . $sSelectClause . " FROM `{$this->CNF['TABLE_JOT_REACTIONS']}` AS `tt` " . $sJoinClause . " WHERE 1 " . $sWhereClause . $sLimitClause;
  2563. $aMethod['params'][] = $aBindings;
  2564. return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
  2565. }
  2566. /**
  2567. * Occurs when delete context object
  2568. * @param $iAuthorId context id (group,space ) and etc...
  2569. */
  2570. function deleteAuthorEntries($iAuthorId)
  2571. {
  2572. return false;
  2573. }
  2574. public function pruningByDate($iDate)
  2575. {
  2576. return 0;
  2577. }
  2578. function updateConvoHash($iConvoId)
  2579. {
  2580. $sHash = $this->_oConfig->generateConvoHash($iConvoId);
  2581. return $this->query("UPDATE `{$this->CNF['TABLE_ENTRIES']}` SET `{$this->CNF['FIELD_HASH']}`=:hash
  2582. WHERE `{$this->CNF['FIELD_ID']}`=:id ", ['hash' => $sHash, 'id' => $iConvoId]);
  2583. }
  2584. function updateConvoFiled($iConvoId, $sField, $mixedValue)
  2585. {
  2586. if (!$sField)
  2587. return false;
  2588. return $this->query("UPDATE `{$this->CNF['TABLE_ENTRIES']}`
  2589. SET `{$sField}`=:value
  2590. WHERE `{$this->CNF['FIELD_ID']}`=:id", ['value' => $mixedValue, 'id' => $iConvoId]);
  2591. }
  2592. function getConvoByHash($sHash, $bIdOnly = true)
  2593. {
  2594. $aConvo = $this->getRow("SELECT * FROM `{$this->CNF['TABLE_ENTRIES']}` WHERE `{$this->CNF['FIELD_HASH']}`=:hash LIMIT 1", ['hash' => $sHash]);
  2595. return $bIdOnly && !empty($aConvo) ? $aConvo[$this->CNF['FIELD_ID']] : $aConvo;
  2596. }
  2597. private function getProfilesByCriteriaSqlParts($aFields)
  2598. {
  2599. $aSqlParts = ['where' => '', 'join' => ''];
  2600. if (isset($aFields['membership'])) {
  2601. $aSqlParts = BxDolAclQuery::getInstance()->getContentByLevelAsSQLPart('sys_profiles', 'id', $aFields['membership']);
  2602. unset($aFields['membership']);
  2603. }
  2604. if (!empty($aFields)) {
  2605. $aSqlParts['join'] .= "LEFT JOIN `bx_persons_data` as `pd` ON `pd`.`id` = `sys_profiles`.`content_id` AND `sys_profiles`.`type` = 'bx_persons'";
  2606. foreach ($aFields as $sName => $mixedValues) {
  2607. if ($sName === 'location' && !empty($mixedValues)) {
  2608. $sLocation = implode("','", $mixedValues);
  2609. $aSqlParts['join'] .= "LEFT JOIN `bx_persons_meta_locations` as `pdl` ON `pdl`.`object_id` = `pd`.`id`";
  2610. $aSqlParts['where'] .= " AND `pdl`.`country` IN ('" . $sLocation . "')";
  2611. continue;
  2612. }
  2613. if (is_array($mixedValues))
  2614. $aSqlParts['where'] .= " AND `pd`.`{$sName}` IN ('" . implode("','", $mixedValues) . "')";
  2615. else
  2616. $aSqlParts['where'] .= " AND `pd`.`{$sName}` = '{$mixedValues}'";
  2617. }
  2618. }
  2619. bx_alert($this->_oConfig->getObject('alert'), 'broadcast_criteria_after', 0, 0, [
  2620. 'fields' => $aFields,
  2621. 'sql' => &$aSqlParts
  2622. ]);
  2623. return $aSqlParts;
  2624. }
  2625. public function getProfilesByCriteria($aFields, $aAddons = [])
  2626. {
  2627. return $this->_getProfilesByCriteria($aFields, $aAddons, false);
  2628. }
  2629. public function getProfilesCountByCriteria($aFields, $aAddons = [])
  2630. {
  2631. return $this->_getProfilesByCriteria($aFields, $aAddons, true);
  2632. }
  2633. private function _getProfilesByCriteria($aFields, $aAddons = [], $bCountOnly = false)
  2634. {
  2635. if (empty($aFields) && empty($aAddons)) {
  2636. return $bCountOnly ? 0 : [];
  2637. }
  2638. $aExcludeProfiles = $aAddons['exclude_profiles'] ?? [];
  2639. $aIncludeProfiles = $aAddons['include_profiles'] ?? [];
  2640. $aQueries = [];
  2641. if (!empty($aFields) || empty($aIncludeProfiles)) {
  2642. $aSqlParts = $this->getProfilesByCriteriaSqlParts($aFields);
  2643. $sWhereClause = !empty($aSqlParts['where']) ? $aSqlParts['where'] : '';
  2644. if (!empty($aExcludeProfiles)) {
  2645. $sWhereClause .= " AND `sys_profiles`.`id` NOT IN (" . implode(',', $aExcludeProfiles) . ")";
  2646. }
  2647. $aQueries[] = "SELECT DISTINCT `sys_profiles`.`id` FROM `sys_profiles`" . $aSqlParts['join'] . " WHERE 1" . $sWhereClause;
  2648. }
  2649. if (!empty($aIncludeProfiles)) {
  2650. $sExcludeClause = '';
  2651. if (!empty($aExcludeProfiles)) {
  2652. $sExcludeClause = " AND `sys_profiles`.`id` NOT IN (" . implode(',', $aExcludeProfiles) . ")";
  2653. }
  2654. $sQueriesParts = implode(',', $aIncludeProfiles);
  2655. $aQueries[] = "SELECT `sys_profiles`.`id` FROM `sys_profiles` WHERE `sys_profiles`.`id` IN ({$sQueriesParts})" . $sExcludeClause;
  2656. }
  2657. $sSql = implode(" UNION ", $aQueries);
  2658. if ($bCountOnly) {
  2659. $sSql = "SELECT COUNT(*) FROM ({$sSql}) AS `t`";
  2660. return (int)$this->getOne($this->prepare($sSql));
  2661. } else {
  2662. return $this->getColumn($this->prepare($sSql));
  2663. }
  2664. }
  2665. function createBroadcastUsers($iConvoId, &$aData)
  2666. {
  2667. $sBegin = "REPLACE INTO `{$this->CNF['TABLE_MASS_TRACKER']}`
  2668. (`{$this->CNF['FIELD_MASS_CONVO_ID']}`, `{$this->CNF['FIELD_MASS_USER_ID']}`)
  2669. VALUES ";
  2670. $bExecuted = false;
  2671. $aProfileChunks = array_chunk($aData, 200);
  2672. foreach ($aProfileChunks as &$aChunk) {
  2673. $aValues = array_map(function ($iProfileId) use ($iConvoId) {
  2674. return "($iConvoId, $iProfileId)";
  2675. }, $aChunk);
  2676. if (!empty($aValues)) {
  2677. $sBegin . implode(",", $aValues);
  2678. $bExecuted |= (bool) $this->query($sBegin . implode(",", $aValues));
  2679. }
  2680. };
  2681. return $bExecuted;
  2682. }
  2683. function getBroadcastParticipants($iConvoId, $iLimit = 0, $iAfterUserId = 0)
  2684. {
  2685. $aBindings = ['id' => $iConvoId];
  2686. $sWhere = "WHERE `{$this->CNF['FIELD_MASS_CONVO_ID']}`=:id";
  2687. if ((int) $iAfterUserId > 0) {
  2688. $aBindings['after_user_id'] = (int) $iAfterUserId;
  2689. $sWhere .= " AND `{$this->CNF['FIELD_MASS_USER_ID']}` > :after_user_id";
  2690. }
  2691. $sLimit = (int) $iLimit > 0 ? " LIMIT " . (int) $iLimit : "";
  2692. return $this->getColumn("SELECT `{$this->CNF['FIELD_MASS_USER_ID']}`
  2693. FROM `{$this->CNF['TABLE_MASS_TRACKER']}`
  2694. {$sWhere}
  2695. ORDER BY `{$this->CNF['FIELD_MASS_USER_ID']}` ASC{$sLimit}", $aBindings);
  2696. }
  2697. function isBroadcastParticipant($iConvoId, $iProfileId)
  2698. {
  2699. return $this->getOne("SELECT COUNT(*)
  2700. FROM `{$this->CNF['TABLE_MASS_TRACKER']}`
  2701. WHERE `{$this->CNF['FIELD_MASS_CONVO_ID']}`=:id AND `{$this->CNF['FIELD_MASS_USER_ID']}`=:user_id", ['id' => $iConvoId, 'user_id' => $iProfileId]) != 0;
  2702. }
  2703. function getNotificationsSettings($sGroup)
  2704. {
  2705. if (!$this->isModuleByName('bx_notifications'))
  2706. return false;
  2707. return $this->getPairs("SELECT `delivery`, `active` FROM `bx_notifications_settings` WHERE `group`=:group", 'delivery', 'active', ['group' => $sGroup]);
  2708. }
  2709. /**
  2710. * For API only.
  2711. */
  2712. public function getJotsByLotIdApi($aData)
  2713. {
  2714. $sMode = isset($aData['mode']) ? $aData['mode'] : 'new';
  2715. $iLot = isset($aData['lot']) ? (int) $aData['lot'] : BX_IM_EMPTY;
  2716. $iStart = isset($aData['start']) ? (int) $aData['start'] : BX_IM_EMPTY;
  2717. $iLimit = isset($aData['limit']) ? (int) $aData['limit'] : BX_IM_EMPTY;
  2718. $sArea = isset($aData['area']) ? $aData['area'] : '';
  2719. $aBindings = [
  2720. 'lot' => (int) $iLot,
  2721. 'start' => (int) $iStart,
  2722. 'limit' => (int) $iLimit
  2723. ];
  2724. $sWhere = $sLimit = '';
  2725. $sWhere = "AND `m`.`{$this->CNF['FIELD_MESSAGE_FK']}` = :lot ";
  2726. $sJoinArea = $sWhereArea = '';
  2727. if ($sArea)
  2728. list($sJoinArea, $sWhereArea) = $this->getJotsByArea($sArea);
  2729. $sQuery = "SELECT `m`.* FROM `{$this->CNF['TABLE_MESSAGES']}` as `m` {$sJoinArea} WHERE 1 {$sWhere} {$sWhereArea} ORDER BY `m`.`{$this->CNF['FIELD_MESSAGE_ID']}` DESC LIMIT :start, :limit";
  2730. return $this->getAll("({$sQuery}) ORDER BY `{$this->CNF['FIELD_MESSAGE_ID']}`", $aBindings);
  2731. }
  2732. public function getVideoConferenceInfoByRoom($sRoom, $iLimit = 0)
  2733. {
  2734. if (!$sRoom)
  2735. return [];
  2736. $sLimit = '';
  2737. $aParams = ['room' => $sRoom];
  2738. if ($iLimit && is_numeric($iLimit)) {
  2739. $limit = (int) $iLimit;
  2740. if ($limit > 0) {
  2741. $sLimit = "LIMIT {$limit}";
  2742. }
  2743. }
  2744. return $this->getAll("SELECT `v`.`{$this->CNF['FJVC_ID']}`,
  2745. `v`.`{$this->CNF['FJVC_LOT_ID']}`,`v`.`{$this->CNF['FJVC_ACTIVE']}`,
  2746. `vt`.`{$this->CNF['FJVCT_ID']}` as `conferance_id`,
  2747. `vt`.`{$this->CNF['FJVCT_START']}`,`vt`.`{$this->CNF['FJVCT_END']}`,
  2748. `vt`. `{$this->CNF['FJVCT_PART']}`, `j`.`{$this->CNF['FIELD_MESSAGE_ID']}` as `jot_id`
  2749. FROM `{$this->CNF['TABLE_JVC']}` as `v`
  2750. INNER JOIN `{$this->CNF['TABLE_JVCT']}` as `vt` ON `v`.`{$this->CNF['FJVC_ID']}`=`vt`.`{$this->CNF['FJVCT_FK']}`
  2751. LEFT JOIN `{$this->CNF['TABLE_MESSAGES']}` as `j` ON `j`.`{$this->CNF['FIELD_MESSAGE_VIDEOC']}` = `vt`.`{$this->CNF['FJVCT_ID']}`
  2752. WHERE `v`.`{$this->CNF['FJVC_ROOM']}`=:room
  2753. ORDER BY `vt`.`{$this->CNF['FJVCT_ID']}` DESC {$sLimit}", $aParams);
  2754. }
  2755. }
  2756. /** @} */