PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.0.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.0.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 1.4.1 1.4.2 1.5.0 1.5.1 All 61 releases
subscription / includes / Admin / Product.php

Product.php in Subscriptions for WooCommerce with Stripe Recurring Payments 2.0.0, at includes/Admin/Product.php

284 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Product editor integration (Subscription tab).
4 *
5 * @package SpringDevs\Subscription\Admin
6 */
7
8 namespace SpringDevs\Subscription\Admin;
9
10 use SpringDevs\Subscription\Illuminate\Helper;
11
12 // HPOS: This file does not access WooCommerce order data directly.
13 // All meta access is for product or subscription data only, not WooCommerce order data.
14 // If you add new order data access, use WooCommerce CRUD for HPOS compatibility.
15
16 /**
17 * Product class
18 *
19 * @package SpringDevs\Subscription\Admin
20 */
21 class Product {
22
23 /**
24 * Initialize the class
25 */
26 public function __construct() {
27 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
28 add_filter( 'woocommerce_product_data_tabs', array( $this, 'register_tab' ) );
29 add_action( 'woocommerce_product_data_panels', array( $this, 'subscription_forms' ) );
30 add_action( 'save_post_product', array( $this, 'save_subscrpt_data' ) );
31 add_filter( 'woocommerce_get_price_html', array( $this, 'change_price_html' ), 10, 2 );
32 }
33
34 /**
35 * Add trial, signup fee etc. with product price.
36 *
37 * @param string $price Price.
38 * @param \WC_Product $product Product.
39 *
40 * @return string
41 */
42 public function change_price_html( $price, $product ) {
43 if ( $product->is_type( 'variable' ) || '' === $price || subscrpt_pro_activated() ) {
44 return $price;
45 }
46
47 $enabled = $product->get_meta( '_subscrpt_enabled' );
48 if ( $enabled ) :
49 $type = Helper::get_typos( 1, $product->get_meta( '_subscrpt_timing_option' ), true );
50 $meta_trial_time = $product->get_meta( '_subscrpt_trial_timing_per' );
51 $trial = null;
52 if ( ! empty( $meta_trial_time ) && $meta_trial_time > 0 ) {
53 $trial_type = Helper::get_typos( $meta_trial_time, $product->get_meta( '_subscrpt_trial_timing_option' ), true );
54 $trial = '<br/> + Get ' . $meta_trial_time . ' ' . ucfirst( $trial_type ) . ' free trial!';
55 }
56
57 $price_html = $price . ' / ' . ucfirst( $type ) . $trial;
58 return $price_html;
59 else :
60 return $price;
61 endif;
62 }
63
64 /**
65 * Enqueue Assets.
66 */
67 public function enqueue_assets() {
68 wp_enqueue_script( 'sdevs_subscription_admin' );
69
70 // Plan view assets on the product editor. Enqueued whether or not Pro is
71 // active: with Pro off, free renders its own panel; with Pro on, the plan
72 // view mounts on Pro's `subscrpt_simple_plan_panel` hook.
73 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
74 if ( ! $screen || 'product' !== $screen->id ) {
75 return;
76 }
77
78 wp_enqueue_style( 'subscrpt_admin_components' );
79 wp_enqueue_script( 'subscrpt_admin_components' );
80
81 // Shared plan-group + selling-plan modal logic. With Pro active the
82 // Subscription tab exposes "+ New plan group", which drives these modals.
83 wp_enqueue_script( 'subscrpt_plan_forms_js' );
84 wp_localize_script( 'subscrpt_plan_forms_js', 'subscrptPlanForms', \SpringDevs\Subscription\Admin\Plans::plan_forms_config() );
85
86 wp_enqueue_script(
87 'subscrpt_product_plans_js',
88 SUBSCRPT_ASSETS . '/js/admin/product-plans.js',
89 array( 'subscrpt_admin_components', 'subscrpt_plan_forms_js' ),
90 SUBSCRPT_VERSION,
91 true
92 );
93
94 wp_localize_script(
95 'subscrpt_product_plans_js',
96 'subscrptProductPlans',
97 array(
98 'restUrl' => esc_url_raw( rest_url( 'wpsubscription/v1/plans' ) ),
99 'nonce' => wp_create_nonce( 'wp_rest' ),
100 'currency' => function_exists( 'get_woocommerce_currency_symbol' )
101 ? html_entity_decode( get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8' )
102 : '$',
103 'i18n' => array(
104 'connectError' => __( 'Could not connect the plan. Please try again.', 'subscription' ),
105 'pickPlan' => __( 'Please select a plan.', 'subscription' ),
106 'confirmDetach' => __( 'Detach this product from the plan?', 'subscription' ),
107 'loading' => __( 'Loading plans…', 'subscription' ),
108 'step1' => __( 'Step 1 of 2 · Plan', 'subscription' ),
109 'step2' => __( 'Step 2 of 2 · Plan', 'subscription' ),
110 'wizardNext' => __( 'Continue', 'subscription' ),
111 'wizardBack' => __( 'Back', 'subscription' ),
112 'wizardCreate' => __( 'Create', 'subscription' ),
113 'addPlan' => __( 'Add plan', 'subscription' ),
114 'copyLinkPrompt' => __( 'Copy this direct checkout link:', 'subscription' ),
115 ),
116 )
117 );
118 }
119
120 /**
121 * Register "Subscription" option tab.
122 *
123 * @param array $tabs Tabs.
124 *
125 * @return array
126 */
127 public function register_tab( $tabs ) {
128 $tabs['sdevs_subscription'] = array(
129 'label' => __( 'Subscription', 'subscription' ),
130 // Shown for simple and variable products. The panel content differs
131 // by type (see subscription_forms): simple renders here in free;
132 // variable is filled by Pro via `subscrpt_variable_subscription_panel`.
133 'class' => array( 'show_if_simple', 'show_if_variable' ),
134 'target' => 'sdevs_subscription_options',
135 'priority' => 11,
136 );
137 return $tabs;
138 }
139
140 /**
141 * Display forms on product create/edit.
142 */
143 public function subscription_forms() {
144 $screen = get_current_screen();
145 $subscrpt_current = ( $screen && 'edit' === $screen->parent_base ) ? wc_get_product( get_the_ID() ) : null;
146
147 // Variable products: free renders the panel shell; the content is filled
148 // by Pro (per-variation sections) via the action below. Free itself is
149 // simple-only, so with Pro inactive it shows an upgrade note.
150 if ( $subscrpt_current && $subscrpt_current->is_type( 'variable' ) ) {
151 ?>
152 <div id="sdevs_subscription_options" class="panel woocommerce_options_panel option_group sdevs-form sdevs_panel show_if_variable" style="padding:10px;">
153 <?php
154 /**
155 * Fires inside the Subscription tab for a variable product. Pro
156 * hooks this to render its per-variation subscription sections.
157 *
158 * @param \WC_Product $subscrpt_current Variable product being edited.
159 */
160 do_action( 'subscrpt_variable_subscription_panel', $subscrpt_current );
161
162 if ( ! has_action( 'subscrpt_variable_subscription_panel' ) ) {
163 ?>
164 <div style="text-align:center;padding:30px 20px;">
165 <span style="display:inline-flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:50%;background:var(--wpsubs-brand-light,#fff1eb);color:var(--wpsubs-brand,#ff4d00);">
166 <span class="dashicons dashicons-lock" style="font-size:24px;width:24px;height:24px;"></span>
167 </span>
168 <h3 style="margin:14px 0 6px;font-size:15px;color:var(--wpsubs-text,#1d2327);display:flex;align-items:center;justify-content:center;gap:8px;">
169 <?php esc_html_e( 'Variable product subscriptions', 'subscription' ); ?>
170 <span class="wpsubs-badge wpsubs-badge--pro"><?php esc_html_e( 'Pro', 'subscription' ); ?></span>
171 </h3>
172 <p style="margin:0 auto;max-width:380px;font-size:13px;line-height:1.6;color:var(--wpsubs-text-muted,#646970);">
173 <?php esc_html_e( 'Sell each variation as its own subscription, with per-variation billing, trials and sign-up fees.', 'subscription' ); ?>
174 </p>
175 <a href="https://wpsubscription.co/?utm_source=plugin&utm_medium=admin&utm_campaign=upgrade_pro" target="_blank" rel="noopener noreferrer" class="wpsubs-btn wpsubs-btn--primary" style="margin-top:16px;">
176 <?php esc_html_e( 'Upgrade to Pro', 'subscription' ); ?>
177 </a>
178 </div>
179 <?php
180 }
181 ?>
182 </div>
183 <?php
184 return;
185 }
186
187 if ( function_exists( 'subscrpt_pro_activated' ) ) {
188 if ( subscrpt_pro_activated() ) {
189 do_action( 'subscrpt_simple_pro_fields', get_the_ID() );
190 } else {
191 $timing_types = array(
192 'days' => __( 'Daily', 'subscription' ),
193 'weeks' => __( 'Weekly', 'subscription' ),
194 'months' => __( 'Monthly', 'subscription' ),
195 'years' => __( 'Yearly', 'subscription' ),
196 );
197 $trial_timing_types = wps_subscription_get_timing_types();
198 $subscrpt_timing = null;
199 $subscrpt_trial_time = null;
200 $subscrpt_trial_timing = null;
201 $subscrpt_cart_txt = 'subscribe';
202 $subscrpt_user_cancell = 'yes';
203 $subscrpt_limit = 'one';
204 $subscrpt_enabled = false;
205
206 $subscrpt_product = null;
207 $screen = get_current_screen();
208 if ( 'edit' === $screen->parent_base ) {
209 $subscrpt_product = wc_get_product( get_the_ID() );
210 if ( $subscrpt_product ) {
211 $subscrpt_enabled = (bool) $subscrpt_product->get_meta( '_subscrpt_enabled' );
212 $subscrpt_timing = $subscrpt_product->get_meta( '_subscrpt_timing_option' );
213 $subscrpt_trial_time = $subscrpt_product->get_meta( '_subscrpt_trial_timing_per' );
214 $subscrpt_trial_timing = $subscrpt_product->get_meta( '_subscrpt_trial_timing_option' );
215 $subscrpt_cart_txt = $subscrpt_product->get_meta( '_subscrpt_cart_btn_label' );
216 $subscrpt_user_cancell = $subscrpt_product->get_meta( '_subscrpt_user_cancel' );
217 $subscrpt_limit = $subscrpt_product->get_meta( '_subscrpt_limit' );
218 }
219 }
220
221 // Simple products: plan view (default) + hidden classic settings.
222 // Variable/other products keep the classic-only panel unchanged.
223 if ( $subscrpt_product && $subscrpt_product->is_type( 'simple' ) && class_exists( '\SpringDevs\Subscription\Admin\Product\Plans' ) ) {
224 ?>
225 <div id="sdevs_subscription_options" class="panel woocommerce_options_panel option_group sdevs-form sdevs_panel show_if_simple" style="padding:10px;" data-subscrpt-product-plans data-product-id="<?php echo esc_attr( $subscrpt_product->get_id() ); ?>"<?php echo Product\Plans::should_default_classic( $subscrpt_product ) ? ' data-subscrpt-default-classic="1"' : ''; ?>>
226 <?php Product\Plans::render_toolbar( $subscrpt_product ); ?>
227 <div data-subscrpt-plan-view>
228 <?php Product\Plans::render_plan_view( $subscrpt_product ); ?>
229 </div>
230 <div data-subscrpt-classic-view style="display:none;">
231 <?php require __DIR__ . '/views/product-classic-fields.php'; ?>
232 </div>
233 </div>
234 <?php
235 Product\Plans::render_checkout_link_modal( $subscrpt_product );
236 } else {
237 include 'views/product-form.php';
238 }
239 }
240 }
241 }
242
243 /**
244 * Save subscription settings.
245 *
246 * @param int $product_id Product Id.
247 *
248 * @return void
249 */
250 public function save_subscrpt_data( $product_id ) {
251 if ( function_exists( 'subscrpt_pro_activated' ) ) {
252 if ( subscrpt_pro_activated() ) {
253 return;
254 }
255 }
256
257 if ( ! isset( $_POST['_subscript_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_subscript_nonce'] ) ), '_subscript_edit_product_nonce' ) ) {
258 return;
259 }
260
261 remove_action( 'save_post_product', array( $this, 'save_subscrpt_data' ) );
262
263 $subscrpt_enable = isset( $_POST['subscrpt_enable'] );
264 $subscrpt_timing = isset( $_POST['subscrpt_timing'] ) ? sanitize_text_field( wp_unslash( $_POST['subscrpt_timing'] ) ) : '';
265 $subscrpt_trial_time = isset( $_POST['subscrpt_trial_time'] ) ? sanitize_text_field( wp_unslash( $_POST['subscrpt_trial_time'] ) ) : '';
266 $subscrpt_trial_timing = isset( $_POST['subscrpt_trial_timing'] ) ? sanitize_text_field( wp_unslash( $_POST['subscrpt_trial_timing'] ) ) : '';
267 $subscrpt_cart_txt = isset( $_POST['subscrpt_cart_txt'] ) ? sanitize_text_field( wp_unslash( $_POST['subscrpt_cart_txt'] ) ) : '';
268 $subscrpt_user_cancel = isset( $_POST['subscrpt_user_cancel'] ) ? sanitize_text_field( wp_unslash( $_POST['subscrpt_user_cancel'] ) ) : '';
269 $subscrpt_limit = isset( $_POST['subscrpt_limit'] ) ? sanitize_text_field( wp_unslash( $_POST['subscrpt_limit'] ) ) : null;
270
271 $product = wc_get_product( $product_id );
272 $product->update_meta_data( '_subscrpt_enabled', $subscrpt_enable );
273 $product->update_meta_data( '_subscrpt_timing_option', $subscrpt_timing );
274 $product->update_meta_data( '_subscrpt_trial_timing_per', $subscrpt_trial_time );
275 $product->update_meta_data( '_subscrpt_trial_timing_option', $subscrpt_trial_timing );
276 $product->update_meta_data( '_subscrpt_cart_btn_label', $subscrpt_cart_txt );
277 $product->update_meta_data( '_subscrpt_user_cancel', $subscrpt_user_cancel );
278 $product->update_meta_data( '_subscrpt_limit', $subscrpt_limit );
279 $product->save();
280
281 add_action( 'save_post_product', array( $this, 'save_subscrpt_data' ) );
282 }
283 }
284