PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.12.3
GiveWP – Donation Plugin and Fundraising Platform v2.12.3
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 / DonorDashboards / Repositories / Donations.php
give / src / DonorDashboards / Repositories Last commit date
Donations.php 4 years ago
Donations.php
385 lines
1 <?php
2 namespace Give\DonorDashboards\Repositories;
3
4 use Give\ValueObjects\Money;
5 use Give\Framework\Database\DB;
6 use Give\Receipt\DonationReceipt;
7 use InvalidArgumentException;
8
9 /**
10 * @since 2.10.0
11 */
12 class Donations {
13 /**
14 * Get donations count for donor
15 *
16 * @param int $donorId
17 * @since 2.10.0
18 *
19 * @return int
20 */
21 public function getDonationCount( $donorId ) {
22 $aggregate = $this->getDonationAggregate( 'count(revenue.id)', $donorId );
23 return $aggregate ? $aggregate->result : null;
24 }
25
26 /**
27 * Get donor revenue
28 *
29 * @param int $donorId
30 * @since 2.10.0
31 *
32 * @return string
33 */
34 public function getRevenue( $donorId ) {
35 $aggregate = $this->getDonationAggregate( 'sum(revenue.amount)', $donorId );
36 return $aggregate ? $this->getAmountWithSeparators( Money::ofMinor( $aggregate->result, give_get_option( 'currency' ) )->getAmount() ) : null;
37 }
38
39 /**
40 * Get average donor revenue
41 *
42 * @param int $donorId
43 * @since 2.10.0
44 *
45 * @return string
46 */
47 public function getAverageRevenue( $donorId ) {
48 $aggregate = $this->getDonationAggregate( 'avg(revenue.amount)', $donorId );
49 return $aggregate ? $this->getAmountWithSeparators( Money::ofMinor( $aggregate->result, give_get_option( 'currency' ) )->getAmount() ) : null;
50 }
51
52 /**
53 * Generates a donation aggregate for a given donor
54 *
55 * @param string $rawAggregate raw SELECT to determine what to aggregate over
56 * @param int $donorId
57 *
58 * @return object
59 */
60 private function getDonationAggregate( $rawAggregate, $donorId ) {
61 global $wpdb;
62
63 return DB::get_row(
64 DB::prepare(
65 "
66 SELECT {$rawAggregate} as result
67 FROM {$wpdb->give_revenue} as revenue
68 INNER JOIN {$wpdb->posts} as posts ON revenue.donation_id = posts.ID
69 INNER JOIN {$wpdb->prefix}give_donationmeta as donationmeta ON revenue.donation_id = donationmeta.donation_id
70 WHERE donationmeta.meta_key = '_give_payment_donor_id'
71 AND donationmeta.meta_value = %d
72 AND posts.post_status IN ( 'publish', 'give_subscription' )
73 ",
74 $donorId
75 )
76 );
77 }
78
79 /**
80 * Get all donation ids by donor ID
81 *
82 * @param int $donorId
83 * @since 2.10.0
84 * @return int[] Donation IDs
85 */
86 protected function getDonationIDs( $donorId ) {
87
88 $statusKeys = give_get_payment_status_keys();
89 $statusQuery = "'" . implode( "','", $statusKeys ) . "'";
90
91 global $wpdb;
92 return DB::get_col(
93 DB::prepare(
94 "
95 SELECT revenue.donation_id as id
96 FROM {$wpdb->give_revenue} as revenue
97 INNER JOIN {$wpdb->posts} as posts ON revenue.donation_id = posts.ID
98 INNER JOIN {$wpdb->prefix}give_donationmeta as donationmeta ON revenue.donation_id = donationmeta.donation_id
99 WHERE donationmeta.meta_key = '_give_payment_donor_id'
100 AND donationmeta.meta_value = %d
101 AND posts.post_status IN ( {$statusQuery} )
102 ",
103 $donorId
104 )
105 );
106 }
107
108
109 /**
110 * Get all donations by donor ID
111 *
112 * @since 2.12.2 return null if donation ids is empty
113 * @since 2.10.0
114 *
115 * @param int $donorId
116 *
117 * @return array Donations
118 */
119 public function getDonations( $donorId ) {
120
121 $ids = $this->getDonationIds( $donorId );
122
123 if ( empty( $ids ) ) {
124 return null;
125 }
126
127 $args = [
128 'number' => -1,
129 'post__in' => $ids,
130 ];
131
132 $query = new \Give_Payments_Query( $args );
133 $payments = $query->get_payments();
134
135 $donations = [];
136 foreach ( $payments as $payment ) {
137 $donations[] = [
138 'id' => $payment->ID,
139 'form' => $this->getFormInfo( $payment ),
140 'payment' => $this->getPaymentInfo( $payment ),
141 'donor' => $this->getDonorInfo( $payment ),
142 'receipt' => $this->getReceiptInfo( $payment ),
143 ];
144 }
145 return $donations;
146 }
147
148 /**
149 * Get form info
150 *
151 * @param Give_Payment $payment
152 * @since 2.10.0
153 * @return array Payment form info
154 */
155 protected function getFormInfo( $payment ) {
156 return [
157 'title' => wp_trim_words( $payment->form_title, 6, ' [...]' ),
158 'id' => $payment->form_id,
159 ];
160 }
161
162 /**
163 * Get payment info
164 *
165 * @param Give_Payment $payment
166 * @since 2.10.0
167 * @return array Payment info
168 */
169 protected function getPaymentInfo( $payment ) {
170
171 $pdfReceiptUrl = '';
172 if ( class_exists( 'Give_PDF_Receipts' ) ) {
173 $pdfReceiptUrl = html_entity_decode( give_pdf_receipts()->engine->get_pdf_receipt_url( $payment->ID ) );
174 }
175
176 $gateways = give_get_payment_gateways();
177
178 return [
179 'amount' => $this->getFormattedAmount( $payment->subtotal, $payment ),
180 'currency' => $payment->currency,
181 'fee' => $this->getFormattedAmount( ( $payment->total - $payment->subtotal ), $payment ),
182 'total' => $this->getFormattedAmount( $payment->total, $payment ),
183 'method' => isset( $gateways[ $payment->gateway ]['checkout_label'] ) ? $gateways[ $payment->gateway ]['checkout_label'] : '',
184 'status' => $this->getFormattedStatus( $payment->status ),
185 'date' => date_i18n( give_date_format( 'checkout' ), strtotime( $payment->date ) ),
186 'time' => date_i18n( 'g:i a', strtotime( $payment->date ) ),
187 'mode' => $payment->get_meta( '_give_payment_mode' ),
188 'pdfReceiptUrl' => $pdfReceiptUrl,
189 'serialCode' => give_is_setting_enabled( give_get_option( 'sequential-ordering_status', 'disabled' ) ) ? Give()->seq_donation_number->get_serial_code( $payment ) : $payment->ID,
190 ];
191 }
192
193 /**
194 * Get array containing dynamic receipt information
195 *
196 * @param Give_Payment $payment
197 * @return array
198 * @since 2.10.0
199 */
200 protected function getReceiptInfo( $payment ) {
201
202 $receipt = new DonationReceipt( $payment->ID );
203
204 /**
205 * Fire the action for receipt object.
206 *
207 * @since 2.7.0
208 */
209 do_action( 'give_new_receipt', $receipt );
210
211 $receiptArr = [];
212
213 $sectionIndex = 0;
214 foreach ( $receipt as $section ) {
215 // Continue if section does not have line items.
216 if ( ! $section->getLineItems() ) {
217 continue;
218 }
219
220 if ( 'PDFReceipt' === $section->id ) {
221 continue;
222 }
223
224 if ( 'Subscription' === $section->id ) {
225 continue;
226 }
227
228 $receiptArr[ $sectionIndex ]['id'] = $section->id;
229
230 if ( $section->label ) {
231 $receiptArr[ $sectionIndex ]['label'] = $section->label;
232 }
233
234 /* @var LineItem $lineItem */
235 foreach ( $section as $lineItem ) {
236 // Continue if line item does not have value.
237 if ( ! $lineItem->value ) {
238 continue;
239 }
240
241 // This class is required to highlight total donation amount in receipt.
242 $detailRowClass = '';
243 if ( DonationReceipt::DONATIONSECTIONID === $section->id ) {
244 $detailRowClass = 'totalAmount' === $lineItem->id ? ' total' : '';
245 }
246
247 $label = html_entity_decode( wp_strip_all_tags( $lineItem->label ) );
248 $value = $lineItem->id === 'paymentStatus' ? $this->getFormattedStatus( $payment->status ) : html_entity_decode( wp_strip_all_tags( $lineItem->value ) );
249
250 $receiptArr[ $sectionIndex ]['lineItems'][] = [
251 'class' => $detailRowClass,
252 'icon' => $this->getIcon( $lineItem->icon ),
253 'label' => $label,
254 'value' => $value,
255 ];
256
257 }
258
259 $sectionIndex++;
260 }
261
262 return $receiptArr;
263 }
264
265 /**
266 * Get icon based on icon HTML string
267 *
268 * @param string $iconHtml
269 * @return string
270 * @since 2.10.0
271 */
272 protected function getIcon( $iconHtml ) {
273
274 if ( empty( $iconHtml ) ) {
275 return '';
276 }
277
278 $iconMap = [
279 'user',
280 'envelope',
281 'globe',
282 'calendar',
283 'building',
284 ];
285
286 foreach ( $iconMap as $icon ) {
287 if ( strpos( $iconHtml, $icon ) !== false ) {
288 return $icon;
289 }
290 }
291
292 }
293
294 /**
295 * Get formatted status object (used for rendering status correctly in Donor Profile)
296 *
297 * @param string $status
298 * @since 2.10.0
299 * @return array Formatted status object (with color and label)
300 */
301 protected function getFormattedStatus( $status ) {
302
303 $statusMap = [];
304
305 $colorMap = [
306 'publish' => '#7ad03a',
307 'give_subscription' => '#5bc0de',
308 'refunded' => '#777',
309 'failed' => '#a00',
310 'abandoned' => '#333',
311 'revoked' => '#d9534f',
312 'pending' => '#ffba00',
313 ];
314
315 foreach ( give_get_payment_statuses() as $key => $value ) {
316
317 if ( $status !== $key ) {
318 continue;
319 }
320
321 $color = '#888';
322 if ( in_array( $key, array_keys( $colorMap ) ) ) {
323 $color = $colorMap[ $key ];
324 }
325
326 $statusMap[ $key ] = [
327 'color' => $color,
328 'label' => $value,
329 ];
330
331 }
332
333 return isset( $statusMap[ $status ] ) ? $statusMap[ $status ] : [
334 'color' => '#FFBA00',
335 'label' => esc_html__( 'Unknown', 'give' ),
336 ];
337 }
338
339 protected function getAmountWithSeparators( $amount ) {
340 $formatted = give_format_amount(
341 $amount,
342 [
343 'decimal' => false,
344 ]
345 );
346
347 return $formatted ? $formatted : (string) $amount;
348 }
349
350 /**
351 * Get formatted payment amount
352 *
353 * @param float $amount
354 * @param Give_Payment $payment
355 * @since 2.10.0
356 * @return string Formatted payment amount (with correct decimals and currency symbol)
357 */
358 protected function getformattedAmount( $amount, $payment ) {
359 return give_currency_filter(
360 give_format_amount(
361 $amount,
362 [
363 'donation_id' => $payment->ID,
364 ]
365 ),
366 [
367 'currency_code' => $payment->currency,
368 'decode_currency' => true,
369 'sanitize' => false,
370 ]
371 );
372 }
373
374 /**
375 * Get donor info
376 *
377 * @param Give_Payment $payment
378 * @since 2.10.0
379 * @return array Donor info
380 */
381 protected function getDonorInfo( $payment ) {
382 return $payment->user_info;
383 }
384 }
385