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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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 = 'EUR')
  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 schedule()
  243. {
  244. self::$IsSchedule = true;
  245. DonationsBitcoin::find_new_donations();
  246. self::expire_ranks();
  247. }
  248. public static function expire_ranks()
  249. {
  250. $QueryID = G::$DB->get_query_id();
  251. G::$DB->query("
  252. SELECT
  253. `UserID`,
  254. `Rank`
  255. FROM
  256. `users_donor_ranks`
  257. WHERE
  258. `Rank` > 1 AND `SpecialRank` != 3 AND `RankExpirationTime` < NOW() - INTERVAL 766 HOUR
  259. ");
  260. // 2 hours less than 32 days to account for schedule run times
  261. if (G::$DB->record_count() > 0) {
  262. $UserIDs = [];
  263. while (list($UserID, $Rank) = G::$DB->next_record()) {
  264. G::$Cache->delete_value("donor_info_$UserID");
  265. G::$Cache->delete_value("donor_title_$UserID");
  266. G::$Cache->delete_value("donor_profile_rewards_$UserID");
  267. $UserIDs[] = $UserID;
  268. }
  269. $In = implode(',', $UserIDs);
  270. G::$DB->query("
  271. UPDATE
  272. `users_donor_ranks`
  273. SET
  274. `Rank` = Rank - IF(Rank = " . MAX_RANK . ", 2, 1),
  275. `RankExpirationTime` = NOW()
  276. WHERE
  277. `UserID` IN($In)
  278. ");
  279. }
  280. G::$DB->set_query_id($QueryID);
  281. }
  282. private static function calculate_rank($Amount)
  283. {
  284. return floor($Amount / 5);
  285. }
  286. public static function update_rank($UserID, $Rank, $TotalRank, $Reason)
  287. {
  288. $Rank = (int) $Rank;
  289. $TotalRank = (int) $TotalRank;
  290. self::donate(
  291. $UserID,
  292. array(
  293. 'Manipulation' => 'Direct',
  294. 'Rank' => $Rank,
  295. 'TotalRank' => $TotalRank,
  296. 'Reason' => $Reason,
  297. 'Source' => 'Modify Values',
  298. 'Currency' => 'EUR'
  299. )
  300. );
  301. }
  302. public static function hide_stats($UserID)
  303. {
  304. $QueryID = G::$DB->get_query_id();
  305. G::$DB->query("
  306. INSERT INTO `users_donor_ranks`(`UserID`, `Hidden`)
  307. VALUES('$UserID', '1')
  308. ON DUPLICATE KEY
  309. UPDATE
  310. `Hidden` = '1'
  311. ");
  312. G::$DB->set_query_id($QueryID);
  313. }
  314. public static function show_stats($UserID)
  315. {
  316. $QueryID = G::$DB->get_query_id();
  317. G::$DB->query("
  318. INSERT INTO `users_donor_ranks`(`UserID`, `Hidden`)
  319. VALUES('$UserID', '0')
  320. ON DUPLICATE KEY
  321. UPDATE
  322. `Hidden` = '0'
  323. ");
  324. G::$DB->set_query_id($QueryID);
  325. }
  326. public static function is_visible($UserID)
  327. {
  328. $QueryID = G::$DB->get_query_id();
  329. G::$DB->query("
  330. SELECT
  331. `Hidden`
  332. FROM
  333. `users_donor_ranks`
  334. WHERE
  335. `Hidden` = '0' AND `UserID` = '$UserID'
  336. ");
  337. $HasResults = G::$DB->has_results();
  338. G::$DB->set_query_id($QueryID);
  339. return $HasResults;
  340. }
  341. public static function has_donor_forum($UserID)
  342. {
  343. $ENV = ENV::go();
  344. return self::get_rank($UserID) >= $ENV->DONOR_FORUM_RANK || self::get_special_rank($UserID) >= MAX_SPECIAL_RANK;
  345. }
  346. /**
  347. * Put all the common donor info in the same cache key to save some cache calls
  348. */
  349. public static function get_donor_info($UserID)
  350. {
  351. // Our cache class should prevent identical memcached requests
  352. $DonorInfo = G::$Cache->get_value("donor_info_$UserID");
  353. if ($DonorInfo === false) {
  354. # todo: Investigate Rank in donations table
  355. $QueryID = G::$DB->get_query_id();
  356. G::$DB->query("
  357. SELECT
  358. `Rank`,
  359. `SpecialRank`,
  360. `TotalRank`,
  361. `DonationTime`,
  362. `RankExpirationTime` + INTERVAL 766 HOUR
  363. FROM
  364. `users_donor_ranks`
  365. WHERE
  366. `UserID` = '$UserID'
  367. ");
  368. // 2 hours less than 32 days to account for schedule run times
  369. if (G::$DB->has_results()) {
  370. list($Rank, $SpecialRank, $TotalRank, $DonationTime, $ExpireTime) = G::$DB->next_record(MYSQLI_NUM, false);
  371. if ($DonationTime === null) {
  372. $DonationTime = 0;
  373. }
  374. if ($ExpireTime === null) {
  375. $ExpireTime = 0;
  376. }
  377. } else {
  378. $Rank = $SpecialRank = $TotalRank = $DonationTime = $ExpireTime = 0;
  379. }
  380. if (Permissions::is_mod($UserID)) {
  381. $Rank = MAX_EXTRA_RANK;
  382. $SpecialRank = MAX_SPECIAL_RANK;
  383. }
  384. G::$DB->query("
  385. SELECT
  386. `IconMouseOverText`,
  387. `AvatarMouseOverText`,
  388. `CustomIcon`,
  389. `CustomIconLink`,
  390. `SecondAvatar`
  391. FROM
  392. `donor_rewards`
  393. WHERE
  394. `UserID` = '$UserID'
  395. ");
  396. $Rewards = G::$DB->next_record(MYSQLI_ASSOC);
  397. G::$DB->set_query_id($QueryID);
  398. $DonorInfo = array(
  399. 'Rank' => (int) $Rank,
  400. 'SRank' => (int) $SpecialRank,
  401. 'TotRank' => (int) $TotalRank,
  402. 'Time' => $DonationTime,
  403. 'ExpireTime' => $ExpireTime,
  404. 'Rewards' => $Rewards
  405. );
  406. G::$Cache->cache_value("donor_info_$UserID", $DonorInfo, 0);
  407. }
  408. return $DonorInfo;
  409. }
  410. public static function get_rank($UserID)
  411. {
  412. return self::get_donor_info($UserID)['Rank'];
  413. }
  414. public static function get_special_rank($UserID)
  415. {
  416. return self::get_donor_info($UserID)['SRank'];
  417. }
  418. public static function get_total_rank($UserID)
  419. {
  420. return self::get_donor_info($UserID)['TotRank'];
  421. }
  422. public static function get_donation_time($UserID)
  423. {
  424. return self::get_donor_info($UserID)['Time'];
  425. }
  426. public static function get_personal_collages($UserID)
  427. {
  428. $DonorInfo = self::get_donor_info($UserID);
  429. if ($DonorInfo['SRank'] === MAX_SPECIAL_RANK) {
  430. $Collages = 5;
  431. } else {
  432. $Collages = min($DonorInfo['Rank'], 5); // One extra collage per donor rank up to 5
  433. }
  434. return $Collages;
  435. }
  436. public static function get_titles($UserID)
  437. {
  438. $Results = G::$Cache->get_value("donor_title_$UserID");
  439. if ($Results === false) {
  440. $QueryID = G::$DB->get_query_id();
  441. G::$DB->query("
  442. SELECT
  443. `Prefix`,
  444. `Suffix`,
  445. `UseComma`
  446. FROM
  447. `donor_forum_usernames`
  448. WHERE
  449. `UserID` = '$UserID'
  450. ");
  451. $Results = G::$DB->next_record();
  452. G::$DB->set_query_id($QueryID);
  453. G::$Cache->cache_value("donor_title_$UserID", $Results, 0);
  454. }
  455. return $Results;
  456. }
  457. public static function get_enabled_rewards($UserID)
  458. {
  459. $Rewards = [];
  460. $Rank = self::get_rank($UserID);
  461. $SpecialRank = self::get_special_rank($UserID);
  462. $HasAll = $SpecialRank === 3;
  463. $Rewards = array(
  464. 'HasAvatarMouseOverText' => false,
  465. 'HasCustomDonorIcon' => false,
  466. 'HasDonorForum' => false,
  467. 'HasDonorIconLink' => false,
  468. 'HasDonorIconMouseOverText' => false,
  469. 'HasProfileInfo1' => false,
  470. 'HasProfileInfo2' => false,
  471. 'HasProfileInfo3' => false,
  472. 'HasProfileInfo4' => false,
  473. 'HasSecondAvatar' => false);
  474. if ($Rank >= 2 || $HasAll) {
  475. $Rewards["HasDonorIconMouseOverText"] = true;
  476. $Rewards["HasProfileInfo1"] = true;
  477. }
  478. if ($Rank >= 3 || $HasAll) {
  479. $Rewards["HasAvatarMouseOverText"] = true;
  480. $Rewards["HasProfileInfo2"] = true;
  481. }
  482. if ($Rank >= 4 || $HasAll) {
  483. $Rewards["HasDonorIconLink"] = true;
  484. $Rewards["HasProfileInfo3"] = true;
  485. }
  486. if ($Rank >= MAX_RANK || $HasAll) {
  487. $Rewards["HasCustomDonorIcon"] = true;
  488. $Rewards["HasDonorForum"] = true;
  489. $Rewards["HasProfileInfo4"] = true;
  490. }
  491. if ($SpecialRank >= 2) {
  492. $Rewards["HasSecondAvatar"] = true;
  493. }
  494. return $Rewards;
  495. }
  496. public static function get_rewards($UserID)
  497. {
  498. return self::get_donor_info($UserID)['Rewards'];
  499. }
  500. public static function get_profile_rewards($UserID)
  501. {
  502. $Results = G::$Cache->get_value("donor_profile_rewards_$UserID");
  503. if ($Results === false) {
  504. $QueryID = G::$DB->get_query_id();
  505. G::$DB->query("
  506. SELECT
  507. `ProfileInfo1`,
  508. `ProfileInfoTitle1`,
  509. `ProfileInfo2`,
  510. `ProfileInfoTitle2`,
  511. `ProfileInfo3`,
  512. `ProfileInfoTitle3`,
  513. `ProfileInfo4`,
  514. `ProfileInfoTitle4`
  515. FROM
  516. `donor_rewards`
  517. WHERE
  518. `UserID` = '$UserID'
  519. ");
  520. $Results = G::$DB->next_record();
  521. G::$DB->set_query_id($QueryID);
  522. G::$Cache->cache_value("donor_profile_rewards_$UserID", $Results, 0);
  523. }
  524. return $Results;
  525. }
  526. private static function add_profile_info_reward($Counter, &$Insert, &$Values, &$Update)
  527. {
  528. if (isset($_POST["profile_title_" . $Counter]) && isset($_POST["profile_info_" . $Counter])) {
  529. $ProfileTitle = db_string($_POST["profile_title_" . $Counter]);
  530. $ProfileInfo = db_string($_POST["profile_info_" . $Counter]);
  531. $ProfileInfoTitleSQL = "ProfileInfoTitle" . $Counter;
  532. $ProfileInfoSQL = "ProfileInfo" . $Counter;
  533. $Insert[] = "$ProfileInfoTitleSQL";
  534. $Values[] = "'$ProfileInfoTitle'";
  535. $Update[] = "$ProfileInfoTitleSQL = '$ProfileTitle'";
  536. $Insert[] = "$ProfileInfoSQL";
  537. $Values[] = "'$ProfileInfo'";
  538. $Update[] = "$ProfileInfoSQL = '$ProfileInfo'";
  539. }
  540. }
  541. public static function update_rewards($UserID)
  542. {
  543. $Rank = self::get_rank($UserID);
  544. $SpecialRank = self::get_special_rank($UserID);
  545. $HasAll = $SpecialRank === 3;
  546. $Counter = 0;
  547. $Insert = [];
  548. $Values = [];
  549. $Update = [];
  550. $Insert[] = "UserID";
  551. $Values[] = "'$UserID'";
  552. if ($Rank >= 1 || $HasAll) {
  553. }
  554. if ($Rank >= 2 || $HasAll) {
  555. if (isset($_POST['donor_icon_mouse_over_text'])) {
  556. $IconMouseOverText = db_string($_POST['donor_icon_mouse_over_text']);
  557. $Insert[] = "IconMouseOverText";
  558. $Values[] = "'$IconMouseOverText'";
  559. $Update[] = "IconMouseOverText = '$IconMouseOverText'";
  560. }
  561. $Counter++;
  562. }
  563. if ($Rank >= 3 || $HasAll) {
  564. if (isset($_POST['avatar_mouse_over_text'])) {
  565. $AvatarMouseOverText = db_string($_POST['avatar_mouse_over_text']);
  566. $Insert[] = "AvatarMouseOverText";
  567. $Values[] = "'$AvatarMouseOverText'";
  568. $Update[] = "AvatarMouseOverText = '$AvatarMouseOverText'";
  569. }
  570. $Counter++;
  571. }
  572. if ($Rank >= 4 || $HasAll) {
  573. if (isset($_POST['donor_icon_link'])) {
  574. $CustomIconLink = db_string($_POST['donor_icon_link']);
  575. if (!Misc::is_valid_url($CustomIconLink)) {
  576. $CustomIconLink = '';
  577. }
  578. $Insert[] = "CustomIconLink";
  579. $Values[] = "'$CustomIconLink'";
  580. $Update[] = "CustomIconLink = '$CustomIconLink'";
  581. }
  582. $Counter++;
  583. }
  584. if ($Rank >= MAX_RANK || $HasAll) {
  585. if (isset($_POST['donor_icon_custom_url'])) {
  586. $CustomIcon = db_string($_POST['donor_icon_custom_url']);
  587. if (!Misc::is_valid_url($CustomIcon)) {
  588. $CustomIcon = '';
  589. }
  590. $Insert[] = "CustomIcon";
  591. $Values[] = "'$CustomIcon'";
  592. $Update[] = "CustomIcon = '$CustomIcon'";
  593. }
  594. self::update_titles($UserID, $_POST['donor_title_prefix'], $_POST['donor_title_suffix'], $_POST['donor_title_comma']);
  595. $Counter++;
  596. }
  597. for ($i = 1; $i <= $Counter; $i++) {
  598. self::add_profile_info_reward($i, $Insert, $Values, $Update);
  599. }
  600. if ($SpecialRank >= 2) {
  601. if (isset($_POST['second_avatar'])) {
  602. $SecondAvatar = db_string($_POST['second_avatar']);
  603. if (!Misc::is_valid_url($SecondAvatar)) {
  604. $SecondAvatar = '';
  605. }
  606. $Insert[] = "SecondAvatar";
  607. $Values[] = "'$SecondAvatar'";
  608. $Update[] = "SecondAvatar = '$SecondAvatar'";
  609. }
  610. }
  611. $Insert = implode(', ', $Insert);
  612. $Values = implode(', ', $Values);
  613. $Update = implode(', ', $Update);
  614. if ($Counter > 0) {
  615. $QueryID = G::$DB->get_query_id();
  616. G::$DB->query("
  617. INSERT INTO `donor_rewards`($Insert)
  618. VALUES($Values)
  619. ON DUPLICATE KEY
  620. UPDATE
  621. $Update
  622. ");
  623. G::$DB->set_query_id($QueryID);
  624. }
  625. G::$Cache->delete_value("donor_profile_rewards_$UserID");
  626. G::$Cache->delete_value("donor_info_$UserID");
  627. }
  628. public static function update_titles($UserID, $Prefix, $Suffix, $UseComma)
  629. {
  630. $QueryID = G::$DB->get_query_id();
  631. $Prefix = trim(db_string($Prefix));
  632. $Suffix = trim(db_string($Suffix));
  633. $UseComma = empty($UseComma);
  634. G::$DB->query("
  635. INSERT INTO `donor_forum_usernames`(
  636. `UserID`,
  637. `Prefix`,
  638. `Suffix`,
  639. `UseComma`
  640. )
  641. VALUES(
  642. '$UserID',
  643. '$Prefix',
  644. '$Suffix',
  645. '$UseComma'
  646. )
  647. ON DUPLICATE KEY
  648. UPDATE
  649. `Prefix` = '$Prefix',
  650. `Suffix` = '$Suffix',
  651. `UseComma` = '$UseComma'
  652. ");
  653. G::$Cache->delete_value("donor_title_$UserID");
  654. G::$DB->set_query_id($QueryID);
  655. }
  656. public static function get_donation_history($UserID)
  657. {
  658. $UserID = (int) $UserID;
  659. if (empty($UserID)) {
  660. error(404);
  661. }
  662. # todo: Investigate Rank in donations table
  663. $QueryID = G::$DB->get_query_id();
  664. G::$DB->query("
  665. SELECT
  666. `Amount`,
  667. `Email`,
  668. `Time`,
  669. `Currency`,
  670. `Reason`,
  671. `Source`,
  672. `AddedBy`,
  673. `Rank`,
  674. `TotalRank`
  675. FROM
  676. `donations`
  677. WHERE
  678. `UserID` = '$UserID'
  679. ORDER BY
  680. `Time`
  681. DESC
  682. ");
  683. $DonationHistory = G::$DB->to_array(false, MYSQLI_ASSOC, false);
  684. G::$DB->set_query_id($QueryID);
  685. return $DonationHistory;
  686. }
  687. public static function get_rank_expiration($UserID)
  688. {
  689. $DonorInfo = self::get_donor_info($UserID);
  690. if ($DonorInfo['SRank'] === MAX_SPECIAL_RANK || $DonorInfo['Rank'] === 1) {
  691. $Return = 'Never';
  692. } elseif ($DonorInfo['ExpireTime']) {
  693. $ExpireTime = strtotime($DonorInfo['ExpireTime']);
  694. if ($ExpireTime - time() < 60) {
  695. $Return = 'Soon';
  696. } else {
  697. $Expiration = time_diff($ExpireTime); // 32 days
  698. $Return = "in $Expiration";
  699. }
  700. } else {
  701. $Return = '';
  702. }
  703. return $Return;
  704. }
  705. public static function get_leaderboard_position($UserID)
  706. {
  707. $UserID = (int) $UserID;
  708. $QueryID = G::$DB->get_query_id();
  709. G::$DB->query("SET @RowNum := 0");
  710. G::$DB->query("
  711. SELECT
  712. `Position`
  713. FROM
  714. (
  715. SELECT
  716. d.UserID,
  717. @RowNum := @RowNum + 1 AS POSITION
  718. FROM
  719. `users_donor_ranks` AS d
  720. ORDER BY
  721. `TotalRank`
  722. DESC
  723. ) l
  724. WHERE
  725. `UserID` = '$UserID'
  726. ");
  727. if (G::$DB->has_results()) {
  728. list($Position) = G::$DB->next_record();
  729. } else {
  730. $Position = 0;
  731. }
  732. G::$DB->set_query_id($QueryID);
  733. return $Position;
  734. }
  735. public static function is_donor($UserID)
  736. {
  737. return self::get_rank($UserID) > 0;
  738. }
  739. public static function currency_exchange($Amount, $Currency)
  740. {
  741. if (!self::is_valid_currency($Currency)) {
  742. error("$Currency is not valid currency");
  743. }
  744. switch ($Currency) {
  745. case 'USD':
  746. $Amount = self::usd_to_euro($Amount);
  747. break;
  748. case 'BTC':
  749. $Amount = self::btc_to_euro($Amount);
  750. break;
  751. default:
  752. break;
  753. }
  754. return round($Amount, 2);
  755. }
  756. public static function is_valid_currency($Currency)
  757. {
  758. return $Currency === 'EUR' || $Currency === 'BTC' || $Currency === 'USD';
  759. }
  760. public static function btc_to_euro($Amount)
  761. {
  762. $Rate = G::$Cache->get_value('btc_rate');
  763. if (empty($Rate)) {
  764. G::$Cache->cache_value('btc_rate', $Rate, 86400);
  765. }
  766. return $Rate * $Amount;
  767. }
  768. public static function usd_to_euro($Amount)
  769. {
  770. $Rate = G::$Cache->get_value('usd_rate');
  771. if (empty($Rate)) {
  772. G::$Cache->cache_value('usd_rate', $Rate, 86400);
  773. }
  774. return $Rate * $Amount;
  775. }
  776. }