PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.1.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.1.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
← All changes | inc/admin/admin.php +19 -178 trunk1.1.0 View file →
@@ -6,16 +6,13 @@
6 6 */
7 7
8 8 namespace SureDonation\Inc\Admin;
9 9
10 -use SureDonation\Inc\Campaigns\Campaign_Cpt;
11 -use SureDonation\Inc\API\Onboarding_API;
12 10 use SureDonation\Inc\Helper;
13 11 use SureDonation\Inc\Onboarding;
14 12 use SureDonation\Inc\Pdf\Pdf_Utils;
15 13 use SureDonation\Inc\Payments\Payment_Helper;
16 14 use SureDonation\Inc\Payments\PayPal\PayPal_Helper;
17 -use SureDonation\Inc\Payments\Stripe\Stripe_Helper;
18 15 use SureDonation\Inc\Traits\Get_Instance;
19 16
20 17 // Exit if accessed directly.
21 18 if ( ! defined( 'ABSPATH' ) ) {
@@ -39,114 +36,11 @@
39 36 add_action( 'admin_menu', [ $this, 'register_menu' ] );
40 37 add_action( 'admin_menu', [ $this, 'hide_forms_submenu' ], 999 );
41 38 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
42 39 add_action( 'admin_init', [ $this, 'redirect_cpt_listings' ] );
43 - add_action( 'admin_init', [ $this, 'register_privacy_policy_content' ] );
44 - add_action( 'admin_init', [ $this, 'register_react_notices' ], 5 );
45 40 }
46 41
47 42 /**
48 - * Register the payment-gateway React admin notice.
49 - *
50 - * Bridges the payment/test-mode nudges into the React admin app via
51 - * Notice_Manager. Runs on admin_init (priority 5) so the notice is
52 - * registered before admin_enqueue_scripts localizes the data for React.
53 - *
54 - * Two mutually-exclusive states, mirroring the existing PHP/front-end
55 - * notice chain:
56 - * - No gateway connected -> prompt to configure a gateway.
57 - * - Connected, but site in test mode -> prompt to switch to live mode.
58 - * When a gateway is connected and the site is live, no notice shows.
59 - *
60 - * Capability-gated to manage_options; the data is only consumed on the
61 - * SureDonation admin pages, where the React app is enqueued.
62 - *
63 - * Hooked - admin_init (priority 5)
64 - *
65 - * @since 1.3.0
66 - * @return void
67 - */
68 - public function register_react_notices() {
69 - if ( ! current_user_can( 'manage_options' ) ) {
70 - return;
71 - }
72 -
73 - if ( ! Payment_Helper::is_any_gateway_connected() ) {
74 - Notice_Manager::register_notice(
75 - [
76 - 'id' => 'sd-configure-gateway',
77 - 'variant' => 'error',
78 - // translators: the <a></a> tags wrap the inline link text and must be kept intact.
79 - 'message' => __( 'Your forms cannot accept donations yet. <a>Connect Stripe or PayPal</a> and you can start accepting them today.', 'suredonation' ),
80 - 'link' => [
81 - // Deep-link to the gateway connect screen, matching the dashboard Quick Access entry.
82 - 'url' => Payment_Helper::get_settings_url( 'stripe' ),
83 - ],
84 - 'event' => Analytics::TRACKED_EVENTS['configure_gateway'],
85 - 'dismissible' => false,
86 - ]
87 - );
88 - return;
89 - }
90 -
91 - if ( Stripe_Helper::is_stripe_connected() && ! Stripe_Helper::is_webhook_configured() ) {
92 - Notice_Manager::register_notice(
93 - [
94 - 'id' => 'sd-webhook-not-configured',
95 - 'variant' => 'error',
96 - // translators: the <a></a> tags wrap the inline link text and must be kept intact.
97 - 'message' => __( 'Webhooks keep SureDonation in sync with Stripe by automatically updating donation and subscription data. Please <a>configure</a> the webhook.', 'suredonation' ),
98 - 'link' => [
99 - 'url' => Payment_Helper::get_settings_url( 'stripe' ),
100 - ],
101 - 'event' => Analytics::TRACKED_EVENTS['webhook'],
102 - 'dismissible' => false,
103 - ]
104 - );
105 - return;
106 - }
107 -
108 - if ( 'test' === Payment_Helper::get_payment_mode() ) {
109 - $settings_url = Payment_Helper::get_settings_url();
110 - Notice_Manager::register_notice(
111 - [
112 - 'id' => 'sd-test-mode-react',
113 - 'variant' => 'error',
114 - // translators: the <a></a> tags wrap the inline link text and must be kept intact.
115 - 'message' => __( 'Supporters cannot donate while your site is in test mode. Anything they try now is a test and no money reaches you. <a>Switch to live mode</a> when you are ready to accept real donations.', 'suredonation' ),
116 - 'link' => [
117 - 'url' => $settings_url,
118 - ],
119 - 'event' => Analytics::TRACKED_EVENTS['test_mode'],
120 - 'dismissible' => false,
121 - ]
122 - );
123 - }
124 - }
125 -
126 - /**
127 - * Register suggested privacy-policy text for the plugin's data transfers.
128 - *
129 - * Surfaces the Phone field's automatic country detection (which sends the
130 - * visitor's IP to ipapi.co) in the WordPress Privacy Policy Guide
131 - * (Settings → Privacy → Policy Guide) so site owners can disclose it in
132 - * their own policy. This only suggests text to admins — it publishes
133 - * nothing and is not shown to donors.
134 - *
135 - * @since 1.1.1
136 - * @return void
137 - */
138 - public function register_privacy_policy_content() {
139 - if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
140 - return;
141 - }
142 -
143 - $content = __( 'When a Phone field with automatic country detection is used, this site sends the visitor’s IP address to a third-party service (ipapi.co) to determine their country code. The IP address is not stored for this purpose; the resulting country code is cached temporarily. Automatic detection can be disabled per Phone field, or site-wide via the “suredonation_phone_geo_enabled” filter.', 'suredonation' );
144 -
145 - wp_add_privacy_policy_content( 'SureDonation', wp_kses_post( wpautop( $content ) ) );
146 - }
147 -
148 - /**
149 43 * Redirect the default CPT list screens for suredonation_form and
150 44 * suredonation_cmpgn to their corresponding plugin pages.
151 45 *
152 46 * For the form listing, attempt to resolve the originating campaign
@@ -152,13 +46,8 @@
152 46 * For the form listing, attempt to resolve the originating campaign
153 47 * from the referer (the "back" arrow on the form editor sends the
154 48 * user here) and redirect to that campaign's single view.
155 49 *
156 - * Campaign creation (post-new.php) is redirected too, so bookmarks and
157 - * third-party links to the raw editor land in the creation drawer rather
158 - * than producing a half-configured campaign. New forms keep using
159 - * post-new.php — the campaign screen links there with a campaign_id.
160 - *
161 50 * @return void
162 51 * @since 1.0.0
163 52 */
164 53 public function redirect_cpt_listings() {
@@ -163,9 +52,9 @@
163 52 */
164 53 public function redirect_cpt_listings() {
165 54 global $pagenow;
166 55
167 - if ( 'edit.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
56 + if ( 'edit.php' !== $pagenow ) {
168 57 return;
169 58 }
170 59
171 60 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading post_type from query, no state mutation.
@@ -170,22 +59,8 @@
170 59
171 60 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading post_type from query, no state mutation.
172 61 $post_type = isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : '';
173 62
174 - if ( 'post-new.php' === $pagenow ) {
175 - /*
176 - * Only for users who can actually open the destination: the admin app
177 - * requires manage_options, while the campaign post type is creatable
178 - * by any role with edit_posts. Redirecting those roles would trade the
179 - * editor for a permission error.
180 - */
181 - if ( Campaign_Cpt::POST_TYPE === $post_type && current_user_can( 'manage_options' ) ) {
182 - wp_safe_redirect( Campaign_Cpt::get_create_url() );
183 - exit;
184 - }
185 - return;
186 - }
187 -
188 63 if ( 'suredonation_form' === $post_type ) {
189 64 $campaign_id = $this->resolve_campaign_id_from_referer();
190 65 $target = $campaign_id
191 66 ? admin_url( 'admin.php?page=suredonation#/campaigns/' . $campaign_id )
@@ -194,9 +69,9 @@
194 69 wp_safe_redirect( $target );
195 70 exit;
196 71 }
197 72
198 - if ( Campaign_Cpt::POST_TYPE === $post_type ) {
73 + if ( 'suredonation_cmpgn' === $post_type ) {
199 74 wp_safe_redirect( admin_url( 'admin.php?page=suredonation#/campaigns' ) );
200 75 exit;
201 76 }
202 77 }
@@ -302,27 +177,12 @@
302 177
303 178 // Load JS translations for the admin app.
304 179 wp_set_script_translations( 'suredonation-admin', 'suredonation' );
305 180
306 - // Campaign guided tour resume point (empty when there is none).
307 - $campaign_tour_progress = get_user_meta( get_current_user_id(), Onboarding_API::TOUR_PROGRESS_META, true );
308 - $campaign_tour_progress = is_string( $campaign_tour_progress ) ? $campaign_tour_progress : '';
309 -
310 - // Campaign whose first-run tour the onboarding wizard armed (empty = none).
311 - $campaign_tour_pending = get_user_meta( get_current_user_id(), Onboarding_API::TOUR_PENDING_META, true );
312 - $campaign_tour_pending = is_scalar( $campaign_tour_pending ) ? (string) $campaign_tour_pending : '';
313 -
314 181 // Localize script with plugin data.
315 - /**
316 - * Filters the bootstrap data localized to the SureDonation admin React app
317 - * (exposed as window.suredonation_admin). Lets features inject additional
318 - * data before it reaches React.
319 - *
320 - * @since 1.3.0
321 - * @param array<string, mixed> $localized_data The admin app bootstrap data.
322 - */
323 - $localized_data = apply_filters(
324 - 'suredonation_admin_app_data',
182 + wp_localize_script(
183 + 'suredonation-admin',
184 + 'suredonation_admin',
325 185 [
326 186 'version' => SUREDONATION_VER,
327 187 'apiUrl' => rest_url( 'suredonation/v1' ),
328 188 'nonce' => wp_create_nonce( 'wp_rest' ),
@@ -331,11 +191,8 @@
331 191 'site_url' => site_url(),
332 192 'admin_url' => admin_url(),
333 193 'is_first_campaign_created' => $this->has_campaigns(),
334 194 'is_onboarding_completed' => Onboarding::get_instance()->is_completed(),
335 - 'campaign_tour_seen' => 'yes' === get_user_meta( get_current_user_id(), Onboarding_API::TOUR_SEEN_META, true ),
336 - 'campaign_tour_progress' => $campaign_tour_progress,
337 - 'campaign_tour_pending' => $campaign_tour_pending,
338 195 'rotating_plugin_banner' => $this->get_rotating_plugin_banner(),
339 196 'smart_tags' => Helper::get_smart_tags(),
340 197 'is_pro_active' => defined( 'SUREDONATION_PRO_VER' ),
341 198 'pro_plugin_version' => defined( 'SUREDONATION_PRO_VER' ) ? SUREDONATION_PRO_VER : '',
@@ -348,25 +205,17 @@
348 205 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
349 206 'plugin_manager_nonce' => wp_create_nonce( 'suredonation_plugin_manager' ),
350 207 'has_abilities_api' => class_exists( 'WP_Ability' ),
351 208 'current_user_login' => wp_get_current_user()->user_login,
352 - 'integrations' => [
353 - 'sure_triggers' => Helper::get_ottokit_integration(),
354 - ],
355 209 // Bootstrap settings data so the General currency list and the
356 210 // PayPal connection state render synchronously (no post-mount
357 211 // fetch flicker). PayPal data is the non-sensitive subset only.
358 212 'payments' => [
359 - 'currencies' => Payment_Helper::get_currencies_list(),
360 - 'paypal' => PayPal_Helper::get_connection_state(),
361 - 'currency_sign_position' => Payment_Helper::get_currency_sign_position(),
362 - 'is_any_gateway_connected' => Payment_Helper::is_any_gateway_connected(),
363 - 'gateway_config_url' => Payment_Helper::get_settings_url( 'stripe' ),
213 + 'currencies' => Payment_Helper::get_currencies_list(),
214 + 'paypal' => PayPal_Helper::get_connection_state(),
364 215 ],
365 216 ]
366 217 );
367 -
368 - wp_localize_script( 'suredonation-admin', 'suredonation_admin', $localized_data );
369 218 }
370 219
371 220 /**
372 221 * Register admin menu.
@@ -615,36 +464,28 @@
615 464 } catch ( \Throwable $e ) {
616 465 $has_givewp_data = false;
617 466 }
618 467
619 - $has_charitable_data = false;
620 - try {
621 - $has_charitable_data = \SureDonation\Inc\Import\Charitable\Source::get_instance()->has_charitable_data();
622 - } catch ( \Throwable $e ) {
623 - $has_charitable_data = false;
624 - }
625 -
626 468 wp_localize_script(
627 469 'suredonation-onboarding',
628 470 'suredonation_onboarding',
629 471 [
630 - 'apiUrl' => rest_url( 'suredonation/v1' ),
631 - 'nonce' => wp_create_nonce( 'wp_rest' ),
632 - 'pluginUrl' => SUREDONATION_URL,
633 - 'adminUrl' => admin_url(),
634 - 'dashboardUrl' => admin_url( 'admin.php?page=suredonation' ),
635 - 'paymentsUrl' => Payment_Helper::get_settings_url( 'stripe' ),
636 - 'campaignsUrl' => admin_url( 'admin.php?page=suredonation#/campaigns' ),
637 - 'docsUrl' => 'https://suredonation.com/docs/',
638 - 'isProActive' => $is_pro,
639 - 'hasGiveWPData' => $has_givewp_data,
640 - 'hasCharitableData' => $has_charitable_data,
641 - 'currentUser' => [
472 + 'apiUrl' => rest_url( 'suredonation/v1' ),
473 + 'nonce' => wp_create_nonce( 'wp_rest' ),
474 + 'pluginUrl' => SUREDONATION_URL,
475 + 'adminUrl' => admin_url(),
476 + 'dashboardUrl' => admin_url( 'admin.php?page=suredonation' ),
477 + 'paymentsUrl' => admin_url( 'admin.php?page=suredonation#/settings?tab=payments' ),
478 + 'campaignsUrl' => admin_url( 'admin.php?page=suredonation#/campaigns' ),
479 + 'docsUrl' => 'https://suredonation.com/docs/',
480 + 'isProActive' => $is_pro,
481 + 'hasGiveWPData' => $has_givewp_data,
482 + 'currentUser' => [
642 483 'firstName' => $current_user ? $current_user->first_name : '',
643 484 'lastName' => $current_user ? $current_user->last_name : '',
644 485 'email' => $current_user ? $current_user->user_email : '',
645 486 ],
646 - 'privacyUrl' => 'https://suredonation.com/privacy-policy/',
487 + 'privacyUrl' => 'https://suredonation.com/privacy-policy/',
647 488 ]
648 489 );
649 490
650 491 // Shim suredonation_admin on the onboarding page too — shared API