initiate_settings_fields(); // Add submenu page. $parent_slug = 'wp-subscription'; add_submenu_page( $parent_slug, __( 'Settings', 'subscription' ), __( 'Settings', 'subscription' ), 'manage_options', 'wp-subscription-settings', [ $this, 'settings_content' ] ); } /** * Initialize settings fields. */ public function initiate_settings_fields() { global $wp_roles; $roles = []; foreach ( ( $wp_roles->roles ?? [] ) as $role_key => $role ) { $roles[ $role_key ] = $role['name']; } // Setting fields. $settings_fields = [ [ 'type' => 'heading', 'group' => 'renewals', 'priority' => 0, 'field_data' => [ 'title' => __( 'Renewals', 'subscription' ), ], ], [ 'type' => 'select', 'group' => 'renewals', 'priority' => 1, 'field_data' => [ 'id' => 'wp_subscription_renewal_process', 'title' => __( 'Renewal Process', 'subscription' ), 'description' => __( 'How renewal process will be done after Subscription Expired.', 'subscription' ), 'options' => [ 'auto' => __( 'Automatic', 'subscription' ), 'manual' => __( 'Manual', 'subscription' ), ], 'selected' => esc_attr( subscrpt_get_renewal_process() ), ], ], [ 'type' => 'input', 'group' => 'renewals', 'priority' => 2, 'field_data' => [ 'id' => 'wp_subscription_manual_renew_cart_notice', 'title' => __( 'Renewal Cart Notice', 'subscription' ), 'description' => __( 'Display Notice when Renewal Subscription product add to cart. Only available for Manual Renewal Process.', 'subscription' ), 'value' => esc_attr( subscrpt_get_manual_renew_cart_notice() ), ], ], [ 'type' => 'toggle', 'group' => 'renewals', 'priority' => 3, 'field_data' => [ 'id' => 'wp_subscription_stripe_auto_renew', 'title' => __( 'Stripe Auto Renewal', 'subscription' ), 'label' => __( 'Accept Stripe Auto Renewals', 'subscription' ), 'description' => class_exists( 'WC_Stripe' ) ? sprintf( /* translators: 1: opening plugin link tag, 2: closing link tag, 3: opening settings link tag */ __( '✓ %1$sWooCommerce Stripe Payment Gateway%2$s is active. %3$sConfigure%2$s', 'subscription' ), '', '', '' ) : sprintf( /* translators: HTML tags */ __( '%1$s WooCommerce Stripe Payment Gateway %2$s plugin is required!', 'subscription' ), '', '' ) . $this->get_stripe_plugin_action(), 'value' => '1', 'checked' => '1' === get_option( 'wp_subscription_stripe_auto_renew', '1' ), ], ], [ 'type' => 'toggle', 'group' => 'renewals', 'priority' => 4, 'field_data' => [ 'id' => 'wp_subscription_auto_renewal_toggle', 'title' => __( 'Auto Renewal Toggle', 'subscription' ), 'label' => __( 'Display the auto renewal toggle', 'subscription' ), 'description' => __( 'Allow customers to turn on and off automatic renewals from their Subscription details page', 'subscription' ), 'value' => '1', 'checked' => '1' === get_option( 'wp_subscription_auto_renewal_toggle', '1' ), ], ], [ 'type' => 'select', 'group' => 'role_based_settings', 'priority' => 2, 'field_data' => [ 'id' => 'wp_subscription_active_role', 'title' => __( 'Subscriber Default Role', 'subscription' ), 'description' => __( 'When a subscription is activated, either manually or after a successful purchase, new users will be assigned this role.', 'subscription' ), 'options' => $roles, 'selected' => esc_attr( get_option( 'wp_subscription_active_role', 'subscriber' ) ), ], ], [ 'type' => 'select', 'group' => 'role_based_settings', 'priority' => 3, 'field_data' => [ 'id' => 'wp_subscription_unactive_role', 'title' => __( 'Subscriber Inactive Role', 'subscription' ), 'description' => __( "If a subscriber's subscription is manually cancelled or expires, they will be assigned this role.", 'subscription' ), 'options' => $roles, 'selected' => esc_attr( get_option( 'wp_subscription_unactive_role', 'customer' ) ), ], ], ]; // Allow other modules to add/modify settings fields. $settings_fields = apply_filters( 'subscrpt_settings_fields', $settings_fields ); // Process settings fields (group & sort). $settings_fields = apply_filters( 'process_subscrpt_settings_fields', $settings_fields ); // Set the settings fields. $this->settings_fields = $settings_fields; } /** * Install / Activate link for the Stripe gateway plugin. * * Rendered inside a field description, which goes through `wp_kses_post()`, * so the link carries data attributes rather than an inline handler; * `integration_settings.js` picks it up. * * @return string Link HTML, or an empty string when the user cannot act on it. */ private function get_stripe_plugin_action() { $slug = 'woocommerce-gateway-stripe'; $installed = '' !== Ajax::get_installed_plugin_file( $slug ); if ( $installed && current_user_can( 'activate_plugins' ) ) { $label = __( 'Activate', 'subscription' ); $busy_label = __( 'Activating…', 'subscription' ); } elseif ( ! $installed && current_user_can( 'install_plugins' ) ) { $label = __( 'Install & Activate', 'subscription' ); $busy_label = __( 'Installing…', 'subscription' ); } else { return ''; } return sprintf( ' %3$s', esc_attr( $slug ), esc_attr( $busy_label ), esc_html( $label ) ); } /** * Enqueue the plugin installer on the settings page. * * @param string $hook The current admin page hook. */ public function enqueue_installer_script( $hook ) { if ( false === strpos( $hook, 'wp-subscription-settings' ) ) { return; } wp_enqueue_script( 'subscrpt-integrations', SUBSCRPT_ASSETS . '/js/integration_settings.js', [], SUBSCRPT_VERSION, true ); wp_localize_script( 'subscrpt-integrations', 'subscrptIntegrations', array( 'nonce' => wp_create_nonce( 'subscrpt_integration_install_nonce' ), 'ajaxUrl' => admin_url( 'admin-ajax.php' ), ) ); } /** * Register settings options. **/ public function register_settings() { register_setting( 'wp_subscription_settings', 'wp_subscription_renewal_process', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ) ); register_setting( 'wp_subscription_settings', 'wp_subscription_manual_renew_cart_notice', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field', ) ); register_setting( 'wp_subscription_settings', 'wp_subscription_active_role', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ) ); register_setting( 'wp_subscription_settings', 'wp_subscription_unactive_role', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ) ); register_setting( 'wp_subscription_settings', 'wp_subscription_stripe_auto_renew', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ) ); register_setting( 'wp_subscription_settings', 'wp_subscription_auto_renewal_toggle', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ) ); do_action( 'subscrpt_register_settings', 'subscrpt_settings' ); } /** * Settings HTML. */ public function settings_content() { $settings_fields = $this->settings_fields; $category_groups = SettingsHelper::category_groups( $settings_fields ); $active_cat = $this->get_active_category( $category_groups ); // Header. $menu = new Menu(); $menu->render_admin_header( __( 'Settings', 'subscription' ) ); include 'views/settings.php'; // Footer. $menu->render_admin_footer(); } /** * Which settings section the page opens on. * * Read from `?cat=`, and it has to be a query argument rather than a * fragment: the form posts to `options.php`, which redirects back to * `_wp_http_referer`, and a fragment never reaches the server. Keeping the * section in the query string is what returns you to the panel you saved * from. * * Validated against the sections that actually hold groups, so an unknown * or hostile value — or one naming a section only Pro fills — opens the * first real section rather than an empty panel. * * @param array $category_groups Section key => group keys. * @return string Section key, or an empty string when there are no groups. */ private function get_active_category( array $category_groups ) { $cats = array_keys( $category_groups ); if ( empty( $cats ) ) { return ''; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only section selection, validated against the list above. $requested = isset( $_GET['cat'] ) ? sanitize_key( wp_unslash( $_GET['cat'] ) ) : ''; // `all` stacks every section on one page; a known section opens just that // one. With nothing requested (or something invalid), open the first // section rather than the stacked "All Settings" view. if ( 'all' === $requested || in_array( $requested, $cats, true ) ) { return $requested; } return $cats[0]; } /** * Enqueue WooCommerce admin styles for settings page. * * @param string $hook The current admin page hook. */ public function enqueue_wc_admin_styles( $hook ) { // Only load on our settings page if ( isset( $_GET['post_type'] ) && strpos( sanitize_text_field( wp_unslash( $_GET['post_type'] ) ), 'subscrpt_order' ) !== false ) { // WooCommerce admin styles wp_enqueue_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css', array(), SUBSCRPT_VERSION ); // Optional: WooCommerce enhanced select2 wp_enqueue_style( 'woocommerce_admin_select2', WC()->plugin_url() . '/assets/css/select2.css', array(), SUBSCRPT_VERSION ); wp_enqueue_script( 'select2' ); } } }