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/helper.php +68 -334 1.4.0 → 1.1.0 View file →
@@ -203,40 +203,8 @@
203 203 return update_post_meta( $campaign_id, self::SUREDONATION_CAMPAIGN_META_KEY, wp_json_encode( $meta ) );
204 204 }
205 205
206 206 /**
207 - * Whether a (possibly nested) block tree contains a block of the given name.
208 - *
209 - * Walks parse_blocks() output, descending into innerBlocks so a block nested
210 - * inside a layout wrapper (Group/Columns) is still found. Note that a block
211 - * inside a synced pattern is not reachable: those parse as `core/block` with
212 - * no innerBlocks.
213 - *
214 - * Lives here rather than on Form_Renderer or Payment_Helper — both need it,
215 - * they sit in unrelated namespaces, and this is a generic block utility with
216 - * no rendering or payment semantics.
217 - *
218 - * @param array<int|string, mixed> $blocks Parsed blocks (parse_blocks output).
219 - * @param string $target Block name to look for.
220 - * @return bool
221 - * @since 1.4.0
222 - */
223 - public static function block_tree_contains( $blocks, $target ) {
224 - foreach ( $blocks as $block ) {
225 - if ( ! is_array( $block ) ) {
226 - continue;
227 - }
228 - if ( isset( $block['blockName'] ) && $block['blockName'] === $target ) {
229 - return true;
230 - }
231 - if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) && self::block_tree_contains( $block['innerBlocks'], $target ) ) {
232 - return true;
233 - }
234 - }
235 - return false;
236 - }
237 -
238 - /**
239 207 * Checks if current value is string or else returns default value
240 208 *
241 209 * @param mixed $data data which need to be checked if is string.
242 210 * @return string
@@ -470,39 +438,13 @@
470 438 return $slug . '-' . $index;
471 439 }
472 440
473 441 /**
474 - * Generate a unique block ID for a server-created block.
475 - *
476 - * Mirrors the client-side generateBlockId() used in each block's edit.js
477 - * (a 7-character base36 string). Blocks created programmatically (e.g. the
478 - * default form auto-generated when a campaign is published) never run the
479 - * editor, so they would otherwise have no block_id. The server-side payment
480 - * validation config is keyed on block_id, so without one no config is stored
481 - * and donations fail with "Invalid form configuration." until the form is
482 - * opened and saved in the editor.
483 - *
484 - * @return string A 7-character base36 identifier.
485 - * @since 1.1.1
486 - */
487 - public static function generate_block_id() {
488 - $chars = '0123456789abcdefghijklmnopqrstuvwxyz';
489 - $block_id = '';
490 - for ( $i = 0; $i < 7; $i++ ) {
491 - $block_id .= $chars[ wp_rand( 0, 35 ) ];
492 - }
493 - return $block_id;
494 - }
495 -
496 - /**
497 442 * Get client IP address for logging purposes.
498 443 *
499 - * Uses REMOTE_ADDR only — forwarded headers (HTTP_X_FORWARDED_FOR,
500 - * HTTP_CLIENT_IP) are deliberately ignored because they are trivially
501 - * spoofable. Note: behind a proxy/CDN that does not restore the real client
502 - * IP, this returns the proxy's address. Suitable for informational logging
503 - * and best-effort geolocation only — do NOT use for security-critical IP
504 - * validation.
444 + * Checks forwarded headers first (for proxied/load-balanced environments)
445 + * then falls back to REMOTE_ADDR. This is suitable for informational
446 + * logging only — do NOT use for security-critical IP validation.
505 447 *
506 448 * @return string Client IP address.
507 449 * @since 0.0.1
508 450 */
@@ -594,9 +536,8 @@
594 536 'data-subscription-billing-cycles' => true,
595 537 'data-currency-symbol' => true,
596 538 'data-message-format' => true,
597 539 'data-payment-methods' => true,
598 - 'data-payment-available' => true,
599 540 'data-method' => true,
600 541 'data-slug' => true,
601 542 'data-required' => true,
602 543 'data-fee-percentage' => true,
@@ -603,43 +544,26 @@
603 544 'data-fee-fixed' => true,
604 545 'data-fee-mode' => true,
605 546 'data-gateway-fees' => true,
606 547 'data-invalid-email-msg' => true,
607 - 'data-invalid-url-msg' => true,
608 548 'data-sd-mask' => true,
609 549 'data-custom-sd-mask' => true,
610 - // Dropdown (tom-select) field.
611 - 'data-multiple' => true,
612 - 'data-searchable' => true,
613 - 'data-preselected' => true,
614 - 'data-min-selection' => true,
615 - 'data-max-selection' => true,
616 - 'data-placeholder' => true,
617 - // Phone (intl-tel-input) field.
618 - 'data-default-country' => true,
619 - 'data-auto-country' => true,
620 - 'data-enable-country-filter' => true,
621 - 'data-country-filter-type' => true,
622 - 'data-include-countries' => true,
623 - 'data-exclude-countries' => true,
624 550 ];
625 551
626 - $allowed = [
627 - 'div' => array_merge(
552 + return [
553 + 'div' => array_merge(
628 554 [
629 555 'id' => true,
630 556 'class' => true,
631 557 'style' => true,
632 558 'role' => true,
633 - 'tabindex' => true,
634 559 'aria-live' => true,
635 560 'aria-atomic' => true,
636 - 'aria-hidden' => true,
637 561 'aria-labelledby' => true,
638 562 ],
639 563 $common_data_attrs
640 564 ),
641 - 'form' => array_merge(
565 + 'form' => array_merge(
642 566 [
643 567 'id' => true,
644 568 'class' => true,
645 569 'method' => true,
@@ -646,22 +570,22 @@
646 570 'action' => true,
647 571 ],
648 572 $common_data_attrs
649 573 ),
650 - 'fieldset' => [
574 + 'fieldset' => [
651 575 'id' => true,
652 576 'class' => true,
653 577 ],
654 - 'legend' => [
578 + 'legend' => [
655 579 'id' => true,
656 580 'class' => true,
657 581 ],
658 - 'label' => [
582 + 'label' => [
659 583 'id' => true,
660 584 'class' => true,
661 585 'for' => true,
662 586 ],
663 - 'input' => array_merge(
587 + 'input' => array_merge(
664 588 [
665 589 'id' => true,
666 590 'class' => true,
667 591 'type' => true,
@@ -675,11 +599,8 @@
675 599 'checked' => true,
676 600 'disabled' => true,
677 601 'readonly' => true,
678 602 'required' => true,
679 - 'tabindex' => true,
680 - 'autocomplete' => true,
681 - 'inputmode' => true,
682 603 'aria-describedby' => true,
683 604 'aria-required' => true,
684 605 'aria-hidden' => true,
685 606 ],
@@ -684,9 +605,9 @@
684 605 'aria-hidden' => true,
685 606 ],
686 607 $common_data_attrs
687 608 ),
688 - 'button' => array_merge(
609 + 'button' => array_merge(
689 610 [
690 611 'id' => true,
691 612 'class' => true,
692 613 'type' => true,
@@ -693,9 +614,9 @@
693 614 'disabled' => true,
694 615 ],
695 616 $common_data_attrs
696 617 ),
697 - 'select' => array_merge(
618 + 'select' => array_merge(
698 619 [
699 620 'id' => true,
700 621 'class' => true,
701 622 'name' => true,
@@ -700,23 +621,19 @@
700 621 'class' => true,
701 622 'name' => true,
702 623 'disabled' => true,
703 624 'required' => true,
704 - 'multiple' => true,
705 - 'tabindex' => true,
706 - 'autocomplete' => true,
707 625 'aria-describedby' => true,
708 626 'aria-required' => true,
709 627 ],
710 628 $common_data_attrs
711 629 ),
712 - 'option' => [
630 + 'option' => [
713 631 'value' => true,
714 - 'class' => true,
715 632 'selected' => true,
716 633 'disabled' => true,
717 634 ],
718 - 'textarea' => array_merge(
635 + 'textarea' => array_merge(
719 636 [
720 637 'id' => true,
721 638 'class' => true,
722 639 'name' => true,
@@ -731,9 +648,9 @@
731 648 'aria-required' => true,
732 649 ],
733 650 $common_data_attrs
734 651 ),
735 - 'span' => array_merge(
652 + 'span' => array_merge(
736 653 [
737 654 'id' => true,
738 655 'class' => true,
739 656 'style' => true,
@@ -740,39 +657,15 @@
740 657 'aria-hidden' => true,
741 658 ],
742 659 $common_data_attrs
743 660 ),
744 - 'p' => [
661 + 'p' => [
745 662 'id' => true,
746 663 'class' => true,
747 664 'style' => true,
748 665 'role' => true,
749 666 ],
750 - 'h1' => [
751 - 'id' => true,
752 - 'class' => true,
753 - ],
754 - 'h2' => [
755 - 'id' => true,
756 - 'class' => true,
757 - ],
758 - 'h3' => [
759 - 'id' => true,
760 - 'class' => true,
761 - ],
762 - 'h4' => [
763 - 'id' => true,
764 - 'class' => true,
765 - ],
766 - 'h5' => [
767 - 'id' => true,
768 - 'class' => true,
769 - ],
770 - 'h6' => [
771 - 'id' => true,
772 - 'class' => true,
773 - ],
774 - 'a' => [
667 + 'a' => [
775 668 'id' => true,
776 669 'class' => true,
777 670 'href' => true,
778 671 'target' => true,
@@ -778,60 +671,25 @@
778 671 'target' => true,
779 672 'rel' => true,
780 673 'style' => true,
781 674 ],
782 - 'strong' => [
675 + 'strong' => [
783 676 'class' => true,
784 677 ],
785 - 'em' => [
678 + 'em' => [
786 679 'class' => true,
787 680 ],
788 - 'ol' => [
681 + 'ol' => [
789 682 'class' => true,
790 683 ],
791 - 'ul' => [
684 + 'ul' => [
792 685 'class' => true,
793 686 ],
794 - 'li' => [
687 + 'li' => [
795 688 'class' => true,
796 689 ],
797 - 'br' => [],
798 - 'hr' => [
799 - 'class' => true,
800 - ],
801 - // img/figure/figcaption back the Image block (inc/blocks/image) — the
802 - // render depends on these entries, so don't drop them in a cleanup.
803 - 'img' => [
804 - 'src' => true,
805 - 'fetchpriority' => true,
806 - 'srcset' => true,
807 - 'sizes' => true,
808 - 'alt' => true,
809 - 'class' => true,
810 - 'style' => true,
811 - 'width' => true,
812 - 'height' => true,
813 - 'loading' => true,
814 - 'decoding' => true,
815 - 'title' => true,
816 - // Lazy-load optimizers (WP Rocket, Perfmatters, Optimole, the
817 - // Bricks theme, …) rewrite wp_get_attachment_image() output into
818 - // these data-* attributes with a data: placeholder in src; allow
819 - // them so kses doesn't strip the real URLs the lazy JS swaps back.
820 - 'data-src' => true,
821 - 'data-srcset' => true,
822 - 'data-sizes' => true,
823 - 'data-lazy-src' => true,
824 - 'data-lazy-srcset' => true,
825 - 'data-lazy-sizes' => true,
826 - ],
827 - 'figure' => [
828 - 'class' => true,
829 - ],
830 - 'figcaption' => [
831 - 'class' => true,
832 - ],
833 - 'svg' => [
690 + 'br' => [],
691 + 'svg' => [
834 692 'class' => true,
835 693 'width' => true,
836 694 'height' => true,
837 695 'viewbox' => true,
@@ -838,9 +696,9 @@
838 696 'fill' => true,
839 697 'xmlns' => true,
840 698 'aria-hidden' => true,
841 699 ],
842 - 'circle' => [
700 + 'circle' => [
843 701 'cx' => true,
844 702 'cy' => true,
845 703 'r' => true,
846 704 'stroke' => true,
@@ -846,9 +704,9 @@
846 704 'stroke' => true,
847 705 'stroke-width' => true,
848 706 'fill' => true,
849 707 ],
850 - 'rect' => [
708 + 'rect' => [
851 709 'x' => true,
852 710 'y' => true,
853 711 'width' => true,
854 712 'height' => true,
@@ -855,9 +713,9 @@
855 713 'rx' => true,
856 714 'stroke' => true,
857 715 'stroke-width' => true,
858 716 ],
859 - 'path' => [
717 + 'path' => [
860 718 'class' => true,
861 719 'd' => true,
862 720 'stroke' => true,
863 721 'stroke-width' => true,
@@ -865,19 +723,8 @@
865 723 'stroke-linejoin' => true,
866 724 'fill' => true,
867 725 ],
868 726 ];
869 -
870 - /**
871 - * Filter the allowed HTML tags/attributes for SureDonation form markup.
872 - *
873 - * Lets extensions (e.g. the SureDonation Pro date/time pickers) permit the
874 - * extra tags or data attributes their fields render.
875 - *
876 - * @since 1.1.1
877 - * @param array<string, array<string, bool>> $allowed Allowed tags/attributes.
878 - */
879 - return apply_filters( 'suredonation_allowed_form_html', $allowed );
880 727 }
881 728
882 729 /**
883 730 * Get the nonce action string for a donation form.
@@ -925,23 +772,21 @@
925 772 ? $data['message']
926 773 : esc_html__( 'Thank you for your donation!', 'suredonation' );
927 774
928 775 return [
929 - 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
930 - 'confirmationType' => $confirmation_type,
931 - 'successTitle' => esc_html__( 'Thank You!', 'suredonation' ),
932 - 'successMessage' => wp_kses_post( self::get_string_value( $success_message ) ),
776 + 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
777 + 'confirmationType' => $confirmation_type,
778 + 'successTitle' => esc_html__( 'Thank You!', 'suredonation' ),
779 + 'successMessage' => wp_kses_post( self::get_string_value( $success_message ) ),
933 780 // Shown when payment succeeded at the gateway but our server-side
934 781 // finalize did not complete; the webhook will finalize it, so the
935 782 // donor must not be prompted to pay again.
936 - 'processingMessage' => esc_html__( 'Payment received. We are finalizing your donation and will email you a confirmation shortly. Please do not pay again.', 'suredonation' ),
937 - 'redirectUrl' => ! empty( $redirect_url ) ? esc_url( self::get_string_value( $redirect_url ) ) : '',
938 - 'submissionAction' => $data['submission_action'],
783 + 'processingMessage' => esc_html__( 'Payment received. We are finalizing your donation and will email you a confirmation shortly. Please do not pay again.', 'suredonation' ),
784 + 'redirectUrl' => ! empty( $redirect_url ) ? esc_url( self::get_string_value( $redirect_url ) ) : '',
785 + 'submissionAction' => $data['submission_action'],
939 786 // translators: %s: formatted fee amount with currency symbol.
940 - 'feeIncludesText' => __( '(includes %s processing fee)', 'suredonation' ),
941 - 'amountPlaceholder' => __( 'Complete the form to view the amount.', 'suredonation' ),
942 - // Currency symbol placement for client-side amount/fee formatting.
943 - 'currencySignPosition' => Payment_Helper::get_currency_sign_position(),
787 + 'feeIncludesText' => __( '(includes %s processing fee)', 'suredonation' ),
788 + 'amountPlaceholder' => __( 'Complete the form to view the amount.', 'suredonation' ),
944 789 ];
945 790 }
946 791
947 792 /**
@@ -1034,9 +879,9 @@
1034 879 'title' => __( 'Success Badge', 'suredonation' ),
1035 880 ],
1036 881 ];
1037 882
1038 - $smart_tags = [
883 + return [
1039 884 'confirmation' => $confirmation_tags,
1040 885 'email' => array_merge(
1041 886 $confirmation_tags,
1042 887 [
@@ -1052,8 +897,16 @@
1052 897 'tag' => '{admin_url}',
1053 898 'title' => __( 'Admin URL', 'suredonation' ),
1054 899 ],
1055 900 [
901 + 'tag' => '{subscription_id}',
902 + 'title' => __( 'Subscription ID', 'suredonation' ),
903 + ],
904 + [
905 + 'tag' => '{subscription_interval}',
906 + 'title' => __( 'Subscription Interval', 'suredonation' ),
907 + ],
908 + [
1056 909 'tag' => '{offline_instructions}',
1057 910 'title' => __( 'Offline Instructions', 'suredonation' ),
1058 911 ],
1059 912 ]
@@ -1090,8 +943,16 @@
1090 943 'tag' => '{payment_method}',
1091 944 'title' => __( 'Payment Method', 'suredonation' ),
1092 945 ],
1093 946 [
947 + 'tag' => '{subscription_id}',
948 + 'title' => __( 'Subscription ID', 'suredonation' ),
949 + ],
950 + [
951 + 'tag' => '{subscription_interval}',
952 + 'title' => __( 'Subscription Interval', 'suredonation' ),
953 + ],
954 + [
1094 955 'tag' => '{refund_amount}',
1095 956 'title' => __( 'Refund Amount', 'suredonation' ),
1096 957 ],
1097 958 ],
@@ -1140,55 +1001,8 @@
1140 1001 'title' => __( 'Admin Email', 'suredonation' ),
1141 1002 ],
1142 1003 ],
1143 1004 ];
1144 -
1145 - // Recurring tags resolve to nothing without Pro, so a free-only site was
1146 - // being offered two tags it could never use. They stay here rather than
1147 - // moving into Pro so that activating Pro does not depend on shipping a
1148 - // matching Pro release; anything Pro adds beyond these comes through the
1149 - // filter below.
1150 - if ( defined( 'SUREDONATION_PRO_VER' ) ) {
1151 - $smart_tags['email_grouped'][0]['tags'][] = [
1152 - 'tag' => '{subscription_id}',
1153 - 'title' => __( 'Recurring Donation ID', 'suredonation' ),
1154 - ];
1155 - $smart_tags['email_grouped'][0]['tags'][] = [
1156 - 'tag' => '{subscription_interval}',
1157 - 'title' => __( 'Frequency', 'suredonation' ),
1158 - ];
1159 - }
1160 -
1161 - /**
1162 - * Filter the grouped smart tags offered in the email notification editor.
1163 - *
1164 - * The list is what an admin can insert, so anything registering a tag
1165 - * resolver via `suredonation_email_smart_tags` needs to advertise it here
1166 - * too. Without this, Pro could resolve recurring tags but had no way to
1167 - * surface them, and free listed subscription tags that could never
1168 - * resolve for a free-only site.
1169 - *
1170 - * @param array<int, array<string, mixed>> $groups Grouped tag definitions.
1171 - * @since 1.4.0
1172 - */
1173 - $grouped = apply_filters( 'suredonation_email_smart_tag_groups', $smart_tags['email_grouped'] );
1174 -
1175 - // The filter feeds the editor's tag picker, which iterates groups and
1176 - // their tags. A callback returning a non-array — or groups without a
1177 - // `tags` array — would fatal there rather than in whatever added it, so
1178 - // the shape is re-checked before it is handed on.
1179 - if ( is_array( $grouped ) ) {
1180 - $smart_tags['email_grouped'] = array_values(
1181 - array_filter(
1182 - $grouped,
1183 - static function ( $group ) {
1184 - return is_array( $group ) && isset( $group['tags'] ) && is_array( $group['tags'] );
1185 - }
1186 - )
1187 - );
1188 - }
1189 -
1190 - return $smart_tags;
1191 1005 }
1192 1006
1193 1007 /**
1194 1008 * Map a payment gateway slug to a human-readable label.
@@ -1224,9 +1038,9 @@
1224 1038 /**
1225 1039 * Render a styled payment-status badge for the donation confirmation.
1226 1040 *
1227 1041 * @param string $status Payment status (e.g. completed, pending, failed).
1228 - * @return array Badge HTML.
1042 + * @return string Badge HTML.
1229 1043 * @since 1.0.0
1230 1044 */
1231 1045 public static function get_payment_status_config( $status ) {
1232 1046 $status = strtolower( trim( (string) $status ) );
@@ -1372,28 +1186,17 @@
1372 1186 /**
1373 1187 * Build the rendered confirmation/thank-you HTML for a donation.
1374 1188 *
1375 1189 * Resolves the form's confirmation message template against the donation's
1376 - * real data (smart tags) so the frontend can display the receipt. The
1377 - * billing interval is lifted out of the nested donation_data column, which
1378 - * is the only field of the set that is not stored as a column of its own.
1190 + * real data (smart tags) so the frontend can display the receipt.
1379 1191 *
1380 - * @param int $donation_id Donation ID.
1381 - * @param array<string, mixed>|null $donation Donation row to render from.
1382 - * Defaults to reading it. Pass one
1383 - * when the caller already holds the
1384 - * row, or when the row on disk does
1385 - * not yet reflect the state being
1386 - * reported to the donor.
1192 + * @param int $donation_id Donation ID.
1387 1193 * @return string Sanitized confirmation HTML, or '' on failure.
1388 1194 * @since 1.0.0
1389 1195 */
1390 - public static function render_confirmation_message( $donation_id, $donation = null ) {
1196 + public static function render_confirmation_message( $donation_id ) {
1197 + $donation = Donations::get( $donation_id );
1391 1198 if ( ! is_array( $donation ) ) {
1392 - $donation = Donations::get( $donation_id );
1393 - }
1394 -
1395 - if ( ! is_array( $donation ) ) {
1396 1199 return '';
1397 1200 }
1398 1201
1399 1202 $form_id = isset( $donation['form_id'] ) ? absint( $donation['form_id'] ) : 0;
@@ -1401,32 +1204,19 @@
1401 1204
1402 1205 $settings = self::get_form_confirmation_settings( $form_id );
1403 1206 $template = ! empty( $settings['message'] ) ? $settings['message'] : self::get_default_confirmation_message();
1404 1207
1405 - // The billing interval is the one field the donation row does not carry
1406 - // as a column; it is written a level down inside donation_data, so it
1407 - // has to be lifted out before the tag map can see it.
1408 - $stored = $donation['donation_data'] ?? [];
1409 - if ( is_string( $stored ) && '' !== $stored ) {
1410 - $stored = json_decode( $stored, true );
1411 - }
1412 - $stored = is_array( $stored ) ? $stored : [];
1413 -
1414 1208 $donation_data = [
1415 - 'id' => $donation_id,
1416 - 'donor_name' => $donation['donor_name'] ?? '',
1417 - 'donor_email' => $donation['donor_email'] ?? '',
1418 - 'amount' => $donation['amount'] ?? 0,
1419 - 'fees_covered' => $donation['fees_covered'] ?? 0,
1420 - 'currency' => $donation['currency'] ?? Payment_Helper::get_currency(),
1421 - 'gateway' => $donation['gateway'] ?? '',
1422 - 'payment_status' => $donation['payment_status'] ?? '',
1423 - 'transaction_id' => $donation['transaction_id'] ?? '',
1424 - 'donation_type' => $donation['donation_type'] ?? 'one-time',
1425 - // Recurring donations resolve these two; a one-time donation has
1426 - // neither, and the tag map already renders a missing value as empty.
1427 - 'subscription_id' => $donation['subscription_id'] ?? '',
1428 - 'subscription_interval' => $stored['subscription_interval'] ?? '',
1209 + 'id' => $donation_id,
1210 + 'donor_name' => $donation['donor_name'] ?? '',
1211 + 'donor_email' => $donation['donor_email'] ?? '',
1212 + 'amount' => $donation['amount'] ?? 0,
1213 + 'fees_covered' => $donation['fees_covered'] ?? 0,
1214 + 'currency' => $donation['currency'] ?? Payment_Helper::get_currency(),
1215 + 'gateway' => $donation['gateway'] ?? '',
1216 + 'payment_status' => $donation['payment_status'] ?? '',
1217 + 'transaction_id' => $donation['transaction_id'] ?? '',
1218 + 'donation_type' => $donation['donation_type'] ?? 'one-time',
1429 1219 ];
1430 1220
1431 1221 $campaign = $campaign_id ? get_post( $campaign_id ) : null;
1432 1222
@@ -1432,62 +1222,6 @@
1432 1222
1433 1223 $rendered = Email_Handler::process_smart_tags( $template, $donation_data, $campaign );
1434 1224
1435 1225 return wp_kses_post( $rendered );
1436 - }
1437 -
1438 - /**
1439 - * Check whether the OttoKit (formerly SureTriggers) plugin is active and
1440 - * authenticated with the OttoKit SaaS.
1441 - *
1442 - * @return bool True when OttoKit is installed, active and connected.
1443 - * @since 1.2.0
1444 - */
1445 - public static function is_suretriggers_ready() {
1446 - if ( ! defined( 'SURE_TRIGGERS_FILE' ) ) {
1447 - // Plugin is deactivated or not installed at all.
1448 - return false;
1449 - }
1450 -
1451 - $suretriggers_data = get_option( 'suretrigger_options', [] );
1452 - if ( ! is_array( $suretriggers_data ) || empty( $suretriggers_data['secret_key'] ) || ! is_string( $suretriggers_data['secret_key'] ) ) {
1453 - // OttoKit is not authenticated yet.
1454 - return false;
1455 - }
1456 -
1457 - return true;
1458 - }
1459 -
1460 - /**
1461 - * Get OttoKit (formerly SureTriggers) integration metadata.
1462 - *
1463 - * Shared by the admin app and the donation form editor so both surface the
1464 - * same install/activate/connect state.
1465 - *
1466 - * @return array<string,mixed> Integration metadata.
1467 - * @since 1.2.0
1468 - */
1469 - public static function get_ottokit_integration() {
1470 - $plugin_file = 'suretriggers/suretriggers.php';
1471 -
1472 - if ( ! function_exists( 'is_plugin_active' ) ) {
1473 - include_once ABSPATH . 'wp-admin/includes/plugin.php';
1474 - }
1475 -
1476 - $status = 'Install';
1477 - if ( is_plugin_active( $plugin_file ) ) {
1478 - $status = 'Activated';
1479 - } elseif ( array_key_exists( $plugin_file, get_plugins() ) ) {
1480 - $status = 'Installed';
1481 - }
1482 -
1483 - return [
1484 - 'title' => 'OttoKit',
1485 - 'slug' => 'suretriggers',
1486 - 'path' => $plugin_file,
1487 - 'status' => $status,
1488 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Filter is owned by the OttoKit plugin.
1489 - 'connected' => apply_filters( 'suretriggers_is_user_connected', '' ),
1490 - 'connection_url' => admin_url( 'admin.php?page=suretriggers' ),
1491 - ];
1492 1226 }
1493 1227 }