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 / Subscriptions / Endpoints / ListSubscriptions.php
give / src / Subscriptions / Endpoints Last commit date
Endpoint.php 5 months ago ListSubscriptionStats.php 8 months ago ListSubscriptions.php 8 months ago SubscriptionActions.php 5 months ago SwitchSubscriptionView.php 3 years ago
ListSubscriptions.php
298 lines
1 <?php
2
3 namespace Give\Subscriptions\Endpoints;
4
5 use Give\Donations\ValueObjects\DonationMetaKeys;
6 use Give\Donors\ValueObjects\DonorMetaKeys;
7 use Give\Framework\Database\DB;
8 use Give\Framework\QueryBuilder\QueryBuilder;
9 use Give\Subscriptions\ListTable\SubscriptionsListTable;
10 use Give\Subscriptions\ValueObjects\SubscriptionMode;
11 use Give\Subscriptions\ValueObjects\SubscriptionStatus;
12 use WP_REST_Request;
13 use WP_REST_Response;
14
15 class ListSubscriptions extends Endpoint
16 {
17 /**
18 * @var string
19 */
20 protected $endpoint = 'admin/subscriptions';
21
22 /**
23 * @var WP_REST_Request
24 */
25 protected $request;
26
27 /**
28 * @var SubscriptionsListTable
29 */
30 protected $listTable;
31
32 /**
33 * @inheritDoc
34 *
35 * @since 4.12.0 Add format parameter to start and end dates, replacing custom validation callback
36 */
37 public function registerRoute()
38 {
39 register_rest_route(
40 'give-api/v2',
41 $this->endpoint,
42 [
43 [
44 'methods' => 'GET',
45 'callback' => [$this, 'handleRequest'],
46 'permission_callback' => [$this, 'permissionsCheck'],
47 ],
48 'args' => [
49 'page' => [
50 'type' => 'integer',
51 'required' => false,
52 'default' => 1,
53 'minimum' => 1
54 ],
55 'perPage' => [
56 'type' => 'integer',
57 'required' => false,
58 'default' => 30,
59 'minimum' => 1
60 ],
61 'donations' => [
62 'type' => 'integer',
63 'required' => false,
64 'default' => 0
65 ],
66 'search' => [
67 'type' => 'string',
68 'required' => false
69 ],
70 'start' => [
71 'type' => 'string',
72 'required' => false,
73 'format' => 'date-time'
74 ],
75 'campaignId' => [
76 'type' => 'integer',
77 'required' => false,
78 'default' => 0
79 ],
80 'end' => [
81 'type' => 'string',
82 'required' => false,
83 'format' => 'date-time'
84 ],
85 'sortColumn' => [
86 'type' => 'string',
87 'required' => false,
88 'sanitize_callback' => 'sanitize_text_field',
89 ],
90 'sortDirection' => [
91 'type' => 'string',
92 'required' => false,
93 'enum' => [
94 'asc',
95 'desc',
96 ],
97 ],
98 'locale' => [
99 'type' => 'string',
100 'required' => false,
101 'default' => get_locale(),
102 ],
103 'testMode' => [
104 'type' => 'boolean',
105 'required' => false,
106 'default' => give_is_test_mode(),
107 ],
108 'return' => [
109 'type' => 'string',
110 'required' => false,
111 'default' => 'columns',
112 'enum' => [
113 'model',
114 'columns',
115 ],
116 ],
117 'status' => [
118 'type' => 'array',
119 'required' => false,
120 'items' => [
121 'type' => 'string',
122 'enum' => array_values(SubscriptionStatus::toArray()),
123 ],
124 'description' => 'Filter subscriptions by status. Accepts comma-separated list of SubscriptionStatus values (e.g., "active,expired,pending"). If not provided, excludes trash subscriptions by default.'
125 ],
126 ],
127 ]
128 );
129 }
130
131 /**
132 * @since 2.24.0
133 *
134 * @param WP_REST_Request $request
135 *
136 * @return WP_REST_Response
137 */
138 public function handleRequest(WP_REST_Request $request): WP_REST_Response
139 {
140 $this->request = $request;
141 $this->listTable = give(SubscriptionsListTable::class);
142
143 $subscriptions = $this->getSubscriptions();
144 $subscriptionsCount = $this->getTotalSubscriptionsCount();
145 $pageCount = (int)ceil($subscriptionsCount / $request->get_param('perPage'));
146
147 if ('model' === $this->request->get_param('return')) {
148 $items = $subscriptions;
149 } else {
150 $this->listTable->items($subscriptions, $this->request->get_param('locale') ?? '');
151 $items = $this->listTable->getItems();
152 }
153
154 return new WP_REST_Response(
155 [
156 'items' => $items,
157 'totalItems' => $subscriptionsCount,
158 'totalPages' => $pageCount,
159 ]
160 );
161 }
162
163 /**
164 * @since 4.12.0 add sort by donor name
165 * @since 2.24.0
166 *
167 * @return array
168 */
169 public function getSubscriptions(): array
170 {
171 $page = $this->request->get_param('page');
172 $perPage = $this->request->get_param('perPage');
173 $sortColumns = $this->listTable->getSortColumnById($this->request->get_param('sortColumn') ?: 'id');
174 $sortDirection = $this->request->get_param('sortDirection') ?: 'desc';
175
176 $query = give()->subscriptions->prepareQuery();
177
178 if ('donorName' === $sortColumns[0]) {
179 $query->attachMeta(
180 'give_donormeta',
181 'customer_id',
182 'donor_id',
183 [DonorMetaKeys::FIRST_NAME, 'firstName'],
184 [DonorMetaKeys::LAST_NAME, 'lastName']
185 );
186 $sortColumns = ['firstName', 'lastName'];
187 }
188
189 $query = $this->getWhereConditions($query);
190
191 foreach ($sortColumns as $sortColumn) {
192 $query->orderBy($sortColumn, $sortDirection);
193 }
194
195 $query->limit($perPage)
196 ->offset(($page - 1) * $perPage);
197
198 $subscriptions = $query->getAll();
199
200 if (!$subscriptions) {
201 return [];
202 }
203
204 return $subscriptions;
205 }
206
207 /**
208 * @since 2.24.0
209 *
210 * @return int
211 */
212 public function getTotalSubscriptionsCount(): int
213 {
214 $query = DB::table('give_subscriptions')->groupBy('payment_mode');
215 $query = $this->getWhereConditions($query);
216
217 return $query->count();
218 }
219
220 /**
221 * @since 4.12.0 Add "status" where condition
222 * @since 4.11.0 fix search by donor name or email
223 * @since 2.24.0 Replace Query Builder with Subscriptions model
224 * @since 2.21.0
225 *
226 * @param QueryBuilder $query
227 *
228 * @return QueryBuilder
229 */
230 private function getWhereConditions(QueryBuilder $query): QueryBuilder
231 {
232 $search = $this->request->get_param('search');
233 $start = $this->request->get_param('start');
234 $end = $this->request->get_param('end');
235 $campaignId = $this->request->get_param('campaignId');
236 $testMode = $this->request->get_param('testMode');
237 $status = $this->request->get_param('status');
238
239 $hasWhereConditions = $search || $start || $end || $campaignId || $status;
240
241 if (!empty($status)) {
242 $query->whereIn('status', $status);
243 } else {
244 // Default behavior: exclude trashed subscriptions
245 $query->where('status', SubscriptionStatus::TRASHED, '<>');
246 }
247
248 if ($search) {
249 if (ctype_digit($search)) {
250 $query->where('id', $search);
251 } else {
252 $query->whereIn('customer_id', static function (QueryBuilder $builder) use ($search) {
253 $builder
254 ->from('give_donors')
255 ->distinct()
256 ->select('id')
257 ->whereLike('name', $search)
258 ->orWhereLike('email', $search);
259 });
260 }
261 }
262
263 if ($start && $end) {
264 $query->whereBetween('created', $start, $end);
265 } elseif ($start) {
266 $query->where('created', $start, '>=');
267 } elseif ($end) {
268 $query->where('created', $end, '<=');
269 }
270
271 if ($campaignId) {
272 $query
273 ->whereIn('id', static function (QueryBuilder $builder) use ($campaignId) {
274 $builder
275 ->from('give_donationmeta')
276 ->distinct()
277 ->select('meta_value')
278 ->where('meta_key', DonationMetaKeys::SUBSCRIPTION_ID)
279 ->whereIn('donation_id', static function (QueryBuilder $builder) use ($campaignId) {
280 $builder
281 ->from('give_donationmeta')
282 ->select('donation_id')
283 ->where('meta_key', DonationMetaKeys::CAMPAIGN_ID)
284 ->where('meta_value', $campaignId);
285 });
286 });
287 }
288
289 if ($hasWhereConditions) {
290 $query->having('payment_mode', '=', $testMode ? SubscriptionMode::TEST : SubscriptionMode::LIVE);
291 } else {
292 $query->where('payment_mode', $testMode ? SubscriptionMode::TEST : SubscriptionMode::LIVE);
293 }
294
295 return $query;
296 }
297 }
298