BxDolVoteReactions.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. /**
  10. * Like based votes for any content
  11. */
  12. class BxDolVoteReactions extends BxTemplVote
  13. {
  14. protected static $_sCounterStyleSimple = 'simple'; // total counter only.
  15. protected static $_sCounterStyleDivided = 'divided'; // counters [icon + counter] divided by reactions.
  16. protected static $_sCounterStyleCompound = 'compound'; // total counter with a list of reaction icons.
  17. protected $_sMenuDoVote; //--- Do vote (reaction) menu name.
  18. protected $_sDataList; //--- Reactions list name.
  19. protected $_aDataList; //--- Reactions list with all reactions.
  20. protected $_sDefault; //--- Default reaction name.
  21. protected $_bQuickMode; //--- Give 'default' reaction when clicked.
  22. protected $_bSingleMode; //--- Auto enabled when only one item in Reactions list.
  23. public function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
  24. {
  25. parent::__construct($sSystem, $iId, $iInit, $oTemplate);
  26. $this->_oQuery = new BxDolVoteReactionsQuery($this);
  27. $this->_sType = BX_DOL_VOTE_TYPE_REACTIONS;
  28. $this->_sMenuDoVote = 'sys_vote_reactions_do';
  29. $this->_sDataList = 'sys_vote_reactions';
  30. $this->_aDataList = [];
  31. $this->_sDefault = 'default';
  32. $this->_bQuickMode = getParam('sys_vote_reactions_quick_mode') == 'on';
  33. }
  34. public function init($iId)
  35. {
  36. if(!parent::init($iId))
  37. return false;
  38. $aReactions = BxDolFormQuery::getDataItems($this->_sDataList, false, BX_DATA_VALUES_ALL);
  39. $sDefault = '';
  40. foreach($aReactions as $sReaction => $aReaction) {
  41. $aData = !empty($aReaction['Data']) ? unserialize($aReaction['Data']) : array();
  42. if(!empty($aData['default']))
  43. $sDefault = $sReaction;
  44. $this->_aDataList[$sReaction] = array(
  45. 'name' => $sReaction,
  46. 'title' => $aReaction['LKey'],
  47. 'title_aux' => $aReaction['LKey2'],
  48. 'use' => isset($aData['use']) ? $aData['use'] : 'emoji',
  49. 'icon' => isset($aData['icon']) ? $aData['icon'] : '',
  50. 'emoji' => isset($aData['emoji']) ? $aData['emoji'] : '',
  51. 'image' => isset($aData['image']) ? $aData['image'] : '',
  52. 'color' => isset($aData['color']) ? $aData['color'] : '',
  53. 'weight' => isset($aData['weight']) ? $aData['weight'] : 1,
  54. 'default' => isset($aData['default']) ? $aData['default'] : '',
  55. );
  56. }
  57. $this->_bSingleMode = count($this->_aDataList) == 1;
  58. if(empty($sDefault) && !empty($this->_aDataList))
  59. $sDefault = current(array_keys($this->_aDataList));
  60. if(!empty($sDefault)) {
  61. $aDefault = $this->_aDataList[$sDefault];
  62. if(((!$this->_bQuickMode && !$this->_bSingleMode) || $this->_bApi) && isset($aDefault['default'])) {
  63. if(is_array($aDefault['default']))
  64. $aDefault = array_merge ($aDefault, $aDefault['default']);
  65. else
  66. $aDefault['icon'] = $aDefault['default'];
  67. }
  68. $this->_aDataList[$this->_sDefault] = $aDefault;
  69. }
  70. }
  71. /**
  72. * Interface functions for outer usage
  73. */
  74. public function getValue()
  75. {
  76. return (int)$this->_aSystem['min_value'];
  77. }
  78. public function getDefault()
  79. {
  80. return $this->_sDefault;
  81. }
  82. public function getReaction($sName)
  83. {
  84. if(empty($this->_aDataList))
  85. $this->getReactions();
  86. return !empty($this->_aDataList[$sName]) ? $this->_aDataList[$sName] : false;
  87. }
  88. public function getReactions($bFullInfo = false)
  89. {
  90. return $bFullInfo ? $this->_aDataList : array_keys($this->_aDataList);
  91. }
  92. public function getTrackBy($aParams)
  93. {
  94. return $this->_oQuery->getTrackBy($aParams);
  95. }
  96. public function getIcon($sReaction, $bWithColor = true)
  97. {
  98. $aReaction = isset($this->_aDataList[$sReaction]) ? $this->_aDataList[$sReaction] : $this->_aDataList[$this->_sDefault];
  99. return $aReaction['icon'] . ($bWithColor && !empty($aReaction['color']) ? ' ' . $aReaction['color'] : '');
  100. }
  101. public function getEmoji($sReaction, $bWithColor = true)
  102. {
  103. $aReaction = isset($this->_aDataList[$sReaction]) ? $this->_aDataList[$sReaction] : $this->_aDataList[$this->_sDefault];
  104. return $aReaction['emoji'];
  105. }
  106. public function getImage($sReaction, $bWithColor = true)
  107. {
  108. $aReaction = isset($this->_aDataList[$sReaction]) ? $this->_aDataList[$sReaction] : $this->_aDataList[$this->_sDefault];
  109. list($sIconFont, $sIconUrl, $sIconA, $sIconHtml) = BxTemplFunctions::getInstanceWithTemplate($this->_oTemplate)->getIcon($aReaction['image']);
  110. if ($sIconUrl)
  111. return $this->_oTemplate->parseImage($sIconUrl, ['class' => 'sys-icon-image']);
  112. return $sIconHtml;
  113. }
  114. /**
  115. * Actions functions
  116. */
  117. public function actionGetDoVotePopup()
  118. {
  119. if(!$this->isEnabled())
  120. return '';
  121. return $this->_getDoVotePopup((int)bx_get('value'));
  122. }
  123. public function actionGetVotedBy()
  124. {
  125. if(!$this->isEnabled())
  126. return '';
  127. $aParams = array();
  128. $sReaction = bx_get('reaction');
  129. if($sReaction !== false) {
  130. $sReaction = bx_process_input($sReaction);
  131. $aReactions = $this->getReactions();
  132. if(!in_array($sReaction, $aReactions))
  133. $sReaction = $this->_sDefault;
  134. $aParams['reaction'] = $sReaction;
  135. }
  136. return $this->_getVotedBy($aParams);
  137. }
  138. /**
  139. * Internal functions
  140. */
  141. protected function _isVote($iObjectId = 0, $bForceGet = false)
  142. {
  143. $aVote = $this->_getVote($iObjectId, $bForceGet);
  144. foreach($aVote as $sKey => $iValue)
  145. if(strpos($sKey, 'count_') !== false && !empty($iValue))
  146. return true;
  147. return false;
  148. }
  149. protected function _isDuplicate($iObjectId, $iAuthorId, $iAuthorIp, $bVoted)
  150. {
  151. return $bVoted && !$this->isUndo();
  152. }
  153. protected function _isCount($aVote = array())
  154. {
  155. if(empty($aVote))
  156. $aVote = $this->_getVote();
  157. foreach($aVote as $sKey => $mixedValue)
  158. if(substr($sKey, 0, 5) == 'count' && (int)$mixedValue != 0)
  159. return true;
  160. return false;
  161. }
  162. protected function _getVoteData()
  163. {
  164. $aData = parent::_getVoteData();
  165. if($aData === false)
  166. return false;
  167. $sReaction = bx_get('reaction');
  168. if($sReaction === false)
  169. return false;
  170. $aData['reaction'] = bx_process_input($sReaction);
  171. return $aData;
  172. }
  173. protected function _returnVoteData($iObjectId, $iAuthorId, $iAuthorIp, $aData, $bVoted, $aParams = [])
  174. {
  175. $aReactions = $this->getReactions(true);
  176. $sReaction = $aData['reaction'];
  177. $bUndo = $this->isUndo();
  178. $bDisabled = $bVoted && !$bUndo;
  179. $aVote = $this->_getVote($iObjectId, true);
  180. $aTrack = $bVoted ? $this->_getTrack($iObjectId, $iAuthorId) : [];
  181. $sSwitchTo = $bVoted ? $sReaction : $this->_sDefault;
  182. $sLabelUse = !empty($aReactions[$sSwitchTo]['use']) ? $aReactions[$sSwitchTo]['use'] : 'emoji';
  183. $sLabelIcon = $this->_getIconDoWithTrack($bVoted, $aTrack);
  184. if(!$bVoted && $sLabelUse != 'icon') {
  185. $sLabelUse = 'icon';
  186. $sLabelIcon = $this->_oTemplate->parseIcon($sLabelIcon);
  187. }
  188. $sJsClick = '';
  189. if(!$bDisabled)
  190. $sJsClick = $bVoted && $bUndo ? $this->getJsClickDo($sReaction) : $this->getJsClick();
  191. $iTotalC = $iTotalS = 0;
  192. foreach(array_keys($aReactions) as $sName) {
  193. $iTotalC += (int)$aVote['count_' . $sName];
  194. $iTotalS += (int)$aVote['sum_' . $sName];
  195. }
  196. $fTotalR = $iTotalC != 0 ? round($iTotalS / $iTotalC, 2) : 0;
  197. $iCount = (int)$aVote['count_' . $sReaction];
  198. $aResult = [
  199. 'code' => 0,
  200. 'reaction' => $this->_bApi ? $aReactions[$sSwitchTo]['name'] : $sReaction,
  201. 'rate' => $aVote['rate_' . $sReaction],
  202. 'count' => $iCount,
  203. 'countf' => $iCount > 0 ? $this->_getCounterLabel($iCount, array('reaction' => $sReaction)) : '',
  204. 'label_use' => $sLabelUse,
  205. 'label_icon' => $sLabelIcon,
  206. 'label_emoji' => $this->_getEmojiDoWithTrack($bVoted, $aTrack),
  207. 'label_image' => $this->_getImageDoWithTrack($bVoted, $aTrack),
  208. 'label_title' => _t($this->_getTitleDoWithTrack($bVoted, $aTrack)),
  209. 'label_click' => $sJsClick,
  210. 'voted' => $bVoted,
  211. 'disabled' => $bVoted && !$this->isUndo(),
  212. 'total' => [
  213. 'rate' => $fTotalR,
  214. 'count' => $iTotalC,
  215. 'countf' => $iTotalC > 0 ? $this->_getCounterLabel($iTotalC, ['show_counter_label_icon' => false, 'reaction' => '']) : '',
  216. ]
  217. ];
  218. $sDefault = $this->getDefault();
  219. $aDefault = $this->getReaction($sDefault);
  220. $aDefaultInfo = $this->getReaction($aDefault['name']);
  221. $aResult['api'] = [
  222. 'performer_id' => $iAuthorId,
  223. 'is_voted' => $aResult['voted'],
  224. 'is_disabled' => $aResult['disabled'],
  225. 'reaction' => $aResult['voted'] ? $aResult['reaction'] : $sDefault,
  226. 'icon' => !empty($aResult['label_emoji']) ? $aResult['label_emoji'] : $aDefaultInfo['emoji'],
  227. 'title' => !empty($aResult['label_title']) ? $aResult['label_title'] : '',
  228. 'counter' => $this->getVote()
  229. ];
  230. return $aResult;
  231. }
  232. protected function _returnVoteDataForSocket($aData, $aMask = [])
  233. {
  234. return parent::_returnVoteDataForSocket($aData, ['code', 'reaction', 'rate', 'count', 'countf', 'total', 'api']);
  235. }
  236. protected function _getIconDoWithTrack($bVoted, $aTrack = [])
  237. {
  238. $sReaction = $bVoted ? $aTrack['reaction'] : $this->_sDefault;
  239. return $this->getIcon($sReaction);
  240. }
  241. protected function _getEmojiDoWithTrack($bVoted, $aTrack = [])
  242. {
  243. $sReaction = $bVoted ? $aTrack['reaction'] : $this->_sDefault;
  244. return $this->getEmoji($sReaction);
  245. }
  246. protected function _getImageDoWithTrack($bVoted, $aTrack = [])
  247. {
  248. $sReaction = $bVoted ? $aTrack['reaction'] : $this->_sDefault;
  249. return $this->getImage($sReaction);
  250. }
  251. protected function _getTitleDoWithTrack($bVoted, $aTrack = [])
  252. {
  253. $sReaction = $bVoted ? $aTrack['reaction'] : $this->_sDefault;
  254. return $this->_aDataList[$sReaction]['title'];
  255. }
  256. protected function _getTitleDoBy($aParams = [])
  257. {
  258. if(isset($aParams['show_counter_style']) && $aParams['show_counter_style'] == self::$_sCounterStyleCompound)
  259. return _t('_vote_do_by_reactions');
  260. $sReaction = !empty($aParams['reaction']) ? $aParams['reaction'] : $this->_sDefault;
  261. return _t('_vote_do_by_x_reaction', _t($this->_aDataList[$sReaction]['title']));
  262. }
  263. }
  264. /** @} */