PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/app/protected/modules/gamification/models/GamePoint.php

https://bitbucket.org/zurmo/zurmo/
PHP | 358 lines | 228 code | 23 blank | 107 comment | 14 complexity | 88f263f2e1a3aa7c22f123ade81ddcfc MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-3.0, LGPL-2.1, BSD-2-Clause
  1. <?php
  2. /*********************************************************************************
  3. * Zurmo is a customer relationship management program developed by
  4. * Zurmo, Inc. Copyright (C) 2015 Zurmo Inc.
  5. *
  6. * Zurmo is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU Affero General Public License version 3 as published by the
  8. * Free Software Foundation with the addition of the following permission added
  9. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10. * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
  11. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12. *
  13. * Zurmo is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License along with
  19. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21. * 02110-1301 USA.
  22. *
  23. * You can contact Zurmo, Inc. with a mailing address at 27 North Wacker Drive
  24. * Suite 370 Chicago, IL 60606. or at email address contact@zurmo.com.
  25. *
  26. * The interactive user interfaces in original and modified versions
  27. * of this program must display Appropriate Legal Notices, as required under
  28. * Section 5 of the GNU Affero General Public License version 3.
  29. *
  30. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  31. * these Appropriate Legal Notices must retain the display of the Zurmo
  32. * logo and Zurmo copyright notice. If the display of the logo is not reasonably
  33. * feasible for technical reasons, the Appropriate Legal Notices must display the words
  34. * "Copyright Zurmo Inc. 2015. All rights reserved".
  35. ********************************************************************************/
  36. /**
  37. * Model for game points.
  38. */
  39. class GamePoint extends Item
  40. {
  41. /**
  42. * @var String
  43. */
  44. const TYPE_USER_ADOPTION = 'UserAdoption';
  45. /**
  46. * @var String
  47. */
  48. const TYPE_SALES = 'Sales';
  49. /**
  50. * @var String
  51. */
  52. const TYPE_NEW_BUSINESS = 'NewBusiness';
  53. /**
  54. * @var String
  55. */
  56. const TYPE_ACCOUNT_MANAGEMENT = 'AccountManagement';
  57. /**
  58. * @var String
  59. */
  60. const TYPE_COMMUNICATION = 'Communication';
  61. /**
  62. * @var String
  63. */
  64. const TYPE_TIME_MANAGEMENT = 'TimeManagement';
  65. protected $isAudited = false;
  66. public function __toString()
  67. {
  68. if (trim($this->type) == '')
  69. {
  70. return Zurmo::t('Core', '(Unnamed)');
  71. }
  72. return $this->type;
  73. }
  74. public function __set($attributeName, $value)
  75. {
  76. if ($attributeName == 'value')
  77. {
  78. $this->replaceValue($value);
  79. }
  80. else
  81. {
  82. parent::__set($attributeName, $value);
  83. }
  84. }
  85. /**
  86. * Given a point type and Item (Either User or Person), try to find an existing model. If the model does
  87. * not exist, create it and populate the Item and type. @return The found or created model.
  88. * @param string $type
  89. * @param Item $person
  90. */
  91. public static function resolveToGetByTypeAndPerson($type, Item $person)
  92. {
  93. assert('is_string($type)');
  94. assert('$person->id > 0');
  95. assert('$person instanceof Contact || $person instanceof User');
  96. $searchAttributeData = array();
  97. $searchAttributeData['clauses'] = array(
  98. 1 => array(
  99. 'attributeName' => 'type',
  100. 'operatorType' => 'equals',
  101. 'value' => $type,
  102. ),
  103. 2 => array(
  104. 'attributeName' => 'person',
  105. 'relatedAttributeName' => 'id',
  106. 'operatorType' => 'equals',
  107. 'value' => $person->getClassId('Item'),
  108. ),
  109. );
  110. $searchAttributeData['structure'] = '1 and 2';
  111. $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter('GamePoint');
  112. $where = RedBeanModelDataProvider::makeWhere('GamePoint', $searchAttributeData, $joinTablesAdapter);
  113. $models = self::getSubset($joinTablesAdapter, null, 2, $where, null);
  114. if (count($models) > 1)
  115. {
  116. $logContent = 'Duplicate Game Point for Person: ' . $person->id . ' with type ' . $type;
  117. GamificationUtil::logAndNotifyOnDuplicateGameModel($logContent);
  118. return $models[0];
  119. }
  120. if (count($models) == 0)
  121. {
  122. $gamePoint = new GamePoint();
  123. $gamePoint->type = $type;
  124. $gamePoint->person = $person;
  125. return $gamePoint;
  126. }
  127. return $models[0];
  128. }
  129. /**
  130. * Given a Item (Either User or Person), Try to find an existing models and index the returning array by
  131. * point type.
  132. * @param Item $person
  133. */
  134. public static function getAllByPersonIndexedByType(Item $person)
  135. {
  136. assert('$person->id > 0');
  137. assert('$person instanceof Contact || $person instanceof User');
  138. $searchAttributeData = array();
  139. $searchAttributeData['clauses'] = array(
  140. 1 => array(
  141. 'attributeName' => 'person',
  142. 'relatedAttributeName' => 'id',
  143. 'operatorType' => 'equals',
  144. 'value' => $person->getClassId('Item'),
  145. ),
  146. );
  147. $searchAttributeData['structure'] = '1';
  148. $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter('GamePoint');
  149. $where = RedBeanModelDataProvider::makeWhere('GamePoint', $searchAttributeData, $joinTablesAdapter);
  150. $models = self::getSubset($joinTablesAdapter, null, null, $where, null);
  151. $indexedModels = array();
  152. foreach ($models as $gamePoint)
  153. {
  154. $indexedModels[$gamePoint->type] = $gamePoint;
  155. }
  156. return $indexedModels;
  157. }
  158. public static function getModuleClassName()
  159. {
  160. return 'GamificationModule';
  161. }
  162. public static function canSaveMetadata()
  163. {
  164. return false;
  165. }
  166. public static function getDefaultMetadata()
  167. {
  168. $metadata = parent::getDefaultMetadata();
  169. $metadata[__CLASS__] = array(
  170. 'members' => array(
  171. 'type',
  172. 'value',
  173. ),
  174. 'relations' => array(
  175. 'person' => array(static::HAS_ONE, 'Item', static::NOT_OWNED,
  176. static::LINK_TYPE_SPECIFIC, 'person'),
  177. 'transactions' => array(static::HAS_MANY, 'GamePointTransaction', static::OWNED),
  178. ),
  179. 'rules' => array(
  180. array('type', 'required'),
  181. array('type', 'type', 'type' => 'string'),
  182. array('type', 'length', 'min' => 1, 'max' => 64),
  183. array('value', 'type', 'type' => 'integer'),
  184. array('value', 'numerical', 'min' => 1),
  185. array('value', 'required'),
  186. array('person', 'required'),
  187. ),
  188. 'elements' => array(
  189. 'person' => 'Person',
  190. ),
  191. 'defaultSortAttribute' => 'type',
  192. 'noAudit' => array(
  193. 'type',
  194. 'value',
  195. 'person',
  196. 'transactions'
  197. ),
  198. );
  199. return $metadata;
  200. }
  201. public static function isTypeDeletable()
  202. {
  203. return true;
  204. }
  205. /**
  206. * Add specified value.
  207. * @param $value
  208. * @param bool $createTransaction
  209. */
  210. public function addValue($value, $createTransaction = true)
  211. {
  212. assert('is_int($value)');
  213. assert('is_bool($createTransaction)');
  214. $this->unrestrictedSet('value', $this->value + $value);
  215. if ($createTransaction)
  216. {
  217. $gamePointTransaction = new GamePointTransaction();
  218. $gamePointTransaction->value = $value;
  219. $this->transactions->add($gamePointTransaction);
  220. }
  221. }
  222. /**
  223. * Replace value with specified value.
  224. * @param int $value
  225. */
  226. public function replaceValue($value)
  227. {
  228. assert('is_int($value)');
  229. $oldValue = $this->value;
  230. $this->unrestrictedSet('value', $value);
  231. $gamePointTransaction = new GamePointTransaction();
  232. $gamePointTransaction->value = $value - $oldValue;
  233. $this->transactions->add($gamePointTransaction);
  234. }
  235. /**
  236. * Given a user and a number, determine if a user's existing total points exceeds the specified number.
  237. * If so, return true, otherwise return false.
  238. * @param User $user
  239. * @param Integer $points
  240. */
  241. public static function doesUserExceedPointsByLevelType(User $user, $points, $levelType)
  242. {
  243. assert('$user->id > 0');
  244. assert('is_int($points)');
  245. assert('is_string($levelType) && $levelType != null');
  246. $data = self::getSummationPointsDataByLevelTypeAndUser($user, $levelType);
  247. if ($data != null && $data['sum'] > $points)
  248. {
  249. return true;
  250. }
  251. else
  252. {
  253. return false;
  254. }
  255. }
  256. /**
  257. * @param User $user
  258. * @param string $levelType
  259. * @return array
  260. */
  261. public static function getSummationPointsDataByLevelTypeAndUser(User $user, $levelType)
  262. {
  263. assert('$user->id > 0');
  264. assert('is_string($levelType) && $levelType != null');
  265. $wherePart = static::getPointTypeWherePartByLevelType($levelType);
  266. $sql = "select sum(value) sum from gamepoint where " . $wherePart . " person_item_id = " .
  267. $user->getClassId('Item') . " group by person_item_id";
  268. return ZurmoRedBean::getRow($sql);
  269. }
  270. /**
  271. * Performance function to grab all summation data by type for a given user.
  272. * @param User $user
  273. * @return array of summation points indexed by the level type
  274. */
  275. public static function getSummationPointsDataByUserIndexedByLevelType(User $user)
  276. {
  277. assert('$user->id > 0');
  278. $sql = "select type, sum(value) sum from gamepoint where person_item_id = " .
  279. $user->getClassId('Item') . " group by type";
  280. $rows = ZurmoRedBean::getAll($sql);
  281. $indexedData = array();
  282. foreach ($rows as $row)
  283. {
  284. $indexedData[$row['type']] = $row['sum'];
  285. }
  286. return $indexedData;
  287. }
  288. /**
  289. * Given a level type, get the corresponding where sql part to filter by point type if applicable. Level types
  290. * match point types for now, so if the level type is not valid then it will thrown an exception.
  291. * @param string $levelType
  292. * @throws NotSupportedException
  293. */
  294. protected static function getPointTypeWherePartByLevelType($levelType)
  295. {
  296. assert('is_string($levelType) && $levelType != null');
  297. if (!in_array($levelType, array(GameLevel::TYPE_GENERAL,
  298. GameLevel::TYPE_SALES,
  299. GameLevel::TYPE_NEW_BUSINESS,
  300. GameLevel::TYPE_ACCOUNT_MANAGEMENT,
  301. GameLevel::TYPE_TIME_MANAGEMENT,
  302. GameLevel::TYPE_COMMUNICATION)))
  303. {
  304. throw new NotSupportedException();
  305. }
  306. if ($levelType == GameLevel::TYPE_GENERAL)
  307. {
  308. return null;
  309. }
  310. else
  311. {
  312. $pointType = $levelType;
  313. return " type = '" . $pointType . "' and ";
  314. }
  315. }
  316. /**
  317. * Returns the display name for the model class.
  318. * @param null | string $language
  319. * @return dynamic label name based on module.
  320. */
  321. protected static function getLabel($language = null)
  322. {
  323. return Zurmo::t('GamificationModule', 'Game Point', array(), null, $language);
  324. }
  325. /**
  326. * Returns the display name for plural of the model class.
  327. * @param null | string $language
  328. * @return dynamic label name based on module.
  329. */
  330. protected static function getPluralLabel($language = null)
  331. {
  332. return Zurmo::t('GamificationModule', 'Game Points', array(), null, $language);
  333. }
  334. }
  335. ?>