Reputation.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. /**
  3. *
  4. * PHP Pro Bid $Id$ /hUzA/d/lsDObXj/yDUpPZrTott3xGoV8tph/Uvm1Wo=
  5. *
  6. * @link http://www.phpprobid.com
  7. * @copyright Copyright (c) 2015 Online Ventures Software & CodeCube SRL
  8. * @license http://www.phpprobid.com/license Commercial License
  9. *
  10. * @version 7.5
  11. */
  12. /**
  13. * reputation (feedback) table service class
  14. */
  15. namespace Ppb\Service;
  16. use Ppb\Db\Table\Reputation as ReputationTable,
  17. Cube\Db\Expr;
  18. class Reputation extends AbstractService
  19. {
  20. const SALE = 'sale';
  21. const PURCHASE = 'purchase';
  22. /**
  23. * positive rating threshold
  24. * any rating that is above this value will be considered positive
  25. */
  26. const POSITIVE_THRESHOLD = 3;
  27. /**
  28. * reputation intervals
  29. */
  30. const INTERVAL_ONE_MONTH = 'INTERVAL 1 MONTH';
  31. const INTERVAL_SIX_MONTHS = 'INTERVAL 6 MONTH';
  32. const INTERVAL_TWELVE_MONTHS = 'INTERVAL 1 YEAR';
  33. /**
  34. *
  35. * allowed reputation scores
  36. *
  37. * @var array
  38. */
  39. public static $scores = array(
  40. 5 => 'Positive',
  41. 3 => 'Neutral',
  42. 1 => 'Negative',
  43. );
  44. /**
  45. *
  46. * reputation intervals (used by the reputation details page)
  47. *
  48. * @var array
  49. */
  50. public static $intervals = array(
  51. self::INTERVAL_ONE_MONTH => 'Last Month',
  52. self::INTERVAL_SIX_MONTHS => 'Last 6 Months',
  53. self::INTERVAL_TWELVE_MONTHS => 'Last 12 Months',
  54. );
  55. /**
  56. *
  57. * reputation icons
  58. *
  59. * @var array
  60. */
  61. public static $icons = array(
  62. 1 => '<i class="fa fa-star-o fa-lg star-yellow"></i>',
  63. 10 => '<i class="fa fa-star-o fa-lg star-green"></i>',
  64. 50 => '<i class="fa fa-star-o fa-lg star-blue"></i>',
  65. 100 => '<i class="fa fa-star-o fa-lg star-red"></i>',
  66. 200 => '<i class="fa fa-star-o fa-lg star-gold"></i>',
  67. );
  68. /**
  69. *
  70. * users table service
  71. *
  72. * @var \Ppb\Service\Users
  73. */
  74. protected $_users;
  75. /**
  76. *
  77. * class constructor
  78. */
  79. public function __construct()
  80. {
  81. parent::__construct();
  82. $this->setTable(
  83. new ReputationTable());
  84. }
  85. /**
  86. *
  87. * get users table service
  88. *
  89. * @return \Ppb\Service\Users
  90. */
  91. public function getUsers()
  92. {
  93. if (!$this->_users instanceof Users) {
  94. $this->setUsers(
  95. new Users());
  96. }
  97. return $this->_users;
  98. }
  99. /**
  100. *
  101. * set users table service
  102. *
  103. * @param \Ppb\Service\Users $users
  104. *
  105. * @return \Ppb\Service\Reputation
  106. */
  107. public function setUsers(Users $users)
  108. {
  109. $this->_users = $users;
  110. return $this;
  111. }
  112. /**
  113. *
  114. * create or update an row in the reputation table
  115. *
  116. * @param array $data
  117. * @param int $posterId force poster id in case the reputation is updated from the members module
  118. * only the admin can update any reputation row
  119. *
  120. * @return \Ppb\Service\Reputation
  121. */
  122. public function save($data, $posterId = null)
  123. {
  124. $row = null;
  125. $data = $this->_prepareSaveData($data);
  126. if (array_key_exists('id', $data)) {
  127. $select = $this->_table->select()
  128. ->where("id = ?", $data['id']);
  129. unset($data['id']);
  130. $row = $this->_table->fetchRow($select);
  131. }
  132. if (count($row) > 0) {
  133. $data['updated_at'] = new Expr('now()');
  134. $where = "id='{$row['id']}'";
  135. if ($posterId !== null) {
  136. $where .= " AND poster_id = '" . intval($posterId) . "'";
  137. }
  138. $this->_table->update($data, $where);
  139. }
  140. else {
  141. $data['created_at'] = new Expr('now()');
  142. $this->_table->insert($data);
  143. }
  144. return $this;
  145. }
  146. /**
  147. *
  148. * save the data from a reputation form post
  149. * this method will also update the reputation_data column in the users table
  150. *
  151. * @param array $ids
  152. * @param float $score
  153. * @param string $comments
  154. * @param int $posterId
  155. *
  156. * @return \Ppb\Service\Reputation
  157. */
  158. public function postReputation(array $ids, $score, $comments, $posterId = null)
  159. {
  160. foreach ($ids as $id) {
  161. $this->save(array(
  162. 'id' => $id,
  163. 'score' => $score,
  164. 'comments' => $comments,
  165. 'posted' => 1
  166. ), $posterId);
  167. $user = $this->findBy('id', $id)->findParentRow('\Ppb\Db\Table\Users', 'User');
  168. $reputationData = serialize(array(
  169. 'score' => $this->getScore($user->getData('id')),
  170. 'percentage' => $this->getPercentage($user->getData('id')),
  171. ));
  172. $user->save(array(
  173. 'reputation_data' => $reputationData,
  174. ));
  175. }
  176. return $this;
  177. }
  178. /**
  179. *
  180. * calculate the reputation score of a user based on different input variables
  181. *
  182. * @param int $userId the id of the user
  183. * @param float $score score threshold
  184. * @param string $operand calculation operand
  185. * @param string $reputationType reputation type to be calculated (sale, purchase)
  186. * @param string $interval calculation interval
  187. *
  188. * @return int resulted score
  189. */
  190. public function calculateScore($userId, $score = null, $operand = '=', $reputationType = null, $interval = null)
  191. {
  192. $select = $this->_table->select(array('total' => new Expr('count(*)')))
  193. ->where('user_id = ?', $userId)
  194. ->where('posted = ?', 1);
  195. if ($score !== null) {
  196. $select->where("score {$operand} ?", $score);
  197. }
  198. if (in_array($reputationType, array(self::SALE, self::PURCHASE))) {
  199. $select->where('reputation_type = ?', $reputationType);
  200. }
  201. if (in_array($interval, array_keys(self::$intervals))) {
  202. $select->where('updated_at >= date_sub(now(), ?)', new Expr($interval));
  203. }
  204. return $this->_table->fetchRow($select)->getData('total');
  205. }
  206. /**
  207. *
  208. * get the reputation score of a certain user
  209. * the method will always get live values from the reputation table
  210. *
  211. * @param int $userId
  212. *
  213. * @return int
  214. */
  215. public function getScore($userId)
  216. {
  217. $positive = $this->calculateScore($userId, self::POSITIVE_THRESHOLD, '>');
  218. $negative = $this->calculateScore($userId, self::POSITIVE_THRESHOLD, '<');
  219. return $positive - $negative;
  220. }
  221. /**
  222. *
  223. * get the positive reputation percentage of a certain user
  224. * the method will always get live values from the reputation table
  225. *
  226. * @param int $userId
  227. *
  228. * @return string
  229. */
  230. public function getPercentage($userId)
  231. {
  232. $all = $this->calculateScore($userId);
  233. if (!$all) {
  234. return 'n/a';
  235. }
  236. $positive = $this->calculateScore($userId, self::POSITIVE_THRESHOLD, '>');
  237. $percentage = round($positive * 100 / $all);
  238. return $percentage . '%';
  239. }
  240. /**
  241. *
  242. * reputation can only be deleted by the administrator, and only from the admin area
  243. *
  244. * @param array $ids reputation ids
  245. *
  246. * @return int the number of affected rows
  247. */
  248. public function delete(array $ids)
  249. {
  250. $result = 0;
  251. foreach ($ids as $id) {
  252. $user = $this->findBy('id', $id)->findParentRow('\Ppb\Db\Table\Users', 'User');
  253. $result += $this->_table->delete(
  254. $this->_table->getAdapter()->quoteInto('id = ?', $id));
  255. $reputationData = serialize(array(
  256. 'score' => $this->getScore($user->getData('id')),
  257. 'percentage' => $this->getPercentage($user->getData('id')),
  258. ));
  259. $user->save(array(
  260. 'reputation_data' => $reputationData,
  261. ));
  262. }
  263. return $result;
  264. }
  265. }