BxDolVoteReactions.php 11 KB

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