PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / trunk
GiveWP – Donation Plugin and Fundraising Platform vtrunk
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / Donations / Migrations / RecalculateExchangeRate.php
give / src / Donations / Migrations Last commit date
AddMissingDonorIdToDonationComments.php 1 year ago MoveDonationCommentToDonationMetaTable.php 3 years ago RecalculateExchangeRate.php 1 year ago SetAutomaticFormattingOption.php 3 years ago UnserializeTitlePrefix.php 1 year ago
RecalculateExchangeRate.php
164 lines
1 <?php
2
3 namespace Give\Donations\Migrations;
4
5 use Give\Donations\ValueObjects\DonationMetaKeys;
6 use Give\Framework\Database\DB;
7 use Give\Framework\Database\Exceptions\DatabaseQueryException;
8 use Give\Framework\Migrations\Contracts\BatchMigration;
9 use Give\Framework\Migrations\Exceptions\DatabaseMigrationException;
10 use Give\Framework\QueryBuilder\QueryBuilder;
11 use Give\Framework\Support\ValueObjects\Money;
12
13 /**
14 * @since 4.2.0
15 */
16 class RecalculateExchangeRate extends BatchMigration
17 {
18 /**
19 * @inheritDoc
20 */
21 public static function id(): string
22 {
23 return 'recalculate_exchange_rate';
24 }
25
26 /**
27 * @inheritDoc
28 */
29 public static function title(): string
30 {
31 return 'Recalculate exchange rate';
32 }
33
34 /**
35 * @inheritdoc
36 */
37 public static function timestamp(): string
38 {
39 return strtotime('2025-04-24 00:00:00');
40 }
41
42 /**
43 * Base query to find donations that need exchange rate recalculation
44 *
45 * @since 4.2.0
46 */
47 protected function query(): QueryBuilder
48 {
49 return DB::table('posts', 'posts')
50 ->where('posts.post_type', 'give_payment')
51 ->orderBy('posts.ID', 'ASC');
52 }
53
54 /**
55 * @inheritDoc
56 * @throws DatabaseMigrationException
57 */
58 public function runBatch($firstId, $lastId): void
59 {
60 try {
61 // Select donations where base currency is not empty,
62 // base currency is different from payment currency,
63 // and either the exchange rate does not exist or is equal to 1
64
65 $query = $this->query()
66 ->select('posts.ID')
67 ->attachMeta(
68 'give_donationmeta',
69 'ID',
70 'donation_id',
71 [DonationMetaKeys::AMOUNT, 'amount'],
72 [DonationMetaKeys::CURRENCY, 'currency'],
73 [DonationMetaKeys::BASE_AMOUNT, 'baseAmount'],
74 [DonationMetaKeys::EXCHANGE_RATE, 'exchangeRate'],
75 ['_give_cs_base_currency', 'baseCurrency']
76 )
77 ->whereIsNotNull('give_donationmeta_attach_meta_baseAmount.meta_value')
78 ->whereRaw('AND give_donationmeta_attach_meta_baseCurrency.meta_value != give_donationmeta_attach_meta_currency.meta_value')
79 ->where(function ($query) {
80 $query->where('give_donationmeta_attach_meta_exchangeRate.meta_value', '1')
81 ->orWhereIsNull('give_donationmeta_attach_meta_exchangeRate.meta_value');
82 });
83
84 // Migration Runner will pass null for lastId in the last step
85 if (is_null($lastId)) {
86 $query->where('posts.ID', $firstId, '>');
87 } else {
88 $query->whereBetween('posts.ID', $firstId, $lastId);
89 }
90
91 $donations = $query->getAll();
92
93 foreach ($donations as $donation) {
94 $amount = Money::fromDecimal($donation->amount, $donation->currency);
95 $baseAmount = Money::fromDecimal($donation->baseAmount, $donation->baseCurrency);
96
97 if ($baseAmount->formatToDecimal() === '0') {
98 continue;
99 }
100
101 /** @var Money $exchangeRate */
102 $exchangeRate = $amount->divide($baseAmount->formatToDecimal());
103
104 give()->payment_meta->update_meta($donation->ID, DonationMetaKeys::EXCHANGE_RATE, $exchangeRate->formatToDecimal());
105 }
106 } catch (DatabaseQueryException $exception) {
107 throw new DatabaseMigrationException(
108 'An error occurred while updating donation exchange rates',
109 0,
110 $exception
111 );
112 }
113 }
114
115 /**
116 * @inheritDoc
117 */
118 public function getItemsCount(): int
119 {
120 return $this->query()->count();
121 }
122
123 /**
124 * @inheritDoc
125 */
126 public function getBatchItemsAfter($lastId): ?array
127 {
128 $subquerySQL = $this->query()
129 ->where('ID', $lastId, '>')
130 ->limit($this->getBatchSize())
131 ->getSQL();
132
133 $item = DB::get_row("SELECT MIN(ID) AS first_id, MAX(ID) AS last_id FROM ($subquerySQL) as batch");
134
135 if (!$item) {
136 return null;
137 }
138
139 return [
140 $item->first_id,
141 $item->last_id,
142 ];
143 }
144
145 /**
146 * @inheritDoc
147 */
148 public function getBatchSize(): int
149 {
150 return 100;
151 }
152
153 /**
154 * @inheritDoc
155 */
156 public function hasMoreItemsToBatch($lastProcessedId): ?bool
157 {
158 return $this->query()
159 ->where('posts.ID', $lastProcessedId, '>')
160 ->limit(1)
161 ->count();
162 }
163 }
164