PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.2.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.2.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
← All changes | includes/Admin/Settings.php +120 -60 1.11.0 → 2.2.0 View file →
@@ -1,8 +1,10 @@
1 1 <?php
2 2
3 3 namespace SpringDevs\Subscription\Admin;
4 4
5 +use SpringDevs\Subscription\Ajax;
6 +
5 7 /**
6 8 * Class Settings
7 9 *
8 10 * @package SpringDevs\Subscription\Admin
@@ -24,8 +26,9 @@
24 26
25 27 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
26 28 add_action( 'admin_init', array( $this, 'register_settings' ) );
27 29 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_wc_admin_styles' ) );
30 + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_installer_script' ) );
28 31 }
29 32
30 33 /**
31 34 * Register submenu on `Subscriptions` menu.
@@ -61,17 +64,17 @@
61 64 // Setting fields.
62 65 $settings_fields = [
63 66 [
64 67 'type' => 'heading',
65 - 'group' => 'main',
68 + 'group' => 'renewals',
66 69 'priority' => 0,
67 70 'field_data' => [
68 - 'title' => __( 'General Settings', 'subscription' ),
71 + 'title' => __( 'Renewals', 'subscription' ),
69 72 ],
70 73 ],
71 74 [
72 75 'type' => 'select',
73 - 'group' => 'main',
76 + 'group' => 'renewals',
74 77 'priority' => 1,
75 78 'field_data' => [
76 79 'id' => 'wp_subscription_renewal_process',
77 80 'title' => __( 'Renewal Process', 'subscription' ),
@@ -79,36 +82,44 @@
79 82 'options' => [
80 83 'auto' => __( 'Automatic', 'subscription' ),
81 84 'manual' => __( 'Manual', 'subscription' ),
82 85 ],
83 - 'selected' => esc_attr( get_option( 'wp_subscription_renewal_process', 'auto' ) ),
86 + 'selected' => esc_attr( subscrpt_get_renewal_process() ),
84 87 ],
85 88 ],
86 89 [
87 90 'type' => 'input',
88 - 'group' => 'main',
91 + 'group' => 'renewals',
89 92 'priority' => 2,
90 93 'field_data' => [
91 94 'id' => 'wp_subscription_manual_renew_cart_notice',
92 95 'title' => __( 'Renewal Cart Notice', 'subscription' ),
93 96 'description' => __( 'Display Notice when Renewal Subscription product add to cart. Only available for Manual Renewal Process.', 'subscription' ),
94 - 'value' => esc_attr( get_option( 'wp_subscription_manual_renew_cart_notice' ) ),
97 + 'value' => esc_attr( subscrpt_get_manual_renew_cart_notice() ),
95 98 ],
96 99 ],
97 100 [
98 101 'type' => 'toggle',
99 - 'group' => 'main',
102 + 'group' => 'renewals',
100 103 'priority' => 3,
101 104 'field_data' => [
102 105 'id' => 'wp_subscription_stripe_auto_renew',
103 106 'title' => __( 'Stripe Auto Renewal', 'subscription' ),
104 107 'label' => __( 'Accept Stripe Auto Renewals', 'subscription' ),
105 - 'description' => sprintf(
106 - /* translators: HTML tags */
107 - __( '%1$s WooCommerce Stripe Payment Gateway %2$s plugin is required!', 'subscription' ),
108 - '<a href="https://wordpress.org/plugins/woocommerce-gateway-stripe/" target="_blank">',
109 - '</a>'
110 - ),
108 + 'description' => class_exists( 'WC_Stripe' )
109 + ? sprintf(
110 + /* translators: 1: opening plugin link tag, 2: closing link tag, 3: opening settings link tag */
111 + __( '&#10003; %1$sWooCommerce Stripe Payment Gateway%2$s is active. %3$sConfigure%2$s', 'subscription' ),
112 + '<a href="https://wordpress.org/plugins/woocommerce-gateway-stripe/" target="_blank">',
113 + '</a>',
114 + '<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) ) . '">'
115 + )
116 + : sprintf(
117 + /* translators: HTML tags */
118 + __( '%1$s WooCommerce Stripe Payment Gateway %2$s plugin is required!', 'subscription' ),
119 + '<a href="https://wordpress.org/plugins/woocommerce-gateway-stripe/" target="_blank">',
120 + '</a>'
121 + ) . $this->get_stripe_plugin_action(),
111 122 'value' => '1',
112 123 'checked' => '1' === get_option( 'wp_subscription_stripe_auto_renew', '1' ),
113 124 ],
114 125 ],
@@ -113,9 +124,9 @@
113 124 ],
114 125 ],
115 126 [
116 127 'type' => 'toggle',
117 - 'group' => 'main',
128 + 'group' => 'renewals',
118 129 'priority' => 4,
119 130 'field_data' => [
120 131 'id' => 'wp_subscription_auto_renewal_toggle',
121 132 'title' => __( 'Auto Renewal Toggle', 'subscription' ),
@@ -126,10 +137,10 @@
126 137 ],
127 138 ],
128 139 [
129 140 'type' => 'select',
130 - 'group' => 'main',
131 - 'priority' => 5,
141 + 'group' => 'role_based_settings',
142 + 'priority' => 2,
132 143 'field_data' => [
133 144 'id' => 'wp_subscription_active_role',
134 145 'title' => __( 'Subscriber Default Role', 'subscription' ),
135 146 'description' => __( 'When a subscription is activated, either manually or after a successful purchase, new users will be assigned this role.', 'subscription' ),
@@ -138,10 +149,10 @@
138 149 ],
139 150 ],
140 151 [
141 152 'type' => 'select',
142 - 'group' => 'main',
143 - 'priority' => 6,
153 + 'group' => 'role_based_settings',
154 + 'priority' => 3,
144 155 'field_data' => [
145 156 'id' => 'wp_subscription_unactive_role',
146 157 'title' => __( 'Subscriber Inactive Role', 'subscription' ),
147 158 'description' => __( "If a subscriber's subscription is manually cancelled or expires, they will be assigned this role.", 'subscription' ),
@@ -148,34 +159,8 @@
148 159 'options' => $roles,
149 160 'selected' => esc_attr( get_option( 'wp_subscription_unactive_role', 'customer' ) ),
150 161 ],
151 162 ],
152 - [
153 - 'type' => 'toggle',
154 - 'group' => 'main',
155 - 'priority' => 9.5,
156 - 'field_data' => [
157 - 'id' => 'subscrpt_cancellation_feedback_enabled',
158 - 'title' => __( 'Cancellation Survey', 'subscription' ),
159 - 'label' => __( 'Ask customers why they are cancelling', 'subscription' ),
160 - 'description' => __( 'Show a short cancellation survey when a customer cancels a subscription, and record the reason for churn tracking.', 'subscription' ),
161 - 'value' => '1',
162 - 'checked' => '1' === get_option( 'subscrpt_cancellation_feedback_enabled', '1' ),
163 - ],
164 - ],
165 - [
166 - 'type' => 'toggle',
167 - 'group' => 'main',
168 - 'priority' => 9.6,
169 - 'field_data' => [
170 - 'id' => 'subscrpt_cancellation_feedback_comment',
171 - 'title' => __( 'Survey Comment Box', 'subscription' ),
172 - 'label' => __( 'Allow an additional comment', 'subscription' ),
173 - 'description' => __( 'Show an optional free-text comment field in the cancellation survey.', 'subscription' ),
174 - 'value' => '1',
175 - 'checked' => '1' === get_option( 'subscrpt_cancellation_feedback_comment', '1' ),
176 - ],
177 - ],
178 163 ];
179 164
180 165 // Allow other modules to add/modify settings fields.
181 166 $settings_fields = apply_filters( 'subscrpt_settings_fields', $settings_fields );
@@ -187,8 +172,61 @@
187 172 $this->settings_fields = $settings_fields;
188 173 }
189 174
190 175 /**
176 + * Install / Activate link for the Stripe gateway plugin.
177 + *
178 + * Rendered inside a field description, which goes through `wp_kses_post()`,
179 + * so the link carries data attributes rather than an inline handler;
180 + * `integration_settings.js` picks it up.
181 + *
182 + * @return string Link HTML, or an empty string when the user cannot act on it.
183 + */
184 + private function get_stripe_plugin_action() {
185 + $slug = 'woocommerce-gateway-stripe';
186 + $installed = '' !== Ajax::get_installed_plugin_file( $slug );
187 +
188 + if ( $installed && current_user_can( 'activate_plugins' ) ) {
189 + $label = __( 'Activate', 'subscription' );
190 + $busy_label = __( 'Activating…', 'subscription' );
191 + } elseif ( ! $installed && current_user_can( 'install_plugins' ) ) {
192 + $label = __( 'Install & Activate', 'subscription' );
193 + $busy_label = __( 'Installing…', 'subscription' );
194 + } else {
195 + return '';
196 + }
197 +
198 + return sprintf(
199 + ' <a href="#" data-subscrpt-install-plugin="%1$s" data-busy-label="%2$s">%3$s</a>',
200 + esc_attr( $slug ),
201 + esc_attr( $busy_label ),
202 + esc_html( $label )
203 + );
204 + }
205 +
206 + /**
207 + * Enqueue the plugin installer on the settings page.
208 + *
209 + * @param string $hook The current admin page hook.
210 + */
211 + public function enqueue_installer_script( $hook ) {
212 + if ( false === strpos( $hook, 'wp-subscription-settings' ) ) {
213 + return;
214 + }
215 +
216 + wp_enqueue_script( 'subscrpt-integrations', SUBSCRPT_ASSETS . '/js/integration_settings.js', [], SUBSCRPT_VERSION, true );
217 +
218 + wp_localize_script(
219 + 'subscrpt-integrations',
220 + 'subscrptIntegrations',
221 + array(
222 + 'nonce' => wp_create_nonce( 'subscrpt_integration_install_nonce' ),
223 + 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
224 + )
225 + );
226 + }
227 +
228 + /**
191 229 * Register settings options.
192 230 **/
193 231 public function register_settings() {
194 232 register_setting(
@@ -238,24 +276,8 @@
238 276 'type' => 'string',
239 277 'sanitize_callback' => 'sanitize_text_field',
240 278 )
241 279 );
242 - register_setting(
243 - 'wp_subscription_settings',
244 - 'subscrpt_cancellation_feedback_enabled',
245 - array(
246 - 'type' => 'string',
247 - 'sanitize_callback' => 'sanitize_text_field',
248 - )
249 - );
250 - register_setting(
251 - 'wp_subscription_settings',
252 - 'subscrpt_cancellation_feedback_comment',
253 - array(
254 - 'type' => 'string',
255 - 'sanitize_callback' => 'sanitize_text_field',
256 - )
257 - );
258 280
259 281 do_action( 'subscrpt_register_settings', 'subscrpt_settings' );
260 282 }
261 283
@@ -263,8 +285,10 @@
263 285 * Settings HTML.
264 286 */
265 287 public function settings_content() {
266 288 $settings_fields = $this->settings_fields;
289 + $category_groups = SettingsHelper::category_groups( $settings_fields );
290 + $active_cat = $this->get_active_category( $category_groups );
267 291
268 292 // Header.
269 293 $menu = new Menu();
270 294 $menu->render_admin_header( __( 'Settings', 'subscription' ) );
@@ -272,8 +296,44 @@
272 296 include 'views/settings.php';
273 297
274 298 // Footer.
275 299 $menu->render_admin_footer();
300 + }
301 +
302 + /**
303 + * Which settings section the page opens on.
304 + *
305 + * Read from `?cat=`, and it has to be a query argument rather than a
306 + * fragment: the form posts to `options.php`, which redirects back to
307 + * `_wp_http_referer`, and a fragment never reaches the server. Keeping the
308 + * section in the query string is what returns you to the panel you saved
309 + * from.
310 + *
311 + * Validated against the sections that actually hold groups, so an unknown
312 + * or hostile value — or one naming a section only Pro fills — opens the
313 + * first real section rather than an empty panel.
314 + *
315 + * @param array<string,string[]> $category_groups Section key => group keys.
316 + * @return string Section key, or an empty string when there are no groups.
317 + */
318 + private function get_active_category( array $category_groups ) {
319 + $cats = array_keys( $category_groups );
320 +
321 + if ( empty( $cats ) ) {
322 + return '';
323 + }
324 +
325 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only section selection, validated against the list above.
326 + $requested = isset( $_GET['cat'] ) ? sanitize_key( wp_unslash( $_GET['cat'] ) ) : '';
327 +
328 + // `all` stacks every section on one page; a known section opens just that
329 + // one. With nothing requested (or something invalid), open the first
330 + // section rather than the stacked "All Settings" view.
331 + if ( 'all' === $requested || in_array( $requested, $cats, true ) ) {
332 + return $requested;
333 + }
334 +
335 + return $cats[0];
276 336 }
277 337
278 338 /**
279 339 * Enqueue WooCommerce admin styles for settings page.