BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

donations.class.php 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. <?php
  2. declare(strict_types=1);
  3. class Donations
  4. {
  5. private static $IsSchedule = false;
  6. /**
  7. * regular_donate
  8. */
  9. public static function regular_donate($UserID, $DonationAmount, $Source, $Reason, $Currency = 'USD')
  10. {
  11. self::donate(
  12. $UserID,
  13. array(
  14. 'Source' => $Source,
  15. 'Price' => $DonationAmount,
  16. 'Currency' => $Currency,
  17. 'Source' => $Source,
  18. 'Reason' => $Reason,
  19. 'SendPM' => true
  20. )
  21. );
  22. }
  23. /**
  24. * donate
  25. */
  26. public static function donate($UserID, $Args)
  27. {
  28. $UserID = (int) $UserID;
  29. $QueryID = G::$DB->get_query_id();
  30. G::$DB->query("
  31. SELECT
  32. 1
  33. FROM
  34. `users_main`
  35. WHERE
  36. `ID` = '$UserID'
  37. LIMIT 1
  38. ");
  39. if (G::$DB->has_results()) {
  40. G::$Cache->InternalCache = false;
  41. foreach ($Args as &$Arg) {
  42. $Arg = db_string($Arg);
  43. }
  44. extract($Args);
  45. // We don't always get a date passed in
  46. if (empty($Date)) {
  47. $Date = sqltime();
  48. }
  49. // Get the ID of the staff member making the edit
  50. $AddedBy = 0;
  51. if (!self::$IsSchedule) {
  52. $AddedBy = G::$LoggedUser['ID'];
  53. }
  54. // Give them the extra invite
  55. $ExtraInvite = G::$DB->affected_rows();
  56. // A staff member is directly manipulating donor points
  57. if (isset($Manipulation) && $Manipulation === 'Direct') {
  58. $DonorPoints = $Rank;
  59. $AdjustedRank = $Rank >= MAX_EXTRA_RANK ? MAX_EXTRA_RANK : $Rank;
  60. G::$DB->query("
  61. INSERT INTO users_donor_ranks(
  62. `UserID`,
  63. `Rank`,
  64. `TotalRank`,
  65. `DonationTime`,
  66. `RankExpirationTime`
  67. )
  68. VALUES(
  69. '$UserID',
  70. '$AdjustedRank',
  71. '$TotalRank',
  72. '$Date',
  73. NOW()
  74. )
  75. ON DUPLICATE KEY
  76. UPDATE
  77. `Rank` = '$AdjustedRank',
  78. `TotalRank` = '$TotalRank',
  79. `DonationTime` = '$Date',
  80. `RankExpirationTime` = NOW()
  81. ");
  82. } else {
  83. // Donations from the store get donor points directly, no need to calculate them
  84. if ($Source === 'Store Parser') {
  85. $ConvertedPrice = self::currency_exchange($Amount * $Price, $Currency);
  86. } else {
  87. $ConvertedPrice = self::currency_exchange($Price, $Currency);
  88. $DonorPoints = self::calculate_rank($ConvertedPrice);
  89. }
  90. // Rank is the same thing as DonorPoints
  91. $IncreaseRank = $DonorPoints;
  92. $CurrentRank = self::get_rank($UserID);
  93. // A user's donor rank can never exceed MAX_EXTRA_RANK
  94. // If the amount they donated causes it to overflow, chnage it to MAX_EXTRA_RANK
  95. // The total rank isn't affected by this, so their original donor point value is added to it
  96. if (($CurrentRank + $DonorPoints) >= MAX_EXTRA_RANK) {
  97. $AdjustedRank = MAX_EXTRA_RANK;
  98. } else {
  99. $AdjustedRank = $CurrentRank + $DonorPoints;
  100. }
  101. G::$DB->query("
  102. INSERT INTO users_donor_ranks(
  103. `UserID`,
  104. `Rank`,
  105. `TotalRank`,
  106. `DonationTime`,
  107. `RankExpirationTime`
  108. )
  109. VALUES(
  110. '$UserID',
  111. '$AdjustedRank',
  112. '$DonorPoints',
  113. '$Date',
  114. NOW()
  115. )
  116. ON DUPLICATE KEY
  117. UPDATE
  118. `Rank` = '$AdjustedRank',
  119. `TotalRank` = TotalRank + '$DonorPoints',
  120. `DonationTime` = '$Date',
  121. `RankExpirationTime` = NOW()
  122. ");
  123. }
  124. // Donor cache key is outdated
  125. G::$Cache->delete_value("donor_info_$UserID");
  126. // Get their rank
  127. $Rank = self::get_rank($UserID);
  128. $TotalRank = self::get_total_rank($UserID);
  129. // Now that their rank and total rank has been set, we can calculate their special rank
  130. self::calculate_special_rank($UserID);
  131. // Hand out invites
  132. G::$DB->query("
  133. SELECT
  134. `InvitesRecievedRank`
  135. FROM
  136. `users_donor_ranks`
  137. WHERE
  138. `UserID` = '$UserID'
  139. ");
  140. list($InvitesRecievedRank) = G::$DB->next_record();
  141. $AdjustedRank = $Rank >= MAX_RANK ? (MAX_RANK - 1) : $Rank;
  142. $InviteRank = $AdjustedRank - $InvitesRecievedRank;
  143. if ($InviteRank > 0) {
  144. $Invites = $ExtraInvite ? ($InviteRank + 1) : $InviteRank;
  145. G::$DB->query("
  146. UPDATE
  147. `users_main`
  148. SET
  149. `Invites` = Invites + '$Invites'
  150. WHERE
  151. `ID` = '$UserID'
  152. ");
  153. G::$DB->query("
  154. UPDATE
  155. `users_donor_ranks`
  156. SET
  157. `InvitesRecievedRank` = '$AdjustedRank'
  158. WHERE
  159. `UserID` = '$UserID'
  160. ");
  161. }
  162. // Send them a thank you PM
  163. if ($SendPM) {
  164. $Subject = "Thank you for your donation";
  165. Misc::send_pm($UserID, 0, $Subject, '');
  166. }
  167. // Lastly, add this donation to our history
  168. G::$DB->query("
  169. INSERT INTO `donations`(
  170. `UserID`,
  171. `Amount`,
  172. `Source`,
  173. `Reason`,
  174. `Currency`,
  175. `Email`,
  176. `Time`,
  177. `AddedBy`,
  178. `Rank`,
  179. `TotalRank`
  180. )
  181. VALUES(
  182. '$UserID',
  183. '$ConvertedPrice',
  184. '$Source',
  185. '$Reason',
  186. '$Currency',
  187. '',
  188. '$Date',
  189. '$AddedBy',
  190. '$DonorPoints',
  191. '$TotalRank'
  192. )
  193. ");
  194. // Clear their user cache keys because the users_info values has been modified
  195. G::$Cache->delete_value("user_info_$UserID");
  196. G::$Cache->delete_value("user_info_heavy_$UserID");
  197. G::$Cache->delete_value("donor_info_$UserID");
  198. }
  199. G::$DB->set_query_id($QueryID);
  200. }
  201. /**
  202. * calculate_special_rank
  203. */
  204. private static function calculate_special_rank($UserID)
  205. {
  206. $UserID = (int) $UserID;
  207. $QueryID = G::$DB->get_query_id();
  208. // Are they are special?
  209. G::$DB->query("
  210. SELECT
  211. `TotalRank`,
  212. `SpecialRank`
  213. FROM
  214. `users_donor_ranks`
  215. WHERE
  216. `UserID` = '$UserID'
  217. ");
  218. if (G::$DB->has_results()) {
  219. // Adjust their special rank depending on the total rank.
  220. list($TotalRank, $SpecialRank) = G::$DB->next_record();
  221. if ($TotalRank < 10) {
  222. $SpecialRank = 0;
  223. }
  224. if ($SpecialRank < 1 && $TotalRank >= 10) {
  225. Misc::send_pm($UserID, 0, 'Special Donor Rank 1', 'Thank You');
  226. $SpecialRank = 1;
  227. }
  228. if ($SpecialRank < 2 && $TotalRank >= 20) {
  229. Misc::send_pm($UserID, 0, 'Special Donor Rank 2', 'Thank You');
  230. $SpecialRank = 2;
  231. }
  232. if ($SpecialRank < 3 && $TotalRank >= 50) {
  233. Misc::send_pm($UserID, 0, 'Special Donor Rank 3', 'Thank You');
  234. $SpecialRank = 3;
  235. }
  236. // Make them special
  237. G::$DB->query("
  238. UPDATE
  239. `users_donor_ranks`
  240. SET
  241. `SpecialRank` = '$SpecialRank'
  242. WHERE
  243. `UserID` = '$UserID'
  244. ");
  245. G::$Cache->delete_value("donor_info_$UserID");
  246. }
  247. G::$DB->set_query_id($QueryID);
  248. }
  249. /**
  250. * expire_ranks
  251. */
  252. public static function expire_ranks()
  253. {
  254. $QueryID = G::$DB->get_query_id();
  255. G::$DB->query("
  256. SELECT
  257. `UserID`,
  258. `Rank`
  259. FROM
  260. `users_donor_ranks`
  261. WHERE
  262. `Rank` > 1 AND `SpecialRank` != 3 AND `RankExpirationTime` < NOW() - INTERVAL 766 HOUR
  263. ");
  264. // 2 hours less than 32 days to account for schedule run times
  265. if (G::$DB->record_count() > 0) {
  266. $UserIDs = [];
  267. while (list($UserID, $Rank) = G::$DB->next_record()) {
  268. G::$Cache->delete_value("donor_info_$UserID");
  269. G::$Cache->delete_value("donor_title_$UserID");
  270. G::$Cache->delete_value("donor_profile_rewards_$UserID");
  271. $UserIDs[] = $UserID;
  272. }
  273. $In = implode(',', $UserIDs);
  274. G::$DB->query("
  275. UPDATE
  276. `users_donor_ranks`
  277. SET
  278. `Rank` = Rank - IF(Rank = " . MAX_RANK . ", 2, 1),
  279. `RankExpirationTime` = NOW()
  280. WHERE
  281. `UserID` IN($In)
  282. ");
  283. }
  284. G::$DB->set_query_id($QueryID);
  285. }
  286. /**
  287. * calculate_rank
  288. */
  289. private static function calculate_rank($Amount)
  290. {
  291. return floor($Amount / 5);
  292. }
  293. /**
  294. * update_rank
  295. */
  296. public static function update_rank($UserID, $Rank, $TotalRank, $Reason)
  297. {
  298. $Rank = (int) $Rank;
  299. $TotalRank = (int) $TotalRank;
  300. self::donate(
  301. $UserID,
  302. array(
  303. 'Manipulation' => 'Direct',
  304. 'Rank' => $Rank,
  305. 'TotalRank' => $TotalRank,
  306. 'Reason' => $Reason,
  307. 'Source' => 'Modify Values',
  308. 'Currency' => 'EUR'
  309. )
  310. );
  311. }
  312. /**
  313. * hide_stats
  314. */
  315. public static function hide_stats($UserID)
  316. {
  317. $QueryID = G::$DB->get_query_id();
  318. G::$DB->query("
  319. INSERT INTO `users_donor_ranks`(`UserID`, `Hidden`)
  320. VALUES('$UserID', '1')
  321. ON DUPLICATE KEY
  322. UPDATE
  323. `Hidden` = '1'
  324. ");
  325. G::$DB->set_query_id($QueryID);
  326. }
  327. /**
  328. * show_stats
  329. */
  330. public static function show_stats($UserID)
  331. {
  332. $QueryID = G::$DB->get_query_id();
  333. G::$DB->query("
  334. INSERT INTO `users_donor_ranks`(`UserID`, `Hidden`)
  335. VALUES('$UserID', '0')
  336. ON DUPLICATE KEY
  337. UPDATE
  338. `Hidden` = '0'
  339. ");
  340. G::$DB->set_query_id($QueryID);
  341. }
  342. /**
  343. * is_visible
  344. */
  345. public static function is_visible($UserID)
  346. {
  347. $QueryID = G::$DB->get_query_id();
  348. G::$DB->query("
  349. SELECT
  350. `Hidden`
  351. FROM
  352. `users_donor_ranks`
  353. WHERE
  354. `Hidden` = '0' AND `UserID` = '$UserID'
  355. ");
  356. $HasResults = G::$DB->has_results();
  357. G::$DB->set_query_id($QueryID);
  358. return $HasResults;
  359. }
  360. /**
  361. * has_donor_forum
  362. */
  363. public static function has_donor_forum($UserID)
  364. {
  365. $ENV = ENV::go();
  366. return self::get_rank($UserID) >= $ENV->DONOR_FORUM_RANK || self::get_special_rank($UserID) >= MAX_SPECIAL_RANK;
  367. }
  368. /**
  369. * Put all the common donor info in the same cache key to save some cache calls
  370. */
  371. public static function get_donor_info($UserID)
  372. {
  373. // Our cache class should prevent identical memcached requests
  374. $DonorInfo = G::$Cache->get_value("donor_info_$UserID");
  375. if ($DonorInfo === false) {
  376. # todo: Investigate Rank in donations table
  377. $QueryID = G::$DB->get_query_id();
  378. G::$DB->query("
  379. SELECT
  380. `Rank`,
  381. `SpecialRank`,
  382. `TotalRank`,
  383. `DonationTime`,
  384. `RankExpirationTime` + INTERVAL 766 HOUR
  385. FROM
  386. `users_donor_ranks`
  387. WHERE
  388. `UserID` = '$UserID'
  389. ");
  390. // 2 hours less than 32 days to account for schedule run times
  391. if (G::$DB->has_results()) {
  392. list($Rank, $SpecialRank, $TotalRank, $DonationTime, $ExpireTime) = G::$DB->next_record(MYSQLI_NUM, false);
  393. if ($DonationTime === null) {
  394. $DonationTime = 0;
  395. }
  396. if ($ExpireTime === null) {
  397. $ExpireTime = 0;
  398. }
  399. } else {
  400. $Rank = $SpecialRank = $TotalRank = $DonationTime = $ExpireTime = 0;
  401. }
  402. if (Permissions::is_mod($UserID)) {
  403. $Rank = MAX_EXTRA_RANK;
  404. $SpecialRank = MAX_SPECIAL_RANK;
  405. }
  406. G::$DB->query("
  407. SELECT
  408. `IconMouseOverText`,
  409. `AvatarMouseOverText`,
  410. `CustomIcon`,
  411. `CustomIconLink`,
  412. `SecondAvatar`
  413. FROM
  414. `donor_rewards`
  415. WHERE
  416. `UserID` = '$UserID'
  417. ");
  418. $Rewards = G::$DB->next_record(MYSQLI_ASSOC);
  419. G::$DB->set_query_id($QueryID);
  420. $DonorInfo = array(
  421. 'Rank' => (int) $Rank,
  422. 'SRank' => (int) $SpecialRank,
  423. 'TotRank' => (int) $TotalRank,
  424. 'Time' => $DonationTime,
  425. 'ExpireTime' => $ExpireTime,
  426. 'Rewards' => $Rewards
  427. );
  428. G::$Cache->cache_value("donor_info_$UserID", $DonorInfo, 0);
  429. }
  430. return $DonorInfo;
  431. }
  432. /**
  433. * get_rank
  434. */
  435. public static function get_rank($UserID)
  436. {
  437. return self::get_donor_info($UserID)['Rank'];
  438. }
  439. /**
  440. * get_special_rank
  441. */
  442. public static function get_special_rank($UserID)
  443. {
  444. return self::get_donor_info($UserID)['SRank'];
  445. }
  446. /**
  447. * get_total_rank
  448. */
  449. public static function get_total_rank($UserID)
  450. {
  451. return self::get_donor_info($UserID)['TotRank'];
  452. }
  453. /**
  454. * get_donation_time
  455. */
  456. public static function get_donation_time($UserID)
  457. {
  458. return self::get_donor_info($UserID)['Time'];
  459. }
  460. /**
  461. * get_personal_collages
  462. */
  463. public static function get_personal_collages($UserID)
  464. {
  465. $DonorInfo = self::get_donor_info($UserID);
  466. if ($DonorInfo['SRank'] === MAX_SPECIAL_RANK) {
  467. $Collages = 5;
  468. } else {
  469. $Collages = min($DonorInfo['Rank'], 5); // One extra collage per donor rank up to 5
  470. }
  471. return $Collages;
  472. }
  473. /**
  474. * get_enabled_rewards
  475. */
  476. public static function get_enabled_rewards($UserID)
  477. {
  478. $Rewards = [];
  479. $Rank = self::get_rank($UserID);
  480. $SpecialRank = self::get_special_rank($UserID);
  481. $HasAll = $SpecialRank === 3;
  482. $Rewards = array(
  483. 'HasAvatarMouseOverText' => false,
  484. 'HasCustomDonorIcon' => false,
  485. 'HasDonorForum' => false,
  486. 'HasDonorIconLink' => false,
  487. 'HasDonorIconMouseOverText' => false,
  488. 'HasProfileInfo1' => false,
  489. 'HasProfileInfo2' => false,
  490. 'HasProfileInfo3' => false,
  491. 'HasProfileInfo4' => false,
  492. 'HasSecondAvatar' => false);
  493. if ($Rank >= 2 || $HasAll) {
  494. $Rewards["HasDonorIconMouseOverText"] = true;
  495. $Rewards["HasProfileInfo1"] = true;
  496. }
  497. if ($Rank >= 3 || $HasAll) {
  498. $Rewards["HasAvatarMouseOverText"] = true;
  499. $Rewards["HasProfileInfo2"] = true;
  500. }
  501. if ($Rank >= 4 || $HasAll) {
  502. $Rewards["HasDonorIconLink"] = true;
  503. $Rewards["HasProfileInfo3"] = true;
  504. }
  505. if ($Rank >= MAX_RANK || $HasAll) {
  506. $Rewards["HasCustomDonorIcon"] = true;
  507. $Rewards["HasDonorForum"] = true;
  508. $Rewards["HasProfileInfo4"] = true;
  509. }
  510. if ($SpecialRank >= 2) {
  511. $Rewards["HasSecondAvatar"] = true;
  512. }
  513. return $Rewards;
  514. }
  515. /**
  516. * get_rewards
  517. */
  518. public static function get_rewards($UserID)
  519. {
  520. return self::get_donor_info($UserID)['Rewards'];
  521. }
  522. /**
  523. * get_profile_rewards
  524. */
  525. public static function get_profile_rewards($UserID)
  526. {
  527. $Results = G::$Cache->get_value("donor_profile_rewards_$UserID");
  528. if ($Results === false) {
  529. $QueryID = G::$DB->get_query_id();
  530. G::$DB->query("
  531. SELECT
  532. `ProfileInfo1`,
  533. `ProfileInfoTitle1`,
  534. `ProfileInfo2`,
  535. `ProfileInfoTitle2`,
  536. `ProfileInfo3`,
  537. `ProfileInfoTitle3`,
  538. `ProfileInfo4`,
  539. `ProfileInfoTitle4`
  540. FROM
  541. `donor_rewards`
  542. WHERE
  543. `UserID` = '$UserID'
  544. ");
  545. $Results = G::$DB->next_record();
  546. G::$DB->set_query_id($QueryID);
  547. G::$Cache->cache_value("donor_profile_rewards_$UserID", $Results, 0);
  548. }
  549. return $Results;
  550. }
  551. /**
  552. * add_profile_info_reward
  553. */
  554. private static function add_profile_info_reward($Counter, &$Insert, &$Values, &$Update)
  555. {
  556. if (isset($_POST["profile_title_" . $Counter]) && isset($_POST["profile_info_" . $Counter])) {
  557. $ProfileTitle = db_string($_POST["profile_title_" . $Counter]);
  558. $ProfileInfo = db_string($_POST["profile_info_" . $Counter]);
  559. $ProfileInfoTitleSQL = "ProfileInfoTitle" . $Counter;
  560. $ProfileInfoSQL = "ProfileInfo" . $Counter;
  561. $Insert[] = "$ProfileInfoTitleSQL";
  562. $Values[] = "'$ProfileInfoTitle'";
  563. $Update[] = "$ProfileInfoTitleSQL = '$ProfileTitle'";
  564. $Insert[] = "$ProfileInfoSQL";
  565. $Values[] = "'$ProfileInfo'";
  566. $Update[] = "$ProfileInfoSQL = '$ProfileInfo'";
  567. }
  568. }
  569. /**
  570. * update_rewards
  571. */
  572. public static function update_rewards($UserID)
  573. {
  574. $Rank = self::get_rank($UserID);
  575. $SpecialRank = self::get_special_rank($UserID);
  576. $HasAll = $SpecialRank === 3;
  577. $Counter = 0;
  578. $Insert = [];
  579. $Values = [];
  580. $Update = [];
  581. $Insert[] = "UserID";
  582. $Values[] = "'$UserID'";
  583. if ($Rank >= 1 || $HasAll) {
  584. }
  585. if ($Rank >= 2 || $HasAll) {
  586. if (isset($_POST['donor_icon_mouse_over_text'])) {
  587. $IconMouseOverText = db_string($_POST['donor_icon_mouse_over_text']);
  588. $Insert[] = "IconMouseOverText";
  589. $Values[] = "'$IconMouseOverText'";
  590. $Update[] = "IconMouseOverText = '$IconMouseOverText'";
  591. }
  592. $Counter++;
  593. }
  594. if ($Rank >= 3 || $HasAll) {
  595. if (isset($_POST['avatar_mouse_over_text'])) {
  596. $AvatarMouseOverText = db_string($_POST['avatar_mouse_over_text']);
  597. $Insert[] = "AvatarMouseOverText";
  598. $Values[] = "'$AvatarMouseOverText'";
  599. $Update[] = "AvatarMouseOverText = '$AvatarMouseOverText'";
  600. }
  601. $Counter++;
  602. }
  603. if ($Rank >= 4 || $HasAll) {
  604. if (isset($_POST['donor_icon_link'])) {
  605. $CustomIconLink = db_string($_POST['donor_icon_link']);
  606. if (!Misc::is_valid_url($CustomIconLink)) {
  607. $CustomIconLink = '';
  608. }
  609. $Insert[] = "CustomIconLink";
  610. $Values[] = "'$CustomIconLink'";
  611. $Update[] = "CustomIconLink = '$CustomIconLink'";
  612. }
  613. $Counter++;
  614. }
  615. if ($Rank >= MAX_RANK || $HasAll) {
  616. if (isset($_POST['donor_icon_custom_url'])) {
  617. $CustomIcon = db_string($_POST['donor_icon_custom_url']);
  618. if (!Misc::is_valid_url($CustomIcon)) {
  619. $CustomIcon = '';
  620. }
  621. $Insert[] = "CustomIcon";
  622. $Values[] = "'$CustomIcon'";
  623. $Update[] = "CustomIcon = '$CustomIcon'";
  624. }
  625. $Counter++;
  626. }
  627. for ($i = 1; $i <= $Counter; $i++) {
  628. self::add_profile_info_reward($i, $Insert, $Values, $Update);
  629. }
  630. if ($SpecialRank >= 2) {
  631. if (isset($_POST['second_avatar'])) {
  632. $SecondAvatar = db_string($_POST['second_avatar']);
  633. if (!Misc::is_valid_url($SecondAvatar)) {
  634. $SecondAvatar = '';
  635. }
  636. $Insert[] = "SecondAvatar";
  637. $Values[] = "'$SecondAvatar'";
  638. $Update[] = "SecondAvatar = '$SecondAvatar'";
  639. }
  640. }
  641. $Insert = implode(', ', $Insert);
  642. $Values = implode(', ', $Values);
  643. $Update = implode(', ', $Update);
  644. if ($Counter > 0) {
  645. $QueryID = G::$DB->get_query_id();
  646. G::$DB->query("
  647. INSERT INTO `donor_rewards`($Insert)
  648. VALUES($Values)
  649. ON DUPLICATE KEY
  650. UPDATE
  651. $Update
  652. ");
  653. G::$DB->set_query_id($QueryID);
  654. }
  655. G::$Cache->delete_value("donor_profile_rewards_$UserID");
  656. G::$Cache->delete_value("donor_info_$UserID");
  657. }
  658. /**
  659. * get_donation_history
  660. */
  661. public static function get_donation_history($UserID)
  662. {
  663. $UserID = (int) $UserID;
  664. if (empty($UserID)) {
  665. error(404);
  666. }
  667. $QueryID = G::$DB->get_query_id();
  668. G::$DB->query("
  669. SELECT
  670. `Amount`,
  671. `Email`,
  672. `Time`,
  673. `Currency`,
  674. `Reason`,
  675. `Source`,
  676. `AddedBy`,
  677. `Rank`,
  678. `TotalRank`
  679. FROM
  680. `donations`
  681. WHERE
  682. `UserID` = '$UserID'
  683. ORDER BY
  684. `Time`
  685. DESC
  686. ");
  687. $DonationHistory = G::$DB->to_array(false, MYSQLI_ASSOC, false);
  688. G::$DB->set_query_id($QueryID);
  689. return $DonationHistory;
  690. }
  691. /**
  692. * get_rank_expiration
  693. */
  694. public static function get_rank_expiration($UserID)
  695. {
  696. $DonorInfo = self::get_donor_info($UserID);
  697. if ($DonorInfo['SRank'] === MAX_SPECIAL_RANK || $DonorInfo['Rank'] === 1) {
  698. $Return = 'Never';
  699. } elseif ($DonorInfo['ExpireTime']) {
  700. $ExpireTime = strtotime($DonorInfo['ExpireTime']);
  701. if ($ExpireTime - time() < 60) {
  702. $Return = 'Soon';
  703. } else {
  704. $Expiration = time_diff($ExpireTime); // 32 days
  705. $Return = "in $Expiration";
  706. }
  707. } else {
  708. $Return = '';
  709. }
  710. return $Return;
  711. }
  712. /**
  713. * get_leaderboard_position
  714. */
  715. public static function get_leaderboard_position($UserID)
  716. {
  717. $UserID = (int) $UserID;
  718. $QueryID = G::$DB->get_query_id();
  719. G::$DB->query("SET @RowNum := 0");
  720. G::$DB->query("
  721. SELECT
  722. `Position`
  723. FROM
  724. (
  725. SELECT
  726. d.UserID,
  727. @RowNum := @RowNum + 1 AS POSITION
  728. FROM
  729. `users_donor_ranks` AS d
  730. ORDER BY
  731. `TotalRank`
  732. DESC
  733. ) l
  734. WHERE
  735. `UserID` = '$UserID'
  736. ");
  737. if (G::$DB->has_results()) {
  738. list($Position) = G::$DB->next_record();
  739. } else {
  740. $Position = 0;
  741. }
  742. G::$DB->set_query_id($QueryID);
  743. return $Position;
  744. }
  745. /**
  746. * is_donor
  747. */
  748. public static function is_donor($UserID)
  749. {
  750. return self::get_rank($UserID) > 0;
  751. }
  752. /**
  753. * currency_exchange
  754. */
  755. public static function currency_exchange($Amount, $Currency)
  756. {
  757. if (!self::is_valid_currency($Currency)) {
  758. error("$Currency is not valid currency");
  759. }
  760. switch ($Currency) {
  761. case 'USD':
  762. $Amount = self::usd_to_euro($Amount);
  763. break;
  764. case 'BTC':
  765. $Amount = self::btc_to_euro($Amount);
  766. break;
  767. default:
  768. break;
  769. }
  770. return round($Amount, 2);
  771. }
  772. /**
  773. * is_valid_currency
  774. */
  775. public static function is_valid_currency($Currency)
  776. {
  777. return $Currency === 'EUR' || $Currency === 'BTC' || $Currency === 'USD';
  778. }
  779. /**
  780. * btc_to_euro
  781. */
  782. public static function btc_to_euro($Amount)
  783. {
  784. $Rate = G::$Cache->get_value('btc_rate');
  785. if (empty($Rate)) {
  786. G::$Cache->cache_value('btc_rate', $Rate, 86400);
  787. }
  788. return $Rate * $Amount;
  789. }
  790. /**
  791. * usd_to_euro
  792. */
  793. public static function usd_to_euro($Amount)
  794. {
  795. $Rate = G::$Cache->get_value('usd_rate');
  796. if (empty($Rate)) {
  797. G::$Cache->cache_value('usd_rate', $Rate, 86400);
  798. }
  799. return $Rate * $Amount;
  800. }
  801. }