PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / trunk
GiveWP – Donation Plugin and Fundraising Platform vtrunk
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 / Campaigns / Repositories / CampaignsDataRepository.php
give / src / Campaigns / Repositories Last commit date
CampaignPageRepository.php 7 months ago CampaignRepository.php 1 year ago CampaignsDataRepository.php 9 months ago
CampaignsDataRepository.php
242 lines
1 <?php
2
3 namespace Give\Campaigns\Repositories;
4
5 use Give\Campaigns\CampaignsDataQuery;
6 use Give\Campaigns\Models\Campaign;
7 use Give\Campaigns\ValueObjects\CampaignGoalType;
8
9 /**
10 * Used to optimize the campaigns list table performance and to avoid n+1 problems.
11 * Instead of doing expensive queries in multiple columns in each row, this class loads everything upfront for multiple campaigns.
12 *
13 * @since 4.0.0
14 */
15 class CampaignsDataRepository
16 {
17 /**
18 * @var array
19 */
20 private $amounts;
21 /**
22 * @var array
23 */
24 private $subscriptionAmounts = [];
25 /**
26 * @var array
27 */
28 private $donationsCount;
29 /**
30 * @var array
31 */
32 private $subscriptionDonationsCount = [];
33 /**
34 * @var array
35 */
36 private $donorsCount;
37 /**
38 * @var array
39 */
40 private $subscriptionDonorsCount = [];
41
42 /**
43 *
44 * @since 4.8.0 added data caching layer
45 *
46 * @param int[] $ids
47 *
48 * @return CampaignsDataRepository
49 */
50 public static function campaigns(array $ids): CampaignsDataRepository
51 {
52 $self = new self();
53 $campaignsData = get_option('give_campaigns_data', []);
54 $campaignsSubscriptionData = get_option('give_campaigns_subscription_data', []);
55
56 // remove cached campaign ids
57 $campaignIds = array_filter($ids, function ($id) use ($campaignsData) {
58 foreach ($campaignsData as $row) {
59 foreach($row as $campaign) {
60 if ($campaign['campaign_id'] == $id) {
61 return false;
62 }
63 }
64 }
65
66 return true;
67 });
68
69 if (
70 ! empty($campaignsData['donationsCount'])
71 || ! empty($campaignsSubscriptionData['donationsCount'])
72 ) {
73 $self->amounts = $campaignsData['amounts'];
74 $self->donationsCount = $campaignsData['donationsCount'];
75 $self->donorsCount = $campaignsData['donorsCount'];
76
77 if (defined('GIVE_RECURRING_VERSION')) {
78 $self->subscriptionAmounts = $campaignsSubscriptionData['amounts'];
79 $self->subscriptionDonationsCount = $campaignsSubscriptionData['donationsCount'];
80 $self->subscriptionDonorsCount = $campaignsSubscriptionData['donorsCount'];
81 }
82
83 return $self;
84 }
85
86 // Fetch data from db
87 $donations = CampaignsDataQuery::donations($campaignIds);
88
89 $self->amounts = $donations->collectIntendedAmounts();
90 $self->donationsCount = $donations->collectDonations();
91 $self->donorsCount = $donations->collectDonors();
92
93 // cache campaigns data
94 update_option('give_campaigns_data', [
95 'amounts' => array_merge($campaignsData['amounts'] ?? [], $self->amounts),
96 'donationsCount' => array_merge($campaignsData['donationsCount'] ?? [], $self->donationsCount),
97 'donorsCount' => array_merge($campaignsData['donorsCount'] ?? [], $self->donorsCount),
98 ]);
99
100 // Set subscriptions data
101 if (defined('GIVE_RECURRING_VERSION')) {
102 $subscriptions = CampaignsDataQuery::subscriptions($campaignIds);
103
104 $self->subscriptionAmounts = $subscriptions->collectInitialAmounts();
105 $self->subscriptionDonationsCount = $subscriptions->collectDonations();
106 $self->subscriptionDonorsCount = $subscriptions->collectDonors();
107
108 // cache campaigns subscriptions data
109 update_option('give_campaigns_subscriptions_data', [
110 'amounts' => array_merge($campaignsSubscriptionData['amounts'] ?? [], $self->subscriptionAmounts),
111 'donationsCount' => array_merge($campaignsSubscriptionData['donationsCount'] ?? [], $self->subscriptionDonationsCount),
112 'donorsCount' => array_merge($campaignsSubscriptionData['donorsCount'] ?? [], $self->subscriptionDonorsCount),
113 ]);
114 }
115
116 return $self;
117 }
118
119 /**
120 * @since 4.2.0 return type of float
121 * @since 4.0.0
122 *
123 * Get revenue for campaign
124 *
125 * @param Campaign $campaign
126 */
127 public function getRevenue(Campaign $campaign): float
128 {
129 $data = $campaign->goalType->isSubscriptions()
130 ? $this->subscriptionAmounts
131 : $this->amounts;
132
133 foreach ($data as $row) {
134 if (isset($row['campaign_id']) && $row['campaign_id'] == $campaign->id) {
135 return $row['sum'];
136 }
137 }
138
139 return 0;
140 }
141
142 /**
143 * @since 4.0.0
144 *
145 * Get donations count for campaign
146 *
147 * @param Campaign $campaign
148 *
149 * @return int
150 */
151 public function getDonationsCount(Campaign $campaign): int
152 {
153 $data = $campaign->goalType->isSubscriptions()
154 ? $this->subscriptionDonationsCount
155 : $this->donationsCount;
156
157 foreach ($data as $row) {
158 if (isset($row['campaign_id']) && $row['campaign_id'] == $campaign->id) {
159 return (int)$row['count'];
160 }
161 }
162
163 return 0;
164 }
165
166 /**
167 * @since 4.0.0
168 *
169 * Get donors count for campaign
170 *
171 * @param Campaign $campaign
172 *
173 * @return int
174 */
175 public function getDonorsCount(Campaign $campaign): int
176 {
177 $data = $campaign->goalType->isSubscriptions()
178 ? $this->subscriptionDonorsCount
179 : $this->donorsCount;
180
181 foreach ($data as $row) {
182 if (isset($row['campaign_id']) && $row['campaign_id'] == $campaign->id) {
183 return (int)$row['count'];
184 }
185 }
186
187 return 0;
188 }
189
190
191 /**
192 * @since 4.0.0
193 *
194 * Get goal data for campaign
195 *
196 * @param Campaign $campaign
197 *
198 * @return array{actual: int, goal: int, actualFormatted: string, goalFormatted:string, percentage:float}
199 */
200 public function getGoalData(Campaign $campaign): array
201 {
202 $actual = $this->getActualGoal($campaign);
203 $percentage = $campaign->goal
204 ? $actual / $campaign->goal
205 : 0;
206
207 return [
208 'actual' => $actual,
209 'goal' => $campaign->goal,
210 'actualFormatted' => $campaign->goalType == CampaignGoalType::AMOUNT
211 ? give_currency_filter(give_format_amount($actual))
212 : $actual,
213 'goalFormatted' => $campaign->goalType == CampaignGoalType::AMOUNT
214 ? give_currency_filter(give_format_amount($campaign->goal))
215 : $campaign->goal,
216 'percentage' => round($percentage * 100, 2),
217 ];
218 }
219
220 /**
221 * @since 4.2.0 return union type int|float
222 * @since 4.0.0
223 *
224 * @param Campaign $campaign
225 *
226 * @return int|float
227 */
228 private function getActualGoal(Campaign $campaign)
229 {
230 switch ($campaign->goalType->getValue()) {
231 case CampaignGoalType::DONATIONS():
232 case CampaignGoalType::SUBSCRIPTIONS():
233 return $this->getDonationsCount($campaign);
234 case CampaignGoalType::DONORS():
235 case CampaignGoalType::DONORS_FROM_SUBSCRIPTIONS():
236 return $this->getDonorsCount($campaign);
237 default:
238 return $this->getRevenue($campaign);
239 }
240 }
241 }
242