| @@ -12,9 +12,8 @@ | ||
| 12 | 12 | |
| 13 | 13 | use Better_Payment\Lite\Admin\DB; |
| 14 | 14 | use Better_Payment\Lite\Classes\Handler; |
| 15 | 15 | use Better_Payment\Lite\Classes\Helper; |
| 16 | -use Better_Payment\Lite\Classes\ProSubscriptionTransactionData; | |
| 17 | 16 | use Better_Payment\Lite\Traits\Helper as TraitsHelper; |
| 18 | 17 | |
| 19 | 18 | if ( ! defined( 'ABSPATH' ) ) { |
| 20 | 19 | exit; |
| @@ -161,14 +160,10 @@ | ||
| 161 | 160 | return ''; |
| 162 | 161 | } |
| 163 | 162 | |
| 164 | 163 | return '<div ' . $wrapper_attributes . '>' . |
| 165 | - '<div class="better-payment-block__notice">' . | |
| 166 | - '<p>' . esc_html__( 'Payment form: enable at least one payment gateway (PayPal, Stripe or Paystack) in Better Payment settings. This notice is only visible to you.', 'better-payment' ) . '</p>' . | |
| 167 | - '<p><a href="' . esc_url( admin_url( 'admin.php?page=better-payment-admin&tab=settings§ion=general' ) ) . '">' . | |
| 168 | - esc_html__( 'Open Better Payment settings', 'better-payment' ) . | |
| 169 | - '</a></p>' . | |
| 170 | - '</div></div>'; | |
| 164 | + $this->render_gateway_notice( $attributes, $global_settings ) . | |
| 165 | + '</div>'; | |
| 171 | 166 | } |
| 172 | 167 | |
| 173 | 168 | // Enqueue scripts/styles before manage_response() so they are present even when the |
| 174 | 169 | // block returns the pending or success state early (the AJAX poller needs better-payment.js). |
| @@ -1013,8 +1008,165 @@ | ||
| 1013 | 1008 | ); |
| 1014 | 1009 | } |
| 1015 | 1010 | |
| 1016 | 1011 | /** |
| 1012 | + * Why a Payment Form block has no gateway, decided per gateway. | |
| 1013 | + * | |
| 1014 | + * Each gateway resolves in `build_block_settings()` from the block's own | |
| 1015 | + * toggle when the block saved one, and from the site setting only when it | |
| 1016 | + * did not. So a gateway is off for one of two reasons, and they are fixed in | |
| 1017 | + * different places: | |
| 1018 | + * | |
| 1019 | + * - `block` — the site has a gateway enabled, but this block switches it | |
| 1020 | + * off. Settings cannot fix it: the gateway is already on there. | |
| 1021 | + * - `global` — no gateway is enabled site-wide. Settings fixes it on its own | |
| 1022 | + * for any gateway the block leaves to the site (`settings_fixes`); a | |
| 1023 | + * gateway the block also switched off needs both (`needs_block`). A new | |
| 1024 | + * block seeds its toggles from the settings, so on a site with nothing | |
| 1025 | + * enabled `needs_block` is the usual case. | |
| 1026 | + * | |
| 1027 | + * Mirrors the editor's `gatewayNoticeState()` (helpers/gatewayNotice.js), so | |
| 1028 | + * the editor and the page never give two different answers. | |
| 1029 | + * | |
| 1030 | + * @param array $attributes Block attributes. | |
| 1031 | + * @param array $global_settings Global plugin settings. | |
| 1032 | + * @return array{reason: string, site_gateways: string[], settings_fixes: string[], needs_block: bool} | |
| 1033 | + */ | |
| 1034 | + public static function gateway_notice_state( $attributes, $global_settings ) { | |
| 1035 | + $gateways = array( | |
| 1036 | + 'PayPal' => array( 'paypalEnabled', 'better_payment_settings_general_general_paypal' ), | |
| 1037 | + 'Stripe' => array( 'stripeEnabled', 'better_payment_settings_general_general_stripe' ), | |
| 1038 | + 'Paystack' => array( 'paystackEnabled', 'better_payment_settings_general_general_paystack' ), | |
| 1039 | + ); | |
| 1040 | + | |
| 1041 | + $site_gateways = array(); | |
| 1042 | + $settings_fixes = array(); | |
| 1043 | + | |
| 1044 | + foreach ( $gateways as $label => $keys ) { | |
| 1045 | + if ( isset( $global_settings[ $keys[1] ] ) && 'yes' === $global_settings[ $keys[1] ] ) { | |
| 1046 | + $site_gateways[] = $label; | |
| 1047 | + } | |
| 1048 | + if ( ! isset( $attributes[ $keys[0] ] ) ) { | |
| 1049 | + $settings_fixes[] = $label; | |
| 1050 | + } | |
| 1051 | + } | |
| 1052 | + | |
| 1053 | + $reason = empty( $site_gateways ) ? 'global' : 'block'; | |
| 1054 | + | |
| 1055 | + return array( | |
| 1056 | + 'reason' => $reason, | |
| 1057 | + 'site_gateways' => $site_gateways, | |
| 1058 | + 'settings_fixes' => $settings_fixes, | |
| 1059 | + 'needs_block' => 'block' === $reason || empty( $settings_fixes ), | |
| 1060 | + ); | |
| 1061 | + } | |
| 1062 | + | |
| 1063 | + /** | |
| 1064 | + * The admin-only notice printed in place of a form with no gateway. | |
| 1065 | + * | |
| 1066 | + * Names the gateways and the place that fixes them, and links to each place | |
| 1067 | + * the fix needs: Better Payment settings, this block's editor, or both. The | |
| 1068 | + * editor link is offered only when the block is really in the current post's | |
| 1069 | + * content — in a template, template part, synced pattern or widget area the | |
| 1070 | + * current post's editor does not contain it, so the notice says where to look | |
| 1071 | + * instead of linking to the wrong screen. | |
| 1072 | + * | |
| 1073 | + * @param array $attributes Block attributes. | |
| 1074 | + * @param array $global_settings Global plugin settings. | |
| 1075 | + * @return string Notice HTML. | |
| 1076 | + */ | |
| 1077 | + private function render_gateway_notice( $attributes, $global_settings ) { | |
| 1078 | + $state = self::gateway_notice_state( $attributes, $global_settings ); | |
| 1079 | + | |
| 1080 | + if ( 'block' === $state['reason'] ) { | |
| 1081 | + $message = sprintf( | |
| 1082 | + /* translators: %s: gateway names, e.g. "PayPal or Stripe". */ | |
| 1083 | + __( 'Payment form: every payment method is switched off in this block’s settings. Turn on %s under Payment Settings in the block sidebar.', 'better-payment' ), | |
| 1084 | + self::join_gateway_names( $state['site_gateways'] ) | |
| 1085 | + ); | |
| 1086 | + } elseif ( $state['needs_block'] ) { | |
| 1087 | + $message = __( 'Payment form: no payment gateway is enabled in Better Payment settings, and every payment method is switched off in this block’s settings. Enable PayPal, Stripe or Paystack in Better Payment settings, then turn the same gateway on under Payment Settings in the block sidebar.', 'better-payment' ); | |
| 1088 | + } else { | |
| 1089 | + $message = sprintf( | |
| 1090 | + /* translators: %s: gateway names, e.g. "PayPal, Stripe or Paystack". */ | |
| 1091 | + __( 'Payment form: enable at least one payment gateway (%s) in Better Payment settings.', 'better-payment' ), | |
| 1092 | + self::join_gateway_names( $state['settings_fixes'] ) | |
| 1093 | + ); | |
| 1094 | + } | |
| 1095 | + | |
| 1096 | + $links = array(); | |
| 1097 | + | |
| 1098 | + if ( 'global' === $state['reason'] ) { | |
| 1099 | + $links[] = '<a href="' . esc_url( admin_url( 'admin.php?page=better-payment-admin&tab=settings§ion=general' ) ) . '">' . | |
| 1100 | + esc_html__( 'Open Better Payment settings', 'better-payment' ) . '</a>'; | |
| 1101 | + } | |
| 1102 | + | |
| 1103 | + $hint = ''; | |
| 1104 | + | |
| 1105 | + if ( $state['needs_block'] ) { | |
| 1106 | + $edit_url = self::block_edit_url(); | |
| 1107 | + | |
| 1108 | + if ( '' !== $edit_url ) { | |
| 1109 | + $links[] = '<a href="' . esc_url( $edit_url ) . '">' . | |
| 1110 | + esc_html__( 'Edit this form in the block editor', 'better-payment' ) . '</a>'; | |
| 1111 | + } else { | |
| 1112 | + $hint = '<p>' . esc_html__( 'This form is not part of this page’s content. Open the template, template part, pattern or widget area that contains it to change its settings.', 'better-payment' ) . '</p>'; | |
| 1113 | + } | |
| 1114 | + } | |
| 1115 | + | |
| 1116 | + return '<div class="better-payment-block__notice">' . | |
| 1117 | + '<p>' . esc_html( $message ) . ' ' . esc_html__( 'This notice is only visible to you.', 'better-payment' ) . '</p>' . | |
| 1118 | + $hint . | |
| 1119 | + ( $links ? '<p class="better-payment-block__notice-actions">' . implode( ' ', $links ) . '</p>' : '' ) . | |
| 1120 | + '</div>'; | |
| 1121 | + } | |
| 1122 | + | |
| 1123 | + /** | |
| 1124 | + * The editor URL of the current post, when it holds a Payment Form block. | |
| 1125 | + * | |
| 1126 | + * Empty when there is no current post, the user may not edit it, or its | |
| 1127 | + * content has no Payment Form block (the block came from a template, template | |
| 1128 | + * part, synced pattern or widget area). | |
| 1129 | + * | |
| 1130 | + * @return string Raw edit URL, or ''. | |
| 1131 | + */ | |
| 1132 | + private static function block_edit_url() { | |
| 1133 | + $post_id = (int) get_the_ID(); | |
| 1134 | + | |
| 1135 | + if ( $post_id <= 0 || ! current_user_can( 'edit_post', $post_id ) ) { | |
| 1136 | + return ''; | |
| 1137 | + } | |
| 1138 | + | |
| 1139 | + if ( ! has_block( 'better-payment/payment-form', $post_id ) ) { | |
| 1140 | + return ''; | |
| 1141 | + } | |
| 1142 | + | |
| 1143 | + return (string) get_edit_post_link( $post_id, 'raw' ); | |
| 1144 | + } | |
| 1145 | + | |
| 1146 | + /** | |
| 1147 | + * "A", "A or B", "A, B or C". | |
| 1148 | + * | |
| 1149 | + * @param string[] $names Gateway names (brand names, not translated). | |
| 1150 | + * @return string Joined list. | |
| 1151 | + */ | |
| 1152 | + private static function join_gateway_names( $names ) { | |
| 1153 | + $names = array_values( $names ); | |
| 1154 | + $last = array_pop( $names ); | |
| 1155 | + | |
| 1156 | + if ( empty( $names ) ) { | |
| 1157 | + return (string) $last; | |
| 1158 | + } | |
| 1159 | + | |
| 1160 | + return sprintf( | |
| 1161 | + /* translators: 1: comma-separated gateway names, 2: the last gateway name. */ | |
| 1162 | + __( '%1$s or %2$s', 'better-payment' ), | |
| 1163 | + implode( ', ', $names ), | |
| 1164 | + $last | |
| 1165 | + ); | |
| 1166 | + } | |
| 1167 | + | |
| 1168 | + /** | |
| 1017 | 1169 | * Resolve the correct Stripe key based on live mode setting. |
| 1018 | 1170 | * |
| 1019 | 1171 | * This matches Elementor's behavior where the key is resolved before being stored |
| 1020 | 1172 | * in better_payment_stripe_public_key/better_payment_stripe_secret_key. |
| @@ -1793,14 +1945,10 @@ | ||
| 1793 | 1945 | foreach ( $user_subscriptions as $tx ) { |
| 1794 | 1946 | $ffi = is_array( $tx->form_fields_info ) ? $tx->form_fields_info : array(); |
| 1795 | 1947 | |
| 1796 | 1948 | // The subscription columns come from the same place as UserAPI's REST rows: Pro fills |
| 1797 | - // `better_payment/user_api/subscription_row`, and Lite's copy serves only an active Pro | |
| 1798 | - // that does not (ProSubscriptionTransactionData, <= 1.4.3). | |
| 1799 | - $row = array(); | |
| 1800 | - if ( ProSubscriptionTransactionData::lite_copy_applies() ) { | |
| 1801 | - $row = ProSubscriptionTransactionData::subscription_row( $row, $ffi ); | |
| 1802 | - } | |
| 1949 | + // `better_payment/user_api/subscription_row`. | |
| 1950 | + $row = array(); | |
| 1803 | 1951 | $built = apply_filters( 'better_payment/user_api/subscription_row', $row, $ffi, $tx ); |
| 1804 | 1952 | $row = is_array( $built ) ? $built : $row; |
| 1805 | 1953 | |
| 1806 | 1954 | foreach ( $row as $key => $value ) { |