BxTimelineDb.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  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 Timeline Timeline
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. class BxTimelineDb extends BxBaseModNotificationsDb
  12. {
  13. protected $_sTableCache;
  14. protected $_sTableEvent2User;
  15. protected $_sTablesRepostTrack;
  16. protected $_sTableHotTrack;
  17. protected $_aTablesMedia;
  18. protected $_aTablesMedia2Events;
  19. /*
  20. * Constructor.
  21. */
  22. function __construct(&$oConfig)
  23. {
  24. parent::__construct($oConfig);
  25. $this->_sTableCache = $this->_sPrefix . 'cache';
  26. $this->_sTableEvent2User = $this->_sPrefix . 'events2users';
  27. $this->_sTableRepostsTrack = $this->_sPrefix . 'reposts_track';
  28. $this->_sTableHotTrack = $this->_sPrefix . 'hot_track';
  29. $this->_aTablesMedia = array(
  30. BX_TIMELINE_MEDIA_PHOTO => $this->_sPrefix . 'photos',
  31. BX_TIMELINE_MEDIA_VIDEO => $this->_sPrefix . 'videos'
  32. );
  33. $this->_aTablesMedia2Events = array(
  34. BX_TIMELINE_MEDIA_PHOTO => $this->_sPrefix . 'photos2events',
  35. BX_TIMELINE_MEDIA_VIDEO => $this->_sPrefix . 'videos2events'
  36. );
  37. }
  38. public function deleteModuleEvents($aData)
  39. {
  40. foreach($aData['handlers'] as $aHandler) {
  41. //Delete system events.
  42. $this->deleteEvent(array('type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
  43. //Delete reposted events.
  44. $aEvents = $this->getEvents(array('browse' => 'reposted_by_descriptor', 'type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
  45. foreach($aEvents as $aEvent) {
  46. $aContent = unserialize($aEvent['content']);
  47. if(isset($aContent['type']) && $aContent['type'] == $aHandler['alert_unit'] && isset($aContent['action']) && $aContent['action'] == $aHandler['alert_action'])
  48. $this->deleteEvent(array('id' => (int)$aEvent['id']));
  49. }
  50. }
  51. }
  52. public function activateModuleEvents($aData, $bActivate = true)
  53. {
  54. $iActivate = $bActivate ? 1 : 0;
  55. foreach($aData['handlers'] as $aHandler) {
  56. //Activate (deactivate) system events.
  57. $this->updateEvent(array('active' => $iActivate), array('type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
  58. //Activate (deactivate) reposted events.
  59. $aEvents = $this->getEvents(array('browse' => 'reposted_by_descriptor', 'type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
  60. foreach($aEvents as $aEvent) {
  61. $aContent = unserialize($aEvent['content']);
  62. if(isset($aContent['type']) && $aContent['type'] == $aHandler['alert_unit'] && isset($aContent['action']) && $aContent['action'] == $aHandler['alert_action'])
  63. $this->updateEvent(array('active' => $iActivate), array('id' => (int)$aEvent['id']));
  64. }
  65. }
  66. }
  67. public function getMaxDuration($aParams)
  68. {
  69. $aParams['browse'] = 'last';
  70. if(isset($aParams['timeline']))
  71. unset($aParams['timeline']);
  72. $aEvent = $this->getEvents($aParams);
  73. if(empty($aEvent) || !is_array($aEvent))
  74. return 0;
  75. $iNowYear = date('Y', time());
  76. return (int)$aEvent['year'] < $iNowYear ? (int)$aEvent['year'] : 0;
  77. }
  78. //--- Repost related methods ---//
  79. public function insertRepostTrack($iEventId, $iAuthorId, $sAuthorIp, $iRepostedId)
  80. {
  81. $iNow = time();
  82. $iAuthorNip = ip2long($sAuthorIp);
  83. $sQuery = $this->prepare("INSERT INTO `{$this->_sTableRepostsTrack}` SET `event_id` = ?, `author_id` = ?, `author_nip` = ?, `reposted_id` = ?, `date` = ?", $iEventId, $iAuthorId, $iAuthorNip, $iRepostedId, $iNow);
  84. return (int)$this->query($sQuery) > 0;
  85. }
  86. public function deleteRepostTrack($iEventId)
  87. {
  88. $sQuery = $this->prepare("DELETE FROM `{$this->_sTableRepostsTrack}` WHERE `event_id` = ?", $iEventId);
  89. return (int)$this->query($sQuery) > 0;
  90. }
  91. public function updateRepostCounter($iId, $iCounter, $iIncrement = 1)
  92. {
  93. return (int)$this->updateEvent(array('reposts' => (int)$iCounter + $iIncrement), array('id' => $iId)) > 0;
  94. }
  95. public function getReposted($sType, $sAction, $iObjectId)
  96. {
  97. $bSystem = $this->_oConfig->isSystem($sType, $sAction);
  98. if($bSystem)
  99. $aParams = array('browse' => 'descriptor', 'type' => $sType, 'action' => $sAction, 'object_id' => $iObjectId);
  100. else
  101. $aParams = array('browse' => 'id', 'value' => $iObjectId);
  102. $aReposted = $this->getEvents($aParams);
  103. if($bSystem && (empty($aReposted) || !is_array($aReposted))) {
  104. $iOwnerId = 0;
  105. $iDate = 0;
  106. $sStatus = BX_TIMELINE_STATUS_DELETED;
  107. $mixedResult = $this->_oConfig->getSystemDataByDescriptor($sType, $sAction, $iObjectId);
  108. if(is_array($mixedResult)) {
  109. $iOwnerId = !empty($mixedResult['owner_id']) ? (int)$mixedResult['owner_id'] : 0;
  110. $iDate = !empty($mixedResult['date']) ? (int)$mixedResult['date'] : 0;
  111. if($this->_oConfig->isUnhideRestored() && !empty($iOwnerId) && !empty($iDate))
  112. $sStatus = BX_TIMELINE_STATUS_ACTIVE;
  113. }
  114. $iId = $this->insertEvent(array(
  115. 'owner_id' => $iOwnerId,
  116. 'type' => $sType,
  117. 'action' => $sAction,
  118. 'object_id' => $iObjectId,
  119. 'object_privacy_view' => $this->_oConfig->getPrivacyViewDefault('object'),
  120. 'content' => '',
  121. 'title' => '',
  122. 'description' => '',
  123. 'date' => $iDate,
  124. 'status' => $sStatus
  125. ));
  126. $aReposted = $this->getEvents(array('browse' => 'id', 'value' => $iId));
  127. }
  128. return $aReposted;
  129. }
  130. function getRepostedBy($iRepostedId)
  131. {
  132. $sQuery = $this->prepare("SELECT `author_id` FROM `{$this->_sTableRepostsTrack}` WHERE `reposted_id`=?", $iRepostedId);
  133. return $this->getColumn($sQuery);
  134. }
  135. function isReposted($iRepostedId, $iOwnerId, $iAuthorId)
  136. {
  137. $sQuery = $this->prepare("SELECT
  138. `te`.`id`
  139. FROM `{$this->_sTableRepostsTrack}` AS `tst`
  140. LEFT JOIN `{$this->_sTable}` AS `te` ON `tst`.`event_id`=`te`.`id`
  141. WHERE `tst`.`author_id`=? AND `tst`.`reposted_id`=? AND `te`.`owner_id`=?", $iAuthorId, $iRepostedId, $iOwnerId);
  142. return (int)$this->getOne($sQuery) > 0;
  143. }
  144. //--- Photo uploader related methods ---//
  145. public function saveMedia($sType, $iEventId, $iItemId)
  146. {
  147. $sTable = $this->_aTablesMedia2Events[$sType];
  148. $sQuery = $this->prepare("INSERT INTO `" . $sTable . "` SET `event_id`=?, `media_id`=?", $iEventId, $iItemId);
  149. return (int)$this->query($sQuery) > 0;
  150. }
  151. public function deleteMedia($sType, $iEventId)
  152. {
  153. $sTable = $this->_aTablesMedia2Events[$sType];
  154. $sQuery = $this->prepare("DELETE FROM `" . $sTable . "` WHERE `event_id` = ?", $iEventId);
  155. return (int)$this->query($sQuery) > 0;
  156. }
  157. public function getMedia($sType, $iEventId, $iOffset = 0)
  158. {
  159. $sTableMedia = $this->_aTablesMedia[$sType];
  160. $sTableMedia2Events = $this->_aTablesMedia2Events[$sType];
  161. $sLimitAddon = '';
  162. if($iOffset != 0)
  163. $sLimitAddon = $this->prepareAsString(" OFFSET ?", $iOffset);
  164. $sQuery = $this->prepare("SELECT
  165. `tme`.`media_id` AS `id`
  166. FROM `" . $sTableMedia2Events . "` AS `tme`
  167. LEFT JOIN `" . $sTableMedia . "` AS `tm` ON `tme`.`media_id`=`tm`.`id`
  168. WHERE `tme`.`event_id`=?" . $sLimitAddon, $iEventId);
  169. return $this->getColumn($sQuery);
  170. }
  171. //--- Link attach related methods ---//
  172. public function getUnusedLinks($iUserId, $iLinkId = 0)
  173. {
  174. $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
  175. $aMethod['params'][1] = array(
  176. 'profile_id' => $iUserId
  177. );
  178. $sWhereAddon = '';
  179. if(!empty($iLinkId)) {
  180. $aMethod['name'] = 'getRow';
  181. $aMethod['params'][1]['id'] = $iLinkId;
  182. $sWhereAddon = " AND `tl`.`id`=:id";
  183. }
  184. $aMethod['params'][0] = "SELECT
  185. `tl`.`id` AS `id`,
  186. `tl`.`profile_id` AS `profile_id`,
  187. `tl`.`media_id` AS `media_id`,
  188. `tl`.`url` AS `url`,
  189. `tl`.`title` AS `title`,
  190. `tl`.`text` AS `text`,
  191. `tl`.`added` AS `added`
  192. FROM `" . $this->_sPrefix . "links` AS `tl`
  193. LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id`
  194. WHERE `tl`.`profile_id`=:profile_id AND ISNULL(`tle`.`event_id`)" . $sWhereAddon . "
  195. ORDER BY `tl`.`added` DESC";
  196. return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);;
  197. }
  198. public function deleteUnusedLinks($iUserId, $iLinkId = 0)
  199. {
  200. $aBindings = array(
  201. 'profile_id' => $iUserId
  202. );
  203. $sWhereAddon = '';
  204. if(!empty($iLinkId)) {
  205. $aBindings['id'] = $iLinkId;
  206. $sWhereAddon = " AND `id`=:id";
  207. }
  208. return $this->query("DELETE FROM `" . $this->_sPrefix . "links` WHERE `profile_id`=:profile_id" . $sWhereAddon, $aBindings);
  209. }
  210. public function saveLink($iEventId, $iLinkId)
  211. {
  212. $sQuery = $this->prepare("INSERT INTO `" . $this->_sPrefix . "links2events` SET `event_id`=?, `link_id`=?", $iEventId, $iLinkId);
  213. return (int)$this->query($sQuery) > 0;
  214. }
  215. public function deleteLinks($iEventId)
  216. {
  217. $sQuery = $this->prepare("DELETE FROM `tl`, `tle` USING `" . $this->_sPrefix . "links` AS `tl` LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id` WHERE `tle`.`event_id` = ?", $iEventId);
  218. return (int)$this->query($sQuery) > 0;
  219. }
  220. public function getLinks($iEventId)
  221. {
  222. $sQuery = $this->prepare("SELECT
  223. `tl`.`id` AS `id`,
  224. `tl`.`profile_id` AS `profile_id`,
  225. `tl`.`media_id` AS `media_id`,
  226. `tl`.`url` AS `url`,
  227. `tl`.`title` AS `title`,
  228. `tl`.`text` AS `text`,
  229. `tl`.`added` AS `added`
  230. FROM `" . $this->_sPrefix . "links` AS `tl`
  231. LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id`
  232. WHERE `tle`.`event_id`=?", $iEventId);
  233. return $this->getAll($sQuery);
  234. }
  235. public function getHot()
  236. {
  237. return $this->getColumn("SELECT `event_id` FROM `" . $this->_sTableHotTrack . "`");
  238. }
  239. public function clearHot()
  240. {
  241. return $this->query("TRUNCATE TABLE `" . $this->_sTableHotTrack . "`");
  242. }
  243. public function getHotTrackByDate($iInterval = 24)
  244. {
  245. $sQuery = "SELECT
  246. `te`.`id` AS `event_id`,
  247. `te`.`date` AS `value`
  248. FROM `" . $this->_sTable . "` AS `te`
  249. WHERE `te`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)";
  250. return $this->getPairs($sQuery, 'event_id', 'value', array('interval' => $iInterval));
  251. }
  252. public function getHotTrackByCommentsDate($sModule, $sTableTrack, $iInterval = 24)
  253. {
  254. $sQuery = "SELECT
  255. `te`.`id` as `event_id`,
  256. MAX(`tt`.`cmt_time`) AS `value`
  257. FROM `" . $this->_sTable . "` AS `te`
  258. INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`id`=`tt`.`cmt_object_id` AND `te`.`type`=:module
  259. WHERE `tt`.`cmt_time` > (UNIX_TIMESTAMP() - 3600 * :interval)
  260. GROUP BY `te`.`id`";
  261. return $this->getPairs($sQuery, 'event_id', 'value', array('module' => $sModule, 'interval' => $iInterval));
  262. }
  263. public function getHotTrackByCommentsDateModule($sModule, $sTableTrack, $iInterval = 24)
  264. {
  265. $sQuery = "SELECT
  266. `te`.`id` as `event_id`,
  267. MAX(`tt`.`cmt_time`) AS `value`
  268. FROM `" . $this->_sTable . "` AS `te`
  269. INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`object_id`=`tt`.`cmt_object_id` AND `te`.`type`=:module
  270. WHERE `tt`.`cmt_time` > (UNIX_TIMESTAMP() - 3600 * :interval)
  271. GROUP BY `te`.`object_id`";
  272. return $this->getPairs($sQuery, 'event_id', 'value', array('module' => $sModule, 'interval' => $iInterval));
  273. }
  274. public function getHotTrackByVotesDate($sModule, $sTableTrack, $iInterval = 24)
  275. {
  276. $sQuery = "SELECT
  277. `te`.`id` as `event_id`,
  278. MAX(`tt`.`date`) AS `value`
  279. FROM `" . $this->_sTable . "` AS `te`
  280. INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`id`=`tt`.`object_id` AND `te`.`type`=:module
  281. WHERE `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)
  282. GROUP BY `te`.`id`";
  283. return $this->getPairs($sQuery, 'event_id', 'value', array('module' => $sModule, 'interval' => $iInterval));
  284. }
  285. public function getHotTrackByVotesDateModule($sModule, $sTableTrack, $iInterval = 24)
  286. {
  287. $sQuery = "SELECT
  288. `te`.`id` as `event_id`,
  289. MAX(`tt`.`date`) AS `value`
  290. FROM `" . $this->_sTable . "` AS `te`
  291. INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`object_id`=`tt`.`object_id` AND `te`.`type`=:module
  292. WHERE `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)
  293. GROUP BY `te`.`object_id`";
  294. return $this->getPairs($sQuery, 'event_id', 'value', array('module' => $sModule, 'interval' => $iInterval));
  295. }
  296. /**
  297. * Hot Track by Sum of Votes during specified Period is currently disabled.
  298. */
  299. public function getHotTrackByVotesSum($sModule, $sTableTrack, $iInterval = 24)
  300. {
  301. $sQuery = "SELECT
  302. `te`.`id` as `event_id`,
  303. SUM(`tt`.`value`) AS `value`
  304. FROM `" . $this->_sTable . "` AS `te`
  305. INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`id`=`tt`.`object_id` AND `te`.`type`=:module
  306. WHERE `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)
  307. GROUP BY `te`.`id`";
  308. return $this->getAll($sQuery, array('module' => $sModule, 'interval' => $iInterval));
  309. }
  310. /**
  311. * Hot Track by Sum of Votes during specified Period is currently disabled.
  312. */
  313. public function getHotTrackByVotesSumModule($sModule, $sTableTrack, $iInterval = 24)
  314. {
  315. $sQuery = "SELECT
  316. `te`.`id` as `event_id`,
  317. SUM(`tt`.`value`) AS `value`
  318. FROM `" . $this->_sTable . "` AS `te`
  319. INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`object_id`=`tt`.`object_id` AND `te`.`type`=:module
  320. WHERE `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)
  321. GROUP BY `te`.`object_id`";
  322. return $this->getAll($sQuery, array('module' => $sModule, 'interval' => $iInterval));
  323. }
  324. public function updateHotTrack($aTrack)
  325. {
  326. return (int)$this->query("REPLACE INTO `" . $this->_sTableHotTrack . "` SET " . $this->arrayToSQL($aTrack)) > 0;
  327. }
  328. public function insertCache($aParamsSet)
  329. {
  330. if(empty($aParamsSet))
  331. return false;
  332. return (int)$this->query("REPLACE INTO `{$this->_sTableCache}` SET " . $this->arrayToSQL($aParamsSet)) > 0;
  333. }
  334. public function deleteCache($aParamsWhere)
  335. {
  336. if(empty($aParamsWhere))
  337. return false;
  338. return (int)$this->query("DELETE FROM `{$this->_sTableCache}` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
  339. }
  340. public function clearCache()
  341. {
  342. return (int)$this->query("DELETE FROM `{$this->_sTableCache}` WHERE 1") > 0;
  343. }
  344. public function getCache($aParams)
  345. {
  346. $CNF = &$this->_oConfig->CNF;
  347. $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
  348. $sFieldsClause = '*';
  349. $sWhereClause = $sLimitClause = '';
  350. if(isset($aParams['start']) && !empty($aParams['per_page']))
  351. $sLimitClause = $aParams['start'] . ", " . $aParams['per_page'];
  352. switch($aParams['browse']) {
  353. case 'list': // by type + owner profile (context) + viewer profile
  354. $aMethod['name'] = 'getAllWithKey';
  355. $aMethod['params'][1] = 'event_id';
  356. $aMethod['params'][2] = array(
  357. 'type' => $aParams['type'],
  358. 'context_id' => $aParams['context_id'],
  359. 'profile_id' => $aParams['profile_id']
  360. );
  361. //--- Apply custom check depending on Type
  362. switch($aParams['type']) {
  363. case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
  364. $aMethod['params'][2]['context_id'] = 0;
  365. break;
  366. case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
  367. $aMethod['params'][2]['context_id'] = $aParams['profile_id'];
  368. break;
  369. }
  370. $sWhereClause .= " AND `type`=:type AND `context_id`=:context_id AND `profile_id`=:profile_id";
  371. break;
  372. }
  373. $sLimitClause = $sLimitClause ? "LIMIT " . $sLimitClause : "";
  374. $aMethod['params'][0] = "SELECT " . $sFieldsClause . "
  375. FROM `{$this->_sTableCache}`
  376. WHERE 1" . $sWhereClause . " ORDER BY `date` DESC " . $sLimitClause;
  377. return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
  378. }
  379. public function publish()
  380. {
  381. $CNF = $this->_oConfig->CNF;
  382. $aEvents = $this->getAll("SELECT `" . $CNF['FIELD_ID'] . "`, `" . $CNF['FIELD_DATE'] . "` FROM `" . $this->_sTable . "` WHERE `" . $CNF['FIELD_STATUS'] . "`='" . BX_TIMELINE_STATUS_AWAITING . "'");
  383. if(empty($aEvents) || !is_array($aEvents))
  384. return false;
  385. $iNow = time();
  386. $aResult = array();
  387. foreach($aEvents as $aEvent)
  388. if($aEvent[$CNF['FIELD_DATE']] <= $iNow)
  389. $aResult[] = $aEvent[$CNF['FIELD_ID']];
  390. return count($aResult) == (int)$this->query("UPDATE `" . $this->_sTable . "` SET `" . $CNF['FIELD_STATUS'] . "`='" . BX_TIMELINE_STATUS_ACTIVE . "' WHERE `id` IN (" . $this->implode_escape($aResult) . ")") ? $aResult : false;
  391. }
  392. protected function _getFilterAddon($iOwnerId, $sFilter)
  393. {
  394. switch($sFilter) {
  395. /**
  396. * Direct posts in Timeline made by a timeline owner ($iOwnerId)
  397. */
  398. case BX_TIMELINE_FILTER_OWNER:
  399. $sFilterAddon = $this->prepareAsString(" AND `{$this->_sTable}`.`action`='' AND `{$this->_sTable}`.`object_id`=? ", $iOwnerId);
  400. break;
  401. /**
  402. * Direct posts in Timeline made by users except a timeline owner ($iOwnerId)
  403. */
  404. case BX_TIMELINE_FILTER_OTHER:
  405. $sFilterAddon = $this->prepareAsString(" AND `{$this->_sTable}`.`action`='' AND `{$this->_sTable}`.`object_id`<>? ", $iOwnerId);
  406. break;
  407. /**
  408. * All (Direct and System) posts in Timeline (owned by $iOwnerId) made by users except the viewer
  409. */
  410. case BX_TIMELINE_FILTER_OTHER_VIEWER:
  411. $sFilterAddon = $this->prepareAsString(" AND (`{$this->_sTable}`.`action`<>'' OR (`{$this->_sTable}`.`action`='' AND `{$this->_sTable}`.`object_id`<>?)) ", bx_get_logged_profile_id());
  412. break;
  413. case BX_TIMELINE_FILTER_ALL:
  414. default:
  415. $sFilterAddon = "";
  416. }
  417. return $sFilterAddon;
  418. }
  419. protected function _getSqlPartsEvents($aParams)
  420. {
  421. $sMethod = 'getAll';
  422. $sSelectClause = "`{$this->_sTable}`.*";
  423. $sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
  424. switch($aParams['browse']) {
  425. case 'owner_id':
  426. $sWhereClause = $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`=? ", $aParams['value']);
  427. break;
  428. case 'common_by_object':
  429. $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
  430. $sWhereClause = $this->prepareAsString("AND SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ")='" . $sCommonPostPrefix . "' AND `{$this->_sTable}`.`object_id`=? ", $aParams['value']);
  431. break;
  432. case 'descriptor':
  433. $sMethod = 'getRow';
  434. $sWhereClause = "";
  435. if(isset($aParams['type']))
  436. $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`type`=? ", $aParams['type']);
  437. if(isset($aParams['action']))
  438. $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`action`=? ", $aParams['action']);
  439. if(isset($aParams['object_id']))
  440. $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`object_id`=? ", $aParams['object_id']);
  441. $sLimitClause = "LIMIT 1";
  442. break;
  443. case 'reposted_by_descriptor':
  444. $sWhereClause = "";
  445. if(isset($aParams['type']))
  446. $sWhereClause .= "AND `{$this->_sTable}`.`content` LIKE " . $this->escape('%' . $aParams['type'] . '%');
  447. if(isset($aParams['action']))
  448. $sWhereClause .= "AND `{$this->_sTable}`.`content` LIKE " . $this->escape('%' . $aParams['action'] . '%');
  449. break;
  450. case 'list':
  451. list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
  452. if(in_array($aParams['type'], array(BX_BASE_MOD_NTFS_TYPE_CONNECTIONS, BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS)))
  453. $sSelectClause = "DISTINCT " . $sSelectClause;
  454. break;
  455. case 'ids':
  456. $sWhereClause = "AND `{$this->_sTable}`.`id` IN (" . $this->implode_escape($aParams['ids']) . ") ";
  457. break;
  458. default:
  459. list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
  460. }
  461. $sSelectClause .= ", DAYOFYEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `days`, DAYOFYEAR(NOW()) AS `today`, ROUND((UNIX_TIMESTAMP() - `{$this->_sTable}`.`date`)/86400) AS `ago_days`, YEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `year`";
  462. if(in_array($aParams['browse'], array('list', 'ids'))) {
  463. $sOrderClause = "";
  464. switch($aParams['type']) {
  465. case BX_TIMELINE_TYPE_HOT:
  466. $sOrderClause = "`{$this->_sTableHotTrack}`.`value` DESC, ";
  467. break;
  468. case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
  469. case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
  470. case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
  471. $sOrderClause = "`{$this->_sTable}`.`sticked` DESC, ";
  472. break;
  473. case BX_BASE_MOD_NTFS_TYPE_OWNER:
  474. $sOrderClause = "`{$this->_sTable}`.`pinned` DESC, ";
  475. break;
  476. }
  477. $sOrderClause = "ORDER BY " . $sOrderClause . "`{$this->_sTable}`.`date` DESC";
  478. }
  479. if(isset($aParams['count']) && $aParams['count'] === true) {
  480. $sMethod = 'getOne';
  481. $sSelectClause = "COUNT(`{$this->_sTable}`.`id`)";
  482. $sLimitClause = "";
  483. }
  484. $aAlertParams = $aParams;
  485. unset($aAlertParams['browse']);
  486. bx_alert($this->_oConfig->getName(), 'get_events', 0, 0, array(
  487. 'browse' => $aParams['browse'],
  488. 'params' => $aAlertParams,
  489. 'table' => $this->_sTable,
  490. 'method' => &$sMethod,
  491. 'select_clause' => &$sSelectClause,
  492. 'join_clause' => &$sJoinClause,
  493. 'where_clause' => &$sWhereClause,
  494. 'order_clause' => &$sOrderClause,
  495. 'limit_clause' => &$sLimitClause
  496. ));
  497. return array($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause);
  498. }
  499. protected function _getSqlPartsEventsList($aParams)
  500. {
  501. $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
  502. $sJoinClause = $sWhereClause = "";
  503. $sWhereClauseStatus = "AND `{$this->_sTable}`.`active`='1' ";
  504. $sWhereClauseStatus .= $this->prepareAsString("AND `{$this->_sTable}`.`status`=? ", isset($aParams['status']) ? $aParams['status'] : BX_TIMELINE_STATUS_ACTIVE);
  505. //--- Apply filter
  506. $sWhereClauseFilter = "";
  507. if(isset($aParams['filter']))
  508. $sWhereClauseFilter = $this->_getFilterAddon($aParams['owner_id'], $aParams['filter']);
  509. //--- Apply timeline
  510. $sWhereClauseTimeline = "";
  511. if(isset($aParams['timeline']) && !empty($aParams['timeline']))
  512. $sWhereClauseTimeline = $this->prepareAsString("AND `date`<=? ", mktime(23, 59, 59, 12, 31, (int)$aParams['timeline']));
  513. //--- Apply modules or handlers filter
  514. $sWhereClauseModules = "";
  515. if(!empty($aParams['modules']) && is_array($aParams['modules']))
  516. $sWhereClauseModules = "AND `" . $this->_sTable . "`.`type` IN (" . $this->implode_escape($aParams['modules']) . ") ";
  517. $sWhereClauseHidden = "";
  518. if(empty($sWhereClauseModules)) {
  519. $aHidden = $this->_oConfig->getHandlersHidden();
  520. $sWhereClauseHidden = !empty($aHidden) && is_array($aHidden) ? "AND `" . $this->_sTableHandlers . "`.`id` NOT IN (" . $this->implode_escape($aHidden) . ") " : "";
  521. }
  522. //--- Apply unpublished (date in future) filter
  523. $sWhereClauseUnpublished = $this->prepareAsString("AND IF(SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "' AND `{$this->_sTable}`.`object_id` = ?, 1, `{$this->_sTable}`.`date` <= UNIX_TIMESTAMP()) ", bx_get_logged_profile_id());
  524. //--- Check type
  525. $sWhereSubclause = "";
  526. switch($aParams['type']) {
  527. case BX_TIMELINE_TYPE_HOT: //--- Hot (Public) Feed.
  528. $sJoinClause .= " INNER JOIN `{$this->_sTableHotTrack}` ON `{$this->_sTable}`.`id`=`{$this->_sTableHotTrack}`.`event_id`";
  529. case BX_BASE_MOD_NTFS_TYPE_PUBLIC: //--- Site (Public) Feed.
  530. //--- Apply privacy filter
  531. $aPrivacyGroups = array(BX_DOL_PG_ALL);
  532. if(isLogged())
  533. $aPrivacyGroups[] = BX_DOL_PG_MEMBERS;
  534. $aQueryParts = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'))->getContentByGroupAsSQLPart($aPrivacyGroups);
  535. $sWhereClause .= $aQueryParts['where'] . " ";
  536. if($this->_oConfig->isShowAll())
  537. break;
  538. //--- Select All System posts
  539. $sWhereSubclause = "SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ") <> '" . $sCommonPostPrefix . "'";
  540. //--- Select Public (Direct) posts created on Home Page Timeline (Public Feed)
  541. $sWhereSubclause .= $this->prepareAsString(" OR `{$this->_sTable}`.`owner_id`=?", 0);
  542. //--- Select Promoted posts.
  543. $sWhereSubclause .= " OR `{$this->_sTable}`.`promoted` <> '0'";
  544. break;
  545. //--- Profile Feed
  546. case BX_BASE_MOD_NTFS_TYPE_OWNER:
  547. if(empty($aParams['owner_id']))
  548. break;
  549. //--- Select Own (System and Direct) posts from Profile's Timeline.
  550. $sWhereSubclause = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = ?)", $aParams['owner_id']);
  551. //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
  552. $sWhereSubclause .= $this->prepareAsString(" OR (`{$this->_sTable}`.`owner_id` = '0' AND IF(SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "', `{$this->_sTable}`.`object_id` = ?, 1))", $aParams['owner_id']);
  553. break;
  554. //--- Profile Connections Feed
  555. case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
  556. if(empty($aParams['owner_id']))
  557. break;
  558. $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
  559. $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
  560. $aJoin1 = $aQueryParts['join'];
  561. $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'object_id', $aParams['owner_id']);
  562. $aJoin2 = $aQueryParts['join'];
  563. //--- Join System and Direct posts made by following members.
  564. $sJoinClause .= " " . $aJoin1['type'] . " JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON ((" . $aJoin1['condition'] . ") OR (SUBSTRING(`" . $this->_sTable . "`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "' AND " . $aJoin2['condition'] . "))";
  565. //--- Exclude Own (Direct) posts on timelines of following members.
  566. //--- Note. Disabled for now.
  567. //$sWhereSubclause = $this->prepareAsString("IF(SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "', `{$this->_sTable}`.`object_id` <> ?, 1)", $aParams['owner_id']);
  568. $sWhereSubclause = "0";
  569. //--- Select Promoted posts.
  570. $sWhereSubclause .= " OR `{$this->_sTable}`.`promoted` <> '0'";
  571. break;
  572. //--- Profile + Profile Connections Feed
  573. case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
  574. if(empty($aParams['owner_id']))
  575. break;
  576. $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
  577. $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
  578. $aJoin1 = $aQueryParts['join'];
  579. $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'object_id', $aParams['owner_id']);
  580. $aJoin2 = $aQueryParts['join'];
  581. $aJoin2['table_alias'] = 'cc';
  582. $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
  583. //--- Join System and Direct posts made by following members. 'LEFT' join is essential to apply different conditions.
  584. $sJoinClause .= " LEFT JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
  585. $sJoinClause .= " LEFT JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON SUBSTRING(`" . $this->_sTable . "`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "' AND " . $aJoin2['condition'];
  586. //--- Select Own (System and Direct) posts from Profile's Timeline.
  587. $sWhereSubclause = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = ?)", $aParams['owner_id']);
  588. //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
  589. $sWhereSubclause .= $this->prepareAsString(" OR (`{$this->_sTable}`.`owner_id` = '0' AND IF(SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "', `{$this->_sTable}`.`object_id` = ?, 1))", $aParams['owner_id']);
  590. //--- Exclude Own (Direct) posts on timelines of following members.
  591. //--- Note. Disabled for now and next check is used instead.
  592. //$sWhereSubclause .= $this->prepareAsString(" OR (NOT ISNULL(`c`.`content`) AND IF(SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ") = '" . $sCommonPostPrefix . "', `{$this->_sTable}`.`object_id` <> ?, 1))", $aParams['owner_id']);
  593. //--- All posts on timelines of following members.
  594. $sWhereSubclause .= " OR NOT ISNULL(`" . $aJoin1['table_alias'] . "`.`content`) OR NOT ISNULL(`" . $aJoin2['table_alias'] . "`.`content`)";
  595. //--- Select Promoted posts.
  596. $sWhereSubclause .= " OR `{$this->_sTable}`.`promoted` <> '0'";
  597. break;
  598. }
  599. $aAlertParams = $aParams;
  600. unset($aAlertParams['type'], $aAlertParams['owner_id']);
  601. bx_alert($this->_oConfig->getName(), 'get_list_by_type', 0, 0, array(
  602. 'type' => $aParams['type'],
  603. 'owner_id' => $aParams['owner_id'],
  604. 'params' => $aAlertParams,
  605. 'table' => $this->_sTable,
  606. 'join_clause' => &$sJoinClause,
  607. 'where_clause' => &$sWhereClause,
  608. 'where_clause_status' => &$sWhereClauseStatus,
  609. 'where_clause_filter' => &$sWhereClauseFilter,
  610. 'where_clause_timeline' => &$sWhereClauseTimeline,
  611. 'where_clause_modules' => &$sWhereClauseModules,
  612. 'where_clause_hidden' => &$sWhereClauseHidden,
  613. 'where_clause_unpublished' => &$sWhereClauseUnpublished,
  614. 'where_subclause' => &$sWhereSubclause
  615. ));
  616. $sWhereClause .= $sWhereClauseStatus;
  617. $sWhereClause .= $sWhereClauseFilter;
  618. $sWhereClause .= $sWhereClauseTimeline;
  619. $sWhereClause .= $sWhereClauseModules;
  620. $sWhereClause .= $sWhereClauseHidden;
  621. $sWhereClause .= $sWhereClauseUnpublished;
  622. if(!empty($sWhereSubclause))
  623. $sWhereClause .= "AND (" . $sWhereSubclause . ") ";
  624. return array($sJoinClause, $sWhereClause);
  625. }
  626. function updateSimilarObject($iId, &$oAlert, $sDuration = 'day')
  627. {
  628. $sType = $oAlert->sUnit;
  629. $sAction = $oAlert->sAction;
  630. //Check handler
  631. $aHandler = $this->_oConfig->getHandlers($sType . '_' . $sAction);
  632. if(empty($aHandler) || !is_array($aHandler) || (int)$aHandler['groupable'] != 1)
  633. return false;
  634. //Check content's extra values
  635. if(isset($aHandler['group_by']) && !empty($aHandler['group_by']) && (!isset($oAlert->aExtras[$aHandler['group_by']]) || empty($oAlert->aExtras[$aHandler['group_by']])))
  636. return false;
  637. $aBindings = array(
  638. 'object_id' => $oAlert->iObject,
  639. 'id' => $iId,
  640. 'owner_id' => $oAlert->iSender,
  641. 'type' => $sType,
  642. 'action' => $sAction
  643. );
  644. $sWhereClause = "";
  645. switch($sDuration) {
  646. case 'day':
  647. $aBindings['day_start'] = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
  648. $aBindings['day_end'] = mktime(23, 59, 59, date('m'), date('d'), date('Y'));
  649. $sWhereClause .= "AND `date`>:day_start AND `date`<:day_end ";
  650. break;
  651. }
  652. if(isset($aHandler['group_by'])) {
  653. $aBindings['content'] = '%' . $oAlert->aExtras[$aHandler['group_by']] . '%';
  654. $sWhereClause .= "AND `content` LIKE :content ";
  655. }
  656. $sSql = "UPDATE `{$this->_sTable}`
  657. SET
  658. `object_id`=CONCAT(`object_id`, ',:object_id'),
  659. `title`='',
  660. `description`='',
  661. `date`=UNIX_TIMESTAMP()
  662. WHERE
  663. `id`<>:id AND
  664. `owner_id`=:owner_id AND
  665. `type`=:type AND
  666. `action`=:action " . $sWhereClause;
  667. $mixedResult = $this->query($sSql, $aBindings);
  668. if((int)$mixedResult > 0)
  669. $this->deleteEvent(array('id' => $iId));
  670. return $mixedResult;
  671. }
  672. }
  673. /** @} */