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