PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 1.10.1
Subscriptions for WooCommerce with Stripe Recurring Payments v1.10.1
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 / Menu.php

Menu.php in Subscriptions for WooCommerce with Stripe Recurring Payments 1.10.1, at includes/Admin/Menu.php

676 lines 22.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SpringDevs\Subscription\Admin;
4
5 /**
6 * Menu class
7 *
8 * @package SpringDevs\Subscription\Admin
9 */
10 class Menu {
11
12 /**
13 * Initialize the class
14 */
15 public function __construct() {
16 add_action( 'admin_menu', array( $this, 'create_admin_menu' ) );
17 add_action( 'admin_menu', array( $this, 'reorder_submenu' ), 999 );
18 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
19 add_action( 'wp_ajax_subscrpt_bulk_action', array( $this, 'handle_bulk_action_ajax' ) );
20 }
21
22 /**
23 * Enqueue admin assets
24 */
25 public function enqueue_admin_assets() {
26 wp_enqueue_style(
27 'wp-subscription-admin',
28 SUBSCRPT_ASSETS . '/css/admin.css',
29 array(),
30 SUBSCRPT_VERSION
31 );
32
33 // Enqueue admin JavaScript for subscription list functionality
34 wp_enqueue_script(
35 'sdevs_subscription_admin',
36 SUBSCRPT_ASSETS . '/js/admin.js',
37 array( 'jquery' ),
38 SUBSCRPT_VERSION,
39 true
40 );
41
42 // Localize script for AJAX
43 wp_localize_script(
44 'sdevs_subscription_admin',
45 'wp_subscription_ajax',
46 array(
47 'nonce' => wp_create_nonce( 'subscrpt_bulk_action_nonce' ),
48 'ajaxurl' => admin_url( 'admin-ajax.php' ),
49 )
50 );
51 }
52
53 /**
54 * Create Subscriptions Menu.
55 */
56 public function create_admin_menu() {
57 $parent_slug = 'wp-subscription';
58 // Determine if the menu is active
59 $is_active = isset( $_GET['page'] ) && strpos( sanitize_text_field( wp_unslash( $_GET['page'] ) ), 'wp-subscription' ) === 0;
60 $icon_url = $is_active
61 ? SUBSCRPT_ASSETS . '/images/icons/subscription-20.png'
62 : SUBSCRPT_ASSETS . '/images/icons/subscription-20-gray.png';
63
64 $pro_text = __( 'WPSubscription Pro required', 'subscription' );
65 $pro_badge = subscrpt_pro_activated() ? '' : ' <span title="' . $pro_text . '"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="#ff6a34" style="vertical-align:middle;margin-bottom:2.2px;flex-shrink:0;" aria-hidden="true"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M19 19h-14c-.5 0 -.9 -.3 -1 -.8l-2 -10c0 -.4 .1 -.8 .5 -1.1c.4 -.2 .8 -.2 1.1 0l4.1 3.3l3.4 -5.1c.4 -.6 1.3 -.6 1.7 0l3.4 5.1l4.1 -3.3c.3 -.3 .8 -.3 1.1 0c.4 .2 .5 .6 .5 1.1l-2 10c0 .5 -.5 .8 -1 .8z"/></svg></span>';
66
67 // Main menu
68 add_menu_page(
69 __( 'WPSubscription', 'subscription' ),
70 __( 'WPSubscription', 'subscription' ),
71 'manage_options',
72 $parent_slug,
73 array( $this, 'render_subscriptions_page' ),
74 $icon_url,
75 40
76 );
77
78 // Subscriptions List
79 add_submenu_page(
80 $parent_slug,
81 __( 'Subscriptions', 'subscription' ),
82 __( 'Subscriptions', 'subscription' ),
83 'manage_options',
84 $parent_slug,
85 array( $this, 'render_subscriptions_page' )
86 );
87
88 // Stats Overview
89 add_submenu_page(
90 $parent_slug,
91 __( 'Reports', 'subscription' ),
92 __( 'Reports', 'subscription' ) . $pro_badge,
93 'manage_options',
94 'wp-subscription-stats',
95 array( $this, 'render_stats_page' )
96 );
97
98 // Subscription Health
99 add_submenu_page(
100 $parent_slug,
101 __( 'Health', 'subscription' ),
102 __( 'Health', 'subscription' ) . $pro_badge,
103 'manage_options',
104 'wp-subscription-health',
105 array( $this, 'render_health_page' )
106 );
107
108 // Delivery Schedules
109 add_submenu_page(
110 $parent_slug,
111 __( 'Delivery Schedules', 'subscription' ),
112 __( 'Delivery Schedules', 'subscription' ) . $pro_badge,
113 'manage_options',
114 'wp-subscription-delivery',
115 array( $this, 'render_delivery_page' )
116 );
117
118 // Help & Resources
119 add_submenu_page(
120 $parent_slug,
121 __( 'Help & Resources', 'subscription' ),
122 __( 'Help & Resources', 'subscription' ),
123 'manage_options',
124 'wp-subscription-support',
125 array( $this, 'render_support_page' )
126 );
127
128 // Add WPSubscription link under WooCommerce menu
129 add_submenu_page(
130 'woocommerce',
131 __( 'WPSubscription', 'subscription' ),
132 __( 'WPSubscription', 'subscription' ),
133 'manage_options',
134 'wp-subscription',
135 array( $this, 'render_subscriptions_page' )
136 );
137 }
138
139 /**
140 * Reorder the WPSubscription submenu after all items are registered.
141 *
142 * Runs at admin_menu priority 999 so every plugin has already inserted
143 * its items. A filter lets the Pro plugin (or any extension) adjust the
144 * slug order before sorting is applied.
145 *
146 * @do_action subscrpt_submenu_order {string[]} $order Ordered list of submenu page slugs.
147 */
148 public function reorder_submenu() {
149 $parent = 'wp-subscription';
150
151 global $submenu;
152
153 if ( empty( $submenu[ $parent ] ) ) {
154 return;
155 }
156
157 // slug => position. Use gaps of 10 so extensions can insert between items.
158 // When pro is not active, pro-only pages (Reports, Delivery, Health) move
159 // to the bottom so free pages stay prominent.
160 if ( subscrpt_pro_activated() ) {
161 $default_order = [
162 'wp-subscription' => 10, // Subscriptions
163 'wp-subscription-stats' => 20, // Reports
164 'wp-subscription-delivery' => 30, // Delivery (pro)
165 'wp-subscription-settings' => 40, // Settings
166 'wp-subscription-health' => 50, // Health
167 'wp-subscription-integrations' => 60, // Integrations
168 'wp-subscription-support' => 70, // Help & Resources
169 'wp-subscription-license' => 80, // License (pro)
170 ];
171 } else {
172 $default_order = [
173 'wp-subscription' => 10, // Subscriptions
174 'wp-subscription-settings' => 20, // Settings
175 'wp-subscription-integrations' => 30, // Integrations
176 'wp-subscription-support' => 40, // Help & Resources
177 'wp-subscription-stats' => 50, // Reports (pro preview)
178 'wp-subscription-delivery' => 60, // Delivery (pro preview)
179 'wp-subscription-health' => 70, // Health (pro preview)
180 'wp-subscription-license' => 80, // License (pro)
181 ];
182 }
183
184 /**
185 * Filter the WPSubscription submenu slug order.
186 *
187 * Each entry is a slug => integer position pair. Lower positions appear
188 * first. Use gaps of 10 between built-in positions so extensions can
189 * insert their own slugs between existing items without renumbering.
190 *
191 * Example (pro plugin adding Delivery at position 35):
192 * add_filter( 'subscrpt_submenu_order', function( $order ) {
193 * $order['wp-subscription-delivery'] = 35;
194 * return $order;
195 * } );
196 *
197 * @param array<string,int> $order Map of slug => position.
198 */
199 $order = apply_filters( 'subscrpt_submenu_order', $default_order );
200
201 // Sort by position value, preserving slug keys.
202 asort( $order );
203
204 // Index current items by slug for fast lookup.
205 $indexed = [];
206 foreach ( $submenu[ $parent ] as $item ) {
207 $indexed[ $item[2] ] = $item;
208 }
209
210 // Build sorted list from the ordered slugs.
211 $sorted = [];
212 foreach ( array_keys( $order ) as $slug ) {
213 if ( isset( $indexed[ $slug ] ) ) {
214 $sorted[] = $indexed[ $slug ];
215 unset( $indexed[ $slug ] );
216 }
217 }
218
219 // Append any remaining items not covered by the order list.
220 foreach ( $indexed as $item ) {
221 $sorted[] = $item;
222 }
223
224 $submenu[ $parent ] = $sorted; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Intentional reorder of submenu items.
225 }
226
227 /**
228 * Render the admin header
229 */
230 public function render_admin_footer() {
231 ?>
232 <div style="text-align:center;margin:38px 0 0 0;font-size:14px;color:#888;">
233 Made with <span style="color:#e25555;font-size:1.1em;">♥</span> by the WPSubscription Team
234 <div style="margin-top:6px;">
235 <a href="https://wpsubscription.co/contact" target="_blank" style="color:#2563eb;text-decoration:none;">Support</a>
236 &nbsp;/&nbsp;
237 <a href="https://docs.converslabs.com/en" target="_blank" style="color:#2563eb;text-decoration:none;">Docs</a>
238 </div>
239 </div>
240 <?php
241 }
242 /**
243 * Render the admin header.
244 *
245 * @param string $title Page title shown on the left.
246 * @param string $subtitle Optional subtitle shown below the title.
247 */
248 public function render_admin_header( string $title = '', string $subtitle = '' ) {
249 $current = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : 'wp-subscription';
250
251 // Kept for backward compatibility — extensions may hook here for side-effects.
252 $menu_items = apply_filters( 'subscrpt_admin_header_menu_items', [], $current );
253 unset( $menu_items ); // Nav no longer rendered in header; navigation is in WP sidebar.
254 ?>
255 <div class="wp-subscription-admin-header">
256 <div class="wp-subscription-admin-header-inner">
257 <div class="wp-subscription-admin-header-left">
258 <nav class="wp-subscription-breadcrumb" aria-label="<?php esc_attr_e( 'Breadcrumb', 'subscription' ); ?>">
259 <a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-subscription' ) ); ?>" class="wp-subscription-breadcrumb-home" aria-label="<?php esc_attr_e( 'WPSubscription Home', 'subscription' ); ?>">
260 <span class="dashicons dashicons-admin-home"></span>
261 </a>
262 <?php if ( $title ) : ?>
263 <span class="wp-subscription-breadcrumb-sep" aria-hidden="true">/</span>
264 <span class="wp-subscription-breadcrumb-current"><?php echo esc_html( $title ); ?></span>
265 <?php endif; ?>
266 </nav>
267 </div>
268 <div class="wp-subscription-admin-header-right">
269 <?php if ( ! class_exists( 'Sdevs_Wc_Subscription_Pro' ) ) : ?>
270 <a target="_blank" href="https://wpsubscription.co/?utm_source=plugin&utm_medium=admin&utm_campaign=upgrade_pro" class="wp-subscription-upgrade-btn"><?php esc_html_e( 'Upgrade to Pro', 'subscription' ); ?></a>
271 <?php endif; ?>
272 <img src="<?php echo esc_url( SUBSCRPT_ASSETS . '/images/logo-title.svg' ); ?>" alt="WPSubscription" class="wp-subscription-logo">
273 </div>
274 </div>
275 </div>
276 <?php
277 }
278
279 /**
280 * Render Subscriptions page
281 */
282 public function render_subscriptions_page() {
283 $this->render_admin_header( __( 'Subscriptions', 'subscription' ), __( 'Manage your subscriptions', 'subscription' ) );
284
285 // Handle filters
286 $status = isset( $_GET['subscrpt_status'] ) ? sanitize_text_field( wp_unslash( $_GET['subscrpt_status'] ) ) : '';
287 $search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
288 $date_filter = isset( $_GET['date_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['date_filter'] ) ) : '';
289 $per_page = isset( $_GET['per_page'] ) ? max( 1, intval( $_GET['per_page'] ) ) : 20;
290 $paged = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1;
291
292 // Handle form submissions (both filters and bulk actions)
293 $request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
294 if ( 'POST' === $request_method ) {
295 // Verify nonce before processing any POST data.
296 $nonce = isset( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) : '';
297 if ( ! wp_verify_nonce( $nonce, 'subscrpt_list_action' ) ) {
298 wp_die( esc_html__( 'Security check failed.', 'subscription' ) );
299 }
300 // Handle bulk actions
301 if ( isset( $_POST['bulk_action'] ) || isset( $_POST['bulk_action2'] ) ) {
302 $bulk_action = isset( $_POST['bulk_action'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk_action'] ) ) : sanitize_text_field( wp_unslash( $_POST['bulk_action2'] ?? '' ) );
303 $action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : sanitize_text_field( wp_unslash( $_POST['action2'] ?? '' ) );
304
305 if ( $bulk_action && $action && $action !== '-1' && isset( $_POST['subscription_ids'] ) && is_array( $_POST['subscription_ids'] ) ) {
306 $subscription_ids = array_map( 'intval', $_POST['subscription_ids'] );
307
308 if ( $action === 'trash' ) {
309 foreach ( $subscription_ids as $sub_id ) {
310 wp_trash_post( $sub_id );
311 }
312 } elseif ( $action === 'restore' ) {
313 foreach ( $subscription_ids as $sub_id ) {
314 wp_untrash_post( $sub_id );
315 }
316 } elseif ( $action === 'delete' ) {
317 foreach ( $subscription_ids as $sub_id ) {
318 wp_delete_post( $sub_id, true );
319 }
320 }
321
322 wp_safe_redirect( admin_url( 'admin.php?page=wp-subscription' ) );
323 exit;
324 }
325 }
326
327 // Handle filter form submission
328 if ( isset( $_POST['filter_action'] ) ) {
329 $filter_params = array();
330
331 if ( ! empty( $_POST['subscrpt_status'] ) ) {
332 $filter_params['subscrpt_status'] = sanitize_text_field( wp_unslash( $_POST['subscrpt_status'] ) );
333 }
334 if ( ! empty( $_POST['date_filter'] ) ) {
335 $filter_params['date_filter'] = sanitize_text_field( wp_unslash( $_POST['date_filter'] ) );
336 }
337 if ( ! empty( $_POST['s'] ) ) {
338 $filter_params['s'] = sanitize_text_field( wp_unslash( $_POST['s'] ) );
339 }
340 if ( ! empty( $_POST['per_page'] ) ) {
341 $filter_params['per_page'] = intval( $_POST['per_page'] );
342 }
343
344 $redirect_url = add_query_arg( $filter_params, admin_url( 'admin.php?page=wp-subscription' ) );
345 wp_safe_redirect( $redirect_url );
346 exit;
347 }
348 }
349
350 // Handle individual actions
351 if ( isset( $_GET['action'] ) && ! empty( $_GET['sub_id'] ) ) {
352 $sub_id = intval( $_GET['sub_id'] );
353 $action = sanitize_text_field( wp_unslash( $_GET['action'] ) );
354 $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
355
356 // Clean trash action.
357 if ( $action === 'clean_trash' ) {
358 // Verify nonce for security.
359 $nonce_action = 'wpsubs_action_clean_trash';
360 if ( ! wp_verify_nonce( $nonce, $nonce_action ) ) {
361 echo '<div class="notice notice-error"><p>' . esc_html__( 'Security check failed. Please try again.', 'subscription' ) . '</p></div>';
362 wp_die();
363 }
364
365 // Clean all trash items.
366 $trash_posts = get_posts(
367 [
368 'post_type' => 'subscrpt_order',
369 'post_status' => 'trash',
370 'numberposts' => -1,
371 'fields' => 'ids',
372 ]
373 );
374
375 foreach ( $trash_posts as $trash_id ) {
376 wp_delete_post( $trash_id, true );
377 }
378
379 wp_safe_redirect( admin_url( 'admin.php?page=wp-subscription&subscrpt_status=trash' ) );
380 exit;
381 } else {
382 // For other actions, verify nonce with subscription ID.
383 $nonce_action = 'wpsubs_action_' . $sub_id;
384 if ( ! wp_verify_nonce( $nonce, $nonce_action ) ) {
385 echo '<div class="notice notice-error"><p>' . esc_html__( 'Security check failed. Please try again.', 'subscription' ) . '</p></div>';
386 wp_die();
387 }
388
389 $redirect_url = admin_url( 'admin.php?page=wp-subscription' );
390
391 switch ( $action ) {
392 case 'duplicate':
393 $post = get_post( $sub_id );
394 if ( $post && $post->post_type === 'subscrpt_order' ) {
395 $new_post = [
396 'post_title' => $post->post_title . ' (Copy)',
397 'post_content' => $post->post_content,
398 'post_status' => 'draft',
399 'post_type' => 'subscrpt_order',
400 ];
401 $new_id = wp_insert_post( $new_post );
402 if ( $new_id ) {
403 $meta = get_post_meta( $sub_id );
404 foreach ( $meta as $key => $values ) {
405 foreach ( $values as $value ) {
406 add_post_meta( $new_id, $key, maybe_unserialize( $value ) );
407 }
408 }
409 }
410 }
411 break;
412 case 'trash':
413 wp_trash_post( $sub_id );
414 break;
415 case 'restore':
416 wp_untrash_post( $sub_id );
417 break;
418 case 'delete':
419 wp_delete_post( $sub_id, true );
420 $redirect_url = admin_url( 'admin.php?page=wp-subscription&subscrpt_status=trash' );
421 break;
422 }
423
424 wp_safe_redirect( $redirect_url );
425 exit;
426 }
427 }
428
429 $args = [
430 'post_type' => 'subscrpt_order',
431 'post_status' => 'any',
432 'posts_per_page' => $per_page,
433 'paged' => $paged,
434 'orderby' => 'date',
435 'order' => 'DESC',
436 ];
437
438 if ( $status ) {
439 $args['post_status'] = $status;
440 }
441 // Search only by subscription ID
442 if ( $search !== '' ) {
443 if ( is_numeric( $search ) ) {
444 $args['p'] = intval( $search );
445 } else {
446 // If not numeric, return no results
447 $args['post__in'] = array( 0 );
448 }
449 }
450 // Dynamic date filter (YYYY-MM)
451 if ( $date_filter && preg_match( '/^\d{4}-\d{2}$/', $date_filter ) ) {
452 $year = substr( $date_filter, 0, 4 );
453 $month = substr( $date_filter, 5, 2 );
454 $args['date_query'][] = [
455 'year' => intval( $year ),
456 'month' => intval( $month ),
457 ];
458 }
459
460 $query = new \WP_Query( $args );
461 $subscriptions = $query->posts;
462 $total = $query->found_posts;
463 $max_num_pages = $query->max_num_pages;
464
465 // Get all possible statuses for filter dropdown
466 $all_statuses = get_post_stati( [ 'show_in_admin_all_list' => true ], 'objects' );
467
468 include __DIR__ . '/views/subscription-list.php';
469 ?>
470 <div style="text-align:center;margin:38px 0 0 0;font-size:14px;color:#888;">
471 Made with <span style="color:#e25555;font-size:1.1em;">♥</span> by the WPSubscription Team
472 <div style="margin-top:6px;">
473 <a href="https://wpsubscription.co/contact" target="_blank" style="color:#2563eb;text-decoration:none;">Support</a>
474 &nbsp;/&nbsp;
475 <a href="https://docs.converslabs.com/en" target="_blank" style="color:#2563eb;text-decoration:none;">Docs</a>
476 </div>
477 </div>
478 <?php
479 }
480
481 /**
482 * Render Stats page
483 */
484 public function render_stats_page() {
485 $this->render_admin_header( __( 'Reports', 'subscription' ), __( 'View your subscription analytics', 'subscription' ) );
486
487 if ( ! subscrpt_pro_activated() ) {
488 include 'views/reports-preview.php';
489 } else {
490 // Allow pro plugin to override the entire stats page content.
491 do_action( 'subscrpt_render_stats_page' );
492 }
493
494 $this->render_admin_footer();
495 }
496
497 /**
498 * Render Health page
499 */
500 public function render_health_page() {
501 $this->render_admin_header( __( 'Health', 'subscription' ), __( 'Monitor your subscription health', 'subscription' ) );
502
503 if ( ! subscrpt_pro_activated() ) {
504 include 'views/health-preview.php';
505 } else {
506 // Allow pro plugin to render the full health page content.
507 do_action( 'subscrpt_render_health_page' );
508 }
509
510 $this->render_admin_footer();
511 }
512
513 /**
514 * Render Delivery Schedules page.
515 * When pro is active, fires subscrpt_render_delivery_page for pro to handle.
516 */
517 public function render_delivery_page() {
518 $this->render_admin_header( __( 'Delivery Schedules', 'subscription' ), __( 'Track and manage subscription delivery schedules.', 'subscription' ) );
519
520 if ( ! subscrpt_pro_activated() ) {
521 include 'views/delivery-preview.php';
522 } else {
523 // Allow pro plugin to render the full delivery page content.
524 do_action( 'subscrpt_render_delivery_page' );
525 }
526
527 $this->render_admin_footer();
528 }
529
530 /**
531 * Render Support page
532 */
533 public function render_support_page() {
534 $this->render_admin_header( __( 'Help & Resources', 'subscription' ), __( 'Documentation, community links, and ways to get help with WPSubscription.', 'subscription' ) );
535 include 'views/support.php';
536 $this->render_admin_footer();
537 }
538
539 /**
540 * Render the legacy subscriptions list page (WP_List_Table based)
541 */
542 public function render_legacy_subscriptions_page() {
543 // No longer needed, as the menu now links directly to the post type list.
544 }
545
546 /**
547 * Handle bulk action AJAX
548 */
549 public function handle_bulk_action_ajax() {
550 // Verify nonce
551 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
552 if ( ! wp_verify_nonce( $nonce, 'subscrpt_bulk_action_nonce' ) ) {
553 wp_send_json_error( array( 'message' => __( 'Security check failed.', 'subscription' ) ) );
554 }
555
556 // Check permissions
557 if ( ! current_user_can( 'manage_woocommerce' ) ) {
558 wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'subscription' ) ) );
559 }
560
561 // Get action and subscription IDs
562 $bulk_action = isset( $_POST['bulk_action'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk_action'] ) ) : '';
563 $subscription_ids = isset( $_POST['subscription_ids'] ) ? array_map( 'intval', $_POST['subscription_ids'] ) : array();
564
565 if ( empty( $subscription_ids ) ) {
566 wp_send_json_error( array( 'message' => __( 'No subscriptions selected.', 'subscription' ) ) );
567 }
568
569 $processed_count = 0;
570 $errors = array();
571
572 foreach ( $subscription_ids as $subscription_id ) {
573 $post = get_post( $subscription_id );
574
575 if ( ! $post || $post->post_type !== 'subscrpt_order' ) {
576 // translators: Subscription ID.
577 $errors[] = sprintf( __( 'Subscription #%d not found.', 'subscription' ), $subscription_id );
578 continue;
579 }
580
581 try {
582 switch ( $bulk_action ) {
583 case 'trash':
584 if ( wp_trash_post( $subscription_id ) ) {
585 ++$processed_count;
586 } else {
587 $errors[] = sprintf(
588 // translators: Subscription ID.
589 __( 'Failed to move subscription #%d to trash.', 'subscription' ),
590 $subscription_id
591 );
592 }
593 break;
594
595 case 'restore':
596 if ( wp_untrash_post( $subscription_id ) ) {
597 ++$processed_count;
598 } else {
599 $errors[] = sprintf(
600 // translators: Subscription ID.
601 __( 'Failed to restore subscription #%d.', 'subscription' ),
602 $subscription_id
603 );
604 }
605 break;
606
607 case 'delete':
608 if ( wp_delete_post( $subscription_id, true ) ) {
609 ++$processed_count;
610 } else {
611 $errors[] = sprintf(
612 // translators: Subscription ID.
613 __( 'Failed to delete subscription #%d.', 'subscription' ),
614 $subscription_id
615 );
616 }
617 break;
618
619 default:
620 $errors[] = sprintf(
621 // translators: Bulk action.
622 __( 'Unknown action: %s', 'subscription' ),
623 $bulk_action
624 );
625 break;
626 }
627 } catch ( Exception $e ) {
628 $errors[] = sprintf(
629 // translators: Subscription ID, Error message.
630 __( 'Error processing subscription #%1$d: %2$s', 'subscription' ),
631 $subscription_id,
632 $e->getMessage()
633 );
634 }
635 }
636
637 // Prepare response message
638 $message = '';
639 if ( $processed_count > 0 ) {
640 switch ( $bulk_action ) {
641 case 'trash':
642 $message = sprintf(
643 // translators: Number of subscriptions.
644 _n( '%d subscription moved to trash.', '%d subscriptions moved to trash.', $processed_count, 'subscription' ),
645 $processed_count
646 );
647 break;
648 case 'restore':
649 $message = sprintf(
650 // translators: Number of subscriptions.
651 _n( '%d subscription restored.', '%d subscriptions restored.', $processed_count, 'subscription' ),
652 $processed_count
653 );
654 break;
655 case 'delete':
656 $message = sprintf(
657 // translators: Number of subscriptions.
658 _n( '%d subscription permanently deleted.', '%d subscriptions permanently deleted.', $processed_count, 'subscription' ),
659 $processed_count
660 );
661 break;
662 }
663 }
664
665 if ( ! empty( $errors ) ) {
666 $message .= ' ' . __( 'Some errors occurred:', 'subscription' ) . ' ' . implode( ', ', $errors );
667 }
668
669 if ( $processed_count > 0 ) {
670 wp_send_json_success( array( 'message' => $message ) );
671 } else {
672 wp_send_json_error( array( 'message' => $message ? $message : __( 'No subscriptions were processed.', 'subscription' ) ) );
673 }
674 }
675 }
676