PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.0.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.0.0
1.6.0 1.5.1 1.5.0 1.4.0 1.3.0 trunk 0.0.1 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0
suredonation / inc / abilities / config-ability.php

config-ability.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management 1.0.0, at inc/abilities/config-ability.php

1,091 lines 38.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Abilities API Configuration
4 *
5 * Defines all ability configurations for the SureDonation plugin.
6 *
7 * @package SureDonation
8 * @since 0.0.1
9 */
10
11 namespace SureDonation\Inc\Abilities;
12
13 use SureDonation\Inc\Helper;
14
15 // Exit if accessed directly.
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 /**
21 * Config_Ability class.
22 *
23 * @since 0.0.1
24 */
25 class Config_Ability {
26 /**
27 * Cached abilities.
28 *
29 * @var array<string, array<string, mixed>>|null
30 */
31 private static $abilities = null;
32
33 /**
34 * Get all ability configurations.
35 *
36 * @return array<string, array<string, mixed>> Ability definitions.
37 */
38 public static function get_abilities() {
39 if ( null !== self::$abilities ) {
40 return self::$abilities;
41 }
42
43 $runtime = new Runtime();
44 $ai_option = Helper::get_suredonation_option( 'ai_settings', [] );
45 $ai_settings = is_array( $ai_option ) ? $ai_option : [];
46
47 $perm_read = static function () use ( $runtime ) {
48 return $runtime->permission_callback( 'manage_options' );
49 };
50
51 $perm_edit = static function () use ( $runtime, $ai_settings ) {
52 return ! empty( $ai_settings['allow_updates'] ) && $runtime->permission_callback( 'manage_options' );
53 };
54
55 $perm_delete = static function () use ( $runtime, $ai_settings ) {
56 return ! empty( $ai_settings['allow_delete'] ) && $runtime->permission_callback( 'manage_options' );
57 };
58
59 $abilities = array_merge(
60 self::get_campaign_abilities( $runtime, $perm_read, $perm_edit, $perm_delete ),
61 self::get_donation_abilities( $runtime, $perm_read, $perm_edit ),
62 self::get_donor_abilities( $runtime, $perm_read ),
63 self::get_form_abilities( $runtime, $perm_read ),
64 self::get_analytics_abilities( $runtime, $perm_read )
65 );
66
67 /**
68 * Filter SureDonation ability configurations.
69 *
70 * @param array $abilities Ability definitions.
71 */
72 $abilities = apply_filters( 'suredonation_config_abilities', $abilities );
73 if ( ! is_array( $abilities ) ) {
74 $abilities = [];
75 }
76
77 self::$abilities = $abilities;
78
79 return $abilities;
80 }
81
82 /**
83 * Get a single ability config by name.
84 *
85 * @param string $ability_name Ability identifier.
86 * @return array<string, mixed>|false Ability config or false.
87 */
88 public static function get_ability( $ability_name ) {
89 if ( null === self::$abilities ) {
90 self::$abilities = self::get_abilities();
91 }
92 return self::$abilities[ $ability_name ] ?? false;
93 }
94
95 /**
96 * Get ability input schema.
97 *
98 * @param string $ability_name Ability identifier.
99 * @return array<string, mixed>|false Input schema or false.
100 */
101 public static function get_ability_input_schema( $ability_name ) {
102 $ability = self::get_ability( $ability_name );
103 if ( false === $ability ) {
104 return false;
105 }
106 $schema = $ability['input_schema'] ?? false;
107 return is_array( $schema ) ? $schema : false;
108 }
109
110 /**
111 * Build meta block for an ability.
112 *
113 * @param float $priority Priority level (1.0 read, 2.0 write, 3.0 destructive).
114 * @param bool $read_only Whether the ability only reads data.
115 * @param bool $destructive Whether the ability destroys data.
116 * @param bool $idempotent Whether repeated calls produce the same result.
117 * @return array<string, mixed> Meta configuration.
118 */
119 private static function build_meta( $priority = 1.0, $read_only = true, $destructive = false, $idempotent = true ) {
120 return [
121 'annotations' => [
122 'priority' => $priority,
123 'readOnlyHint' => $read_only,
124 'destructiveHint' => $destructive,
125 'idempotentHint' => $idempotent,
126 'openWorldHint' => false,
127 ],
128 'mcp' => [
129 'public' => true,
130 'type' => 'tool',
131 ],
132 ];
133 }
134
135 /**
136 * Get campaign ability configurations.
137 *
138 * @param Runtime $runtime Runtime instance.
139 * @param callable $perm_read Read permission closure.
140 * @param callable $perm_edit Edit permission closure.
141 * @param callable $perm_delete Delete permission closure.
142 * @return array<string, array<string, mixed>> Campaign abilities.
143 */
144 private static function get_campaign_abilities( $runtime, $perm_read, $perm_edit, $perm_delete ) {
145 $ns = SUREDONATION_ABILITY_API_NAMESPACE;
146
147 return [
148 $ns . 'list-campaigns' => [
149 'label' => __( 'List campaigns', 'suredonation' ),
150 'description' => __( 'Returns a paginated list of fundraising campaigns with optional search, status filter, and sorting.', 'suredonation' ),
151 'category' => 'suredonation',
152 'permission_callback' => $perm_read,
153 'input_schema' => [
154 'type' => 'object',
155 'properties' => [
156 'search' => [
157 'type' => 'string',
158 'description' => __( 'Search campaigns by title.', 'suredonation' ),
159 'default' => '',
160 ],
161 'status' => [
162 'type' => 'string',
163 'enum' => [ 'all', 'publish', 'draft' ],
164 'default' => 'all',
165 'description' => __( 'Filter by post status.', 'suredonation' ),
166 ],
167 'sort_by' => [
168 'type' => 'string',
169 'enum' => [ 'date', 'title', 'status' ],
170 'default' => 'date',
171 'description' => __( 'Column to sort by.', 'suredonation' ),
172 ],
173 'order' => [
174 'type' => 'string',
175 'enum' => [ 'ASC', 'DESC' ],
176 'default' => 'DESC',
177 'description' => __( 'Sort direction.', 'suredonation' ),
178 ],
179 'page' => [
180 'type' => 'integer',
181 'default' => 1,
182 'description' => __( 'Page number (1-based).', 'suredonation' ),
183 ],
184 'per_page' => [
185 'type' => 'integer',
186 'default' => 20,
187 'description' => __( 'Results per page (max 100).', 'suredonation' ),
188 ],
189 ],
190 ],
191 'output_schema' => [
192 'type' => 'object',
193 'properties' => [
194 'campaigns' => [
195 'type' => 'array',
196 'items' => [
197 'type' => 'object',
198 'properties' => [
199 'id' => [ 'type' => 'integer' ],
200 'title' => [ 'type' => 'string' ],
201 'status' => [ 'type' => 'string' ],
202 'goal_type' => [ 'type' => 'string' ],
203 'goal' => [ 'type' => 'number' ],
204 'raised' => [ 'type' => 'number' ],
205 'donors' => [ 'type' => 'integer' ],
206 'progress' => [ 'type' => 'number' ],
207 'created_at' => [ 'type' => 'string' ],
208 'modified_at' => [ 'type' => 'string' ],
209 ],
210 ],
211 ],
212 'total' => [
213 'type' => 'integer',
214 'description' => __( 'Total matching campaigns.', 'suredonation' ),
215 ],
216 'total_pages' => [
217 'type' => 'integer',
218 'description' => __( 'Total pages.', 'suredonation' ),
219 ],
220 ],
221 ],
222 'execute_callback' => static function ( $input ) use ( $runtime ) {
223 return $runtime->list_campaigns( $input );
224 },
225 'meta' => self::build_meta( 1.0, true, false, true ),
226 ],
227
228 $ns . 'get-campaign' => [
229 'label' => __( 'Get campaign', 'suredonation' ),
230 'description' => __( 'Returns a single fundraising campaign by ID with real-time stats including total raised, donor count, and progress.', 'suredonation' ),
231 'category' => 'suredonation',
232 'permission_callback' => $perm_read,
233 'input_schema' => [
234 'type' => 'object',
235 'required' => [ 'id' ],
236 'properties' => [
237 'id' => [
238 'type' => 'integer',
239 'description' => __( 'The campaign ID.', 'suredonation' ),
240 ],
241 ],
242 ],
243 'output_schema' => [
244 'type' => 'object',
245 'properties' => [
246 'id' => [ 'type' => 'integer' ],
247 'title' => [ 'type' => 'string' ],
248 'description' => [ 'type' => 'string' ],
249 'status' => [ 'type' => 'string' ],
250 'goal_type' => [ 'type' => 'string' ],
251 'goal' => [ 'type' => 'number' ],
252 'raised' => [ 'type' => 'number' ],
253 'donors' => [ 'type' => 'integer' ],
254 'progress' => [ 'type' => 'number' ],
255 'donation_count' => [ 'type' => 'integer' ],
256 'average_donation' => [ 'type' => 'number' ],
257 'largest_donation' => [ 'type' => 'number' ],
258 'is_goal_reached' => [ 'type' => 'boolean' ],
259 'require_terms' => [ 'type' => 'boolean' ],
260 'created_at' => [ 'type' => 'string' ],
261 'modified_at' => [ 'type' => 'string' ],
262 ],
263 ],
264 'execute_callback' => static function ( $input ) use ( $runtime ) {
265 return $runtime->get_campaign( $input );
266 },
267 'meta' => self::build_meta( 1.0, true, false, true ),
268 ],
269
270 $ns . 'create-campaign' => [
271 'label' => __( 'Create campaign', 'suredonation' ),
272 'description' => __( 'Creates a new fundraising campaign with title, description, goal settings, and optional fee coverage/terms configuration.', 'suredonation' ),
273 'category' => 'suredonation',
274 'permission_callback' => $perm_edit,
275 'input_schema' => [
276 'type' => 'object',
277 'required' => [ 'title' ],
278 'properties' => [
279 'title' => [
280 'type' => 'string',
281 'description' => __( 'Campaign title.', 'suredonation' ),
282 ],
283 'description' => [
284 'type' => 'string',
285 'format' => 'html',
286 'description' => __( 'Campaign description (HTML allowed).', 'suredonation' ),
287 'default' => '',
288 ],
289 'goal_type' => [
290 'type' => 'string',
291 'enum' => [ 'raised_amount', 'donation_count' ],
292 'default' => 'raised_amount',
293 'description' => __( 'Goal type: track by amount raised or donation count.', 'suredonation' ),
294 ],
295 'goal_amount' => [
296 'type' => 'number',
297 'description' => __( 'Goal amount (0 for no goal).', 'suredonation' ),
298 'default' => 0,
299 ],
300 'campaign_status' => [
301 'type' => 'string',
302 'enum' => [ 'active', 'paused', 'completed' ],
303 'default' => 'active',
304 'description' => __( 'Campaign status.', 'suredonation' ),
305 ],
306 'require_terms' => [
307 'type' => 'boolean',
308 'default' => false,
309 'description' => __( 'Require terms acceptance before donating.', 'suredonation' ),
310 ],
311 'terms_text' => [
312 'type' => 'string',
313 'default' => '',
314 'description' => __( 'Terms and conditions text.', 'suredonation' ),
315 ],
316 ],
317 ],
318 'output_schema' => [
319 'type' => 'object',
320 'properties' => [
321 'id' => [
322 'type' => 'integer',
323 'description' => __( 'New campaign ID.', 'suredonation' ),
324 ],
325 'title' => [ 'type' => 'string' ],
326 'status' => [ 'type' => 'string' ],
327 'message' => [ 'type' => 'string' ],
328 ],
329 ],
330 'execute_callback' => static function ( $input ) use ( $runtime ) {
331 return $runtime->create_campaign( $input );
332 },
333 'meta' => self::build_meta( 2.0, false, false, false ),
334 ],
335
336 $ns . 'update-campaign' => [
337 'label' => __( 'Update campaign', 'suredonation' ),
338 'description' => __( 'Updates an existing campaign. All fields except ID are optional — only provided fields are updated.', 'suredonation' ),
339 'category' => 'suredonation',
340 'permission_callback' => $perm_edit,
341 'input_schema' => [
342 'type' => 'object',
343 'required' => [ 'id' ],
344 'properties' => [
345 'id' => [
346 'type' => 'integer',
347 'description' => __( 'Campaign ID to update.', 'suredonation' ),
348 ],
349 'title' => [
350 'type' => 'string',
351 'description' => __( 'Campaign title.', 'suredonation' ),
352 ],
353 'description' => [
354 'type' => 'string',
355 'format' => 'html',
356 'description' => __( 'Campaign description (HTML allowed).', 'suredonation' ),
357 ],
358 'goal_type' => [
359 'type' => 'string',
360 'enum' => [ 'raised_amount', 'donation_count' ],
361 'description' => __( 'Goal type.', 'suredonation' ),
362 ],
363 'goal_amount' => [
364 'type' => 'number',
365 'description' => __( 'Goal amount.', 'suredonation' ),
366 ],
367 'campaign_status' => [
368 'type' => 'string',
369 'enum' => [ 'active', 'paused', 'completed' ],
370 'description' => __( 'Campaign status.', 'suredonation' ),
371 ],
372 'require_terms' => [
373 'type' => 'boolean',
374 'description' => __( 'Require terms acceptance.', 'suredonation' ),
375 ],
376 'terms_text' => [
377 'type' => 'string',
378 'description' => __( 'Terms and conditions text.', 'suredonation' ),
379 ],
380 ],
381 ],
382 'output_schema' => [
383 'type' => 'object',
384 'properties' => [
385 'id' => [ 'type' => 'integer' ],
386 'title' => [ 'type' => 'string' ],
387 'status' => [ 'type' => 'string' ],
388 'message' => [ 'type' => 'string' ],
389 ],
390 ],
391 'execute_callback' => static function ( $input ) use ( $runtime ) {
392 return $runtime->update_campaign( $input );
393 },
394 'meta' => self::build_meta( 2.0, false, false, false ),
395 ],
396
397 $ns . 'delete-campaign' => [
398 'label' => __( 'Delete campaign', 'suredonation' ),
399 'description' => __( 'Permanently deletes a campaign by ID. This action cannot be undone.', 'suredonation' ),
400 'category' => 'suredonation',
401 'permission_callback' => $perm_delete,
402 'input_schema' => [
403 'type' => 'object',
404 'required' => [ 'id' ],
405 'properties' => [
406 'id' => [
407 'type' => 'integer',
408 'description' => __( 'Campaign ID to delete.', 'suredonation' ),
409 ],
410 ],
411 ],
412 'output_schema' => [
413 'type' => 'object',
414 'properties' => [
415 'id' => [ 'type' => 'integer' ],
416 'message' => [ 'type' => 'string' ],
417 ],
418 ],
419 'execute_callback' => static function ( $input ) use ( $runtime ) {
420 return $runtime->delete_campaign( $input );
421 },
422 'meta' => self::build_meta( 3.0, false, true, false ),
423 ],
424
425 $ns . 'duplicate-campaign' => [
426 'label' => __( 'Duplicate campaign', 'suredonation' ),
427 'description' => __( 'Creates a copy of an existing campaign as a draft. Copies title (with " (Copy)" suffix), description, and settings.', 'suredonation' ),
428 'category' => 'suredonation',
429 'permission_callback' => $perm_edit,
430 'input_schema' => [
431 'type' => 'object',
432 'required' => [ 'id' ],
433 'properties' => [
434 'id' => [
435 'type' => 'integer',
436 'description' => __( 'Campaign ID to duplicate.', 'suredonation' ),
437 ],
438 ],
439 ],
440 'output_schema' => [
441 'type' => 'object',
442 'properties' => [
443 'id' => [
444 'type' => 'integer',
445 'description' => __( 'New campaign ID.', 'suredonation' ),
446 ],
447 'title' => [ 'type' => 'string' ],
448 'message' => [ 'type' => 'string' ],
449 ],
450 ],
451 'execute_callback' => static function ( $input ) use ( $runtime ) {
452 return $runtime->duplicate_campaign( $input );
453 },
454 'meta' => self::build_meta( 2.0, false, false, false ),
455 ],
456
457 $ns . 'get-campaign-form-locations' => [
458 'label' => __( 'Get campaign form locations', 'suredonation' ),
459 'description' => __( 'Finds all pages and posts where a campaign donation form block is embedded. Returns page IDs, titles, and edit/view URLs.', 'suredonation' ),
460 'category' => 'suredonation',
461 'permission_callback' => $perm_read,
462 'input_schema' => [
463 'type' => 'object',
464 'required' => [ 'id' ],
465 'properties' => [
466 'id' => [
467 'type' => 'integer',
468 'description' => __( 'Campaign ID.', 'suredonation' ),
469 ],
470 ],
471 ],
472 'output_schema' => [
473 'type' => 'object',
474 'properties' => [
475 'locations' => [
476 'type' => 'array',
477 'items' => [
478 'type' => 'object',
479 'properties' => [
480 'id' => [ 'type' => 'integer' ],
481 'title' => [ 'type' => 'string' ],
482 'type' => [ 'type' => 'string' ],
483 'status' => [ 'type' => 'string' ],
484 'edit_url' => [ 'type' => 'string' ],
485 'view_url' => [ 'type' => 'string' ],
486 ],
487 ],
488 ],
489 ],
490 ],
491 'execute_callback' => static function ( $input ) use ( $runtime ) {
492 return $runtime->get_campaign_form_locations( $input );
493 },
494 'meta' => self::build_meta( 1.0, true, false, true ),
495 ],
496 ];
497 }
498
499 /**
500 * Get donation ability configurations.
501 *
502 * @param Runtime $runtime Runtime instance.
503 * @param callable $perm_read Read permission closure.
504 * @param callable $perm_edit Edit permission closure.
505 * @return array<string, array<string, mixed>> Donation abilities.
506 */
507 private static function get_donation_abilities( $runtime, $perm_read, $perm_edit ) {
508 $ns = SUREDONATION_ABILITY_API_NAMESPACE;
509
510 return [
511 $ns . 'list-donations' => [
512 'label' => __( 'List donations', 'suredonation' ),
513 'description' => __( 'Returns a paginated list of donations with optional search, status filter, campaign filter, and sorting.', 'suredonation' ),
514 'category' => 'suredonation',
515 'permission_callback' => $perm_read,
516 'input_schema' => [
517 'type' => 'object',
518 'properties' => [
519 'search' => [
520 'type' => 'string',
521 'description' => __( 'Search donations by donor name or email.', 'suredonation' ),
522 'default' => '',
523 ],
524 'status' => [
525 'type' => 'string',
526 'enum' => [ 'all', 'pending', 'processing', 'completed', 'failed', 'refunded', 'partially_refunded', 'cancelled' ],
527 'default' => 'all',
528 'description' => __( 'Filter by payment status.', 'suredonation' ),
529 ],
530 'campaign_id' => [
531 'type' => 'integer',
532 'default' => 0,
533 'description' => __( 'Filter by campaign ID (0 for all campaigns).', 'suredonation' ),
534 ],
535 'sort_by' => [
536 'type' => 'string',
537 'enum' => [ 'created_at', 'amount', 'donor_name', 'payment_status' ],
538 'default' => 'created_at',
539 'description' => __( 'Column to sort by.', 'suredonation' ),
540 ],
541 'order' => [
542 'type' => 'string',
543 'enum' => [ 'ASC', 'DESC' ],
544 'default' => 'DESC',
545 'description' => __( 'Sort direction.', 'suredonation' ),
546 ],
547 'page' => [
548 'type' => 'integer',
549 'default' => 1,
550 'description' => __( 'Page number (1-based).', 'suredonation' ),
551 ],
552 'per_page' => [
553 'type' => 'integer',
554 'default' => 20,
555 'description' => __( 'Results per page (max 100).', 'suredonation' ),
556 ],
557 ],
558 ],
559 'output_schema' => [
560 'type' => 'object',
561 'properties' => [
562 'donations' => [
563 'type' => 'array',
564 'items' => [
565 'type' => 'object',
566 'properties' => [
567 'id' => [ 'type' => 'integer' ],
568 'campaign_id' => [ 'type' => 'integer' ],
569 'campaign_title' => [ 'type' => 'string' ],
570 'donor_name' => [ 'type' => 'string' ],
571 'donor_email' => [ 'type' => 'string' ],
572 'amount' => [ 'type' => 'number' ],
573 'currency' => [ 'type' => 'string' ],
574 'payment_status' => [ 'type' => 'string' ],
575 'donation_type' => [ 'type' => 'string' ],
576 'gateway' => [ 'type' => 'string' ],
577 'created_at' => [ 'type' => 'string' ],
578 ],
579 ],
580 ],
581 'total' => [
582 'type' => 'integer',
583 'description' => __( 'Total matching donations.', 'suredonation' ),
584 ],
585 'total_pages' => [
586 'type' => 'integer',
587 'description' => __( 'Total pages.', 'suredonation' ),
588 ],
589 ],
590 ],
591 'execute_callback' => static function ( $input ) use ( $runtime ) {
592 return $runtime->list_donations( $input );
593 },
594 'meta' => self::build_meta( 1.0, true, false, true ),
595 ],
596
597 $ns . 'get-donation' => [
598 'label' => __( 'Get donation', 'suredonation' ),
599 'description' => __( 'Returns a single donation by ID with full details including donor info, payment data, transaction ID, and activity logs.', 'suredonation' ),
600 'category' => 'suredonation',
601 'permission_callback' => $perm_read,
602 'input_schema' => [
603 'type' => 'object',
604 'required' => [ 'id' ],
605 'properties' => [
606 'id' => [
607 'type' => 'integer',
608 'description' => __( 'The donation ID.', 'suredonation' ),
609 ],
610 ],
611 ],
612 'output_schema' => [
613 'type' => 'object',
614 'properties' => [
615 'id' => [ 'type' => 'integer' ],
616 'campaign_id' => [ 'type' => 'integer' ],
617 'campaign_title' => [ 'type' => 'string' ],
618 'donor_id' => [ 'type' => 'integer' ],
619 'donor_name' => [ 'type' => 'string' ],
620 'donor_email' => [ 'type' => 'string' ],
621 'donor_phone' => [ 'type' => 'string' ],
622 'amount' => [ 'type' => 'number' ],
623 'fees_covered' => [ 'type' => 'number' ],
624 'refunded_amount' => [ 'type' => 'number' ],
625 'currency' => [ 'type' => 'string' ],
626 'donation_type' => [ 'type' => 'string' ],
627 'is_anonymous' => [ 'type' => 'boolean' ],
628 'donor_comment' => [ 'type' => 'string' ],
629 'payment_status' => [ 'type' => 'string' ],
630 'payment_mode' => [ 'type' => 'string' ],
631 'gateway' => [ 'type' => 'string' ],
632 'transaction_id' => [ 'type' => 'string' ],
633 'created_at' => [ 'type' => 'string' ],
634 'updated_at' => [ 'type' => 'string' ],
635 'logs' => [ 'type' => 'array' ],
636 ],
637 ],
638 'execute_callback' => static function ( $input ) use ( $runtime ) {
639 return $runtime->get_donation( $input );
640 },
641 'meta' => self::build_meta( 1.0, true, false, true ),
642 ],
643
644 $ns . 'get-donation-notes' => [
645 'label' => __( 'Get donation notes', 'suredonation' ),
646 'description' => __( 'Returns paginated notes for a donation. Notes are admin-added comments for internal tracking.', 'suredonation' ),
647 'category' => 'suredonation',
648 'permission_callback' => $perm_read,
649 'input_schema' => [
650 'type' => 'object',
651 'required' => [ 'id' ],
652 'properties' => [
653 'id' => [
654 'type' => 'integer',
655 'description' => __( 'The donation ID.', 'suredonation' ),
656 ],
657 'page' => [
658 'type' => 'integer',
659 'default' => 1,
660 'description' => __( 'Page number.', 'suredonation' ),
661 ],
662 'per_page' => [
663 'type' => 'integer',
664 'default' => 10,
665 'description' => __( 'Notes per page (max 100).', 'suredonation' ),
666 ],
667 ],
668 ],
669 'output_schema' => [
670 'type' => 'object',
671 'properties' => [
672 'notes' => [
673 'type' => 'array',
674 'items' => [
675 'type' => 'object',
676 'properties' => [
677 'id' => [ 'type' => 'string' ],
678 'content' => [ 'type' => 'string' ],
679 'author_id' => [ 'type' => 'integer' ],
680 'created_at' => [ 'type' => 'string' ],
681 ],
682 ],
683 ],
684 'total' => [
685 'type' => 'integer',
686 'description' => __( 'Total notes.', 'suredonation' ),
687 ],
688 'total_pages' => [
689 'type' => 'integer',
690 'description' => __( 'Total pages.', 'suredonation' ),
691 ],
692 ],
693 ],
694 'execute_callback' => static function ( $input ) use ( $runtime ) {
695 return $runtime->get_donation_notes( $input );
696 },
697 'meta' => self::build_meta( 1.0, true, false, true ),
698 ],
699
700 $ns . 'add-donation-note' => [
701 'label' => __( 'Add donation note', 'suredonation' ),
702 'description' => __( 'Adds an internal note to a donation for admin tracking purposes.', 'suredonation' ),
703 'category' => 'suredonation',
704 'permission_callback' => $perm_edit,
705 'input_schema' => [
706 'type' => 'object',
707 'required' => [ 'id', 'note' ],
708 'properties' => [
709 'id' => [
710 'type' => 'integer',
711 'description' => __( 'The donation ID.', 'suredonation' ),
712 ],
713 'note' => [
714 'type' => 'string',
715 'description' => __( 'The note content.', 'suredonation' ),
716 ],
717 ],
718 ],
719 'output_schema' => [
720 'type' => 'object',
721 'properties' => [
722 'note_id' => [
723 'type' => 'string',
724 'description' => __( 'The new note ID.', 'suredonation' ),
725 ],
726 'message' => [ 'type' => 'string' ],
727 ],
728 ],
729 'execute_callback' => static function ( $input ) use ( $runtime ) {
730 return $runtime->add_donation_note( $input );
731 },
732 'meta' => self::build_meta( 2.0, false, false, false ),
733 ],
734 ];
735 }
736
737 /**
738 * Get donor ability configurations.
739 *
740 * @param Runtime $runtime Runtime instance.
741 * @param callable $perm_read Read permission closure.
742 * @return array<string, array<string, mixed>> Donor abilities.
743 */
744 private static function get_donor_abilities( $runtime, $perm_read ) {
745 $ns = SUREDONATION_ABILITY_API_NAMESPACE;
746
747 $donor_detail_schema = [
748 'type' => 'object',
749 'properties' => [
750 'id' => [ 'type' => 'integer' ],
751 'name' => [ 'type' => 'string' ],
752 'email' => [ 'type' => 'string' ],
753 'phone' => [ 'type' => 'string' ],
754 'user_id' => [ 'type' => 'integer' ],
755 'donor_status' => [ 'type' => 'string' ],
756 'total_donated' => [ 'type' => 'number' ],
757 'donation_count' => [ 'type' => 'integer' ],
758 'largest_donation' => [ 'type' => 'number' ],
759 'first_donation_date' => [ 'type' => 'string' ],
760 'last_donation_date' => [ 'type' => 'string' ],
761 'donor_tags' => [ 'type' => 'array' ],
762 'created_at' => [ 'type' => 'string' ],
763 'updated_at' => [ 'type' => 'string' ],
764 ],
765 ];
766
767 return [
768 $ns . 'list-donors' => [
769 'label' => __( 'List donors', 'suredonation' ),
770 'description' => __( 'Returns a paginated list of donors with optional status filter and sorting by name, total donated, donation count, or date.', 'suredonation' ),
771 'category' => 'suredonation',
772 'permission_callback' => $perm_read,
773 'input_schema' => [
774 'type' => 'object',
775 'properties' => [
776 'status' => [
777 'type' => 'string',
778 'enum' => [ 'all', 'active', 'inactive', 'blocked' ],
779 'default' => 'all',
780 'description' => __( 'Filter by donor status.', 'suredonation' ),
781 ],
782 'sort_by' => [
783 'type' => 'string',
784 'enum' => [ 'created_at', 'name', 'email', 'total_donated', 'donation_count', 'last_donation_date' ],
785 'default' => 'created_at',
786 'description' => __( 'Column to sort by.', 'suredonation' ),
787 ],
788 'order' => [
789 'type' => 'string',
790 'enum' => [ 'ASC', 'DESC' ],
791 'default' => 'DESC',
792 'description' => __( 'Sort direction.', 'suredonation' ),
793 ],
794 'page' => [
795 'type' => 'integer',
796 'default' => 1,
797 'description' => __( 'Page number (1-based).', 'suredonation' ),
798 ],
799 'per_page' => [
800 'type' => 'integer',
801 'default' => 20,
802 'description' => __( 'Results per page (max 100).', 'suredonation' ),
803 ],
804 ],
805 ],
806 'output_schema' => [
807 'type' => 'object',
808 'properties' => [
809 'donors' => [
810 'type' => 'array',
811 'items' => [
812 'type' => 'object',
813 'properties' => [
814 'id' => [ 'type' => 'integer' ],
815 'name' => [ 'type' => 'string' ],
816 'email' => [ 'type' => 'string' ],
817 'phone' => [ 'type' => 'string' ],
818 'donor_status' => [ 'type' => 'string' ],
819 'total_donated' => [ 'type' => 'number' ],
820 'donation_count' => [ 'type' => 'integer' ],
821 'largest_donation' => [ 'type' => 'number' ],
822 'first_donation_date' => [ 'type' => 'string' ],
823 'last_donation_date' => [ 'type' => 'string' ],
824 'created_at' => [ 'type' => 'string' ],
825 ],
826 ],
827 ],
828 'total' => [
829 'type' => 'integer',
830 'description' => __( 'Total matching donors.', 'suredonation' ),
831 ],
832 'total_pages' => [
833 'type' => 'integer',
834 'description' => __( 'Total pages.', 'suredonation' ),
835 ],
836 ],
837 ],
838 'execute_callback' => static function ( $input ) use ( $runtime ) {
839 return $runtime->list_donors( $input );
840 },
841 'meta' => self::build_meta( 1.0, true, false, true ),
842 ],
843
844 $ns . 'get-donor' => [
845 'label' => __( 'Get donor', 'suredonation' ),
846 'description' => __( 'Returns a single donor by ID with full stats including total donated, donation count, largest donation, and donation dates.', 'suredonation' ),
847 'category' => 'suredonation',
848 'permission_callback' => $perm_read,
849 'input_schema' => [
850 'type' => 'object',
851 'required' => [ 'id' ],
852 'properties' => [
853 'id' => [
854 'type' => 'integer',
855 'description' => __( 'The donor ID.', 'suredonation' ),
856 ],
857 ],
858 ],
859 'output_schema' => $donor_detail_schema,
860 'execute_callback' => static function ( $input ) use ( $runtime ) {
861 return $runtime->get_donor( $input );
862 },
863 'meta' => self::build_meta( 1.0, true, false, true ),
864 ],
865
866 $ns . 'get-donor-by-email' => [
867 'label' => __( 'Get donor by email', 'suredonation' ),
868 'description' => __( 'Looks up a donor by email address. Returns full donor details if found, or an error if no donor exists with that email.', 'suredonation' ),
869 'category' => 'suredonation',
870 'permission_callback' => $perm_read,
871 'input_schema' => [
872 'type' => 'object',
873 'required' => [ 'email' ],
874 'properties' => [
875 'email' => [
876 'type' => 'string',
877 'description' => __( 'The donor email address.', 'suredonation' ),
878 ],
879 ],
880 ],
881 'output_schema' => $donor_detail_schema,
882 'execute_callback' => static function ( $input ) use ( $runtime ) {
883 return $runtime->get_donor_by_email( $input );
884 },
885 'meta' => self::build_meta( 1.0, true, false, true ),
886 ],
887
888 $ns . 'get-top-donors' => [
889 'label' => __( 'Get top donors', 'suredonation' ),
890 'description' => __( 'Returns top donors ranked by total donated amount. Useful for identifying major supporters and generating donor reports.', 'suredonation' ),
891 'category' => 'suredonation',
892 'permission_callback' => $perm_read,
893 'input_schema' => [
894 'type' => 'object',
895 'properties' => [
896 'limit' => [
897 'type' => 'integer',
898 'default' => 10,
899 'description' => __( 'Number of top donors to return (max 100).', 'suredonation' ),
900 ],
901 ],
902 ],
903 'output_schema' => [
904 'type' => 'object',
905 'properties' => [
906 'donors' => [
907 'type' => 'array',
908 'items' => [
909 'type' => 'object',
910 'properties' => [
911 'id' => [ 'type' => 'integer' ],
912 'name' => [ 'type' => 'string' ],
913 'email' => [ 'type' => 'string' ],
914 'total_donated' => [ 'type' => 'number' ],
915 'donation_count' => [ 'type' => 'integer' ],
916 ],
917 ],
918 ],
919 ],
920 ],
921 'execute_callback' => static function ( $input ) use ( $runtime ) {
922 return $runtime->get_top_donors( $input );
923 },
924 'meta' => self::build_meta( 1.0, true, false, true ),
925 ],
926 ];
927 }
928
929 /**
930 * Get form ability configurations.
931 *
932 * @param Runtime $runtime Runtime instance.
933 * @param callable $perm_read Read permission closure.
934 * @return array<string, array<string, mixed>> Form abilities.
935 */
936 private static function get_form_abilities( $runtime, $perm_read ) {
937 $ns = SUREDONATION_ABILITY_API_NAMESPACE;
938
939 return [
940 $ns . 'list-forms' => [
941 'label' => __( 'List donation forms', 'suredonation' ),
942 'description' => __( 'Returns donation forms with optional campaign filter and status filter. Forms are the front-end donation widgets linked to campaigns.', 'suredonation' ),
943 'category' => 'suredonation',
944 'permission_callback' => $perm_read,
945 'input_schema' => [
946 'type' => 'object',
947 'properties' => [
948 'campaign_id' => [
949 'type' => 'integer',
950 'default' => 0,
951 'description' => __( 'Filter by campaign ID (0 for all campaigns).', 'suredonation' ),
952 ],
953 'status' => [
954 'type' => 'string',
955 'enum' => [ 'any', 'publish', 'draft', 'trash' ],
956 'default' => 'any',
957 'description' => __( 'Filter by form status.', 'suredonation' ),
958 ],
959 'per_page' => [
960 'type' => 'integer',
961 'default' => 20,
962 'description' => __( 'Results per page (max 100).', 'suredonation' ),
963 ],
964 ],
965 ],
966 'output_schema' => [
967 'type' => 'object',
968 'properties' => [
969 'forms' => [
970 'type' => 'array',
971 'items' => [
972 'type' => 'object',
973 'properties' => [
974 'id' => [ 'type' => 'integer' ],
975 'title' => [ 'type' => 'string' ],
976 'status' => [ 'type' => 'string' ],
977 'campaign_id' => [ 'type' => 'integer' ],
978 'campaign_name' => [ 'type' => 'string' ],
979 'created_at' => [ 'type' => 'string' ],
980 'modified_at' => [ 'type' => 'string' ],
981 'edit_url' => [ 'type' => 'string' ],
982 ],
983 ],
984 ],
985 ],
986 ],
987 'execute_callback' => static function ( $input ) use ( $runtime ) {
988 return $runtime->list_forms( $input );
989 },
990 'meta' => self::build_meta( 1.0, true, false, true ),
991 ],
992
993 $ns . 'get-form' => [
994 'label' => __( 'Get donation form', 'suredonation' ),
995 'description' => __( 'Returns a single donation form by ID with campaign association, status, and edit URL.', 'suredonation' ),
996 'category' => 'suredonation',
997 'permission_callback' => $perm_read,
998 'input_schema' => [
999 'type' => 'object',
1000 'required' => [ 'id' ],
1001 'properties' => [
1002 'id' => [
1003 'type' => 'integer',
1004 'description' => __( 'The donation form ID.', 'suredonation' ),
1005 ],
1006 ],
1007 ],
1008 'output_schema' => [
1009 'type' => 'object',
1010 'properties' => [
1011 'id' => [ 'type' => 'integer' ],
1012 'title' => [ 'type' => 'string' ],
1013 'status' => [ 'type' => 'string' ],
1014 'campaign_id' => [ 'type' => 'integer' ],
1015 'campaign_name' => [ 'type' => 'string' ],
1016 'created_at' => [ 'type' => 'string' ],
1017 'modified_at' => [ 'type' => 'string' ],
1018 'edit_url' => [ 'type' => 'string' ],
1019 ],
1020 ],
1021 'execute_callback' => static function ( $input ) use ( $runtime ) {
1022 return $runtime->get_form( $input );
1023 },
1024 'meta' => self::build_meta( 1.0, true, false, true ),
1025 ],
1026 ];
1027 }
1028
1029 /**
1030 * Get analytics ability configurations.
1031 *
1032 * @param Runtime $runtime Runtime instance.
1033 * @param callable $perm_read Read permission closure.
1034 * @return array<string, array<string, mixed>> Analytics abilities.
1035 */
1036 private static function get_analytics_abilities( $runtime, $perm_read ) {
1037 $ns = SUREDONATION_ABILITY_API_NAMESPACE;
1038
1039 return [
1040 $ns . 'get-donation-trends' => [
1041 'label' => __( 'Get donation trends', 'suredonation' ),
1042 'description' => __( 'Returns donation trend data grouped by day, week, or month. Supports date range filtering. Useful for charts and analytics.', 'suredonation' ),
1043 'category' => 'suredonation',
1044 'permission_callback' => $perm_read,
1045 'input_schema' => [
1046 'type' => 'object',
1047 'properties' => [
1048 'after' => [
1049 'type' => 'string',
1050 'default' => '',
1051 'description' => __( 'Start date (YYYY-MM-DD). Empty for no lower bound.', 'suredonation' ),
1052 ],
1053 'before' => [
1054 'type' => 'string',
1055 'default' => '',
1056 'description' => __( 'End date (YYYY-MM-DD). Empty for no upper bound.', 'suredonation' ),
1057 ],
1058 'group' => [
1059 'type' => 'string',
1060 'enum' => [ 'day', 'week', 'month' ],
1061 'default' => 'day',
1062 'description' => __( 'Group results by time period.', 'suredonation' ),
1063 ],
1064 ],
1065 ],
1066 'output_schema' => [
1067 'type' => 'object',
1068 'properties' => [
1069 'trends' => [
1070 'type' => 'array',
1071 'items' => [
1072 'type' => 'object',
1073 'properties' => [
1074 'period' => [ 'type' => 'string' ],
1075 'donation_count' => [ 'type' => 'integer' ],
1076 'total_amount' => [ 'type' => 'number' ],
1077 ],
1078 ],
1079 ],
1080 'currency' => [ 'type' => 'string' ],
1081 ],
1082 ],
1083 'execute_callback' => static function ( $input ) use ( $runtime ) {
1084 return $runtime->get_donation_trends( $input );
1085 },
1086 'meta' => self::build_meta( 1.0, true, false, true ),
1087 ],
1088 ];
1089 }
1090 }
1091