PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 8.6.1
WooCommerce v8.6.1
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / src / Internal / Admin / Orders / PageController.php
woocommerce / src / Internal / Admin / Orders Last commit date
MetaBoxes 2 years ago COTRedirectionController.php 2 years ago Edit.php 2 years ago EditLock.php 2 years ago ListTable.php 2 years ago PageController.php 2 years ago PostsRedirectionController.php 2 years ago
PageController.php
579 lines
1 <?php
2 namespace Automattic\WooCommerce\Internal\Admin\Orders;
3
4 use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
5 use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
6
7 /**
8 * Controls the different pages/screens associated to the "Orders" menu page.
9 */
10 class PageController {
11
12 use AccessiblePrivateMethods;
13
14 /**
15 * The order type.
16 *
17 * @var string
18 */
19 private $order_type = '';
20
21 /**
22 * Instance of the posts redirection controller.
23 *
24 * @var PostsRedirectionController
25 */
26 private $redirection_controller;
27
28 /**
29 * Instance of the orders list table.
30 *
31 * @var ListTable
32 */
33 private $orders_table;
34
35 /**
36 * Instance of orders edit form.
37 *
38 * @var Edit
39 */
40 private $order_edit_form;
41
42 /**
43 * Current action.
44 *
45 * @var string
46 */
47 private $current_action = '';
48
49 /**
50 * Order object to be used in edit/new form.
51 *
52 * @var \WC_Order
53 */
54 private $order;
55
56 /**
57 * Verify that user has permission to edit orders.
58 *
59 * @return void
60 */
61 private function verify_edit_permission() {
62 if ( 'edit_order' === $this->current_action && ( ! isset( $this->order ) || ! $this->order ) ) {
63 wp_die( esc_html__( 'You attempted to edit an order that does not exist. Perhaps it was deleted?', 'woocommerce' ) );
64 }
65
66 if ( $this->order->get_type() !== $this->order_type ) {
67 wp_die( esc_html__( 'Order type mismatch.', 'woocommerce' ) );
68 }
69
70 if ( ! current_user_can( get_post_type_object( $this->order_type )->cap->edit_post, $this->order->get_id() ) && ! current_user_can( 'manage_woocommerce' ) ) {
71 wp_die( esc_html__( 'You do not have permission to edit this order', 'woocommerce' ) );
72 }
73
74 if ( 'trash' === $this->order->get_status() ) {
75 wp_die( esc_html__( 'You cannot edit this item because it is in the Trash. Please restore it and try again.', 'woocommerce' ) );
76 }
77 }
78
79 /**
80 * Verify that user has permission to create order.
81 *
82 * @return void
83 */
84 private function verify_create_permission() {
85 if ( ! current_user_can( get_post_type_object( $this->order_type )->cap->publish_posts ) && ! current_user_can( 'manage_woocommerce' ) ) {
86 wp_die( esc_html__( 'You don\'t have permission to create a new order', 'woocommerce' ) );
87 }
88
89 if ( isset( $this->order ) ) {
90 $this->verify_edit_permission();
91 }
92 }
93
94 /**
95 * Claims the lock for the order being edited/created (unless it belongs to someone else).
96 * Also handles the 'claim-lock' action which allows taking over the order forcefully.
97 *
98 * @return void
99 */
100 private function handle_edit_lock() {
101 if ( ! $this->order ) {
102 return;
103 }
104
105 $edit_lock = wc_get_container()->get( EditLock::class );
106
107 $locked = $edit_lock->is_locked_by_another_user( $this->order );
108
109 // Take over order?
110 if ( ! empty( $_GET['claim-lock'] ) && wp_verify_nonce( $_GET['_wpnonce'] ?? '', 'claim-lock-' . $this->order->get_id() ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
111 $edit_lock->lock( $this->order );
112 wp_safe_redirect( $this->get_edit_url( $this->order->get_id() ) );
113 exit;
114 }
115
116 if ( ! $locked ) {
117 $edit_lock->lock( $this->order );
118 }
119
120 add_action(
121 'admin_footer',
122 function() use ( $edit_lock ) {
123 $edit_lock->render_dialog( $this->order );
124 }
125 );
126 }
127
128 /**
129 * Sets up the page controller, including registering the menu item.
130 *
131 * @return void
132 */
133 public function setup(): void {
134 global $plugin_page, $pagenow;
135
136 $this->redirection_controller = new PostsRedirectionController( $this );
137
138 // Register menu.
139 if ( 'admin_menu' === current_action() ) {
140 $this->register_menu();
141 } else {
142 add_action( 'admin_menu', 'register_menu', 9 );
143 }
144
145 // Not on an Orders page.
146 if ( 'admin.php' !== $pagenow || 0 !== strpos( $plugin_page, 'wc-orders' ) ) {
147 return;
148 }
149
150 $this->set_order_type();
151 $this->set_action();
152
153 $page_suffix = ( 'shop_order' === $this->order_type ? '' : '--' . $this->order_type );
154
155 self::add_action( 'load-woocommerce_page_wc-orders' . $page_suffix, array( $this, 'handle_load_page_action' ) );
156 self::add_action( 'admin_title', array( $this, 'set_page_title' ) );
157 }
158
159 /**
160 * Perform initialization for the current action.
161 */
162 private function handle_load_page_action() {
163 $screen = get_current_screen();
164 $screen->post_type = $this->order_type;
165
166 if ( method_exists( $this, 'setup_action_' . $this->current_action ) ) {
167 $this->{"setup_action_{$this->current_action}"}();
168 }
169 }
170
171 /**
172 * Set the document title for Orders screens to match what it would be with the shop_order CPT.
173 *
174 * @param string $admin_title The admin screen title before it's filtered.
175 *
176 * @return string The filtered admin title.
177 */
178 private function set_page_title( $admin_title ) {
179 if ( ! $this->is_order_screen( $this->order_type ) ) {
180 return $admin_title;
181 }
182
183 $wp_order_type = get_post_type_object( $this->order_type );
184 $labels = get_post_type_labels( $wp_order_type );
185
186 if ( $this->is_order_screen( $this->order_type, 'list' ) ) {
187 $admin_title = sprintf(
188 // translators: 1: The label for an order type 2: The name of the website.
189 esc_html__( '%1$s &lsaquo; %2$s &#8212; WordPress', 'woocommerce' ),
190 esc_html( $labels->name ),
191 esc_html( get_bloginfo( 'name' ) )
192 );
193 } elseif ( $this->is_order_screen( $this->order_type, 'edit' ) ) {
194 $admin_title = sprintf(
195 // translators: 1: The label for an order type 2: The title of the order 3: The name of the website.
196 esc_html__( '%1$s #%2$s &lsaquo; %3$s &#8212; WordPress', 'woocommerce' ),
197 esc_html( $labels->edit_item ),
198 absint( $this->order->get_id() ),
199 esc_html( get_bloginfo( 'name' ) )
200 );
201 } elseif ( $this->is_order_screen( $this->order_type, 'new' ) ) {
202 $admin_title = sprintf(
203 // translators: 1: The label for an order type 2: The name of the website.
204 esc_html__( '%1$s &lsaquo; %2$s &#8212; WordPress', 'woocommerce' ),
205 esc_html( $labels->add_new_item ),
206 esc_html( get_bloginfo( 'name' ) )
207 );
208 }
209
210 return $admin_title;
211 }
212
213 /**
214 * Determines the order type for the current screen.
215 *
216 * @return void
217 */
218 private function set_order_type() {
219 global $plugin_page;
220
221 $this->order_type = str_replace( array( 'wc-orders--', 'wc-orders' ), '', $plugin_page );
222 $this->order_type = empty( $this->order_type ) ? 'shop_order' : $this->order_type;
223
224 $wc_order_type = wc_get_order_type( $this->order_type );
225 $wp_order_type = get_post_type_object( $this->order_type );
226
227 if ( ! $wc_order_type || ! $wp_order_type || ! $wp_order_type->show_ui || ! current_user_can( $wp_order_type->cap->edit_posts ) ) {
228 wp_die();
229 }
230 }
231
232 /**
233 * Sets the current action based on querystring arguments. Defaults to 'list_orders'.
234 *
235 * @return void
236 */
237 private function set_action(): void {
238 switch ( isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '' ) {
239 case 'edit':
240 $this->current_action = 'edit_order';
241 break;
242 case 'new':
243 $this->current_action = 'new_order';
244 break;
245 default:
246 $this->current_action = 'list_orders';
247 break;
248 }
249 }
250
251 /**
252 * Registers the "Orders" menu.
253 *
254 * @return void
255 */
256 public function register_menu(): void {
257 $order_types = wc_get_order_types( 'admin-menu' );
258
259 foreach ( $order_types as $order_type ) {
260 $post_type = get_post_type_object( $order_type );
261
262 add_submenu_page(
263 'woocommerce',
264 $post_type->labels->name,
265 $post_type->labels->menu_name,
266 $post_type->cap->edit_posts,
267 'wc-orders' . ( 'shop_order' === $order_type ? '' : '--' . $order_type ),
268 array( $this, 'output' )
269 );
270 }
271
272 // In some cases (such as if the authoritative order store was changed earlier in the current request) we
273 // need an extra step to remove the menu entry for the menu post type.
274 add_action(
275 'admin_init',
276 function() use ( $order_types ) {
277 foreach ( $order_types as $order_type ) {
278 remove_submenu_page( 'woocommerce', 'edit.php?post_type=' . $order_type );
279 }
280 }
281 );
282 }
283
284 /**
285 * Outputs content for the current orders screen.
286 *
287 * @return void
288 */
289 public function output(): void {
290 switch ( $this->current_action ) {
291 case 'edit_order':
292 case 'new_order':
293 $this->order_edit_form->display();
294 break;
295 case 'list_orders':
296 default:
297 $this->orders_table->prepare_items();
298 $this->orders_table->display();
299 break;
300 }
301 }
302
303 /**
304 * Handles initialization of the orders list table.
305 *
306 * @return void
307 */
308 private function setup_action_list_orders(): void {
309 $this->orders_table = wc_get_container()->get( ListTable::class );
310 $this->orders_table->setup(
311 array(
312 'order_type' => $this->order_type,
313 )
314 );
315
316 if ( $this->orders_table->current_action() ) {
317 $this->orders_table->handle_bulk_actions();
318 }
319
320 $this->strip_http_referer();
321 }
322
323 /**
324 * Perform a redirect to remove the `_wp_http_referer` and `_wpnonce` strings if present in the URL (see also
325 * wp-admin/edit.php where a similar process takes place), otherwise the size of this field builds to an
326 * unmanageable length over time.
327 */
328 private function strip_http_referer(): void {
329 $current_url = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) );
330 $stripped_url = remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), $current_url );
331
332 if ( $stripped_url !== $current_url ) {
333 wp_safe_redirect( $stripped_url );
334 exit;
335 }
336 }
337
338 /**
339 * Prepares the order edit form for creating or editing an order.
340 *
341 * @see \Automattic\WooCommerce\Internal\Admin\Orders\Edit.
342 * @since 8.1.0
343 */
344 private function prepare_order_edit_form(): void {
345 if ( ! $this->order || ! in_array( $this->current_action, array( 'new_order', 'edit_order' ), true ) ) {
346 return;
347 }
348
349 $this->order_edit_form = $this->order_edit_form ?? new Edit();
350 $this->order_edit_form->setup( $this->order );
351 $this->order_edit_form->set_current_action( $this->current_action );
352 }
353
354 /**
355 * Handles initialization of the orders edit form.
356 *
357 * @return void
358 */
359 private function setup_action_edit_order(): void {
360 global $theorder;
361 $this->order = wc_get_order( absint( isset( $_GET['id'] ) ? $_GET['id'] : 0 ) );
362 $this->verify_edit_permission();
363 $this->handle_edit_lock();
364 $theorder = $this->order;
365
366 $this->prepare_order_edit_form();
367 }
368
369 /**
370 * Handles initialization of the orders edit form with a new order.
371 *
372 * @return void
373 */
374 private function setup_action_new_order(): void {
375 global $theorder;
376
377 $this->verify_create_permission();
378
379 $order_class_name = wc_get_order_type( $this->order_type )['class_name'];
380 if ( ! $order_class_name || ! class_exists( $order_class_name ) ) {
381 wp_die();
382 }
383
384 $this->order = new $order_class_name();
385 $this->order->set_object_read( false );
386 $this->order->set_status( 'auto-draft' );
387 $this->order->set_created_via( 'admin' );
388 $this->order->save();
389 $this->handle_edit_lock();
390
391 // Schedule auto-draft cleanup. We re-use the WP event here on purpose.
392 if ( ! wp_next_scheduled( 'wp_scheduled_auto_draft_delete' ) ) {
393 wp_schedule_event( time(), 'daily', 'wp_scheduled_auto_draft_delete' );
394 }
395
396 $theorder = $this->order;
397
398 $this->prepare_order_edit_form();
399 }
400
401 /**
402 * Returns the current order type.
403 *
404 * @return string
405 */
406 public function get_order_type() {
407 return $this->order_type;
408 }
409
410 /**
411 * Helper method to generate a link to the main orders screen.
412 *
413 * @return string Orders screen URL.
414 */
415 public function get_orders_url(): string {
416 return wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ?
417 admin_url( 'admin.php?page=wc-orders' ) :
418 admin_url( 'edit.php?post_type=shop_order' );
419 }
420
421 /**
422 * Helper method to generate edit link for an order.
423 *
424 * @param int $order_id Order ID.
425 *
426 * @return string Edit link.
427 */
428 public function get_edit_url( int $order_id ) : string {
429 if ( ! wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ) {
430 return admin_url( 'post.php?post=' . absint( $order_id ) ) . '&action=edit';
431 }
432
433 $order = wc_get_order( $order_id );
434
435 // Confirm we could obtain the order object (since it's possible it will not exist, due to a sync issue, or may
436 // have been deleted in a separate concurrent request).
437 if ( false === $order ) {
438 wc_get_logger()->debug(
439 sprintf(
440 /* translators: %d order ID. */
441 __( 'Attempted to determine the edit URL for order %d, however the order does not exist.', 'woocommerce' ),
442 $order_id
443 )
444 );
445 $order_type = 'shop_order';
446 } else {
447 $order_type = $order->get_type();
448 }
449
450 return add_query_arg(
451 array(
452 'action' => 'edit',
453 'id' => absint( $order_id ),
454 ),
455 $this->get_base_page_url( $order_type )
456 );
457 }
458
459 /**
460 * Helper method to generate a link for creating order.
461 *
462 * @param string $order_type The order type. Defaults to 'shop_order'.
463 * @return string
464 */
465 public function get_new_page_url( $order_type = 'shop_order' ) : string {
466 $url = wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ?
467 add_query_arg( 'action', 'new', $this->get_base_page_url( $order_type ) ) :
468 admin_url( 'post-new.php?post_type=' . $order_type );
469
470 return $url;
471 }
472
473 /**
474 * Helper method to generate a link to the main screen for a custom order type.
475 *
476 * @param string $order_type The order type.
477 *
478 * @return string
479 *
480 * @throws \Exception When an invalid order type is passed.
481 */
482 public function get_base_page_url( $order_type ): string {
483 $order_types_with_ui = wc_get_order_types( 'admin-menu' );
484
485 if ( ! in_array( $order_type, $order_types_with_ui, true ) ) {
486 // translators: %s is a custom order type.
487 throw new \Exception( sprintf( __( 'Invalid order type: %s.', 'woocommerce' ), esc_html( $order_type ) ) );
488 }
489
490 return admin_url( 'admin.php?page=wc-orders' . ( 'shop_order' === $order_type ? '' : '--' . $order_type ) );
491 }
492
493 /**
494 * Helper method to check if the current admin screen is related to orders.
495 *
496 * @param string $type Optional. The order type to check for. Default shop_order.
497 * @param string $action Optional. The purpose of the screen to check for. 'list', 'edit', or 'new'.
498 * Leave empty to check for any order screen.
499 *
500 * @return bool
501 */
502 public function is_order_screen( $type = 'shop_order', $action = '' ) : bool {
503 if ( ! did_action( 'current_screen' ) ) {
504 wc_doing_it_wrong(
505 __METHOD__,
506 sprintf(
507 // translators: %s is the name of a function.
508 esc_html__( '%s must be called after the current_screen action.', 'woocommerce' ),
509 esc_html( __METHOD__ )
510 ),
511 '7.9.0'
512 );
513
514 return false;
515 }
516
517 $valid_types = wc_get_order_types( 'view-order' );
518 if ( ! in_array( $type, $valid_types, true ) ) {
519 wc_doing_it_wrong(
520 __METHOD__,
521 sprintf(
522 // translators: %s is the name of an order type.
523 esc_html__( '%s is not a valid order type.', 'woocommerce' ),
524 esc_html( $type )
525 ),
526 '7.9.0'
527 );
528
529 return false;
530 }
531
532 if ( wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ) {
533 if ( $action ) {
534 switch ( $action ) {
535 case 'edit':
536 $is_action = 'edit_order' === $this->current_action;
537 break;
538 case 'list':
539 $is_action = 'list_orders' === $this->current_action;
540 break;
541 case 'new':
542 $is_action = 'new_order' === $this->current_action;
543 break;
544 default:
545 $is_action = false;
546 break;
547 }
548 }
549
550 $type_match = $type === $this->order_type;
551 $action_match = ! $action || $is_action;
552 } else {
553 $screen = get_current_screen();
554
555 if ( $action ) {
556 switch ( $action ) {
557 case 'edit':
558 $screen_match = 'post' === $screen->base && filter_input( INPUT_GET, 'post', FILTER_VALIDATE_INT );
559 break;
560 case 'list':
561 $screen_match = 'edit' === $screen->base;
562 break;
563 case 'new':
564 $screen_match = 'post' === $screen->base && 'add' === $screen->action;
565 break;
566 default:
567 $screen_match = false;
568 break;
569 }
570 }
571
572 $type_match = $type === $screen->post_type;
573 $action_match = ! $action || $screen_match;
574 }
575
576 return $type_match && $action_match;
577 }
578 }
579