PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.10.4
GiveWP – Donation Plugin and Fundraising Platform v2.10.4
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 5 years ago
Donations.php
382 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 * @param int $donorId
113 * @since 2.10.0
114 * @return array Donations
115 */
116 public function getDonations( $donorId ) {
117
118 $ids = $this->getDonationIds( $donorId );
119
120 if ( $ids === null ) {
121 return null;
122 }
123
124 $args = [
125 'number' => -1,
126 'post__in' => $ids,
127 ];
128
129 $query = new \Give_Payments_Query( $args );
130 $payments = $query->get_payments();
131
132 $donations = [];
133 foreach ( $payments as $payment ) {
134 $donations[] = [
135 'id' => $payment->ID,
136 'form' => $this->getFormInfo( $payment ),
137 'payment' => $this->getPaymentInfo( $payment ),
138 'donor' => $this->getDonorInfo( $payment ),
139 'receipt' => $this->getReceiptInfo( $payment ),
140 ];
141 }
142 return $donations;
143 }
144
145 /**
146 * Get form info
147 *
148 * @param Give_Payment $payment
149 * @since 2.10.0
150 * @return array Payment form info
151 */
152 protected function getFormInfo( $payment ) {
153 return [
154 'title' => wp_trim_words( $payment->form_title, 6, ' [...]' ),
155 'id' => $payment->form_id,
156 ];
157 }
158
159 /**
160 * Get payment info
161 *
162 * @param Give_Payment $payment
163 * @since 2.10.0
164 * @return array Payment info
165 */
166 protected function getPaymentInfo( $payment ) {
167
168 $pdfReceiptUrl = '';
169 if ( class_exists( 'Give_PDF_Receipts' ) ) {
170 $pdfReceiptUrl = html_entity_decode( give_pdf_receipts()->engine->get_pdf_receipt_url( $payment->ID ) );
171 }
172
173 $gateways = give_get_payment_gateways();
174
175 return [
176 'amount' => $this->getFormattedAmount( $payment->subtotal, $payment ),
177 'currency' => $payment->currency,
178 'fee' => $this->getFormattedAmount( ( $payment->total - $payment->subtotal ), $payment ),
179 'total' => $this->getFormattedAmount( $payment->total, $payment ),
180 'method' => isset( $gateways[ $payment->gateway ]['checkout_label'] ) ? $gateways[ $payment->gateway ]['checkout_label'] : '',
181 'status' => $this->getFormattedStatus( $payment->status ),
182 'date' => date_i18n( give_date_format( 'checkout' ), strtotime( $payment->date ) ),
183 'time' => date_i18n( 'g:i a', strtotime( $payment->date ) ),
184 'mode' => $payment->get_meta( '_give_payment_mode' ),
185 'pdfReceiptUrl' => $pdfReceiptUrl,
186 'serialCode' => give_is_setting_enabled( give_get_option( 'sequential-ordering_status', 'disabled' ) ) ? Give()->seq_donation_number->get_serial_code( $payment ) : $payment->ID,
187 ];
188 }
189
190 /**
191 * Get array containing dynamic receipt information
192 *
193 * @param Give_Payment $payment
194 * @return array
195 * @since 2.10.0
196 */
197 protected function getReceiptInfo( $payment ) {
198
199 $receipt = new DonationReceipt( $payment->ID );
200
201 /**
202 * Fire the action for receipt object.
203 *
204 * @since 2.7.0
205 */
206 do_action( 'give_new_receipt', $receipt );
207
208 $receiptArr = [];
209
210 $sectionIndex = 0;
211 foreach ( $receipt as $section ) {
212 // Continue if section does not have line items.
213 if ( ! $section->getLineItems() ) {
214 continue;
215 }
216
217 if ( 'PDFReceipt' === $section->id ) {
218 continue;
219 }
220
221 if ( 'Subscription' === $section->id ) {
222 continue;
223 }
224
225 $receiptArr[ $sectionIndex ]['id'] = $section->id;
226
227 if ( $section->label ) {
228 $receiptArr[ $sectionIndex ]['label'] = $section->label;
229 }
230
231 /* @var LineItem $lineItem */
232 foreach ( $section as $lineItem ) {
233 // Continue if line item does not have value.
234 if ( ! $lineItem->value ) {
235 continue;
236 }
237
238 // This class is required to highlight total donation amount in receipt.
239 $detailRowClass = '';
240 if ( DonationReceipt::DONATIONSECTIONID === $section->id ) {
241 $detailRowClass = 'totalAmount' === $lineItem->id ? ' total' : '';
242 }
243
244 $label = html_entity_decode( wp_strip_all_tags( $lineItem->label ) );
245 $value = $lineItem->id === 'paymentStatus' ? $this->getFormattedStatus( $payment->status ) : html_entity_decode( wp_strip_all_tags( $lineItem->value ) );
246
247 $receiptArr[ $sectionIndex ]['lineItems'][] = [
248 'class' => $detailRowClass,
249 'icon' => $this->getIcon( $lineItem->icon ),
250 'label' => $label,
251 'value' => $value,
252 ];
253
254 }
255
256 $sectionIndex++;
257 }
258
259 return $receiptArr;
260 }
261
262 /**
263 * Get icon based on icon HTML string
264 *
265 * @param string $iconHtml
266 * @return string
267 * @since 2.10.0
268 */
269 protected function getIcon( $iconHtml ) {
270
271 if ( empty( $iconHtml ) ) {
272 return '';
273 }
274
275 $iconMap = [
276 'user',
277 'envelope',
278 'globe',
279 'calendar',
280 'building',
281 ];
282
283 foreach ( $iconMap as $icon ) {
284 if ( strpos( $iconHtml, $icon ) !== false ) {
285 return $icon;
286 }
287 }
288
289 }
290
291 /**
292 * Get formatted status object (used for rendering status correctly in Donor Profile)
293 *
294 * @param string $status
295 * @since 2.10.0
296 * @return array Formatted status object (with color and label)
297 */
298 protected function getFormattedStatus( $status ) {
299
300 $statusMap = [];
301
302 $colorMap = [
303 'publish' => '#7ad03a',
304 'give_subscription' => '#5bc0de',
305 'refunded' => '#777',
306 'failed' => '#a00',
307 'abandoned' => '#333',
308 'revoked' => '#d9534f',
309 'pending' => '#ffba00',
310 ];
311
312 foreach ( give_get_payment_statuses() as $key => $value ) {
313
314 if ( $status !== $key ) {
315 continue;
316 }
317
318 $color = '#888';
319 if ( in_array( $key, array_keys( $colorMap ) ) ) {
320 $color = $colorMap[ $key ];
321 }
322
323 $statusMap[ $key ] = [
324 'color' => $color,
325 'label' => $value,
326 ];
327
328 }
329
330 return isset( $statusMap[ $status ] ) ? $statusMap[ $status ] : [
331 'color' => '#FFBA00',
332 'label' => esc_html__( 'Unknown', 'give' ),
333 ];
334 }
335
336 protected function getAmountWithSeparators( $amount ) {
337 $formatted = give_format_amount(
338 $amount,
339 [
340 'decimal' => false,
341 ]
342 );
343
344 return $formatted ? $formatted : (string) $amount;
345 }
346
347 /**
348 * Get formatted payment amount
349 *
350 * @param float $amount
351 * @param Give_Payment $payment
352 * @since 2.10.0
353 * @return string Formatted payment amount (with correct decimals and currency symbol)
354 */
355 protected function getformattedAmount( $amount, $payment ) {
356 return give_currency_filter(
357 give_format_amount(
358 $amount,
359 [
360 'donation_id' => $payment->ID,
361 ]
362 ),
363 [
364 'currency_code' => $payment->currency,
365 'decode_currency' => true,
366 'sanitize' => false,
367 ]
368 );
369 }
370
371 /**
372 * Get donor info
373 *
374 * @param Give_Payment $payment
375 * @since 2.10.0
376 * @return array Donor info
377 */
378 protected function getDonorInfo( $payment ) {
379 return $payment->user_info;
380 }
381 }
382