BxDolPrivacy.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. define('BX_DOL_PG_HIDDEN', '1');
  10. define('BX_DOL_PG_MEONLY', '2');
  11. define('BX_DOL_PG_ALL', '3');
  12. define('BX_DOL_PG_MEMBERS', '4');
  13. define('BX_DOL_PG_FRIENDS', '5');
  14. define('BX_DOL_PG_DEFAULT', BX_DOL_PG_ALL);
  15. /**
  16. * Privacy settings for any content.
  17. *
  18. * Integration of the content with privacy engine allows site member
  19. * to organize the access to his content.
  20. *
  21. * Related classes:
  22. * BxDolPrivacyQuery - database queries.
  23. *
  24. * Example of usage:
  25. * 1. Register your privacy actions in `sys_privacy_actions` database table.
  26. * 2. Add one privacy field(with INT type) in the table with your items for each action.
  27. * For example, for action 'comment', the field name should be 'allow_comment_to'.
  28. * 3. Add group choosers for necessary actions in the form, which is used to add new items.
  29. * @code
  30. * $oPrivacy = new BxDolPrivacy();
  31. * $oPrivacy->getGroupChooser($iItemOwnerId, $sModuleUri, $sModuleAction);
  32. * @endcode
  33. *
  34. * 4. Check privacy when any user tries to view an item.
  35. * @code
  36. * $oPrivacy = new BxDolPrivacy($sTable, $sFieldId, $sFieldOwnerId);
  37. * if($oPrivacy->check($sAction, $iObjectId, $iViewerId)) {
  38. * //show necessary content
  39. * }
  40. * @endcode
  41. *
  42. * @see an example of integration in BoonEx modules, for example: Posts
  43. *
  44. *
  45. * Memberships/ACL:
  46. * Doesn't depend on user's membership.
  47. *
  48. *
  49. * Alerts:
  50. * no alerts available
  51. *
  52. */
  53. class BxDolPrivacy extends BxDolFactory implements iBxDolFactoryObject
  54. {
  55. protected $_oDb;
  56. protected $_sObject;
  57. protected $_aObject;
  58. /**
  59. * Constructor
  60. * @param $aObject array of grid options
  61. */
  62. protected function __construct($aObject)
  63. {
  64. parent::__construct();
  65. $this->_aObject = $aObject;
  66. $this->_sObject = $aObject['object'];
  67. $this->_oDb = new BxDolPrivacyQuery();
  68. $this->_oDb->init($this->_aObject);
  69. }
  70. /**
  71. * Get privacy object instance by object name
  72. * @param $sObject object name
  73. * @return object instance or false on error
  74. */
  75. public static function getObjectInstance($sObject)
  76. {
  77. if(isset($GLOBALS['bxDolClasses']['BxDolPrivacy!' . $sObject]))
  78. return $GLOBALS['bxDolClasses']['BxDolPrivacy!' . $sObject];
  79. $aObject = BxDolPrivacyQuery::getPrivacyObject($sObject);
  80. if(!$aObject || !is_array($aObject))
  81. return false;
  82. $sClass = 'BxTemplPrivacy';
  83. if(!empty($aObject['override_class_name'])) {
  84. $sClass = $aObject['override_class_name'];
  85. if(!empty($aObject['override_class_file']))
  86. require_once(BX_DIRECTORY_PATH_ROOT . $aObject['override_class_file']);
  87. }
  88. $o = new $sClass($aObject);
  89. return ($GLOBALS['bxDolClasses']['BxDolPrivacy!' . $sObject] = $o);
  90. }
  91. /**
  92. * Get Select element with available groups.
  93. *
  94. * @param string $sObject privacy object name.
  95. * @param integer $iOwnerId object's owner ID.
  96. * @param array $aParams an array of custom selector's params (dynamic_groups - an array of arrays('key' => group_id, 'value' => group_title), title - the title to be used for generated field).
  97. * @return an array with Select element description.
  98. */
  99. public static function getGroupChooser($sObject, $iOwnerId = 0, $aParams = array())
  100. {
  101. $oPrivacy = BxDolPrivacy::getObjectInstance($sObject);
  102. if(empty($oPrivacy))
  103. return array();
  104. $sModule = $oPrivacy->_aObject['module'];
  105. $sAction = $oPrivacy->_aObject['action'];
  106. if($iOwnerId == 0)
  107. $iOwnerId = bx_get_logged_profile_id();
  108. $sValue = $oPrivacy->_oDb->getDefaultGroupByUser($sModule, $sAction, $iOwnerId);
  109. if(empty($sValue))
  110. $sValue = $oPrivacy->_oDb->getDefaultGroup($sModule, $sAction);
  111. $aValues = $oPrivacy->getGroups();
  112. if(isset($aParams['dynamic_groups']) && is_array($aParams['dynamic_groups']))
  113. $aValues = array_merge($aValues, $aParams['dynamic_groups']);
  114. $sName = $oPrivacy->convertActionToField($sAction);
  115. $sTitle = isset($aParams['title']) && !empty($aParams['title']) ? $aParams['title'] : '';
  116. if(empty($sTitle)) {
  117. $sTitle = $oPrivacy->_oDb->getTitle($sModule, $sAction);
  118. $sTitle = _t(!empty($sTitle) ? $sTitle : '_' . $sName);
  119. }
  120. return array(
  121. 'type' => 'select',
  122. 'name' => $sName,
  123. 'caption' => $sTitle,
  124. 'value' => $sValue,
  125. 'values' => $aValues,
  126. 'checker' => array(
  127. 'func' => 'avail',
  128. 'error' => _t('_ps_ferr_incorrect_select')
  129. ),
  130. 'db' => array(
  131. 'pass' => 'Int'
  132. )
  133. );
  134. }
  135. /**
  136. * Get database field name for action.
  137. *
  138. * @param string $sObject privacy object name.
  139. * @param string $sAction action name.
  140. * @return string with field name.
  141. */
  142. public static function getFieldName($sObject, $sAction = '')
  143. {
  144. $oPrivacy = BxDolPrivacy::getObjectInstance($sObject);
  145. if(empty($oPrivacy))
  146. return '';
  147. if(empty($sAction))
  148. $sAction = $oPrivacy->_aObject['action'];
  149. return $oPrivacy->convertActionToField($sAction);
  150. }
  151. /**
  152. * Get necessary condition array to use privacy in search classes
  153. * @param $mixedGroupId group ID or array of group IDs
  154. * @return array of conditions, for now with 'restriction' part only is returned
  155. */
  156. public function getContentByGroupAsCondition($mixedGroupId)
  157. {
  158. return array(
  159. 'restriction' => array (
  160. 'privacy_' . $this->_sObject => array(
  161. 'value' => $mixedGroupId,
  162. 'field' => $this->convertActionToField($this->_aObject['action']),
  163. 'operator' => is_array($mixedGroupId) ? 'in' : '=',
  164. 'table' => $this->_aObject['table'],
  165. ),
  166. ),
  167. );
  168. }
  169. /**
  170. * Get necessary condition array to use privacy in search classes
  171. * @param $iProfileIdOwner owner profile ID
  172. * @return array of conditions, for now with 'restriction' part only is returned
  173. */
  174. public function getContentPublicAsCondition($iProfileIdOwner = 0, $aCustomGroups = array())
  175. {
  176. $mixedPrivacyGroups = $this->getPrivacyGroupsForContentPublic($iProfileIdOwner, $aCustomGroups);
  177. if($mixedPrivacyGroups === true)
  178. return array();
  179. return $this->getContentByGroupAsCondition($mixedPrivacyGroups);
  180. }
  181. /**
  182. * Get necessary parts of SQL query to use privacy in other queries
  183. * @param $mixedGroupId group ID or array of group IDs
  184. * @return array of SQL string parts, for now 'where' part only is returned
  185. */
  186. public function getContentByGroupAsSQLPart($mixedGroupId)
  187. {
  188. $sField = $this->convertActionToField($this->_aObject['action']);
  189. return $this->_oDb->getContentByGroupAsSQLPart($sField, $mixedGroupId);
  190. }
  191. /**
  192. * Get necessary parts of SQL query to use privacy in other queries
  193. * @param $iProfileIdOwner owner profile ID
  194. * @return array of SQL string parts, for now 'where' part only is returned
  195. */
  196. public function getContentPublicAsSQLPart($iProfileIdOwner = 0, $aCustomGroups = array())
  197. {
  198. $mixedPrivacyGroups = $this->getPrivacyGroupsForContentPublic($iProfileIdOwner, $aCustomGroups);
  199. if($mixedPrivacyGroups === true)
  200. return array();
  201. return $this->getContentByGroupAsSQLPart($mixedPrivacyGroups);
  202. }
  203. /**
  204. * Check whether the viewer can make requested action.
  205. *
  206. * @param integer $iObjectId object ID the action to be performed with.
  207. * @param integer $iViewerId viewer ID.
  208. * @return boolean result of operation.
  209. */
  210. function check($iObjectId, $iViewerId = 0)
  211. {
  212. if(empty($iViewerId))
  213. $iViewerId = (int)bx_get_logged_profile_id();
  214. $aObject = $this->getObjectInfo($this->convertActionToField($this->_aObject['action']), $iObjectId);
  215. if(empty($aObject) || !is_array($aObject))
  216. return false;
  217. if($aObject['group_id'] == BX_DOL_PG_HIDDEN)
  218. return false;
  219. if(isAdmin() || $iViewerId == $aObject['owner_id'])
  220. return true;
  221. $aGroup = $this->_oDb->getGroupsBy(array('type' => 'id', 'id' => $aObject['group_id']));
  222. if(!empty($aGroup) && is_array($aGroup) && (int)$aGroup['active'] == 1 && !empty($aGroup['check'])) {
  223. $sCheckMethod = $this->getCheckMethod($aGroup['check']);
  224. if(method_exists($this, $sCheckMethod) && $this->$sCheckMethod($aObject['owner_id'], $iViewerId))
  225. return true;
  226. }
  227. return $this->isDynamicGroupMember($aObject['group_id'], $aObject['owner_id'], $iViewerId, $iObjectId);
  228. }
  229. public function checkMeOnly($iOwnerId, $iViewerId)
  230. {
  231. return false;
  232. }
  233. public function checkPublic($iOwnerId, $iViewerId)
  234. {
  235. return true;
  236. }
  237. public function checkMembers($iOwnerId, $iViewerId)
  238. {
  239. return isMember();
  240. }
  241. public function checkFriends($iOwnerId, $iViewerId)
  242. {
  243. return BxDolConnection::getObjectInstance('sys_profiles_friends')->isConnected($iOwnerId, $iViewerId, true);
  244. }
  245. public function setTableFieldAuthor($sValue)
  246. {
  247. $this->_aObject['table_field_author'] = $sValue;
  248. $this->_oDb->init($this->_aObject);
  249. }
  250. protected function getObjectInfo($sAction, $iObjectId)
  251. {
  252. return $this->_oDb->getObjectInfo($sAction, $iObjectId);
  253. }
  254. protected function getPrivacyGroupsForContentPublic($iProfileIdOwner = 0, $aCustomGroups = array())
  255. {
  256. $aGroups = array(BX_DOL_PG_ALL);
  257. if(isLogged()) {
  258. $iProfileIdLogged = bx_get_logged_profile_id();
  259. if($iProfileIdLogged == $iProfileIdOwner)
  260. return true;
  261. $aGroups[] = BX_DOL_PG_MEMBERS;
  262. if($iProfileIdOwner && $this->checkFriends($iProfileIdOwner, $iProfileIdLogged))
  263. $aGroups[] = BX_DOL_PG_FRIENDS;
  264. }
  265. return array_merge($aGroups, $aCustomGroups);
  266. }
  267. protected function getCheckMethod($s)
  268. {
  269. if(substr($s, 0, 1) != '@')
  270. return false;
  271. return bx_gen_method_name(str_replace('@', 'check_', $s));
  272. }
  273. protected function convertActionToField($sAction)
  274. {
  275. return 'allow_' . strtolower(str_replace(' ', '-', $sAction)) . '_to';
  276. }
  277. /**
  278. * Check whethere viewer is a member of dynamic group.
  279. *
  280. * @param mixed $mixedGroupId dynamic group ID.
  281. * @param integer $iObjectOwnerId object owner ID.
  282. * @param integer $iViewerId viewer ID.
  283. * @return boolean result of operation.
  284. */
  285. protected function isDynamicGroupMember($mixedGroupId, $iObjectOwnerId, $iViewerId, $iObjectId)
  286. {
  287. return false;
  288. }
  289. /**
  290. * get privacy groups for getGroupChooser
  291. */
  292. protected function getGroups()
  293. {
  294. $aValues = array();
  295. $aGroups = $this->_oDb->getGroupsBy(array('type' => 'active'));
  296. foreach($aGroups as $aGroup) {
  297. if((int)$aGroup['active'] == 0)
  298. continue;
  299. $aValues[] = array('key' => $aGroup['id'], 'value' => _t($aGroup['title']));
  300. }
  301. return $aValues;
  302. }
  303. }
  304. /** @} */