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 26KB

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