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