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
← All changes | includes/Admin/Subscriptions.php +307 -233 1.3.12.0.0 View file →
@@ -4,8 +4,13 @@
4 4
5 5 use SpringDevs\Subscription\Illuminate\Action;
6 6 use SpringDevs\Subscription\Illuminate\Helper;
7 7
8 +// HPOS: This file is compatible with WooCommerce High-Performance Order Storage (HPOS).
9 +// All WooCommerce order data is accessed via WooCommerce CRUD methods (wc_get_order, etc.).
10 +// All direct post meta access is for subscription data only, not WooCommerce order data.
11 +// If you add new order data access, use WooCommerce CRUD for HPOS compatibility.
12 +
8 13 /**
9 14 * Subscriptions class
10 15 *
11 16 * @package SpringDevs\Subscription\Admin
@@ -11,8 +16,9 @@
11 16 * @package SpringDevs\Subscription\Admin
12 17 */
13 18 class Subscriptions {
14 19
20 +
15 21 /**
16 22 * Initialize the class.
17 23 */
18 24 public function __construct() {
@@ -19,19 +25,33 @@
19 25 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
20 26 add_filter( 'post_row_actions', array( $this, 'post_row_actions' ) );
21 27 add_filter( 'manage_subscrpt_order_posts_columns', array( $this, 'add_custom_columns' ) );
22 28 add_action( 'manage_subscrpt_order_posts_custom_column', array( $this, 'add_custom_columns_data' ), 10, 2 );
23 - add_action( 'add_meta_boxes', array( $this, 'create_meta_boxes' ) );
24 - add_action( 'admin_head-post.php', array( $this, 'some_styles' ) );
25 - add_action( 'admin_head-post-new.php', array( $this, 'some_styles' ) );
26 - add_action( 'admin_footer-post.php', array( $this, 'some_scripts' ) );
27 - add_action( 'admin_footer-post-new.php', array( $this, 'some_scripts' ) );
28 - add_action( 'save_post', array( $this, 'save_subscrpt_order' ) );
29 + add_action( 'load-post.php', array( $this, 'redirect_legacy_edit_screen' ) );
29 30 add_filter( 'woocommerce_order_item_get_formatted_meta_data', array( $this, 'remove_order_meta' ), 10, 1 );
30 31 add_filter( 'bulk_actions-edit-subscrpt_order', array( $this, 'remove_bulk_actions' ) );
32 + add_action( 'restrict_manage_posts', array( $this, 'add_subscription_filter_select' ) );
33 + add_action( 'admin_menu', array( $this, 'add_overview_submenu' ), 40 );
31 34 }
32 35
33 36 /**
37 + * Redirect the legacy CPT edit screen to the standalone details page.
38 + *
39 + * The subscription details UI now lives at
40 + * admin.php?page=wp-subscription-details. Anyone landing on the old
41 + * post.php edit screen for a subscrpt_order is sent there.
42 + *
43 + * @return void
44 + */
45 + public function redirect_legacy_edit_screen() {
46 + $post_id = isset( $_GET['post'] ) ? absint( wp_unslash( $_GET['post'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
47 + if ( $post_id && 'subscrpt_order' === get_post_type( $post_id ) ) {
48 + wp_safe_redirect( admin_url( 'admin.php?page=wp-subscription-details&id=' . $post_id ) );
49 + exit;
50 + }
51 + }
52 +
53 + /**
34 54 * Remove 'Edit` and 'Trash' from bulk actions.
35 55 *
36 56 * @param array $actions Action list.
37 57 *
@@ -39,8 +59,9 @@
39 59 */
40 60 public function remove_bulk_actions( $actions ) {
41 61 unset( $actions['edit'] );
42 62 unset( $actions['trash'] );
63 +
43 64 return $actions;
44 65 }
45 66
46 67 /**
@@ -56,8 +77,9 @@
56 77 if ( isset( $meta->key ) && '_renew_subscrpt' !== $meta->key ) {
57 78 $temp_metas[ $key ] = $meta;
58 79 }
59 80 }
81 +
60 82 return $temp_metas;
61 83 }
62 84
63 85 /**
@@ -85,8 +107,9 @@
85 107 unset( $actions['inline hide-if-no-js'] );
86 108 unset( $actions['view'] );
87 109 unset( $actions['trash'] );
88 110 unset( $actions['edit'] );
111 +
89 112 return $actions;
90 113 }
91 114
92 115 /**
@@ -96,14 +119,15 @@
96 119 *
97 120 * @return array
98 121 */
99 122 public function add_custom_columns( $columns ) {
100 - $columns['subscrpt_start_date'] = __( 'Start Date', 'sdevs_subscrpt' );
101 - $columns['subscrpt_customer'] = __( 'Customer', 'sdevs_subscrpt' );
102 - $columns['subscrpt_next_date'] = __( 'Next Date', 'sdevs_subscrpt' );
103 - $columns['subscrpt_status'] = __( 'Status', 'sdevs_subscrpt' );
123 + $columns['subscrpt_start_date'] = __( 'Start Date', 'subscription' );
124 + $columns['subscrpt_customer'] = __( 'Customer', 'subscription' );
125 + $columns['subscrpt_next_date'] = __( 'Next Date', 'subscription' );
126 + $columns['subscrpt_status'] = __( 'Status', 'subscription' );
104 127 unset( $columns['date'] );
105 128 unset( $columns['cb'] );
129 +
106 130 return $columns;
107 131 }
108 132
109 133 /**
@@ -114,14 +138,15 @@
114 138 *
115 139 * @return void
116 140 */
117 141 public function add_custom_columns_data( $column, $post_id ) {
118 - $order_id = get_post_meta( $post_id, '_subscrpt_order_id', true );
119 - $order = wc_get_order( $order_id );
142 + // HPOS: Safe. Only retrieves WooCommerce order via CRUD, and subscription meta via post meta.
143 + $order_id = get_post_meta( $post_id, '_subscrpt_order_id', true ); // HPOS: Only subscription meta, not order meta.
144 + $order = wc_get_order( $order_id ); // HPOS: Safe, uses WooCommerce CRUD.
120 145 if ( $order ) {
121 146 if ( 'subscrpt_start_date' === $column ) {
122 147 $start_date = get_post_meta( $post_id, '_subscrpt_start_date', true );
123 - echo ! empty( $start_date ) ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-';
148 + echo ! empty( $start_date ) ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-';
124 149 } elseif ( 'subscrpt_customer' === $column ) {
125 150 ?>
126 151 <?php echo wp_kses_post( $order->get_formatted_billing_full_name() ); ?>
127 152 <br />
@@ -127,241 +152,132 @@
127 152 <br />
128 153 <a href="mailto:<?php echo wp_kses_post( $order->get_billing_email() ); ?>"><?php echo wp_kses_post( $order->get_billing_email() ); ?></a>
129 154 <br />
130 155 <?php if ( ! empty( $order->get_billing_phone() ) ) : ?>
131 - Phone : <a href="tel:<?php echo esc_js( $order->get_billing_phone() ); ?>"><?php echo esc_js( $order->get_billing_phone() ); ?></a>
156 + Phone : <a
157 + href="tel:<?php echo esc_js( $order->get_billing_phone() ); ?>"><?php echo esc_js( $order->get_billing_phone() ); ?></a>
132 158 <?php endif; ?>
133 159 <?php
134 160 } elseif ( 'subscrpt_next_date' === $column ) {
135 161 $next_date = get_post_meta( $post_id, '_subscrpt_next_date', true );
136 - echo ! empty( $next_date ) ? esc_html( gmdate( 'F d, Y', $next_date ) ) : '-';
162 + echo ! empty( $next_date ) ? esc_html( wp_date( 'F d, Y', $next_date ) ) : '-';
137 163 } elseif ( 'subscrpt_status' === $column ) {
138 164 $status_obj = get_post_status_object( get_post_status( $post_id ) );
139 165 ?>
140 - <span class="subscrpt-<?php echo esc_html( $status_obj->name ); ?>"><?php echo esc_html( $status_obj->label ); ?></span>
166 + <span
167 + class="subscrpt-legacy-status subscrpt-legacy-status--<?php echo esc_html( $status_obj->name ); ?>"><?php echo esc_html( $status_obj->label ); ?></span>
141 168 <?php
142 169 }
143 170 } else {
144 - esc_html_e( 'Order not found !!', 'sdevs_subscrpt' );
171 + esc_html_e( 'Order not found !!', 'subscription' );
145 172 }
146 173 }
147 174
148 175 /**
149 - * Create metaboxes for admin subscriptions.
150 - */
151 - public function create_meta_boxes() {
152 - remove_meta_box( 'submitdiv', 'subscrpt_order', 'side' );
153 - add_meta_box(
154 - 'subscrpt_order_save_post',
155 - __( 'Subscription Action', 'sdevs_subscrpt' ),
156 - array( $this, 'subscrpt_order_save_post' ),
157 - 'subscrpt_order',
158 - 'side',
159 - 'default'
160 - );
161 -
162 - add_meta_box(
163 - 'subscrpt_customer_info',
164 - __( 'Customer Info', 'sdevs_subscrpt' ),
165 - array( $this, 'customer_info' ),
166 - 'subscrpt_order',
167 - 'side',
168 - 'default'
169 - );
170 -
171 - add_meta_box(
172 - 'subscrpt_order_info',
173 - __( 'Subscription Info', 'sdevs_subscrpt' ),
174 - array( $this, 'subscrpt_order_info' ),
175 - 'subscrpt_order',
176 - 'normal',
177 - 'default'
178 - );
179 -
180 - add_meta_box(
181 - 'subscrpt_order_history',
182 - __( 'Subscription History', 'sdevs_subscrpt' ),
183 - array( $this, 'order_histories' ),
184 - 'subscrpt_order',
185 - 'normal',
186 - 'default'
187 - );
188 -
189 - add_meta_box(
190 - 'subscrpt_order_activities',
191 - __( 'Subscription Activities', 'sdevs_subscrpt' ),
192 - array( $this, 'order_activities' ),
193 - 'subscrpt_order',
194 - 'normal',
195 - 'default'
196 - );
197 - }
198 -
199 - /**
200 - * Display Order Histories.
176 + * Build the subscription info rows.
201 177 *
202 - * @param \WP_Post $post Post Object.
178 + * Assembles the label/value rows describing a subscription (product, cost,
179 + * dates, status, payment method, addresses, trial, etc.) and applies the
180 + * `subscrpt_admin_info_rows` filter so extensions (e.g. the Pro plugin) can
181 + * add or reorder rows. Returns null when the related order is missing.
203 182 *
204 - * @return void
205 - */
206 - public function order_histories( $post ) {
207 - $subscription_id = $post->ID;
208 - global $wpdb;
209 - $table_name = $wpdb->prefix . 'subscrpt_order_relation';
210 - // @phpcs:ignore
211 - $order_histories = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i WHERE subscription_id=%d', array( $table_name, $subscription_id ) ) );
212 -
213 - include 'views/order-history.php';
214 - }
215 -
216 - /**
217 - * Display Order Activities
183 + * @param int $subscription_id Subscription (subscrpt_order) post ID.
218 184 *
219 - * @param \WP_Post $post Post Object.
220 - *
221 - * @return void
185 + * @return array<string,array{label:string,value:string}>|null
222 186 */
223 - public function order_activities( $post ) {
224 - if ( function_exists( 'subscrpt_pro_activated' ) ) :
225 - if ( subscrpt_pro_activated() ) :
226 - do_action( 'subscrpt_order_activities', $post->ID );
227 - else :
228 - ?>
229 - <a href="https://springdevs.com/subscription" target="_blank">
230 - <img style="width: 100%;" src="<?php echo esc_html( SUBSCRPT_ASSETS . '/images/subscrpt-ads.png' ); ?>" />
231 - </a>
232 - <?php
233 - endif;
234 - endif;
235 - }
236 -
237 - /**
238 - * Save subscription HTML.
239 - */
240 - public function subscrpt_order_save_post() {
241 - $actions = array(
242 - array(
243 - 'label' => __( 'Activate Subscription', 'sdevs_subscrpt' ),
244 - 'value' => 'active',
245 - ),
246 - array(
247 - 'label' => __( 'Pending Subscription', 'sdevs_subscrpt' ),
248 - 'value' => 'pending',
249 - ),
250 - array(
251 - 'label' => __( 'Expire Subscription', 'sdevs_subscrpt' ),
252 - 'value' => 'expired',
253 - ),
254 - array(
255 - 'label' => __( 'Pending Cancel Subscription', 'sdevs_subscrpt' ),
256 - 'value' => 'pe_cancelled',
257 - ),
258 - array(
259 - 'label' => __( 'Cancel Subscription', 'sdevs_subscrpt' ),
260 - 'value' => 'cancelled',
261 - ),
262 - );
263 - $status = get_post_status( get_the_ID() );
264 - include 'views/subscription-save-meta.php';
265 - }
266 -
267 - /**
268 - * Display Customer Info
269 - *
270 - * @param \WP_Post $post Post Object.
271 - *
272 - * @return void
273 - */
274 - public function customer_info( $post ) {
275 - $order_id = get_post_meta( $post->ID, '_subscrpt_order_id', true );
276 - $order = wc_get_order( $order_id );
277 - if ( ! $order ) {
278 - return;
279 - }
280 - include 'views/subscription-customer.php';
281 - }
282 -
283 - /**
284 - * Display subscription info.
285 - *
286 - * @return void
287 - */
288 - public function subscrpt_order_info() {
289 - $order_id = get_post_meta( get_the_ID(), '_subscrpt_order_id', true );
290 - $order_item_id = get_post_meta( get_the_ID(), '_subscrpt_order_item_id', true );
291 - $trial = get_post_meta( get_the_ID(), '_subscrpt_trial', true );
292 - $start_date = get_post_meta( get_the_ID(), '_subscrpt_start_date', true );
293 - $next_date = get_post_meta( get_the_ID(), '_subscrpt_next_date', true );
294 - $trial_start_date = get_post_meta( get_the_ID(), '_subscrpt_trial_started', true );
295 - $trial_end_date = get_post_meta( get_the_ID(), '_subscrpt_trial_ended', true );
296 - $trial_mode = get_post_meta( get_the_ID(), '_subscrpt_trial_mode', true );
187 + public static function get_info_rows( $subscription_id ) {
188 + $order_id = get_post_meta( $subscription_id, '_subscrpt_order_id', true );
189 + $order_item_id = get_post_meta( $subscription_id, '_subscrpt_order_item_id', true );
190 + $trial = get_post_meta( $subscription_id, '_subscrpt_trial', true );
191 + $start_date = get_post_meta( $subscription_id, '_subscrpt_start_date', true );
192 + $next_date = get_post_meta( $subscription_id, '_subscrpt_next_date', true );
193 + $trial_start_date = get_post_meta( $subscription_id, '_subscrpt_trial_started', true );
194 + $trial_end_date = get_post_meta( $subscription_id, '_subscrpt_trial_ended', true );
195 + $trial_mode = get_post_meta( $subscription_id, '_subscrpt_trial_mode', true );
297 196 $order = wc_get_order( $order_id );
298 197 if ( ! $order ) {
299 - return;
198 + return null;
300 199 }
301 200 $order_item = $order->get_item( $order_item_id );
302 201
303 202 $product_name = $order_item->get_name();
304 203 $product_link = get_the_permalink( $order_item->get_product_id() );
305 - $rows = array(
306 - 'product' => array(
307 - 'label' => __( 'Product', 'sdevs_subscrpt' ),
204 +
205 + // Get payment information
206 + $product_id = $order_item->get_product_id();
207 + $max_payments = subscrpt_get_max_payments( $subscription_id ) ? subscrpt_get_max_payments( $subscription_id ) : 0;
208 + $payments_made = subscrpt_count_payments_made( $subscription_id );
209 +
210 + $rows = array(
211 + 'product' => array(
212 + 'label' => __( 'Product', 'subscription' ),
308 213 'value' => '<a href="' . esc_html( $product_link ) . '" target="_blank">' . esc_html( $product_name ) . '</a>',
309 214 ),
310 - 'cost' => array(
311 - 'label' => __( 'Cost', 'sdevs_subscrpt' ),
312 - 'value' => Helper::format_price_with_order_item( get_post_meta( get_the_ID(), '_subscrpt_price', true ), $order_item->get_id() ),
215 + 'cost' => array(
216 + 'label' => __( 'Cost', 'subscription' ),
217 + 'value' => Helper::get_subscription_recurring_price_html( $subscription_id, $order_item ),
313 218 ),
314 - 'quantity' => array(
315 - 'label' => __( 'Qty', 'sdevs_subscrpt' ),
219 + 'quantity' => array(
220 + 'label' => __( 'Qty', 'subscription' ),
316 221 'value' => "x{$order_item->get_quantity()}",
317 222 ),
223 + );
224 +
225 + // Add payment information if max_payments is set and not unlimited
226 + if ( ! empty( $max_payments ) && $max_payments > 0 ) {
227 + $rows['total_payments'] = array(
228 + 'label' => __( 'Total Payments', 'subscription' ),
229 + 'value' => esc_html( $payments_made ) . ' / ' . esc_html( $max_payments ),
230 + );
231 + }
232 +
233 + $rows += array(
318 234 'start_date' => array(
319 - 'label' => __( 'Started date', 'sdevs_subscrpt' ),
320 - 'value' => ! empty( $start_date ) ? gmdate( 'F d, Y', $trial && $trial_start_date ? $trial_start_date : $start_date ) : '-',
235 + 'label' => __( 'Started date', 'subscription' ),
236 + 'value' => ! empty( $start_date ) ? wp_date( 'F d, Y', $trial && $trial_start_date ? $trial_start_date : $start_date ) : '-',
321 237 ),
322 238 'next_date' => array(
323 - 'label' => __( 'Payment due date', 'sdevs_subscrpt' ),
324 - 'value' => ! empty( $next_date ) ? gmdate( 'F d, Y', $trial && $trial_end_date && 'on' === $trial_mode ? $trial_end_date : ( $next_date ?? '-' ) ) : '-',
239 + 'label' => __( 'Payment due date', 'subscription' ),
240 + 'value' => ! empty( $next_date ) ? wp_date( 'F d, Y', $trial && $trial_end_date && 'on' === $trial_mode ? $trial_end_date : ( $next_date ?? '-' ) ) : '-',
325 241 ),
326 242 'status' => array(
327 - 'label' => __( 'Status', 'sdevs_subscrpt' ),
328 - 'value' => '<span class="subscrpt-' . get_post_status() . '">' . get_post_status_object( get_post_status() )->label . '</span>',
243 + 'label' => __( 'Status', 'subscription' ),
244 + 'value' => '<span class="subscrpt-legacy-status subscrpt-legacy-status--' . get_post_status( $subscription_id ) . '">' . get_post_status_object( get_post_status( $subscription_id ) )->label . '</span>',
329 245 ),
330 246 'payment_method' => array(
331 - 'label' => __( 'Payment Method', 'sdevs_subscrpt' ),
247 + 'label' => __( 'Payment Method', 'subscription' ),
332 248 'value' => empty( $order->get_payment_method_title() ) ? '-' : $order->get_payment_method_title(),
333 249 ),
334 250 'billing_address' => array(
335 - 'label' => __( 'Billing', 'sdevs_subscrpt' ),
336 - 'value' => $order->get_formatted_billing_address() ? $order->get_formatted_billing_address() : __( 'No billing address set.', 'sdevs_subscrpt' ),
251 + 'label' => __( 'Billing', 'subscription' ),
252 + 'value' => $order->get_formatted_billing_address() ? $order->get_formatted_billing_address() : __( 'No billing address set.', 'subscription' ),
337 253 ),
338 254 'shipping_address' => array(
339 - 'label' => __( 'Shipping', 'sdevs_subscrpt' ),
340 - 'value' => $order->get_formatted_shipping_address() ? $order->get_formatted_shipping_address() : __( 'No shipping address set.', 'sdevs_subscrpt' ),
255 + 'label' => __( 'Shipping', 'subscription' ),
256 + 'value' => $order->get_formatted_shipping_address() ? $order->get_formatted_shipping_address() : __( 'No shipping address set.', 'subscription' ),
341 257 ),
342 258 );
343 259 if ( $trial ) {
344 260 $rows = array_slice( $rows, 0, 3, true ) + array(
345 261 'trial' => array(
346 - 'label' => __( 'Trial', 'sdevs_subscrpt' ),
262 + 'label' => __( 'Trial', 'subscription' ),
347 263 'value' => $trial,
348 264 ),
349 265 'trial_period' => array(
350 - 'label' => __( 'Trial Period', 'sdevs_subscrpt' ),
351 - 'value' => ( $trial_start_date && $trial_end_date ? ' [ ' . gmdate( 'F d, Y', $trial_start_date ) . ' - ' . gmdate( 'F d, Y', $trial_end_date ) . ' ] ' : __( 'Trial isn\'t activated yet! ', 'sdevs_subscrpt' ) ),
266 + 'label' => __( 'Trial Period', 'subscription' ),
267 + 'value' => ( $trial_start_date && $trial_end_date ? ' [ ' . wp_date( 'F d, Y', $trial_start_date ) . ' - ' . wp_date( 'F d, Y', $trial_end_date ) . ' ] ' : __( 'Trial isn\'t activated yet! ', 'subscription' ) ),
352 268 ),
353 269 ) + array_slice( $rows, 3, count( $rows ) - 1, true );
354 270 }
355 271
356 272 if ( class_exists( 'WC_Stripe' ) && 'stripe' === $order->get_payment_method() ) {
357 - $is_auto_renew = get_post_meta( get_the_ID(), '_subscrpt_auto_renew', true );
273 + $is_auto_renew = get_post_meta( $subscription_id, '_subscrpt_auto_renew', true );
358 274 $new_rows = array();
359 275 foreach ( $rows as $key => $value ) {
360 276 $new_rows[ $key ] = $value;
361 277 if ( 'payment_method' === $key ) {
362 278 $new_rows['stripe_auto_renewal'] = array(
363 - 'label' => __( 'Stripe Auto Renewal', 'sdevs_subscrpt' ),
279 + 'label' => __( 'Stripe Auto Renewal', 'subscription' ),
364 280 'value' => '0' !== $is_auto_renew ? 'On' : 'Off',
365 281 );
366 282 }
367 283 }
@@ -368,62 +284,29 @@
368 284
369 285 $rows = $new_rows;
370 286 }
371 287
372 - $rows = apply_filters( 'subscrpt_admin_info_rows', $rows, get_the_ID(), $order );
288 + $rows = apply_filters( 'subscrpt_admin_info_rows', $rows, $subscription_id, $order );
373 289
374 - include 'views/subscription-info.php';
290 + return $rows;
375 291 }
376 292
377 293 /**
378 - * Include some styles.
294 + * Apply a status change to a subscription.
379 295 *
380 - * @return void
381 - */
382 - public function some_styles() {
383 - global $post;
384 - if ( 'subscrpt_order' === $post->post_type ) :
385 - ?>
386 - <style>
387 - .submitbox {
388 - display: flex;
389 - justify-content: space-around;
390 - }
391 -
392 - .subscrpt_sub_box {
393 - display: grid;
394 - line-height: 2;
395 - }
396 - </style>
397 - <?php
398 - endif;
399 - }
400 -
401 - /**
402 - * Disable changes popup.
296 + * Updates the subscription post status, fires the admin status-change email
297 + * notification, runs the subscription status action, and completes the
298 + * related order when the subscription becomes active. Called from the
299 + * standalone subscription details page.
403 300 *
301 + * @param int $post_id Subscription (subscrpt_order) post ID.
302 + * @param string $action Target status slug.
303 + *
404 304 * @return void
405 305 */
406 - public function some_scripts() {
407 - global $post;
408 - if ( 'subscrpt_order' === $post->post_type ) :
409 - ?>
410 - <script>
411 - jQuery(document).ready(function() {
412 - jQuery(window).off("beforeunload", null);
413 - });
414 - </script>
415 - <?php
416 - endif;
417 - }
306 + public static function process_status_change( $post_id, $action ) {
307 + $old_status = get_post_status( $post_id );
418 308
419 - public function save_subscrpt_order( $post_id ) {
420 - if ( wp_is_post_revision( $post_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! isset( $_POST['subscrpt_order_action'] ) ) {
421 - return;
422 - }
423 - remove_all_actions( 'save_post' );
424 -
425 - $action = sanitize_text_field( $_POST['subscrpt_order_action'] );
426 309 wp_update_post(
427 310 array(
428 311 'ID' => $post_id,
429 312 'post_status' => $action,
@@ -429,14 +312,205 @@
429 312 'post_status' => $action,
430 313 )
431 314 );
432 315
316 + if ( $old_status !== $action ) {
317 + $old_status_object = get_post_status_object( $old_status );
318 + $new_status_object = get_post_status_object( $action );
319 + WC()->mailer();
320 + do_action( 'subscrpt_status_changed_admin_email_notification', $post_id, $old_status_object->label, $new_status_object->label );
321 + }
322 +
433 323 $order_id = get_post_meta( $post_id, '_subscrpt_order_id', true );
434 324 if ( 'active' === $action ) {
435 325 $order = wc_get_order( $order_id );
436 - $order->update_status( 'completed' );
437 - Action::status( $action, $post_id, false );
326 + if ( $order ) {
327 + $order->update_status( 'completed' );
328 + }
329 + Action::status( $action, $post_id );
438 330 } else {
439 331 Action::status( $action, $post_id );
440 332 }
333 + }
334 +
335 + public function add_subscription_filter_select() {
336 + // Implementation of add_subscription_filter_select method
337 + }
338 +
339 + public function add_overview_submenu() {
340 + // Remove and re-add submenu to ensure Overview is first
341 + remove_submenu_page( 'edit.php?post_type=subscrpt_order', 'edit.php?post_type=subscrpt_order' );
342 + add_submenu_page(
343 + 'edit.php?post_type=subscrpt_order',
344 + __( 'Overview', 'subscription' ),
345 + __( 'Overview', 'subscription' ),
346 + 'manage_options',
347 + 'subscription_overview',
348 + array( $this, 'render_overview_page' ),
349 + 0
350 + );
351 + add_submenu_page(
352 + 'edit.php?post_type=subscrpt_order',
353 + __( 'All Subscriptions', 'subscription' ),
354 + __( 'All Subscriptions', 'subscription' ),
355 + 'manage_options',
356 + 'edit.php?post_type=subscrpt_order',
357 + '',
358 + 1
359 + );
360 + if ( ! class_exists( 'Sdevs_Wc_Subscription_Pro' ) ) {
361 + add_submenu_page(
362 + 'edit.php?post_type=subscrpt_order',
363 + __( 'Go Pro', 'subscription' ),
364 + __( 'Go Pro', 'subscription' ),
365 + 'manage_options',
366 + 'wp_subscription_go_pro',
367 + array( $this, 'render_go_pro_page' ),
368 + 99
369 + );
370 + }
371 + }
372 +
373 + public function render_overview_page() {
374 + ?>
375 + <div class="wrap wpsubscription-overview" style="max-width:1100px;margin:40px auto 0 auto;">
376 + <div class="wpsubscription-overview-card" style="background:#fff;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,0.06);padding:40px 32px 32px 32px;">
377 + <div class="wpsubscription-overview-top" style="display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:start;margin-bottom:40px;">
378 + <div class="wpsubscription-overview-info" style="display:flex;flex-direction:column;gap:18px;">
379 + <h1 style="margin-bottom:0.2em;"><?php esc_html_e( 'WPSubscription Overview', 'subscription' ); ?></h1>
380 + <p class="product-desc" style="font-size:1.15em;line-height:1.6;max-width:500px;">
381 + <?php esc_html_e( 'WPSubscription is the most seamless and reliable WooCommerce subscription solution for store owners looking to grow recurring revenue. Easily manage recurring payments, automate renewals, and delight your customers with flexible plans.', 'subscription' ); ?>
382 + </p>
383 + <div class="wpsubscription-links" style="display:flex;gap:12px;flex-wrap:wrap;">
384 + <a href="https://docs.wpsubscription.co/en?utm_source=plugin&utm_medium=admin&utm_campaign=docs" target="_blank" class="button button-secondary"><?php esc_html_e( 'Documentation', 'subscription' ); ?></a>
385 + <a href="https://wpsubscription.co/?utm_source=plugin&utm_medium=admin&utm_campaign=upgrade_pro" target="_blank" class="button button-secondary"><?php esc_html_e( 'Website', 'subscription' ); ?></a>
386 + </div>
387 + </div>
388 + <div class="promo-video" style="text-align:center;">
389 + <iframe width="420" height="236" src="https://www.youtube.com/embed/2e6o5p0M7L4" title="WPSubscription Promo" frameborder="0" allowfullscreen style="max-width:100%;border-radius:8px;"></iframe>
390 + </div>
391 + </div>
392 +
393 + <div class="wpsubscription-what-section" style="margin-bottom:40px;">
394 + <h2><?php esc_html_e( 'What does Subscriptions for WooCommerce do?', 'subscription' ); ?></h2>
395 + <p style="font-size:1.08em;max-width:900px;line-height:1.7;">
396 + <?php esc_html_e( 'Subscriptions for WooCommerce enables you to create and manage recurring payment products and services with ease. Automate renewals, offer flexible billing schedules, and provide your customers with a seamless subscription experience. Whether you sell digital content, physical goods, or memberships, WPSubscription gives you the tools to grow your recurring revenue.', 'subscription' ); ?>
397 + </p>
398 + </div>
399 +
400 + <h2 style="margin-top:2em;"><?php esc_html_e( 'Highlights', 'subscription' ); ?></h2>
401 + <div class="wpsubscription-features-grid">
402 + <div class="feature-box"><span class="dashicons dashicons-admin-generic"></span><h3>Easy Setup</h3><p>Get started in minutes with our intuitive onboarding wizard.</p></div>
403 + <div class="feature-box"><span class="dashicons dashicons-money"></span><h3>Multiple Gateways</h3><p>Support for Stripe, PayPal, and Paddle out of the box.</p></div>
404 + <div class="feature-box"><span class="dashicons dashicons-schedule"></span><h3>Flexible Plans</h3><p>Create and manage various subscription types and delivery schedules.</p></div>
405 + <div class="feature-box"><span class="dashicons dashicons-chart-line"></span><h3>Comprehensive Dashboard</h3><p>Monitor and manage all subscriptions in one place.</p></div>
406 + </div>
407 + </div>
408 + </div>
409 + <style>
410 + .wpsubscription-overview .promo-video { text-align:center; }
411 + .wpsubscription-features-grid {
412 + display: grid;
413 + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
414 + gap: 24px;
415 + margin-top: 32px;
416 + }
417 + .feature-box {
418 + background: #fff;
419 + border-radius: 10px;
420 + box-shadow: 0 2px 8px rgba(0,0,0,0.06);
421 + padding: 24px 18px 18px 18px;
422 + text-align: center;
423 + transition: transform 0.2s, box-shadow 0.2s;
424 + will-change: transform;
425 + }
426 + .feature-box:hover {
427 + transform: translateY(-6px) scale(1.03);
428 + box-shadow: 0 6px 24px rgba(0,0,0,0.10);
429 + }
430 + .feature-box .dashicons {
431 + font-size: 2.2em;
432 + color: #7f54b3;
433 + margin-bottom: 10px;
434 + display: block;
435 + }
436 + .feature-box h3 {
437 + margin: 12px 0 8px 0;
438 + font-size: 1.15em;
439 + }
440 + .feature-box p {
441 + color: #555;
442 + font-size: 1em;
443 + margin: 0;
444 + }
445 + </style>
446 + <?php
447 + }
448 +
449 + public function render_go_pro_page() {
450 + if ( class_exists( 'Sdevs_Wc_Subscription_Pro' ) ) {
451 + echo '<div class="notice notice-info" style="margin:40px auto;max-width:700px;text-align:center;font-size:1.2em;">Pro is already active.</div>';
452 + return;
453 + }
454 + ?>
455 + <div class="wrap wpsubscription-go-pro" style="max-width:900px;margin:40px auto 0 auto;">
456 + <div class="wpsubscription-go-pro-card" style="background:#fff;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,0.06);padding:40px 32px 32px 32px;">
457 + <h1 style="margin-bottom:0.5em;"><?php esc_html_e( 'Upgrade to WPSubscription Pro', 'subscription' ); ?></h1>
458 + <p style="font-size:1.12em;max-width:600px;line-height:1.6;">
459 + <?php esc_html_e( 'Unlock the full power of subscriptions for WooCommerce. Get advanced features, priority support, and more ways to grow your recurring revenue.', 'subscription' ); ?>
460 + </p>
461 + <table class="wpsubscription-compare-table" style="width:100%;margin:32px 0 40px 0;border-collapse:separate;border-spacing:0;box-shadow:0 1px 4px rgba(0,0,0,0.04);background:#fafbfc;border-radius:8px;overflow:hidden;">
462 + <thead>
463 + <tr style="background:#f8f9fa;">
464 + <th style="padding:18px 12px 18px 24px;font-size:1.08em;text-align:left;border:none;"></th>
465 + <th style="padding:18px 12px;font-size:1.08em;text-align:center;border:none;">Free</th>
466 + <th style="padding:18px 12px;font-size:1.08em;text-align:center;border:none;color:#7f54b3;">Pro</th>
467 + </tr>
468 + </thead>
469 + <tbody>
470 + <tr>
471 + <td style="padding:16px 12px 16px 24px;">Simple subscription products</td>
472 + <td style="text-align:center;">✔️</td>
473 + <td style="text-align:center;">✔️</td>
474 + </tr>
475 + <tr style="background:#f6f7f7;">
476 + <td style="padding:16px 12px 16px 24px;">Automated recurring billing</td>
477 + <td style="text-align:center;">✔️</td>
478 + <td style="text-align:center;">✔️</td>
479 + </tr>
480 + <tr>
481 + <td style="padding:16px 12px 16px 24px;">Multiple payment gateways</td>
482 + <td style="text-align:center;">✔️</td>
483 + <td style="text-align:center;">✔️</td>
484 + </tr>
485 + <tr style="background:#f6f7f7;">
486 + <td style="padding:16px 12px 16px 24px;">Customer self-service portal</td>
487 + <td style="text-align:center;">✔️</td>
488 + <td style="text-align:center;">✔️</td>
489 + </tr>
490 + <tr>
491 + <td style="padding:16px 12px 16px 24px;">Priority support</td>
492 + <td style="text-align:center;">—</td>
493 + <td style="text-align:center;">✔️</td>
494 + </tr>
495 + <tr style="background:#f6f7f7;">
496 + <td style="padding:16px 12px 16px 24px;">Advanced reporting & analytics</td>
497 + <td style="text-align:center;">—</td>
498 + <td style="text-align:center;">✔️</td>
499 + </tr>
500 + <tr>
501 + <td style="padding:16px 12px 16px 24px;">Variable product support</td>
502 + <td style="text-align:center;">—</td>
503 + <td style="text-align:center;font-weight:600;color:#43a047;">✔️</td>
504 + </tr>
505 + </tbody>
506 + </table>
507 + <div style="text-align:center;margin-top:24px;">
508 + <a href="https://wpsubscription.co/?utm_source=plugin&utm_medium=admin&utm_campaign=upgrade_pro" target="_blank" class="button button-primary button-hero" style="font-size:1.2em;padding:16px 40px 16px 40px;background:#7f54b3;border:none;box-shadow:0 2px 8px rgba(127,84,179,0.10);">
509 + <?php esc_html_e( 'Upgrade to Pro', 'subscription' ); ?>
510 + </a>
511 + </div>
512 + </div>
513 + </div>
514 + <?php
441 515 }
442 516 }