BxBaseModGroupsModule.php 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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 BaseGroups Base classes for groups modules
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. define('BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR', 1);
  12. define('BX_BASE_MOD_GROUPS_ROLE_MODERATOR', 2);
  13. define('BX_BASE_MOD_GROUPS_ACTION_EDIT', 'edit');
  14. define('BX_BASE_MOD_GROUPS_ACTION_CHANGE_COVER', 'change_cover');
  15. define('BX_BASE_MOD_GROUPS_ACTION_INVITE', 'invite');
  16. define('BX_BASE_MOD_GROUPS_ACTION_MANAGE_FANS', 'manage_fans');
  17. define('BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES', 'manage_roles');
  18. define('BX_BASE_MOD_GROUPS_ACTION_DELETE', 'delete');
  19. /**
  20. * Groups profiles module.
  21. */
  22. class BxBaseModGroupsModule extends BxBaseModProfileModule
  23. {
  24. function __construct(&$aModule)
  25. {
  26. parent::__construct($aModule);
  27. }
  28. /**
  29. * Get possible recipients for start conversation form
  30. */
  31. public function actionAjaxGetInitialMembers ()
  32. {
  33. $sTerm = bx_get('term');
  34. $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
  35. header('Content-Type:text/javascript; charset=utf-8');
  36. echo(json_encode($a));
  37. }
  38. /**
  39. * Process Process Invitation
  40. */
  41. public function actionProcessInvite ($sKey, $iGroupProfileId, $bAccept)
  42. {
  43. $aData = $this->_oDb->getInviteByKey($sKey, $iGroupProfileId);
  44. if (isset($aData['invited_profile_id'])){
  45. $CNF = &$this->_oConfig->CNF;
  46. if (!isset($CNF['OBJECT_CONNECTIONS']) || !($oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTIONS'])))
  47. return '';
  48. $iInvitedProfileId = $aData['invited_profile_id'];
  49. if ($iInvitedProfileId != bx_get_logged_profile_id())
  50. return '';
  51. if ($bAccept){
  52. if($oConnection && !$oConnection->isConnected($iInvitedProfileId, $iGroupProfileId)){
  53. $oConnection->addConnection($iInvitedProfileId, $iGroupProfileId);
  54. $oConnection->addConnection($iGroupProfileId, $iInvitedProfileId);
  55. }
  56. }
  57. $this->_oDb->deleteInviteByKey($sKey, $iGroupProfileId);
  58. }
  59. }
  60. public function serviceGetSearchResultUnit ($iContentId, $sUnitTemplate = '')
  61. {
  62. if(empty($sUnitTemplate))
  63. $sUnitTemplate = 'unit.html';
  64. return parent::serviceGetSearchResultUnit($iContentId, $sUnitTemplate);
  65. }
  66. /**
  67. * @see BxBaseModProfileModule::serviceGetSpaceTitle
  68. */
  69. public function serviceGetSpaceTitle()
  70. {
  71. return _t($this->_oConfig->CNF['T']['txt_sample_single']);
  72. }
  73. /**
  74. * @see iBxDolProfileService::serviceGetParticipatingProfiles
  75. */
  76. public function serviceGetParticipatingProfiles($iProfileId, $aConnectionObjects = false)
  77. {
  78. if (isset($this->_oConfig->CNF['OBJECT_CONNECTIONS'])){
  79. $aConnectionObjects = array($this->_oConfig->CNF['OBJECT_CONNECTIONS'], 'sys_profiles_subscriptions');
  80. return parent::serviceGetParticipatingProfiles($iProfileId, $aConnectionObjects);
  81. }
  82. return parent::serviceGetParticipatingProfiles($iProfileId);
  83. }
  84. /**
  85. * Check if this module entry can be used as profile
  86. */
  87. public function serviceActAsProfile ()
  88. {
  89. return false;
  90. }
  91. /**
  92. * Check if this module is group profile
  93. */
  94. public function serviceIsGroupProfile ()
  95. {
  96. return true;
  97. }
  98. /**
  99. * check if provided profile is member of the group
  100. */
  101. public function serviceIsFan ($iGroupProfileId, $iProfileId = false)
  102. {
  103. $oGroupProfile = BxDolProfile::getInstance($iGroupProfileId);
  104. return $this->isFan($oGroupProfile->getContentId(), $iProfileId);
  105. }
  106. /**
  107. * check if provided profile is admin of the group
  108. */
  109. public function serviceIsAdmin ($iGroupProfileId, $iProfileId = false)
  110. {
  111. if(!$iProfileId)
  112. $iProfileId = bx_get_logged_profile_id();
  113. $oGroupProfile = BxDolProfile::getInstance($iGroupProfileId);
  114. $iGroupContentId = $oGroupProfile->getContentId();
  115. if(!$this->isFan($iGroupContentId, $iProfileId))
  116. return false;
  117. $aGroupContentInfo = $this->_oDb->getContentInfoById($iGroupContentId);
  118. return $this->_oDb->isAdmin($iGroupProfileId, $iProfileId, $aGroupContentInfo);
  119. }
  120. public function serviceGetAdminRole($iGroupProfileId, $iProfileId = false)
  121. {
  122. if(!$iProfileId)
  123. $iProfileId = bx_get_logged_profile_id();
  124. if(!$this->serviceIsAdmin($iGroupProfileId, $iProfileId))
  125. return 0;
  126. return $this->_oDb->getRole($iGroupProfileId, $iProfileId);
  127. }
  128. /**
  129. * Delete profile from fans and admins tables
  130. * @param $iProfileId profile id
  131. */
  132. public function serviceDeleteProfileFromFansAndAdmins ($iProfileId)
  133. {
  134. $CNF = &$this->_oConfig->CNF;
  135. $this->_oDb->deleteAdminsByProfileId($iProfileId);
  136. if (isset($CNF['OBJECT_CONNECTIONS']) && ($oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTIONS'])))
  137. $oConnection->onDeleteInitiatorAndContent($iProfileId);
  138. }
  139. /**
  140. * Reset group's author for particular group
  141. * @param $iContentId group id
  142. * @return false of error, or number of updated records on success
  143. */
  144. public function serviceReassignEntityAuthor ($iContentId)
  145. {
  146. $aContentInfo = $this->_oDb->getContentInfoById((int)$iContentId);
  147. if (!$aContentInfo)
  148. return false;
  149. if (!($oGroupProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $this->getName())))
  150. return false;
  151. $aAdmins = $this->_oDb->getAdmins($oGroupProfile->id());
  152. return $this->_oDb->updateAuthorById($iContentId, $aAdmins ? array_pop($aAdmins) : 0);
  153. }
  154. /**
  155. * Entry actions and social sharing block
  156. */
  157. public function serviceEntityAllActions ($mixedContent = false, $aParams = array())
  158. {
  159. $CNF = &$this->_oConfig->CNF;
  160. if(!empty($mixedContent)) {
  161. if(!is_array($mixedContent))
  162. $mixedContent = array((int)$mixedContent, (method_exists($this->_oDb, 'getContentInfoById')) ? $this->_oDb->getContentInfoById((int)$mixedContent) : array());
  163. }
  164. else {
  165. $mixedContent = $this->_getContent();
  166. if($mixedContent === false)
  167. return false;
  168. }
  169. list($iContentId, $aContentInfo) = $mixedContent;
  170. if(!empty($CNF['FIELD_PICTURE']) && !empty($aContentInfo[$CNF['FIELD_PICTURE']]))
  171. $aParams = array_merge(array(
  172. 'entry_thumb' => (int)$aContentInfo[$CNF['FIELD_PICTURE']]
  173. ), $aParams);
  174. return parent::serviceEntityAllActions ($mixedContent, $aParams);
  175. }
  176. /**
  177. * Reset group's author when author profile is deleted
  178. * @param $iProfileId profile id
  179. * @return number of changed items
  180. */
  181. public function serviceReassignEntitiesByAuthor ($iProfileId)
  182. {
  183. $a = $this->_oDb->getEntriesByAuthor((int)$iProfileId);
  184. if (!$a)
  185. return 0;
  186. $iCount = 0;
  187. foreach ($a as $aContentInfo)
  188. $iCount += ('' == $this->serviceReassignEntityAuthor($aContentInfo[$this->_oConfig->CNF['FIELD_ID']]) ? 1 : 0);
  189. return $iCount;
  190. }
  191. public function servicePrepareFields ($aFieldsProfile)
  192. {
  193. $CNF = &$this->_oConfig->CNF;
  194. $aFieldsProfile[$CNF['FIELD_NAME']] = $aFieldsProfile['name'];
  195. $aFieldsProfile[$CNF['FIELD_TEXT']] = isset($aFieldsProfile['description']) ? $aFieldsProfile['description'] : '';
  196. unset($aFieldsProfile['name']);
  197. unset($aFieldsProfile['description']);
  198. return $aFieldsProfile;
  199. }
  200. public function serviceOnRemoveConnection ($iGroupProfileId, $iInitiatorId)
  201. {
  202. $CNF = &$this->_oConfig->CNF;
  203. list ($iProfileId, $iGroupProfileId, $oGroupProfile) = $this->_prepareProfileAndGroupProfile($iGroupProfileId, $iInitiatorId);
  204. if (!$oGroupProfile)
  205. return false;
  206. $this->_oDb->fromAdmins($iGroupProfileId, $iProfileId);
  207. if ($oConn = BxDolConnection::getObjectInstance('sys_profiles_subscriptions'))
  208. return $oConn->removeConnection($iProfileId, $iGroupProfileId);
  209. return false;
  210. }
  211. public function serviceAddMutualConnection ($iGroupProfileId, $iInitiatorId, $bSendInviteOnly = false)
  212. {
  213. $CNF = &$this->_oConfig->CNF;
  214. list ($iProfileId, $iGroupProfileId, $oGroupProfile) = $this->_prepareProfileAndGroupProfile($iGroupProfileId, $iInitiatorId);
  215. if (!$oGroupProfile)
  216. return false;
  217. if (!($aContentInfo = $this->_oDb->getContentInfoById((int)BxDolProfile::getInstance($iGroupProfileId)->getContentId())))
  218. return false;
  219. if (!isset($CNF['OBJECT_CONNECTIONS']) || !($oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTIONS'])))
  220. return false;
  221. $sEntryTitle = $aContentInfo[$CNF['FIELD_NAME']];
  222. $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aContentInfo[$CNF['FIELD_ID']]);
  223. // send invitation to the group
  224. if ($bSendInviteOnly && !$oConnection->isConnected((int)$iInitiatorId, $oGroupProfile->id()) && !$oConnection->isConnected($oGroupProfile->id(), (int)$iInitiatorId) && bx_get_logged_profile_id() != $iProfileId) {
  225. bx_alert($this->getName(), 'join_invitation', $aContentInfo[$CNF['FIELD_ID']], $iGroupProfileId, array('content' => $aContentInfo, 'entry_title' => $sEntryTitle, 'entry_url' => $sEntryUrl, 'group_profile' => $iGroupProfileId, 'profile' => $iProfileId, 'notification_subobject_id' => $iProfileId, 'object_author_id' => $iGroupProfileId));
  226. }
  227. // send notification to group's admins that new connection is pending confirmation
  228. elseif (!$bSendInviteOnly && $oConnection->isConnected((int)$iInitiatorId, $oGroupProfile->id()) && !$oConnection->isConnected($oGroupProfile->id(), (int)$iInitiatorId) && $aContentInfo['join_confirmation']) {
  229. bx_alert($this->getName(), 'join_request', $aContentInfo[$CNF['FIELD_ID']], $iGroupProfileId, array(
  230. 'object_author_id' => $iGroupProfileId,
  231. 'performer_id' => $iProfileId,
  232. 'content' => $aContentInfo,
  233. 'entry_title' => $sEntryTitle,
  234. 'entry_url' => $sEntryUrl,
  235. 'group_profile' => $iGroupProfileId,
  236. 'profile' => $iProfileId
  237. ));
  238. }
  239. // send notification that join request was accepted
  240. else if (!$bSendInviteOnly && $oConnection->isConnected((int)$iInitiatorId, $oGroupProfile->id(), true) && $oGroupProfile->getModule() != $this->getName() && bx_get_logged_profile_id() != $iProfileId) {
  241. bx_alert($this->getName(), 'join_request_accepted', $aContentInfo[$CNF['FIELD_ID']], $iGroupProfileId, array(
  242. 'object_author_id' => $iGroupProfileId,
  243. 'performer_id' => $iProfileId,
  244. 'content' => $aContentInfo,
  245. 'entry_title' => $sEntryTitle,
  246. 'entry_url' => $sEntryUrl,
  247. 'group_profile' => $iGroupProfileId,
  248. 'profile' => $iProfileId
  249. ));
  250. }
  251. // new fan was added
  252. if ($oConnection->isConnected($oGroupProfile->id(), (int)$iInitiatorId, true)) {
  253. // follow group on join
  254. if (BxDolService::call($oGroupProfile->getModule(), 'act_as_profile')){
  255. $this->addFollower($oGroupProfile->id(), (int)$iInitiatorId);
  256. }
  257. else{
  258. $this->addFollower((int)$iInitiatorId, $oGroupProfile->id());
  259. }
  260. bx_alert($this->getName(), 'fan_added', $aContentInfo[$CNF['FIELD_ID']], $iGroupProfileId, array(
  261. 'object_author_id' => $iGroupProfileId,
  262. 'performer_id' => $iProfileId,
  263. 'content' => $aContentInfo,
  264. 'entry_title' => $sEntryTitle,
  265. 'entry_url' => $sEntryUrl,
  266. 'group_profile' => $iGroupProfileId,
  267. 'profile' => $iProfileId,
  268. ));
  269. $this->doAudit($iGroupProfileId, $iInitiatorId, '_sys_audit_action_group_join_request_accepted');
  270. return false;
  271. }
  272. // don't automatically add connection (mutual) if group requires manual join confirmation
  273. if ($bSendInviteOnly || $aContentInfo['join_confirmation'])
  274. return false;
  275. // check if connection already exists
  276. if ($oConnection->isConnected($oGroupProfile->id(), (int)$iInitiatorId, true) || $oConnection->isConnected($oGroupProfile->id(), (int)$iInitiatorId))
  277. return false;
  278. if (!$oConnection->addConnection($oGroupProfile->id(), (int)$iInitiatorId))
  279. return false;
  280. return true;
  281. }
  282. public function serviceFansTable ()
  283. {
  284. $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->CNF['OBJECT_GRID_CONNECTIONS']);
  285. if (!$oGrid)
  286. return false;
  287. return $oGrid->getCode();
  288. }
  289. public function serviceInvitesTable ()
  290. {
  291. if (!isset($this->_oConfig->CNF['OBJECT_GRID_INVITES']))
  292. return false;
  293. $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->CNF['OBJECT_GRID_INVITES']);
  294. if (!$oGrid)
  295. return false;
  296. return $oGrid->getCode();
  297. }
  298. public function serviceFans ($iContentId = 0, $bAsArray = false)
  299. {
  300. if (!$iContentId)
  301. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  302. if (!$iContentId)
  303. return false;
  304. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  305. if (!$aContentInfo)
  306. return false;
  307. if (!($oGroupProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $this->getName())))
  308. return false;
  309. if(!$bAsArray) {
  310. bx_import('BxDolConnection');
  311. $mixedResult = $this->serviceBrowseConnectionsQuick ($oGroupProfile->id(), $this->_oConfig->CNF['OBJECT_CONNECTIONS'], BX_CONNECTIONS_CONTENT_TYPE_CONTENT, true);
  312. if (!$mixedResult)
  313. return MsgBox(_t('_sys_txt_empty'));
  314. }
  315. else
  316. $mixedResult = BxDolConnection::getObjectInstance($this->_oConfig->CNF['OBJECT_CONNECTIONS'])->getConnectedContent($oGroupProfile->id(), true);
  317. return $mixedResult;
  318. }
  319. public function serviceAdmins ($iContentId = 0)
  320. {
  321. $CNF = &$this->_oConfig->CNF;
  322. if(!$iContentId)
  323. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  324. if(!$iContentId)
  325. return false;
  326. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $this->getName());
  327. if(!$oGroupProfile)
  328. return false;
  329. $iStart = (int)bx_get('start');
  330. $iLimit = !empty($CNF['PARAM_NUM_CONNECTIONS_QUICK']) ? getParam($CNF['PARAM_NUM_CONNECTIONS_QUICK']) : 4;
  331. if(!$iLimit)
  332. $iLimit = 4;
  333. $aProfiles = $this->_oDb->getAdmins($oGroupProfile->id(), $iStart, $iLimit+1);
  334. if(empty($aProfiles) || !is_array($aProfiles))
  335. return false;
  336. return $this->_serviceBrowseQuick($aProfiles, $iStart, $iLimit);
  337. }
  338. public function serviceBrowseJoinedEntries ($iProfileId = 0, $bDisplayEmptyMsg = false)
  339. {
  340. if (!$iProfileId)
  341. $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
  342. if (!$iProfileId)
  343. return '';
  344. return $this->_serviceBrowse ('joined_entries', array('joined_profile' => $iProfileId), BX_DB_PADDING_DEF, $bDisplayEmptyMsg);
  345. }
  346. public function serviceBrowseCreatedEntries ($iProfileId = 0, $bDisplayEmptyMsg = false)
  347. {
  348. if (!$iProfileId)
  349. $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
  350. if (!$iProfileId)
  351. return '';
  352. return $this->_serviceBrowse ('created_entries', array('author' => $iProfileId), BX_DB_PADDING_DEF, $bDisplayEmptyMsg);
  353. }
  354. public function serviceEntityInvite ($iContentId = 0, $bErrorMsg = true)
  355. {
  356. if (isset($this->_oConfig->CNF['OBJECT_FORM_ENTRY_DISPLAY_INVITE']))
  357. return $this->_serviceEntityForm ('editDataForm', $iContentId, $this->_oConfig->CNF['OBJECT_FORM_ENTRY_DISPLAY_INVITE'], false, $bErrorMsg);
  358. return false;
  359. }
  360. /**
  361. * Entry social sharing block
  362. */
  363. public function serviceEntitySocialSharing ($mixedContent = false, $aParams = array())
  364. {
  365. if(!empty($mixedContent)) {
  366. if(!is_array($mixedContent))
  367. $mixedContent = array((int)$mixedContent, array());
  368. }
  369. else {
  370. $mixedContent = $this->_getContent();
  371. if($mixedContent === false)
  372. return false;
  373. }
  374. list($iContentId, $aContentInfo) = $mixedContent;
  375. $oGroupProfile = BxDolProfile::getInstanceByContentAndType((int)$iContentId, $this->getName());
  376. if(!$oGroupProfile)
  377. return false;
  378. return parent::serviceEntitySocialSharing(array($iContentId, $aContentInfo), array(
  379. 'title' => $oGroupProfile->getDisplayName()
  380. ));
  381. }
  382. /**
  383. * Data for Notifications module
  384. */
  385. public function serviceGetNotificationsData()
  386. {
  387. $sModule = $this->_aModule['name'];
  388. $aSettingsTypes = array('follow_member', 'follow_context');
  389. if($this->serviceActAsProfile())
  390. $aSettingsTypes = array('personal', 'follow_member');
  391. return array(
  392. 'handlers' => array(
  393. array('group' => $sModule . '_vote', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doVote', 'module_name' => $sModule, 'module_method' => 'get_notifications_vote', 'module_class' => 'Module'),
  394. array('group' => $sModule . '_vote', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'undoVote'),
  395. array('group' => $sModule . '_score_up', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doVoteUp', 'module_name' => $sModule, 'module_method' => 'get_notifications_score_up', 'module_class' => 'Module'),
  396. array('group' => $sModule . '_score_down', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doVoteDown', 'module_name' => $sModule, 'module_method' => 'get_notifications_score_down', 'module_class' => 'Module'),
  397. array('group' => $sModule . '_fan_added', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'fan_added', 'module_name' => $sModule, 'module_method' => 'get_notifications_fan_added', 'module_class' => 'Module'),
  398. array('group' => $sModule . '_join_request', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'join_request', 'module_name' => $sModule, 'module_method' => 'get_notifications_join_request', 'module_class' => 'Module', 'module_event_privacy' => $this->_oConfig->CNF['OBJECT_PRIVACY_VIEW_NOTIFICATION_EVENT']),
  399. array('group' => $sModule . '_timeline_post_common', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'timeline_post_common', 'module_name' => $sModule, 'module_method' => 'get_notifications_timeline_post_common', 'module_class' => 'Module'),
  400. ),
  401. 'settings' => array(
  402. array('group' => 'vote', 'unit' => $sModule, 'action' => 'doVote', 'types' => $aSettingsTypes),
  403. array('group' => 'score_up', 'unit' => $sModule, 'action' => 'doVoteUp', 'types' => $aSettingsTypes),
  404. array('group' => 'score_down', 'unit' => $sModule, 'action' => 'doVoteDown', 'types' => $aSettingsTypes),
  405. array('group' => 'fan', 'unit' => $sModule, 'action' => 'fan_added', 'types' => $aSettingsTypes),
  406. array('group' => 'join', 'unit' => $sModule, 'action' => 'join_request', 'types' => $aSettingsTypes),
  407. array('group' => 'timeline_post', 'unit' => $sModule, 'action' => 'timeline_post_common', 'types' => $aSettingsTypes)
  408. ),
  409. 'alerts' => array(
  410. array('unit' => $sModule, 'action' => 'doVote'),
  411. array('unit' => $sModule, 'action' => 'undoVote'),
  412. array('unit' => $sModule, 'action' => 'doVoteUp'),
  413. array('unit' => $sModule, 'action' => 'doVoteDown'),
  414. array('unit' => $sModule, 'action' => 'fan_added'),
  415. array('unit' => $sModule, 'action' => 'join_request'),
  416. array('unit' => $sModule, 'action' => 'timeline_post_common'),
  417. )
  418. );
  419. }
  420. /**
  421. * Notification about new member requst in the group
  422. */
  423. public function serviceGetNotificationsJoinRequest($aEvent)
  424. {
  425. return $this->_serviceGetNotification($aEvent, $this->_oConfig->CNF['T']['txt_ntfs_join_request']);
  426. }
  427. /**
  428. * Notification about new member in the group
  429. */
  430. public function serviceGetNotificationsFanAdded($aEvent)
  431. {
  432. return $this->_serviceGetNotification($aEvent, $this->_oConfig->CNF['T']['txt_ntfs_fan_added']);
  433. }
  434. protected function _serviceGetNotification($aEvent, $sLangKey)
  435. {
  436. $CNF = &$this->_oConfig->CNF;
  437. $iContentId = (int)$aEvent['object_id'];
  438. $oGroupProfile = BxDolProfile::getInstanceByContentAndType((int)$iContentId, $this->getName());
  439. if(!$oGroupProfile)
  440. return array();
  441. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  442. if(empty($aContentInfo) || !is_array($aContentInfo))
  443. return array();
  444. $oProfile = BxDolProfile::getInstance((int)$aEvent['subobject_id']);
  445. if(!$oProfile)
  446. return array();
  447. /*
  448. * Note. Group Profile URL is used for both Entry and Subentry URLs,
  449. * because Subentry URL has higher display priority and notification
  450. * should be linked to Group Profile (Group Profile -> Members tab)
  451. * instead of Personal Profile of a member, who performed an action.
  452. */
  453. $sEntryUrl = $oGroupProfile->getUrl();
  454. if(!empty($CNF['URL_ENTRY_FANS']))
  455. $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_ENTRY_FANS'], array(
  456. 'profile_id' => $oGroupProfile->id()
  457. ));
  458. return array(
  459. 'entry_sample' => $CNF['T']['txt_sample_single'],
  460. 'entry_url' => $sEntryUrl,
  461. 'entry_caption' => $oGroupProfile->getDisplayName(),
  462. 'entry_author' => $oGroupProfile->id(),
  463. 'subentry_sample' => $oProfile->getDisplayName(),
  464. 'subentry_url' => $sEntryUrl,
  465. 'lang_key' => $sLangKey
  466. );
  467. }
  468. /**
  469. * Data for Timeline module
  470. */
  471. public function serviceGetTimelineData()
  472. {
  473. return BxBaseModGeneralModule::serviceGetTimelineData();
  474. }
  475. /**
  476. * Entry post for Timeline module
  477. */
  478. public function serviceGetTimelinePost($aEvent, $aBrowseParams = array())
  479. {
  480. $a = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
  481. if($a === false)
  482. return false;
  483. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($aEvent['object_id'], $this->getName());
  484. $a['content']['url'] = $oGroupProfile->getUrl();
  485. $a['content']['title'] = $oGroupProfile->getDisplayName();
  486. return $a;
  487. }
  488. // ====== PERMISSION METHODS
  489. /**
  490. * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden.
  491. */
  492. public function checkAllowedView ($aDataEntry, $isPerformAction = false)
  493. {
  494. return $this->serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction);
  495. }
  496. public function serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction = false, $iProfileId = false)
  497. {
  498. $bInvited = false;
  499. if (bx_get('key')){
  500. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($aDataEntry[$this->_oConfig->CNF['FIELD_ID']], $this->getName());
  501. $mixedInvited = $this->isInvited(bx_get('key'), $oGroupProfile->id());
  502. if ($mixedInvited === true)
  503. $bInvited = true;
  504. }
  505. if ($this->isFan($aDataEntry[$this->_oConfig->CNF['FIELD_ID']], $iProfileId) || $bInvited)
  506. return CHECK_ACTION_RESULT_ALLOWED;
  507. return parent::serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction, $iProfileId);
  508. }
  509. /**
  510. * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden.
  511. */
  512. public function checkAllowedCompose(&$aDataEntry, $isPerformAction = false)
  513. {
  514. if(!$this->isFan($aDataEntry[$this->_oConfig->CNF['FIELD_ID']]))
  515. return _t('_sys_txt_access_denied');
  516. return parent::checkAllowedCompose ($aDataEntry, $isPerformAction);
  517. }
  518. /**
  519. * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden.
  520. */
  521. public function checkAllowedFanAdd(&$aDataEntry, $isPerformAction = false)
  522. {
  523. $mixedResult = $this->_modGroupsCheckAllowedFanAdd($aDataEntry, $isPerformAction);
  524. // call alert to allow custom checks
  525. bx_alert('system', 'check_allowed_fan_add', 0, 0, array(
  526. 'module' => $this->getName(),
  527. 'content_info' => $aDataEntry,
  528. 'profile_id' => bx_get_logged_profile_id(),
  529. 'override_result' => &$mixedResult
  530. ));
  531. return $mixedResult;
  532. }
  533. public function _modGroupsCheckAllowedFanAdd (&$aDataEntry, $isPerformAction = false)
  534. {
  535. if ($this->isFan($aDataEntry[$this->_oConfig->CNF['FIELD_ID']]) || !isLogged())
  536. return _t('_sys_txt_access_denied');
  537. return $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $this->_oConfig->CNF['OBJECT_CONNECTIONS'], true, false);
  538. }
  539. /**
  540. * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden.
  541. */
  542. public function checkAllowedFanRemove (&$aDataEntry, $isPerformAction = false)
  543. {
  544. if (CHECK_ACTION_RESULT_ALLOWED === $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $this->_oConfig->CNF['OBJECT_CONNECTIONS'], false, true, true))
  545. return CHECK_ACTION_RESULT_ALLOWED;
  546. return $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $this->_oConfig->CNF['OBJECT_CONNECTIONS'], false, true, false);
  547. }
  548. protected function _checkAllowedActionByFan($sAction, $aDataEntry, $iPerformerId = 0)
  549. {
  550. $CNF = &$this->_oConfig->CNF;
  551. $bRoles = $this->_oConfig->isRoles();
  552. if(empty($iPerformerId))
  553. $iPerformerId = bx_get_logged_profile_id();
  554. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($aDataEntry[$CNF['FIELD_ID']], $this->getName());
  555. $iGroupProfileId = $oGroupProfile->id();
  556. if(!$bRoles && $this->_oDb->isAdmin($iGroupProfileId, $iPerformerId, $aDataEntry))
  557. return CHECK_ACTION_RESULT_ALLOWED;
  558. if($bRoles && $this->isAllowedActionByRole($sAction, $aDataEntry, $iGroupProfileId, $iPerformerId))
  559. return CHECK_ACTION_RESULT_ALLOWED;
  560. return _t('_sys_txt_access_denied');
  561. }
  562. public function isAllowedActionByRole($sAction, $aDataEntry, $iGroupProfileId, $iPerformerId)
  563. {
  564. $bResult = false;
  565. $iRole = $this->_oDb->getRole($iGroupProfileId, $iPerformerId);
  566. if(!empty($iRole))
  567. switch($sAction) {
  568. case BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES:
  569. if($iRole == BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR)
  570. $bResult = true;
  571. break;
  572. default:
  573. $bResult = true;
  574. }
  575. // call alert to allow custom checks
  576. bx_alert('system', 'check_allowed_action_by_role', 0, 0, array(
  577. 'module' => $this->getName(),
  578. 'action' => $sAction,
  579. 'content_profile_id' => $iGroupProfileId,
  580. 'content_info' => $aDataEntry,
  581. 'profile_id' => $iPerformerId,
  582. 'profile_role' => $iRole,
  583. 'override_result' => &$bResult
  584. ));
  585. return $bResult;
  586. }
  587. public function checkAllowedManageFans($mixedDataEntry, $isPerformAction = false)
  588. {
  589. $aDataEntry = array();
  590. if(!is_array($mixedDataEntry)) {
  591. $oGroupProfile = BxDolProfile::getInstance((int)$mixedDataEntry);
  592. if($oGroupProfile && $this->getName() == $oGroupProfile->getModule())
  593. $aDataEntry = $this->_oDb->getContentInfoById($oGroupProfile->getContentId());
  594. }
  595. else
  596. $aDataEntry = $mixedDataEntry;
  597. if($this->_checkAllowedActionByFan(BX_BASE_MOD_GROUPS_ACTION_MANAGE_FANS, $aDataEntry) === CHECK_ACTION_RESULT_ALLOWED)
  598. return CHECK_ACTION_RESULT_ALLOWED;
  599. return parent::checkAllowedEdit($aDataEntry, $isPerformAction);
  600. }
  601. public function checkAllowedManageAdmins($mixedDataEntry, $isPerformAction = false)
  602. {
  603. $aDataEntry = array();
  604. if(!is_array($mixedDataEntry)) {
  605. $oGroupProfile = BxDolProfile::getInstance((int)$mixedDataEntry);
  606. if($oGroupProfile && $this->getName() == $oGroupProfile->getModule())
  607. $aDataEntry = $this->_oDb->getContentInfoById($oGroupProfile->getContentId());
  608. }
  609. else
  610. $aDataEntry = $mixedDataEntry;
  611. if($this->_checkAllowedActionByFan(BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES, $aDataEntry) === CHECK_ACTION_RESULT_ALLOWED)
  612. return CHECK_ACTION_RESULT_ALLOWED;
  613. return parent::checkAllowedEdit($aDataEntry, $isPerformAction);
  614. }
  615. public function checkAllowedEdit($aDataEntry, $isPerformAction = false)
  616. {
  617. if($this->_checkAllowedActionByFan(BX_BASE_MOD_GROUPS_ACTION_EDIT, $aDataEntry) === CHECK_ACTION_RESULT_ALLOWED)
  618. return CHECK_ACTION_RESULT_ALLOWED;
  619. return parent::checkAllowedEdit($aDataEntry, $isPerformAction);
  620. }
  621. public function checkAllowedInvite($aDataEntry, $isPerformAction = false)
  622. {
  623. if($this->_checkAllowedActionByFan(BX_BASE_MOD_GROUPS_ACTION_INVITE, $aDataEntry) === CHECK_ACTION_RESULT_ALLOWED)
  624. return CHECK_ACTION_RESULT_ALLOWED;
  625. return $this->checkAllowedEdit ($aDataEntry, $isPerformAction);
  626. }
  627. public function checkAllowedChangeCover($aDataEntry, $isPerformAction = false)
  628. {
  629. if($this->_checkAllowedActionByFan(BX_BASE_MOD_GROUPS_ACTION_CHANGE_COVER, $aDataEntry) === CHECK_ACTION_RESULT_ALLOWED)
  630. return CHECK_ACTION_RESULT_ALLOWED;
  631. return parent::checkAllowedChangeCover($aDataEntry, $isPerformAction);
  632. }
  633. public function checkAllowedDelete(&$aDataEntry, $isPerformAction = false)
  634. {
  635. if($this->_checkAllowedActionByFan(BX_BASE_MOD_GROUPS_ACTION_DELETE, $aDataEntry) === CHECK_ACTION_RESULT_ALLOWED)
  636. return CHECK_ACTION_RESULT_ALLOWED;
  637. return parent::checkAllowedDelete($aDataEntry, $isPerformAction);
  638. }
  639. public function checkAllowedJoin(&$aDataEntry, $isPerformAction = false)
  640. {
  641. if (bx_get('key')){
  642. $sKey = bx_get('key');
  643. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($aDataEntry[$this->_oConfig->CNF['FIELD_ID']], $this->getName());
  644. $aData = $this->_oDb->getInviteByKey($sKey, $oGroupProfile->id());
  645. if (isset($aData['invited_profile_id']) && $aData['invited_profile_id'] == bx_get_logged_profile_id()){
  646. return CHECK_ACTION_RESULT_ALLOWED;
  647. }
  648. }
  649. return _t('_sys_txt_access_denied');
  650. }
  651. public function checkAllowedSubscribeAdd(&$aDataEntry, $isPerformAction = false)
  652. {
  653. $mixedResult = $this->_modGroupsCheckAllowedSubscribeAdd($aDataEntry, $isPerformAction);
  654. // call alert to allow custom checks
  655. bx_alert('system', 'check_allowed_subscribe_add', 0, 0, array(
  656. 'module' => $this->getName(),
  657. 'content_info' => $aDataEntry,
  658. 'profile_id' => bx_get_logged_profile_id(),
  659. 'override_result' => &$mixedResult
  660. ));
  661. return $mixedResult;
  662. }
  663. /**
  664. * Note. Is mainly needed for internal usage. Access level is 'public' to allow outer calls from alerts.
  665. */
  666. public function _modGroupsCheckAllowedSubscribeAdd(&$aDataEntry, $isPerformAction = false)
  667. {
  668. if(!$this->isFan($aDataEntry[$this->_oConfig->CNF['FIELD_ID']]))
  669. return _t('_sys_txt_access_denied');
  670. return parent::_modProfileCheckAllowedSubscribeAdd($aDataEntry, $isPerformAction);
  671. }
  672. /**
  673. * @deprecated since version 11.0.3 and can be removed in the next version.
  674. */
  675. public function _checkAllowedSubscribeAdd (&$aDataEntry, $isPerformAction = false)
  676. {
  677. return parent::checkAllowedSubscribeAdd ($aDataEntry, $isPerformAction);
  678. }
  679. public function doAudit($iGroupProfileId, $iFanId, $sAction)
  680. {
  681. $oProfile = BxDolProfile::getInstance($iFanId);
  682. $iContentId = $oProfile->getContentId();
  683. $sModule = $oProfile->getModule();
  684. $oModule = BxDolModule::getInstance($sModule);
  685. if (BxDolRequest::serviceExists($sModule, 'act_as_profile') && BxDolService::call($sModule, 'act_as_profile') && $oModule->_oConfig){
  686. $CNF = $oModule->_oConfig->CNF;
  687. $aContentInfo = BxDolRequest::serviceExists($sModule, 'get_all') ? BxDolService::call($sModule, 'get_all', array(array('type' => 'id', 'id' => $iContentId))) : array();
  688. $AuditParams = array(
  689. 'content_title' => (isset($CNF['FIELD_TITLE']) && isset($aContentInfo[$CNF['FIELD_TITLE']])) ? $aContentInfo[$CNF['FIELD_TITLE']] : '',
  690. 'context_profile_id' => $iGroupProfileId,
  691. 'context_profile_title' => BxDolProfile::getInstance($iGroupProfileId)->getDisplayName()
  692. );
  693. bx_audit(
  694. $iContentId,
  695. $sModule,
  696. $sAction,
  697. $AuditParams
  698. );
  699. }
  700. }
  701. protected function _checkAllowedConnect (&$aDataEntry, $isPerformAction, $sObjConnection, $isMutual, $isInvertResult, $isSwap = false)
  702. {
  703. $sResult = $this->checkAllowedView($aDataEntry);
  704. $oPrivacy = BxDolPrivacy::getObjectInstance($this->_oConfig->CNF['OBJECT_PRIVACY_VIEW']);
  705. // if profile view isn't allowed but visibility is in partially visible groups
  706. // then display buttons to connect (befriend, join) to profile,
  707. // if other conditions (in parent::_checkAllowedConnect) are met as well
  708. if (CHECK_ACTION_RESULT_ALLOWED !== $sResult && !in_array($aDataEntry[$this->_oConfig->CNF['FIELD_ALLOW_VIEW_TO']], array_merge($oPrivacy->getPartiallyVisiblePrivacyGroups(), array('s'))))
  709. return $sResult;
  710. return parent::_checkAllowedConnect ($aDataEntry, $isPerformAction, $sObjConnection, $isMutual, $isInvertResult, $isSwap);
  711. }
  712. public function addFollower ($iProfileId1, $iProfileId2)
  713. {
  714. $oConnectionFollow = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
  715. if($oConnectionFollow && !$oConnectionFollow->isConnected($iProfileId1, $iProfileId2)){
  716. $oConnectionFollow->addConnection($iProfileId1, $iProfileId2);
  717. return true;
  718. }
  719. return false;
  720. }
  721. public function isFan ($iContentId, $iProfileId = false)
  722. {
  723. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $this->getName());
  724. if (isset($this->_oConfig->CNF['OBJECT_CONNECTIONS']))
  725. return $oGroupProfile && ($oConnection = BxDolConnection::getObjectInstance($this->_oConfig->CNF['OBJECT_CONNECTIONS'])) && $oConnection->isConnected($iProfileId ? $iProfileId : bx_get_logged_profile_id(), $oGroupProfile->id(), true);
  726. return false;
  727. }
  728. public function isInvited ($sKey, $iProfileId)
  729. {
  730. $CNF = &$this->_oConfig->CNF;
  731. $aData = $this->_oDb->getInviteByKey($sKey, $iProfileId);
  732. if (!isset($aData['invited_profile_id']))
  733. return _t($CNF['T']['txt_invitation_popup_error_invitation_absent']);
  734. if ($aData['invited_profile_id'] != bx_get_logged_profile_id())
  735. return _t($CNF['T']['txt_invitation_popup_error_wrong_user']);
  736. return true;
  737. }
  738. public function setRole($iGroupProfileId, $iFanProfileId, $iRole)
  739. {
  740. if(($mixedResult = $this->checkAllowedManageAdmins($iGroupProfileId)) !== CHECK_ACTION_RESULT_ALLOWED)
  741. return array('code' => 1, 'msg' => $mixedResult);
  742. if(!$this->_oDb->setRole($iGroupProfileId, $iFanProfileId, $iRole))
  743. return array('code' => 2, 'msg' => _t('_error occured'));
  744. $this->onSetRole($iGroupProfileId, $iFanProfileId, $iRole);
  745. return array('code' => 0);
  746. }
  747. public function onSetRole($iGroupProfileId, $iFanProfileId, $iRole)
  748. {
  749. $CNF = &$this->_oConfig->CNF;
  750. $iProfileId = bx_get_logged_profile_id();
  751. $oGroupProfile = BxDolProfile::getInstance($iGroupProfileId);
  752. $aGroupProfileInfo = $this->_oDb->getContentInfoById((int)$oGroupProfile->getContentId());
  753. $aRoles = BxDolFormQuery::getDataItems($CNF['OBJECT_PRE_LIST_ROLES']);
  754. // notify about admin status
  755. if(!empty($CNF['EMAIL_FAN_SET_ROLE']) && $iFanProfileId != $iProfileId)
  756. sendMailTemplate($CNF['EMAIL_FAN_SET_ROLE'], 0, $iFanProfileId, array(
  757. 'EntryUrl' => $oGroupProfile->getUrl(),
  758. 'EntryTitle' => $oGroupProfile->getDisplayName(),
  759. 'Role' => $aRoles[$iRole]
  760. ), BX_EMAIL_NOTIFY);
  761. // subscribe advanced group members automatically
  762. $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
  763. if($iRole != 0)
  764. $oConnection->addConnection($iFanProfileId, $iGroupProfileId);
  765. else
  766. $oConnection->removeConnection($iFanProfileId, $iGroupProfileId);
  767. bx_alert($this->getName(), 'set_role', $aGroupProfileInfo[$CNF['FIELD_ID']], $iGroupProfileId, array(
  768. 'object_author_id' => $iGroupProfileId,
  769. 'performer_id' => $iProfileId,
  770. 'fan_id' => $iFanProfileId,
  771. 'content' => $aGroupProfileInfo,
  772. 'role' => $iRole,
  773. 'group_profile' => $iGroupProfileId,
  774. 'profile' => $iProfileId
  775. ));
  776. $this->doAudit($iGroupProfileId, $iFanProfileId, '_sys_audit_action_group_role_changed');
  777. }
  778. protected function _getImagesForTimelinePost($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
  779. {
  780. $CNF = &$this->_oConfig->CNF;
  781. $oGroupProfile = BxDolProfile::getInstanceByContentAndType($aEvent['object_id'], $this->getName());
  782. $sSrc = '';
  783. if(isset($CNF['FIELD_COVER']) && !empty($aContentInfo[$CNF['FIELD_COVER']]))
  784. $sSrc = $oGroupProfile->getCover();
  785. if(empty($sSrc) && isset($CNF['FIELD_PICTURE']) && !empty($aContentInfo[$CNF['FIELD_PICTURE']]))
  786. $sSrc = $oGroupProfile->getPicture();
  787. return empty($sSrc) ? array() : array(
  788. array('id' => $aContentInfo[$CNF['FIELD_PICTURE']], 'url' => $sUrl, 'src' => $sSrc, 'src_orig' => $sSrc),
  789. );
  790. }
  791. protected function _prepareProfileAndGroupProfile($iGroupProfileId, $iInitiatorId)
  792. {
  793. if (!($oGroupProfile = BxDolProfile::getInstance($iGroupProfileId)))
  794. return array(0, 0, null);
  795. if ($oGroupProfile->getModule() == $this->getName()) {
  796. $iProfileId = $iInitiatorId;
  797. $iGroupProfileId = $oGroupProfile->id();
  798. } else {
  799. $iProfileId = $oGroupProfile->id();
  800. $iGroupProfileId = $iInitiatorId;
  801. }
  802. return array($iProfileId, $iGroupProfileId, $oGroupProfile);
  803. }
  804. }
  805. /** @} */