PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / trunk
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management vtrunk
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 / admin / admin-ajax.php

admin-ajax.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management trunk, at inc/admin/admin-ajax.php

227 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin AJAX handlers.
4 *
5 * @package SureDonation
6 */
7
8 namespace SureDonation\Inc\Admin;
9
10 use SureDonation\Inc\Helper;
11 use SureDonation\Inc\Payments\Payment_Helper;
12 use SureDonation\Inc\Post_Types\Donation_Form;
13 use SureDonation\Inc\Traits\Get_Instance;
14
15 // Exit if accessed directly.
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 /**
21 * Handles admin-side AJAX for recommended-plugin install and activate.
22 *
23 * Installation reuses WordPress core's `wp_ajax_install_plugin` handler;
24 * activation is handled here.
25 *
26 * @since 1.0.0
27 */
28 class Admin_Ajax {
29 use Get_Instance;
30
31 /**
32 * Constructor.
33 *
34 * @since 1.0.0
35 */
36 public function __construct() {
37 add_action( 'wp_ajax_suredonation_recommended_plugin_install', 'wp_ajax_install_plugin' );
38 add_action( 'wp_ajax_suredonation_recommended_plugin_activate', [ $this, 'recommended_plugin_activate' ] );
39 add_action( 'wp_ajax_suredonation_integration', [ $this, 'generate_data_for_suretriggers_integration' ] );
40 }
41
42 /**
43 * Activate a recommended plugin.
44 *
45 * @since 1.0.0
46 * @return void
47 */
48 public function recommended_plugin_activate() {
49 if ( ! current_user_can( 'activate_plugins' ) ) {
50 wp_send_json_error(
51 [
52 'success' => false,
53 'message' => __( 'You do not have permission to activate plugins.', 'suredonation' ),
54 ]
55 );
56 }
57
58 if ( ! check_ajax_referer( 'suredonation_plugin_manager', 'security', false ) ) {
59 wp_send_json_error(
60 [
61 'success' => false,
62 'message' => __( 'Invalid security token. Please refresh the page and try again.', 'suredonation' ),
63 ]
64 );
65 }
66
67 $plugin_init = isset( $_POST['init'] ) ? sanitize_text_field( wp_unslash( $_POST['init'] ) ) : '';
68
69 if ( '' === $plugin_init ) {
70 wp_send_json_error(
71 [
72 'success' => false,
73 'message' => __( 'No plugin specified.', 'suredonation' ),
74 ]
75 );
76 }
77
78 if ( ! function_exists( 'activate_plugin' ) ) {
79 require_once ABSPATH . 'wp-admin/includes/plugin.php';
80 }
81
82 $activated = activate_plugin( $plugin_init, '', false, true );
83
84 if ( is_wp_error( $activated ) ) {
85 wp_send_json_error(
86 [
87 'success' => false,
88 'message' => $activated->get_error_message(),
89 ]
90 );
91 }
92
93 wp_send_json_success(
94 [
95 'success' => true,
96 'message' => __( 'Plugin activated successfully.', 'suredonation' ),
97 ]
98 );
99 }
100
101 /**
102 * Generate the configuration payload required by the OttoKit (formerly
103 * SureTriggers) embed to render the automation builder iframe.
104 *
105 * Called from the donation form settings. The embed is scoped to the
106 * form's CAMPAIGN — `embedded_identifier` and `selected_options` use the
107 * campaign ID so every form in a campaign shares the same automations,
108 * matching OttoKit's campaign-level trigger filtering.
109 *
110 * @since 1.2.0
111 * @return void
112 */
113 public function generate_data_for_suretriggers_integration() {
114 if ( ! current_user_can( 'manage_options' ) ) {
115 wp_send_json_error( [ 'message' => __( 'You do not have permission to access this page.', 'suredonation' ) ] );
116 }
117
118 if ( ! check_ajax_referer( 'suredonation_suretriggers_nonce', 'security', false ) ) {
119 wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'suredonation' ) ] );
120 }
121
122 if ( ! Helper::is_suretriggers_ready() ) {
123 wp_send_json_error(
124 [
125 'code' => 'invalid_secret_key',
126 'message' => __( 'OttoKit is not configured properly.', 'suredonation' ),
127 ]
128 );
129 }
130
131 $form_id = isset( $_POST['formId'] ) ? absint( wp_unslash( $_POST['formId'] ) ) : 0;
132
133 if ( ! $form_id || Donation_Form::POST_TYPE !== get_post_type( $form_id ) ) {
134 wp_send_json_error( [ 'message' => __( 'Invalid form ID.', 'suredonation' ) ] );
135 }
136
137 // Resolve the campaign this form belongs to — automations are scoped per campaign.
138 $campaign_id = absint( Helper::get_string_value( get_post_meta( $form_id, Donation_Form::META_CAMPAIGN_ID, true ) ) );
139
140 if ( ! $campaign_id ) {
141 wp_send_json_error(
142 [
143 'code' => 'no_campaign',
144 'message' => __( 'This form is not linked to a campaign yet.', 'suredonation' ),
145 ]
146 );
147 }
148
149 $campaign = get_post( $campaign_id );
150 $campaign_name = ( $campaign && ! empty( $campaign->post_title ) )
151 ? $campaign->post_title
152 /* translators: %d: Campaign ID. */
153 : sprintf( __( 'Campaign #%d', 'suredonation' ), $campaign_id );
154
155 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Filter is owned by the OttoKit plugin.
156 $api_url = apply_filters( 'suretriggers_get_iframe_url', SUREDONATION_SURETRIGGERS_INTEGRATION_BASE_URL );
157
158 // Format required by OttoKit to inject the builder iframe into the target id.
159 $body = [
160 'client_id' => 'SureDonation',
161 'st_embed_url' => $api_url,
162 'embedded_identifier' => $campaign_id,
163 'target' => 'suretriggers-iframe-wrapper', // The div where OttoKit injects the iframe must have this id.
164 'event' => [
165 'label' => __( 'Donation Completed', 'suredonation' ),
166 'value' => 'suredonation_donation_completed',
167 'description' => __( 'Runs when a donation payment is completed', 'suredonation' ),
168 ],
169 'summary' => $campaign_name,
170 'selected_options' => [
171 // Key must match the OttoKit trigger's campaign field name
172 // (`suredonation_campaign`) for the builder to pre-select it.
173 'suredonation_campaign' => [
174 'value' => $campaign_id,
175 'label' => $campaign_name,
176 ],
177 ],
178 'integration' => 'SureDonation',
179 // Flat shape — keys must mirror the runtime trigger context that
180 // OttoKit's WP module emits (get_donation_context / the pluggable
181 // "Fetch Data"). A nested `donation` object here makes OttoKit label
182 // the fields "Donation Campaign Id" etc., which then don't match the
183 // flat runtime keys ("Campaign Id"), so field mappings resolve empty.
184 'sample_response' => [
185 'donation_id' => 12,
186 'campaign_id' => $campaign_id,
187 'campaign_title' => $campaign_name,
188 'form_id' => $form_id,
189 'form_title' => get_the_title( $form_id ),
190 'donor_id' => 1,
191 'donor_name' => __( 'John Doe', 'suredonation' ),
192 'donor_email' => 'john@example.com',
193 'donor_phone' => '',
194 'amount' => 100.00,
195 'fees_covered' => 0,
196 'currency' => Payment_Helper::get_currency(),
197 'payment_status' => 'completed',
198 'payment_mode' => 'live',
199 'gateway' => 'stripe',
200 'transaction_id' => 'pi_1234567890',
201 'donation_type' => 'one-time',
202 'is_anonymous' => 0,
203 'donor_comment' => '',
204 'subscription_id' => '',
205 'subscription_status' => '',
206 'created_at' => gmdate( 'Y-m-d H:i:s' ),
207 'updated_at' => gmdate( 'Y-m-d H:i:s' ),
208 ],
209 ];
210
211 wp_send_json_success(
212 [
213 'message' => 'success',
214 /**
215 * Filter the configuration payload passed to the OttoKit embed.
216 *
217 * @param array<string,mixed> $body Embed configuration payload.
218 * @param int $campaign_id Resolved campaign ID.
219 * @param int $form_id Donation form ID the embed was opened from.
220 * @since 1.2.0
221 */
222 'data' => apply_filters( 'suredonation_suretriggers_integration_data_filter', $body, $campaign_id, $form_id ),
223 ]
224 );
225 }
226 }
227