PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.2.0
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.2.0
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 All 66 releases
better-payment / includes / Campaign / CampaignStats.php

CampaignStats.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.2.0, at includes/Campaign/CampaignStats.php

123 lines 4.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\Campaign;
4
5 use Better_Payment\Lite\Controller;
6
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit;
9 }
10
11 /**
12 * Computes and caches campaign stats (total raised, donor count, progress %).
13 */
14 class CampaignStats extends Controller {
15
16 private static int $cache_ttl = 2 * MINUTE_IN_SECONDS;
17
18 /**
19 * Get stats for a campaign, using a 1-hour transient cache.
20 */
21 public static function get_stats( int $campaign_id, bool $use_cache = true ): array {
22 $transient_key = 'bpc_stats_' . $campaign_id;
23
24 if ( $use_cache ) {
25 $cached = get_transient( $transient_key );
26 if ( $cached !== false ) {
27 return $cached;
28 }
29 }
30
31 $raw = self::query_stats( $campaign_id );
32
33 $goal = (float) get_post_meta( $campaign_id, '_bpc_goal_amount', true );
34 $raised = $raw['total_raised'];
35
36 $progress = ( $goal > 0 ) ? min( 100.0, round( ( $raised / $goal ) * 100, 1 ) ) : 0.0;
37
38 $end_date = get_post_meta( $campaign_id, '_bpc_end_date', true );
39 $days_remaining = null;
40
41 if ( $end_date ) {
42 $diff = ( strtotime( $end_date ) - current_time( 'timestamp' ) );
43 $days_remaining = max( 0, (int) ceil( $diff / DAY_IN_SECONDS ) );
44 }
45
46 $stats = apply_filters( 'better_payment/campaign/stats', array_merge( $raw, [
47 'goal' => $goal,
48 'progress' => $progress,
49 'days_remaining' => $days_remaining,
50 ] ), $campaign_id );
51
52 set_transient( $transient_key, $stats, self::$cache_ttl );
53
54 return $stats;
55 }
56
57 /**
58 * Bust the stats cache for a campaign — call after a new payment is linked.
59 */
60 public static function bust_cache( int $campaign_id ) {
61 delete_transient( 'bpc_stats_' . $campaign_id );
62 }
63
64 /**
65 * Register WordPress hooks.
66 * Called once from the plugin bootstrap.
67 */
68 public static function register_hooks(): void {
69 // Bust cache when a payment is confirmed (status updated to a successful state).
70 // Fires from Handler.php after each gateway's wpdb->update() call.
71 add_action( 'better_payment/payment_confirmed', [ static::class, 'on_payment_confirmed' ] );
72 }
73
74 /**
75 * Look up the campaign_id on the confirmed payment row and bust its stats cache.
76 *
77 * @param int $payment_id Row ID in wp_better_payment.
78 */
79 public static function on_payment_confirmed( int $payment_id ): void {
80 global $wpdb;
81 $campaign_id = (string) $wpdb->get_var(
82 $wpdb->prepare(
83 "SELECT campaign_id FROM {$wpdb->prefix}better_payment WHERE id = %d LIMIT 1",
84 $payment_id
85 )
86 );
87 if ( $campaign_id !== '' && $campaign_id !== '0' ) {
88 self::bust_cache( (int) $campaign_id );
89 }
90 }
91
92 private static function query_stats( int $campaign_id ): array {
93 global $wpdb;
94
95 $payment_table = $wpdb->prefix . 'better_payment';
96 $approved_statuses = "'" . implode( "','", array_map( 'esc_sql', self::approved_statuses() ) ) . "'";
97
98 $row = $wpdb->get_row(
99 $wpdb->prepare(
100 "SELECT
101 COALESCE(SUM(amount), 0) AS total_raised,
102 COUNT(DISTINCT email) AS donor_count,
103 MAX(payment_date) AS last_donation_date
104 FROM `{$payment_table}`
105 WHERE campaign_id = %s
106 AND status IN ({$approved_statuses})",
107 (string) $campaign_id
108 ),
109 ARRAY_A
110 );
111
112 return [
113 'total_raised' => (float) ( $row['total_raised'] ?? 0 ),
114 'donor_count' => (int) ( $row['donor_count'] ?? 0 ),
115 'last_donation_date' => $row['last_donation_date'] ?? null,
116 ];
117 }
118
119 private static function approved_statuses(): array {
120 return [ 'Completed', 'paid', 'complete', 'succeeded' ];
121 }
122 }
123